Skip to content

Commit f10f172

Browse files
authored
[web] Update SurfacePath to use PathRef (flutter#19557)
* Update SurfacePath to use PathRef * Fix test analysis errors * Switch DDRect to use path to reduce paint time processing * Implement toString() for debug mode * Fix contains (bounds inclusive) edge case, add test * Update recording canvas test for drawDRRect change * Update diffrate for arc/conic render change * Add test for winding for beveled border. Fix checkOnCurve * Fix mono quad winding on curve check * fix _chopCubicAtYExtrema and add test case * Address reviewer comments / setAll API usage
1 parent 9b3e341 commit f10f172

21 files changed

+5322
-1657
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,9 +492,14 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/offset.dart
492492
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/opacity.dart
493493
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/painting.dart
494494
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/path/conic.dart
495+
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/path/cubic.dart
495496
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/path/path.dart
496497
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/path/path_metrics.dart
498+
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/path/path_ref.dart
497499
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/path/path_to_svg.dart
500+
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/path/path_utils.dart
501+
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/path/path_windings.dart
502+
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/path/tangent.dart
498503
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/picture.dart
499504
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/platform_view.dart
500505
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/recording_canvas.dart

lib/web_ui/lib/src/engine.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,14 @@ part 'engine/surface/offset.dart';
100100
part 'engine/surface/opacity.dart';
101101
part 'engine/surface/painting.dart';
102102
part 'engine/surface/path/conic.dart';
103+
part 'engine/surface/path/cubic.dart';
103104
part 'engine/surface/path/path.dart';
104105
part 'engine/surface/path/path_metrics.dart';
106+
part 'engine/surface/path/path_ref.dart';
105107
part 'engine/surface/path/path_to_svg.dart';
108+
part 'engine/surface/path/path_utils.dart';
109+
part 'engine/surface/path/path_windings.dart';
110+
part 'engine/surface/path/tangent.dart';
106111
part 'engine/surface/picture.dart';
107112
part 'engine/surface/platform_view.dart';
108113
part 'engine/surface/recording_canvas.dart';

lib/web_ui/lib/src/engine/canvas_pool.dart

Lines changed: 38 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -509,69 +509,47 @@ class _CanvasPool extends _SaveStackTracking {
509509
}
510510
}
511511

512+
// Float buffer used for path iteration.
513+
static Float32List _runBuffer = Float32List(PathRefIterator.kMaxBufferSize);
514+
512515
/// 'Runs' the given [path] by applying all of its commands to the canvas.
513516
void _runPath(html.CanvasRenderingContext2D ctx, SurfacePath path) {
514517
ctx.beginPath();
515-
final List<Subpath> subpaths = path.subpaths;
516-
final int subpathCount = subpaths.length;
517-
for (int subPathIndex = 0; subPathIndex < subpathCount; subPathIndex++) {
518-
final Subpath subpath = subpaths[subPathIndex];
519-
final List<PathCommand> commands = subpath.commands;
520-
final int commandCount = commands.length;
521-
for (int c = 0; c < commandCount; c++) {
522-
final PathCommand command = commands[c];
523-
switch (command.type) {
524-
case PathCommandTypes.bezierCurveTo:
525-
final BezierCurveTo curve = command as BezierCurveTo;
526-
ctx.bezierCurveTo(
527-
curve.x1, curve.y1, curve.x2, curve.y2, curve.x3, curve.y3);
528-
break;
529-
case PathCommandTypes.close:
530-
ctx.closePath();
531-
break;
532-
case PathCommandTypes.ellipse:
533-
final Ellipse ellipse = command as Ellipse;
534-
if (c == 0) {
535-
// Ellipses that start a new path need to set start point,
536-
// otherwise it incorrectly uses last point.
537-
ctx.moveTo(subpath.startX, subpath.startY);
538-
}
539-
DomRenderer.ellipse(ctx,
540-
ellipse.x,
541-
ellipse.y,
542-
ellipse.radiusX,
543-
ellipse.radiusY,
544-
ellipse.rotation,
545-
ellipse.startAngle,
546-
ellipse.endAngle,
547-
ellipse.anticlockwise);
548-
break;
549-
case PathCommandTypes.lineTo:
550-
final LineTo lineTo = command as LineTo;
551-
ctx.lineTo(lineTo.x, lineTo.y);
552-
break;
553-
case PathCommandTypes.moveTo:
554-
final MoveTo moveTo = command as MoveTo;
555-
ctx.moveTo(moveTo.x, moveTo.y);
556-
break;
557-
case PathCommandTypes.rRect:
558-
final RRectCommand rrectCommand = command as RRectCommand;
559-
_RRectToCanvasRenderer(ctx)
560-
.render(rrectCommand.rrect, startNewPath: false);
561-
break;
562-
case PathCommandTypes.rect:
563-
final RectCommand rectCommand = command as RectCommand;
564-
ctx.rect(rectCommand.x, rectCommand.y, rectCommand.width,
565-
rectCommand.height);
566-
break;
567-
case PathCommandTypes.quadraticCurveTo:
568-
final QuadraticCurveTo quadraticCurveTo = command as QuadraticCurveTo;
569-
ctx.quadraticCurveTo(quadraticCurveTo.x1, quadraticCurveTo.y1,
570-
quadraticCurveTo.x2, quadraticCurveTo.y2);
571-
break;
572-
default:
573-
throw UnimplementedError('Unknown path command $command');
574-
}
518+
final Float32List p = _runBuffer;
519+
final PathRefIterator iter = PathRefIterator(path.pathRef);
520+
int verb = 0;
521+
while ((verb = iter.next(p)) != SPath.kDoneVerb) {
522+
switch (verb) {
523+
case SPath.kMoveVerb:
524+
ctx.moveTo(p[0], p[1]);
525+
break;
526+
case SPath.kLineVerb:
527+
ctx.lineTo(p[2], p[3]);
528+
break;
529+
case SPath.kCubicVerb:
530+
ctx.bezierCurveTo(p[2], p[3], p[4], p[5], p[6], p[7]);
531+
break;
532+
case SPath.kQuadVerb:
533+
ctx.quadraticCurveTo(p[2], p[3], p[4], p[5]);
534+
break;
535+
case SPath.kConicVerb:
536+
final double w = iter.conicWeight;
537+
Conic conic = Conic(p[0], p[1], p[2], p[3], p[4], p[5], w);
538+
List<ui.Offset> points = conic.toQuads();
539+
final int len = points.length;
540+
for (int i = 1; i < len; i += 2) {
541+
final double p1x = points[i].dx;
542+
final double p1y = points[i].dy;
543+
final double p2x = points[i + 1].dx;
544+
final double p2y = points[i + 1].dy;
545+
ctx.quadraticCurveTo(p1x, p1y, p2x, p2y);
546+
}
547+
break;
548+
case SPath.kCloseVerb:
549+
ctx.closePath();
550+
break;
551+
default:
552+
throw UnimplementedError('Unknown path verb $verb');
575553
}
576554
}
577555
}

lib/web_ui/lib/src/engine/surface/clip.dart

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
65
part of engine;
76

87
/// Mixin used by surfaces that clip their contents using an overflowing DOM
@@ -261,15 +260,15 @@ class PersistedPhysicalShape extends PersistedContainerSurface
261260
}
262261
return;
263262
} else {
264-
final Ellipse? ellipse = path.webOnlyPathAsCircle;
265-
if (ellipse != null) {
266-
final double rx = ellipse.radiusX;
267-
final double ry = ellipse.radiusY;
263+
final ui.Rect? ovalRect = path.webOnlyPathAsCircle;
264+
if (ovalRect != null) {
265+
final double rx = ovalRect.width / 2.0;
266+
final double ry = ovalRect.height / 2.0;
268267
final String borderRadius =
269268
rx == ry ? '${rx}px ' : '${rx}px ${ry}px ';
270269
final html.CssStyleDeclaration style = rootElement!.style;
271-
final double left = ellipse.x - rx;
272-
final double top = ellipse.y - ry;
270+
final double left = ovalRect.left;
271+
final double top = ovalRect.top;
273272
style
274273
..left = '${left}px'
275274
..top = '${top}px'

0 commit comments

Comments
 (0)