トップページ > 空即是色 > 2007年の記事 > MacOSX環境のOpenGLで日本語文字列の描画

空即是色 MacOSX環境のOpenGLで日本語文字列の描画

2007年 10月07日

Cocoaを利用することで、意外と簡単にできる。
大きな流れとしては、

  1. NSFontに日本語フォント(例えばヒラギノ)を設定する。
  2. NSAttributedStringを↑のNSFontで作成。
  3. NSImageに文字を描画。
  4. それを、ビットマップ画像(NSBitmapImageRep)に変換する。
  5. んで、OpenGLのテクスチャに登録して描画

日本語文字列を簡単に描画できるGLTexStringクラスを作ったので、詳しくは下記を参照。

2007年10月8日追記
  • メモリ管理が適当だったので、その辺を修正しました。
  • /Developer/Examples/OpenGL/Cocoa/GLImageWall/に、stringTextureというより汎用的に使用できるクラスがあります(via hrkw氏)。

GLTexStringの使い方

GLTexString *texStr;
 
- (void)initGL {
	glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
	glClearDepth( 1.0f );
	glDisable(GL_CULL_FACE);
	glEnable( GL_BLEND );
	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
 
	NSString *string = [NSString stringWithCString:"こんにちは、世界!"];
	texStr = [[GLTexString alloc] initWithString:string];
}
 
- (void)loop {
	glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
 
	gluLookAt( 0, 0, 8, 0, 0, 0, 0, 1, 0 );
 
	glPushMatrix();
	glTranslatef( -4.5, -0.5, 0 );
	glColor3f( 1, 1, 1 );
	[texStr draw];
	glPopMatrix();
 
	[[self openGLContext] flushBuffer];
}

GLTexString.h

#import <Cocoa/Cocoa.h>
#import <OpenGL/gl.h>
#import <OpenGL/OpenGL.h>
 
#define TEX_WIDTH 128
#define TEX_HEIGHT 128
#define FONT_NAME @"HiraKakuPro-W6"
/*
 * HiraKakuPro-W3
 * HiraKakuPro-W6
 * HiraKakuStd-W8
 * HiraMaruPro-W4
 * HiraMinPro-W3
 * HiraMinPro-W6
 */
 
@interface GLTexString : NSObject
{
	NSString *string;
	NSAttributedString *attrString;
	GLuint *texId;
}
 
- (id) initWithString:(NSString*)aString;
- (void) draw;
- (void) dealloc;
 
@end

GLTexString.m

#import "GLTexString.h"
 
@implementation GLTexString
 
- (id) initWithString:(NSString*)aString {
	[super init];
 
	int i, strSize;
	float fontSize;
	NSFont *font;
	NSDictionary *attrsDictionary;
	NSAttributedString *singleChar;
	NSImage **images;
	NSBitmapImageRep **imageReps;
	NSImage* img;
	NSPoint point;
	NSSize size, screenResolution;
 
	// copy to string from aString
	string = [NSString stringWithString:aString];
 
	// alloc texture id and image buffer
	strSize = [string length];
	texId = (GLuint*)malloc( sizeof(GLuint)*strSize );
	images = (NSImage**)malloc( sizeof(NSImage*)*strSize );
	imageReps = (NSBitmapImageRep**)malloc( sizeof(NSBitmapImageRep*)*strSize );
	for( i = 0; i < strSize; i++ ){
		images[i] = [[NSImage alloc] initWithSize:NSMakeSize( TEX_WIDTH, TEX_HEIGHT )];
	}
 
	// font settings
	screenResolution = [[[[NSScreen mainScreen] deviceDescription] objectForKey:NSDeviceResolution] sizeValue];
	fontSize = TEX_WIDTH * 72.0/screenResolution.width;
	font = [NSFont fontWithName:FONT_NAME size:fontSize];
	attrsDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
		font, NSFontAttributeName,
		[NSColor whiteColor], NSForegroundColorAttributeName,
		[NSColor clearColor], NSBackgroundColorAttributeName,
		nil
	];
 
	// alloc attributed string
	attrString = [[NSAttributedString alloc] initWithString:string attributes:attrsDictionary];
 
	// create texture id
	glEnable( GL_TEXTURE_2D );
	glGenTextures( strSize, texId );
 
	// build texture image
	for( i = 0; i < strSize; i++ ){
		img = images[i];
		singleChar = [attrString attributedSubstringFromRange:NSMakeRange(i,1)];
		// setting background color
		[img setBackgroundColor:[NSColor clearColor]];
		// calc center position
		size = [singleChar size];
		point = NSMakePoint( (TEX_WIDTH-size.width)/2, (TEX_HEIGHT-size.height)/2 );
		// draw character to image
		[img lockFocus];
		[singleChar drawAtPoint:point];
		[img unlockFocus];
 
		// alloc bitmap image from NSImage
		imageReps[i] = [[NSBitmapImageRep alloc] initWithData:[img TIFFRepresentation]];
 
		// texture settings
		glBindTexture( GL_TEXTURE_2D, texId[i] );
		glTexImage2D(
			GL_TEXTURE_2D, 0, GL_RGBA,
			TEX_WIDTH, TEX_HEIGHT, 0,
			[imageReps[i] hasAlpha] ? GL_RGBA :GL_RGB,
			GL_UNSIGNED_BYTE,
			[imageReps[i] bitmapData]
		);
		glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
		glBindTexture( GL_TEXTURE_2D, 0 );
	}
	glDisable( GL_TEXTURE_2D );
 
	// release
	for( i = 0; i < strSize; i++ ){
		[imageReps[i] release];
		[images[i] release];
	}
	free( imageReps );
	free( images );
 
	return self;
}
 
- (void) draw {
	int i, strSize;
	strSize = [string length];
	glEnable( GL_TEXTURE_2D );
	for( i = 0; i < strSize; i++ ){
		glBindTexture( GL_TEXTURE_2D, texId[i] );
		glBegin(GL_POLYGON);
		glTexCoord2f( 0, 1 );
		glVertex3f( i*1, 0, 0 );
		glTexCoord2f( 1, 1 );
		glVertex3f( i*1+1, 0, 0 );
		glTexCoord2f( 1, 0 );
		glVertex3f( i*1+1, 1, 0 );
		glTexCoord2f( 0, 0 );
		glVertex3f( i*1, 1, 0 );
		glEnd();
	}
	glDisable( GL_TEXTURE_2D );
}
 
- (void) dealloc {
	glDeleteTextures( [string length], texId );
	free( texId );
	[attrString release];
	[super dealloc];
}
 
@end

ページの先頭へ戻る

トラックバック

この記事のトラックバックURL:http://null-null.net/mt/mt-tb.cgi/488

ページの先頭へ戻る

コメント

hrkw (2007年10月07日)

/Developer/Examples/OpenGL/Cocoa/GLImageWall/
にstringTextureってクラスが入ってて、そいつは結構よくできてますよ。
ちょうど某展で日本語やってくれって言われて使ったところでした。
でもって、このサンプル自体かなり用途限定なので、ぜひマルチモニタで見てやってください。

nogami (2007年10月08日)

おー勉強になります。
GL_TEXTURE_RECTANGLE_EXTを使うと、
2の累乗以外のサイズもテクスチャに設定できるとは。
今回は一文字ごとにテクスチャにして操作したいので、
stringTextureはそれ以外の所で使ってみようと思います。

>ぜひマルチモニタで見てやってください。
見てみたものの、マルチモニタ環境ではないので用途は謎でした…orz

さ (2007年10月08日)

色々やってみた感じQuesoGLC(なぜか発音できない)が一番楽だったよー
依存ライブラリが2つぐらいあるけど、UTF-8エンコードのconst char*を渡すと勝手に書いてくれます。

http://quesoglc.sourceforge.net/

nogami (2007年10月09日)

おーこれは、MacOSX環境に限らずマルチプラットフォーム使えるのかな。
試しにmake installして、適当なサンプルをコンパイルしてみたら、いろいろエラーが…
これは使うまでがハードル高いかも。

ページの先頭へ戻る

iPhoneDev.null-null.net

コメントの一覧

特定のキーワードにマッチした内容の記事をTumblrやMovableTypeに自動的に投稿する
  • nogami
    (2008年03月18日)
  • プールデザイン菅沼
    (2008年03月25日)
  • yuiyui
    (2008年04月12日)
MacOSX環境のOpenGLで日本語文字列の描画
  • nogami
    (2007年10月08日)

  • (2007年10月08日)
  • nogami
    (2007年10月09日)
ウップス!
  • あるぱっか
    (2007年05月24日)
  • nogami
    (2007年05月28日)
  • あるぱっか
    (2007年05月30日)

RSSフィード

このブログの更新情報を、XML(ATOM)フォーマットで提供しています。
ご利用のRSSリーダーやアプリケーションにRSSフィードを登録してください。

ページの先頭へ戻る


Copyright(c) Daisuke Nogami. All Right Reserved.