android – Canvas.clipPath(Path) not clipping as expected-ThrowExceptions

Exception or error:

I’m trying to clip a canvas drawing operation to an arc-shaped wedge. However, I’m not getting the intended result after setting the clipping path to the canvas.

For illustration, here is what I’m doing:

enter image description here

path.reset();

//Move to point #1
path.moveTo(rect.centerX(), rect.centerY());

//Per the documentation, this will draw a connecting line from the current
//position to the starting position of the arc (at 0 degrees), add the arc
//and my current position now lies at #2.
path.arcTo(rect, 0, -30);

//This should then close the path, finishing back at the center point (#3)
path.close();

This works, and when I simply draw this path (canvas.drawPath(path, paint)) it draws the wedge as shown above. However, when I set this path as the canvas’s clipping path and draw into it:

//I've tried it with and without the Region.Op parameter
canvas.clipPath(path, Region.Op.REPLACE);
canvas.drawColor(Color.BLUE);

I get the following result instead (the wedge is left just to show reference):

enter image description here

So it instead seems to clip to the bounding rect of the Path, and not the Path itself. Any ideas what’s happening here?

EDIT Just as an update, I’ve found a much more efficient way of doing this that allows for hardware acceleration. First, draw the entire image (that you’d be clipping) into an offscreen bitmap. Make a BitmapShader using this Bitmap, set that shader to a Paint, then draw the wedge path using that Paint object:

drawMyBitmap(bitmap);
Shader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setShader(shader);

@Override
public void onDraw(Canvas canvas) {
    canvas.drawArc(rect,         //The rectangle bounding the circle
                   startAngle,   //The angle (CW from 3 o'clock) to start
                   sweepAngle,   //The angle (CW from 3 o'clock) of the arc
                   true,         //Boolean of whether to draw a filled arc (wedge)
                   paint         //The paint with the shader attached
    );
}
How to solve:

Are you using HC or above or otherwise using hardware acceleration?

If so, clipPath is unsupported and problematic.

developer.android.com/guide/topics/graphics/hardware-accel.html.

###

OP’s question is specifically about using a clipping region and has been answered by @Simon. Bear in mind, however, that there’s a more straightforward way of drawing a filled arc:

Create a Paint:

mPaint = new Paint();
mPaint.setColor(Color.BLUE);
mPaint.setStyle(Style.FILL);
mPaint.setAntiAlias(true);

When drawing, simply draw the path:

canvas.drawPath(path, mPaint);

Leave a Reply

Your email address will not be published. Required fields are marked *