6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

NSStringのサイズ取得の穴

Last updated at Posted at 2017-03-06

#sizeWithAttributes
sizeWithAttributesは、正しいサイズを取得できないケースがあります。

文字列に、指定フォントに無いものが含まれていれば、sizeWithAttributesは正しいサイズを取得出来ません。

例えば、等倍フォントである「Courier」は日本語が含まれていません。
フォントに「Courier」を指定し、文字列に日本語が含まれていれば、sizeWithAttributesは本来のサイズを返しません。

iOSでは、足りない分は他フォントで代用、文字が表示されない事は無いので、
一見困ることはないのですが、上記の様な落とし穴に注意してください。

CoreTextならば、このような場合でも正しいサイズが取得できます。

サイズ取得の比較
NSString *text = @"チ";

// 文字装飾
NSMutableDictionary *dictAttr = [NSMutableDictionary dictionary];
[dictAttr setObject:[UIFont fontWithName:@"Courier" size:64.0] forKey:NSFontAttributeName];

/* ********************
 * sizeWithAttributesでサイズ取得
 ******************** */
// サイズ取得
CGSize sizeFont = [text sizeWithAttributes:dictAttr];

// ログ出力
NSLog(@"sizeWith~:%@", NSStringFromCGSize(sizeFont));

/* ********************
 * CoreTextでサイズ取得
 ******************** */
// 装飾文字列の生成
NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:text attributes:dictAttr];
//フレームセッターの作成
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attrStr);
// サイズ取得
CGSize contentSize = CTFramesetterSuggestFrameSizeWithConstraints(
                                                                  framesetter,
                                                                  CFRangeMake(0, attrStr.length),
                                                                  nil,
                                                                  CGSizeMake(200, 200),
                                                                  nil);

// ログ出力
NSLog(@"CoreText:%@", NSStringFromCGSize(contentSize));

出力ログ
sizeWith~:{64, 64}
CoreText:{64, 71}

このように、sizeWithAttributesでは縦幅が小さくなっています。

#drawInRect
drawInRectでも、上記に起因すると思われる問題が見られます。

drawInRectは、sizeWithAttributesと同じ認識を元に、描画の原点としている?

前述のtextを描画
CGRect rectImage = CGRectMake(0, 0, 96.0, 96.0);

// 画像処理開始
UIGraphicsBeginImageContextWithOptions(rectImage.size, NO, 0.0);

// テキストの描画
[text drawInRect:rectImage withAttributes:dictAttr];
UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
    
// 画像処理終了
UIGraphicsEndImageContext();

resultImage

64x64に対して96x96の十分な余裕を持たせても、"チ"の上部がわずかに欠けてしまっています。

本来64x71のところ、
drawInRectが64x64と誤認している為、原点がズレてしまっていると思われます。

drawInRectのy軸を少しズラすと、上部も描画されます

#まとめ
日本語が含まれないフォントの使用は、それほど珍しくないように思います。
その都度、CoreTextを意識しないといけないのは少々面倒な話ですね。

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?