Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/box-shadow #66

Merged
merged 3 commits into from
Mar 17, 2021
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
Binary file modified integration_tests/snapshots/BoxShadow basic usage.1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified integration_tests/snapshots/BoxShadow remove box-shadow.1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
74 changes: 74 additions & 0 deletions integration_tests/specs/css/css-box/box-shadow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,80 @@ describe('BoxShadow', () => {
await matchElementImageSnapshot(reference);
});

it('with background color', async () => {
let div;
div = createElement(
'div',
{
style: {
display: 'inline-block',
width: '200px',
height: '100px',
margin: '20px',
backgroundColor: 'green',
boxShadow: '0 0 10px 5px rgba(0, 0, 0, 0.6)',
},
},
);
BODY.appendChild(div);
await matchViewportSnapshot();
});

it('without background color and shadow offset', async () => {
let div;
div = createElement(
'div',
{
style: {
display: 'inline-block',
width: '200px',
height: '100px',
margin: '20px',
boxShadow: '0 0 10px 5px rgba(0, 0, 0, 0.6)',
},
},
);
BODY.appendChild(div);
await matchViewportSnapshot();
});

it('with shadow blur and spread radius', async () => {
let div;
div = createElement(
'div',
{
style: {
display: 'inline-block',
width: '200px',
height: '100px',
margin: '20px',
boxShadow: '5px 5px 10px 0px rgba(0, 0, 0, 0.6)',
},
},
);
BODY.appendChild(div);
await matchViewportSnapshot();
});

it('with border radius', async () => {
let div;
div = createElement(
'div',
{
style: {
display: 'inline-block',
width: '200px',
height: '100px',
margin: '20px',
borderRadius: '10px',
boxShadow: '5px 5px 10px 0px rgba(0, 0, 0, 0.6)',
},
},
);
BODY.appendChild(div);
await matchViewportSnapshot();
});

it('remove box-shadow', async () => {
const div = createElementWithStyle('div', {
width: '50px',
Expand Down
46 changes: 41 additions & 5 deletions kraken/lib/src/rendering/box_decoration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -200,12 +200,48 @@ class BoxDecorationPainter extends BoxPainter {
if (_decoration.boxShadow == null)
return;
for (final BoxShadow boxShadow in _decoration.boxShadow) {
final Paint paint = boxShadow.toPaint();
final Rect bounds = rect.shift(boxShadow.offset).inflate(boxShadow.spreadRadius);
_paintBox(canvas, bounds, paint, textDirection);
_paintBoxShadow(canvas, rect, textDirection, boxShadow);
}
}

void _paintBoxShadow(Canvas canvas, Rect rect, TextDirection textDirection, BoxShadow boxShadow) {
final Paint paint = Paint()
..color = boxShadow.color
// Following W3C spec, blur sigma is exactly half the blur radius
// which is different from the value of Flutter:
// https://www.w3.org/TR/css-backgrounds-3/#shadow-blur
// https://html.spec.whatwg.org/C/#when-shadows-are-drawn
..maskFilter = MaskFilter.blur(BlurStyle.normal, boxShadow.blurRadius / 2);

// Rect of box shadow not including blur radius
final Rect shadowRect = rect.shift(boxShadow.offset).inflate(boxShadow.spreadRadius);
// Rect of box shadow including blur radius, add 1 pixel to avoid the fill bleed in (due to antialiasing)
final Rect shadowBlurRect = rect.shift(boxShadow.offset).inflate(boxShadow.spreadRadius + boxShadow.blurRadius + 1);
// Path of border rect
Path borderPath;
// Path of box shadow rect
Path shadowPath;
// Path of box shadow including blur rect
Path shadowBlurPath;

if (_decoration.borderRadius == null) {
borderPath = Path()..addRect(rect);
shadowPath = Path()..addRect(shadowRect);
shadowBlurPath = Path()..addRect(shadowBlurRect);
} else {
borderPath = Path()..addRRect(_decoration.borderRadius.resolve(textDirection).toRRect(rect));
shadowPath = Path()..addRRect(_decoration.borderRadius.resolve(textDirection).toRRect(shadowRect));
shadowBlurPath = Path()..addRRect(_decoration.borderRadius.resolve(textDirection).toRRect(shadowBlurRect));
}

// Path of shadow blur rect subtract border rect of which the box shadow should paint
final Path clipedPath = Path.combine(PathOperation.difference, shadowBlurPath, borderPath);
canvas.save();
canvas.clipPath(clipedPath);
canvas.drawPath(shadowPath, paint);
canvas.restore();
}

void _paintBackgroundColor(Canvas canvas, Rect rect, TextDirection textDirection) {
if (_decoration.color != null || _decoration.gradient != null)
_paintBox(canvas, rect, _getBackgroundPaint(rect, textDirection), textDirection);
Expand Down Expand Up @@ -349,8 +385,6 @@ class BoxDecorationPainter extends BoxPainter {
final Rect rect = offset & configuration.size;
final TextDirection textDirection = configuration.textDirection;

_paintShadows(canvas, rect, textDirection);

bool hasLocalAttachment = hasLocalBackgroundImage(renderStyle);
if (!hasLocalAttachment) {
Rect backgroundClipRect = _getBackgroundClipRect(offset, configuration);
Expand All @@ -368,6 +402,8 @@ class BoxDecorationPainter extends BoxPainter {
borderRadius: _decoration.borderRadius as BorderRadius,
textDirection: configuration.textDirection,
);

_paintShadows(canvas, rect, textDirection);
}

@override
Expand Down