I would like to have a better understanding of how the components of Android's (2D) Canvas drawing pipeline fit together.
For example, how do XferMode, Shader, MaskFilter and ColorFilter interact? The reference docs for these classes are pretty sparse and the docs for Canvas and Paint don't really add any useful explanation.
It's also not entirely clear to me how drawing operations that have intrinsic colors (eg: drawBitmap
, versus the "vector" primitives like drawRect
) fit into all of this -- do they always ignore the Paint
's color and use use their intrinsic color instead?
I was also surprised by the fact that one can do something like this:
Paint eraser = new Paint();
eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawOval(rectF, eraser);
This erases an oval. Before I noticed this my mental-model was that drawing to a canvas (conceptually) draws to a separate "layer" and then that layer is composed with the Canvas's Bitmap using the Paint's transfer mode. If it were as simple as that then the above code would erase the entire Bitmap (within the clipping region) as CLEAR always sets the color (and alpha) to 0 regardless of the source's alpha. So this implies that there's an additional sort of masking going on to constrain the erasing to an oval.
I did find the API demos but each demo works "in a vacuum" and doesn't show how the thing it focusses on (eg: XferModes) interacts with other stuff (eg: ColorFilters).
With enough time and effort I could empirically figure out how these pieces relate or go decipher the source, but I'm hoping that someone else has already worked this out, or better yet that there's some actual documentation of the pipeline/drawing-model that I missed.
This question was inspired by seeing the code in this answer to another SO question.
Update
While looking around for some documentation it occurred to me that since much the stuff I'm interested in here seems to be a pretty thin veneer on top of skia, maybe there's some skia documentation that would be helpful. The best thing I could find is the documentation for SkPaint
which says:
There are 6 types of effects that can be assigned to a paint:
- SkPathEffect - modifications to the geometry (path) before it generates an alpha mask (e.g. dashing)
- SkRasterizer - composing custom mask layers (e.g. shadows)
- SkMaskFilter - modifications to the alpha mask before it is colorized and drawn (e.g. blur, emboss)
- SkShader - e.g. gradients (linear, radial, sweep), bitmap patterns (clamp, repeat, mirror)
- SkColorFilter - modify the source color(s) before applying the xfermode (e.g. color matrix)
- SkXfermode - e.g. porter-duff transfermodes, blend modes
It isn't stated explicitly, but I'm guessing that the order of the effects here is the order they appear in the pipeline.