cocos2d-xのCCLabelTTFでテキストの自動改行

cocos2d-xのCCLabelTTFで、横幅を固定し、テキストをその横幅に応じて自動改行させ、なおかつ高さは明示的に指定せずに、テキスト量に応じて可変にしたい(自動的に最適な高さにしたい)場合。

CCLabelTTF::create(const char *string, const char *fontName, float fontSize, const CCSize& dimensions, CCTextAlignment hAlignment)

を使って、dimensionsに例えば CCSize(100.f, 0)といった具合に、高さ0を指定してやれば良い。

ただし、表示させるテキストが空の行(いわゆる”\n\n”)を含む場合、おそらく空行の分の高さが無視され、結果、テキストの末尾の1行分が表示されないという不具合がある(cocos2d-x 2.2.2)。
空行が2行分あれば、末尾2行分が切れるはずだ。

これを回避するには、”\n \n”のように、空行にスペースをひとつ入れてやると良い。
そうすれば、そこは空行ではなく「文字のある行」として、きちんと高さの計算が合うらしい。

ただし、iOS7の場合で、条件によってはこれでも末尾が切れる場合があるようだ。
原因を探ると、結局のところ、CCImageのdrawInRectに行き当たった。

ちなみに、CCLabelTTFで文字の縁取りを行うenableStrokeがiOS7で正常に機能しないという話があって、これもCCImageのdrawInRectが原因らしい。
というわけで、これを修正することで両方の不具合を解消できる。

CCLabelTTFのenableStrokeをiOS7に対応させる – Poppin Games Engineer Blog

こちらのブログにCCImageのdrawInRectをiOS7に対応させる方法が記載されているので、ありがたく使わせてもらいました。

CCImage.mm内に

// XXX: ios7 casting

というコメントがあるので、その下を書き換える。
OSの判別処理を含めて、こんな感じかな。

unsigned uHoriFlag = eAlign & 0x0f;
if ([[UIDevice currentDevice].systemVersion floatValue] < 7.f) {
    UITextAlignment align = 
        (UITextAlignment)((2 == uHoriFlag) ? UITextAlignmentRight : 
            (3 == uHoriFlag) ? UITextAlignmentCenter : UITextAlignmentLeft);
    [str drawInRect:CGRectMake(textOriginX, textOrigingY, textWidth, textHeight) withFont:font lineBreakMode:NSLineBreakByWordWrapping alignment:(NSTextAlignment)align];
}
else {
    NSMutableParagraphStyle *paragraphStyle = [[[NSMutableParagraphStyle alloc] init] autorelease];
    paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
    paragraphStyle.alignment = 
        ((2 == uHoriFlag) ? NSTextAlignmentRight :
             (3 == uHoriFlag) ? NSTextAlignmentCenter : NSTextAlignmentLeft);
    UIColor *strokeColor = [UIColor colorWithRed:pInfo->strokeColorR green:pInfo->strokeColorG blue:pInfo->strokeColorB alpha:1.0];
    UIColor *fontColor = [UIColor colorWithRed:pInfo->tintColorR green:pInfo->tintColorG blue:pInfo->tintColorB alpha:1.0];
    NSDictionary *attribute = 
        @{NSFontAttributeName:font,
            NSParagraphStyleAttributeName:paragraphStyle,
            NSForegroundColorAttributeName:fontColor,
            NSStrokeColorAttributeName:strokeColor,
            NSStrokeWidthAttributeName:@(-pInfo->strokeSize * 4.f)
        };
    [str drawInRect:CGRectMake(textOriginX, textOrigingY, textWidth, textHeight) withAttributes:attribute];
}

alignはiOS6以前でしか使わないようなので、ここに持ってきてます。

あと、NSStrokeWidthAttributeName:@(-pInfo->strokeSize * 4.f)の部分ですが、Poppin Games Engineer Blogさんのコードでは *2 となっているところを *4にしています。
縁取りの太さなんですが、iOS6の場合と比べると2倍ではまだ太さが足らなくて、4倍でちょうどのように思えるので。
でも、なぜ4倍になるのかよく分からない。

2倍なら、たとえば縁取りが外側と内側で2倍になる、ということかな?と思えもするが。
retina解像度の2倍も掛かってくるのだろうか?

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です