GLFun(22)~Texture2Dクラス(11)

2012. 01. 16
9)initWithString:dimensions:alignment:fontName:fontSize:メソッド

initWithString:dimensions:alignment:fontName:fontSize:メソッドはTextカテゴリに属している、指定した文字列と矩形領域、フォントから画像データを生成し、initWithData:pixelFormat:pixelsWide:pixelsHigh:contentSize:メソッドを呼び出してテクスチャオブジェクトを作成するメソッドです。

- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(UITextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size
{
    NSUInteger width,
        height,
        i;
    CGContextRef context;
    void* data;
    CGColorSpaceRef colorSpace;
    UIFont * font;

    font = [UIFont fontWithName:name size:size];

    width = dimensions.width;
    if((width != 1) && (width & (width - 1))) {
        i = 1;
        while(i < width)
        i *= 2;
        width = i;
    }
    height = dimensions.height;
    if((height != 1) && (height & (height - 1))) {
        i = 1;
        while(i < height)
        i *= 2;
        height = i;
    }

    colorSpace = CGColorSpaceCreateDeviceGray();
    data = calloc(height, width);
    context = CGBitmapContextCreate(data, width, height, 8, width, colorSpace, kCGImageAlphaNone);
    CGColorSpaceRelease(colorSpace);

    CGContextSetGrayFillColor(context, 1.0, 1.0);
    CGContextTranslateCTM(context, 0.0, height);
    CGContextScaleCTM(context, 1.0, -1.0);    //NOTE: NSString draws in UIKit referential i.e. renders upside-down compared to CGBitmapContext referential
    UIGraphicsPushContext(context);
        [string drawInRect:CGRectMake(0, 0, dimensions.width, dimensions.height) withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:alignment];
    UIGraphicsPopContext();

    self = [self initWithData:data pixelFormat:kTexture2DPixelFormat_A8 pixelsWide:width pixelsHigh:height contentSize:dimensions];

    CGContextRelease(context);
    free(data);

    return self;
}

ローカル変数)

 NSUInteger  width 画像の幅(2の累乗に補正した値)
 height 画像の高さ(2の累乗に補正した値)
 i whileループで使用するカウンタ用の変数
 CGContextRef  context 画像処理を行うためのグラフィックスコンテキスト
 void*  data テクスチャ用画像データを保持するメモリ領域
 CGColorSpaceRef  colorSpace 色空間情報
 UIFont *  font フォントオブジェクト

フォントオブジェクトの生成)

引数として受け取ったフォント名name(プロパティのnameとは別物)とフォントサイズsizeから、fontWithName:size:メソッドでフォントオブジェクトを生成します。

テクスチャ用サイズへの補正)

initWithImage:と同様にテクスチャ用の画像サイズとして、引数として受け取ったサイズdimensionsから2の累乗に補正した幅widthと高さheightを設定します。
(『GLFun(20)~Texture2Dクラス(9)』参照)

条件はほぼ同じですがwhileループの条件でsizeToFitによる制限をかけていないので、設定される大きさは元サイズを超える最小の2の累乗になります。

ビットマップグラフィックスコンテキストの生成)

このメソッドで生成する文字列のテクスチャは白色不透明の文字のため、色空間はグレースケール、色成分も各ピクセル8ビット分だけ確保することになります。

最初にCGColorSpaceCreateDeviceGrayでデバイス依存のグレースケール色空間を生成します。

次に画像データを保持するdataのメモリを、callocで高さ×幅×1バイト(8ビット)分確保します。
(『初心者のためのポイント学習C言語/ライブラリ関数一覧/calloc』参照)

続いてCGBitmapContextCreate』でビットマップグラフィックスコンテキストを生成します。

色空間がグレースケールなのでinitWithImage:のkTexture2DPixelFormat_A8の場合とほぼ同じで、第七引数がアルファチャンネル無しのkCGImageAlphaNoneになる点だけが異なります。

コンテキストの生成が済んだら、不要になった色空間をCGColorSpaceReleaseで解放します。

CGColorSpaceCreateDeviceGray

CGColorSpaceRef CGColorSpaceCreateDeviceGray(
    void
);

デバイス依存のグレースケール色空間を生成します。

戻り値はデバイス依存のグレースケール色空間です。

このオブジェクトは、CGColorSpaceReleaseを呼び出すことによって解放する責任があります。

失敗した場合はNULLを返します。

Mac OS X v10.4以降では、この色空間はもはやデバイスに依存せず、『色空間名』で説明されている汎用的なもの(kCGColorSpaceGenericGray)に置換されています。

Mac OS X v10.4以降でこの関数を使用する場合、色は汎用的な色空間にマッピングされます。

カラーマッチングをバイパスする場合は、対象となるコンテキストの色空間を使用してください。

デバイスでの色は、出力デバイス上で表示する時に依存している色空間への変換、ないしは他の方法での変更はされず、色の視覚的な外観を保持しようとはしません。

したがって、デバイスの色空間の色は異なる出力デバイス上で表示する時に、しばしば異なって表示されます。

この理由から、デバイス色空間は色の保存が重要な場合には推奨されません。

フォント色の設定)

文字列の色はコンテキストの塗りつぶし色としてCGContextSetGrayFillColor』で設定します。

第一引数は設定するコンテキストを指定します。

第二引数はグレーレベルで、黒の0.0から白の1.0までの値を指定します。

第三引数は不透明度のレベルで、透明の0.0から不透明の1.0までの値を指定します。

ここでは第二、第三引数とも1.0なので、フォント色は不透明な白色となります。

CGContextSetGrayFillColor

void CGContextSetGrayFillColor (
    CGContextRef c,
    CGFloat gray,
    CGFloat alpha
);

DeviceGray色空間内の値に現在の塗りつぶし色を設定します。

この関数を呼び出すと2つのことが起こります。

・QuartzはDeviceGrayに現在の塗りつぶし色空間を設定します。
・Quartzはグレーとアルファパラメータで指定した値に現在の塗りつぶし色を設定します。

c:現在の塗りつぶし色を設定するグラフィックスコンテキストを指定します。

gray:希望するグレーレベルを指定する値を指定します。
DeviceGray色空間は0.0(完全な黒)から1.0(完全な白)までの範囲の値の指定を許可します。

alpha:不透明度レベルの値を指定します。
値は0.0(透明)から1.0(不透明)までの範囲で指定できます。
範囲外の値は0.0または1.0にクリッピングされます。

コンテキスト内でのユーザ座標系の原点の変更)

コードの中で、『NSStringのUIKitに関連する描画、すなわちレンダリングは『CGBitmapContext』関連と比較して逆さまになります。』という注意書きがあります。

詳細は後述しますがコンテキストに文字列を描画するメソッドdrawInRect:withFont:lineBreakMode:alignment:はUIKitのメソッドなため、左上角を原点とするUIKit座標系で描画されます。

したがって左下角を原点とするCore Graphics座標系に戻した際には、x軸を中心に反転した画像になるためCGContextScaleCTMでy座標の反転を行います。

また(コードの記述順と前後しますが)、それによってy座標が負の値になるので、CGContextTranslateCTMで原点を画像の高さheight分移動させます。

CGContextScaleCTM

void CGContextScaleCTM (
    CGContextRef c,
    CGFloat sx,
    CGFloat sy
);

コンテキスト内のユーザ座標系のスケールを変更します。

c:グラフィックスコンテキストを指定します。

sx:指定されたコンテキストの座標空間のx軸をスケールする係数を指定します。

sy:指定されたコンテキストの座標空間のy軸をスケールする係数を指定します。

コンテキストへの文字列の描画)

前述の通り文字列の描画はUIKit上で行うためグラフィックスコンテキストを切り替える必要があります。

まずUIGraphicsPushContext』で、Core Graphicsのビットマップグラフィックスコンテキストで現在のコンテキストを作成します。

次にdrawInRect:withFont:lineBreakMode:alignment:で文字列を描画します。

第一引数は描画する境界矩形で、原点を(0, 0)に、サイズは元サイズとなるdimensions構造体の幅と高さを指定します。

第二引数は文字列の描画に使用するフォントで、呼び出し時の引数が渡されます。

第三引数は文字列の改行オプションで、ここでは単語の境界で折り返すUILineBreakModeWordWrapが指定されています。

第四引数は領域内での文字列の揃え方で、呼び出し時の引数が渡されます。

文字列の描画を終えたら、UIGraphicsPopContextで現在のコンテキストを破棄し、元のコンテキストに戻ります。

UIGraphicsPushContext

void UIGraphicsPushContext (
    CGContextRef context
);

指定したグラフィックスコンテキストで現在のコンテキストを作成します。

この関数は、以前のグラフィックスの状態を保存したり、指定したコンテキストで現在のコンテキストの作成に使用することができます。

この関数は、UIGraphicsPopContext関数の呼び出しと対にしてバランスを取る必要があります。

context:現在のコンテキストを作成するグラフィックスコンテキストを指定します。

drawInRect:withFont:lineBreakMode:alignment:

- (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode alignment:(UITextAlignment)alignment

指定された境界矩形、フォントそして属性を使用して、現在のグラフィックスコンテキスト内に文字列を描画します。

戻り値はレンダリングされた文字列の実際のサイズです。

rect:文字列を描画する(現在のグラフィックスコンテキストの)境界矩形を指定します。

font:レンダリングに使用するフォントを指定します。

lineBreakMode:文字列のサイズを計算するための改行オプションを指定します。
有効な値は『UILineBreakMode』を参照してください。

alignment:境界矩形内のテキストの揃え方を指定します。
有効な値は『UITextAlignment』を参照してください。

UILineBreakMode

テキストの折り返しと切り詰めのオプションです。

typedef enum {
    UILineBreakModeWordWrap = 0,
    UILineBreakModeCharacterWrap,
    UILineBreakModeClip,
    UILineBreakModeHeadTruncation,
    UILineBreakModeTailTruncation,
    UILineBreakModeMiddleTruncation,
UILineBreakMode;

UILineBreakModeWordWrap
単語の境界でのみ、折り返しまたは切り取りを行います。
これはデフォルトの折り返しオプションです。

UILineBreakModeCharacterWrap
最も近い文字の境界で、文字列の折り返しまたは切り取ります。

UILineBreakModeClip
描画矩形の終端に到達した時にテキストを切り取ります。
このオプションは文字列の終端で文字が部分的にレンダリングされる可能性があります。

UILineBreakModeHeadTruncation
行頭から(必要に応じて)テキストを切り詰めます。
複数行のテキストの場合は、最初の行のテキストのみが切り詰められます。

UILineBreakModeTailTruncation
行末から(必要に応じて)テキストを切り詰めます。
複数行のテキストの場合は、最後の行のテキストのみが切り詰められます。

UILineBreakModeMiddleTruncation
行の中央から(必要に応じて)テキストを切り詰めます。
複数行のテキストの場合は、行の中央のテキストのみが切り詰められます。

(矩形領域内で描画する)指定されたポイントで描画するための方法に対し、これらのオプションは文字列に適用される切り取り動作を指定します。

UIGraphicsPopContext

void UIGraphicsPopContext (
    void
);

スタックの先頭から現在のグラフィックスコンテキストを削除して、以前のコンテキストを復元します。

この関数はUIGraphicsPushContext関数の呼び出しとのバランスを取るために使用されます。

この関数は、アプリケーションのメインスレッドからのみ呼び出す必要があります。

テクスチャオブジェクトの作成)

作成した文字列からの画像データを元に、initWithData:pixelFormat:pixelsWide:pixelsHigh:contentSize:を呼び出してテクスチャオブジェクトを生成、バインド、設定します。
(同メソッドについては『GLFun(16)~Texture2Dクラス(5)』を参照してください)

ピクセルフォーマットはkTexture2DPixelFormat_A8を指定します。

コンテキストと画像データの解放)

不要となったコンテキストはCGContextReleaseで、画像データはfreeで解放します。

実行について)

GLFunViewクラスのdrawメソッドで、セグメンテッドコントロールでImageを選択した場合の実装は後で解説するのですが、画像ファイルを描画するinitWithImage:の代わりにinitWithString:dimensions:alignment:fontName:fontSize:メソッドを呼び出す場合の注意点を紹介します。

Texture2Dオブジェクトspriteを次のように設定します。

self.sprite = [[Texture2D alloc] initWithString:@"\アッカリ~ン/" dimensions:CGSizeMake(220.0, 40.0) alignment:UITextAlignmentCenter fontName:@"Hiragino Kaku Gothic ProN" fontSize:36.0];

文字列を『\アッカリ~ン/』、表示領域を220×40ピクセル、文字揃えはUITextAlignmentCenterで中央揃えに、フォントはヒラギノ角ゴシックの36ポイントを指定して実行すると下記のようになります。

7724

赤はデフォルトの選択色で、選択色を変えればその色になります。

しかし画像データはグレースケールで作りましたから色が付くことはないはずで、そもそも文字が表示されません。

これはinitWithData:pixelFormat:pixelsWide:pixelsHigh:contentSize:メソッド(『GLFun(16)~Texture2Dクラス(5)』参照)のkTexture2DPixelFormat_A8の場合、glTexImage2Dでテクスチャの色要素およびピクセルデータのフォーマットをアルファ成分であるGL_ALPHAに設定しているため、色成分と認識されず正常に表示できないようです。

そこでGL_ALPHAから輝度値を示すGL_LUMINANCEに変更します。

glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);

7725

すると正常に文字列が表示されるようになります。

GLFunでは文字列テクスチャの使用を想定していないので対応していないのは仕方ありませんが、アルファ成分のみの画像と併用するのであればTexture2DPixelFormatの定数に輝度用の値を追加して上記のように設定すると良いかもしれません。



参考文献

iOS OpenGL ESプログラミングガイド

OpenGL ES 1.1 Reference Pages

CGColorSpace Reference

CGContext Reference

UIKit Function Reference

NSString UIKit Additions Reference

初心者のためのポイント学習C言語/ライブラリ関数一覧/calloc

はじめてのiPhone3プログラミングはじめてのiPhone3プログラミング
(2009/12/17)
Dave Mark、Jeff LaMarche 他

商品詳細を見る

Beginning Ios 6 Development: Exploring the Ios SdkBeginning Ios 6 Development: Exploring the Ios Sdk
(2012/12/26)
David Mark、Jack Nutting 他

商品詳細を見る






SoundLink Mini Bluetooth speaker_ii_limited
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
05 | 2017/06 | 07
Sun Mon Tue Wed Thu Fri Sat
- - - - 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 -
Recent Articles
iTunes


Swift
Categories
Tips
Profile

水月杏香

Author:水月杏香
永遠の初心者プログラマ。

Wish List
WACOM


ARC
Technical Q&A
情報プロパティリストキー
Start Developing iOS Apps Today
BOSE

SoundLink Mini Bluetooth speaker_ii_limited
Reference
NSApplicationDelegateプロトコル
NSArrayクラス
NSAutoreleasePoolクラス
NSBundleクラス
NSBundle UIKit追加分
NSCalendarクラス
NSCoderクラス
NSCodingプロトコル
NSCopyingプロトコル
NSDataクラス
NSDateクラス
NSDateFormatterクラス
NSDictionaryクラス
NSEntityDescriptionクラス
NSEnumeratorクラス
NSErrorクラス
NSExceptionクラス
NSFetchRequestクラス
NSFileHandleクラス
NSFileManagerクラス
NSIndexPathクラス
NSIndexPath UIKit追加分
NSKeyedArchiverクラス
NSKeyedUnarchiverクラス
NSKeyValueCodingプロトコル
NSLocaleクラス
NSManagedObjectクラス
NSManagedObjectContextクラス
NSManagedObjectModelクラス
NSMutableArrayクラス
NSMutableCopyingプロトコル
NSMutableDictionaryクラス
NSMutableSetクラス
NSNotificationクラス
NSNotificationCenterクラス
NSNullクラス
NSNumberクラス
NSObjectクラス
NSObject UIKit追加分
NSObjectプロトコル
NSPersistentStoreクラス
NSPersistentStoreCoordinatorクラス
NSPredicateクラス
NSPropertyListSerializationクラス
NSRunLoopクラス
NSSetクラス
NSStringクラス
NSString UIKit追加分
NSTimerクラス
NSTimeZoneクラス
NSURLクラス
NSURLProtectionSpaceクラス
NSURLRequestクラス
NSUserDefaultsクラス
NSValueクラス

UIActionSheetクラス
UIActionSheetDelegateプロトコル
UIActivityIndicatorViewクラス
UIAlertViewクラス
UIAlertViewDelegateプロトコル
UIApplicationクラス
UIApplicationDelegateプロトコル
UIBarButtonItemクラス
UIBarItemクラス
UIButtonクラス
UIColorクラス
UIControlクラス
UIDatePickerクラス
UIDeviceクラス
UIEventクラス
UIFontクラス
UIGestureRecognizerクラス
UIImageクラス
UIImageViewクラス
UIKit Function
UILabelクラス
UINavigationControllerクラス
UINavigationItemクラス
UIPickerViewクラス
UIPickerViewDataSourceプロトコル
UIPickerViewDelegateプロトコル
UIPinchGestureRecognizerクラス
UIResponderクラス
UIScreenクラス
UIScrollViewクラス
UISearchBarクラス
UISearchBarDelegateプロトコル
UISegmentedControlクラス
UISliderクラス
UISwipeGestureRecognizerクラス
UISwitchクラス
UITableViewクラス
UITableViewCellクラス
UITableViewControllerクラス
UITableViewDataSourceプロトコル
UITableViewDelegateプロトコル
UITapGestureRecognizerクラス
UITextFieldクラス
UITextFieldDelegateプロトコル
UITextInputTraitsプロトコル
UITextViewクラス
UITextViewDelegateプロトコル
UIToolbarクラス
UITouchクラス
UIViewクラス
UIViewControllerクラス
UIWebViewクラス
UIWebViewDelegateプロトコル
UIWindowクラス

AVAudioPlayerクラス
AVAudioPlayerDelegateプロトコル

CADisplayLinkクラス
CAEAGLLayerクラス
CALayerクラス

CGAffineTransform
CGBitmapContext
CGColor
CGColorSpace
CGContext
CGGeometry
CGImage
CGPath

EAGLContextクラス
EAGLDrawableプロトコル

Foundation Constants
Foundation Data Types
Foundation Functions

MPMediaItemクラス
MPMediaItemArtworkクラス
MPMediaPlaylistクラス
MPMediaPropertyPredicateクラス
MPMediaQueryクラス
MPMusicPlayerControllerクラス

Randomization Services

System Sound Services
Amazon


OpenGL ES
SQLite
Monthly Archives
Recent Comments
Recent TrackBacks
RSS Link
Visitors
QR Code
QR