CGPathRef from string

前端 未结 2 1437
野的像风
野的像风 2021-02-04 20:52

Please how can we get path of particular arabic of french letter ? I\'ve just found out that CTFontCreatePathForGlyph will give CGPathRef like, but its will be the outline of te

相关标签:
2条回答
  • 2021-02-04 21:18

    You dont require ur path to be converted into NSString at all.

    You can create the path for text as follows:

        CTFontRef font = CTFontCreateWithName(CFSTR("Helvetica-Bold"), 72.0f, NULL);
    NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:
                           (id)font, kCTFontAttributeName,
                           nil];
    NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:@"Hello World!"
                                                                     attributes:attrs];
    CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)attrString);
    CFArrayRef runArray = CTLineGetGlyphRuns(line);
    
    // for each RUN
    for (CFIndex runIndex = 0; runIndex < CFArrayGetCount(runArray); runIndex++)
    {
        // Get FONT for this run
        CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runArray, runIndex);
        CTFontRef runFont = CFDictionaryGetValue(CTRunGetAttributes(run), kCTFontAttributeName);
    
        // for each GLYPH in run
        for (CFIndex runGlyphIndex = 0; runGlyphIndex < CTRunGetGlyphCount(run); runGlyphIndex++) 
        {
            // get Glyph & Glyph-data
            CFRange thisGlyphRange = CFRangeMake(runGlyphIndex, 1);
            CGGlyph glyph;
            CGPoint position;
            CTRunGetGlyphs(run, thisGlyphRange, &glyph);
            CTRunGetPositions(run, thisGlyphRange, &position);
    
            // Get PATH of outline
            {
                CGPathRef letter = CTFontCreatePathForGlyph(runFont, glyph, NULL);
                CGAffineTransform t = CGAffineTransformMakeTranslation(position.x, position.y);
                CGPathAddPath(letters, &t, letter);
                CGPathRelease(letter);
            }
        }
    }
    CFRelease(line);
    

    This is how you create a path, for sample code please refer this link. This code is a part of this sample project. Hope this helps you

    0 讨论(0)
  • 2021-02-04 21:38

    I needed this in Swift but it was painful to work out. I hope this is useful to someone else! I've written it as extensions to String and NSAttributedString to be more versatile.

    You might see the letters as upside-down depending on how you're drawing your path. You can fix this by adding a vertical flip transform to the call to CTFontCreatePathForGlyph() (a vertical flip is just a CGAffineTransform with a scaleY of -1).

    public extension String {
        func path(withFont font: UIFont) -> CGPath {
            let attributedString = NSAttributedString(string: self, attributes: [.font: font])
            let path = attributedString.path()
            return path
        }
    }
    
    public extension NSAttributedString {
        func path() -> CGPath {
            let path = CGMutablePath()
    
            // Use CoreText to lay the string out as a line
            let line = CTLineCreateWithAttributedString(self as CFAttributedString)
    
            // Iterate the runs on the line
            let runArray = CTLineGetGlyphRuns(line)
            let numRuns = CFArrayGetCount(runArray)
            for runIndex in 0..<numRuns {
    
                // Get the font for this run
                let run = unsafeBitCast(CFArrayGetValueAtIndex(runArray, runIndex), to: CTRun.self)
                let runAttributes = CTRunGetAttributes(run) as Dictionary
                let runFont = runAttributes[kCTFontAttributeName] as! CTFont
    
                // Iterate the glyphs in this run
                let numGlyphs = CTRunGetGlyphCount(run)
                for glyphIndex in 0..<numGlyphs {
                    let glyphRange = CFRangeMake(glyphIndex, 1)
    
                    // Get the glyph
                    var glyph : CGGlyph = 0
                    withUnsafeMutablePointer(to: &glyph) { glyphPtr in
                        CTRunGetGlyphs(run, glyphRange, glyphPtr)
                    }
    
                    // Get the position
                    var position : CGPoint = .zero
                    withUnsafeMutablePointer(to: &position) {positionPtr in
                        CTRunGetPositions(run, glyphRange, positionPtr)
                    }
    
                    // Get a path for the glyph
                    guard let glyphPath = CTFontCreatePathForGlyph(runFont, glyph, nil) else {
                        continue
                    }
    
                    // Transform the glyph as it is added to the final path
                    let t = CGAffineTransform(translationX: position.x, y: position.y)
                    path.addPath(glyphPath, transform: t)
                }
            }
    
            return path
        }
    }
    
    0 讨论(0)
提交回复
热议问题