Skip to content

Commit

Permalink
Shadows paint at the wrong scale in replayed CGDisplayLists
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=246369
rdar://96967173

Reviewed by Simon Fraser.

* Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp:
(WebCore::GraphicsContextCG::fillRect):
(WebCore::GraphicsContextCG::fillRoundedRectImpl):
(WebCore::GraphicsContextCG::fillRectWithRoundedHole):
(WebCore::GraphicsContextCG::setCGShadow):
(WebCore::GraphicsContextCG::clearCGShadow):
(WebCore::GraphicsContextCG::didUpdateState):
(WebCore::setCGShadow): Deleted.
Make setCGShadow virtual so that GraphicsContextCGDisplayList can adjust its behavior.
Drive-by factor out clearCGShadow so all the CGContext-touching code is all in one place.

* Source/WebCore/platform/graphics/cg/GraphicsContextCG.h:
* Source/WebKit/Shared/RemoteLayerTree/CGDisplayListImageBufferBackend.mm:
(WebKit::GraphicsContextCGDisplayList::GraphicsContextCGDisplayList):
Work around a confusion re: the base CTM with CGDisplayList image buffers
by mapping the shadow parameters out through the hidden immutable base transform.
We don't actually use the transform here, instead just faking it with the scale
and flip, because we have no mechanism for mapping a size with negative values
through an AffineTransform.

Canonical link: https://commits.webkit.org/255442@main
  • Loading branch information
hortont424 committed Oct 12, 2022
1 parent eeb0925 commit ff0ba2b
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 11 deletions.
24 changes: 13 additions & 11 deletions Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
Expand Up @@ -816,8 +816,7 @@ void GraphicsContextCG::fillRect(const FloatRect& rect)
bool drawOwnShadow = canUseShadowBlur();
CGContextStateSaver stateSaver(context, drawOwnShadow);
if (drawOwnShadow) {
// Turn off CG shadows.
CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
clearCGShadow();

ShadowBlur contextShadow(dropShadow(), shadowsIgnoreTransforms());
contextShadow.drawRectShadow(*this, FloatRoundedRect(rect));
Expand All @@ -837,8 +836,7 @@ void GraphicsContextCG::fillRect(const FloatRect& rect, const Color& color)
bool drawOwnShadow = canUseShadowBlur();
CGContextStateSaver stateSaver(context, drawOwnShadow);
if (drawOwnShadow) {
// Turn off CG shadows.
CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
clearCGShadow();

ShadowBlur contextShadow(dropShadow(), shadowsIgnoreTransforms());
contextShadow.drawRectShadow(*this, FloatRoundedRect(rect));
Expand All @@ -864,8 +862,7 @@ void GraphicsContextCG::fillRoundedRectImpl(const FloatRoundedRect& rect, const
bool drawOwnShadow = canUseShadowBlur();
CGContextStateSaver stateSaver(context, drawOwnShadow);
if (drawOwnShadow) {
// Turn off CG shadows.
CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
clearCGShadow();

ShadowBlur contextShadow(dropShadow(), shadowsIgnoreTransforms());
contextShadow.drawRectShadow(*this, rect);
Expand Down Expand Up @@ -913,8 +910,7 @@ void GraphicsContextCG::fillRectWithRoundedHole(const FloatRect& rect, const Flo
bool drawOwnShadow = canUseShadowBlur();
CGContextStateSaver stateSaver(context, drawOwnShadow);
if (drawOwnShadow) {
// Turn off CG shadows.
CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
clearCGShadow();

ShadowBlur contextShadow(dropShadow(), shadowsIgnoreTransforms());
contextShadow.drawInsetShadow(*this, rect, roundedHoleRect);
Expand Down Expand Up @@ -1030,10 +1026,10 @@ static void applyShadowOffsetWorkaroundIfNeeded(CGContextRef context, CGFloat& x
#endif
}

static void setCGShadow(CGContextRef context, RenderingMode renderingMode, const FloatSize& offset, float blur, const Color& color, bool shadowsIgnoreTransforms)
void GraphicsContextCG::setCGShadow(RenderingMode renderingMode, const FloatSize& offset, float blur, const Color& color, bool shadowsIgnoreTransforms)
{
if (offset.isZero() && !blur) {
CGContextSetShadowWithColor(context, CGSizeZero, 0, 0);
clearCGShadow();
return;
}

Expand All @@ -1042,6 +1038,7 @@ static void setCGShadow(CGContextRef context, RenderingMode renderingMode, const
CGFloat xOffset = offset.width();
CGFloat yOffset = offset.height();
CGFloat blurRadius = blur;
CGContextRef context = platformContext();

if (!shadowsIgnoreTransforms) {
CGAffineTransform userToBaseCTM = getUserToBaseCTM(context);
Expand Down Expand Up @@ -1075,6 +1072,11 @@ static void setCGShadow(CGContextRef context, RenderingMode renderingMode, const
CGContextSetShadowWithColor(context, CGSizeMake(xOffset, yOffset), blurRadius, cachedCGColor(color).get());
}

void GraphicsContextCG::clearCGShadow()
{
CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
}

void GraphicsContextCG::didUpdateState(GraphicsContextState& state)
{
if (!state.changes())
Expand All @@ -1101,7 +1103,7 @@ void GraphicsContextCG::didUpdateState(GraphicsContextState& state)
break;

case GraphicsContextState::Change::DropShadow:
setCGShadow(context, renderingMode(), state.dropShadow().offset, state.dropShadow().blurRadius, state.dropShadow().color, state.shadowsIgnoreTransforms());
setCGShadow(renderingMode(), state.dropShadow().offset, state.dropShadow().blurRadius, state.dropShadow().color, state.shadowsIgnoreTransforms());
break;

case GraphicsContextState::Change::Alpha:
Expand Down
5 changes: 5 additions & 0 deletions Source/WebCore/platform/graphics/cg/GraphicsContextCG.h
Expand Up @@ -135,9 +135,14 @@ class WEBCORE_EXPORT GraphicsContextCG : public GraphicsContext {
GraphicsContextPlatformPrivate* deprecatedPrivateContext() const final;
#endif

protected:
virtual void setCGShadow(RenderingMode, const FloatSize& offset, float blur, const Color&, bool shadowsIgnoreTransforms);

private:
void convertToDestinationColorSpaceIfNeeded(RetainPtr<CGImageRef>&);

void clearCGShadow();

GraphicsContextPlatformPrivate* m_data { nullptr };
};

Expand Down
Expand Up @@ -54,6 +54,7 @@
m_immutableBaseTransform.translate(0, -ceilf(parameters.logicalSize.height() * parameters.resolutionScale));
m_immutableBaseTransform.scale(parameters.resolutionScale);
m_inverseImmutableBaseTransform = *m_immutableBaseTransform.inverse();
m_resolutionScale = parameters.resolutionScale;
}

void setCTM(const WebCore::AffineTransform& transform) final
Expand All @@ -68,9 +69,19 @@ void setCTM(const WebCore::AffineTransform& transform) final

bool canUseShadowBlur() const final { return false; }

protected:
void setCGShadow(WebCore::RenderingMode renderingMode, const WebCore::FloatSize& offset, float blur, const WebCore::Color& color, bool shadowsIgnoreTransforms) override
{
// This doesn't use `m_immutableBaseTransform.mapSize` because it doesn't output negative lengths.
WebCore::FloatSize scaledOffset = offset;
scaledOffset.scale(m_resolutionScale, -m_resolutionScale);
GraphicsContextCG::setCGShadow(renderingMode, scaledOffset, blur * m_resolutionScale, color, shadowsIgnoreTransforms);
}

private:
WebCore::AffineTransform m_immutableBaseTransform;
WebCore::AffineTransform m_inverseImmutableBaseTransform;
float m_resolutionScale;
};

WTF_MAKE_ISO_ALLOCATED_IMPL(CGDisplayListImageBufferBackend);
Expand Down

0 comments on commit ff0ba2b

Please sign in to comment.