Skip to content

Commit

Permalink
[Shape] Fixed stroke path calculation for custom interpolation start …
Browse files Browse the repository at this point in the history
…shape.

PiperOrigin-RevId: 629942322
  • Loading branch information
pekingme authored and leticiarossi committed May 2, 2024
1 parent d44a06c commit e4fbb84
Showing 1 changed file with 57 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ public class MaterialShapeDrawable extends Drawable implements TintAwareDrawable
public @interface CompatibilityShadowMode {}

private static final Paint clearPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

static {
clearPaint.setColor(Color.WHITE);
clearPaint.setXfermode(new PorterDuffXfermode(Mode.DST_OUT));
Expand All @@ -134,6 +135,7 @@ public class MaterialShapeDrawable extends Drawable implements TintAwareDrawable
private final Region transparentRegion = new Region();
private final Region scratchRegion = new Region();
private ShapeAppearanceModel strokeShapeAppearance;
private ShapeAppearanceModel strokeInterpolationStartShapeAppearance;

private final Paint fillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint strokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
Expand Down Expand Up @@ -226,9 +228,7 @@ public MaterialShapeDrawable(@NonNull ShapeAppearanceModel shapeAppearanceModel)
this(new MaterialShapeDrawableState(shapeAppearanceModel, null));
}

/**
* @hide
*/
/** @hide */
@RestrictTo(LIBRARY_GROUP)
protected MaterialShapeDrawable(@NonNull MaterialShapeDrawableState drawableState) {
this.drawableState = drawableState;
Expand Down Expand Up @@ -301,7 +301,7 @@ public ShapeAppearanceModel getShapeAppearanceModel() {
* Set the shape appearance when interpolation is 0.
*
* @param startShape the ShapeAppearanceModel for the shape when interpolation is 0. The edge
* treatments within it are ignored.
* treatments within it are ignored.
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
Expand Down Expand Up @@ -492,9 +492,7 @@ public void setStrokeWidth(float strokeWidth) {
invalidateSelf();
}

/**
* Get the tint color factoring in any other runtime modifications such as elevation overlays.
*/
/** Get the tint color factoring in any other runtime modifications such as elevation overlays. */
@ColorInt
public int getResolvedTintColor() {
return resolvedTintColor;
Expand Down Expand Up @@ -1093,7 +1091,13 @@ private void maybeDrawCompatShadow(@NonNull Canvas canvas) {
@RestrictTo(LIBRARY_GROUP)
protected void drawShape(
@NonNull Canvas canvas, @NonNull Paint paint, @NonNull Path path, @NonNull RectF bounds) {
drawShape(canvas, paint, path, drawableState.shapeAppearanceModel, bounds);
drawShape(
canvas,
paint,
path,
drawableState.shapeAppearanceModel,
drawableState.interpolationStartShapeAppearanceModel,
bounds);
}

/** Draw the path or try to draw a round rect if possible. */
Expand All @@ -1102,11 +1106,12 @@ private void drawShape(
@NonNull Paint paint,
@NonNull Path path,
@NonNull ShapeAppearanceModel shapeAppearanceModel,
@NonNull ShapeAppearanceModel interpolationStartShapeAppearanceModel,
@NonNull RectF bounds) {
if (shapeAppearanceModel.isRoundRect(bounds)) {
float endRadius = shapeAppearanceModel.getTopLeftCornerSize().getCornerSize(bounds);
shapeAppearanceModel = drawableState.interpolationStartShapeAppearanceModel;
float startRadius = shapeAppearanceModel.getTopLeftCornerSize().getCornerSize(bounds);
float startRadius =
interpolationStartShapeAppearanceModel.getTopLeftCornerSize().getCornerSize(bounds);
float radius = lerp(startRadius, endRadius, drawableState.interpolation);
canvas.drawRoundRect(bounds, radius, radius, paint);
} else {
Expand All @@ -1115,7 +1120,13 @@ private void drawShape(
}

private void drawFillShape(@NonNull Canvas canvas) {
drawShape(canvas, fillPaint, path, drawableState.shapeAppearanceModel, getBoundsAsRectF());
drawShape(
canvas,
fillPaint,
path,
drawableState.shapeAppearanceModel,
drawableState.interpolationStartShapeAppearanceModel,
getBoundsAsRectF());
}

/**
Expand All @@ -1129,7 +1140,12 @@ private void drawFillShape(@NonNull Canvas canvas) {
@RestrictTo(LIBRARY_GROUP)
protected void drawStrokeShape(@NonNull Canvas canvas) {
drawShape(
canvas, strokePaint, pathInsetByStroke, strokeShapeAppearance, getBoundsInsetByStroke());
canvas,
strokePaint,
pathInsetByStroke,
strokeShapeAppearance,
strokeInterpolationStartShapeAppearance,
getBoundsInsetByStroke());
}

private void prepareCanvasForShadow(@NonNull Canvas canvas) {
Expand Down Expand Up @@ -1202,7 +1218,9 @@ public int getShadowOffsetY() {
* Math.cos(Math.toRadians(drawableState.shadowCompatRotation)));
}

/** @deprecated see {@link ShapeAppearancePathProvider} */
/**
* @deprecated see {@link ShapeAppearancePathProvider}
*/
@Deprecated
public void getPathForSize(int width, int height, @NonNull Path path) {
calculatePathForSize(new RectF(0, 0, width, height), path);
Expand All @@ -1226,6 +1244,18 @@ protected final void calculatePathForSize(@NonNull RectF bounds, @NonNull Path p

/** Calculates the path that can be used to draw the stroke entirely inside the shape */
private void calculateStrokePath() {
updateStrokeShapeAppearanceModels();

pathProvider.calculatePath(
strokeShapeAppearance,
strokeInterpolationStartShapeAppearance,
drawableState.interpolation,
getBoundsInsetByStroke(),
null,
pathInsetByStroke);
}

private void updateStrokeShapeAppearanceModels() {
// Adjust corner radius in order to draw the stroke so that the corners of the background are
// drawn on top of the edges.
final float strokeInsetLength = -getStrokeInsetLength();
Expand All @@ -1244,13 +1274,20 @@ public CornerSize apply(@NonNull CornerSize cornerSize) {
}
});

pathProvider.calculatePath(
strokeShapeAppearance,
drawableState.interpolationStartShapeAppearanceModel,
drawableState.interpolation,
getBoundsInsetByStroke(),
null,
pathInsetByStroke);
strokeInterpolationStartShapeAppearance =
getInterpolationStartShapeAppearanceModel()
.withTransformedCornerSizes(
new CornerSizeUnaryOperator() {
@NonNull
@Override
public CornerSize apply(@NonNull CornerSize cornerSize) {
// Don't adjust for relative corners they will change by themselves when the
// bounds change.
return cornerSize instanceof RelativeCornerSize
? cornerSize
: new AdjustedCornerSize(strokeInsetLength, cornerSize);
}
});
}

@TargetApi(VERSION_CODES.LOLLIPOP)
Expand Down

0 comments on commit e4fbb84

Please sign in to comment.