Skip to content

Commit bbd1292

Browse files
pekingmedsn5ft
authored andcommitted
[Shape] Optimized path calculation in MaterialShapeDrawable.
Added a check for `shouldCalculatePath()` before recalculating the fill and stroke paths during drawing. This prevents unnecessary path calculations when the shape is not visible or doesn't need path updates. PiperOrigin-RevId: 814298357
1 parent 9366a84 commit bbd1292

File tree

1 file changed

+31
-10
lines changed

1 file changed

+31
-10
lines changed

lib/java/com/google/android/material/shape/MaterialShapeDrawable.java

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,11 @@ private void updateZ() {
883883
drawableState.shadowCompatOffset = (int) Math.ceil(z * SHADOW_OFFSET_MULTIPLIER);
884884
// Recalculate fillPaint tint filter based on z, elevationOverlayProvider, etc.
885885
updateTintFilter();
886-
invalidateSelfIgnoreShape();
886+
if (shouldCalculatePath()) {
887+
invalidateSelf();
888+
} else {
889+
invalidateSelfIgnoreShape();
890+
}
887891
}
888892

889893
/**
@@ -1124,17 +1128,24 @@ public void draw(@NonNull Canvas canvas) {
11241128
final int prevStrokeAlpha = strokePaint.getAlpha();
11251129
strokePaint.setAlpha(modulateAlpha(prevStrokeAlpha, drawableState.alpha));
11261130

1131+
boolean shouldCalculatePathFromShapeAppearanceModel = shouldCalculatePath();
1132+
11271133
if (hasFill()) {
11281134
if (pathDirty) {
1129-
calculatePath(getBoundsAsRectF(), path);
1135+
if (shouldCalculatePathFromShapeAppearanceModel) {
1136+
calculatePath(getBoundsAsRectF(), path);
1137+
}
11301138
pathDirty = false;
11311139
}
11321140
maybeDrawCompatShadow(canvas);
11331141
drawFillShape(canvas);
11341142
}
11351143
if (hasStroke()) {
1136-
if(strokePathDirty){
1137-
calculateStrokePath();
1144+
if (strokePathDirty) {
1145+
updateStrokeShapeAppearanceModels();
1146+
if (shouldCalculatePathFromShapeAppearanceModel) {
1147+
calculateStrokePath();
1148+
}
11381149
strokePathDirty = false;
11391150
}
11401151
drawStrokeShape(canvas);
@@ -1144,6 +1155,10 @@ public void draw(@NonNull Canvas canvas) {
11441155
strokePaint.setAlpha(prevStrokeAlpha);
11451156
}
11461157

1158+
private boolean shouldCalculatePath() {
1159+
return hasCompatShadow() || !isRoundRect();
1160+
}
1161+
11471162
private void maybeDrawCompatShadow(@NonNull Canvas canvas) {
11481163
if (!hasCompatShadow()) {
11491164
return;
@@ -1157,14 +1172,21 @@ private void maybeDrawCompatShadow(@NonNull Canvas canvas) {
11571172
return;
11581173
}
11591174

1175+
Rect drawableBounds = getBounds();
11601176
// The extra height is the amount that the path draws outside of the bounds of the shape. This
11611177
// happens for some shapes like TriangleEdgeTreatment when it draws a triangle outside.
1162-
int pathExtraWidth = (int) (pathBounds.width() - getBounds().width());
1163-
int pathExtraHeight = (int) (pathBounds.height() - getBounds().height());
1178+
int pathExtraWidth = (int) (pathBounds.width() - drawableBounds.width());
1179+
int pathExtraHeight = (int) (pathBounds.height() - drawableBounds.height());
11641180

11651181
if (pathExtraWidth < 0 || pathExtraHeight < 0) {
11661182
throw new IllegalStateException(
1167-
"Invalid shadow bounds. Check that the treatments result in a valid path.");
1183+
"Invalid shadow bounds. Check that the treatments result in a valid path."
1184+
+ " extra width: "
1185+
+ pathExtraWidth
1186+
+ " extra height: "
1187+
+ pathExtraHeight
1188+
+ " path bounds: "
1189+
+ pathBounds);
11681190
}
11691191

11701192
// Drawing the shadow in a bitmap lets us use the clear paint rather than using clipPath to
@@ -1178,8 +1200,8 @@ private void maybeDrawCompatShadow(@NonNull Canvas canvas) {
11781200

11791201
// Top Left of shadow (left - shadowCompatRadius, top - shadowCompatRadius) should be drawn at
11801202
// (0, 0) on shadowCanvas. Offset is handled by prepareCanvasForShadow and drawCompatShadow.
1181-
float shadowLeft = getBounds().left - drawableState.shadowCompatRadius - pathExtraWidth;
1182-
float shadowTop = getBounds().top - drawableState.shadowCompatRadius - pathExtraHeight;
1203+
float shadowLeft = drawableBounds.left - drawableState.shadowCompatRadius - pathExtraWidth;
1204+
float shadowTop = drawableBounds.top - drawableState.shadowCompatRadius - pathExtraHeight;
11831205
shadowCanvas.translate(-shadowLeft, -shadowTop);
11841206
drawCompatShadow(shadowCanvas);
11851207
canvas.drawBitmap(shadowLayer, shadowLeft, shadowTop, null);
@@ -1374,7 +1396,6 @@ protected final void calculatePathForSize(@NonNull RectF bounds, @NonNull Path p
13741396

13751397
/** Calculates the path that can be used to draw the stroke entirely inside the shape */
13761398
private void calculateStrokePath() {
1377-
updateStrokeShapeAppearanceModels();
13781399
pathProvider.calculatePath(
13791400
strokeShapeAppearanceModel,
13801401
springAnimatedStrokeCornerSizes,

0 commit comments

Comments
 (0)