IOS reader practice series (1) coretext plain text typographical basics, ioscoretext

Source: Internet
Author: User

IOS reader practice series (1) coretext plain text typographical basics, ioscoretext

I have previously made an App for the company's reading class. Recently I have time to write the implementation process of the reading part for logic sorting, we plan to write a series of articles in the hope of involving as many aspects and details as possible. You are welcome to exchange, speak out, and make progress together.

Coretext is used for typographical reading. In this article, coretext is used to implement basic typographical functions.

For the implementation principle of coretext, you can view the document or other materials. Here we will not introduce it. We will only introduce how to apply coretext to implement a simple text layout function.

Because coretext is out-of-screen layout, that is, before the content is rendered to the screen, the layout of the content has been completed.

The general process of the typographical process is divided into steps:

1. the attribute string is obtained by raw text data and related configurations.

2. Get CTFramesetter from the attribute string

3. CTFrame is obtained by CTFramesetter and the drawing area.

4. render the CTFrame to the context of the view.

 

1. the attribute string is obtained by raw text data and related configurations.

The most important part of this section is to get related configurations, which may include text alignment, segment ending indent, and line height. The following are some related configuration attributes:

@ Interface CTFrameParserConfigure: NSObject @ property (nonatomic, assign) CGFloat frameWidth; @ property (nonatomic, assign) CGFloat frameHeight; // font property @ property (nonatomic, assign) CGFloat wordSpace; @ property (nonatomic, strong) UIColor * textColor; @ property (nonatomic, strong) NSString * fontName; @ property (nonatomic, assign) CGFloat fontSize; // paragraph attributes @ property (nonatomic, assign) CGFloat lineSpace; @ property (nonatomic, assign) CTTextAlignment textAlignment; // text alignment mode @ property (nonatomic, assign) CGFloat firstlineHeadIndent; // indent the first line of a field @ property (nonatomic, assign) CGFloat headIndent; // indent the entire left side of a segment @ property (nonatomic, assign) CGFloat tailIndent; // indent the end of a segment @ property (nonatomic, assign) CTLineBreakMode lineBreakMode; // line feed mode @ property (nonatomic, assign) CGFloat lineHeightMutiple; // The Row Height factor (its value indicates a multiple of the original Row Height) @ property (nonatomic, assign) CGFloat maxLineHeight; // maximum row height limit (0 indicates unlimited, non-negative, and the Row Height cannot exceed this value) @ property (nonatomic, assign) CGFloat minLineHeight; // minimum row height limit @ property (nonatomic, assign) CGFloat paragrap1_forespace; // The Spacing Before the segment (relative to the spacing added to the previous segment) @ property (nonatomic, assign) CGFloat paragraphAfterSpace; // The end spacing (the spacing relative to the next segment) @ property (nonatomic, assign) CTWritingDirection writeDirection; // The writing direction @ property (nonatomic, assign) CGFloat lineSpacingAdjustment; // The space in points added between lines within the paragraph (commonly known as leading ). @ end

Next, we will use these attributes to generate the configurations we need. After assigning values to these attributes based on our needs, we will use the following methods to get the configurations we need:

// Returns a set of all attributes of the text, including fonts and paragraphs.-(NSDictionary *) attributesWithConfig :( CTFrameParserConfigure *) config {// specifies the section attribute CGFloat lineSpacing = config. lineSpace; CGFloat firstLineIndent = config. firstlineHeadIndent; CGFloat lineIndent = config. headIndent; CGFloat tailIndent = config. tailIndent; CTLineBreakMode lineBreakMode = config. lineBreakMode; CGFloat lineHeightMutiple = config. lineHeightMutiple; CGFloat paragrap1_forespace = config. paragrapsponforespace; CGFloat paragraphAfterSpace = config. paragraphAfterSpace; CTWritingDirection writeDirect = config. writeDirection; CTTextAlignment textAlignment = config. response; const CFIndex kNumberOfSettings = 13; Response paragraphSettings [kNumberOfSettings] = {response, sizeof (CGFloat), & lineSpacing}, {response, sizeof (CGFloat), & lineSpacing }, {queue, sizeof (CGFloat), & lineSpacing}, {queue, sizeof (textAlignment), & textAlignment}, {queue, sizeof (firstLineIndent), & firstLineIndent}, {queue, sizeof (lineIndent), & lineIndent}, {region, sizeof (tailIndent), & tailIndent}, {region, sizeof (lineBreakMode), & lineBreakMode}, {region, sizeof (lineHeightMutiple), & lineHeightMutiple}, {queue, sizeof (lineHeightMutiple), & queue}, {queue, sizeof (paragrap1_forespace), & paragrap1_forespace}, {queue, sizeof (paragraphAfterSpace), & paragraphAfterSpace}, {signature, sizeof (writeDirect), & writeDirect},}; inclutheparagraphref = Signature (paragraphSettings, kNumberOfSettings ); /*** font attribute */CGFloat fontSize = config. fontSize; // use the postName after iOS10 // CTFontRef fontRef = CTFontCreateWithName (CFStringRef) config. fontName, fontSize, NULL); CTFontRef fontRef = forward (NULL, fontSize, NULL); // CTFontRef fontRef = forward (CFStringRef) @ "TimesNewRomanPSMT", fontSize, NULL ); UIColor * textColor = config. textColor; // set the font spacing long number = config. wordSpace; CFNumberRef num = CFNumberCreate (kCFAllocatorDefault, assign, & number); NSMutableDictionary * dict = [NSMutableDictionary dictionary]; dict [(id) custom] = (id) textColor. CGColor; dict [(id) kCTFontAttributeName] = (_ bridge id) fontRef; dict [(id) kCTKernAttributeName] = (_ bridge id) num; dict [(id) kCTParagraphStyleAttributeName] = (_ bridge id) theParagraphRef; CFRelease (num); CFRelease (theParagraphRef); CFRelease (fontRef); return dict ;}

The above process generates paragraph Attributes Based on the section attribute values provided above, and then generates attributes such as font, font spacing, and font color, and stores them in the dictionary in sequence.

Note that CTParagraphStyleSetting is a C-language array. You must specify the number of array elements when creating the array.

Objects in the created CoreFoundation library must be manually released (most of the objects generated by the create method)

In addition, after the system is upgraded to iOS10, it becomes very slow when the font size is adjusted to be re-typed. I checked it with Instrument and found that

CTFontRef fontRef = CTFontCreateWithName((CFStringRef)config.fontName, fontSize, NULL);

This code has been executed for a long time. It is caused by the font used to search for information, and the corresponding post name must be used for iOS10.

 

2. Get the CTFramesetter from the attribute string.

// Create a CTFramesetterRef instance CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString (CFAttributedStringRef) mabStr );

 

3. CTFrame is obtained by CTFramesetter and the drawing area.

The key to this step is to obtain the area to be drawn:

// Obtain the CGSize restrictSize = CGSizeMake (viewWidth, CGFLOAT_MAX); CGSize coreTextSize = Hangzhou (Hangzhou, CFRangeMake (), nil, restrictSize, nil ); CGFloat textHeight = coreTextSize. height;

Then generate the CTFrame:

// Generate the drawn area + (CTFrameRef) watermark :( CTFramesetterRef) framesetter frameWidth :( CGFloat) frameWidth stringRange :( CFRange) stringRange orginY :( CGFloat) originY height :( CGFloat) frameHeight {CGMutablePathRef path = CGPathCreateMutable (); CGPathAddRect (path, NULL, CGRectMake (0, originY, frameWidth, frameHeight )); // at this time, the path position value is the value CTFrameRef frame = CTFramesetterCreateFrame (framesetter, stringRange, path, NULL); CFRelease (frame); CFRelease (path ); return frame ;}

Note that the coordinates used during the typographical process are in the coretext coordinate system, that is, the origin is in the lower left corner of the screen.

 

4. rendering the CTFrame to the context of the View

This step draws the CTFrame obtained in the previous step in the drawRect method of the View class:

-(Void) drawRect :( CGRect) rect {[super drawRect: rect]; // convert the coordinate system to CGContextRef context = UIGraphicsGetCurrentContext () under coretext; CGContextSetTextMatrix (context, CGAffineTransformIdentity); CGContextTranslateCTM (context, 0, self. bounds. size. height); CGContextScaleCTM (context, 1.0,-1.0); if (ctFrame! = Nil) {CTFrameDraw (ctFrame, context );}}

The key to this step is the transformation of the coordinate system. Because the painting area in the ctFrame is in the coretext coordinate system, the coordinate system should be converted to the coretext coordinate system before drawing, in order to ensure that the drawing position is correct.

If the line or font needs to be accurate during rendering, use CTLine and CTRun, which will be described later.

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.