现在的位置: 首页 > 综合 > 正文

Iphone 画图层

2019年11月24日 ⁄ 综合 ⁄ 共 7208字 ⁄ 字号 评论关闭

Example: Using Multiple CGLayer objects to Draw a Flag

This section shows how to use two CGLayer objects to draw the flag shown in Figure 12-5
onscreen. First you’ll see how to reduce the flag to simple drawing
primitives, then you’ll look at the code needed to accomplish the
drawing.

Figure 12-5  
The result of using layers to draw the United States flag

The result of using layers to draw the United States flag

From the perspective of drawing it onscreen, the flag has three parts:

  • A
    pattern of red and white stripes. You can reduce the pattern to a
    single red stripe because, for onscreen drawing, you can assume a white
    background. You create a single red rectangle, then repeatedly draw the
    rectangle at various offsets to create the seven red stripes necessary
    for the U.S. flag. A CGLayer is ideal for repeated drawing. You draw
    the red rectangle to a CGLayer, then draw the CGLayer onscreen seven
    times.

  • A blue rectangle. You need the blue
    rectangle once, so using a CGLayer is of no benefit. When it comes time
    to draw the blue rectangle, draw it directly onscreen.

  • A
    pattern of 50 white stars. Like the red stripe, a CGLayer is ideal for
    drawing the stars. You create a path that outlines a star shape, and
    then fill the path with white. Draw one star to a CGLayer, then draw
    the layer 50 times, adjusting the offset each time to get the
    appropriate spacing.

The code in “Code that uses layers to draw a flag”
produces the output shown in Figure 12-5
.
A detailed explanation for each numbered line of code appears following
the listing. The listing is rather long, so you might want to print the
explanation so that you can read it as you look at the code. The myDrawFlag
routine is called from within a Cocoa or Carbon application. The
application passes a window graphics context and a rectangle that
specifies the size of the view associated with the window graphics
context.


Note:
 Before
you call this or any routine that uses CGLayer objects, you must check
to make sure that the system is running Mac OS X v10.4 or later and has
a graphics card that supports using CGLayer objects.


Listing 12-1  
Code that uses layers to draw a flag

void myDrawFlag (CGContextRef context, CGRect* contextRect)
{
    int          i, j,
                 num_six_star_rows = 5,
                 num_five_star_rows = 4;
    float        start_x = 5.0,// 1
                 start_y = 108.0,// 2
                 red_stripe_spacing = 34.0,// 3
                 h_spacing = 26.0,// 4
                 v_spacing = 22.0;// 5
    CGContextRef myLayerContext1,
                 myLayerContext2;
    CGLayerRef   stripeLayer,
                 starLayer;
    CGRect       myBoundingBox,// 6
                 stripeRect,
                 starField;
 // ***** Setting up the primitives *****
    const CGPoint myStarPoints[] = {{ 5, 5},   {10, 15},// 7
                                    {10, 15},  {15, 5},
                                    {15, 5},   {2.5, 11},
                                    {2.5, 11}, {16.5, 11},
                                    {16.5, 11},{5, 5}};
 
    stripeRect  = CGRectMake (0, 0, 400, 17); // stripe// 8
    starField  =  CGRectMake (0, 102, 160, 119); // star field// 9
 
    myBoundingBox = CGRectMake (0, 0, contextRect->size.width, // 10
                                      contextRect->size.height);
 
     // ***** Creating layers and drawing to them *****
    stripeLayer = CGLayerCreateWithContext (context, // 11
                            stripeRect.size, NULL);
    myLayerContext1 = CGLayerGetContext (stripeLayer);// 12
 
    CGContextSetRGBFillColor (myLayerContext1, 1, 0 , 0, 1);// 13
    CGContextFillRect (myLayerContext1, stripeRect);// 14
 
    starLayer = CGLayerCreateWithContext (context,
                            starField.size, NULL);// 15
    myLayerContext2 = CGLayerGetContext (starLayer);// 16
    CGContextSetRGBFillColor (myLayerContext2, 1.0, 1.0, 1.0, 1);// 17
    CGContextAddLines (myLayerContext2, myStarPoints, 10);// 18
    CGContextFillPath (myLayerContext2);    // 19
 
     // ***** Drawing to the window graphics context *****
    CGContextSaveGState(context);    // 20
    for (i=0; i< 7;  i++)   // 21
    {
        CGContextDrawLayerAtPoint (context, CGPointZero, stripeLayer);// 22
        CGContextTranslateCTM (context, 0.0, red_stripe_spacing);// 23
    }
    CGContextRestoreGState(context);// 24
 
    CGContextSetRGBFillColor (context, 0, 0, 0.329, 1.0);// 25
    CGContextFillRect (context, starField);// 26
 
    CGContextSaveGState (context);              // 27
    CGContextTranslateCTM (context, start_x, start_y);      // 28
    for (j=0; j< num_six_star_rows;  j++)   // 29
    {
        for (i=0; i< 6;  i++)
        {
            CGContextDrawLayerAtPoint (context,CGPointZero,
                                            starLayer);// 30
            CGContextTranslateCTM (context, h_spacing, 0);// 31
        }
        CGContextTranslateCTM (context, (-i*h_spacing), v_spacing); // 32
    }
    CGContextRestoreGState(context);
 
    CGContextSaveGState(context);
    CGContextTranslateCTM (context, start_x + h_spacing/2, // 33
                                 start_y + v_spacing/2);
    for (j=0; j< num_five_star_rows;  j++)  // 34
    {
        for (i=0; i< 5;  i++)
        {
        CGContextDrawLayerAtPoint (context, CGPointZero,
                            starLayer);// 35
            CGContextTranslateCTM (context, h_spacing, 0);// 36
        }
        CGContextTranslateCTM (context, (-i*h_spacing), v_spacing);
    }
    CGContextRestoreGState(context);
 
    CGLayerRelease(stripeLayer);// 37
    CGLayerRelease(starLayer);        // 38
}

Here’s what the code does:

  1. Declares a variable for the horizontal location of the first star.

  2. Declares a variable for the vertical location of the first star.

  3. Declares a variable for the spacing between the red stripes on the flag.

  4. Declares a variable for the horizontal spacing between the stars on the flag.

  5. Declares a variable for the vertical spacing between the stars on the flag.

  6. Declares rectangles that specify where to draw the flag to (bounding box), the stripe layer, and the star field.

  7. Declares an array of points that specify the lines that trace out one star.

  8. Creates a rectangle that is the shape of a single stripe.

  9. Creates a rectangle that is the shape of the star field.

  10. Creates a bounding box that is the same size as the window graphics context passed to the myDrawFlag
    routine.

  11. Creates a layer that is initialized with the window graphics context passed to the myDrawFlag
    routine.

  12. Gets the graphics context associated with that layer. You’ll use this layer for the stripe drawing.

  13. Sets the fill color to opaque red for the graphics context associated with the stripe layer.

  14. Fills a rectangle that represents one red stripe.

  15. Creates another layer that is initialized with the window graphics context passed to the myDrawFlag
    routine.

  16. Gets the graphics context associated with that layer. You’ll use this layer for the star drawing.

  17. Sets the fill color to opaque white for the graphics context associated with the star layer.

  18. Adds the 10 lines defined by the myStarPoints
    array to the context associated with the star layer.

  19. Fills the path, which consists of the 10 lines you just added.

  20. Saves
    the graphics state of the windows graphics context. You need to do
    this, because you’ll draw the same stripe repeatedly, but in different
    locations.

  21. Sets up a loop that iterates 7 times, once for each red stripe on the flag.

  22. Draws the stripe layer (which consists of a single red stripe).

  23. Translates
    the current transformation matrix so that the origin is positioned at
    the location where the next red stripe must be drawn.

  24. Restores the graphics state to what is was prior to drawing the stripes.

  25. Sets
    the fill color to the appropriate shade of blue for the star field.
    Note that this color has an opacity of 1.0. Although all the colors in
    this example are opaque, they don’t need to be. You can create nice
    effects with layered drawing by using partially transparent colors.
    Recall that an alpha value of 0.0 specifies a transparent color.

  26. Fills
    the star field rectangle with blue. You draw this rectangle directly to
    the window graphics context. Don’t use layers if you are drawing
    something only once.

  27. Saves the graphics state for the window graphics context because you’ll be transforming the CTM to position the stars properly.

  28. Translates
    the CTM so that the origin lies in the star field, positioned for the
    first star (left side) in the first (bottom) row.

  29. This
    and the next for loop sets up the code to repeatedly draw the star
    layer so the five odd rows on the flag each contain six stars.

  30. Draws the star layer to the window graphics context. Recall that the star layer contains one white star.

  31. Positions the CTM so that the origin is moved to the right in preparation for drawing the next star.

  32. Positions the CTM so that the origin is moved upward in preparation for drawing the next row of stars.

  33. Translates
    the CTM so that the origin lies in the star field, positioned for the
    first star (left side) in the second row from the bottom. Note that the
    even rows are offset with respect to the odd rows.

  34. This
    and the next for loop sets up the code to repeatedly draw the star
    layer so the four even rows on the flag each contain five stars.

  35. Draws the star layer to the window graphics context.

  36. Positions the CTM so that the origin is moved to the right in preparation for drawing the next star.

  37. Releases the stripe layer.

  38. Releases the star layer.

抱歉!评论已关闭.