Created
February 21, 2022 22:01
-
-
Save umurgdk/030d5c22ac3c91718c38c1a5655e0810 to your computer and use it in GitHub Desktop.
TextRendering CoreText
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- (void)drawRect:(NSRect)dirtyRect { | |
[super drawRect:dirtyRect]; | |
CGContextRef ctx = [NSGraphicsContext currentContext].CGContext; | |
[NSColor.blackColor setFill]; | |
CGContextFillRect(ctx, CGRectMake(0, self.label.frame.size.height, self.label.frame.size.width, self.label.frame.size.height)); | |
CFIndex stringLen = CFStringGetLength(text); | |
CTFontRef font = CTFontCreateUIFontForLanguage(kCTFontUIFontSystem, 24.0f, nil); | |
// MARK: - Get Glyph Rects | |
UniChar *characters = (UniChar *)malloc(sizeof(UniChar) * stringLen); | |
CGGlyph *glyphs = (CGGlyph *)malloc(sizeof(CGGlyph) * stringLen); | |
CGRect *glyphRects = (CGRect *)malloc(sizeof(CGRect) * stringLen); | |
CFStringGetCharacters(text, CFRangeMake(0, stringLen), characters); | |
CTFontGetGlyphsForCharacters(font, characters, glyphs, stringLen); | |
CTFontGetBoundingRectsForGlyphs(font, kCTFontOrientationDefault, glyphs, glyphRects, stringLen); | |
// MARK: - Draw Glyph Rects | |
CFMutableAttributedStringRef attributedString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0); | |
CFAttributedStringReplaceString(attributedString, CFRangeMake(0, 0), text); | |
CFAttributedStringSetAttribute(attributedString, CFRangeMake(0, CFAttributedStringGetLength(attributedString)), kCTFontAttributeName, font); | |
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attributedString); | |
CFRange fitRange; | |
CGSize frameSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, 0), NULL, CGSizeMake(self.bounds.size.width, CGFLOAT_MAX), &fitRange); | |
[NSColor.redColor setStroke]; | |
CGContextTranslateCTM(ctx, 0, self.label.frame.size.height); | |
CGContextStrokeRect(ctx, CGRectMake(0, 0, frameSize.width, frameSize.height)); | |
CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedString(attributedString); | |
CTLineRef line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, stringLen)); | |
CFArrayRef runs = CTLineGetGlyphRuns(line); | |
[NSColor.greenColor setStroke]; | |
[NSColor.labelColor setFill]; | |
for (int i = 0; i < CFArrayGetCount(runs); i++) { | |
CTRunRef run = CFArrayGetValueAtIndex(runs, i); | |
CFIndex glyphCount = CTRunGetGlyphCount(run); | |
CGGlyph *glyphs = malloc(sizeof(CGGlyph) * glyphCount); | |
CTRunGetGlyphs(run, CFRangeMake(0, 0), glyphs); | |
CGPoint *glyphPositions = malloc(sizeof(CGSize) * glyphCount); | |
CTRunGetPositions(run, CFRangeMake(0, 0), glyphPositions); | |
CGRect *glyphRects = malloc(sizeof(CGRect) * glyphCount); | |
CTFontGetBoundingRectsForGlyphs(font, kCTFontOrientationDefault, glyphs, glyphRects, glyphCount); | |
for (int j = 0; j < glyphCount; j++) { | |
CGRect rect = CGRectOffset(glyphRects[j], glyphPositions[j].x, glyphPositions[j].y); | |
rect = CGRectApplyAffineTransform(rect, CGAffineTransformMakeScale(1, -1)); | |
rect = CGRectOffset(rect, 0, frameSize.height); | |
CGContextStrokeRect(ctx, rect); | |
CGAffineTransform glyphTransform = CGAffineTransformMakeTranslation(glyphPositions[j].x, glyphPositions[j].y + frameSize.height); | |
glyphTransform = CGAffineTransformScale(glyphTransform, 1, -1); | |
CGPathRef glyphPath = CTFontCreatePathForGlyph(font, glyphs[j], &glyphTransform); | |
CGContextSaveGState(ctx); | |
// CGContextTranslateCTM(ctx, rect.origin.x, rect.origin.y); | |
// CGContextScaleCTM(ctx, 1, -1); | |
CGContextAddPath(ctx, glyphPath); | |
CGContextFillPath(ctx); | |
CGContextRestoreGState(ctx); | |
CGPathRelease(glyphPath); | |
} | |
free(glyphRects); | |
free(glyphPositions); | |
free(glyphs); | |
} | |
CFRelease(line); | |
CFRelease(typesetter); | |
CFRelease(framesetter); | |
CFRelease(attributedString); | |
free(characters); | |
free(glyphs); | |
CFRelease(font); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment