iOS image text mixed arrangement

Mixed text arrangement, text click events and text animation (which are not discussed, but can be handled through view). If it is a simple operation, it can be handled with UITextView. When special customization is required, CoreText can be used. It is a powerful text processing framework that supports all customized operations related to text arrangement. Combined with CoreGraphics, the mixed text arrangement function can be realized.

Implementation principle

CoreText is an underlying text drawing framework. What it really draws is only the text part. If pictures are involved, it still needs to be drawn manually. It mainly calculates its layout after collecting the paragraph style, line style, font size and style configuration information of the text. It mainly includes the following key categories.

  1. CTFramesetter (typesetting)
  2. CFFrame (paragraph, frame)
  3. CFLine (line)
  4. CTRun (text)
  5. Cfttypesetter (typesetting)

Origin position

  • The text origin position in CoreText and UIView are based on the mirror symmetry of X bearing, and the Y coordinate is opposite

Appkit->NSView: leftBottom
UIKit->UIView: topRight
CoreGraphic->Context: letBottom

CoreText object model

  • CFAttributedStringRef: attribute string, used to store the text characters and attributes of the drawing amount

  • CTFramesetterRef: corresponds to CTFramesetter, which is initialized through CFAttributedStringRef. As the production plant of CTFrame, it is responsible for generating the corresponding CTFrame according to the corresponding Path

  • CTFrame: you can draw directly to the Context through the CTFrameDraw function. Before drawing, you can fine tune some parameters through CTLine

  • CTLine: the interior of ctframe is composed of multiple ctlines, and each CTLine can be regarded as one line

  • CTRun: or Glyph Run. Each CTLine is composed of multiple spoof CTRun. CTRun is a group of text with the same display style (similar to textspan in fluent) and a group of font aggregates with the same attributes

General processing steps

  • Gets the current context object
  • Flip coordinate system, Y-axis symmetry
  • Create AttributedString and convert it to the corresponding CTFramesetterRef
  • Create drawing area: CGPathRef
  • Create CTFrame from CTFramesetterRef and CGPathRef
  • CGFrameDraw draws text
func layoutParagraph() {
           
        let context = UIGraphicsGetCurrentContext()!
           
           //1. Reverse y, and the coordinate system of coregraphics is at the sitting angle
           context.translateBy(x: 0, y: self.bounds.size.height);
           context.scaleBy(x: 1.0, y: -1.0)
           context.textMatrix = CGAffineTransform.identity;
           
           //2. Create path
           let path = CGMutablePath();
           let rect = CGRect(x: 10.0, y: 10.0, width: 200.0, height: 200.0);
           path.addRect(rect)
           
           //3. Create ` CFAttributedString`
           let data = "Hello, World! I know nothing in the world that has as much power as a word. Sometimes I write one, and I look at it, until it begins to shine.".withCString{ $0 }
           let cfString = CFStringCreateWithCString(kCFAllocatorDefault,data, CFStringBuiltInEncodings.UTF8.rawValue)
           let attrString =
           CFAttributedStringCreateMutable(kCFAllocatorDefault, 0)!;
           CFAttributedStringReplaceString(attrString, CFRangeMake(0, 0), cfString)
           
           //4. Set the properties of some text
           let colorSpace = CGColorSpaceCreateDeviceRGB()
           let components = [CGFloat(0.0), CGFloat(0.3), CGFloat(0.3), CGFloat(0.8) ].withUnsafeBufferPointer{ $0 }
           let redColor = CGColor(colorSpace: colorSpace, components: components.baseAddress!)
           CFAttributedStringSetAttribute(attrString, CFRangeMake(0, 12),
           kCTForegroundColorAttributeName, redColor);
           
           //5. Create a text layout object
           let framesetter = CTFramesetterCreateWithAttributedString(attrString)
           
           //6. Draw clips
           let frame = CTFramesetterCreateFrame(framesetter,
                                                CFRangeMake(0,0), path, nil);
           //7. Execute drawing
           CTFrameDraw(frame, context)
       }

Local click judgment

  • Because the text in CoreText is typeset based on CTFrame, which includes multiple ctlines, it is easy to get the position and size of each line, judge whether the click is on a line, and CTLine can further judge whether the clicked text is on the specified coordinates of CTLine. By facilitating the NSTextCheckingResult result of this String, calculate the specific position of the text according to ran.

Mixed arrangement of pictures and texts

  • CoreText itself does not support image rendering. Core Graphics is required for image rendering. CoreText only provides reserved space for image rendering through the setting of cctron. This setting needs to use ctrundelegate. Ctrundelegate is used as an entry for CTRun related attributes or operation extensions, so that we can do some custom behaviors for CTRun. The way to leave a position for an image is to add a blank CTRun and customize its ascent, descent, width and other parameters to leave a blank position for the corresponding image when drawing text. Then the image is drawn in the corresponding blank position using the Core Graphics interface.

  • Using CTRunDelegateCreate, you can create a CTRunDelegate, which receives two parameters, one is the callback structure, and the other is the object that needs to be passed in during all callback calls. The structure of callbacks is CTRunDelegateCallbacks, which mainly contains some callback functions, such as callback functions that return the values of ascent, descent and width of the current run. As for how to identify the current run in the function, you can achieve the purpose in the second parameter of CTRunDelegateCreate, because the second parameter of CTRunDelegateCreate will be used as the input parameter of each callback call.

Reference link

CoreText Programming Guide: https://developer.apple.com/library/archive/documentation/StringsTextFonts/Conceptual/CoreText_Programming/Introduction/Introduction.html#//apple_ref/doc/uid/TP40005533

YYText: https://github.com/ibireme/YYText

Tags: iOS

Posted by neverett on Thu, 12 May 2022 14:22:37 +0300