NSAttributedStringに
      ついて
        2012.8.25
       Cocoa勉強会
        大森智史
• スライド、サンプルは基本的にすべて公開し
 ます。
あんた、誰?


• と、いうわけで自己紹介。
• 大森智史といいます。

• Objective-Cで遊んでます。

• 印刷会社勤務。
• と、いうことで本題に
• 職業柄、電子書籍系のレビューなどは気に
 なっています。

• 先日、ある電子書籍の案内を見ていたら、す
 こし違和感を覚えました。
2012 AppStore
2012 ミナミ・リエロ/株式会社日本文芸社/株式会社メディアタブレット/アドベンチャー 「女医が教える最高のセックス」より引用
サンプル画面




2012 AppStore
2012 ミナミ・リエロ/株式会社日本文芸社/株式会社メディアタブレット/アドベンチャー 「女医が教える最高のセックス」より引用
気がつきましたか?
2012 ミナミ・リエロ/株式会社日本文芸社/株式会社メディアタブレット/アドベンチャー 「女医が教える最高のセックス」より引用
2012 ミナミ・リエロ/株式会社日本文芸社/株式会社メディアタブレット/アドベンチャー 「女医が教える最高のセックス」より引用
おかしいでしょ?
2012 ミナミ・リエロ/株式会社日本文芸社/株式会社メディアタブレット/アドベンチャー 「女医が教える最高のセックス」より引用
• そこで、研究熱心な私は、購入して詳細を見
 て見ることにしました。
初めに言っときますけど
組版の研究目的です。!
やっぱり変です。




2012 ミナミ・リエロ/株式会社日本文芸社/株式会社メディアタブレット/アドベンチャー 「女医が教える最高のセックス」より引用
組版         の


研究ですからね!
  本当ですよ!
きっと
• どうも横書き用のグリフを並べているだけな
 んでしょう。

• 縦書きは縦書き用のグリフを使わないと!全
 体にバランス悪い。

• 「。」「、」だけは処理しているようだが。
いいかげんな実装は
  やめていただきたい!

• きちんと実装しましょう。

• 縦書きは単に文字を縦にを並べれはいいとい
 うものではないです。
と、いうことで
きちんと実装するには
• フォント情報を読んで

• グリフを読んで

• レイアウトして
• 参考資料

• 日本語組版の要件

• W3C

• http://www.w3.org/TR/2012/NOTE-
  jlreq-20120403/ja/
そこまでする
必要はありません
CoreTextで属性付きテキストを
        描画
     こんな感じでいいです。
どうするか?
属性付きテキストとは
• フォント、色、サイズ

• 下線

• 段落設定 左    え右   え

• NSAttributedStringを使います。
• 属性付きテキストだけでは段落設定や縦組み
 などはダメだけどCoreTextと組み合わせるこ
 とで、多彩な表現が簡単に。
だが、しかし
• 今、iOS 5.1では、コンテキストを使ってしか
 書く方法がない!

• OS XにはdrawStringとかdrawRectとかView
 に書く方法がある!

• 将来に期待したい!
コンテキスト
•   とりあえず、コンテキストで書く方法


•   - (void)drawRect:(CGRect)rect {

    //コンテキスト
! CGContextRef context = UIGraphicsGetCurrentContext();



•   ....書いていく


•   }
• コンテキストを取得

• AttributedStringを作成

• フレームを作成

• 描画
• 以上です。
コンテキスト
•    レイヤーのコンテキストに書いていく方法


•    - (void)drawRect:(CGRect)rect {

    //レイヤーを作成
     CGLayerRef          layer;
     CGContextRef        layerContext;

    layer = CGLayerCreateWithContext(context,CGSizeMake(800,
800),NULL);
    //レイヤーのコンテキストを取得
     layerContext = CGLayerGetContext(layer);

•    ....書いていく


•    }
属性
フォント


ヒラギノ角ゴ ヒラギノ明朝
フォント
CTFontRef aFont1 =
    CTFontCreateWithName(CFSTR("HiraKakuProN-W6"), 20, NULL);

NSDictionary *fontAttributes1 =
         [NSDictionary dictionaryWithObjectsAndKeys:

          (__bridge id)aFont1, @"NSFont"
            ...
            ,nil ];
NSAttributedString *grayString = [[NSAttributedString alloc]
initWithString:@"リガチャnn ffi fln"
attributes:fontAttributes1];
カラー

カラー  カラー
カラー
NSDictionary *fontAttributes1 =
         [NSDictionary dictionaryWithObjectsAndKeys:

         (__bridge id)darkGrayColor, @"CTForegroundColor",
            ...
            ,nil ];
リガチャ(合字)
リガチャ
NSDictionary *fontAttributes1 =
         [NSDictionary dictionaryWithObjectsAndKeys:

         [NSNumber numberWithBool:YES],kCTLigatureAttributeName,
            ...
            ,nil ];
下線
下線
NSDictionary *fontAttributes1 =
         [NSDictionary dictionaryWithObjectsAndKeys:

        (__bridge id)redColor,kCTUnderlineColorAttributeName,
 [NSNumber numberWithInt:0x0100],kCTUnderlineStyleAttributeName,
            ...
            ,nil ];
段落設定
(センターそろえ)
段落設定
              センターそろえ
NSDictionary *fontAttributes1 =
         [NSDictionary dictionaryWithObjectsAndKeys:
         paragraphStyleAttr, kCTParagraphStyleAttributeName,
            ...
            ,nil ];
id paragraphStyleAttr = ((^ {

        CTParagraphStyleSetting paragraphStyles[] = (CTParagraphStyleSetting[]){
            (CTParagraphStyleSetting)
            { kCTParagraphStyleSpecifierAlignment, sizeof(alignment), &alignment},
            (CTParagraphStyleSetting)
            { kCTParagraphStyleSpecifierLineHeightMultiple, sizeof(float_t),
(float_t[]){ lineHeight } },
            (CTParagraphStyleSetting)
            { kCTParagraphStyleSpecifierMinimumLineHeight, sizeof(float_t), (float_t[])
{lineHeight } },
            (CTParagraphStyleSetting)
            { kCTParagraphStyleSpecifierMaximumLineHeight, sizeof(float_t), (float_t[])
{lineHeight } },
            (CTParagraphStyleSetting)
            { kCTParagraphStyleSpecifierLineSpacing, sizeof(float_t), (float_t[])
{ 0.0f } },
            (CTParagraphStyleSetting)
            { kCTParagraphStyleSpecifierMinimumLineSpacing, sizeof(float_t),
(float_t[]){ 0.0f } },
            (CTParagraphStyleSetting)
            { kCTParagraphStyleSpecifierMaximumLineSpacing, sizeof(float_t),
(float_t[]){ 0.0f } }

        };
CTParagraphStyleRef paragraphStyleRef = CTParagraphStyleCreate(paragraphStyles,
sizeof(paragraphStyles) / sizeof(CTParagraphStyleSetting));
        return (__bridge id)paragraphStyleRef;

    })());
デモ
TEST1
縦組み用
縦組み用文字
NSDictionary *fontAttributes1 =
         [NSDictionary dictionaryWithObjectsAndKeys:

         [NSNumber numberWithBool:YES], @"CTVerticalForms",
            ...
            ,nil ];
+フレーム設定
     が必要
AttributedStringじゃないけれど
フレーム設定
//フレーム作成
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter,
CFRangeMake(0, 0), path,
 (__bridge CFDictionaryRef)[NSDictionary
dictionaryWithObjectsAndKeys:

[NSNumber
numberWithUnsignedInt:kCTFrameProgressionRightToLeft],
@"CTFrameProgression",

nil]);
文字間を等幅に
 (デリゲート使用)
文字間を等幅に
CGFloat MyGetWidthCallback( void* refCon ){
    NSLog(@"Width being set %s",refCon);
    return 30.0;
}
- (void)drawRect:(CGRect)rect{
    CTRunDelegateCallbacks callbacks;
    callbacks.getWidth = MyGetWidthCallback;
    CTRunDelegateRef delegate = CTRunDelegateCreate(&callbacks,
NULL);
NSDictionary *fontAttributes1 =
         [NSDictionary dictionaryWithObjectsAndKeys:

         delegate,kCTRunDelegateAttributeName,
            ...
            ,nil ];
文字間を調整
(カーニング使用)
文字間を調整
NSDictionary *fontAttributes1 =
         [NSDictionary dictionaryWithObjectsAndKeys:

         [NSNumber numberWithFloat:5.0],kCTKernAttributeName,
                                     ,
            ...
            ,nil ];
リンク情報
リンク情報

NSDictionary *fontAttributes1 =
         [NSDictionary dictionaryWithObjectsAndKeys:

         @"http://www.apple.co. jp/" ,@"NSLinkAttributeName",

            ...
            ,nil ];
デモ
TEST2
まとめ

• NSAttributedString+CoreTextで簡単にきれい
  なレイアウト

• iOSではコンテキスト描画...。Macでは
  drawRect()とかあるし、シャドウも掛けられ
  たりするし...将来に期待!
ありがとうございました

Cocoa勉強会201208