路径定了一个或多个形状,或是子路径。一个子路径可由直线,曲线,或者同由两者构成。它可以是开放的,也可以是合的。一个子路径可以是简单的形状,如线、矩形、星形;也可以是复的形状,如山脉的廓或者是涂3-1示了一些我可以建的路径。左上角的直线可以是虚线;直线也可以是实线。上的路径是由多条曲线组成的开放路径。右上角的同心填充了色,但没有描。左下角的加利福尼州是合路径,由多曲线和直线构成,且路径行填充和描。两个星形明了填充路径的两种方式,我将在本章详细描述。

当我们需要在一个图形上下文中构建一个路径时,我们需要调用CGContextBeginPath来标记Quartz。然后,我们调用函数CGContextMovePoint来设置每一个图形或子路径的起始点。在构建起始点后,我们可以添加直线、弧、曲线。记住如下规则:
  • 在开始绘制路径前,调用函数CGContextBeginPath;
  • 直线、弧、曲线开始于当前点。空路径没有当前点;我们必须调用CGContextMoveToPoint来设置第一个子路径的起始点,或者调用一个便利函数来隐式地完成该任务。
  • 如果要闭合当前子路径,调用函数CGContextClosePath。随后路径将开始一个新的子路径,即使我们不显示设置一个新的起始点。
  • 当绘制弧时,Quartz将在当前点与弧的起始点间绘制一条直线。
  • 添加椭圆和矩形的Quartz程序将在路径中添加新的闭合子路径。
  • 我们必须调用绘制函数来填充或者描边一条路径,因为创建路径时并不会绘制路径。
在绘制路径后,将清空图形上下文。我们也许想保留路径,特别是在绘制复杂场景时,我们需要反复使用。基于此,Quartz提供了两个数据类型来创建可复用路径—CGPathRef和CGMutablePathRef。我们可以调用函数CGPathCreateMutable来创建可变的CGPath对象,并可向该对象添加直线、弧、曲线和矩形。Quartz提供了一个类似于操作图形上下文的CGPath的函数集合。这些路径函数操作CGPath对象,而不是图形上下文。这些函数包括:
  • CGPathCreateMutable,取代CGContextBeginPath
  • CGPathMoveToPoint,取代CGContextMoveToPoint
  • CGPathAddLineToPoint,取代CGContexAddLineToPoint
  • CGPathAddCurveToPoint,取代CGContexAddCurveToPoint
  • CGPathAddEllipseInRect,取代CGContexAddEllipseInRect
  • CGPathAddArc,取代CGContexAddArc
  • CGPathAddRect,取代CGContexAddRect
  • CGPathCloseSubpath,取代CGContexClosePath
如果想要添加一个路径到图形上下文,可以调用CGContextAddPath。路径将保留在图形上下文中,直到Quartz绘制它。我们可以调用CGContextAddPath再次添加路径。

制路径
我们可以绘制填充或描边的路径。描边(Stroke)是绘制路径的边框。填充是绘制路径包含的区域。Quartz提供了函数来填充或描边路径。描边线的属性(宽度、颜色等),填充色及Quartz用于计算填充区域的方法都是图形状态的一部分。

影响描的属性
我们可以使用表3-1中的属性来决定如何对路径进行描边操作。这边属性是图形上下文的一部分,这意味着我们设置的值将会影响到后续的描边操作,直到我们个性这些值。

Quartz 2D编程指南(3) - 路径(Paths)【上】
linewidth是线的总宽度,单位是用户空间单元。
linejoin属性指定如何绘制线段间的联接点。Quartz支持表3-2中描述的联接样式。

Table 3-2 直线联接样式
 
复制代码
  1. void CGContextSetLineDash (
  2. CGContextRef ctx,
  3. float phase,
  4. c*****t float lengths[],
  5. size_t count,
  6. );

其中lengths属性指定了虚线段的长度,该值是在绘制片断与未绘制片断之间交替。phase属性指定虚线模式的起始点。图3-11显示了虚线模式:
 
复制代码
  1. CGContextBeginPath(context);                                                                                                                                                                                                                                                                 for(k = 0; k < count; k += 2) {                                                                                                                                                                                                                                                                                  CGContextMoveToPoint(context,s[k].x, s[k].y); CGContextAddLineToPoint(context,s[k+1].x, s[k+1].y);}CGContextStrokePath(context);

当我们调用CGContextStrokeLineSegments时,我们通过点数组来指定线段,并组织成点对的形式。每一对是由线段的起始点与终止点组成。例如,数组的第一个点指定了第一条直线的起始点,第二个点是第一条直线的终点,第三个点是第二条直线的起始点,依此类推。
填充路径
当我们填充当前路径时,Quartz将路径包含的每个子路径都看作是闭合的。然后,使用这些闭合路径并计算填充的像素。 Quartz有两种方式来计算填充区域。椭圆和矩形这样的路径其区域都很明显。但是如果路径是由几个重叠的部分组成或者路径包含多个子路径(如图3-12所示),我们则有两种规则来定义填充区域。
默认的规则是非零缠绕数规则(nonzero windingnumber rule)。为了确定一个点是否需要绘制,我们从该点开始绘制一条直线穿过绘图的边界。从0开始计数,每次路径片断从左到右穿过直线是,计数加1;而从右到左穿过直线时,计数减1。如果结果为0,则不绘制该点,否则绘制。路径片断绘制的方向会影响到结果。图3-13显示了使用非缠绕数规则对内圆和外圆进行填充的结果。当两个圆绘制方向相同时,两个圆都被填充。如果方向相反,则内圆不填充。
我们也可以使用偶数-奇数规则。为了确定一个点是否被绘制,我们从该点开始绘制一条直线穿过绘图的边界。计算穿过该直线的路径片断的数目。如果是奇数,则绘制该点,如果是偶数,则不绘制该点。路径片断绘制的方向不影响结果。如图3-12所示,无论两个圆的绘制方向是什么,填充结果都是一样的。

Quartz 2D编程指南(3) - 路径(Paths)【上】
Quartz提供了表3-5中的函数来填充当前路径。其中一些是填充矩形及椭圆的便捷函数。
表3-5 填充路径的函数
[ 此帖被德鲁伊在2011-11-14 14:05重新编辑 ]

相关文章: