2012-08-08 102 views
0

我正在使用CoreText在MAC OS X上實現自定義文本佈局算法。我必須在自定義NSView子類對象內的不同位置部分渲染CTRun的一部分。CTRunDraw()確實實現了正確的行爲

這是我實現的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; 

}

回答

0

你在這裏濫用CTRun。 A CTRun是一個包含擺放的字形的水平框。試圖將它的一部分放在另一個下面是沒有意義的(當然,在任何稍微複雜的情況下,這樣的排版都是錯誤的)。爲什麼?那麼,因爲在某些特定位置出現換行符時,選擇的字形可能會有所不同(例如,可能會發生連字)。另外請注意,字符和字形之間不一定是1:1映射。我的猜測是你可能不需要你自己的全定製排版機(並且相信我,寫一個是複雜的,所以如果你不需要的話,不要寫一個)。相反,只需使用CTTypesetter和/或CTFramesetter即可獲得所需的輸出。