mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Take devicePixelRatio into account when drawing shadows (#13786)
* Take devicePixelRatio into account when drawing shadows This fixes a bug where shadows were offset in CanvasKit * Respond to review comments
This commit is contained in:
parent
63e8c6275e
commit
e150bf3305
@ -108,6 +108,7 @@ class SkCanvas {
|
||||
|
||||
void drawShadow(ui.Path path, ui.Color color, double elevation,
|
||||
bool transparentOccluder) {
|
||||
drawSkShadow(skCanvas, path, color, elevation, transparentOccluder);
|
||||
drawSkShadow(skCanvas, path, color, elevation, transparentOccluder,
|
||||
ui.window.devicePixelRatio);
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,8 +341,60 @@ class PhysicalShapeLayer extends ContainerLayer
|
||||
@override
|
||||
void preroll(PrerollContext prerollContext, Matrix4 matrix) {
|
||||
prerollChildren(prerollContext, matrix);
|
||||
paintBounds =
|
||||
ElevationShadow.computeShadowRect(_path.getBounds(), _elevation);
|
||||
|
||||
paintBounds = _path.getBounds();
|
||||
if (_elevation == 0.0) {
|
||||
// No need to extend the paint bounds if there is no shadow.
|
||||
return;
|
||||
} else {
|
||||
// Add some margin to the paint bounds to leave space for the shadow.
|
||||
// We fill this whole region and clip children to it so we don't need to
|
||||
// join the child paint bounds.
|
||||
// The offset is calculated as follows:
|
||||
|
||||
// .--- (kLightRadius)
|
||||
// -------/ (light)
|
||||
// | /
|
||||
// | /
|
||||
// |/
|
||||
// |O
|
||||
// /| (kLightHeight)
|
||||
// / |
|
||||
// / |
|
||||
// / |
|
||||
// / |
|
||||
// ------------- (layer)
|
||||
// /| |
|
||||
// / | | (elevation)
|
||||
// A / | |B
|
||||
// ------------------------------------------------ (canvas)
|
||||
// --- (extent of shadow)
|
||||
//
|
||||
// E = lt } t = (r + w/2)/h
|
||||
// } =>
|
||||
// r + w/2 = ht } E = (l/h)(r + w/2)
|
||||
//
|
||||
// Where: E = extent of shadow
|
||||
// l = elevation of layer
|
||||
// r = radius of the light source
|
||||
// w = width of the layer
|
||||
// h = light height
|
||||
// t = tangent of AOB, i.e., multiplier for elevation to extent
|
||||
final double devicePixelRatio = ui.window.devicePixelRatio;
|
||||
|
||||
final double radius = kLightRadius * devicePixelRatio;
|
||||
// tangent for x
|
||||
double tx = (radius + paintBounds.width * 0.5) / kLightHeight;
|
||||
// tangent for y
|
||||
double ty = (radius + paintBounds.height * 0.5) / kLightHeight;
|
||||
|
||||
paintBounds = ui.Rect.fromLTRB(
|
||||
paintBounds.left - tx,
|
||||
paintBounds.top - ty,
|
||||
paintBounds.right + tx,
|
||||
paintBounds.bottom + ty,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@ -228,7 +228,8 @@ class SkRecordingCanvas implements RecordingCanvas {
|
||||
@override
|
||||
void drawShadow(ui.Path path, ui.Color color, double elevation,
|
||||
bool transparentOccluder) {
|
||||
drawSkShadow(skCanvas, path, color, elevation, transparentOccluder);
|
||||
drawSkShadow(skCanvas, path, color, elevation, transparentOccluder,
|
||||
ui.window.devicePixelRatio);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@ -193,12 +193,17 @@ js.JsArray<double> makeSkMatrix(Float64List matrix4) {
|
||||
return skMatrix;
|
||||
}
|
||||
|
||||
// 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,
|
||||
ui.Color color,
|
||||
double elevation,
|
||||
bool transparentOccluder,
|
||||
double devicePixelRatio,
|
||||
) {
|
||||
const double ambientAlpha = 0.039;
|
||||
const double spotAlpha = 0.25;
|
||||
@ -222,9 +227,10 @@ void drawSkShadow(
|
||||
|
||||
skCanvas.callMethod('drawShadow', <dynamic>[
|
||||
path._skPath,
|
||||
js.JsArray<double>.from(<double>[0, 0, elevation]),
|
||||
js.JsArray<double>.from(<double>[shadowX, shadowY, 600]),
|
||||
800,
|
||||
js.JsArray<double>.from(<double>[0, 0, devicePixelRatio * elevation]),
|
||||
js.JsArray<double>.from(
|
||||
<double>[shadowX, shadowY, devicePixelRatio * kLightHeight]),
|
||||
devicePixelRatio * kLightRadius,
|
||||
tonalColors['ambient'],
|
||||
tonalColors['spot'],
|
||||
flags,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user