0

Is it possible to specify a Rect on a Canvas to ignore subsequent Canvas.drawXYZ() calls, whereas other parts of the Canvas is being rendered? It's like a reverse clip rectangle.

For example, I have a 100*100 canvas, there are already some stuff drawn onto it. But I would like to clip the top left 50*50 to not be drawn anything else. At this stage, subsequent calls should draw anywhere except the top left 50*50.

Some Noob Student
  • 14,186
  • 13
  • 65
  • 103

1 Answers1

3

There's a relatively simple answer to this, with added complexity if you require hardware acceleration.

Simple answer: Use the clipRect variant with the Op parameter set to DIFFERENCE. This will effectively add everything but the rectangle you specify to the clip:

canvas.clipRect(new Rect(0, 0, 50, 50), Op.DIFFERENCE);
// Now draw whatever you like.

However, Op.DIFFERENCE isn't supported if you've got hardware acceleration turned on, as will happen for your view by default when building for ICS. (Try the code above, built for Android 4+ in a non-hardware accelerated emulator, and on a real ICS device. You'll probably see that it works fine on the former, but not the latter.)

If hardware acceleration isn't important to you, you can just turn it off. But that's less than ideal.

Luckily, hardware acceleration or no hardware acceleration, clipRect does support Op.UNION to make a union of your new rectangle and the existing region. So in your case, you can treat the region you want to draw into as two separate rectangles added together, and add them both to the clipping area like this:

// Rectangle down right-hand side
canvas.clipRect(new Rect(50, 0, 100, 100));
// Rectangle across bottom. This overlaps with the 
// above, but that doesn't matter.
canvas.clipRect(new Rect(0, 50, 100, 100), Op.UNION);

...and that should work whether you're hardware-accelerated or not.

See the Android docs for exact details on what's not supported with hardware acceleration.

Community
  • 1
  • 1
Matt Gibson
  • 37,886
  • 9
  • 99
  • 128