2017-07-16 61 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); 
} 

这将正确绘制每个字形。