SDL_TTFで文字列を表示 その2
前回紹介しましたSDL_TTFの使い方ですが、
一部ロジック的におかしな所がありましたので、
再度作り直しました。
SDL_TTF
サンプルプログラムのダウンロードはこちら:
SDL_TTF_sample
キーボードを操作するごとに、プログラム内に埋め込んだ文字列を表示します。
マウスボタンを操作するごとに、表示されている文字列の色を変更します。
libttf.c
/**************************************** 概要:TTFフォント読み込み・描画 詳細:SDL_TTFを使用して描画を行う ファイル名:libttf.c *****************************************/ #include "libttf.h" #include <SDL/SDL_ttf.h> #include <stdio.h> #include <string.h> #pragma comment(lib,"SDL_ttf.lib") #define MAX_COUNT (512) /****************************************/ /* 構造体宣言 */ /****************************************/ /****************************************/ /* 作成済みの文字列データがあれば */ /* 使いまわす為、リストにして保存 */ /* フォントデータのリスト */ /****************************************/ typedef struct ttf_list { SDL_Surface *text_img; /* 作成された文字データを保存 */ char *text; /* 文字列データ */ struct ttf_list *next; /* 次の文字列データへ */ Uint32 color; /* 現在の描画色 */ }TTF_List; /****************************************/ /* フィールド */ /****************************************/ static SDL_Surface *screen; static TTF_Font *font; static TTF_List *top_imglist; static Uint32 defColor; static SDL_Rect screen_range; /****************************************/ /* 関数定義 */ /****************************************/ static void create_list(SDL_Surface *surface, const char *str); static void delete_list(void); static SDL_Surface *img_get(const char *str); static SDL_Surface *render_text(const char *str,Uint32 color); static int copy_surface(SDL_Surface *src,SDL_Surface *dst); static int make_range(SDL_Rect *rect); static int remake_color(SDL_Surface *img, Uint32 col); static int lock(void); static void unlock(void); static Uint32 length(const char *str); static TTF_List *get_list(const char *str); /****************************************/ /* 関数実装 */ /****************************************/ /****************************************/ /* 概要:SDL_TTFの初期化 */ /* 詳細:描画先スクリーンとパス */ /* フォントサイズを設定 */ /* 引数:s 描画先スクリーン */ /* file_path ファイルのパス */ /* Uint8 フォントサイズ */ /* 返却:0:初期化失敗 */ /* 1:初期化成功 */ /****************************************/ int ttf_init(SDL_Surface *s,const char *file_path, Uint8 size) { if( !TTF_WasInit() && s != NULL && file_path != NULL) { if(TTF_Init() == -1) return 0; font = TTF_OpenFont (file_path,size%TTF_MAXSIZE); if(font == NULL) { TTF_Quit(); return 0; } screen = s; defColor = 0x00000000; }else{ return 0; } return 1; } /****************************************/ /* 概要:ライブラリの終了 */ /* 詳細:SDL_TTFライブラリの終了 */ /* 引数:無し */ /* 返却:無し */ /****************************************/ void ttf_dest(void) { delete_list(); if(font != NULL) TTF_CloseFont(font); if( TTF_WasInit() ) TTF_Quit(); font = NULL; } /****************************************/ /* 概要:フォントファイルを初期化 */ /* 詳細:フォントサイズを変える */ /* 引数:ファイルパス */ /* 返却:成功:1 失敗:0 */ /****************************************/ int ttf_remake(const char *file_path, Uint8 size) { if( !TTF_WasInit() ) { if(TTF_Init() == -1 || screen == NULL) return 0; } if(font != NULL) TTF_CloseFont(font); font = NULL; font = TTF_OpenFont (file_path,size % TTF_MAXSIZE); if( font == NULL) return 0; return 1; } /****************************************/ /* 概要:通常のフォントカラーを設定 */ /* 詳細:通常のフォントカラーを設定 */ /* 引数:32ビットカラー */ /* 返却:無し */ /****************************************/ void ttf_color(Uint32 color) { defColor = color; } /****************************************/ /* 概要:文字列をスクリーンに描画 */ /* 詳細:座標指定して文字列描画 */ /* SDL_TTFの関数を利用して作成した */ /* 文字列データをリストに保存 */ /* 同じ文字列を再描画する場合は、 */ /* バッファに格納された文字列イメージ */ /* を使い描画する */ /* 引数:文字列、横軸、縦軸 */ /* 返却:文字列描画先の矩形情報 */ /****************************************/ SDL_Rect ttf_put(const char *str,int x,int y) { SDL_Surface *img; SDL_Rect rect = { 0,0,0,0 }; /********************************/ /* 文字列イメージを取得 */ /********************************/ img = img_get(str); if(img == NULL) return rect; rect.h = img->h; rect.w = img->w; rect.x = x; rect.y = y; /********************************/ /* デフォルトカラーに変更 */ /********************************/ if( get_list(str)->color != defColor ) remake_color(img, defColor); /********************************/ /* 描画範囲を作り直す */ /********************************/ make_range( &rect ); SDL_BlitSurface(img, NULL, screen, &rect); return rect; } /****************************************/ /* 概要:色を指定して文字列を描画 */ /* 詳細:色を指定して文字列を描画 */ /* 引数:文字列、横軸、縦軸、描画色 */ /* 返却:文字列描画先の矩形情報 */ /****************************************/ SDL_Rect ttf_put_color(const char *str,int x,int y, Uint32 color) { SDL_Rect rect = { 0,0,0,0 }; return rect; } /****************************************/ /* 概要:文字列をグラデーションで描画 */ /* 詳細:文字列をグラデーションで描画 */ /* 引数:文字列、フォントの情報 */ /* 返却:文字列描画先の矩形情報 */ /****************************************/ SDL_Rect ttf_put_effect(const char *str,TTF_Info *info) { SDL_Rect rect = { 0,0,0,0 }; return rect; } /****************************************/ /* 概要:文字列をグラデーションで描画 */ /* 詳細:文字列をグラデーションで描画 */ /* 引数:文字列、フォントの情報 */ /* 返却:文字列描画先の矩形情報 */ /****************************************/ SDL_Rect ttf_put_effect2(const char *str,TTF_Info *info) { SDL_Rect rect = { 0,0,0,0 }; return rect; } /****************************************/ /* 概要:保存された文字列バッファ消去 */ /* 詳細:リストをクリアする */ /* 引数:無し */ /* 返却:無し */ /****************************************/ void ttf_clean(void) { delete_list(); } /****************************************/ /* 概要:リスト生成 */ /* 詳細:イメージリストの生成 */ /* 引数:生成する文字列 */ /* 返却:無し */ /****************************************/ static void create_list(SDL_Surface *surface, const char *str) { TTF_List *new_font = (TTF_List*)malloc(sizeof(TTF_List)); TTF_List **tmp; if(new_font == NULL) return; new_font->color = defColor; new_font->text_img = surface; new_font->next = NULL; new_font->text = (char*)malloc(length(str)); memcpy(new_font->text, str, length(str)); for(tmp = &top_imglist; *tmp != NULL; tmp = &(*tmp)->next); *tmp = new_font; } /****************************************/ /* 概要:リスト削除 */ /* 詳細:画像リスト削除 */ /* 引数:無し */ /* 返却:無し */ /****************************************/ static void delete_list(void) { TTF_List *node = top_imglist; TTF_List *tmp; while(node != NULL) { tmp = node->next; /* 次のリストを退避 */ if(node->text_img != NULL) SDL_FreeSurface(node->text_img); /* 画像イメージの解放 */ if(node->text != NULL) free(node->text); /* 文字列領域の解放 */ memset(node,0,sizeof(TTF_List)); /* Clean Memory */ free(node); /* メモリの解放 */ node = tmp; /* 次のリストへ */ } } /****************************************/ /* 概要:文字列イメージバッファの取得 */ /* 詳細:文字列画像データを取得 */ /* 引数:文字列 */ /* 返却:文字列画像データ */ /****************************************/ static SDL_Surface *img_get(const char *str) { SDL_Surface *img; TTF_List *tmp; tmp = get_list(str); if( tmp == NULL ) { img = render_text(str,defColor); create_list(img,str); } else { img = tmp->text_img; } return img; } /****************************************/ /* 概要:テキストイメージの作成 */ /* 詳細:テキストイメージの作成 */ /* 引数:文字列、カラー */ /* 返却:生成されたイメージ */ /****************************************/ static SDL_Surface *render_text(const char *str,Uint32 color) { SDL_Color c; SDL_Surface *img,*tmp; SDL_GetRGB(color, screen->format, &c.r, &c.g, &c.b); /********************************/ /* フォントイメージを作る */ /********************************/ tmp = TTF_RenderUTF8_Solid(font, str, c); /********************************/ /* 画像を画面フォーマットに変換*/ /********************************/ img = SDL_DisplayFormatAlpha(tmp); /********************************/ /* Release The Font image */ /********************************/ SDL_FreeSurface( tmp ); return img; } /****************************************/ /* 概要:描画先矩形情報の調整 */ /* 詳細:描画先から溢れた場合の調整 */ /* 引数:矩形情報 */ /* 返却:0:未調整 1:調整済み */ /****************************************/ static int make_range(SDL_Rect *rect) { if(screen != NULL) { Uint16 h = (Uint16)screen->h; Uint16 w = (Uint16)screen->w; if(rect->h >= h) rect->h = h; if(rect->w >= w) rect->w = w; if(rect->y >= h - rect->h) rect->y = h - rect->h; else if(rect->y < 0) rect->y = 0; if(rect->x >= w - rect->x) rect->x = w - rect->x; else if(rect->x < 0) rect->x = 0; return 1; } return 0; } /****************************************/ /* 概要:画像の色を再調整する */ /* 詳細:バッファに確保された色を変更 */ /* 引数:文字列イメージ */ /* 返却:0:変更失敗 1:変更成功 */ /****************************************/ static int remake_color(SDL_Surface *img, Uint32 col) { Uint32 x,y; /* マスクする画像の横軸、縦軸 */ Uint32 w,h; /* マスクする画像の幅、高さ */ SDL_PixelFormat *fmt = img->format; /* ピクセルフォーマットを取得 */ Uint8 bit_pxl = fmt->BitsPerPixel; /* 1ピクセルのビット数を算出 */ Uint8 byt_pxl = fmt->BytesPerPixel; /* 1ピクセルのバイト数を算出 */ Uint32 *pixels = img->pixels; /* ピクセルデータの先頭アドレス */ Uint16 pitch = img->pitch; /* 1スキャンラインのバイト数 */ Uint16 bpp = img->format->BytesPerPixel; Uint32 *msk_pxl; /* マスクするピクセルのアドレス */ if( bit_pxl == 8 || !lock() ) { return 0; } /****************************/ /* RGBカラー値をピクセル */ /* フォーマットに写像後 */ /* 変換後の値を取得 */ /****************************/ col = SDL_MapRGBA(fmt, (col&fmt->Rmask)>>fmt->Rshift, (col&fmt->Gmask)>>fmt->Gshift, (col&fmt->Bmask)>>fmt->Bshift, fmt->Amask>>fmt->Ashift ); y = 0; /* マスクする画像データの縦軸 */ h = img->h; /* マスクする画像データの高さ */ while( y < h ) { x = 0; /* マスクする画像データの横軸 */ w = img->w; /* マスクする画像データの幅 */ while( x < w ) { /****************************************/ /* マスクするアドレスを取得 */ /****************************************/ msk_pxl = (Uint32*)((Uint32)pixels + (x * bpp) + (pitch * y)); /****************************************/ /* アルファ値を抽出する */ /* アルファ値0でなければマスクする */ /****************************************/ if( *msk_pxl & fmt->Amask ) { /************************************************/ /* 1ピクセルのビット数により処理を分ける */ /************************************************/ switch( bit_pxl ) { /* 8ビットピクセルデータの色を変更 */ case 8: /* 8_BitsPerPixels NoSupport */ break; /* 16ビットピクセルデータの色を変更 */ case 16: *(Uint16*)msk_pxl = col; break; /* 24ビットピクセルデータの色を変更 */ case 24: /* エンディンアンにより処理を分ける */ /* 何故かここだけエンディアンを意識する...(*´д`*) */ #if (SDL_BYTEORDER == SDL_BIG_ENDIAN) /* Mac系OSの場合 */ msk_pxl[0] = (col >> 16) & 0xff; msk_pxl[1] = (col >> 8) & 0xff; msk_pxl[2] = col & 0xff; #else /* Windows系OSの場合 */ msk_pxl[0] = col & 0xff; msk_pxl[1] = (col >> 8) & 0xff; msk_pxl[2] = (col >> 16) & 0xff; #endif break; /* 32ビットピクセルデータの色を変更 */ case 32: *(Uint32*)msk_pxl = col; break; /* その他のピクセルデータの色を変更 */ default: /* No Support */ break; } } x++; /* 次の横軸にアクセスする */ } y++; /* 次の縦軸にアクセスする */ } /* カラー変更の終了 */ unlock(); return 1; } static int lock(void) { if(SDL_MUSTLOCK(screen)) { if(SDL_LockSurface(screen) < 0) return 0; } return 1; } static void unlock(void) { if(SDL_MUSTLOCK(screen)) { SDL_UnlockSurface(screen); } } /****************************************/ /* 概要:文字数返却 */ /* 詳細:strnlen()使用 */ /* 引数:文字列 */ /* 返却:文字数(\0を含む) */ /****************************************/ static Uint32 length(const char *str) { return (Uint32)strnlen(str,MAX_COUNT) + 1; } /****************************************/ /* 概要:画像保存リスト返却 */ /* 詳細:strnlen()使用 */ /* 引数:文字列 */ /* 返却:画像リスト */ /****************************************/ static TTF_List *get_list(const char *str) { TTF_List *tmp; char *text; if( top_imglist != NULL ) { tmp = top_imglist; do { text = (char*)tmp->text; if( !strncmp(text, str, length(text)) ) return tmp; tmp = tmp->next; } while(tmp != NULL); } return NULL; } /**************************************** end libttf.c *****************************************/ |