Fix layer damage and clipping for Text shadows
Fixes: 27787426
Change-Id: I4c65cca0cfcd343a9cfbaedd3a32b83f90df2ecf
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index ea4f4eb..f43bf86 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -195,7 +195,7 @@
}
static void renderTextShadow(BakedOpRenderer& renderer, FontRenderer& fontRenderer,
- const TextOp& op, const BakedOpState& state) {
+ const TextOp& op, const BakedOpState& textOpState) {
renderer.caches().textureState().activateTexture(0);
PaintUtils::TextShadow textShadow;
@@ -216,13 +216,41 @@
Glop glop;
GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
- .setRoundRectClipState(state.roundRectClipState)
+ .setRoundRectClipState(textOpState.roundRectClipState)
.setMeshTexturedUnitQuad(nullptr)
- .setFillShadowTexturePaint(*texture, textShadow.color, *op.paint, state.alpha)
- .setTransform(state.computedState.transform, TransformFlags::None)
+ .setFillShadowTexturePaint(*texture, textShadow.color, *op.paint, textOpState.alpha)
+ .setTransform(textOpState.computedState.transform, TransformFlags::None)
.setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width(), sy + texture->height()))
.build();
- renderer.renderGlop(state, glop);
+
+ // Compute damage bounds and clip (since may differ from those in textOpState).
+ // Bounds should be same as text op, but with dx/dy offset and radius outset
+ // applied in local space.
+ auto& transform = textOpState.computedState.transform;
+ Rect shadowBounds = op.unmappedBounds; // STROKE
+ const bool expandForStroke = op.paint->getStyle() != SkPaint::kFill_Style;
+ if (expandForStroke) {
+ shadowBounds.outset(op.paint->getStrokeWidth() * 0.5f);
+ }
+ shadowBounds.translate(textShadow.dx, textShadow.dy);
+ shadowBounds.outset(textShadow.radius, textShadow.radius);
+ transform.mapRect(shadowBounds);
+ if (CC_UNLIKELY(expandForStroke &&
+ (!transform.isPureTranslate() || op.paint->getStrokeWidth() < 1.0f))) {
+ shadowBounds.outset(0.5f);
+ }
+
+ auto clipState = textOpState.computedState.clipState;
+ if (clipState->mode != ClipMode::Rectangle
+ || !clipState->rect.contains(shadowBounds)) {
+ // need clip, so pass it and clip bounds
+ shadowBounds.doIntersect(clipState->rect);
+ } else {
+ // don't need clip, ignore
+ clipState = nullptr;
+ }
+
+ renderer.renderGlop(&shadowBounds, clipState, glop);
}
enum class TextRenderType {