Merge "Use new Skia DrawShadow API"

This commit is contained in:
TreeHugger Robot
2017-02-06 19:18:42 +00:00
committed by Android (Google) Code Review

View File

@@ -24,6 +24,7 @@
#include <SkGaussianEdgeShader.h>
#include <SkPathOps.h>
#include <SkRRectsGaussianEdgeMaskFilter.h>
#include <SkShadowUtils.h>
namespace android {
namespace uirenderer {
@@ -115,498 +116,6 @@ void EndReorderBarrierDrawable::onDraw(SkCanvas* canvas) {
}
}
/**
* @param canvas the destination for the shadow draws
* @param shape the shape casting the shadow
* @param casterZValue the Z value of the caster RRect
* @param ambientAlpha the maximum alpha value to use when drawing the ambient shadow
* @param draw the function used to draw 'shape'
*/
template <typename Shape, typename F>
static void DrawAmbientShadowGeneral(SkCanvas* canvas, const Shape& shape, float casterZValue,
float ambientAlpha, F&& draw) {
if (ambientAlpha <= 0) {
return;
}
const float kHeightFactor = 1.f/128.f;
const float kGeomFactor = 64;
float umbraAlpha = 1 / (1 + SkMaxScalar(casterZValue*kHeightFactor, 0));
float radius = casterZValue*kHeightFactor*kGeomFactor;
sk_sp<SkMaskFilter> mf = SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
SkBlurMask::ConvertRadiusToSigma(radius), SkBlurMaskFilter::kNone_BlurFlag);
SkPaint paint;
paint.setAntiAlias(true);
paint.setMaskFilter(std::move(mf));
paint.setARGB(ambientAlpha*umbraAlpha, 0, 0, 0);
draw(shape, paint);
}
/**
* @param canvas the destination for the shadow draws
* @param shape the shape casting the shadow
* @param casterZValue the Z value of the caster RRect
* @param lightPos the position of the light casting the shadow
* @param lightWidth
* @param spotAlpha the maximum alpha value to use when drawing the spot shadow
* @param draw the function used to draw 'shape'
*/
template <typename Shape, typename F>
static void DrawSpotShadowGeneral(SkCanvas* canvas, const Shape& shape, float casterZValue,
float spotAlpha, F&& draw) {
if (spotAlpha <= 0) {
return;
}
const Vector3 lightPos = SkiaPipeline::getLightCenter();
float zRatio = casterZValue / (lightPos.z - casterZValue);
// clamp
if (zRatio < 0.0f) {
zRatio = 0.0f;
} else if (zRatio > 0.95f) {
zRatio = 0.95f;
}
float blurRadius = SkiaPipeline::getLightRadius()*zRatio;
SkAutoCanvasRestore acr(canvas, true);
sk_sp<SkMaskFilter> mf = SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
SkBlurMask::ConvertRadiusToSigma(blurRadius), SkBlurMaskFilter::kNone_BlurFlag);
SkPaint paint;
paint.setAntiAlias(true);
paint.setMaskFilter(std::move(mf));
paint.setARGB(spotAlpha, 0, 0, 0);
// approximate projection by translating and scaling projected offset of bounds center
// TODO: compute the actual 2D projection
SkScalar scale = lightPos.z / (lightPos.z - casterZValue);
canvas->scale(scale, scale);
SkPoint center = SkPoint::Make(shape.getBounds().centerX(), shape.getBounds().centerY());
SkMatrix ctmInverse;
if (!canvas->getTotalMatrix().invert(&ctmInverse)) {
ALOGW("Matrix is degenerate. Will not render shadow!");
return;
}
SkPoint lightPos2D = SkPoint::Make(lightPos.x, lightPos.y);
ctmInverse.mapPoints(&lightPos2D, 1);
canvas->translate(zRatio*(center.fX - lightPos2D.fX), zRatio*(center.fY - lightPos2D.fY));
draw(shape, paint);
}
#define MAX_BLUR_RADIUS 16383.75f
#define MAX_PAD 64
/**
* @param casterRect the rectangle bounds of the RRect casting the shadow
* @param casterCornerRadius the x&y radius for all the corners of the RRect casting the shadow
* @param ambientAlpha the maximum alpha value to use when drawing the ambient shadow
* @param spotAlpha the maximum alpha value to use when drawing the spot shadow
* @param casterAlpha the alpha value of the RRect casting the shadow (0.0-1.0 range)
* @param casterZValue the Z value of the caster RRect
* @param scaleFactor the scale needed to map from src-space to device-space
* @param canvas the destination for the shadow draws
*/
static void DrawRRectShadows(const SkRect& casterRect, SkScalar casterCornerRadius,
SkScalar ambientAlpha, SkScalar spotAlpha, SkScalar casterAlpha, SkScalar casterZValue,
SkScalar scaleFactor, SkCanvas* canvas) {
SkASSERT(casterCornerRadius >= 0.0f);
// For all of these, we need to ensure we have a rrect with radius >= 0.5f in device space
const SkScalar minRadius = 0.5f / scaleFactor;
const bool isOval = casterCornerRadius >= std::max(SkScalarHalf(casterRect.width()),
SkScalarHalf(casterRect.height()));
const bool isRect = casterCornerRadius <= minRadius;
sk_sp<SkShader> edgeShader(SkGaussianEdgeShader::Make());
if (ambientAlpha > 0.0f) {
static const float kHeightFactor = 1.0f / 128.0f;
static const float kGeomFactor = 64.0f;
SkScalar srcSpaceAmbientRadius = casterZValue * kHeightFactor * kGeomFactor;
// the device-space radius sent to the blur shader must fit in 14.2 fixed point
if (srcSpaceAmbientRadius*scaleFactor > MAX_BLUR_RADIUS) {
srcSpaceAmbientRadius = MAX_BLUR_RADIUS/scaleFactor;
}
const float umbraAlpha = 1.0f / (1.0f + std::max(casterZValue * kHeightFactor, 0.0f));
const SkScalar ambientOffset = srcSpaceAmbientRadius * umbraAlpha;
// For the ambient rrect, we inset the offset rect by half the srcSpaceAmbientRadius
// to get our stroke shape.
SkScalar ambientPathOutset = std::max(ambientOffset - srcSpaceAmbientRadius * 0.5f,
minRadius);
SkRRect ambientRRect;
const SkRect temp = casterRect.makeOutset(ambientPathOutset, ambientPathOutset);
if (isOval) {
ambientRRect = SkRRect::MakeOval(temp);
} else if (isRect) {
ambientRRect = SkRRect::MakeRectXY(temp, ambientPathOutset, ambientPathOutset);
} else {
ambientRRect = SkRRect::MakeRectXY(temp, casterCornerRadius + ambientPathOutset,
casterCornerRadius + ambientPathOutset);
}
SkPaint paint;
paint.setAntiAlias(true);
paint.setStyle(SkPaint::kStroke_Style);
// we outset the stroke a little to cover up AA on the interior edge
float pad = 0.5f;
paint.setStrokeWidth(srcSpaceAmbientRadius + 2.0f * pad);
// handle scale of radius and pad due to CTM
pad *= scaleFactor;
const SkScalar devSpaceAmbientRadius = srcSpaceAmbientRadius * scaleFactor;
SkASSERT(devSpaceAmbientRadius <= MAX_BLUR_RADIUS);
SkASSERT(pad < MAX_PAD);
// convert devSpaceAmbientRadius to 14.2 fixed point and place in the R & G components
// convert pad to 6.2 fixed point and place in the B component
uint16_t iDevSpaceAmbientRadius = (uint16_t)(4.0f * devSpaceAmbientRadius);
paint.setColor(SkColorSetARGB((unsigned char) ambientAlpha, iDevSpaceAmbientRadius >> 8,
iDevSpaceAmbientRadius & 0xff, (unsigned char)(4.0f * pad)));
paint.setShader(edgeShader);
canvas->drawRRect(ambientRRect, paint);
}
if (spotAlpha > 0.0f) {
const Vector3 lightPos = SkiaPipeline::getLightCenter();
float zRatio = casterZValue / (lightPos.z - casterZValue);
// clamp
if (zRatio < 0.0f) {
zRatio = 0.0f;
} else if (zRatio > 0.95f) {
zRatio = 0.95f;
}
const SkScalar lightWidth = SkiaPipeline::getLightRadius();
SkScalar srcSpaceSpotRadius = 2.0f * lightWidth * zRatio;
// the device-space radius sent to the blur shader must fit in 14.2 fixed point
if (srcSpaceSpotRadius*scaleFactor > MAX_BLUR_RADIUS) {
srcSpaceSpotRadius = MAX_BLUR_RADIUS/scaleFactor;
}
SkRRect spotRRect;
if (isOval) {
spotRRect = SkRRect::MakeOval(casterRect);
} else if (isRect) {
spotRRect = SkRRect::MakeRectXY(casterRect, minRadius, minRadius);
} else {
spotRRect = SkRRect::MakeRectXY(casterRect, casterCornerRadius, casterCornerRadius);
}
SkRRect spotShadowRRect;
// Compute the scale and translation for the spot shadow.
const SkScalar scale = lightPos.z / (lightPos.z - casterZValue);
spotRRect.transform(SkMatrix::MakeScale(scale, scale), &spotShadowRRect);
SkPoint center = SkPoint::Make(spotShadowRRect.rect().centerX(),
spotShadowRRect.rect().centerY());
SkMatrix ctmInverse;
if (!canvas->getTotalMatrix().invert(&ctmInverse)) {
ALOGW("Matrix is degenerate. Will not render spot shadow!");
return;
}
SkPoint lightPos2D = SkPoint::Make(lightPos.x, lightPos.y);
ctmInverse.mapPoints(&lightPos2D, 1);
const SkPoint spotOffset = SkPoint::Make(zRatio*(center.fX - lightPos2D.fX),
zRatio*(center.fY - lightPos2D.fY));
SkAutoCanvasRestore acr(canvas, true);
// We want to extend the stroked area in so that it meets up with the caster
// geometry. The stroked geometry will, by definition already be inset half the
// stroke width but we also have to account for the scaling.
// We also add 1/2 to cover up AA on the interior edge.
SkScalar scaleOffset = (scale - 1.0f) * SkTMax(SkTMax(SkTAbs(casterRect.fLeft),
SkTAbs(casterRect.fRight)), SkTMax(SkTAbs(casterRect.fTop),
SkTAbs(casterRect.fBottom)));
SkScalar insetAmount = spotOffset.length() - (0.5f * srcSpaceSpotRadius) +
scaleOffset + 0.5f;
// Compute area
SkScalar strokeWidth = srcSpaceSpotRadius + insetAmount;
SkScalar strokedArea = 2.0f*strokeWidth * (spotShadowRRect.width()
+ spotShadowRRect.height());
SkScalar filledArea = (spotShadowRRect.height() + srcSpaceSpotRadius)
* (spotShadowRRect.width() + srcSpaceSpotRadius);
SkPaint paint;
paint.setAntiAlias(true);
// If the area of the stroked geometry is larger than the fill geometry, just fill it.
if (strokedArea > filledArea || casterAlpha < 1.0f || insetAmount < 0.0f) {
paint.setStyle(SkPaint::kStrokeAndFill_Style);
paint.setStrokeWidth(srcSpaceSpotRadius);
} else {
// Since we can't have unequal strokes, inset the shadow rect so the inner
// and outer edges of the stroke will land where we want.
SkRect insetRect = spotShadowRRect.rect().makeInset(insetAmount/2.0f, insetAmount/2.0f);
SkScalar insetRad = SkTMax(spotShadowRRect.getSimpleRadii().fX - insetAmount/2.0f,
minRadius);
spotShadowRRect = SkRRect::MakeRectXY(insetRect, insetRad, insetRad);
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(strokeWidth);
}
// handle scale of radius and pad due to CTM
const SkScalar devSpaceSpotRadius = srcSpaceSpotRadius * scaleFactor;
SkASSERT(devSpaceSpotRadius <= MAX_BLUR_RADIUS);
const SkScalar devSpaceSpotPad = 0;
SkASSERT(devSpaceSpotPad < MAX_PAD);
// convert devSpaceSpotRadius to 14.2 fixed point and place in the R & G
// components convert devSpaceSpotPad to 6.2 fixed point and place in the B component
uint16_t iDevSpaceSpotRadius = (uint16_t)(4.0f * devSpaceSpotRadius);
paint.setColor(SkColorSetARGB((unsigned char) spotAlpha, iDevSpaceSpotRadius >> 8,
iDevSpaceSpotRadius & 0xff, (unsigned char)(4.0f * devSpaceSpotPad)));
paint.setShader(edgeShader);
canvas->translate(spotOffset.fX, spotOffset.fY);
canvas->drawRRect(spotShadowRRect, paint);
}
}
/**
* @param casterRect the rectangle bounds of the RRect casting the shadow
* @param casterCornerRadius the x&y radius for all the corners of the RRect casting the shadow
* @param ambientAlpha the maximum alpha value to use when drawing the ambient shadow
* @param spotAlpha the maximum alpha value to use when drawing the spot shadow
* @param casterZValue the Z value of the caster RRect
* @param scaleFactor the scale needed to map from src-space to device-space
* @param clipRR the oval or rect with which the drawn roundrect must be intersected
* @param canvas the destination for the shadow draws
*/
static void DrawRRectShadowsWithClip(const SkRect& casterRect, SkScalar casterCornerRadius,
SkScalar ambientAlpha, SkScalar spotAlpha, SkScalar casterZValue, SkScalar scaleFactor,
const SkRRect& clipRR, SkCanvas* canvas) {
SkASSERT(casterCornerRadius >= 0.0f);
const bool isOval = casterCornerRadius >= std::max(SkScalarHalf(casterRect.width()),
SkScalarHalf(casterRect.height()));
if (ambientAlpha > 0.0f) {
static const float kHeightFactor = 1.0f / 128.0f;
static const float kGeomFactor = 64.0f;
const SkScalar srcSpaceAmbientRadius = casterZValue * kHeightFactor * kGeomFactor;
const SkScalar devSpaceAmbientRadius = srcSpaceAmbientRadius * scaleFactor;
const float umbraAlpha = 1.0f / (1.0f + std::max(casterZValue * kHeightFactor, 0.0f));
const SkScalar ambientOffset = srcSpaceAmbientRadius * umbraAlpha;
const SkRect srcSpaceAmbientRect = casterRect.makeOutset(ambientOffset, ambientOffset);
SkRect devSpaceAmbientRect;
canvas->getTotalMatrix().mapRect(&devSpaceAmbientRect, srcSpaceAmbientRect);
SkRRect devSpaceAmbientRRect;
if (isOval) {
devSpaceAmbientRRect = SkRRect::MakeOval(devSpaceAmbientRect);
} else {
const SkScalar devSpaceCornerRadius = scaleFactor * (casterCornerRadius + ambientOffset);
devSpaceAmbientRRect = SkRRect::MakeRectXY(devSpaceAmbientRect, devSpaceCornerRadius,
devSpaceCornerRadius);
}
const SkRect srcSpaceAmbClipRect = clipRR.rect().makeOutset(ambientOffset, ambientOffset);
SkRect devSpaceAmbClipRect;
canvas->getTotalMatrix().mapRect(&devSpaceAmbClipRect, srcSpaceAmbClipRect);
SkRRect devSpaceAmbientClipRR;
if (clipRR.isOval()) {
devSpaceAmbientClipRR = SkRRect::MakeOval(devSpaceAmbClipRect);
} else {
SkASSERT(clipRR.isRect());
devSpaceAmbientClipRR = SkRRect::MakeRect(devSpaceAmbClipRect);
}
SkRect cover = srcSpaceAmbClipRect;
if (!cover.intersect(srcSpaceAmbientRect)) {
return;
}
SkPaint paint;
paint.setColor(SkColorSetARGB((unsigned char) ambientAlpha, 0, 0, 0));
paint.setMaskFilter(SkRRectsGaussianEdgeMaskFilter::Make(devSpaceAmbientRRect,
devSpaceAmbientClipRR, devSpaceAmbientRadius));
canvas->drawRect(cover, paint);
}
if (spotAlpha > 0.0f) {
const Vector3 lightPos = SkiaPipeline::getLightCenter();
float zRatio = casterZValue / (lightPos.z - casterZValue);
// clamp
if (zRatio < 0.0f) {
zRatio = 0.0f;
} else if (zRatio > 0.95f) {
zRatio = 0.95f;
}
const SkScalar lightWidth = SkiaPipeline::getLightRadius();
const SkScalar srcSpaceSpotRadius = 2.0f * lightWidth * zRatio;
const SkScalar devSpaceSpotRadius = srcSpaceSpotRadius * scaleFactor;
// Compute the scale and translation for the spot shadow.
const SkScalar scale = lightPos.z / (lightPos.z - casterZValue);
const SkMatrix spotMatrix = SkMatrix::MakeScale(scale, scale);
SkRect srcSpaceScaledRect = casterRect;
spotMatrix.mapRect(&srcSpaceScaledRect);
srcSpaceScaledRect.outset(SkScalarHalf(srcSpaceSpotRadius),
SkScalarHalf(srcSpaceSpotRadius));
SkRRect srcSpaceSpotRRect;
if (isOval) {
srcSpaceSpotRRect = SkRRect::MakeOval(srcSpaceScaledRect);
} else {
srcSpaceSpotRRect = SkRRect::MakeRectXY(srcSpaceScaledRect, casterCornerRadius * scale,
casterCornerRadius * scale);
}
SkPoint center = SkPoint::Make(srcSpaceSpotRRect.rect().centerX(),
srcSpaceSpotRRect.rect().centerY());
SkMatrix ctmInverse;
if (!canvas->getTotalMatrix().invert(&ctmInverse)) {
ALOGW("Matrix is degenerate. Will not render spot shadow!");
return;
}
SkPoint lightPos2D = SkPoint::Make(lightPos.x, lightPos.y);
ctmInverse.mapPoints(&lightPos2D, 1);
const SkPoint spotOffset = SkPoint::Make(zRatio*(center.fX - lightPos2D.fX),
zRatio*(center.fY - lightPos2D.fY));
SkAutoCanvasRestore acr(canvas, true);
canvas->translate(spotOffset.fX, spotOffset.fY);
SkRect devSpaceScaledRect;
canvas->getTotalMatrix().mapRect(&devSpaceScaledRect, srcSpaceScaledRect);
SkRRect devSpaceSpotRRect;
if (isOval) {
devSpaceSpotRRect = SkRRect::MakeOval(devSpaceScaledRect);
} else {
const SkScalar devSpaceScaledCornerRadius = casterCornerRadius * scale * scaleFactor;
devSpaceSpotRRect = SkRRect::MakeRectXY(devSpaceScaledRect, devSpaceScaledCornerRadius,
devSpaceScaledCornerRadius);
}
SkPaint paint;
paint.setColor(SkColorSetARGB((unsigned char) spotAlpha, 0, 0, 0));
SkRect srcSpaceScaledClipRect = clipRR.rect();
spotMatrix.mapRect(&srcSpaceScaledClipRect);
srcSpaceScaledClipRect.outset(SkScalarHalf(srcSpaceSpotRadius),
SkScalarHalf(srcSpaceSpotRadius));
SkRect devSpaceScaledClipRect;
canvas->getTotalMatrix().mapRect(&devSpaceScaledClipRect, srcSpaceScaledClipRect);
SkRRect devSpaceSpotClipRR;
if (clipRR.isOval()) {
devSpaceSpotClipRR = SkRRect::MakeOval(devSpaceScaledClipRect);
} else {
SkASSERT(clipRR.isRect());
devSpaceSpotClipRR = SkRRect::MakeRect(devSpaceScaledClipRect);
}
paint.setMaskFilter(SkRRectsGaussianEdgeMaskFilter::Make(devSpaceSpotRRect,
devSpaceSpotClipRR, devSpaceSpotRadius));
SkRect cover = srcSpaceScaledClipRect;
if (!cover.intersect(srcSpaceSpotRRect.rect())) {
return;
}
canvas->drawRect(cover, paint);
}
}
/**
* @param casterRect the rectangle bounds of the RRect casting the shadow
* @param casterCornerRadius the x&y radius for all the corners of the RRect casting the shadow
* @param casterClipRect a rectangular clip that must be intersected with the
* shadow-casting RRect prior to casting the shadow
* @param revealClip a circular clip that must be interested with the castClipRect
* and the shadow-casting rect prior to casting the shadow
* @param ambientAlpha the maximum alpha value to use when drawing the ambient shadow
* @param spotAlpha the maximum alpha value to use when drawing the spot shadow
* @param casterAlpha the alpha value of the RRect casting the shadow (0.0-1.0 range)
* @param casterZValue the Z value of the caster RRect
* @param canvas the destination for the shadow draws
*
* We have special cases for 4 round rect shadow draws:
* 1) a RRect clipped by a reveal animation
* 2) a RRect clipped by a rectangle
* 3) an unclipped RRect with non-uniform scale
* 4) an unclipped RRect with uniform scale
* 1,2 and 4 require that the scale is uniform.
* 1 and 2 require that rects stay rects.
*/
static bool DrawShadowsAsRRects(const SkRect& casterRect, SkScalar casterCornerRadius,
const SkRect& casterClipRect, const RevealClip& revealClip, SkScalar ambientAlpha,
SkScalar spotAlpha, SkScalar casterAlpha, SkScalar casterZValue, SkCanvas* canvas) {
SkScalar scaleFactors[2];
if (!canvas->getTotalMatrix().getMinMaxScales(scaleFactors)) {
ALOGW("Matrix is degenerate. Will not render shadow!");
return false;
}
// The casterClipRect will be empty when bounds clipping is disabled
bool casterIsClippedByRect = !casterClipRect.isEmpty();
bool uniformScale = scaleFactors[0] == scaleFactors[1];
if (revealClip.willClip()) {
if (casterIsClippedByRect || !uniformScale || !canvas->getTotalMatrix().rectStaysRect()) {
return false; // Fall back to the slow path since PathOps are required
}
const float revealRadius = revealClip.getRadius();
SkRect revealClipRect = SkRect::MakeLTRB(revealClip.getX()-revealRadius,
revealClip.getY()-revealRadius, revealClip.getX()+revealRadius,
revealClip.getY()+revealRadius);
SkRRect revealClipRR = SkRRect::MakeOval(revealClipRect);
DrawRRectShadowsWithClip(casterRect, casterCornerRadius, ambientAlpha, spotAlpha,
casterZValue, scaleFactors[0], revealClipRR, canvas);
return true;
}
if (casterIsClippedByRect) {
if (!uniformScale || !canvas->getTotalMatrix().rectStaysRect()) {
return false; // Fall back to the slow path since PathOps are required
}
SkRRect casterClipRR = SkRRect::MakeRect(casterClipRect);
DrawRRectShadowsWithClip(casterRect, casterCornerRadius, ambientAlpha, spotAlpha,
casterZValue, scaleFactors[0], casterClipRR, canvas);
return true;
}
// The fast path needs uniform scale
if (!uniformScale) {
SkRRect casterRR = SkRRect::MakeRectXY(casterRect, casterCornerRadius, casterCornerRadius);
DrawAmbientShadowGeneral(canvas, casterRR, casterZValue, ambientAlpha,
[&](const SkRRect& rrect, const SkPaint& paint) {
canvas->drawRRect(rrect, paint);
});
DrawSpotShadowGeneral(canvas, casterRR, casterZValue, spotAlpha,
[&](const SkRRect& rrect, const SkPaint& paint) {
canvas->drawRRect(rrect, paint);
});
return true;
}
DrawRRectShadows(casterRect, casterCornerRadius, ambientAlpha, spotAlpha, casterAlpha,
casterZValue, scaleFactors[0], canvas);
return true;
}
// copied from FrameBuilder::deferShadow
void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable* caster) {
const RenderProperties& casterProperties = caster->getNodeProperties();
@@ -626,8 +135,8 @@ void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable*
return;
}
float ambientAlpha = SkiaPipeline::getAmbientShadowAlpha()*casterAlpha;
float spotAlpha = SkiaPipeline::getSpotShadowAlpha()*casterAlpha;
float ambientAlpha = (SkiaPipeline::getAmbientShadowAlpha()/255.f)*casterAlpha;
float spotAlpha = (SkiaPipeline::getSpotShadowAlpha()/255.f)*casterAlpha;
const float casterZValue = casterProperties.getZ();
const RevealClip& revealClip = casterProperties.getRevealClip();
@@ -659,19 +168,7 @@ void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable*
hwuiMatrix.copyTo(shadowMatrix);
canvas->concat(shadowMatrix);
const Outline& casterOutline = casterProperties.getOutline();
Rect possibleRect;
float radius;
if (casterOutline.getAsRoundRect(&possibleRect, &radius)) {
if (DrawShadowsAsRRects(possibleRect.toSkRect(), radius, casterClipRect, revealClip,
ambientAlpha, spotAlpha, casterAlpha, casterZValue, canvas)) {
return;
}
}
// Hard cases and calls to general shadow code
const SkPath* casterOutlinePath = casterProperties.getOutline().getPath();
// holds temporary SkPath to store the result of intersections
SkPath tmpPath;
const SkPath* casterPath = casterOutlinePath;
@@ -691,16 +188,11 @@ void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable*
Op(*casterPath, clipBoundsPath, kIntersect_SkPathOp, &tmpPath);
casterPath = &tmpPath;
}
DrawAmbientShadowGeneral(canvas, *casterPath, casterZValue, ambientAlpha,
[&](const SkPath& path, const SkPaint& paint) {
canvas->drawPath(path, paint);
});
DrawSpotShadowGeneral(canvas, *casterPath, casterZValue, spotAlpha,
[&](const SkPath& path, const SkPaint& paint) {
canvas->drawPath(path, paint);
});
const Vector3 lightPos = SkiaPipeline::getLightCenter();
SkPoint3 skiaLightPos = SkPoint3::Make(lightPos.x, lightPos.y, lightPos.z);
SkShadowUtils::DrawShadow(canvas, *casterPath, casterZValue, skiaLightPos,
SkiaPipeline::getLightRadius(), ambientAlpha, spotAlpha, SK_ColorBLACK,
casterAlpha < 1.0f ? SkShadowFlags::kTransparentOccluder_ShadowFlag : 0);
}
}; // namespace skiapipeline