トップページ > 記事閲覧
フォントにある文字を取得
名前:明太チーズ 日時: 2017/02/22 10:53

フォントに定義されている文字の一覧を取得することはできますか? フォントに存在しない文字は別のフォントで描画する、といったことをしたいのですが、 その為にはフォントにどの文字のデータがあるかを調べる必要があるのです、、、 フォントハンドルに対して調べられれば十分です
メンテ

Page: 1 |

Re: フォントにある文字を取得 ( No.1 )
名前:管理人 日時:2017/02/23 03:08

> フォントに定義されている文字の一覧を取得することはできますか? 現在のところそのような機能はありません 少し調べた限りでは1文字単位でフォントにその文字が存在するかどうかを確認する 方法はありそうですが、一覧で取得できる機能が必要でしょうか?
メンテ
Re: フォントにある文字を取得 ( No.2 )
名前:明太チーズ 日時:2017/02/23 15:52

いえ、一文字ずつでも構いません
メンテ
Re: フォントにある文字を取得 ( No.3 )
名前:管理人 日時:2017/02/24 22:29

ご返答ありがとうございます 既存の関数でフォントに指定の文字が存在するかどうかを判断できるようにプログラムを変更してみましたので、 よろしければこちらのバージョンをダウンロードしてください m(_ _)m https://dxlib.xsrv.jp/temp/DxLibVCTest.exe // VisualC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCCTest.exe // BorlandC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCC2Test.exe // C++ Builder 10.1 Berlin 用 https://dxlib.xsrv.jp/temp/DxLibGCC_MinGWTest.exe // MinGW 用 https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // .NET用 https://dxlib.xsrv.jp/temp/DxLibMakeTest.exe // ソース (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』を、VCをお使いの場合は『リビルド』をして下さい) 使用する関数は GetFontCharInfo です // フォントハンドルの指定の文字の描画情報を取得する int GetFontCharInfo( int FontHandle, char *Char, int *DrawX, int *DrawY, int *NextCharX, int *SizeX, int *SizeY ) ; フォントに含まれる文字の情報を取得するための関数なのですが、 これまではフォントに含まれない文字を指定しても代替文字の情報が返ってきてしまっていたので、 今回の変更でフォントに含まれない文字を指定した場合はエラーとなり -1 を返すようにしました DrawX, DrawY, NextCharX, SizeX, SizeY は NULL でも良いようになっていますので、 例えばあるフォントハンドルのフォントに "あ" という文字が含まれているか調べる場合は if( GetFontCharInfo( FontHandle, "あ", NULL, NULL, NULL, NULL, NULL ) < 0 ) { // 文字がない } else { // 文字がある } として判断することができます よろしければお使いください m(_ _)m
メンテ
Re: フォントにある文字を取得 ( No.4 )
名前:明太チーズ 日時:2017/02/26 16:14

わざわざ対応ありがとうございます。 英字部分は欧文フォントを使い、日本語の部分は別の似たフォントを使って描画する、ということを目指していたのですが、これで実装できそうです。 ですが、管理人さんの「代替フォント」という言葉を読んで思ったのですが、描画に使われる代替フォントを指定することはできますでしょうか? それができると、より簡単な実装で先ほど申し上げた機能が作れるのですが……
メンテ
Re: フォントにある文字を取得 ( No.5 )
名前:管理人 日時:2017/02/27 13:39

> ですが、管理人さんの「代替フォント」という言葉を読んで思ったのですが、描画に使われる代替フォントを指定することはできますでしょうか? 今のところ代替フォントを指定する機能はありません、でも比較的簡単に実装できる気がします 追加する関数はこんな感じで大丈夫そうでしょうか? // 代替フォントを登録する // int FontHandle : 代替フォントを登録するフォントハンドル // int SubstitutionFontHandle : 代替フォントハンドル // int DrawY : 本来の描画 Y 座標に対する代替フォントを描画する相対 Y 座標 // int Priority : 代替フォントを複数登録した場合用の優先順位 AddSubstitutionFontToHandle( int FontHandle, int SubstitutionFontHandle, int DrawY, int Priority ) ; // 代替フォントの登録を解除する // int FontHandle : 代替フォントの登録を解除するフォントハンドル // int SubstitutionFontHandle : 代替フォントハンドル SubSubstitutionFontToHandle( int FontHandle, int SubstitutionFontHandle ) ;
メンテ
Re: フォントにある文字を取得 ( No.6 )
名前:明太チーズ 日時:2017/02/28 00:13

はい、これで大丈夫だと思います。
メンテ
Re: フォントにある文字を取得 ( No.7 )
名前:管理人 日時:2017/02/28 00:43

了解しました すみません、少し取り掛かってみましたが、予想よりはちょっと手間が掛かりそうなので 完成は次の週末になるかもしれません m(_ _;m
メンテ
Re: フォントにある文字を取得 ( No.8 )
名前:yumetodo 日時:2017/02/28 19:16

いや、そのAPIだとちょっと使いにくいような・・・。 ここはFallbackFontHandleという別の概念を追加して int MakeFallbackHandle(const TCHAR* const* FallbackFontNameArray, size_t FallbackFontNameArraySize, int Size , int Thick , int FontType ); というふうにしたほうがわかりやすいのでは・・・。CSSのFontFalmilyに近くなりますし。 const wchar_t* font_names[] = { L"Segoe UI", "IPAexゴシック", "IPAゴシック", "Lucida Grande", YuGothic, '游ゴシック', "Hiragino Kaku Gothic ProN", "ヒラギノ角ゴ ProN W3", Meiryo, メイリオ, sans-serif, "MS Goshic" }; const int fonts = MakeFallbackHandle(font_names, std::size(font_names), 18, 3, DX_FONTTYPE_ANTIALIASING); DrawStringToHandle(0 , 0 , L"この素晴らしいライブラリに祝福を!" , GetColor( 255 , 255 , 255 ) , fonts);
メンテ
Re: フォントにある文字を取得 ( No.9 )
名前:明太チーズ 日時:2017/03/01 14:58

このような機能を使うほど文字に拘る開発者なら(つまり私ですが)、 実行する環境のフォントに依存した表示にしたりせず、DXフォントファイルかttfを付属させると思うので、 CSSのフォントファミリーとは少し目的が違います。(あくまでも、文字単位で分岐させたいという件なので) 順序を直接指定するのは分かりやすくていいんですが、フォント名からしか作れないのはちょっと問題です フォントファイルから読み込んだ等、ハンドルのみしか扱えない状況もあるので、、、 また、フォントハンドルから作るのであれば、各ハンドルのcharsetを制限することで、 日本語フォントの英数字部分と別の日本語フォントの日本語部分とを取り合わせることもできますから、 やはり直接フォント名で指定するのはすこし制約があるかなと 個人的に扱いやすいのは、DrawStringToHandleの引数int fontを複数用意する形です。 二つ目以降は隠し引数にして、指定があった場合は順に(前から、あるいは後ろから)優先される感じで、、、 ただ、毎回フォントのセットを指定しなければいけないことと、指定できる数の上限ができてしまうという問題はあります。 もしフォントのセットをハンドルにするのであれば、それをファイルにして一括で読み込めるといいのですが、 どの文字をどのフォントで描画するかまでしていしてフォントメーカーを扱うのはやや難しいのではないかと思います。 あっでも、既にあるフォントファイルをマージする形ならやり易いかも (各フォントファイルを作る段階で使用する文字は指定しているので、マージするときは優先順を指定するのみ)
メンテ
Re: フォントにある文字を取得 ( No.10 )
名前:管理人 日時:2017/03/01 23:46

> yumetodoさん 同じサイズを指定してもフォントによって大きさが異なるので、フォント毎に 大きさやオフセットを指定できるようにする必要はあると思います > 明太チーズさん 便利さを少し追求すると色々やるべきことはあると思うのですが、それをしてしまうと 作業時間的にiOS対応を優先したい規模になってしまうので、すみませんが今回は No.5 の関数の実装に留めさせてください
メンテ
Re: フォントにある文字を取得 ( No.11 )
名前:明太チーズ 日時:2017/03/01 23:54

分かりました。 起動時の処理として一回書く程度なら多少不便でも全く問題はないので、構いません。
メンテ
Re: フォントにある文字を取得 ( No.12 )
名前:管理人 日時:2017/03/05 20:51

すみません、実装をしようとしてひとつ勘違いしていたかもしれないことがあるのでご質問させてください 私は代替フォントの機能を漠然と「元のフォントに無い文字を代替フォントの文字で描画する機能」と考えていたのですが、 そのような機能で問題ないでしょうか? そのような機能の場合、例えば「MS ゴシック」のような多くの文字に対応しているフォントを元のフォントとすると、 「英数字だけ Arial を使いたい」と思っても、「MS ゴシック」にも英数字が存在するので、 この機能で「英数字だけを Arial で描画する」ことはできません その場合は逆に「Arial のフォントハンドル」を元のフォントとして、「MS ゴシックのフォントハンドル」を 代替フォントにすることで英数字のみ Arial で描画することができますが( Arial には日本語文字などが 存在しないため )そのような使い方で良いでしょうか? 代案として考えたのは「代替フォントを使用する文字コードの範囲を指定する」で、例えば引数は以下のようになります // StartChar : 代替する文字の範囲の先頭文字 // EndChar : 代替する文字の範囲の終端文字 int AddSubstitutionFontToHandle( int FontHandle, int SubstitutionFontHandle, int DrawX, int DrawY, char *StartChar, char *EndChar ) ; 使用例としてはこのような感じで AddSubstitutionFontToHandle( FontHandle, SubFontHandle, 0, 0, 0, "a", "z" ) ; AddSubstitutionFontToHandle( FontHandle, SubFontHandle, 0, 0, 0, "A", "Z" ) ; AddSubstitutionFontToHandle( FontHandle, SubFontHandle, 0, 0, 0, "0", "9" ) ; 文字で代替する範囲を指定します この機能の場合、元のフォントにある文字も代替フォントの文字に置き換えることができますが、 必要な知識は多くなり、記述すべきコードも増えます 機能的には後者の「代替範囲を指定する」の方が強力なのですが、使い方も難しくなるので少し悩みます 明太チーズさんのご要望に応えるにあたっては、元の「元のフォントに無い文字を代替フォントで描画する」で十分でしょうか? それとも代案の「代替する文字の範囲を指定できる」方が良いでしょうか? お手数で申し訳ありませんがご意見をいただければと思います m(_ _;m
メンテ
Re: フォントにある文字を取得 ( No.13 )
名前:yumetodo 日時:2017/03/05 21:22

>文字コードの範囲を指定する DxLibは内部的にUTF-16で文字列を扱っているはずなので、TCHAR型がwcahr_tではない場合、実装が大変なのでは・・・? 仮に実装したとして、TCAHRがwcahr_tかcharかによって挙動が変わりますし・・・。 Unicode code pointでの範囲指定(JavaScriptの正規表現の[]の実装のような)なら、 つまりwchar_t型での指定(char16_t/char32_t型でもいいですが)のみにして、ということであれば文字コードの闇にユーザーが踏み込む必要がなくいいと思いますが
メンテ
Re: フォントにある文字を取得 ( No.14 )
名前:明太チーズ 日時:2017/03/06 16:53

私は基本的にDXフォントファイルのフォントしか使っていないので(実行するPCのフォントが充実しているか、あてにならないので)、 CreateDXFontDataの/Aで指定した文字の指定を生かしたいと思っていました 例えば数字部分だけMSゴシックにするならば、 @MSゴシックから数字のみを指定してフォントファイルを作成、 @Arialからそのほかの文字を指定してフォントファイルを作成 Bゲーム側で@とAを読み込んで混ぜる という使用方法を想定していました。 私としてはこれができれば満足なのですが、フォントファイルを使わない他のユーザーのことも考えると、どうするのがよいか…… DXライブラリの内部仕様にはあまり明るくないのですが、 もしフォントハンドルが持っている情報の中に、使っている文字を任意に保存できているのならば CreateFontToHandleを使ってインストールされたフォントから文字を作るときにも フォントファイルを作成するときと同じように使用する文字の配列を指定することができるようにすれば 私の先ほどの実装で、フォントファイルを使わないユーザーも恩恵を受けることができるのではないでしょうか 纏めると実装してほしい機能は、 @文字の情報がフォントファイルに保存されているか否かで使用するフォントを分岐する機能 A/Aで文字列を指定したフォントファイルを読み込んだ時と、同じ結果のハンドルをインストールされたフォントから作成する機能 の2つとなります。いかがでしょうか
メンテ
Re: フォントにある文字を取得 ( No.15 )
名前:管理人 日時:2017/03/07 02:30

ご返答ありがとうございます なるほど、フォントハンドルを作成する際に使用する文字列を指定するのですね… そして代替フォントの指定の際は文字の指定は無し… 確かにご提案の方式が最適解のように感じます ただ、『A/Aで文字列を指定したフォントファイルを読み込んだ時と、同じ結果のハンドルをインストールされたフォントから作成する機能』が 少し重い作業となりそうなので、今回は『@文字の情報がフォントファイルに保存されているか否かで使用するフォントを分岐する機能』のみの 実装となるかもしれません… そして実装時期ですが、バグの修正を優先したいので再び週末になってしまうかもしれません、申し訳ありません m(_ _;m > yumetodoさん 一応 TCHAR がシフトJISでもUTF-8でもそこまで手間無く範囲を判定することはできますが、 確かにご指摘の通り使用される方のことを考えても wchar_t型で指定できた方が良いですね (・・;; 今回は範囲指定の実装は無くなりそうですが、別の機会で文字の範囲指定をすることになったら wchar_t型で 指定するようにします
メンテ
Re: フォントにある文字を取得 ( No.16 )
名前:明太チーズ 日時:2017/03/07 20:53

前向きな検討ありがとうございます。 とりあえずは@だけでも、やりたかったことは実装できるので大丈夫です Aの機能が実装されると、このような案件に限らず一般的なメリットもある (使用メモリが減ったりするんじゃないでしょうか?)と思いますので、 いつかお時間のあるときにでも実装して頂けると(なにもしていない提案者としてですが)嬉しいです。
メンテ
Re: フォントにある文字を取得 ( No.17 )
名前:管理人 日時:2017/03/09 01:03

お待たせしました、代替フォントの機能を実装したバージョンをアップしましたので、 よろしければダウンロードしてください m(_ _;m https://dxlib.xsrv.jp/temp/DxLibVCTest.exe // VisualC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCCTest.exe // BorlandC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCC2Test.exe // C++ Builder 10.1 Berlin 用 https://dxlib.xsrv.jp/temp/DxLibGCC_MinGWTest.exe // MinGW 用 https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // .NET用 https://dxlib.xsrv.jp/temp/DxLibAndroidTest.exe // Android用 https://dxlib.xsrv.jp/temp/DxLibMakeTest.exe // ソース (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』を、VCをお使いの場合は『リビルド』をして下さい) 追加した関数は以下の通りです( No.5 とほぼ同じですが、 Priority は無くなりました ) // 代替フォントハンドル( FontHandle に無い文字を描画しようとしたときに代わりに使用されるフォントハンドル )を登録する // int FontHandle : 代替フォントを登録するフォントハンドル // int SubstitutionFontHandle : 代替フォントハンドル // int DrawX : 本来の描画 X 座標に対する代替フォントを描画する相対 X 座標 // int DrawY : 本来の描画 Y 座標に対する代替フォントを描画する相対 Y 座標 int AddSubstitutionFontToHandle( int FontHandle, int SubstitutionFontHandle, int DrawX, int DrawY ) ; // 代替フォントハンドルの登録を解除する // int FontHandle : 代替フォントの登録を解除するフォントハンドル // int SubstitutionFontHandle : 代替フォントハンドル int SubSubstitutionFontToHandle( int FontHandle, int SubstitutionFontHandle ) ; Aの実装はやはり少し時間がかかりそうだったので、今回は見送りました… > (使用メモリが減ったりするんじゃないでしょうか?) 実装の方法は二つあって、   方法1 内部でDXフォントファイルと全く同じデータを作成して使用する機能を実装   方法2 通常のフォントハンドルに使用できる文字の制限を加えるだけの機能を実装 方法1の場合はDXフォントファイルと同じく使用メモリは減りますが、DXフォントファイルの作成は ファイルに含める文字が多ければ多いほど時間が掛かるのであまり実用的ではないかもしれません 方法2の場合は現在の通常のフォントハンドル機能に使用できる文字を制限する情報と処理を 加えるというもので、こちらはフォントハンドルの作成は一瞬で終わりますが、使用できる 文字の情報を保持したり使用する文字が制限対象ではないか調べたりする必要がある分 使用メモリと処理負荷が増加します 実用的なのは方法2なので、実装するとしたら方法2の方になると思います
メンテ
Re: フォントにある文字を取得 ( No.18 )
名前:明太チーズ(解決) 日時:2017/03/14 01:47

遅くなりましたが、動作確認しました。 対応ありがとうございました。
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存