API はこれをサポートしていますか? そうでない場合、どうすればできますか?
Core Text にはCTFontCreatePathForGlyph
、1 つの文字をパスに変換できるものがあります。これをループで使用して、文字列をパスとして作成することもできますが、スペーシングやカーニング、その他すべての厄介なことに対処する必要があります。同じフォントとサイズの UILabel で描画された場合と同じように見える文字列パスを探しています。
API はこれをサポートしていますか? そうでない場合、どうすればできますか?
Core Text にはCTFontCreatePathForGlyph
、1 つの文字をパスに変換できるものがあります。これをループで使用して、文字列をパスとして作成することもできますが、スペーシングやカーニング、その他すべての厄介なことに対処する必要があります。同じフォントとサイズの UILabel で描画された場合と同じように見える文字列パスを探しています。
このプロジェクトの UIBezierPath+TextPaths カテゴリを見てください: https://github.com/aderussell/string-to-CGPathRef。
単一行および複数行の文字列のパスを作成する方法と、それらを CAShapeLayers で使用する方法を示します。
カテゴリは単なるラッパーであり、内部関数は iOS または Mac OS X で使用できます。プロジェクトを CoreText フレームワークにリンクするだけで済みます。
これについては、 Ohmuによる低レベルのテキスト レンダリングという記事があり、かなり詳しく説明されています。このコードを試してみたところ、動作することが確認できました。
ただし、Core Text を使用しているため、レンダリングはおそらくUILabel
. また、サンプル記事は一行しか扱っていません。複数の行に拡張するには、完全な Core Text システムをセットアップする必要があります。それ以外の:
CTLineRef line = CTLineCreateWithAttributedString( attStr ) ;
Core Text Programming Guide の説明に従って、 CTFramesetterRef
( CTFramesetterCreateWithAttributedString
) とCTFrameRef
( )を設定する必要があります。CTFramesetterCreateFrame
その後、フレーム内のすべての行を で取得できますCTFrameGetLines()
。
for
次に、サンプル記事でループをラップします。
CFArrayRef runArray = CTLineGetGlyphRuns(line);
// for each RUN
for (CFIndex runIndex = 0; runIndex < CFArrayGetCount(runArray); runIndex++)
すべての行を反復する別のループを使用します。ループの内側のコアは同一である必要があります。
CGMutablePathRef
サンプル記事では、グラフィック コンテキストを作成し、単一のグリフのパスをこのコンテキストのパスに追加しますが、またはを簡単に作成してUIBezierPath
、単一のグリフのパスをそのオブジェクトに追加することもできます。
これをテストしないと 100% はっきりしないことの 1 つは、最終的なパスでグリフの垂直位置を調整する方法です。CTFrameGetLineOrigins()
おそらく、各行の位置を取得し、この位置をレンダリングされた各グリフに追加するために呼び出す必要があります (おそらく、テキスト マトリックスで変換した後)。