Skip to content

Path.combine not implemented in the HTML backend #44572

Closed

Description

@eugene-kalaganov

this code below works fine on flutter mobile
but on web it throws an error

import 'package:flutter/material.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: SafeArea(
          child: Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                UnicornOutlineButton(
                  strokeWidth: 2,
                  radius: 24,
                  gradient: LinearGradient(colors: [Colors.black, Colors.redAccent]),
                  child: Text('OMG', style: TextStyle(fontSize: 16)),
                  onPressed: () {},
                ),
                SizedBox(width: 0, height: 24),
                UnicornOutlineButton(
                  strokeWidth: 4,
                  radius: 16,
                  gradient: LinearGradient(
                    colors: [Colors.blue, Colors.yellow],
                    begin: Alignment.topCenter,
                    end: Alignment.bottomCenter,
                  ),
                  child: Text('Wow', style: TextStyle(fontSize: 16)),
                  onPressed: () {},
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class UnicornOutlineButton extends StatelessWidget {
  final _GradientPainter _painter;
  final Widget _child;
  final VoidCallback _callback;
  final double _radius;

  UnicornOutlineButton({
    @required double strokeWidth,
    @required double radius,
    @required Gradient gradient,
    @required Widget child,
    @required VoidCallback onPressed,
  })  : this._painter = _GradientPainter(strokeWidth: strokeWidth, radius: radius, gradient: gradient),
        this._child = child,
        this._callback = onPressed,
        this._radius = radius;

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: _painter,
      child: GestureDetector(
        behavior: HitTestBehavior.translucent,
        onTap: _callback,
        child: InkWell(
          borderRadius: BorderRadius.circular(_radius),
          onTap: _callback,
          child: Container(
            constraints: BoxConstraints(minWidth: 88, minHeight: 48),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                _child,
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class _GradientPainter extends CustomPainter {
  final Paint _paint = Paint();
  final double radius;
  final double strokeWidth;
  final Gradient gradient;

  _GradientPainter({@required double strokeWidth, @required double radius, @required Gradient gradient})
      : this.strokeWidth = strokeWidth,
        this.radius = radius,
        this.gradient = gradient;

  @override
  void paint(Canvas canvas, Size size) {
    // create outer rectangle equals size
    Rect outerRect = Offset.zero & size;
    var outerRRect = RRect.fromRectAndRadius(outerRect, Radius.circular(radius));

    // create inner rectangle smaller by strokeWidth
    Rect innerRect = Rect.fromLTWH(strokeWidth, strokeWidth, size.width - strokeWidth * 2, size.height - strokeWidth * 2);
    var innerRRect = RRect.fromRectAndRadius(innerRect, Radius.circular(radius - strokeWidth));

    // apply gradient shader
    _paint.shader = gradient.createShader(outerRect);

    // create difference between outer and inner paths and draw it
    Path path1 = Path()..addRRect(outerRRect);
    Path path2 = Path()..addRRect(innerRRect);
    var path = Path.combine(PathOperation.difference, path1, path2);
    canvas.drawPath(path, _paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => oldDelegate != this;
}

here is full log

Performing hot restart...
Reloaded application in 423ms.
══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
The following UnimplementedError was thrown during paint():
UnimplementedError

The relevant error-causing widget was:
CustomPaint org-dartlang-app:///packages/mywebapp/main.dart:64:12

When the exception was thrown, this was the stack:
package:dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 194:49  throw_
package:build_web_compilers/lib/ui/src/ui/canvas.dart 2200:5                          combine
package:mywebapp/main.dart 115:21                                                     paint
package:flutter/src/rendering/custom_paint.dart 531:12                                [_paintWithPainter]
package:flutter/src/rendering/custom_paint.dart 572:7                                 paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/box.dart 2508:14                                        defaultPaint
package:flutter/src/rendering/flex.dart 948:7                                         paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/shifted_box.dart 70:14                                  paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/shifted_box.dart 70:14                                  paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/box.dart 2508:14                                        defaultPaint
package:flutter/src/rendering/custom_layout.dart 396:5                                paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/proxy_box.dart 123:14                                   paint
package:flutter/src/material/material.dart 530:11                                     paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/proxy_box.dart 123:14                                   paint
package:flutter/src/rendering/object.dart 384:12                                      pushLayer
package:flutter/src/rendering/proxy_box.dart 1757:14                                  paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/proxy_box.dart 123:14                                   paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/proxy_box.dart 123:14                                   paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 135:10                                      _repaintCompositedChild
package:flutter/src/rendering/object.dart 95:5                                        repaintCompositedChild
package:flutter/src/rendering/object.dart 201:7                                       [_compositeChild]
package:flutter/src/rendering/object.dart 182:7                                       paintChild
package:flutter/src/rendering/proxy_box.dart 123:14                                   paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/proxy_box.dart 921:16                                   paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/proxy_box.dart 123:14                                   paint
package:flutter/src/rendering/proxy_box.dart 2464:13                                  paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/proxy_box.dart 123:14                                   paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 135:10                                      _repaintCompositedChild
package:flutter/src/rendering/object.dart 95:5                                        repaintCompositedChild
package:flutter/src/rendering/object.dart 201:7                                       [_compositeChild]
package:flutter/src/rendering/object.dart 182:7                                       paintChild
package:flutter/src/rendering/proxy_box.dart 123:14                                   paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/proxy_box.dart 123:14                                   paint
package:flutter/src/rendering/proxy_box.dart 3174:11                                  paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/box.dart 2508:14                                        defaultPaint
package:flutter/src/rendering/stack.dart 589:5                                        paintStack
package:flutter/src/rendering/stack.dart 597:7                                        paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/proxy_box.dart 123:14                                   paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/proxy_box.dart 123:14                                   paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/proxy_box.dart 123:14                                   paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/proxy_box.dart 123:14                                   paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/proxy_box.dart 123:14                                   paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/proxy_box.dart 123:14                                   paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 184:12                                      paintChild
package:flutter/src/rendering/view.dart 210:14                                        paint
package:flutter/src/rendering/object.dart 2211:7                                      [_paintWithContext]
package:flutter/src/rendering/object.dart 135:10                                      _repaintCompositedChild
package:flutter/src/rendering/object.dart 95:5                                        repaintCompositedChild
package:flutter/src/rendering/object.dart 937:29                                      flushPaint
package:flutter/src/rendering/binding.dart 346:19                                     drawFrame
package:flutter/src/widgets/binding.dart 774:13                                       drawFrame
package:flutter/src/rendering/binding.dart 283:5                                      [_handlePersistentFrameCallback]
package:flutter/src/scheduler/binding.dart 1101:15                                    [_invokeFrameCallback]
package:flutter/src/scheduler/binding.dart 1040:9                                     handleDrawFrame
package:flutter/src/scheduler/binding.dart 849:7                                      <fn>
package:dart-sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart 48:19       internalCallback

The following RenderObject was being processed when the exception was fired: RenderCustomPaint#dc268 relayoutBoundary=up4:
creator: CustomPaint ← UnicornOutlineButton ← Column ← Center ← MediaQuery ← Padding ← SafeArea ←
_BodyBuilder ← MediaQuery ← LayoutId-[<_ScaffoldSlot.body>] ← CustomMultiChildLayout ←
AnimatedBuilder ← ⋯
parentData: offset=Offset(0.0, 0.0); flex=null; fit=null (can use size)
constraints: BoxConstraints(0.0<=w<=1920.0, 0.0<=h<=Infinity)
size: Size(88.0, 48.0)
This RenderObject had the following descendants (showing up to depth 5):
child: RenderSemanticsGestureHandler#078b7 relayoutBoundary=up5 NEEDS-PAINT
child: RenderPointerListener#fd406 relayoutBoundary=up6 NEEDS-PAINT
child: RenderSemanticsAnnotations#9008b relayoutBoundary=up7 NEEDS-PAINT
child: RenderMouseRegion#dec56 relayoutBoundary=up8 NEEDS-PAINT
child: RenderSemanticsGestureHandler#cea3a relayoutBoundary=up9 NEEDS-PAINT
════════════════════════════════════════════════════════════════════════════════════════════════════
Another exception was thrown: UnimplementedError

if I commented this line, everything if ok and working fine, but I need subtract one path from another. Actually all path operations are throwing errors on flutter web.
var path = Path.combine(PathOperation.difference, path1, path2);

Tried on MAC Catalina and Windows 10.

flutter doctor -v

    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 3.5)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 40.2.2
    • Dart plugin version 191.8593
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)

[✓] Connected device (2 available)
    • Chrome     • chrome     • web-javascript • Google Chrome 78.0.3904.97
    • Web Server • web-server • web-javascript • Flutter Tools

• No issues found!

my original post on SO https://stackoverflow.com/questions/55395641/outlined-transparent-button-with-gradient-border-in-flutter/55638138

Activity

  1. iapicca commented on Nov 11, 2019

    @iapicca

    Hi @eugene-kalaganov
    could you please provide your complete flutter doctor -v
    thank you

  2. added
    a: imagesLoading, displaying, rendering images
    c: crashStack traces logged to the console
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    platform-webWeb applications specifically
    on Nov 11, 2019
  3. eugene-kalaganov commented on Nov 11, 2019

    @eugene-kalaganov
    Author

    I added it, please see at the end of my post

  4. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Nov 11, 2019
  5. changed the title [-]Path.combine throws UNIMPLEMENTED ERROR[/-] [+]Path.combine not implemented[/+] on Nov 11, 2019
  6. changed the title [-]Path.combine not implemented[/-] [+][web] Path.combine not implemented[/+] on Nov 11, 2019
  7. added this to the milestone on Nov 21, 2019
  8. diegoveloper commented on Jan 10, 2020

    @diegoveloper
    Member

    same issue here

  9. diegoveloper commented on Jan 13, 2020

    @diegoveloper
    Member

    This is a sample where you can find and replicate the issue : https://dartpad.dev/82a2a6fc764abb55503b164d181c4616

  10. 61 remaining items

  11. reiko-dev commented on Feb 7, 2024

    @reiko-dev
  12. JaffaKetchup commented on Jun 1, 2024

    @JaffaKetchup
    Contributor

    I feel like this could be a higher priority than P3. It's got 3 customers + crowd already, and has been open since 2019.

  13. rydmike commented on Jun 1, 2024

    @rydmike
    Contributor

    @JaffaKetchup I read somewhere that the html renderer is on a "potential" deprecation path. If so, maybe that is why it has not been addressed and probably wont be.

  14. naychrist commented on Sep 25, 2024

    @naychrist

    this issue is still present, with and without the wasm flag. As wasm is new I imagine this is not to be deprecated so would be great to see fixed.

  15. JaffaKetchup commented on Sep 25, 2024

    @JaffaKetchup
    Contributor

    The HTML renderer is indeed being deprecated, and I'm not sure this is possible to occur when running with Wasm. AFAIK Wasm uses skwasm and non-Wasm uses CanvasKit, both of which use WebGL, which implements the encessary methods (Wasm forces skwasm, it cannot use HTML rendering). Are you sure that this occurs in the latest Flutter versions when using CanvasKit or skwasm?

  16. naychrist commented on Sep 26, 2024

    @naychrist

    I can confirm that a simple path combine operation (cutting poly out of a rect) that works in macos desktop with flutter 3.24.3 does not work with the default web renderer, canvaskit renderer or wasm. On web the hole is not cut out and the rect is displayed solid.

    I have had to use a workaround with the polybool package for web for now but keen to see this resolved.

  17. JaffaKetchup commented on Sep 26, 2024

    @JaffaKetchup
    Contributor

    That sounds like a potentially different issue? This issue should throw UnimplementedError as in the original report, and is specifically about it not being implemented in the HTML renderer, not an issue with its implementation in any of the WebGL renderers.

  18. naychrist commented on Sep 26, 2024

    @naychrist

    yeah true that no exception is thrown. just fails silently using the same method with all the web renderers.

  19. JaffaKetchup commented on Apr 3, 2025

    @JaffaKetchup
    Contributor

    This can probably be closed since HTML support is pretty much gone. Path.combine has other issues on the web as well.

  20. yjbanov commented on May 27, 2025

    @yjbanov
    Contributor

    As the HTML renderer has been deprecated and removed from the default Flutter SDK, we're now closing all issues that affect only the HTML renderer. For more information, please see:

  21. github-actions commented on Jun 11, 2025

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  22. locked as resolved and limited conversation to collaborators on Jun 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Issues that are less important to the Flutter projecta: imagesLoading, displaying, rendering imagesc: crashStack traces logged to the consolecustomer: crowdAffects or could affect many people, though not necessarily a specific customer.customer: thrivecustomer: web10e: web_htmlHTML rendering backend for Webfound in release: 3.13Found to occur in 3.13found in release: 3.17Found to occur in 3.17frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-webWeb applications specificallyr: solvedIssue is closed as solvedteam-webOwned by Web platform teamteam: skip-testAn issue used to track tests that are skipped.triaged-webTriaged by Web platform team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions