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

Revert "Revert "fix shadows and mask filter blurs (#16963)" (#17008)" #17040

Merged
merged 1 commit into from
Mar 10, 2020
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
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