フォント名を取得

フォントファイルからフォント名を取得するモジュールを作ったのでこちらで公開してみます。
いろいろと中途半端なところがありますが、とりあえず公開しておいて後日更新することにします。

使い方

このモジュールを使用することで以下の命令が有効になります。

get_fontname

この命令に指定するパラメータは、

第一パラメータには フォントファイルへのパス
第二パラメータには 結果を受け取る変数

を指定します。
「例」

get_fontname "font.ttf", getname

なおフォントファイルの対応形式は、

TTF, TTC, OTF

のみになっています。

フォントのバージョン情報など多々無視してたり、私自身フォントについて詳しい訳でもないので、対応形式であっても上手く読み込めない物もあるかもしれません。何か問題があれば報告して頂ければありがたいです。
もしくは wiki なので修正してくださっても構いません、むしろ助かります。

モジュール

//	モジュールの説明 :
//	これは TrueType(Collection 対応), OpenType の
//	フォントファイルからフォント名を取得するモジュールです。
//
//	このモジュールが提供する命令 :
//	get_fontname	# ttf, ttc, otf 形式のフォントファイルのパスからフォント名を取得する


#ifndef mod_getfontname

#module mod_getfontname

	// 対応したフォントファイルからフォント名を取得する(ttf, ttc, otf に対応)
	// get_fontname fontpath, getdata
	// fontpath	: 取得するフォントのファイル名
	// getdata	: 取得したフォント名を受け取る変数
	// 戻り値	: 取得したフォント名の数が返る(失敗したら 0 が返る)

	#deffunc get_fontname str fontpath, var getdata

		// ファイルの存在確認
		exist fontpath
		if strsize = -1	:return 0

		// 拡張子によって処理を分ける
		switch getpath(fontpath, 2 | 16)
			// そのまま TTF として取得する
			case ".ttf"
			case ".otf"
				get_fontname_ttf fontpath, getdata
				swbreak
			// TTC ヘッダーから TTF のオフセットを読み取ってそこから取得する
			// (get_fontname_ttc 内で get_fontname_ttf をオフセット付きで実行)
			case ".ttc"
				get_fontname_ttc  fontpath, getdata
				swbreak
			default
				return 0
				swbreak
		swend

		return stat


	// TTC 形式のフォントファイルからフォント名を取得する
	// get_fontname_ttc fontpath, getdata
	// fontpath	: 取得するフォントのファイル名
	// getdata	: 取得したフォント名を受け取る変数
	// 戻り値	: 取得したフォント名の数が返る(失敗したら 0 が返る)

	#deffunc local get_fontname_ttc str fontpath, var getdata

		// TTCヘッダーのオフセットテーブルへのオフセット配列直前までを読み込む
		sdim TTC_Header, 12
		bload fontpath, TTC_Header, 12

		// 読み込んだ TTCヘッダー部分のデータを個別変数に取り出す
		TTCTag = ""	:lpoke TTCTag, 0, lpeek(TTC_Header, 0)
;		Version = lpeek_big2litle(TTC_Header, 4)
		numFonts = lpeek_big2litle(TTC_Header, 8)

		// ttc フォントファイルじゃなかったら処理しない
		if TTCTag ! "ttcf"	:return 0

		// 取得した numFonts を元に TTCヘッダーのオフセットテーブルを配列に取得
		dim OffsetTable, numFonts
		bload fontpath, OffsetTable, 4 * numFonts, 12

		// オフセットテーブル配列をビッグエンディアンからリトルエンディアンに変換して格納し直す
		repeat numFonts
			OffsetTable(cnt) = lpeek_big2litle(OffsetTable(cnt))
		loop

		// オフセットテーブルへのオフセットを使ってフォント名を取り出す
		getdata = ""
		repeat numFonts
			get_fontname_ttf fontpath, fontname, OffsetTable(cnt)
			if cnt > 0	:getdata += "\n"
			getdata += fontname
		loop

		return numFonts


	// TTF 形式のフォントファイルからフォント名を取得する
	// get_fontname_ttc fontpath, getdata
	// fontpath	: 取得するフォントのファイル名
	// getdata	: 取得したフォント名を受け取る変数
	// 戻り値	: 取得すれば 1 が、出来なければ 0 が返るが今のところ 1 しか返らない

	#deffunc local get_fontname_ttf str fontpath, var getdata, int offset_position

		// フォントの始めのオフセットテーブルの情報を読み込む
		dim offset_table, 3
		bload fontpath, offset_table, 12, offset_position
		sfnt_version  = offset_table
		numTables     = wpeek_big2litle(offset_table, 4)
		searchRange   = wpeek_big2litle(offset_table, 6)
		entrySelector = wpeek_big2litle(offset_table, 8)
		rangeShift    = wpeek_big2litle(offset_table, 10)

		// 指定したタグ名のテーブルを探しそこから値を取得
		dim table_record, 4 * numTables
		bload fontpath, table_record, 16 * numTables, 12 + offset_position
		tr_tag = ""
		repeat numTables
			index = cnt * 4
			memcpy tr_tag, table_record(index), 4
			if tr_tag = "name"	:break
		loop
		tr_offset = lpeek_big2litle(table_record, index * 4 + 8)
		tr_length = lpeek_big2litle(table_record, index * 4 + 12)

		// 名前テーブルから値を取得
		dim naming_table, 2
		bload fontpath, naming_table, 6, tr_offset
		nt_count        = wpeek_big2litle(naming_table, 2)
		nt_stringOffset = wpeek_big2litle(naming_table, 4)

		// ネームレコードの特定の要素を取得
		dim name_records, 3 * nt_count
		bload fontpath, name_records, 12 * nt_count, tr_offset + 6
		repeat nt_count
			index = cnt * 12
			nr_platformID = wpeek_big2litle(name_records, index)
			nr_languageID = wpeek_big2litle(name_records, index + 4)
			nr_nameID     = wpeek_big2litle(name_records, index + 6)
			nr_length     = wpeek_big2litle(name_records, index + 8)
			nr_offset     = wpeek_big2litle(name_records, index + 10)
			if nr_platformID = 3 & nr_languageID = 0x409 & nr_nameID = 4	:break
		loop

		// ファイルからフォント名を取得
		getdata = bload_biguni2sjis(fontpath, tr_offset + nt_stringOffset + nr_offset, nr_length)
		return 1


	// 内部で使用する専用マクロと命令

	#define ctype getbyte(%1,%2)((%1) >> (%2) * 8 & $ff)

	#defcfunc big2litle_endian_4 int lit
		return getbyte(lit, 0) << 24 | getbyte(lit, 1) << 16 | getbyte(lit, 2) << 8 | getbyte(lit, 3)

	#defcfunc big2litle_endian_2 int lit
		return getbyte(lit, 0) << 8 | getbyte(lit, 1)

	#defcfunc lpeek_big2litle var data, int idx
		return big2litle_endian_4(lpeek(data, idx))

	#defcfunc wpeek_big2litle var data, int idx
		return big2litle_endian_2(wpeek(data, idx))

	#deffunc big2litle_endian_unicode var data, int size
		repeat size / 2
			wpoke data, cnt * 2, wpeek_big2litle(data, cnt * 2)
		loop
		return

	#defcfunc bload_big2litle_4 str path, int idx
		ldata = 0
		bload path, ldata, 4, idx
		return big2litle_endian_4(ldata)

	#defcfunc bload_big2litle_2 str path, int idx
		wdata = 0
		bload path, wdata, 2, idx
		return big2litle_endian_2(wdata)

	#defcfunc bload_biguni2sjis str path, int idx, int size
		sdim string, size + 2
		bload path, string, size, idx
		big2litle_endian_unicode string, size
		return cnvwtos(string)

#global

#endif




// サンプルスクリプト
#if 0;1			; ←ここを 1 にするとサンプルスクリプトを実行できる

// 実行するサンプルスクリプトを切り替える(0〜1)
#define TEST 0		; ←ここの数字を変えると実行サンプルが変わる

/*
	簡単な使い方のサンプル
*/
#if TEST = 0

	// フォントファイルのパス
	fontpath = "font.ttf"				; ここに取得したいフォントのファイル名を代入

	// フォントファイル名からフォント名を得る
	get_fontname fontpath, fontlist		; fontpaht 部分には直接パスを書いてもOK
	num = stat							; ここに取得数が入る
	mes "取得数:" + num

	// 取得できていればフォント名を表示する
	if num > 0 {
		mes fontlist					; 取得したフォント名を表示
	}

#endif

/*
	フォントフォルダから取得してみるサンプル
*/
#if TEST = 1

#define CSIDL_FONTS		0x0014
#define DIR_FONT		dirinfo(CSIDL_FONTS | 0x10000)

	screen 0, 800, 480

	// フォントフォルダ内のフォントファイル一覧を取得
	chdir DIR_FONT
	notesel list
	dirlist list_tmp, "*.ttc"	:list += list_tmp	:listmax += stat
	dirlist list_tmp, "*.ttf"	:list += list_tmp	:listmax += stat
	dirlist list_tmp, "*.otf"	:list += list_tmp	:listmax += stat
	title "" + listmax + " files"	; ファイル数表示
	sdim list_tmp					; メモリ削減

	// リストボックス作成
	lb_w = GINFO_WINX / 3
	lb_h = GINFO_WINY - 15
	listsel = -1, -1
	objsize lb_w
	listbox listsel, lb_h, list
	cx = lb_w + 5

	// リストボックスの選択変更を監視
	repeat
		wait 25
		if listsel ! listsel(1) {
			listsel(1) = listsel

			// 画面クリア
			color 255, 255, 255	:boxf
			color	:pos lb_w, 0

			// 選択したフォントファイル名を取得して表示
			noteget filename, listsel
			mes "「ファイル名」\n" + filename + "\n"

			// フォントファイルからフォント名を取得
			get_fontname filename, fontname
			num = stat

			// 状況に応じて表示
			if num > 0 {
				// コレクションファイルなら格納数を表示
				if getpath(filename, 2 | 16) = ".ttc" {
					mes "「格納数」\n" + num + "\n"
				}
				// 取得したフォント名を表示
				mes "「フォント名」"
				mes fontname
			} else {
				mes "取得できませんでした。"
			}
		}
	loop

#endif

#endif

コメント

  • とりあえず初版を公開しました! -- tyty? 2015-09-02 (水) 14:20:34
  • 半放置気味のこちらを盛り上げていただいてありがとうございます! -- y.tack? 2015-09-02 (水) 16:11:10
  • いえいえ いえーい!って取り乱しました…すみません。折角あるのに活用しないのも勿体無いと思ってたので使ってみました。それと変更した時に差分履歴が見れるのもブログにはない利点なのでやっぱり便利です。 -- tyty? 2015-09-02 (水) 18:39:57
  • いぇーい!家入(既出w) -- y.tack? 2015-09-03 (木) 16:36:28
  • Thanks a million. -- y.tack? 2015-09-03 (木) 20:11:17
  • Thanks a lot. -- y.tack? 2015-09-03 (木) 20:14:19
  • 一区切りつきましたか。乙っす。自己紹介ページ作りたいですよね。そろそろ。お互い -- y.tak? 2015-09-03 (木) 20:49:30
  • 説明文の対応形式の中の1つが OTC と誤っていたのを OTF に修正しました(恥ずかちっ) -- tyty? 2015-09-03 (木) 23:30:32
  • 紹介ページいいですね。っていうか懐かしいです開発wikiを思い出します! -- tyty? 2015-09-03 (木) 23:34:19
  • OTFと言えばおやじトラックファクトリーを思い出しますwハルカリのwハルカとユカリでハルカリーw -- y.tack? 2015-09-04 (金) 15:25:00
  • 理解出来てないですが 一応目通しました #ifndef使ってるの初めて見たかも 他人のスクリプトを読むのは勉強になるはずですが あんまりやったことなかったりw -- y.tack? 2015-09-04 (金) 17:06:58
  • ファクトリは分からなかったですがハルカリは昔何かのアニメのEDで聞いた事ありますね しかも割りとその歌好きでした(笑) -- tyty? 2015-09-04 (金) 23:08:52
  • どもども!技術処でネタ話が膨らみすぎるのもなんなのでスクリプトの方に話を戻します、#ifndef は昔は苦手意識ありましたが最近は割りと使う様にしてます、同じファイルを #include した時に重複定義でエラーになら無い様に。ちゃんとモジュールを公開して使ってもらうには大事かなと思い始めたためです、なので自分だけで使う奴には使ってません(^^;)。詳しく無いですが #ifndef の使い方って専らそれ用途だと思いますね。 -- tyty? 2015-09-04 (金) 23:18:28
  • 人のスクリプト読むの大事ですけど私もある程度ちゃんと読める様になったのは割りと最近だったような気がします。確かにちゃんと読むとお勉強になりますね。でもこのモジュールの場合はフォントファイルのフォーマットを理解してないと読んでも多分チンプンカンプンだと思うのであまり参考にならないかも知れません。自分もフォーマットや構造を読めもしない英語のサイトとか調べて何とか理解したので。 -- tyty? 2015-09-04 (金) 23:28:22
  • モジュール内のコメント文が「オフセットをビッグエンディアンにして」と誤っていたのを「ビッグエンディアンからリトルエンディアンに」と意味が正しくなるように修正しました。 -- tyty? 2015-09-04 (金) 23:50:20
  • >#ifndef 大事なのはわかってたんですけど、使ってるのを見たことがないのは、英単語だけ知ってて 用例を見たことがないのにつうじますねw でもどうやってTESTすればいいかわからなかったり、今までもそれで使ってなかったようなw -- y.tack? 2015-09-05 (土) 06:30:18
  • mod変数なしと相性がよい気がして ってかmod変数と組み合わせると頭の中でこんがらがるんですよねw -- y.tack? 2015-09-05 (土) 06:43:37
  • ちょっと違うかも知れないですが、百聞は一見に如かず的な事ことなのかも知れませんね。テストはわざと重複定義してエラーなら失敗で通れば成功、って感じで手動テストを。mod変数は便利ですがある意味鬼門です! -- tyty? 2015-09-05 (土) 16:00:56
  • 本当は #define で定義した固有の識別定数を使って #ifndef 指定したほうが良いのでしょうけど、私は面倒くさいので #module に指定したモジュール名をそのまま指定していますね。 -- tyty? 2015-09-06 (日) 17:28:38
  • モジュールで使っているマクロ名など色々おかしかったのをリネームしました。 -- tyty? 2015-09-08 (火) 02:14:49
  • マクロの処理が間違ってて実行すら出来なかった致命的な誤りを修正しました。 -- tyty? 2015-10-08 (木) 00:16:25
  • スパムに目を付けられたっぽいのでコメント機能停止してみました。
  • 勝手になんか書かれるの嫌だったらページ凍結を推奨します -- Y_repeat?
  • wiki なので私が作成したページであっても編集されるのは今も尚大歓迎なのですが、コメント欄があるとスパムが投稿しやすいのかな?と思いコメ欄をまず無くして様子見をしてたのでした。 -- tyty? 2017-09-19 (火) 08:53:22