PorterDuff and Path

2.4k Views Asked by At

In my project I have a bitmap filling the entire screen. On this bitmap i draw a path with

android.graphics.Canvas.drawPath(Path path, Paint paint)

the paint is set in order to stroke and fill the content of the path. What I would achieve is to erase the portion of the bitamp that intersect the path. I have managed to obtain the same behavior using on another bitmmap instead of the path, and using the porter duff rules. Is there any chance to do the same thing with the path?

    mPaintPath.setARGB(100, 100, 100, 100);// (100, 100, 100, 100)
    mPaintPath.setStyle(Paint.Style.FILL_AND_STROKE);
    mPaintPath.setAntiAlias(true);
    mPath.moveTo(x0, y0));
    mPath.lineTo(x1, y1);
    mPath.lineTo(x2, y2);
    mPath.lineTo(x3, y3);
    mPath.lineTo(x0, y0);
    mPath.close();
    c.drawPath(mPath, mPaintPath);
1

There are 1 best solutions below

3
On BEST ANSWER

Sure, just draw the path to an offscreen buffer so you can use it as a mask when you draw the bitmap, something like this:

// Create an offscreen buffer
int layer = c.saveLayer(0, 0, width, height, null,
        Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG);

// Setup a paint object for the path
mPaintPath.setARGB(255, 255, 255, 255);
mPaintPath.setStyle(Paint.Style.FILL_AND_STROKE);
mPaintPath.setAntiAlias(true);

// Draw the path onto the offscreen buffer
mPath.moveTo(x0, y0);
mPath.lineTo(x1, y1);
mPath.lineTo(x2, y2);
mPath.lineTo(x3, y3);
mPath.lineTo(x0, y0);
mPath.close();
c.drawPath(mPath, mPaintPath);

// Draw a bitmap on the offscreen buffer and use the path that's already
// there as a mask
mBitmapPaint.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT));
c.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

// Composit the offscreen buffer (a masked bitmap) to the canvas
c.restoreToCount(layer);

If you can withstand aliasing, there's an easier way: just setup a clip path (note the use of Region.Op.DIFFERENCE which causes the insides of the path to be clipped away rather than clipping everything outside of the path):

// Setup a clip path
mPath.moveTo(x0, y0);
mPath.lineTo(x1, y1);
mPath.lineTo(x2, y2);
mPath.lineTo(x3, y3);
mPath.lineTo(x0, y0);
mPath.close();
c.clipPath(mPath, Op.DIFFERENCE);

// Draw the bitmap using the path clip
c.drawBitmap(mBitmap, 0, 0, mBitmapPaint);