In my ImageView's onDraw
I am struggling to convert a Drawable object to a Bitmap (respecting scaling). I'm loading an SVG file as a PictureDrawable. Then I'm trying to apply rounded corners to the image with a BitmapShader. In order to do that I have to convert the Drawable to Bitmap. It basically works, but I'm not getting my head around the scaling procedure.
Bitmap bitmap = Bitmap.createBitmap(
picture.getIntrinsicWidth(),
picture.getIntrinsicHeight(),
Bitmap.Config.ARGB_8888
)
Canvas canvas = new Canvas( bitmap )
// Scaling the Canvas appears to work ...
canvas.concat( getImageMatrix() )
canvas.drawPicture(
picture.getPicture,
// ... however this will not fill the viewport, as the getWidth and getHeight
// values do not reflect the scaling
new RectF( 0, 0, canvas.getWidth(), canvas.getHeight() )
)
paint.setShader( new BitmapShader( bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP ) )
canvas.drawRoundRect(
new RectF( 0, 0, bitmap.getWidth(), bitmap.getHeight() ),
radius,
radius,
paint
)
Erroneous rendering example for centerCrop scaling:
Besides the problem described in the code comments above I am wondering whether it might be possible to mask the the Picture/SVG file with drawing operations such as clipPath instead of this heavy Bitmap conversion. But it'd have to be anti-aliased, of course.
The code was originally written in Scala and loosely translated to Java for SO, so please ignore any Syntax errors
With pskink's answer (Make Image view rounded (not the image)) to a similar question I came to the following solution, based on the saveLayer approach (with some minor modifications).
@Override
public void onDraw( Canvas canvas )
{
Paint paint1 = new Paint( Paint.ANTI_ALIAS_FLAG )
Paint paint2 = new Paint()
paint2.setXfermode( new PorterDuffXfermode( Mode.SRC_IN ) )
Drawable drawable = getDrawable()
RectF rectangle = new RectF()
rectangle.set( drawable.getBounds() )
getImageMatrix.mapRect( rectangle )
rectangle.offset( getPaddingLeft(), getPaddingTop() )
// Prevent radius being drawn out of canvas bounds
rectangle.intersect( new RectF( 0, 0, canvas.getWidth(), canvas.getHeight() ) )
int restore = canvas.saveLayer( rectangle, null, Canvas.ALL_SAVE_FLAG )
canvas.drawRoundRect( rectangle, radius.getValue(), radius.getValue(), paint1 )
canvas.saveLayer( rectangle, paint2, Canvas.ALL_SAVE_FLAG )
super.onDraw( canvas )
canvas.restoreToCount( restore )
}
The above code ignores object caching in class level and ignores NPE from getDrawable().