Quartz 2D编程指南(3)路径(Paths)

Paths 

      路径定义了一个或多个形状,或是子路径。一个子路径可由直线,曲线,或者同时由两者构成。它可以是开放的,也可以是闭合的。一个子路径可以是简单的形状,如线、圆、矩形、星形;也可以是复杂的形状,如山脉的轮廓或者是涂鸦。图 3 - 1 显示了一些我们可以创建的路径。左上角的直线可以是虚线;直线也可以是实线。上边中间的路径是由多条曲线组成的开放路径。右上角的同心圆填充了颜色,但没有描边。左下角的加利福尼亚州是闭合路径,由许多曲线和直线构成,且对路径进行填充和描边。两个星形阐明了填充路径的两种方式,我们将在本章详细描述。
                     
                        Figure 3-1   Quartz supports path-based drawing
                        Quartz supports path-based drawing

在本章中,我们将学习如何构建路径,如何对路径进行填充和描边,及影响路径表现形式的参数。

Path Creation and Path Painting

      路径创建及路径绘制是两个独立的工作。首先我们先创建路径。当我们需要渲染路径时,我们需要使用 Quartz 来绘制它。正如图 3 - 1 中所示,我们可以选择对路径进行描边,填充路径,或同时进行这两种操作。我们同样可以将其它对象绘制到路径所表示的范围内,即对对象进行裁减。

      图 3 - 2 绘制了一个路径,该路径包含两个子路径。左边的子路径是一个矩形,右边的子路径是由直线和曲线组成的抽象形状。两个子路径都进行了填充及描边( stroked )。
                  
                       Figure 3-2   A path that contains two shapes, or subpaths
                       
                                           A path that contains two shapes, or subpaths

      图 3 - 3 显示了多条独立绘制的路径。每个路径饮食随机生成的曲线,一些进行填充,另一些进行了描边。这些路径都包含在一个圆形裁减区域内。
                               
                           Figure 3-3   A clipping area constrains drawing
                      A clipping area constrains drawing

The Building Blocks

      子路径是由直线、弧和曲线构成的。 Quartz 同样也提供了简便的函数用于添加矩形或椭圆等形状。点也是路径最基本的构建块,因为点定义了形状的起始点与终止点。

Points

      点由 x, y 坐标值定义,用于在用户空间指定 一个位置。我们可以调用函数 CGContextMoveToPoint   来为新的子路径指定起始点 Quartz 跟踪当前点,用于记录路径构建过程中最新的位置。例如,如果调用函数 CGContextMoveToPoint 并设置位置为 ( 10 , 10 ) ,即将当前点移动到位置 ( 10 , 10 ) 。如果在水平位置绘制 50 个单位长度的直线,则直线的终点为 ( 60 , 10 ) ,该点变成当前点。直线、弧和曲线总是从当前点开始绘制。

      大多数时候我们通过传递 (x, y) 值给 Quartz 函数来指定一个点。一些函数需要我们传递一个   CGPoint 数据结构,该结构包含两个浮点值。

Lines

       直线由两个端点定义。起始点通常是当前点,所以创建直线时,我们只需要指定终止点。我们使用函数 CGContextAddLineToPoint   来添加一条直线到子路径中。
     
      我们可以调用 CGContextAddLines . 函数添加一系列相关的直线到子路径中。我们传递一个点数组给这个函数。第一个点必须是第一条直线的起始点;剩下的点是端点。 Quartz 从第一个点开始绘制一个新子路径,然后每两个相邻点连接成一条线段。

Arcs

      弧是圆弧段。 Quartz 提供了两个函数来创建弧。函数 CGContextAddArc   从圆中来创建一个曲线段。我们指定一个圆心,半径和放射角 ( 以弧度为单位 ) 放射角为 2 PI 时,创建的是一个圆。图 3 - 4 显示了多个独立的路径。每个路径都包含一个随机生成的圆;一些是填充的,另一些是描边的。

                    Figure 3-4   Multiple paths; each path contains a randomly generated circle
                                Multiple paths; each path contains a randomly generated circle
      函数 CGContextAddArcToPoint   用于为矩形创建内切弧的场景。 Quartz 使用我们提供的端点创建两条正切线。同样我们需要提供圆的半径。弧心是两条半径的交叉点,每条半径都与相应的正切线垂直。弧的两个端点是正切线的正切点,如图 3 - 5 所示。红色的部分是实际绘制的部分。

                   Figure 3-5   Defining an arc with two tangent lines and a radius
                      
                      Defining an arc with two tangent lines and a radius
      
       如果当前路径已经包含了一个子路径, Quartz 将追加一条从当前点到弧的起始点的直线段。如果当前路径为空, Quartz 将创建一个新的子路径,该子路径从弧的起始点开始,而不添加初始的直线段。

curves

      二次与三次 Bezier 曲线是代数曲线,可以指定任意的曲线形状。曲线上的点通过一个应用于起始、终点及一个或多个控制点的多项式计算得出。这种方式定义的形状是向量图的基础。这个公式比将位数组更容易存储,并且曲线可以在任何分辨下重新创建。

      图 3 - 6 显示了一些路径的曲线。每条路径包含一条随机生成的曲线;一些是填充的,另一些是描边的
               Figure 3-6   Multiple paths; each path contains a randomly generated curve
                          Multiple paths; each path contains a randomly generated curve
      我们使用函数   CGContextAddCurveToPoint Bezier 曲线连接到当前点,并传递控制点和端点作为参数,如图 3 - 7 所示。两个控制点的位置决定了曲线的形状。如果两个控制点都在两个端点上面,则曲线向上凸起。如果两个控制点都在两个端点下面,则曲线向下凹。如果第二个控制点比第一个控制点离得当前点近,则曲线自交叉,创建了一个回路。
                     Figure 3-7   A cubic Bézier curve uses two control points
                       
                                 A cubic Bézier curve uses two control points
       我们能够调用函数 CGContextAddQuadCurveToPoint 来创建 Bezier曲线 ,并传递端点及一个控制点,如图 3 - 8 所示,由于使用相同的端点和不同的控制点 显示的2种结果 。控制点决定了曲线弯曲的方向,由于只使用一个控制点,所以无法创建出许多有趣的 曲线。例如我们无法使用一个单一的控制点创建出交叉的曲线。
                      Figure 3-8   A quadratic Bézier curve uses one control point
                         
                          A quadratic Bézier curve uses one control point

Closing a Subpath

         我们可以调用函数 CGContextClosePath 来关闭当前子路径。该函数用一条直接来连接当前点与起始点,以使路径闭合。起始与终点重合的直线、弧和曲线并不自动闭合路径,我们必须调用CGContextClosePath来闭合路径。

        Quartz的一些函数将路径的子路径看成是闭合的。这些函数显示地添加一条直线来闭合 子路径,如同调用了CGContextClosePath函数。

     在闭合一条子路径后,如果程序再添加直线、弧或曲线到路径,Quartz将在闭合的子路径的起点开始创建一个新的子路径。

Ellipses

      椭圆是一种特殊的圆。椭圆是通过定义两个焦点,在平面内所有与这两个焦点的距离之和相等的点所构成的图形。图 3 - 9 显示了一些独立的路径。每个路径都包含一个随机生成的椭圆;一些进行了填充,另一边进行了描边。
               
                   Figure 3-9  Multiple paths; each path contains a randomly generated ellipse    
                               Multiple paths; each path contains a randomly generated ellipse
      我们可以调用 CGContextAddEllipseInRect . 函数来添加一个椭圆到当前路径。我们提供一个矩形来定义一个椭圆。 Quartz 利用一系列的 Bezier 曲线来模拟椭圆。椭圆的中心就是矩形的中心。如果矩形的宽与高相等,则椭圆变成了圆,且圆的半径为矩形宽度的一半。如果矩形的宽与高不相等,则定义了椭圆的长轴与短轴。
   
      添加到路径中的椭圆开始于一个 move-to 操作,结束于一个 close-subpath 操作,所有的移动方向都是顺时针。

Rectangles

      我们可以调用 CGContextAddRect 来添加一个矩形到当前路径中,并提供一个 CGRect   结构体 ( 包含矩形的原点及大小 ) 作为参数。
     添加到路径的矩形开始于一个 move-to 操作,结束于一个 close-subpath 操作,所有的移动方向都是逆时针方向。
     我们也可能调用 CGContextAddRects 函数来添加一系列的矩形到当前路径,并传递一个 CGRect 结构体的数组。图 3 - 10 显示了一些独立的路径。每个路径包含一个随机生成的矩形;一些进行了填充,另一边进行了描边。

             Figure 3-10   Multiple paths; each path contains a randomly generated rectangle
                                Multiple paths; each path contains a randomly generated rectangle
Creating a Path

      当我们需要在一个图形上下文中构建一个路径时,我们需要调用 CGContextBeginPath   来标记 Quartz 。然后,我们调用函数 CGContextMovePoint 来设置每一个图形或子路径的起始点。在构建起始点后,我们可以添加直线、弧、曲线。记住如下规则:

1:在开始绘制路径前,调用函数 CGContextBeginPath
2:直线、弧、曲线开始于当前点。空路径没有当前点;我们必须调用 CGContextMoveToPoint 来设置第一个子路径的起始点,或者调用一个便利函数来隐式地完成该任务。
3:如果想要闭合当前子路径,调用函数 CGContextClosePath 。随后路径将开始一个新的子路径,即使我们不显示设置一个新的起始点。
4:当绘制弧时, Quartz 将在当前点与弧的起始点间绘制一条直线。
5:添加椭圆和矩形的 Quartz 程序将在路径中添加新的闭合子路径。
6:我们必须调用绘制函数来填充或者描边一条路径,因为创建路径时并不会绘制路径。更多: See  Painting a Path

     在绘制路径后,将清空图形上下文。我们也许想保留路径,特别是在绘制复杂场景时,我们需要反复使用。基于此, Quartz 提供了两个数据类型来创建可复用路径 CGPathRef CGMutablePathRef 。我们可以调用函数 CGPathCreateMutable   来创建可变的 CGPath 对象,并可向该对象添加直线、弧、曲线和矩形。 Quartz 提供了一个类似于操作图形上下文的 CGPath 的函数集合。这些路径函数操作 CGPath 对象,而不是图形上下文。这些函数包括:

CGPathAddArc , which replaces  CGContextAddArc
CGPathAddRect , which replaces  CGContextAddRect

     如果想要添加一个路径到图形上下文,可以调用 CGContextAddPath 。路径将保留在图形上下文中,直到 Quartz 绘制它。我们可以调用 CGContextAddPath 再次添加路径。

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

Parameters That Affect Stroking

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

               Table 3-1   Parameters that affect how Quartz strokes the current path                         

Parameter

Function to set parameter value

Line width

CGContextSetLineWidth

Line join

CGContextSetLineJoin

Line cap

CGContextSetLineCap

Miter limit

CGContextSetMiterLimit

Line dash pattern

CGContextSetLineDash

Stroke color space

CGContextSetStrokeColorSpace

Stroke color

CGContextSetStrokeColorCGContextSetStrokeColorWithColor

Stroke pattern

CGContextSetStrokePattern


linewidth 是线的总宽度,单位是用户空间单元。

linejoin 属性指定如何绘制线段间的联接点。 Quartz 支持表 3 - 2 中描述的联接样式。

Table 3-2  Line join styles

Style

Appearance

Description

Miter join

Miter join

Quartz extends the outer edges of the strokes for the two segments until they meet at an angle, as in a picture frame. If the segments meet at too sharp an angle, a bevel join is used instead. A segment is too sharp if the length of the miter divided by the line width is greater than the miter limit.

Round join

Round join

Quartz draws a semicircular arc with a diameter equal to the line width around the endpoint. The enclosed area is filled in.

Bevel join

Bevel join

Quartz finishes the two segments with butt caps. The resulting notch beyond the ends of the segments is filled with a triangle.


linecap 指定如何绘制直线的端点。 Quartz 支持表 3 - 3 所示的线帽类型。默认的是 butt cap

Table 3-3  Line cap styles

Style

Appearance

Description

Butt cap

Butt cap

Quartz squares off the stroke at the endpoint of the path. There is no projection beyond the end of the path.

Round cap

Round cap

Quartz draws a circle with a diameter equal to the line width around the point where the two segments meet, producing a rounded corner. The enclosed area is filled in.

Projecting square cap

Projecting square cap

Quartz extends the stroke beyond the endpoint of the path for a distance equal to half the line width. The extension is squared off.


      闭合路径将起始点看作是一个联接点;起始点同样也使用选定的直线连接方法进行渲染。如果通过添加一条连接到起始点的直线来闭合路径,则路径的两个端点都使用选定的线帽类型来绘制。

   Linedash pattern( 虚线模式 ) 允许我们沿着描边绘制虚线。我们通过在 CGContextSetLineDash 结构体中指定虚线数组和虚线相位来控制虚线的大小及位置。
void CGContextSetLineDash (
                           CGContextRef ctx,
                           CGFloat phase,
                           const CGFloat lengths[],
                           size_t count
                           );
      其中 lengths 属性 是一个 CGFloat 型数组 , 每个 CGFloat 值控制点线的实现长度和间距 . 比如 {2,3} 代表实线长度为 2, 间距为 3. 其实也可以理解实现和没有的概念, 反复重复你设置的值 ,该值是在绘制线段与未绘制线段之间交替。 phase 属性指定虚线模式的起始点。图 3 - 11 显示了虚线模式:
                                      Figure 3-11   Examples of line dash patterns
                                  Examples of line dash patterns
      描边颜色空间 (stroke color space) 定义了 Quartz 如何解析描边的颜色。我们同样也可以指定一个封装了颜色和颜色空间的 CGColorRef 数据类型。

Functions for Stroking a Path

Quartz 提供了表 3 - 4 中的函数来描边当前路径。其中一些是描边矩形及椭圆的便捷函数。

Table 3-4  Functions that stroke paths

Function

Description

CGContextStrokePath

Strokes the current path.

CGContextStrokeRect

Strokes the specified rectangle.

CGContextStrokeRectWithWidth

Strokes the specified rectangle, using the specified line width.

CGContextStrokeEllipseInRect

Strokes an ellipse that fits inside the specified rectangle.

CGContextStrokeLineSegments

Strokes a sequence of lines. 

CGContextDrawPath

If you pass the constant kCGPathStroke, strokes the current path. See Filling a Path if you want to both fill and stroke a path.


函数 CGContextStrokeLineSegments功能 等同于如下代码:
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 时,我们通过点数组来指定线段,并组织成点对的形式。每一对是由线段的起始点与终止点组成。例如,数组的第一个点指定了第一条直线的起始点,第二个点是第一条直线的终点,第三个点是第二条直线的起始点,依此类推。

Filling a Path

      当我们填充当前路径时, Quartz 将路径包含的每个子路径都看作是闭合的。然后,使用这些闭合路径并计算填充的像素。 Quartz 有两种方式来计算填充区域。椭圆和矩形这样的路径其区域都很明显。但是如果路径是由几个重叠的部分组成或者路径包含多个子路径 ( 如图 3 - 12 所示 ) ,我们则有两种规则来定义填充区域。

      默认的规则是非零缠绕数规则 (nonzero windingnumber rule) 。为了确定一个点是否需要绘制,我们从该点开始绘制一条直线穿过绘图的边界。从 0 开始计数,每次路径片断从左到右穿过直线,计数加 1 ;而从右到左穿过直线时,计数减 1 。如果结果为 0 ,则不绘制该点,否则绘制。路径片断绘制的方向会影响到结果。图 3 - 13 显示了使用非缠绕数规则对内圆和外圆进行填充的结果。当两个圆绘制方向相同时,两个圆都被填充。如果方向相反,则内圆不填充。

     我们也可以使用偶数 - 奇数规则来确定一个点是否应该被绘制,我们从该点开始绘制一条直线穿过绘图的边界。计算穿过该直线的路径片断的数目。如果是奇数,则绘制该点,如果是偶数,则不绘制该点。路径片断绘制的方向不影响结果。如图 3 - 12 所示,无论两个圆的绘制方向是什么,填充结果都是一样的。

                           Figure 3-12   Concentric circles filled using different fill rules

                                    Concentric circles filled using different fill rules

Quartz 提供了表 3 - 5 中的函数来填充当前路径。其中一些是填充矩形及椭圆的便捷函数。

Table 3-5  Functions that fill paths

Function

Description

CGContextEOFillPath

Fills the current path using the even-odd rule.

CGContextFillPath

Fills the current path using the nonzero winding number rule.

CGContextFillRect

Fills the area that fits inside the specified rectangle.

CGContextFillRects

Fills the areas that fits inside the specified rectangles.

CGContextFillEllipseInRect

Fills an ellipse that fits inside the specified rectangle.

CGContextDrawPath

Fills the current path if you pass kCGPathFill (nonzero winding number rule) or kCGPathEOFill (even-odd rule). Fills and strokes the current path if you pass kCGPathFillStroke or kCGPathEOFillStroke.


Setting Blend Modes

      混合模式指定了 Quartz 如何将绘图绘制到背景上。 Quartz 默认使用普通混合模式 (normal blend mode) ,该模式使用如下公式来计算前景绘图与背景绘图如何混合:

result = (alpha * foreground) + ( 1 - alpha) *background

   Color and Color Spaces 章节里面详细讨论了颜色值的 alpha 组件,该组件用于指定颜色的透明度。在本章的例子中,我们可以假设颜色值是完全不透明的 (alpha = 1. 0 ) 。对于不透明的颜色值,当我们用普通混合模式时,所有绘制于背景之上的绘图都会遮掩住背景。

      我们可以调用函数 CGContextSetBlendMode , 并传递适当的混合模式常量值来设置混合模式来达到我们想到的效果。记住混合模式是图形状态的一部分。如果调用了函数 CGContextSaveGState   来改变混合模式,则调用函数   CGContextRestoreGState 来重新设置混合模式为普通混合模式。

      接下来的内容例举了不同混合模式上将图 3 - 13 的矩形绘制到图 3 - 14 的矩形之上的效果。背景图使用普通混合模式来绘制。然后调用 CGContextSetBlendMode 函数来改变混合模式。最后绘制前景矩形
                 
                       Figure 3-13   The rectangles painted in the foreground
                                        The rectangles painted in the foreground

                        Figure 3-14   The rectangles painted in the background
                                         The rectangles painted in the background

注意:我们同样可以使用混合模式来组合两张图片或将图片与图形上下文中已有的内容进行混合。 Using Blend Modes with Images提供了相关信息对于如何处理使用 混合模式来组合两张图片。

Normal Blend Mode

      由于普通混合模式是默认的混合模式,所以在设置了其它混合模式后,可以调用 CGContextSetBlendMode 并传递 kCGBlendModeNormal 来将混合模式重设为默认。图 3 - 15 显示了普通混合模式上图 3 - 13 与图 3 - 14 混合的效果。
                         Figure 3-15   Rectangles painted using normal blend mode
                                         Rectangles painted using normal blend mode

Multiply Blend Mode

       正片叠底混合模式指定将前景的图片采样与背景图片采样相乘。结果颜色至少与两个采样颜色之一一样暗。图 3 - 16 显示了混合结果。我们可以调用 CGContextSetBlendMode 并传递 kCGBlendModeMultiply 来设置这种混合模式。
                      Figure 3-16   Rectangles painted using multiply blend mode
                                         Rectangles painted using multiply blend mode

Screen Blend Mode

      屏幕混合模式指定将前景图片采样的反转色与背景图片的反转色相乘。结果颜色至少与两种采样颜色之一一样亮。图 3 - 17 显示了混合结果。我们可以调用 CGContextSetBlendMode 并传递 kCGBlendModeScreen 来设置这种混合模式。
                Figure 3-17   Rectangles painted using screen blend mode
                                       Rectangles painted using screen blend mode

Overlay Blend Mode

      叠加混合模式是将前景图片与背景图片或者正片叠底,或者屏幕化,这取决于背景颜色。背景颜色值与前景颜色值以反映出背景颜色的亮度与暗度。图3-18显示了混合效果。我们可以调用CGContextSetBlendMode并传递kCGBlendModeOverlay来设置这种混合模式。
                     Figure 3-18   Rectangles painted using overlay blend mode
                                      Rectangles painted using overlay blend mode

Darken Blend Mode
    
      通过选择前景图片与背景图片更暗的采样来混合图片采样。背景图片采样被前景图片采样更暗的部分取代,而其它部分不变。图 3 - 19 显示了混合效果。我们可以调用 CGContextSetBlendMode 并传递 kCGBlendModeDarken 来设置这种混合模式。
                     Figure 3-19   Rectangles painted using darken blend mode
                                      Rectangles painted using darken blend mode

Lighten Blend Mode

      通过选择前景图片与背景图片更亮的采样来混合图片采样。背景图片采样被前景图片采样更亮的部分取代,而其它部分不变。图 3 - 20 显示了混合效果。我们可以调用 CGContextSetBlendMode 并传递 kCGBlendModeLighten 来设置这种混合模式。
                     Figure 3-20   Rectangles painted using lighten blend mode
                                     Rectangles painted using lighten blend mode

Color Dodge Blend Mode

      加亮背景图片采样以反映出前景图片采样。被指定为黑色的前景图片采样值将不产生变化。图 3 - 21 显示了混合效果。我们可以调用 CGContextSetBlendMode 并传递 kCGBlendModeColorDodge 来设置这种混合模式。
                     Figure 3-21   Rectangles painted using color dodge blend mode                                                                    
                                    Rectangles painted using color dodge blend mode

Color Burn Blend Mode

      加深背景图片采样以反映出前景图片采样。被指定为白色的前景图片采样值将不产生变化。图 3 - 21 显示了混合效果。我们可以调用 CGContextSetBlendMode 并传递 kCGBlendModeColorBurn 来设置这种混合模式。
                    Figure 3-22   Rectangles painted using color burn blend mode
                                   Rectangles painted using color burn blend mode

Soft Light Blend Mode

      根据前景采样颜色减淡或加深颜色值。如果前景采样颜色比 50 % 灰度值更亮,则减淡背景,类似于 Dodge 模式。如果前景采样颜色比 50 % 灰度值更暗,则加强背景,类似于 Burn 模式。纯黑或纯白的图片采样将产生更暗或更亮的区域。但是但是 不产生纯白或纯黑的颜色。该效果类似于将一个漫射光源放于一个前景图前。该效果用于在场景中添加高光效果。图 3 - 23 显示了混合效果。我们可以调用 CGContextSetBlendMode 并传递 kCGBlendModeSoftLight 来设置这种混合模式。
                  Figure 3-23   Rectangles painted using soft light blend mode
                                  Rectangles painted using soft light blend mode

Hard Light Blend Mode

     根据前景图片采样颜色正片叠加或屏幕化颜色。如果前景采样颜色比 50 % 灰度值更亮,则减淡背景,类似于 screen 模式。如果前景采样颜色比 50 % 灰度值更暗,则加深背景,类似于 multiply 模式。如果前景采样颜色等于 50 % 灰度,则前景颜色不变。纯黑与纯白的颜色图片采样将产生纯黑或纯白的颜色值。该效果类似于将一个强光源放于一个前景图前。该效果用于在场景中添加高光效果。图 3 - 24 显示了混合效果。我们可以调用 CGContextSetBlendMode 并传递 kCGBlendModeHardLight 来设置这种混合模式。
                   Figure 3-24   Rectangles painted using hard light blend mode
                                  Rectangles painted using hard light blend mode

Difference Blend Mode

      将前景图片采样颜色值与背景图片采样值相减,相减的前后关系取决于哪个采样的亮度值更大。黑色的前景采样值不发生变化;白色值转化为背景的值。图 3 - 25 显示了混合效果。我们可以调用 CGContextSetBlendMode 并传递 kCGBlendModeDifference 来设置这种混合模式。
                   Figure 3-25   Rectangles painted using difference blend mode
                                  Rectangles painted using difference blend mode

Exclusion Blend Mode

       该效果类似于 Difference 效果,只是对比度更低。黑色的前景采样值不发生变化;白色值转化为背景的值。图 3 - 26 显示了混合效果。我们可以调用 CGContextSetBlendMode 并传递 kCGBlendModeExclusion 来设置这种混合模式。
                    Figure 3-26   Rectangles painted using exclusion blend mode
                                   Rectangles painted using exclusion blend mode

Hue Blend Mode

      使用背景的亮度和饱和度与前景的色相混合。图 3 - 27 显示了混合效果。我们可以调用 CGContextSetBlendMode 并传递 kCGBlendModeHue 来设置这种混合模式。
                    Figure 3-27   Rectangles painted using hue blend mode
                                   Rectangles painted using hue blend mode

Saturation Blend Mode

     混合背景的亮度和色相前景的饱和度。背景中没有饱和度的区域不发生变化。图 3 - 28 显示了混合效果。我们可以调用 CGContextSetBlendMode 并传递 kCGBlendModeSaturation 来设置这种混合模式。
                  Figure 3-28   Rectangles painted using saturation blend mode
                                   Rectangles painted using saturation blend mode

Color Blend Mode

      混合背景的亮度值与前景的色相与饱和度。该模式保留图片的灰度级。我们可以使用该模式绘制单色图片或彩色图片。图 3 - 29 显示了混合效果。我们可以调用 CGContextSetBlendMode 并传递 kCGBlendModeColor 来设置这种混合模式。
                   Figure 3-29   Rectangles painted using color blend mode
                                   Rectangles painted using color blend mode

Luminosity Blend Mode

     将背景图片的色相、饱和度与背景图片的亮度相混合。该模块产生一个与 Color Blend 模式相反的效果。图 3 - 30 显示了混合效果。我们可以调用 CGContextSetBlendMode 并传递 kCGBlendModeLuminosity 来设置这种混合模式。
                Figure 3-30   Rectangles painted using luminosity blend mode
                                  Rectangles painted using luminosity blend mode

Clipping to a Path

      当前裁剪区域是从路径中创建,作为一个遮罩,从而允许遮住我们不想绘制的部分。例如,我们有一个很大的位图图片,但只需要显示其中一小部分,则可以设置裁减区域来显示我们想显示的部分。

      当我们绘制的时候, Quartz 只渲染裁剪区域里面的东西。裁剪区域内的闭合路径是可见的;而在区域外的部分是不可见的。

      当图形上下文初 始创建时,裁减区域包含上下文所有的可绘制区域 ( 例如, PDF 上下文的 media box) 。我们可以通过设置当前路径来改变裁剪区域,然后使用裁减函数来取代绘制函数。裁剪函数与当前已有的裁剪区域求交集以获得路径的填充区域。因此,我们可以求交取得裁减区域,缩小图片的可视区域,但是不能扩展裁减区域。

      裁减区域是图形状态的一部分。为了恢复先前的裁减区域,我们可以在裁减前保存图形状态,并在裁减绘制后恢复图 形状态。

代码清单 3 - 1 显示了绘制圆形后设置裁减区域。该段代码使得绘图被裁减,效果类似于图 3 - 3 所示。对其它的例子可以看 see  Clip the Context  in the chapter  Gradients

Listing 3 - 1   Setting up a circular clip area
CGContextBeginPath (context);
CGContextAddArc (context, w/2, h/2, ((w>h) ? h : w)/2,0,2*PI,0);
CGContextClosePath (context);
CGContextClip (context);

 Table 3-6  Functions that clip the graphics context

Function

Description

CGContextClip

Uses the nonzero winding number rule to calculate the intersection of the current path with the current clipping path.

CGContextEOClip

Uses the even-odd rule to calculate the intersection of the current path with the current clipping path.

CGContextClipToRect

Sets the clipping area to the area that intersects both the current clipping path and the specified rectangle.

CGContextClipToRects

Sets the clipping area to the area that intersects both the current clipping path and region within the specified rectangles.

CGContextClipToMask

Maps a mask into the specified rectangle and intersects it with the current clipping area of the graphics context. Any subsequent path drawing you perform to the graphics context is clipped. (See Masking an Image by Clipping the Context.)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值