Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[web] Add support for path transform #12794

Merged
merged 19 commits into from
Oct 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/platform_views.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/plugins.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/pointer_binding.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/recording_canvas.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/rrect_renderer.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/accessibility.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/checkable.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/image.dart
Expand Down
1 change: 1 addition & 0 deletions lib/web_ui/lib/src/engine.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ part 'engine/platform_views.dart';
part 'engine/plugins.dart';
part 'engine/pointer_binding.dart';
part 'engine/recording_canvas.dart';
part 'engine/rrect_renderer.dart';
part 'engine/semantics/accessibility.dart';
part 'engine/semantics/checkable.dart';
part 'engine/semantics/image.dart';
Expand Down
197 changes: 6 additions & 191 deletions lib/web_ui/lib/src/engine/bitmap_canvas.dart
Original file line number Diff line number Diff line change
Expand Up @@ -454,202 +454,16 @@ class BitmapCanvas extends EngineCanvas with SaveStackTracking {
@override
void drawRRect(ui.RRect rrect, ui.PaintData paint) {
_applyPaint(paint);
_drawRRectPath(rrect);
_RRectToCanvasRenderer(ctx).render(rrect);
_strokeOrFill(paint);
}

void _drawRRectPath(ui.RRect inputRRect, {bool startNewPath = true}) {
// TODO(mdebbar): Backport the overlapping corners fix to houdini_painter.js
// To draw the rounded rectangle, perform the following steps:
// 0. Ensure border radius don't overlap
// 1. Flip left,right top,bottom since web doesn't support flipped
// coordinates with negative radii.
// 2. draw the line for the top
// 3. draw the arc for the top-right corner
// 4. draw the line for the right side
// 5. draw the arc for the bottom-right corner
// 6. draw the line for the bottom of the rectangle
// 7. draw the arc for the bottom-left corner
// 8. draw the line for the left side
// 9. draw the arc for the top-left corner
//
// After drawing, the current point will be the left side of the top of the
// rounded rectangle (after the corner).
// TODO(het): Confirm that this is the end point in Flutter for RRect

// Ensure border radius curves never overlap
final ui.RRect rrect = inputRRect.scaleRadii();

double left = rrect.left;
double right = rrect.right;
double top = rrect.top;
double bottom = rrect.bottom;
if (left > right) {
left = right;
right = rrect.left;
}
if (top > bottom) {
top = bottom;
bottom = rrect.top;
}
final double trRadiusX = rrect.trRadiusX.abs();
final double tlRadiusX = rrect.tlRadiusX.abs();
final double trRadiusY = rrect.trRadiusY.abs();
final double tlRadiusY = rrect.tlRadiusY.abs();
final double blRadiusX = rrect.blRadiusX.abs();
final double brRadiusX = rrect.brRadiusX.abs();
final double blRadiusY = rrect.blRadiusY.abs();
final double brRadiusY = rrect.brRadiusY.abs();

if (startNewPath) {
ctx.beginPath();
}

ctx.moveTo(left + trRadiusX, top);

// Top side and top-right corner
ctx.lineTo(right - trRadiusX, top);
ctx.ellipse(
right - trRadiusX,
top + trRadiusY,
trRadiusX,
trRadiusY,
0,
1.5 * math.pi,
2.0 * math.pi,
false,
);

// Right side and bottom-right corner
ctx.lineTo(right, bottom - brRadiusY);
ctx.ellipse(
right - brRadiusX,
bottom - brRadiusY,
brRadiusX,
brRadiusY,
0,
0,
0.5 * math.pi,
false,
);

// Bottom side and bottom-left corner
ctx.lineTo(left + blRadiusX, bottom);
ctx.ellipse(
left + blRadiusX,
bottom - blRadiusY,
blRadiusX,
blRadiusY,
0,
0.5 * math.pi,
math.pi,
false,
);

// Left side and top-left corner
ctx.lineTo(left, top + tlRadiusY);
ctx.ellipse(
left + tlRadiusX,
top + tlRadiusY,
tlRadiusX,
tlRadiusY,
0,
math.pi,
1.5 * math.pi,
false,
);
}

void _drawRRectPathReverse(ui.RRect inputRRect, {bool startNewPath = true}) {
// Ensure border radius curves never overlap
final ui.RRect rrect = inputRRect.scaleRadii();

double left = rrect.left;
double right = rrect.right;
double top = rrect.top;
double bottom = rrect.bottom;
final double trRadiusX = rrect.trRadiusX.abs();
final double tlRadiusX = rrect.tlRadiusX.abs();
final double trRadiusY = rrect.trRadiusY.abs();
final double tlRadiusY = rrect.tlRadiusY.abs();
final double blRadiusX = rrect.blRadiusX.abs();
final double brRadiusX = rrect.brRadiusX.abs();
final double blRadiusY = rrect.blRadiusY.abs();
final double brRadiusY = rrect.brRadiusY.abs();

if (left > right) {
left = right;
right = rrect.left;
}
if (top > bottom) {
top = bottom;
bottom = rrect.top;
}
// Draw the rounded rectangle, counterclockwise.
ctx.moveTo(right - trRadiusX, top);

if (startNewPath) {
ctx.beginPath();
}

// Top side and top-left corner
ctx.lineTo(left + tlRadiusX, top);
ctx.ellipse(
left + tlRadiusX,
top + tlRadiusY,
tlRadiusX,
tlRadiusY,
0,
1.5 * math.pi,
1 * math.pi,
true,
);

// Left side and bottom-left corner
ctx.lineTo(left, bottom - blRadiusY);
ctx.ellipse(
left + blRadiusX,
bottom - blRadiusY,
blRadiusX,
blRadiusY,
0,
1 * math.pi,
0.5 * math.pi,
true,
);

// Bottom side and bottom-right corner
ctx.lineTo(right - brRadiusX, bottom);
ctx.ellipse(
right - brRadiusX,
bottom - brRadiusY,
brRadiusX,
brRadiusY,
0,
0.5 * math.pi,
0 * math.pi,
true,
);

// Right side and top-right corner
ctx.lineTo(right, top + trRadiusY);
ctx.ellipse(
right - trRadiusX,
top + trRadiusY,
trRadiusX,
trRadiusY,
0,
0 * math.pi,
1.5 * math.pi,
true,
);
}

@override
void drawDRRect(ui.RRect outer, ui.RRect inner, ui.PaintData paint) {
_applyPaint(paint);
_drawRRectPath(outer);
_drawRRectPathReverse(inner, startNewPath: false);
_RRectRenderer renderer = _RRectToCanvasRenderer(ctx);
renderer.render(outer);
renderer.render(inner, startNewPath: false, reverse: true);
_strokeOrFill(paint);
}

Expand Down Expand Up @@ -886,7 +700,8 @@ class BitmapCanvas extends EngineCanvas with SaveStackTracking {
break;
case PathCommandTypes.rRect:
final RRectCommand rrectCommand = command;
_drawRRectPath(rrectCommand.rrect, startNewPath: false);
_RRectToCanvasRenderer(ctx).render(rrectCommand.rrect,
startNewPath: false);
break;
case PathCommandTypes.rect:
final RectCommand rectCommand = command;
Expand Down
Loading