Skip to content

Commit

Permalink
Revert "Revert "fix shadows and mask filter blurs (#16963)" (#17008)" (
Browse files Browse the repository at this point in the history
…#17040)

This reverts 619acd5 and re-lands 6cfa7fc. The 6cfa7fc was good. The screenshot changes were expected.

Fixes flutter/flutter#32215
  • Loading branch information
yjbanov committed Mar 10, 2020
1 parent 7f942f2 commit d41e25b
Show file tree
Hide file tree
Showing 11 changed files with 582 additions and 450 deletions.
2 changes: 1 addition & 1 deletion lib/web_ui/dev/goldens_lock.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
repository: https://github.com/flutter/goldens.git
revision: 1699ba6fd7093a0a610f82618fa30546e7974777
revision: 8f692819e8881b7d2131dbd61d965c21d5e3e345
21 changes: 9 additions & 12 deletions lib/web_ui/lib/src/engine/bitmap_canvas.dart
Original file line number Diff line number Diff line change
Expand Up @@ -353,17 +353,16 @@ class BitmapCanvas extends EngineCanvas {

@override
void drawImage(ui.Image image, ui.Offset p, SurfacePaintData paint) {
//_applyPaint(paint);
final HtmlImage htmlImage = image;
final html.ImageElement imgElement = htmlImage.cloneImageElement();
String blendMode = _stringForBlendMode(paint.blendMode);
imgElement.style.mixBlendMode = blendMode;
_drawImage(imgElement, p);
_drawImage(image, p, paint);
_childOverdraw = true;
_canvasPool.allocateExtraCanvas();
}

void _drawImage(html.ImageElement imgElement, ui.Offset p) {
html.ImageElement _drawImage(ui.Image image, ui.Offset p, SurfacePaintData paint) {
final HtmlImage htmlImage = image;
final html.Element imgElement = htmlImage.cloneImageElement();
final ui.BlendMode blendMode = paint.blendMode;
imgElement.style.mixBlendMode = _stringForBlendMode(blendMode);
if (_canvasPool.isClipped) {
final List<html.Element> clipElements = _clipContent(
_canvasPool._clipStack, imgElement, p, _canvasPool.currentTransform);
Expand All @@ -380,12 +379,12 @@ class BitmapCanvas extends EngineCanvas {
rootElement.append(imgElement);
_children.add(imgElement);
}
return imgElement;
}

@override
void drawImageRect(
ui.Image image, ui.Rect src, ui.Rect dst, SurfacePaintData paint) {
final HtmlImage htmlImage = image;
final bool requiresClipping = src.left != 0 ||
src.top != 0 ||
src.width != image.width ||
Expand All @@ -395,9 +394,6 @@ class BitmapCanvas extends EngineCanvas {
!requiresClipping) {
drawImage(image, dst.topLeft, paint);
} else {
final html.Element imgElement = htmlImage.cloneImageElement();
final ui.BlendMode blendMode = paint.blendMode;
imgElement.style.mixBlendMode = _stringForBlendMode(blendMode);
if (requiresClipping) {
save();
clipRect(dst);
Expand All @@ -414,7 +410,8 @@ class BitmapCanvas extends EngineCanvas {
targetTop += topMargin;
}
}
_drawImage(imgElement, ui.Offset(targetLeft, targetTop));

final html.ImageElement imgElement = _drawImage(image, ui.Offset(targetLeft, targetTop), paint);
// To scale set width / height on destination image.
// For clipping we need to scale according to
// clipped-width/full image width and shift it according to left/top of
Expand Down
83 changes: 40 additions & 43 deletions lib/web_ui/lib/src/engine/canvas_pool.dart
Original file line number Diff line number Diff line change
Expand Up @@ -581,49 +581,46 @@ class _CanvasPool extends _SaveStackTracking {

void drawShadow(ui.Path path, ui.Color color, double elevation,
bool transparentOccluder) {
final List<CanvasShadow> shadows =
ElevationShadow.computeCanvasShadows(elevation, color);
if (shadows.isNotEmpty) {
for (final CanvasShadow shadow in shadows) {
// TODO(het): Shadows with transparent occluders are not supported
// on webkit since filter is unsupported.
if (transparentOccluder && browserEngine != BrowserEngine.webkit) {
// We paint shadows using a path and a mask filter instead of the
// built-in shadow* properties. This is because the color alpha of the
// paint is added to the shadow. The effect we're looking for is to just
// paint the shadow without the path itself, but if we use a non-zero
// alpha for the paint the path is painted in addition to the shadow,
// which is undesirable.
context.save();
context.translate(shadow.offsetX, shadow.offsetY);
context.filter = _maskFilterToCss(
ui.MaskFilter.blur(ui.BlurStyle.normal, shadow.blur));
context.strokeStyle = '';
context.fillStyle = colorToCssString(shadow.color);
_runPath(context, path);
context.fill();
context.restore();
} else {
// TODO(het): We fill the path with this paint, then later we clip
// by the same path and fill it with a fully opaque color (we know
// the color is fully opaque because `transparentOccluder` is false.
// However, due to anti-aliasing of the clip, a few pixels of the
// path we are about to paint may still be visible after we fill with
// the opaque occluder. For that reason, we fill with the shadow color,
// and set the shadow color to fully opaque. This way, the visible
// pixels are less opaque and less noticeable.
context.save();
context.filter = 'none';
context.strokeStyle = '';
context.fillStyle = colorToCssString(shadow.color);
context.shadowBlur = shadow.blur;
context.shadowColor = colorToCssString(shadow.color.withAlpha(0xff));
context.shadowOffsetX = shadow.offsetX;
context.shadowOffsetY = shadow.offsetY;
_runPath(context, path);
context.fill();
context.restore();
}
final SurfaceShadowData shadow = computeShadow(path.getBounds(), elevation);
if (shadow != null) {
// TODO(het): Shadows with transparent occluders are not supported
// on webkit since filter is unsupported.
if (transparentOccluder && browserEngine != BrowserEngine.webkit) {
// We paint shadows using a path and a mask filter instead of the
// built-in shadow* properties. This is because the color alpha of the
// paint is added to the shadow. The effect we're looking for is to just
// paint the shadow without the path itself, but if we use a non-zero
// alpha for the paint the path is painted in addition to the shadow,
// which is undesirable.
context.save();
context.translate(shadow.offset.dx, shadow.offset.dy);
context.filter = _maskFilterToCss(
ui.MaskFilter.blur(ui.BlurStyle.normal, shadow.blurWidth));
context.strokeStyle = '';
context.fillStyle = colorToCssString(color);
_runPath(context, path);
context.fill();
context.restore();
} else {
// TODO(het): We fill the path with this paint, then later we clip
// by the same path and fill it with a fully opaque color (we know
// the color is fully opaque because `transparentOccluder` is false.
// However, due to anti-aliasing of the clip, a few pixels of the
// path we are about to paint may still be visible after we fill with
// the opaque occluder. For that reason, we fill with the shadow color,
// and set the shadow color to fully opaque. This way, the visible
// pixels are less opaque and less noticeable.
context.save();
context.filter = 'none';
context.strokeStyle = '';
context.fillStyle = colorToCssString(color);
context.shadowBlur = shadow.blurWidth;
context.shadowColor = colorToCssString(color.withAlpha(0xff));
context.shadowOffsetX = shadow.offset.dx;
context.shadowOffsetY = shadow.offset.dy;
_runPath(context, path);
context.fill();
context.restore();
}
}
}
Expand Down
4 changes: 0 additions & 4 deletions lib/web_ui/lib/src/engine/compositor/util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -286,10 +286,6 @@ js.JsArray<double> makeSkiaColorStops(List<double> colorStops) {
return jsColorStops;
}

// These must be kept in sync with `flow/layers/physical_shape_layer.cc`.
const double kLightHeight = 600.0;
const double kLightRadius = 800.0;

void drawSkShadow(
js.JsObject skCanvas,
SkPath path,
Expand Down
15 changes: 8 additions & 7 deletions lib/web_ui/lib/src/engine/dom_canvas.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,15 @@ class DomCanvas extends EngineCanvas with SaveElementStackTracking {
}());
String effectiveTransform;
final bool isStroke = paint.style == ui.PaintingStyle.stroke;
final double strokeWidth = paint.strokeWidth ?? 0.0;
final double left = math.min(rect.left, rect.right);
final double right = math.max(rect.left, rect.right);
final double top = math.min(rect.top, rect.bottom);
final double bottom = math.max(rect.top, rect.bottom);
if (currentTransform.isIdentity()) {
if (isStroke) {
effectiveTransform =
'translate(${left - (paint.strokeWidth / 2.0)}px, ${top - (paint.strokeWidth / 2.0)}px)';
'translate(${left - (strokeWidth / 2.0)}px, ${top - (strokeWidth / 2.0)}px)';
} else {
effectiveTransform = 'translate(${left}px, ${top}px)';
}
Expand All @@ -97,7 +98,7 @@ class DomCanvas extends EngineCanvas with SaveElementStackTracking {
final Matrix4 translated = currentTransform.clone();
if (isStroke) {
translated.translate(
left - (paint.strokeWidth / 2.0), top - (paint.strokeWidth / 2.0));
left - (strokeWidth / 2.0), top - (strokeWidth / 2.0));
} else {
translated.translate(left, top);
}
Expand All @@ -109,18 +110,18 @@ class DomCanvas extends EngineCanvas with SaveElementStackTracking {
..transformOrigin = '0 0 0'
..transform = effectiveTransform;

final String cssColor = paint.color == null ? '#000000'
: colorToCssString(paint.color);
final String cssColor =
paint.color == null ? '#000000' : colorToCssString(paint.color);

if (paint.maskFilter != null) {
style.filter = 'blur(${paint.maskFilter.webOnlySigma}px)';
}

if (isStroke) {
style
..width = '${right - left - paint.strokeWidth}px'
..height = '${bottom - top - paint.strokeWidth}px'
..border = '${paint.strokeWidth}px solid $cssColor';
..width = '${right - left - strokeWidth}px'
..height = '${bottom - top - strokeWidth}px'
..border = '${strokeWidth}px solid $cssColor';
} else {
style
..width = '${right - left}px'
Expand Down
Loading

0 comments on commit d41e25b

Please sign in to comment.