Quartz 2D 编程指南三:路径

2017-06-08  本文已影响89人  bobociel
logo.PNG

Paths(路径)

A path defines one or more shapes, or subpaths. A subpath can consist of straight lines, curves, or both. It can be open or closed. A subpath can be a simple shape, such as a line, circle, rectangle, or star, or a more complex shape such as the silhouette of a mountain range or an abstract doodle. Figure 3-1 shows some of the paths you can create. The straight line (at the upper left of the figure) is dashed; lines can also be solid. The squiggly path (in the middle top) is made up of several curves and is an open path. The concentric circles are filled, but not stroked. The State of California is a closed path, made up of many curves and lines, and the path is both stroked and filled. The stars illustrate two options for filling paths, which you’ll read about later in this chapter.

路径定义一个或多个形状或子路径。 子路径可以由直线,曲线或两者组成。 它可以是开放的或是闭合的。 子路径可以是简单的形状,例如线,圆,矩形或星形,或更复杂的形状,例如山脉或抽象涂鸦的轮廓。 图3-1显示了可以创建的一些路径。 直线(在图的左上方)是虚线; 线条也可以是实线。 波浪路径(中间顶部)由几条曲线组成,是一条开放的路径。 同心圆被填充,但没有描边。 加利福尼亚州是一条封闭的路径,由许多曲线和线条组成,路径既被描边又被填充。 星星说明了填充路径的两种方式,您将在本章后面阅读。

Figure 3-1 Quartz supports path-based drawing

In this chapter, you’ll learn about the building blocks that make up paths, how to stroke and paint paths, and the parameters that affect the appearance of paths.

在本章中,您将了解组成路径的构建块,如何描边和填充路径,以及影响路径表现形式的参数。

1.Path Creation and Path Painting(路径创建和绘制)

Path creation and path painting are separate tasks. First you create a path. When you want to render a path, you request Quartz to paint it. As you can see in Figure 3-1, you can choose to stroke the path, fill the path, or both stroke and fill the path. You can also use a path to constrain the drawing of other objects within the bounds of the path creating, in effect, a clipping area.

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

Figure 3-2 shows a path that has been painted and that contains two subpaths. The subpath on the left is a rectangle, and the subpath on the right is an abstract shape made up of straight lines and curves. Each subpath is filled and its outline stroked.

图3-2显示了已绘制的路径,其中包含两个子路径。 左边的子路径是一个矩形,右边的子路径是由直线和曲线组成的抽象形状。 每个子路径都被填充和描边。

[图片上传失败...(image-eebcb4-1534606000681)]

Figure 3-3 shows multiple paths drawn independently. Each path contains a randomly generated curve, some of which are filled and others stroked. Drawing is constrained to a circular area by a clipping area.

图3-3显示了独立绘制的多条路径。 每个路径包含一个随机生成的曲线,其中一些曲线被填充,其他的被描边。 这些路径被包含在圆形裁减区内。
[图片上传失败...(image-eb2d44-1534606000681)]

2.The Building Blocks(构建块,积木)

Subpaths are built from lines, arcs, and curves. Quartz also provides convenience functions to add rectangles and ellipses with a single function call. Points are also essential building blocks of paths because points define starting and ending locations of shapes.

子路径由线,弧和曲线构成。 Quartz还提供了方便的功能,通过单个函数调用来添加矩形和椭圆。 点也是路径的基本构建块,因为点定义了形状的起始和终止位置。

(1).Points

Points are x and y coordinates that specify a location in user space. You can call the function CGContextMoveToPoint to specify a starting position for a new subpath. Quartz keeps track of the current point, which is the last location used for path construction. For example, if you call the function CGContextMoveToPoint to set a location at (10,10), that moves the current point to (10,10). If you then draw a horizontal line 50 units long, the last point on the line, that is, (60,10), becomes the current point. Lines, arcs, and curves are always drawn starting from the current point.

Most of the time you specify a point by passing to Quartz functions two floating-point values to specify x and y coordinates. Some functions require that you pass a CGPoint data structure, which holds two floating-point values.

点是指定用户空间中的位置的x和y坐标。您可以调用函数CGContextMoveToPoint为新的子路径指定起始位置。Quartz跟踪当前点,这是用于路径构建的最后一个位置。例如,如果您调用函数CGContextMoveToPoint来设置位置(10,10),就是将当前点移动到(10,10)。如果你随后绘制一条50行长的水平线,则线上的最后一点即(60,10)成为当前点。线,弧和曲线总是从当前点开始绘制。

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

(2).Lines(直线)

A line is defined by its endpoints. Its starting point is always assumed to be the current point, so when you create a line, you specify only its endpoint. You use the function CGContextAddLineToPoint to append a single line to a subpath.

直线由端点实现。 它的起始点为当前点,因此当您创建一条线时,只能指定其端点。 您使用函数CGContextAddLineToPoint将一天线添加到子路径。

You can add a series of connected lines to a path by calling the function CGContextAddLines. You pass this function an array of points. The first point must be the starting point of the first line; the remaining points are endpoints. Quartz begins a new subpath at the first point and connects a straight line segment to each endpoint.

您可以通过调用函数CGContextAddLines将一系列相互连接的线添加到路径。 传递给一个数组给这个函数。 该数组第一点必须是第一行的起点; 其余的点是端点。 Quartz在第一个点开始一个新的子路径,并将直线段连接到每个端点。

(3.)Arcs(圆弧)

Arcs are circle segments. Quartz provides two functions that create arcs. The function CGContextAddArc creates a curved segment from a circle. You specify the center of the circle, the radius, and the radial angle (in radians). You can create a full circle by specifying a radial angle of 2 pi. Figure 3-4 shows multiple paths drawn independently. Each path contains a randomly generated circle; some are filled and others are stroked.

Figure 3-4 Multiple paths; each path contains a randomly generated circle

圆弧是圆弧段。 Quartz提供了两个创建弧的功能。 函数CGContextAddArc从圆形创建一个曲线段。 您指定圆的中心,半径和径向角(以弧度表示)。 您可以通过指定2 pi的径向角度创建一个完整的圆。 图3-4显示了独立绘制的多条路径。 每个路径都包含一个随机生成的圆; 一些被填充,其他被描边。

The function CGContextAddArcToPoint is ideal to use when you want to round the corners of a rectangle. Quartz uses the endpoints you supply to create two tangent lines. You also supply the radius of the circle from which Quartz slices the arc. The center point of the arc is the intersection of two radii, each of which is perpendicular to one of the two tangent lines. Each endpoint of the arc is a tangent point on one of the tangent lines, as shown in Figure 3-5. The red portion of the circle is what’s actually drawn.

函数CGContextAddArcToPoint是您想要圆角矩形时的理想选择。 Quartz使用您提供的端点来创建两条切线。 您还可以提供圆形半径,Quartz切割圆弧。 弧的中心点是两个半径的交点,每个半径垂直于两条切线之一。 圆弧的每个端点都是切线之一的切点,如图3-5所示。 圆的红色部分是实际绘制的。

Figure 3-5 Defining an arc with two tangent lines and a radius

If the current path already contains a subpath, Quartz appends a straight line segment from the current point to the starting point of the arc. If the current path is empty, Quartz creates a new subpath at the starting point for the arc and does not add the initial straight line segment.

如果当前路径已经包含子路径,Quartz将直线段从当前点附加到弧的起点。如果当前路径为空,Quartz会在弧的起始点创建一个新的子路径,并且不添加初始直线段。

(4).Curves(曲线)

Quadratic and cubic Bézier curves are algebraic curves that can specify any number of interesting curvilinear shapes. Points on these curves are calculated by applying a polynomial formula to starting and ending points, and one or more control points. Shapes defined in this way are the basis for vector graphics. A formula is much more compact to store than an array of bits and has the advantage that the curve can be re-created at any resolution.

Figure 3-6 shows a variety of curves created by drawing multiple paths independently. Each path contains a randomly generated curve; some are filled and others are stroked.

二次和三次贝塞尔曲线是可以指定任意数量的有趣曲线形状的代数曲线。 通过将多项式公式应用于起点和终点以及一个或多个控制点来计算这些曲线上的点。 以这种方式定义的形状是矢量图形的基础。 一个公式比一个位数组要小得多,具有可以以任何分辨率重新创建曲线的优点。

图3-6显示了通过独立绘制多个路径创建的各种曲线。 每个路径包含随机生成的曲线; 一些被填充,其他被描边。

Figure 3-6 Multiple paths; each path contains a randomly generated curve

The polynomial formulas that give to rise to quadratic and cubic Bézier curves, and the details on how to generate the curves from the formulas, are discussed in many mathematics texts and online sources that describe computer graphics. These details are not discussed here.

提出二次和三次贝塞尔曲线的多项式公式,以及如何从公式生成曲线的细节,在描述计算机图形学的许多数学文本和在线来源中进行了讨论。 这些细节不在这里讨论。

You use the function CGContextAddCurveToPoint to append a cubic Bézier curve from the current point, using control points and an endpoint you specify. Figure 3-7 shows the cubic Bézier curve that results from the current point, control points, and endpoint shown in the figure. The placement of the two control points determines the geometry of the curve. If the control points are both above the starting and ending points, the curve arches upward. If the control points are both below the starting and ending points, the curve arches downward.

您可以使用CGContextAddCurveToPoint函数从当前点附加立方Bézier曲线,使用控制点和指定的端点。 图3-7显示了从图中所示的当前点,控制点和端点产生的立方Bézier曲线。 两个控制点的放置决定曲线的几何形状。 如果控制点都在起点和终点之上,曲线向上弯曲。 如果控制点都在起点和终点以下,曲线向下弯曲。

Figure 3-7 A cubic Bézier curve uses two control points

You can append a quadratic Bézier curve from the current point by calling the function CGContextAddQuadCurveToPoint, and specifying a control point and an endpoint. Figure 3-8 shows two curves that result from using the same endpoints but different control points. The control point determines the direction that the curve arches. It’s not possible to create as many interesting shapes with a quadratic Bézier curve as you can with a cubic one because quadratic curves use only one control point. For example, it’s not possible to create a crossover using a single control point.

您可以通过调用函数CGContextAddQuadCurveToPoint并指定控制点和端点,从当前点追加二次贝塞尔曲线。图3-8显示了使用相同端点但不同控制点产生的两条曲线。控制点决定曲线曲线的方向。不可能使用二次贝塞尔曲线创建尽可能多的有趣形状,因为可以使用三次曲线,因为二次曲线仅使用一个控制点。例如,不可能使用单个控制点创建交叉。

Figure 3-8 A quadratic Bézier curve uses one control point
(5).Closing a Subpath(关闭子路径)

To close the current subpath, your application should call CGContextClosePath. This function adds a line segment from the current point to the starting point of the subpath and closes the subpath. Lines, arcs, and curves that end at the starting point of a subpath do not actually close the subpath. You must explicitly call CGContextClosePath to close a subpath.

要关闭当前子路径,应用程序应该调用CGContextClosePath。 此函数将一个线段从当前点添加到子路径的起始点,并关闭子路径。 在子路径的起点处结束的线,弧和曲线实际上不会关闭子路径。 您必须显式调用CGContextClosePath来关闭子路径。

Some Quartz functions treat a path’s subpaths as if they were closed by your application. Those commands treat each subpath as if your application had called CGContextClosePath to close it, implicitly adding a line segment to the starting point of the subpath.

一些Quartz函数会将路径的子路径视为被应用程序关闭。 那些命令会将每个子路径视为应用程序调用CGContextClosePath来关闭它,将子段隐式添加到子路径的起始点。

After closing a subpath, if your application makes additional calls to add lines, arcs, or curves to the path, Quartz begins a new subpath starting at the starting point of the subpath you just closed.

关闭一个子路径后,如果您的应用程序进行额外的调用以将线,弧或曲线添加到路径,Quartz将从您刚刚关闭的子路径的起始点开始一个新的子路径。

(6).Ellipses(椭圆)

An ellipse is essentially a squashed circle. You create one by defining two focus points and then plotting all the points that lie at a distance such that adding the distance from any point on the ellipse to one focus to the distance from that same point to the other focus point is always the same value. Figure 3-9 shows multiple paths drawn independently. Each path contains a randomly generated ellipse; some are filled and others are stroked.

椭圆基本上是一个挤压的圆。 您可以通过定义两个焦点点,然后绘制位于距离处的所有点,从而将从椭圆上的任何点到一个焦点的距离添加到从同一点到另一个焦点的距离始终是相同的值。 图3-9显示了独立绘制的多条路径。 每个路径包含随机生成的椭圆; 一些被填充,其他被描边。

Figure 3-9 Multiple paths; each path contains a randomly generated ellipse

You can add an ellipse to the current path by calling the function CGContextAddEllipseInRect. You supply a rectangle that defines the bounds of the ellipse. Quartz approximates the ellipse using a sequence of Bézier curves. The center of the ellipse is the center of the rectangle. If the width and height of the rectangle are equal (that is, a square), the ellipse is circular, with a radius equal to one-half the width (or height) of the rectangle. If the width and height of the rectangle are unequal, they define the major and minor axes of the ellipse.

您可以通过调用函数CGContextAddEllipseInRect将椭圆添加到当前路径。您提供一个定义椭圆边界的矩形。Quartz使用一系列贝塞尔曲线近似椭圆。椭圆的中心是矩形的中心。如果矩形的宽度和高度相等(即一个正方形),则椭圆是圆形的,半径等于矩形的宽度(或高度)的一半。如果矩形的宽度和高度不相等,则它们定义椭圆的主轴和短轴。

The ellipse that is added to the path starts with a move-to operation and ends with a close-subpath operation, with all moves oriented in the clockwise direction.

椭圆的创建开始于移动操作,结束于闭合子路径操作,所有的移动方向都沿顺时针方向。

(7).Rectangles(矩形)

You can add a rectangle to the current path by calling the function CGContextAddRect. You supply a CGRect structure that contains the origin of the rectangle and its width and height.

The rectangle that is added to the path starts with a move-to operation and ends with a close-subpath operation, with all moves oriented in the counter-clockwise direction.

You can add many rectangles to the current path by calling the function CGContextAddRects and supplying an array of CGRect structures. Figure 3-10 shows multiple paths drawn independently. Each path contains a randomly generated rectangle; some are filled and others are stroked.

您可以通过调用函数CGContextAddRect向当前路径添加一个矩形。 您提供的CGRect结构包含矩形的起点及其宽度和高度。

添加到路径的矩形以移动操作开始,并以紧靠子路径操作结束,所有移动方向都沿逆时针方向。

您可以通过调用函数CGContextAddRects并提供一组CGRect结构,将许多矩形添加到当前路径。 图3-10显示了独立绘制的多条路径。 每个路径包含随机生成的矩形; 一些被填充,其他被描边。

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

3.Creating a Path(创建路径)

When you want to construct a path in a graphics context, you signal Quartz by calling the function CGContextBeginPath. Next, you set the starting point for the first shape, or subpath, in the path by calling the function CGContextMoveToPoint. After you establish the first point, you can add lines, arcs, and curves to the path, keeping in mind the following:

当您想在图形上下文中构建路径时,通过调用函数CGContextBeginPath来通知Quartz。接下来,通过调用函数CGContextMoveToPoint,在路径中设置第一个形状或子路径的起始点。建立第一个点后,您可以将线条,弧线和曲线添加到路径中,请牢记以下几点:

After you paint a path, it is flushed from the graphics context. You might not want to lose your path so easily, especially if it depicts a complex scene you want to use over and over again. For that reason, Quartz provides two data types for creating reusable paths—CGPathRef and CGMutablePathRef. You can call the function CGPathCreateMutable
to create a mutable CGPath object to which you can add lines, arcs, curves, and rectangles. Quartz provides a set of CGPath functions that parallel the functions discussed in The Building Blocks. The path functions operate on a CGPath object instead of a graphics context. These functions are:

绘制路径后,从图形上下文中刷新。你可能不想这么容易地失去你的路径,特别是如果它描绘了一个复杂的场景,你想要一遍又一遍地使用。因此,Quartz提供了两种创建可重用路径的数据类型--CGPathRef和CGMutablePathRef。您可以调用函数CGPathCreateMutable
创建一个可变CGPath对象,您可以向其中添加线,弧,曲线和矩形。 Quartz提供了一组并行于“构建块”中讨论的功能的CGPath函数。路径函数对CGPath对象而不是图形上下文进行操作。这些功能是:

See Quartz 2D Reference Collection for a complete list of the path functions.
When you want to append the path to a graphics context, you call the function CGContextAddPath. The path stays in the graphics context until Quartz paints it. You can add the path again by calling CGContextAddPath.

有关路径函数的完整列表,请参阅Quartz 2D参考集合。
当您要将路径追加到图形上下文时,可以调用函数CGContextAddPath。路径停留在图形上下文中,直到Quartz绘制它。您可以通过调用CGContextAddPath再次添加路径。

Note: You can replace the path in a graphics context with the stroked version of the path by calling the function CGContextReplacePathWithStrokedPath.

注意:您可以通过调用函数CGContextReplacePathWithStrokedPath将图形上下文中的路径替换为轨迹版本的路径。
(使用绘制当前路径时覆盖的区域作为当前CGContextRef中的新路径。举例来说,假如当前CGContextRef包含一个圆形路径且线宽为10,调用该方法后,当前CGContextRef将包含一个环宽为10的环形路径。)

4.Painting a Path(绘制路径)

You can paint the current path by stroking or filling or both. Stroking paints a line that straddles the path. Filling paints the area contained within the path. Quartz has functions that let you stroke a path, fill a path, or both stroke and fill a path. The characteristics of the stroked line (width, color, and so forth), the fill color, and the method Quartz uses to calculate the fill area are all part of the graphics state (see Graphics States).

您可以通过描边或填充或两者来绘制当前路径。 描边是根据路径绘制线条。 填充是绘制包含在路径内的区域。 Quartz有一些功能,可以让您划一条路径,填充一条路径,或者两条路线,并填充路径。 笔画线的特征(宽度,颜色等),填充颜色以及Quartz用于计算填充区域的方法都是图形状态的一部分(参见图形状态)。

(1).Parameters That Affect Stroking(影响描边的参数)

You can affect how a path is stroked by modifying the parameters listed in Table 3-1. These parameters are part of the graphics state, which means that the value you set for a parameter affects all subsequent stroking until you set the parameter to another value.

您可以通过修改表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

The line width is the total width of the line, expressed in units of the user space. The line straddles the path, with half of the total width on either side.

线宽是线的总宽度,以用户空间的单位表示。 线跨越路径,两边各占总宽度的一半。

The line join specifies how Quartz draws the junction between connected line segments. Quartz supports the line join styles described in Table 3-2. The default style is miter join.

线连接指定Quartz如何绘制连接的线段之间的连接。 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.

The line cap specifies the method used by CGContextStrokePath to draw the endpoint of the line. Quartz supports the line cap styles described in Table 3-3. The default style is butt cap.

线帽指定CGContextStrokePath用于绘制线的端点的方法。 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 [图片上传失败...(image-2dd4f-1534606000681)] 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 [图片上传失败...(image-f45303-1534606000681)] Quartz extends the stroke beyond the endpoint of the path for a distance equal to half the line width. The extension is squared off.

A closed subpath treats the starting point as a junction between connected line segments; the starting point is rendered using the selected line-join method. In contrast, if you close the path by adding a line segment that connects to the starting point, both ends of the path are drawn using the selected line-cap method.

在封闭的子路径中,起始点被视为线段之间的连接点,它使用所选的线连接方法渲染起点。 相比之下,如果连接起点和端点形成直线来关闭路径,则使用所选线帽法绘制路径的两端。

A line dash pattern allows you to draw a segmented line along the stroked path. You control the size and placement of dash segments along the line by specifying the dash array and the dash phase as parameters to CGContextSetLineDash:

void CGContextSetLineDash (
    CGContextRef ctx,
    CGFloat phase,
    const CGFloat lengths[],
    size_t count
);

虚线允许您沿着描边路径绘制虚线。 您可以通过将虚线数组和虚线相位指定为CGContextSetLineDash的参数来控制虚线段的大小和位置:

void CGContextSetLineDash (
    CGContextRef ctx,
    CGFloat phase,
    const CGFloat lengths[],
    size_t count
);

The elements of the lengths parameter specify the widths of the dashes, alternating between the painted and unpainted segments of the line. The phase parameter specifies the starting point of the dash pattern. Figure 3-11 shows some line dash patterns.

长度参数的元素指定破折号的宽度,在线的绘制和未上漆段之间交替。 相位参数指定破折号模式的起始点。 图3-11显示了一些线条划线模式。

Figure 3-11 Examples of line dash patterns

The stroke color space determines how the stroke color values are interpreted by Quartz. You can also specify a Quartz color (CGColorRef data type) that encapsulates both color and color space. For more information on setting color space and color, see Color and Color Spaces.

笔画颜色空间决定了Quartz如何解释笔画颜色值。您还可以指定封装颜色和颜色空间的Quartz颜色(CGColorRef数据类型)。有关设置颜色空间和颜色的更多信息,请参阅颜色和颜色空间。

(2).Functions for Stroking a Path(描边函数)

Quartz provides the functions shown in Table 3-4 for stroking the current path. Some are convenience functions for stroking rectangles or ellipses.

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.

The function CGContextStrokeLineSegments is equivalent to the following code:

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);

When you call CGContextStrokeLineSegments, you specify the line segments as an array of points, organized as pairs. Each pair consists of the starting point of a line segment followed by the ending point of a line segment. For example, the first point in the array specifies the starting position of the first line, the second point specifies the ending position of the first line, the third point specifies the starting position of the second line, and so forth.

当您调用CGContextStrokeLineSegments时,可以将线段指定为一组数组,以组合方式组织。 每一对由线段的起始点,后跟一个线段的终点组成。 例如,数组中的第一个点指定第一行的起始位置,第二个点指定第一行的结束位置,第三个点指定第二行的起始位置,等等。

(3).Filling a Path(填充路径)

When you fill the current path, Quartz acts as if each subpath contained in the path were closed. It then uses these closed subpaths and calculates the pixels to fill. There are two ways Quartz can calculate the fill area. Simple paths such as ovals and rectangles have a well-defined area. But if your path is composed of overlapping segments or if the path includes multiple subpaths, such as the concentric circles shown in Figure 3-12, there are two rules you can use to determine the fill area.

当填充当前路径时,Quartz的行为就像路径中包含的每个子路径都被关闭一样。 然后使用这些封闭的子路径并计算要填充的像素。 Quartz可以通过两种方式计算填充区域。 诸如椭圆形和矩形的简单路径具有明确的区域。 但是,如果您的路径由重叠段组成,或者如果路径包含多个子路径,例如图3-12所示的同心圆,则可以使用两个规则来确定填充区域。

The default fill rule is called the nonzero winding number rule. To determine whether a specific point should be painted, start at the point and draw a line beyond the bounds of the drawing. Starting with a count of 0, add 1 to the count every time a path segment crosses the line from left to right, and subtract 1 every time a path segment crosses the line from right to left. If the result is 0, the point is not painted. Otherwise, the point is painted. The direction that the path segments are drawn affects the outcome. Figure 3-12 shows two sets of inner and outer circles that are filled using the nonzero winding number rule. When each circle is drawn in the same direction, both circles are filled. When the circles are drawn in opposite directions, the inner circle is not filled.

默认填充规则称为非零绕组数规则。要确定是否应绘制特定点,请从该点开始,并绘制一条超出图形边界的线。从0开始,每次路径段从左到右跨越线时,将1加1,每次路径段从右到左跨越时,减1。如果结果为0,则不绘制点。否则,点被画。绘制路径段的方向影响结果。图3-12显示了使用非零绕组数量规则填充的两组内圈和外圈。当每个圆圈以相同方向绘制时,两个圆圈都被填充。当圆圈以相反方向绘制时,内圈未被填充。

You can opt to use the even-odd rule. To determine whether a specific point should be painted, start at the point and draw a line beyond the bounds of the drawing. Count the number of path segments that the line crosses. If the result is odd, the point is painted. If the result is even, the point is not painted. The direction that the path segments are drawn doesn’t affect the outcome. As you can see in Figure 3-12, it doesn’t matter which direction each circle is drawn, the fill will always be as shown.

您可以选择使用偶数规则。要确定是否应绘制特定点,请从该点开始,并绘制一条超出图形边界的线。计算行跨越的路径段数。如果结果是奇数,则绘制点。如果结果是均匀的,点不画。绘制路径段的方向不影响结果。如图3-12所示,绘制每个圆的方向并不影响绘制结果,填充将始终如图所示。

Figure 3-12 Concentric circles filled using different fill rules

Quartz provides the functions shown in Table 3-5 for filling the current path. Some are convenience functions for stroking rectangles or ellipses.
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.
(4).Setting Blend Modes(设置混合模式)

Blend modes specify how Quartz applies paint over a background. Quartz uses normal blend mode by default, which combines the foreground painting with the background painting using the following formula:
result = (alpha * foreground) + (1 - alpha) * background

混合模式指定Quartz如何将绘图绘制在背景上。 Quartz默认使用普通混合模式,它使用以下公式将前景绘画与背景绘画相结合:
result = (alpha * foreground) + (1 - alpha) * background

Color and Color Spaces provides a detailed discussion of the alpha component of a color, which specifies the opacity of a color. For the examples in this section, you can assume a color is completely opaque (alpha value = 1.0). For opaque colors, when you paint using normal blend mode, anything you paint over the background completely obscures the background.

颜色和颜色空间提供了颜色的alpha分量的详细讨论,它指定了颜色的不透明度。 对于本节中的示例,您可以假定颜色完全不透明(alpha值= 1.0)。 对于不透明的颜色,当您使用普通混合模式进行绘制时,所有绘制在背景之上的内容都会遮挡住背景。

You can set the blend mode to achieve a variety of effects by calling the function CGContextSetBlendMode, passing the appropriate blend mode constant. Keep in mind that the blend mode is part of the graphics state. If you use the function CGContextSaveGState prior to changing the blend mode, then calling the function CGContextRestoreGState resets the blend mode to normal.

您可以通过调用函数CGContextSetBlendMode来设置混合模式以实现各种效果,传递适当的混合模式常量。 请记住,混合模式是图形状态的一部分。 如果在更改混合模式之前使用函数CGContextSaveGState,则调用函数CGContextRestoreGState会将混合模式重置为正常。

The rest of this section show the results of painting the rectangles shown in Figure 3-13 over the rectangles shown in Figure 3-14. In each case (Figure 3-15 through Figure 3-30), the background rectangles are painted using normal blend mode. Then the blend mode is changed by calling the function CGContextSetBlendMode with the appropriate constant. Finally, the foreground rectangles are painted.

本节的其余部分显示了如图3-14所示的矩形绘画的结果,如图3-14所示。在每种情况下(图3-15至图3-30),使用正常混合模式绘制背景矩形。然后通过使用适当的常量调用函数CGContextSetBlendMode来更改混合模式。最后,绘制前景矩形。

Figure 3-13 The rectangles painted in the foreground

[图片上传失败...(image-f37547-1534606000681)]

Note: You can also use blend modes to composite two images or to composite an image over any content that’s already drawn to the graphics context. Using Blend Modes with Images provides information on how to use blend modes to composite images and shows the results of applying blend modes to two images.

注意:您还可以使用混合模式复合两个图像,或者将图像复合到已经绘制到图形上下文的任何内容上。使用混合模式与图像提供有关如何使用混合模式合成图像的信息,并显示将混合模式应用于两个图像的结果。

Blend Mode Sample
1.Normal Blend Mode [图片上传失败...(image-fe43f5-1534606000681)]
2.Multiply Blend Mode Figure 3-16 Rectangles painted using multiply blend mode
3.Screen Blend Mode Figure 3-17 Rectangles painted using screen blend mode
4.Overlay Blend Mode Figure 3-18 Rectangles painted using overlay blend mode
5.Darken Blend Mode Figure 3-19 Rectangles painted using darken blend mode
6.Lighten Blend Mode Figure 3-20 Rectangles painted using lighten blend mode
7.Color Dodge Blend Mode Figure 3-21 Rectangles painted using color dodge blend mode
8.Color Burn Blend Mode [图片上传失败...(image-39a36f-1534606000681)]
9.Soft Light Blend Mode Figure 3-23 Rectangles painted using soft light blend mode
10.Hard Light Blend Mode [图片上传失败...(image-24270f-1534606000681)]
11.Difference Blend Mode [图片上传失败...(image-4a40bf-1534606000681)]
12.Exclusion Blend Mode Figure 3-26 Rectangles painted using exclusion blend mode
13.Hue Blend Mode Figure 3-27 Rectangles painted using hue blend mode
14.Saturation Blend Mode Figure 3-28 Rectangles painted using saturation blend mode
15.Color Blend Mode [图片上传失败...(image-662538-1534606000681)]
16.Luminosity Blend Mode Figure 3-30 Rectangles painted using luminosity blend mode

5.Clipping to a Path(剪裁路径)

The current clipping area is created from a path that serves as a mask, allowing you to block out the part of the page that you don’t want to paint. For example, if you have a very large bitmap image and want to show only a small portion of it, you could set the clipping area to display only the portion you want to show.

当前的裁剪区域是从一个作为遮照的路径创建的,可以阻止您不想绘制的页面部分。 例如,如果您有一个非常大的位图图像,并且仅显示其一小部分,则可以将剪切区域设置为仅显示要显示的部分。

When you paint, Quartz renders paint only within the clipping area. Drawing that occurs inside the closed subpaths of the clipping area is visible; drawing that occurs outside the closed subpaths of the clipping area is not.

绘图时,Quartz只在剪裁区域内绘制。 在剪裁区域的封闭子路径内发生的绘图是可见的; 在剪裁区域的封闭子路径之外的绘图是不可见的。

When the graphics context is initially created, the clipping area includes all of the paintable area of the context (for example, the media box of a PDF context). You alter the clipping area by setting the current path and then using a clipping function instead of a drawing function. The clipping function intersects the filled area of the current path with the existing clipping area. Thus, you can intersect the clipping area, shrinking the visible area of the picture, but you cannot increase the area of the clipping area.

当最初创建图形上下文时,剪切区域包括上下文的所有可绘制区域(例如,PDF上下文的媒体框)。您通过设置当前路径,然后使用剪切功能而不是绘图功能来更改裁剪区域。剪切功能与当前路径的填充区域与现有剪切区域相交。因此,您可以与裁剪区域相交,缩小图片的可见区域,但不能增加裁剪区域的面积。

The clipping area is part of the graphics state. To restore the clipping area to a previous state, you can save the graphics state before you clip, and restore the graphics state after you’re done with clipped drawing.

裁剪区域是图形状态的一部分。要将裁剪区域还原到以前的状态,可以在剪辑之前保存图形状态,并在完成剪切绘制后恢复图形状态。

Listing 3-1 shows a code fragment that sets up a clipping area in the shape of a circle. This code causes drawing to be clipped, similar to what’s shown in Figure 3-3. (For another example, 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

代码例子:

    CGContextRef content = UIGraphicsGetCurrentContext();
    // ********************** Paths *******************
    //1. 创建路径
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, 25, 25);
    CGPathAddArc(path, NULL, 25, 25, 50, 0, M_PI_2, NO);
    CGPathCloseSubpath(path);  // 关闭路径-弧线和曲线无法闭合路径需要调用-CGPathCloseSubpath
    CGPathAddRect(path, nil, CGRectMake(100, 10, 100, 100));
    CGPathAddRect(path, nil, CGRectMake(10, 100, 100, 100));
    CGContextAddPath(content, path); // 添加到当前上下文

    //2. 设置描边参数
    CGFloat lengths[] = {3,1};
    CGContextSetFillColorWithColor(content, [UIColor greenColor].CGColor); // 填充颜色
    CGContextSetRGBStrokeColor(content, 1, 1, 0, 1); // 描边颜色
    CGContextSetLineWidth(content, 2);               // 描边宽度
    CGContextSetLineCap(content, kCGLineCapRound);   // 描边线帽
    CGContextSetLineJoin(content, kCGLineJoinMiter); // 描边连接
    CGContextSetLineDash(content, 0, lengths, 2);    // 描边虚线

    //3. 设置混合模式
    CGContextSetBlendMode(content, kCGBlendModeNormal);

    //4. 绘制路径
    CGContextStrokePath(content);   // 描边路径
//    CGContextFillPath(content);     // 填充路径
//    CGContextDrawPath(content, kCGPathFillStroke); // 设置填充模式,绘制路径
```![logo.PNG](https://img.haomeiwen.com/i1956008/25af5711e8a7266e.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
上一篇下一篇

猜你喜欢

热点阅读