I've been trying to figure this out all night, but answers found on Google relate to very specific problems regarding Android's canvas and I haven't found any 101 explanations on this topic. Even Android documentation uses bitmaps instead of drawing shapes.
Specific problem:
I need to draw an oval and a path on canvas. And according to documentation colour source out with one colour, destination out another colour and overlapping area, either source in or destination in, a third colour. I'm trying to do all this in an offscreen canvas. but problems arise with some of the steps above and get worse when trying to combine them in any way.
Code -
Bitmap bmp = Bitmap.CreateBitmap (720, 720, Bitmap.Config.Argb8888); Canvas c = new Canvas (bmp); Paint paint = new Paint (); paint.SetARGB (255, 255, 0, 0); c.DrawOval (200, 200, 520, 520, paint); //assumed destination paint.SetARGB (255, 0, 0, 255); paint.SetXfermode (new PorterDuffXfermode (PorterDuff.Mode.*)); //replace mode here paint.SetStyle (Paint.Style.Fill); Path path = new Path (); path.MoveTo (c.Width / 2f, c.Height / 2f); foreach (var m in measurements) { //calculations float x = xCalculatedValue float y = yCalculatedValue path.LineTo (x, y); } path.LineTo (c.Width / 2f, c.Height / 2f); c.DrawPath (path, paint); //assumed sourceSource out -
This instead draws what XOR is supposed to draw.
- Destination out -
This works as expected.
- Source in -
This draws what source atop should.
- Destination in -
This draws what destination should.
More general question:
What do source and destination refer to in this context? Intuitively I would assume that destination is the current state of the canvas bitmap and source is the matrix added by canvas.Draw* and Paint PortedDuff.Mode. But that doesn't seem to be the case.
EDIT: This is basically the effect I'm after, where the "star" is a dynamic path. Coloured three different colours depending on overlap.
EDIT 2: York Shen did a great job answering the actual question. But for anyone wanting to get a similar effect here's the final code.
Bitmap DrawGraphBitmapOffscreen ()
{
Bitmap bmp = Bitmap.CreateBitmap (720, 720, Bitmap.Config.Argb8888);
Canvas c = new Canvas (bmp);
// Replace with calculated path
Path path = new Path ();
path.MoveTo (c.Width / 2f, c.Height / 2f);
path.LineTo (263, 288);
path.LineTo (236, 202);
path.LineTo (312, 249);
path.LineTo (331, 162);
path.LineTo (374, 240);
path.LineTo (434, 174);
path.LineTo (431, 263);
path.LineTo (517, 236);
path.LineTo (470, 312);
path.LineTo (557, 331);
path.LineTo (479, 374);
path.LineTo (545, 434);
path.LineTo (456, 431);
path.LineTo (483, 517);
path.LineTo (407, 470);
path.LineTo (388, 557);
path.LineTo (345, 479);
path.LineTo (285, 545);
path.LineTo (288, 456);
path.LineTo (202, 483);
path.LineTo (249, 407);
path.LineTo (162, 388);
path.LineTo (240, 345);
path.LineTo (174, 285);
path.LineTo (263, 288);
path.Close ();
Paint paint = new Paint ();
paint.SetARGB (255, 255, 0, 0);
paint.SetStyle (Paint.Style.Fill);
c.DrawPath (path, paint);
paint.SetARGB (255, 0, 0, 255);
paint.SetXfermode (new PorterDuffXfermode (PorterDuff.Mode.SrcIn));
c.DrawOval (200, 200, 520, 520, paint);
paint.SetARGB (255, 255, 255, 255);
paint.SetXfermode (new PorterDuffXfermode (PorterDuff.Mode.DstOver));
c.DrawOval (200, 200, 520, 520, paint);
return bmp;
}

