この記事は、TrueTypeフォントテキストの品質設定に関するシリーズの一部です。以前の記事については、パート1を参照してください。
以前の記事では、定数設定を使用してTrueTypeフォントテキストの品質を変更する方法について説明しました。この記事では、TTF PolyDrawモードを使用して品質を動的に変更する方法について説明します。
動的TTF PolyDrawモード
TTF PolyDrawモードは、レンダラーまたはODAベクトル化フレームワーククライアントによって実際のテッセレーションデータが必要になるまで、テキスト文字のテッセレーションを回避します。これは、事前にテッセレーションされたジオメトリの代わりに、フォントマネージャーがベジェ曲線情報をジオメトリコンベアに渡し、クライアントコードがTrueTypeフォント処理に必要な任意の品質を使用してテキストをテッセレーションできることを意味します。たとえば、ODAベクトル化モジュールは、現在利用可能な偏差でそのようなテキスト文字をテッセレーションできるため、テキスト品質はどのズームレベルでも良好です。比較すると、一定のテキスト品質のフォントマネージャーは、事前にテッセレーションされた頂点の大きな配列をシステムメモリに保持する必要がないため、グラフィックキャッシュを準備する際に、フォント文字が必要な品質でテッセレーションされます。
OdaMfcAppサンプルアプリケーションでTTF PolyDrawモードを使用する
OdaMfcApp サンプルアプリケーションで TTF PolyDraw モードを有効にするには、[ツール] -> [オプション] -> [TTF: PolyDraw モード] を選択します。
テキストが遠くに見えるようにズームアウトします。
グラフィックキャッシュを更新するために REGEN コマンドを呼び出し、その後テキストにズームします。
テキストの品質が粗くなりすぎた場合は、REGEN コマンドを再度呼び出して、より良い品質でグラフィックキャッシュを更新します。
次に、テキストにズームして近づけます。
どのズームレベルでも、REGEN コマンドを呼び出して、現在のズームレベルに最適な品質でグラフィックキャッシュを更新できます。
.dwg データベースで TTF PolyDraw モードを有効にする
.dwg データベースで TTF PolyDraw モードを有効にするには、OdGiContextForDbDatabase::setTtfPolyDrawMode() メソッドを呼び出すだけです (ODA ドキュメントを参照、ログインが必要です)。
pGiContextForDwgDatabase->setTtfPolyDrawMode(true);
TTF PolyDraw モードを一般的に有効にする
TTF PolyDrawモードを有効にする一般的な方法(Kernel SDKに基づくすべてのODA製品で機能します)は、OdGiContext::ttfPolyDraw()メソッドをオーバーライドすることです(ODAドキュメント、ログインが必要です)。OdGiContextはすべてのODAベクトル化プロセスによって呼び出されるため、ttfPolyDraw()メソッドを使用して、それらのいずれかに対してTTF PolyDrawモードを有効にできます。デフォルトでは、ttfPolyDraw()メソッドはfalseを返します。各ODA製品、Drawings(.dwgファイルと.dgnファイルの両方)、BIM、およびPRCには、独自のOdGiContextの実装があります。たとえば、Drawings SDKでは、このクラスはOdGiContextForDbDatabaseと呼ばれます。各OdGiContextの実装は、OdGiContextForDbDatabaseのようにttfPolyDraw()メソッドを独自にオーバーライドおよび実装できますが、必要なOdGiContext実装から継承された独自のクラスでこのメソッドを再度オーバーライドし、それをODAベクトル化フレームワークに渡すことに問題はありません。
ベクトル化コンベアでのTTF PolyDrawデータのサポート
TrueTypeフォントのテキスト文字は通常、シェルジオメトリプリミティブを使用して描画されます。これらは、shellProcメソッドのオーバーライドを使用してジオメトリコンベアでアクセスできます。TTF PolyDrawモードが有効になっている場合、TrueTypeフォント文字に対してはshellProcの代わりにttfPolyDrawProcジオメトリコンベアメソッドが呼び出されます。クライアントコードがttfPolyDrawProcメソッドをオーバーライドしない場合、それはOdGiGeometrySimplifier::ttfPolyDrawProcメソッドの実装によって処理され、現在設定されている偏差を持つshellProcジオメトリプリミティブに変換されます(詳細についてはODAブログを参照してください)。
クライアントコードは、OdGiConveyorGeometry::ttfPolyDrawProcメソッドをオーバーライドして、PolyDrawデータを独立して処理できます。たとえば、これはTXTEXPコマンドで、特定の精度でTrueTypeフォントのテキスト輪郭をテッセレーションするために行われます。
void ttfPolyDrawProc(OdInt32 numVertices, const OdGePoint3d* vertexList,
OdInt32 faceListSize, const OdInt32* faceList,
const OdUInt8* pBezierTypes, const OdGiFaceData* pFaceData = 0)
.\main\Drawing\Examples\ExCommands\ExTxtExp.cpp、TXTEXPコマンドのソースコードを参照してください。ttfPolyDrawProcメソッドにはshellProcと同様の引数が含まれていますが、pBezierTypes値の配列によって拡張されています。この配列のエントリ数は、ttfPolyDrawProcメソッドに渡される頂点の数と同様です。次の表は、この配列に存在する可能性のある値を説明しています。
| 値 (ビットフラグ) | 説明 |
|---|---|
| 1 (閉じた図形) | この値は通常、「Line To」または「Bezier To」フラグと組み合わされ、現在描画されている図形が閉じている必要があることを意味します。この場合、次の値(存在する場合)は次の図形の最初の点を表します。 |
| 2 (Line To) | 前の頂点からこの頂点まで描画された単純な線。 |
| 4 (Bezier To) | ベジェ曲線の制御点。ベジェ曲線は4つの頂点で構成され、そのうち最後の3つはこのフラグでマークされます。 |
| 6 (Move To) | 分離した図形の最初の点をマークします。 |
このビットフラグをC++列挙型として形式化できます。
enum pdFlags
{
kpdCloseFigure = 0x01,
kpdLineTo = 0x02,
kpdBezierTo = 0x04,
kpdMoveTo = 0x06
};
TXTEXPコマンドの例からの簡略化されたコードの次の部分は、このフラグの配列を処理して一連のポリラインを作成する方法を示しています。
int nVerts = 0; // Number of vertexes currently processed for this polyline
OdDbPolylinePtr pPl; // Currently processing polyline
int bzCnt = 0; // Number of points collected for Bezier curve
OdGePoint3d bzSpl[4]; // Collected Bezier curve points
for (OdInt32 i = 0; i < numVertices; i++)
{
if (pBezierTypes[i] == kpdMoveTo)
{ // Create new polyline and add first vertex
pPl = OdDbPolyline::createObject();
nVerts = 0;
pPl->addVertexAt(nVerts++, vertexList[i].convert2d());
}
else
{
if (GETBIT(pBezierTypes[i], kpdLineTo))
{ // Add line segment
pPl->addVertexAt(nVerts++, vertexList[i].convert2d());
}
else if (GETBIT(pBezierTypes[i], kpdBezierTo))
{
bzCnt++; // Collect next Bezier curve vertex
bzSpl[bzCnt] = vertexList[i];
if (bzCnt == 3)
{
const int nSegs = 8; // Set number of segment for Bezier curve tessellation
// This is a sequence of 3 bezierTo points + previous point, so when we collect 3rd bezierTo,
// we could construct cubic spline based on 4 points.
. . .
// Add last vertex
pPl->addVertexAt(nVerts++, vertexList[i].convert2d());
bzCnt = 0;
}
}
}
if (GETBIT(pBezierTypes[i], kpdCloseFigure))
{
appendEntity(pPl); // Add currently processed polyline
// Create next polyline for processing and add first vertex
pPl = OdDbPolyline::createObject();
nVerts = 0;
pPl->addVertexAt(nVerts++, vertexList[i].convert2d());
}
}
このコードは、4つの頂点から構成される累積された3次スプラインを、必要な数のポリラインセグメントにテッセレーションするための古典的なアルゴリズムを使用しています。
const int nSegs = 8; // Set number of segments for Bezier curve tessellation
// This is a sequence of 3 bezierTo points + previous point, so when we collect 3rd bezierTo,
// we could construct cubic spline based on 4 points.
pPl->getEndPoint(bzSpl[0]); // Get previous point for tessellation
double d = 1. / nSegs;
for (int n = 1; n < nSegs; n++)
{
double t = d * n;
double u = 1.0 - t;
double tt = t * t, uu = u * u;
double uuu = uu * u, ttt = tt * t;
double uut3 = uu * t * 3, utt3 = u * tt * 3;
pnt = OdGePoint3d(
bzSpl[0].x * uuu + bzSpl[1].x * uut3 + bzSpl[2].x * utt3 + bzSpl[3].x * ttt,
bzSpl[0].y * uuu + bzSpl[1].y * uut3 + bzSpl[2].y * utt3 + bzSpl[3].y * ttt,
bzSpl[0].z * uuu + bzSpl[1].z * uut3 + bzSpl[2].z * utt3 + bzSpl[3].z * ttt);
pPl->addVertexAt(nVerts++, pnt.convert2d());
}
// Add last vertex
pPl->addVertexAt(nVerts++, vertexList[i].convert2d());
bzCnt = 0;
このコードの実行後、指定された品質(テッセレーション精度)でTrueTypeフォントの文字の輪郭を表すポリラインのセットが出力されます。
これは、TrueTypeフォントのテキスト品質を調整するシリーズの最後の記事です。