0

我正在使用 CoreText 在 MAC OS X 上实现自定义文本布局算法。我必须在自定义 NSView 子类对象内的不同位置部分呈现 CTRun 的一部分。

这是我对drawRect的实现:方法

- (void)drawRect:(NSRect)dirtyRect {
// Drawing code here.
CGContextRef context =
(CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
CGContextSaveGState(context); {
    [[NSColor whiteColor] set];
    NSRectFill(dirtyRect);


    CTFontRef font = CTFontCreateWithName(CFSTR("Menlo"), 20, &CGAffineTransformIdentity);

    CFTypeRef values[] = {font};
    CFStringRef keys[] = {kCTFontAttributeName};

    CFDictionaryRef dictionary =
    CFDictionaryCreate(NULL,
                       (const void **)&keys,
                       (const void **)&values,
                       sizeof(keys) / sizeof(keys[0]),
                       &kCFTypeDictionaryKeyCallBacks,
                       &kCFTypeDictionaryValueCallBacks);

    CFAttributedStringRef longString =
    CFAttributedStringCreate(kCFAllocatorDefault, CFSTR("this_is_a_very_long_string_that_compromises_many_glyphs,we_wil_see_it:)"), dictionary);
    CTLineRef lineRef = CTLineCreateWithAttributedString(longString);

    CFArrayRef runsArray = CTLineGetGlyphRuns(lineRef);
    CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runsArray, 0);

    CGAffineTransform textTransform = CGAffineTransformIdentity;
    textTransform = CGAffineTransformScale(textTransform, 1.0, -1.0);
    CGContextSetTextMatrix(context, textTransform);

    CGAffineTransform sequenceTransform =
    CGAffineTransformIdentity;
    sequenceTransform = CGAffineTransformTranslate(sequenceTransform, 0, 23.2818);


    CGPoint firstPoint = CGPointApplyAffineTransform(CGPointMake(0, 0), sequenceTransform);
    CFRange firstRange = CFRangeMake(0, 24);
    CGContextSetTextPosition(context, firstPoint.x, firstPoint.y);
    CTRunDraw(run, context, firstRange);

    CGPoint secondPoint = CGPointApplyAffineTransform(CGPointMake(0, 26.2812), sequenceTransform);
    CFRange secondRange = CFRangeMake(24, 24);
    CGContextSetTextPosition(context, secondPoint.x, secondPoint.y);
    CTRunDraw(run, context, secondRange);

    CGPoint thirdPoint = CGPointApplyAffineTransform(CGPointMake(0, 52.5625), sequenceTransform);
    CFRange thirdRange = CFRangeMake(48, 23);
    CGContextSetTextPosition(context, thirdPoint.x, thirdPoint.y);
    CTRunDraw(run, context, thirdRange);

}
CGContextRestoreGState(context);

}

这是此代码的输出 https://docs.google.com/open?id=0B8df1OdxKw4FYkE5Z1d1VUZQYWs

问题是 CTRunDraw() 方法在指定范围以外的位置插入空格。

我想要的是它应该将运行的部分渲染在正确的位置。这是我想要的正确输出。(正确的输出是原始输出的photoshop)。 https://docs.google.com/open?id=0B8df1OdxKw4FcFRnS0p1cFBfa28

注意:我在自定义 NSView 子类中使用翻转坐标系。

- (BOOL)isFlipped {
return YES;

}

4

1 回答 1

0

你在CTRun这里误用了。ACTRun是一个包含布局字形的水平框。尝试将它的一部分绘制在另一个下面是没有意义的(在任何稍微复杂的情况下,这种排版肯定是错误的)。为什么?好吧,因为在某些情况下,如果给定位置有换行符,则选择的字形可能会有所不同(例如,连字可能会发生这种情况)。另外,请注意,字符和字形之间不一定存在 1:1 映射。

我的猜测是,您可能不需要自己的完整自定义排版机(相信我,写一个很复杂,所以如果您不需要,就不要写一个)。相反,只需使用CTTypesetter和/或CTFramesetter获取您想要的输出。

于 2013-05-16T17:08:13.620 回答