CATextLayer 中不需要的填充 (Unwanted padding in CATextLayer)


問題描述

CATextLayer 中不需要的填充 (Unwanted padding in CATextLayer)

I am having a problem of drawing a character in a CATextLayer such that the layer is exactly the size of the character.

I use the code below to get the size of the glyph corresponding to the character in the string. At the moment I am neglecting diacretics, so that I am assuming that there is a one to one correlation between glyphs and characters.

I also get nice bounding box values for several characters for the Helvetica font at size 128pt:

Character | x   | y     | width | height |
B         | 9.4 |   0.0 | 70.8  | 91.8   |
y         | 1.3 | -27.4 | 61.2  | 96.0   |

I am not sure where the origin of the coordinate system is located in which the coordinates are expressed. I am assuming that (0,0) is at the very left and vertically located on the baseline of the font. That is why 'y' has a negative y value.

I am using this code to calculate the size of a capital B and resize its CATextLayer accordingly.

- (CATextLayer *) testTextLayer
{
    CATextLayer *l = [CATextLayer layer];
    l.string = @"B";
    NSUInteger len = [l.string length];
    l.fontSize =128.f;
    CGColorRef blackColor = CGColorCreateGenericGray(0.f, 1.f);
    l.foregroundColor = blackColor;
    CGColorRelease(blackColor);

    // need to set CGFont explicitly to convert font property to a CGFontRef
    CGFontRef layerFont = CGFontCreateWithFontName((CFStringRef)@"Helvetica");
    l.font = layerFont;

    // get characters from NSString
    UniChar *characters = (UniChar *)malloc(sizeof(UniChar)*len);
    CFStringGetCharacters((__bridge CFStringRef)l.string, CFRangeMake(0, [l.string length]), characters);

    // Get CTFontRef from CGFontRef
    CTFontRef coreTextFont = CTFontCreateWithGraphicsFont(layerFont, l.fontSize, NULL, NULL);

    // allocate glyphs and bounding box arrays for holding the result
    // assuming that each character is only one glyph, which is wrong
    CGGlyph *glyphs = (CGGlyph *)malloc(sizeof(CGGlyph)*len);
    CTFontGetGlyphsForCharacters(coreTextFont, characters, glyphs, len);

    // get bounding boxes for glyphs
    CGRect *bb = (CGRect *)malloc(sizeof(CGRect)*len);
    CTFontGetBoundingRectsForGlyphs(coreTextFont, kCTFontDefaultOrientation, glyphs, bb, len);
    CFRelease(coreTextFont);

    l.position = CGPointMake(200.f, 100.f);

    l.bounds = bb[0];

    l.backgroundColor = CGColorCreateGenericRGB(0.f, .5f, .9f, 1.f);

    free(characters);
    free(glyphs);
    free(bb);

    return l;
}

This is the result I am getting from the above code. It seems to me that the size is correct, however there is some kind of padding taking place around the character.

Now my questions

  1. Am I right with the assumption of the origin of the bounding box of the glyph?
  2. How can one draw the letter such that it fits neatly into the layer, without this padding? Or alternatively, how can one control this padding?

Maybe I am missing an obvious point here. Is there now way after setting the size and the font of the layer to shrink wrap the layer around the character in a defined way (meaning with optional padding, a bit like in CSS)?



參考解法

方法 1:

How about creating a CGPath from a glyph with CTFontCreatePathForGlyph and then getting its bounding box with CGPathGetBoundingBox?

An alternative would be to create a CTRun somehow and use the CTRunGetImageBounds function which also returns a "tight" bounding box, but this probably requires more lines of code than the aforementioned approach and you'd need to have a graphics context.

方法 2:

I assume this has to do with the built-in space around letters. Their bounding box usually includes some amount of space that serves as a general spacing if you assemble glyphs in a line. These are then optimized with kerning tables.

And yes, extracting the actual bezier path is a very good method of getting a tight bounding box. I have been doing that for years, though I have no experience using CATextLayers.

(by GorillaPatchomzMartin Winter)

參考文件

  1. Unwanted padding in CATextLayer (CC BY-SA 3.0/4.0)

#cocoa #core-text #core-animation






相關問題

為什麼 NSWindow 或 NSView 實例處理它自己的鍵事件,而不是它的委託? (Why does an NSWindow or NSView instance handle its own key events, and not its delegate?)

通過 IKImage 視圖預覽圖像 (Previewg images via IKImage View)

Gaya Jendela Kustom di Kakao (Custom Window Style in Cocoa)

Apakah NSURLConnections termasuk dalam model atau pengontrol saya? (Do NSURLConnections belong in my model or controller?)

Эквівалент ключа NMenuItem не працуе, калі меню схавана (NSMenuItem Key Equivalent not working when menu is hidden)

透明窗口中的圓形 NSView (Rounded NSView in a Transparent Window)

單元格中不可見的 UITextField 已將 userInteractionEnabled 設置為 No (UITextField in cell that is not visible has userInteractionEnabled set to No)

如何為自定義 NSImageRep 子類實現 -draw (How to implement -draw for custom NSImageRep subclass)

從 Objective-C 中的核心數據元素獲取和設置值? (Getting and Setting values from Core Data elements in Objective-C?)

來自 URL 編碼問題的 NSArray (NSArray from URL encoding problem)

停靠欄下的窗口化opengl遊戲中的雙光標 (Double cursor in windowed opengl game under dock)

在特定的 NSTableview 單元格中對角線繪製線條 (Draw Lines Diagonally in a particular NSTableview cell)







留言討論