为什么整个单词的sizeWithFont
与其字母大小的总和产生不同的结果?
以下是包含和不包含字距的文本示例:
CGFloat fontSize = 36;
UIFont *font = [UIFont systemFontOfSize:fontSize];
NSArray *wordsToTest = @[@"IIIIIIIII", @"VAVAVAVAV"];
for (NSString *testWord in wordsToTest) {
CGFloat widthOfTextWithFont = [testWord sizeWithFont:font].width;
CGFloat widthOfTextUsingIteration = 0;
for (int i = 0; i < [testWord length]; i++) {
NSRange range = NSMakeRange(i, 1);
NSString *nextLetter = [testWord substringWithRange:range];
widthOfTextUsingIteration += [nextLetter sizeWithFont:font].width;
}
NSDictionary *attributesKerningDisabled = @{NSFontAttributeName : font,
NSKernAttributeName : @0.0F};
NSAttributedString *attributedStringWithDisabledKerning = [[NSAttributedString alloc] initWithString:testWord attributes:attributesKerningDisabled];
NSDictionary *attributesKerningEnabled = @{NSFontAttributeName : font,
NSKernAttributeName : @1.0F};
NSAttributedString *attributedStringWithEnabledKerning = [[NSAttributedString alloc] initWithString:testWord attributes:attributesKerningEnabled];
NSLog(@"Test for string: %@", testWord);
NSLog(@"Length of the whole word: %f", widthOfTextWithFont);
NSLog(@"Length of word, using iteration: %f", widthOfTextUsingIteration);
NSLog(@"Length of attributed string with enabled kerning: %f", [attributedStringWithEnabledKerning size].width);
NSLog(@"Length of attributed string with disabled kerning: %f", [attributedStringWithDisabledKerning size].width);
}
结果如下:
Test for string: IIIIIIIII
Length of the whole word: 84.000000
Length of word, using iteration: 90.000000
Length of attributed string with enabled kerning: 93.000000
Length of attributed string with disabled kerning: 84.000000
Test for string: VAVAVAVAV
Length of the whole word: 204.000000
Length of word, using iteration: 206.000000
Length of attributed string with enabled kerning: 200.000000
Length of attributed string with disabled kerning: 204.000000
这是Apple文档的一部分:
NSKernAttributeName 此属性的值是包含浮点值的NSNumber对象。此值指定调整kern-pair字符的点数。字距调整可防止特定字符之间出现不需要的空间,具体取决于字体。值0表示禁用字距调整。此属性的默认值为0.
答案 0 :(得分:3)
大概是因为字距调整。字距调整是改变连续字母之间间距的过程,以使文本看起来更好看。
当您获得完整字符串的大小时,将应用字距调整。对于个别角色来说,没有什么可以克服,所以可以考虑间距。
我不相信你使用NSKernAttributeName
会关闭字距。我认为使用“克恩”这个术语。在这种情况下是不准确的,它实际上只是指字符之间的额外间距,而不是为字体定义的字距。
答案 1 :(得分:1)
正如@AnindyaSengupta所指出的那样,如果你对整个文本的所有字形前进的总和进行四舍五入,或者如果你将每个字形前进向上舍入,则向上舍入是不同的。 两个CoreText函数说明了这些差异:
/* round up the the advances for the whole text */
static double getTextAdvances(NSString *text, CTFontRef font)
{
unichar *characters = malloc(sizeof(unichar) * text.length);
CGGlyph *glyphs = malloc(sizeof(CGGlyph) * text.length);
CGSize *advances = malloc(sizeof(CGSize) * text.length);
[text getCharacters:characters range:NSMakeRange(0, text.length)];
CTFontGetGlyphsForCharacters(font, characters, glyphs, text.length);
CTFontGetAdvancesForGlyphs(font, kCTFontHorizontalOrientation, glyphs, advances, text.length);
free(characters);
free(glyphs);
CGFloat sum = 0.;
for (NSUInteger i = 0; i < text.length; i++)
sum += advances[i].width;
free(advances);
// round up the whole advances
return ceilf(sum);
}
/* round up each glyphs advances */
static double getCharactersAdvancesSum(NSString *text, CTFontRef font)
{
unichar *characters = malloc(sizeof(unichar) * text.length);
CGGlyph *glyphs = malloc(sizeof(CGGlyph) * text.length);
CGSize *advances = malloc(sizeof(CGSize) * text.length);
[text getCharacters:characters range:NSMakeRange(0, text.length)];
CTFontGetGlyphsForCharacters(font, characters, glyphs, text.length);
CTFontGetAdvancesForGlyphs(font, kCTFontHorizontalOrientation, glyphs, advances, text.length);
free(characters);
free(glyphs);
CGFloat sum = 0.;
for (NSUInteger i = 0; i < text.length; i++)
// round up advance width
sum += ceilf(advances[i].width);
free(advances);
return sum;
}
// test method
CGFloat fontSize = 36;
UIFont *font = [UIFont systemFontOfSize:fontSize];
NSArray *wordsToTest = @[@"IIIIIIIII", @"VAVAVAVAV"];
for (NSString *testWord in wordsToTest) {
// … snip
NSLog(@"Test for string: %@", testWord);
NSLog(@"Length of the whole word: %f", widthOfTextWithFont);
NSLog(@"Length of word, using iteration: %f", widthOfTextUsingIteration);
// … skip kerning logs
NSLog(@"Round up whole text advances %f", getTextAdvances(testWord, (CTFontRef)font));
NSLog(@"Round up per Characters Advances %f", getCharactersAdvancesSum(testWord, (CTFontRef)font));
}
测试结果:
Test for string: IIIIIIIII
Length of the whole word: 84.000000
Length of word, using iteration: 90.000000
Round up whole text advances 84.000000
Round up per Characters Advances 90.000000
Test for string: VAVAVAVAV
Length of the whole word: 204.000000
Length of word, using iteration: 206.000000
Round up whole text advances 204.000000
Round up per Characters Advances 206.000000