I. Introduction of BASIC knowledge
1. Characters (Character) and glyphs (Glyphs)
An important process of text display in a typesetting system is the conversion of a character to a glyph, which is the element of the information itself, and the glyph is a graphical representation of the character, and other representations such as pronunciation. Characters in a computer are actually a code, a character set of encoding, such as the Unicode character set, the majority of the existence of the characters. And the glyph is a graphic, usually stored in a font file, the glyph also has its encoding, that is, its index in the font. One character can correspond to multiple glyphs (different fonts, or different styles of the same font: bold Italic, and so on); multiple characters may also correspond to a glyph, such as the ligatures (ligatures) of the character.
Roman ligatures
Here's a look at the various parameters of the glyph, the so-called glyph metric glyph Metrics
- Bounding box (border bbox), this is an imaginary frame, which is loaded into glyphs as tightly as possible.
- Baseline (baseline), an imaginary line, a line of glyphs are used as a reference to the upper and lower positions, there is a point to the left of this line is called the origin of the baseline,
- Ascent (upstream height) the distance from the origin to the top of the font (where the advanced is the baseline as the reference line), and ascent is a positive
- Descent (downlink height) The distance from the origin to the bottom of the deepest glyph in the font, descent is a negative value (such as the distance from the bottom of a font origin to the deepest glyph is 2, then the descent is-2)
- Linegap (line spacing), Linegap can also be called leading (in fact, it should be called external leading), row height lineheight can be ascent + |descent| + Linegap to calculate.
Some metrics expertise can also refer to the free type document Glyph metrics, in fact, iOS is using the free type library for font rendering.
2. Coordinate system
The first thing to say is that the coordinate system in Apple programming is a lot of tricks and often surprises developers. The original point of the coordinate system in the traditional Mac is in the lower-left corner, such as the nsview default coordinate system, where the origin is in the lower left corner. But some of the Mac's view is for the convenience of its implementation to transform the origin to the upper-left corner, like Nstableview coordinate system coordinates origin is in the upper left corner. IOS Uikit The UIView coordinate system origin in the upper-left corner.
At the bottom, the context of the Core graphics uses the coordinate system's origin in the lower-left corner. In iOS, the underlying interface is drawn through the core graphics, so how does the coordinate series change? In the DrawRect method of UIView, we can get the current graphics Context through Uigraphicsgetcurrentcontext (). Before the DrawRect method is called, the graphics context is created and configured, so you just use it. If you are careful, you can see that the value returned by CGCONTEXTGETCTM (Cgcontextref c) is not cgaffinetransformidentity by printing it to see that the value is
Printing description of CONTEXTCTM: (cgaffinetransform) CONTEXTCTM = { A = 1 b = 0 c = 0 d =-1 TX = 0 ty = 460 }
This is the result of non-retina resolution, if it is the value of the a,d,ty above the retina will multiply by 2, if the value of the iphone 5,ty will be larger. But the function is the same is the context space coordinate system flip, so that the original left lower point to the upper left corner, the y-axis is also transformed into a downward direction.
It said a lot, the following into the topic, the Core text is located in the desktop layout system, using the traditional origin in the lower left-hand coordinate system, so it is drawn in the text when the reference to the lower left corner of the origin of the drawing. But the context of iOS's UIView DrawRect method has been made a flip, and if you don't do anything, you'll see that the text is mirrored and upside down when you do a core text drawing directly on the context.
So first we need to flip the coordinate system and insert the code.
01.0,-1.0);
Next we implement a most basic and simple drawing, the code is as follows
- (void) DrawRect: (CGRect) rect{[Super Drawrect:rect]; //gets the current contextCgcontextref context =Uigraphicsgetcurrentcontext (); //Flip Coordinate systemCgcontextsettextmatrix (context, cgaffinetransformidentity); CGCONTEXTTRANSLATECTM (Context,0, Self.bounds.size.height); CGCONTEXTSCALECTM (Context,1.0, -1.0); //Draw PathCgmutablepathref Path =cgpathcreatemutable (); Cgpathaddrect (Path, NULL, self.bounds); //create a drawn string and Ctframensattributedstring *attstring = [[Nsattributedstring alloc] initwithstring:@"Hello Core Text world!"]; Ctframesetterref Framesetter=ctframesettercreatewithattributedstring ((cfattributedstringref) attstring); Ctframeref Frame=ctframesettercreateframe (Framesetter, Cfrangemake (0, [attstring length]), path, NULL); //DrawingCtframedraw (frame, context); //Freeing Memorycfrelease (frame); Cfrelease (path); Cfrelease (Framesetter);}
Implementation results:
Here to explain Ctframesetter and ctframe, first we look at two graphs, can help us to better understand the Coretext object model
Ctframe can be understood as a whole canvas consisting of many rows (Ctline), each consisting of one or more small squares (ctrun), and we do not need to create them ourselves ctrun,core Text will automatically create the Ctrun based on the properties of the nsattributedstring. Each Ctrun object corresponds to a different property, so you have the freedom to control the font, color, word spacing, and so on.
Ctframesetter is actually the Ctframe factory method, generated ctrrame by a given nsattributedstring, while the system automatically creates the Cttypesetter,cttypesetter is the class that manages your fonts.
So how do you use nsattributedstring? How to set the line height, font style, size?
The following lists the properties that can be set
ConstCfstringref Kctcharactershapeattributename; //The Font shape property must be the Cfnumberref object default to 0, and not 0 for the corresponding character shape definition, such as 1 for the traditional character shapeConstCfstringref Kctfontattributename; //the Font property must be a Ctfont objectConstCfstringref Kctkernattributename; //the character interval property must be a Cfnumberref objectConstCfstringref Kctligatureattributename; //sets whether to use the hyphenation property, set to 0, which means that the hyphenation attribute is not used. The standard English ligatures are FI,FL. The default value is 1, which is used as a standard ligature. That is, when you search for F, FL is treated as a literal. Must be cfnumberref default to 1, preferably 0,1,2ConstCfstringref Kctforegroundcolorattributename; //The font Color property must be a Cgcolor object, and the default is blackConstCfstringref Kctforegroundcolorfromcontextattributename; //the font Color property for the context must be cfbooleanref default to False,ConstCfstringref Kctparagraphstyleattributename; //Paragraph Style property must be Ctparagraphstyle object default to nilConstCfstringref Kctstrokewidthattributename; //Stroke line width must be Cfnumberref object, default 0.0f, 3.0f standardConstCfstringref Kctstrokecolorattributename; //the color property of the stroke must be a Cgcolorref object, the default is the foreground colorConstCfstringref Kctsuperscriptattributename; //Setting the font's Subscript property must be the Cfnumberref object defaults to 0, which is 1 for subscript, and 1 for superscript, requiring font support. Style Cn1 such as permutations and combinationsConstCfstringref Kctunderlinecolorattributename; //font Underline Color property must be a Cgcolorref object, default is foreground colorConstCfstringref Kctunderlinestyleattributename; //The font Underline style property must be a Cfnumberref object, and the default Kctunderlinestylenone can be modified by ctunderlinestyplemodifiers underline styleConstcfstringref Kctverticalformsattributename;//the Glyph Direction property of the text must be cfbooleanref default to False,false for horizontal orientation, true for vertical directionConstcfstringref Kctglyphinfoattributename;//font Information property must be a Ctglyphinfo objectConstcfstringref Kctrundelegateattributename//Ctrun The delegate property must be a Ctrundelegate object
For example, let's be clear.
- (void) DrawRect: (cgrect) rect {[Super Drawrect:rect]; //1.Cgcontextref context =Uigraphicsgetcurrentcontext (); //2. Catch and change coordinatesCgcontextsettextmatrix (context, cgaffinetransformidentity); CGCONTEXTTRANSLATECTM (Context,0, Self.bounds.size.height); CGCONTEXTSCALECTM (Context,1.0, -1.0); Nsmutableattributedstring*attristring = [[Nsmutableattributedstring alloc] initwithstring:@"This is test!"] ; //Change the font color of this to red[Attristring AddAttribute: (NSString *) Kctforegroundcolorattributename value: (ID) [Uicolor Redcolor]. Cgcolor Range:nsmakerange (0,4)]; //turn the is into green[Attristring AddAttribute: (NSString *) Kctforegroundcolorattributename value: (ID) [Uicolor Greencolor]. Cgcolor Range:nsmakerange (5,2)]; //Change the font of this, value must be a ctfontref[Attristring AddAttribute: (NSString *) Kctunderlinestyleattributename value: (ID) [NSNumber numberwithint:kctunderlinestyledouble] Range:nsmakerange (0,4)]; //underline this, value can be selected in the specified enumeration[Attristring AddAttribute: (NSString *) Kctunderlinestyleattributename value: (ID) [NSNumber numberwithint:kctunderlinestyledouble] Range:nsmakerange (0,4)]; //Draw PathCgmutablepathref Path =cgpathcreatemutable (); Cgpathaddrect (Path, NULL, self.bounds); //create a drawn string and CtframeCtframesetterref Framesetter =ctframesettercreatewithattributedstring ((cfattributedstringref) attristring); Ctframeref Frame=ctframesettercreateframe (Framesetter, Cfrangemake (0, [attristring length]), path, NULL); //DrawingCtframedraw (frame, context); //Freeing Memorycfrelease (frame); Cfrelease (path); Cfrelease (Framesetter); }
The effect is as follows
The simple custom drawing is done here.
First knowledge of Coretext