Lau*_*ves 60 android skia android-canvas
我想更好地了解Android(2D)Canvas绘图管道的组件如何组合在一起.
例如,XferMode,Shader,MaskFilter和ColorFilter如何交互?这些类的参考文档非常稀疏,Canvas和Paint的文档并没有真正添加任何有用的解释.
我也不完全清楚具有内在颜色的绘图操作(例如:drawBitmap与"矢量"原语相比drawRect)是否适合所有这些 - 他们总是忽略Paint颜色并使用其内在颜色吗?
我也很惊讶,人们可以这样做:
Paint eraser = new Paint();
eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawOval(rectF, eraser);
Run Code Online (Sandbox Code Playgroud)
这抹去了椭圆形.在我注意到这一点之前,我的心理模型是绘制到画布(概念上)绘制到单独的"图层",然后使用Paint的传输模式使用Canvas的位图组合该图层.如果它那么简单那么上面的代码将擦除整个位图(在剪辑区域内),因为CLEAR 总是将颜色(和alpha)设置为0,而不管源的alpha是什么.所以这意味着还有一种额外的掩蔽来限制擦除到椭圆形.
我确实找到了API演示,但是每个演示都"在真空中"工作,并没有显示它关注的东西(例如:XferModes)如何与其他东西(例如:ColorFilters)交互.
有了足够的时间和精力,我可以凭经验弄清楚这些部分是如何相关或破译源的,但我希望其他人已经解决了这个问题,或者更好的是,有一些管道/绘图模型的实际文档,我错过了.
这个问题的灵感来自于在另一个SO问题的答案中看到代码.
在寻找一些文档的同时,我想到,由于我在这里感兴趣的东西似乎是一个非常薄的贴面,在skia之上,也许有一些skia文档会有所帮助.我能找到的最好的东西是文件SkPaint说:
可以为paint分配6种效果:
- SkPathEffect - 在生成alpha蒙版(例如,破折号)之前对几何(路径)的修改
- SkRasterizer - 组成自定义遮罩层(例如阴影)
- SkMaskFilter - 在对alpha蒙版进行着色和绘制之前对其进行修改(例如模糊,浮雕)
- SkShader - 例如渐变(线性,径向,扫描),位图图案(钳位,重复,镜像)
- SkColorFilter - 在应用xfermode之前修改源颜色(例如颜色矩阵)
- SkXfermode - 例如porter-duff transfermodes,混合模式
它没有明确说明,但我猜这里效果的顺序是它们在管道中出现的顺序.
Lau*_*ves 48
就像Romain Guy说的那样,"这个问题很难在StackOverflow上回答".没有任何完整的文档,完整的文档将包含在这里很大.
我最后通过源阅读并做了一堆实验.我沿途记笔记,最后把它们变成了一个文件,你可以在这里看到:
以及这个图:
http://xenomachina.com/android-canvas-pipeline.png
显然,这是"非官方的",所以正常的警告适用.
基于以上所述,以下是一些"子问题"的答案:
我也不完全清楚具有内在颜色的绘图操作(例如:
drawBitmap与"矢量"原语相比drawRect)是否适合所有这些 - 他们总是忽略Paint颜色并使用其内在颜色吗?
"源色"来自于Shader.在drawBitmap该Shader暂时被一取代BitmapShader,如果非ALPHA_8 Bitmap使用.在其他情况下,如果没有Shader指定a Shader只生成纯色Paint,则使用颜色.
我也很惊讶,人们可以这样做:
Run Code Online (Sandbox Code Playgroud)Paint eraser = new Paint(); eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); canvas.drawOval(rectF, eraser);这抹去了椭圆形.在我注意到这一点之前,我的心理模型是绘制到画布(概念上)绘制到单独的"图层",然后使用Paint的传输模式使用Canvas的位图组合该图层.如果它那么简单那么上面的代码将擦除整个位图(在剪辑区域内),因为CLEAR 总是将颜色(和alpha)设置为0,而不管源的alpha是什么.所以这意味着还有一种额外的掩蔽来限制擦除到椭圆形.
所述XferMode适用于"源色彩"(从Shader)和"目的地颜色"(来自Canvas的Bitmap).然后使用在光栅化中计算的掩码将结果与目标混合.有关详细信息,请参阅上述文档中的"传输"阶段.
Rom*_*Guy 11
StackOverflow上很难回答这个问题.然而,在我开始之前,请注意形状(例如drawRect())没有内在颜色.颜色信息始终来自Paint对象.
这抹去了椭圆形.在我注意到这一点之前,我的心理模型是绘制到画布(概念上)绘制到单独的"图层",然后使用Paint的传输模式使用Canvas的位图组合该图层.如果它那么简单那么上面的代码将擦除整个位图(在剪辑区域内),因为CLEAR总是将颜色(和alpha)设置为0,而不管源的alpha是什么.所以这意味着还有一种额外的掩蔽来限制擦除到椭圆形.
你的模型有点偏.椭圆不会绘制到单独的图层中(除非您调用Canvas.saveLayer()),它将直接绘制到Canvas的支持位图上.Paint的传输模式应用于基元绘制的每个像素.在这种情况下,只有椭圆光栅化的结果会影响位图.没有特别的遮蔽,椭圆形本身就是面具.
无论如何,这是管道的简化视图:
(我刚看到你的更新,是的,你发现的内容按顺序描述了管道的各个阶段.)
当使用图层(Canvas.saveLayer())时,管道变得更加复杂,因为管道加倍.您首先浏览管道以在屏幕外位图(图层)内渲染图元,然后通过管道将屏幕外位图应用于画布.
| 归档时间: |
|
| 查看次数: |
10541 次 |
| 最近记录: |