2011-11-26/20:01:51
http://code.google.com/p/skia/wiki/SkRegion code.google.skia.wiki
Skia使用SkRegion表示canvas的裁剪范围。
SkRegion对外部不透明,但可以通过迭代器(iterator)查询。
SkRegion可以与其他的SkRegion或者矩形(可以当做简单的region)相组合。
只要记得数学类中的操作(如交集、并集、不同等)就会使用SkRegion.
bool SkRegion::isEmpty(); bool SkRegion::isRect(); bool SkRegion::isComplex();
SkRegions分类为三种:empty、rectangle、complex.
(空、矩形、复杂)?
所有空的SkRegion是相等的(使用操作符==)。
相比较而言,SkRect 和SKIRect中,任何fLeft>=fRight或者fTop>=fBottom的SkRect或者SkIRect都是认为是空的,但是他们是不同的矩形,不相等。
SkRect a = { 0, 0, 0, 0 }; SkRect b = { 1, 1, 1, 1 };
矩形a和b都是空的,但是他们被定义为不相等。但是所有空的SkRegion是相等的。
如果你查询空SkRegion对象的范围,你总是会得到{0,0,0,0},即使你移动这个SkRegion对象,仍然是{0,0,0,0}。
SkRegion a, b; // regions default to empty assert(a == b); a.offset(10, 20); assert(a == b); assert(a.getBounds() == { 0, 0, 0, 0 }); // not legal C++, but you get the point assert(b.getBounds() == { 0, 0, 0, 0 });
要初始化SkRegion,可以使用多种set函数,例如:
SkRegion a, b; a.setRect(10, 10, 50, 50); b.setRect(rect); // see SkIRect c.setPath(path); // see SkPath
上面是SkCanvas执行任意一种clip()操作的第一步,裁剪数据先转换成设备坐标(见:SkMatrix),然后用这些rect或者path的数据初始化一个SkRegion对象,最后的步骤是将这个新的SkRegion对象用指定的操作与已经存在的clip范围相结合。结合方式有:
enum Op { kUnion_Op, kIntersect_Op, kDifference_Op, kXor_Op, kReverseDifference_Op, kReplace_Op };
调用clip操作的时候默认执行 kIntersect_Op 操作,其他方式也是同样有效的。
// returns true if the resulting clip is non-empty (i.e. drawing can still occur) clip区域不为空返回true,
bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op) { SkRegion rgn; // peek at the CTM (current transformation matrix on the canvas) const SkMatrix& m = this->getTotalMatrix(); if (m.rectStaysRect()) { // check if a transformed rect can be represented as another rect 判断矩形是否能被另一个矩形代替?(矩阵是平行矩阵?) SkRect deviceRect; m.mapRect(&deviceRect, rect); 将形参rect(SkRect类型)转化成当前canvas矩阵上的 deviceRect(SkRect类型) SkIRect intRect; deviceRect.round(&intRect); 用deviceRect设置intRect(SkIRect类型) rgn.setRect(intRect); 用intRect设置rgn(SkRegion) } else { // matrix rotates or skew (or is perspective) 矩阵旋转 或者 倾斜 或者是 透视矩阵? SkPath path; path.addRect(rect); 用形参rect初始化path(SkPath) path.transform(m); 将path用当前canvas的矩阵转换 rgn.setPath(path); 用path设置rgn } // now combine the new region with the current one, using the specified *op* return fCurrentClip.op(rgn, op); //用指定的合并方式op合并 新的rgn 和 canvas的当前clip区域 }
ezhong的博客园:http://www.cnblogs.com/ezhong/