How to draw context stacks and matrices using quartz2d in IOS development _ios

Source: Internet
Author: User

Context Stacks

How does qurza2d draw the drawing information and drawing properties into the graphics context?

Description

Creates a new project, customizes a view class and storyboard association, and overrides the Drowrect method in the class.
Three steps to draw a line:
(1) Getting context
(2) Drawing
(3) Rendering
Requirements: Draw two separate lines
Code and Effect diagram:

Copy Code code as follows:

-(void) DrawRect: (cgrect) rect
{
Get context
Cgcontextref Ctx=uigraphicsgetcurrentcontext ();
Drawing
First line
Cgcontextmovetopoint (CTX, 20, 100);
Cgcontextaddlinetopoint (CTX, 100, 320);

Second line
Cgcontextmovetopoint (CTX, 40, 200);
Cgcontextaddlinetopoint (CTX, 80, 100);
Rendering
Cgcontextstrokepath (CTX);

}


Effect Chart:

Set the width of the segment: Two ends are rounded, color, etc.
Code and renderings (found that the second line is also rendered as the style and state of the first line)

Copy Code code as follows:

-(void) DrawRect: (cgrect) rect
{
Get context
Cgcontextref Ctx=uigraphicsgetcurrentcontext ();
Drawing
First line
Cgcontextmovetopoint (CTX, 20, 100);
Cgcontextaddlinetopoint (CTX, 100, 320);

Set the state of the first line
Set the width of a line
Cgcontextsetlinewidth (CTX, 12);
Set the color of a line
[[Uicolor Browncolor]set];
To set the style at both ends of a line to rounded corners
Cgcontextsetlinecap (Ctx,kcglinecapround);
To render a line
Cgcontextstrokepath (CTX);

Second line
Cgcontextmovetopoint (CTX, 40, 200);
Cgcontextaddlinetopoint (CTX, 80, 100);
Rendering
Cgcontextstrokepath (CTX);

}


Effect Chart:

New requirements: To make the color of two lines different, ask the second line to become the original. To meet the above requirements, there are several ways to do this:

The first approach:
When the second line is set, empty its state

Copy Code code as follows:

-(void) DrawRect: (cgrect) rect
{
Get context
Cgcontextref Ctx=uigraphicsgetcurrentcontext ();
Drawing
First line
Cgcontextmovetopoint (CTX, 20, 100);
Cgcontextaddlinetopoint (CTX, 100, 320);

Set the state of the first line
Set the width of a line
Cgcontextsetlinewidth (CTX, 12);
Set the color of a line
[[Uicolor Browncolor]set];
To set the style at both ends of a line to rounded corners
Cgcontextsetlinecap (Ctx,kcglinecapround);
To render a line
Cgcontextstrokepath (CTX);

Second line
Cgcontextmovetopoint (CTX, 40, 200);
Cgcontextaddlinetopoint (CTX, 80, 100);

Empty status
Cgcontextsetlinewidth (CTX, 1);
[[Uicolor Blackcolor]set];
Cgcontextsetlinecap (Ctx,kcglinecapbutt);

Rendering
Cgcontextstrokepath (CTX);

}


The second approach:
The first line from the start to the rendering of the code to cut to the second line after the rendering is finished, so that the first drawing and rendering a line, the line does not set the drawing information, the display of the second line to the system default effect.

Copy Code code as follows:

-(void) DrawRect: (cgrect) rect
{
Get context
Cgcontextref Ctx=uigraphicsgetcurrentcontext ();
Drawing

Second line
Cgcontextmovetopoint (CTX, 40, 200);
Cgcontextaddlinetopoint (CTX, 80, 100);

Empty status
Cgcontextsetlinewidth (CTX, 1);
[[Uicolor Blackcolor]set];

Cgcontextsetlinecap (Ctx,kcglinecapbutt);

Rendering
Cgcontextstrokepath (CTX);

First line
Cgcontextmovetopoint (CTX, 20, 100);
Cgcontextaddlinetopoint (CTX, 100, 320);

Set the state of the first line
Set the width of a line
Cgcontextsetlinewidth (CTX, 12);
Set the color of a line
[[Uicolor Browncolor]set];
To set the style at both ends of a line to rounded corners
Cgcontextsetlinecap (Ctx,kcglinecapround);
To render a line
Cgcontextstrokepath (CTX);
}


The results are the same in both ways:

However, in some cases, you must first draw the first line and then draw the second line, requiring the cross section, the second line to cover the top of the first line. If this is the case, then only use the first approach, but if there are new requirements, the requirement to draw two lines on this basis, it needs to clear the state of the CTX many times, very troublesome. To solve this problem, we introduce the graphics context stack below.

Second, the complete process of drawing
The program starts, displaying the custom view. When the program first appears in front of us, the program calls the DrawRect: method, gets the graphics context (in memory), and then saves the drawing information using the graphics context, which is understood as having a region in the graphics context to hold the drawing information. There is an area for saving the state of the drawing (line width, fillet, color). The line is not drawn directly to the view, it can be understood that there is a separate area in the graphics context to draw the graph first, and when the rendering method is invoked, the plotted graph is displayed to view.

In the drawing area, you save the drawing status area to find the corresponding state information (line width, fillet, color), and then draw the first line in the drawing area to complete. In fact, before rendering, the line has been drawn in the drawing area.
As shown in figure:

Description: These schematics and the program code block in this article, do not have one by one correspondence, just to illustrate the complete process of drawing.
When you invoke the rendering method, the drawing area has been drawn directly to the view, which is what we see.
As shown in figure:

When you draw the second article, if you do not reset the state of the drawing, you can find that the drawing state you used when you drew the first antenna is also saved in the graphics context, and the second line is set according to the first line (the previous drawing state) before the second line is rendered. After rendering, the second line is displayed to the screen.
Reference code:

Copy Code code as follows:

-(void) DrawRect: (cgrect) rect
{
Get context
Cgcontextref Ctx=uigraphicsgetcurrentcontext ();
Drawing
First line
Cgcontextmovetopoint (CTX, 20, 100);
Cgcontextaddlinetopoint (CTX, 100, 320);

Set the state of the first line
Set the width of a line
Cgcontextsetlinewidth (CTX, 12);
Set the color of a line
[[Uicolor Browncolor]set];
To set the style at both ends of a line to rounded corners
Cgcontextsetlinecap (Ctx,kcglinecapround);
To render a line
Cgcontextstrokepath (CTX);

Second line
Cgcontextmovetopoint (CTX, 40, 200);
Cgcontextaddlinetopoint (CTX, 80, 100);
Rendering
Cgcontextstrokepath (CTX);
}


If the state is cleared, before rendering, the second line is drawn in the drawing area to find the current drawing information (has changed--emptied), draw the second line based on the drawing information, and invoke the rendering method to display the second line to the view.
Reference code:

Copy Code code as follows:

-(void) DrawRect: (cgrect) rect
{
Get context
Cgcontextref Ctx=uigraphicsgetcurrentcontext ();
Drawing
First line
Cgcontextmovetopoint (CTX, 20, 100);
Cgcontextaddlinetopoint (CTX, 100, 320);

Set the state of the first line
Set the width of a line
Cgcontextsetlinewidth (CTX, 12);
Set the color of a line
[[Uicolor Browncolor]set];
To set the style at both ends of a line to rounded corners
Cgcontextsetlinecap (Ctx,kcglinecapround);
To render a line
Cgcontextstrokepath (CTX);

Second line
Cgcontextmovetopoint (CTX, 40, 200);
Cgcontextaddlinetopoint (CTX, 80, 100);

Empty status
Cgcontextsetlinewidth (CTX, 1);
[[Uicolor Blackcolor]set];
Cgcontextsetlinecap (Ctx,kcglinecapbutt);

Rendering
Cgcontextstrokepath (CTX);
}

Third, the graphics context stack
1. Simple description
After acquiring the graphics context, through Cgcontextsavegstate (CTX); method to copy the currently acquired context and save a copy of the most pure graphics context.
Before drawing the second line, use the Cgcontextrestoregstate (CTX) method to restore the purest graphics context that was saved at the beginning.
Code:

Copy Code code as follows:

-(void) DrawRect: (cgrect) rect
{
Get context
Cgcontextref Ctx=uigraphicsgetcurrentcontext ();
Save a copy of the original graphics context
Cgcontextsavegstate (CTX);

Drawing
First line
Cgcontextmovetopoint (CTX, 20, 100);
Cgcontextaddlinetopoint (CTX, 100, 320);

Set the state of the first line
Set the width of a line
Cgcontextsetlinewidth (CTX, 12);
Set the color of a line
[[Uicolor Browncolor]set];
To set the style at both ends of a line to rounded corners
Cgcontextsetlinecap (Ctx,kcglinecapround);
To render a line
Cgcontextstrokepath (CTX);

The purest graphic context that was saved at the beginning of the restore
Cgcontextrestoregstate (CTX);
Second line
Cgcontextmovetopoint (CTX, 40, 200);
Cgcontextaddlinetopoint (CTX, 80, 100);

Empty status
Cgcontextsetlinewidth (CTX, 1);
[[Uicolor Blackcolor]set];
Cgcontextsetlinecap (Ctx,kcglinecapbutt);

Rendering
Cgcontextstrokepath (CTX);
}

2. Graphics context stack mechanism
When you draw the first line, a copy of the current graphics context is saved to the graphics context stack.

When drawing the second line, go to the graphics context stack to take out the top of the stack of drawing information, as the second line of state information, the second line of state information is based on the original saved the graphics context to draw.

Note: Save a few times in the stack, then you can take several times (such as can not save 1 times, take two times, in the second time, the stack is empty will be directly hung out).

Matrix operations
first, about matrix operation
1. Draw a quadrilateral
Completes a quadrilateral drawing by setting two endpoints (long and wide).
Code:

Copy Code code as follows:

-(void) DrawRect: (cgrect) rect
{
Draw Quadrilateral
Get Graphics context
Cgcontextref Ctx=uigraphicsgetcurrentcontext ();
Drawing
Cgcontextaddrect (CTX, CGRectMake (20, 50, 100, 100));
Rendering
Cgcontextstrokepath (CTX);
}


Description: Drawing a rectangle in this way has a weakness: the drawn rectangle is always positive. The following figure:

2. Draw a crooked quadrilateral
How do I draw a crooked rectangle? (done by matrix operation, similar to deformation operation)
You can deform (rotate, scale, pan) the things you draw by using matrix manipulation.
Methods: CGCONTEXTROTATECTM (< #CGContextRef C#>, < #CGFloat angle#>) should accept two parameters (graphics context, radians)
Note: Setting the matrix operation must be done before the graphic is added, if it is set after the graphic is added, it is not valid.
Code:

Copy Code code as follows:

-(void) DrawRect: (cgrect) rect
{
Draw Quadrilateral
Get Graphics context
Cgcontextref Ctx=uigraphicsgetcurrentcontext ();
Matrix operations
Note: Setting the matrix operation must precede the addition of the drawing information
Rotate 45 degrees
CGCONTEXTROTATECTM (CTX, m_pi_4);

Drawing
Cgcontextaddrect (CTX, CGRectMake (150, 100, 100, 100));
Rendering
Cgcontextstrokepath (CTX);
}


Effect:

Second, about rotation
1. Rotate Demo
View is able to display views because it has layer on it, and future graphics are rendered to layer.
And, when the rotation is the whole layer are rotated, you can draw a circle to verify.
Code 1 (not rotated):

Copy Code code as follows:

-(void) DrawRect: (cgrect) rect
{
Get Graphics context
Cgcontextref Ctx=uigraphicsgetcurrentcontext ();
Matrix operations
Note: Setting the matrix operation must precede the addition of the drawing information
Rotate 45 degrees
CGCONTEXTROTATECTM (CTX, m_pi_4);

Drawing
Draw Quadrilateral
Cgcontextaddrect (CTX, CGRectMake (150, 100, 100, 100));
Draw a Circle
Cgcontextaddellipseinrect (CTX, CGRectMake (200, 200, 50, 50));
Rendering
Cgcontextstrokepath (CTX);
}


Effect:

Code 2 (Rotate):

Copy Code code as follows:

-(void) DrawRect: (cgrect) rect
{
Get Graphics context
Cgcontextref Ctx=uigraphicsgetcurrentcontext ();
Matrix operations
Note: Setting the matrix operation must precede the addition of the drawing information
Rotate 45 degrees
CGCONTEXTROTATECTM (CTX, m_pi_4);

Drawing
Draw Quadrilateral
Cgcontextaddrect (CTX, CGRectMake (150, 100, 100, 100));
Draw a Circle
Cgcontextaddellipseinrect (CTX, CGRectMake (200, 200, 50, 50));
Rendering
Cgcontextstrokepath (CTX);
}


Effect:

2. Supplementary note on rotation
Tip: When rotating, the whole layer is rotated.

Third, scaling
Methods: CGCONTEXTSCALECTM (< #CGContextRef c#> < #CGFloat sx#> < #CGFloat sy#>)
The method receives three parameters (the graphics context, the scaling in the x direction, and the scaling in the Y direction).
code example:

Copy Code code as follows:

-(void) DrawRect: (cgrect) rect
{
Get Graphics context
Cgcontextref Ctx=uigraphicsgetcurrentcontext ();
Matrix operations
Note: Setting the matrix operation must precede the addition of the drawing information
Zoom, X-direction scaling 0.5 times times, y-direction scaling 1.5 times times
CGCONTEXTSCALECTM (CTX, 0.5, 1.5);

Drawing
Draw Quadrilateral
Cgcontextaddrect (CTX, CGRectMake (150, 100, 100, 100));
Draw a Circle
Cgcontextaddellipseinrect (CTX, CGRectMake (200, 200, 50, 50));
Rendering
Cgcontextstrokepath (CTX);
}


Effect:

Four, translation
Methods: CGCONTEXTTRANSLATECTM (< #CGContextRef c#> < #CGFloat tx#> < #CGFloat ty#>)
The method receives three parameters (graphics context, offset in the x direction, offset in the y direction)
code example:

Copy Code code as follows:

-(void) DrawRect: (cgrect) rect
{
Get Graphics context
Cgcontextref Ctx=uigraphicsgetcurrentcontext ();
Matrix operations
Note: Setting the matrix operation must precede the addition of the drawing information
Pan, x direction move 50,y Direction 100
CGCONTEXTTRANSLATECTM (CTX, 50, 100);

Drawing
Draw Quadrilateral
Cgcontextaddrect (CTX, CGRectMake (150, 100, 100, 100));
Draw a Circle
Cgcontextaddellipseinrect (CTX, CGRectMake (200, 200, 50, 50));
Rendering
Cgcontextstrokepath (CTX);
}


Effect:

Tip: The origin of the coordinate is the upper-left corner of the view.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.