Skip to content

Commit

Permalink
Add granular rounding for corners.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 264495417
  • Loading branch information
sjudd authored and glide-copybara-robot committed Aug 20, 2019
1 parent 01addba commit f36a9fa
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.bumptech.glide.load.resource.bitmap;

import android.graphics.Bitmap;
import androidx.annotation.NonNull;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.util.Util;
import java.nio.ByteBuffer;
import java.security.MessageDigest;

/** A {@link BitmapTransformation} which has a different raddius for each corner of a bitmap. */
public final class GranularRoundedCorners extends BitmapTransformation {
private static final String ID = "com.bumptech.glide.load.resource.bitmap.GranularRoundedCorners";
private static final byte[] ID_BYTES = ID.getBytes(CHARSET);

private final float topLeft;
private final float topRight;
private final float bottomRight;
private final float bottomLeft;

/** Provide the radii to round the corners of the bitmap. */
public GranularRoundedCorners(
float topLeft, float topRight, float bottomRight, float bottomLeft) {
this.topLeft = topLeft;
this.topRight = topRight;
this.bottomRight = bottomRight;
this.bottomLeft = bottomLeft;
}

@Override
protected Bitmap transform(
@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
return TransformationUtils.roundedCorners(
pool, toTransform, topLeft, topRight, bottomRight, bottomLeft);
}

@Override
public boolean equals(Object o) {
if (o instanceof GranularRoundedCorners) {
GranularRoundedCorners other = (GranularRoundedCorners) o;
return topLeft == other.topLeft
&& topRight == other.topRight
&& bottomRight == other.bottomRight
&& bottomLeft == other.bottomLeft;
}
return false;
}

@Override
public int hashCode() {
int hashCode = Util.hashCode(ID.hashCode(), Util.hashCode(topLeft));
hashCode = Util.hashCode(topRight, hashCode);
hashCode = Util.hashCode(bottomRight, hashCode);
return Util.hashCode(bottomLeft, hashCode);
}

@Override
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
messageDigest.update(ID_BYTES);

byte[] radiusData =
ByteBuffer.allocate(16)
.putFloat(topLeft)
.putFloat(topRight)
.putFloat(bottomRight)
.putFloat(bottomLeft)
.array();
messageDigest.update(radiusData);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
Expand Down Expand Up @@ -472,9 +473,71 @@ public static Bitmap roundedCorners(
* @throws IllegalArgumentException if roundingRadius, width or height is 0 or less.
*/
public static Bitmap roundedCorners(
@NonNull BitmapPool pool, @NonNull Bitmap inBitmap, int roundingRadius) {
@NonNull BitmapPool pool, @NonNull Bitmap inBitmap, final int roundingRadius) {
Preconditions.checkArgument(roundingRadius > 0, "roundingRadius must be greater than 0.");

return roundedCorners(
pool,
inBitmap,
new DrawRoundedCornerFn() {
@Override
public void drawRoundedCorners(Canvas canvas, Paint paint, RectF rect) {
canvas.drawRoundRect(rect, roundingRadius, roundingRadius, paint);
}
});
}

/**
* Creates a bitmap from a source bitmap and rounds the corners, applying a potentially different
* [X, Y] radius to each corner.
*
* <p>This method does <em>NOT</em> resize the given {@link Bitmap}, it only rounds it's corners.
* To both resize and round the corners of an image, consider {@link
* com.bumptech.glide.request.RequestOptions#transform(Transformation[])} and/or {@link
* com.bumptech.glide.load.MultiTransformation}.
*
* @param inBitmap the source bitmap to use as a basis for the created bitmap.
* @param topLeft top-left radius
* @param topRight top-right radius
* @param bottomRight bottom-right radius
* @param bottomLeft bottom-left radius
* @return a {@link Bitmap} similar to inBitmap but with rounded corners.
*/
public static Bitmap roundedCorners(
@NonNull BitmapPool pool,
@NonNull Bitmap inBitmap,
final float topLeft,
final float topRight,
final float bottomRight,
final float bottomLeft) {
return roundedCorners(
pool,
inBitmap,
new DrawRoundedCornerFn() {
@Override
public void drawRoundedCorners(Canvas canvas, Paint paint, RectF rect) {
Path path = new Path();
path.addRoundRect(
rect,
new float[] {
topLeft,
topLeft,
topRight,
topRight,
bottomRight,
bottomRight,
bottomLeft,
bottomLeft
},
Path.Direction.CW);
canvas.drawPath(path, paint);
}
});
}

private static Bitmap roundedCorners(
@NonNull BitmapPool pool, @NonNull Bitmap inBitmap, DrawRoundedCornerFn drawRoundedCornerFn) {

// Alpha is required for this transformation.
Bitmap.Config safeConfig = getAlphaSafeConfig(inBitmap);
Bitmap toTransform = getAlphaSafeBitmap(pool, inBitmap);
Expand All @@ -492,7 +555,7 @@ public static Bitmap roundedCorners(
try {
Canvas canvas = new Canvas(result);
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
canvas.drawRoundRect(rect, roundingRadius, roundingRadius, paint);
drawRoundedCornerFn.drawRoundedCorners(canvas, paint, rect);
clear(canvas);
} finally {
BITMAP_DRAWABLE_LOCK.unlock();
Expand Down Expand Up @@ -559,6 +622,12 @@ static void initializeMatrixForRotation(int exifOrientation, Matrix matrix) {
}
}

/** Convenience function for drawing a rounded bitmap. */
private interface DrawRoundedCornerFn {

void drawRoundedCorners(Canvas canvas, Paint paint, RectF rect);
}

private static final class NoLock implements Lock {

@Synthetic
Expand Down

0 comments on commit f36a9fa

Please sign in to comment.