2017-07-16 109 views
0

我試圖通過CGPathRefs將文本分成所有不同的部分。例如,L有一條路徑和?有兩個(點和其他)。將CGPathRef拆分爲多個路徑

目前,我可以將每個字母作爲路徑,但是在「?」的示例中,該路徑包含點和其餘的一個。我想分割它們,但我似乎無法使它起作用。

爲了將文本分成路徑,我使用了堆棧溢出的一些答案,它運行良好,這裏是我將每個字母作爲路徑的部分。在這裏,我也通過「CGPathApply」功能運行它看每一個人的一點

CGPathRef letter = CTFontCreatePathForGlyph(runFont, glyph, NULL); 
NSMutableArray *pathElements = [NSMutableArray array]; 
CGPathApply(letter, (__bridge void * _Nullable)(pathElements), getPointsFromBezier); 

然後我看每一個點在getPointsFromBezier這樣的:

void getPointsFromBezier(void *info, const CGPathElement *element){ 
    CGPoint *p = element->points; 
    NSString *name; 
    switch (element->type) { 
     case kCGPathElementMoveToPoint: name = @"kCGPathElementMoveToPoint"; break; 
     case kCGPathElementAddLineToPoint: name = @"kCGPathElementAddLineToPoint"; break; 
     case kCGPathElementAddQuadCurveToPoint: name = @"kCGPathElementAddQuadCurveToPoint"; break; 
     case kCGPathElementAddCurveToPoint: name = @"kCGPathElementAddCurveToPoint"; break; 
     case kCGPathElementCloseSubpath: name = @"kCGPathElementCloseSubpath"; break; 
     default: name = @"default"; break; 
    } 
    NSLog(@"Type: %@ || Point: %@", name, NSStringFromCGPoint(*p)); 
} 

這給我的輸出是這樣的:

Type: kCGPathElementMoveToPoint || Point: {11.75, 0} 
Type: kCGPathElementAddLineToPoint || Point: {11.75, 9.729} 
Type: kCGPathElementAddQuadCurveToPoint || Point: {11.75, 11.26} 
.. 
.. 
Type: kCGPathElementAddQuadCurveToPoint || Point: {13.00, 10.52} 
Type: kCGPathElementAddLineToPoint || Point: {13.00, 0} 
Type: kCGPathElementCloseSubpath || Point: {13.00, 0} 
Type: kCGPathElementMoveToPoint || Point: {12.75, 18.75} 
Type: kCGPathElementAddQuadCurveToPoint || Point: {11.5, 18.94} 
Type: kCGPathElementAddLineToPoint || Point: {11.5, 19.95} 
Type: kCGPathElementAddQuadCurveToPoint || Point: {11.5, 20.41} 
.. 
.. 
Type: kCGPathElementAddQuadCurveToPoint || Point: {12.75, 18.169} 
Type: kCGPathElementCloseSubpath || Point: {12.75, 18.169} 

我在這裏輸入的字符是ก็,我們可以清楚地看到,它在輸出兩個不同的路徑(即,兩個kCGPathElementMoveToPoint和兩個kCGPathElementCloseSubpath)。

我不知道如何正確或很好地創建兩個單獨的CGPathRefs。

回答

0

其實,在寫這個問題的時候,我幾乎解決了它。

我創建了一個靜態可變的CGPath,然後我在通過CGPathApply調用的函數中添加點。像這樣:

static CGMutablePathRef path; 

void getPointsFromBezier(void *info, const CGPathElement *element){ 
    CGPoint *p = element->points; 

    if (element->type == kCGPathElementMoveToPoint){ 
     path = CGPathCreateMutable(); 
     CGPathMoveToPoint(path, nil, p->x, p->y); 
    } 
    else if (element->type == kCGPathElementAddLineToPoint){ 
     CGPathAddLineToPoint(path, nil, p->x, p->y); 
    } 
    else if (element->type == kCGPathElementAddQuadCurveToPoint){ 
     CGPathAddQuadCurveToPoint(path, nil, p->x, p->y, p->x, p->y); 
    } 
    else if (element->type == kCGPathElementAddCurveToPoint){ 
     // ... 
    } 
    else if (element->type == kCGPathElementCloseSubpath){ 
     CGPathCloseSubpath(path); 
     [((__bridge NSMutableArray*)info) addObject:(__bridge id _Nonnull)(path)]; 
     path = nil; 
     CGPathRelease(path); 
    } 
} 

然後我簡單地遍歷原始方法中的每個路徑,並繪製它們而不是原始的「字母」CGPath。

CGPathRef letter = CTFontCreatePathForGlyph(runFont, glyph, NULL); 
NSMutableArray *pathElements = [NSMutableArray array]; 
CGPathApply(letter, (__bridge void * _Nullable)(pathElements), getPointsFromBezier); 

for (id e in pathElements) { 
    CGContextSaveGState(ctx); 
    CGContextTranslateCTM(ctx,position.x,0 - 40 + CGRectGetMidY(rect) - self.font.descender + position.y); 
    CGContextScaleCTM(ctx, 1, -1); 
    CGContextAddPath(ctx, (CGPathRef)e); 
    [[self r] setFill]; 
    CGContextFillPath(ctx); 
    CGContextRestoreGState(ctx); 
} 

CGPathRelease(letter); 

這種作品。一個問題是,我沒有得到正確的曲線,所以得到的路徑並不像應該那樣平滑。如果我解決問題,我會更新。

這是迄今爲止的結果,您可以看到圖像與底部原始圖像相比有點塊。然而,他們有兩種不同的顏色,這是最初要解決的問題。

enter image description here

更新:我發現每一個點(元素 - >點)包含剩餘的數據(x和y的)正確繪製點。例如:

if (element->type == kCGPathElementAddQuadCurveToPoint){ 
    CGPoint *p0 = &points[0]; // Control points for bezier path 
    CGPoint *p1 = &points[1]; // Actual points 
    CGPathAddQuadCurveToPoint(path, 
           nil, 
           p0->x, 
           p0->y, 
           p1->x, 
           p1->y); 
} 

這將正確繪製每個字形。