TrueType グリフのアウトラインを描画するには、方法

重要: このサポート技術情報 (以下「KB」) は、翻訳者による翻訳の代わりに、マイクロソフト機械翻訳システムによって翻訳されたものです。マイクロソフトは、お客様に、マイクロソフトが提供している全ての KB を日本語でご利用いただけるように、翻訳者による翻訳 KB に加え機械翻訳 KB も提供しています。しかしながら、機械翻訳の品質は翻訳者による翻訳ほど十分ではありません。誤訳や、文法、言葉使い、その他、たとえば日本語を母国語としない方が日本語を話すときに間違えるようなミスを含んでいる可能性があります。マイクロソフトは、機械翻訳の品質、及び KB の内容の誤訳やお客様が KB を利用されたことによって生じた直接または間接的な問題や損害については、いかなる責任も負わないものとします。マイクロソフトは、機械翻訳システムの改善を継続的に行っています。

英語版 KB:243285
概要
Win32 API GetGlyphOutline 関数は、TrueType フォントをネイティブのグリフのアウトライン データを返すことができます。TrueType グリフのアウトラインを描画するには、データのネイティブ b-スプライン定義から一連のベジエ行定義に変換する必要があります。続いて、 PolyBezier Win32 API 関数のアウトラインの描画に使用できます。
詳細
は、 GetGlyphOutline 関数は、Win32 アプリケーション プログラミングの Interface(API) で、TrueType アウトラインを取得できます。二次 b-スプライン曲線は TrueType アウトラインを持つバッファー、GGO_NATIVE フォーマットのオプションを設定します。2 次 B スプライン TrueType では、TrueType フォント ファイルのグリフのアウトラインを作成する使用されます。1 B-スプラインの描画関数を実装したり、使用したりすることができますこれらのアウトラインの曲線を描画するのには PolyBezier Win32 API の関数です。

二次 b-スプライン曲線は、いくつかの制御点を使用して複数の曲線セグメントのパス定義のパラメトリック曲線のクラスです。2 次曲線は、2 つ目の注文パラメトリック曲線です。2 次計画法を Win32 API の関数では、ベジエ曲線を描画するため描画できますある 3 次曲線に変換される場合は直接二次スプラインを描画するのには、API 関数はありません。呼ばれる PolyBezier.

二次 b-スプライン曲線の特定とパラメトリック曲線は通常コンピューター サイエンスでのグラフィックスの well-researched トピックです。さらに、非常に複雑なすることもできます。テキストではさまざまなアルゴリズムが発行されましたが、二次スプラインを描画するための関数を実装するために使用されるようなアルゴリズムを記述する、この資料の範囲外にあります。

は、 PolyBezier 立方または 3 番目のパラメトリック曲線は、ベジエ曲線をであるため、2 次スプライン関数を描画できます。2 次スプラインは、2 つ目の注文数式であるため、高い順立方方程式の面で表すことができます。サンプル コードでは、2 次と 3 次曲線を表す数式が与えられますが、その派生この記事では説明しません。

この資料のサンプル コードは GGO_NATIVE グリフ バッファーによって返されるを解析する方法のデモンストレーションですが GetGlyphOutline 関数です。GGO_NATIVE の形式フラグが返されるバッファーに準拠して、 TTPOLYGONHEADER 構造体です。は、 TTPOLYGONHEADER 構造とそのすぐ後に続くデータの TrueType グリフの輪郭の 1 つを構成しています。これにより、明示的に返されない場合は、暗黙的に閉じるの 1 つの完全なパスを曲線輪郭です。

プラットフォーム SDK のマニュアルを参照してください、 TTPOLYGONHEADERTTPOLYCURVE 構造体。

複数のカーブ セグメントによって表されるグリフの輪郭で構成されます。 TTPOLYCURVE 構造体。輪郭、 TTPOLYGONHEADER 1 つまたは複数が続きます TTPOLYCURVE 構造体および座標データをポイントします。は、 pfxStart メンバーは、線の始点の座標を示します。曲線の数を記録、以後、 TTPOLYGONHEADER しては、 cb メンバーです。グリフの原点を基準に開始位置です。グリフの原点は、文字のベースラインの位置にある文字の左下隅です。

TTPOLYCURVE 曲線レコード (曲線セグメント) 二次 b-スプライン制御点または単純なポリライン ポイントのいずれかの構成をされます。ポイントの数によっては、 TTPOLYCURVEcpfx メンバーです。スプラインまたはポリラインのいずれかのカーブのタイプによっては、 wType メンバーです。座標点の配列構造をすぐに従います。曲線の開始点では、 apfx メンバーです。

グリフが 2 つ以上の線を含めることができますので、1 つまたは複数のグループにはバッファーが含まれます。 TTPOLYGONHEADER 構造とデータを使用します。以降の配分は、前の仕事で、ネイティブのバッファーの直後パックされます。次の輪郭が始まり、 TTPOLYGONHEADER 次のバイトを超える曲線の前のレコードの最後のポイント。

このサンプル コード各輪郭を形成するベジエ ライン セグメントの一覧を作成するのには、GGO_NATIVE バッファーを解析することによって、TrueType のグリフのアウトラインを描画します。ベジエ ライン セグメントの一覧からを使用して描画されます。 PolyBezier.バッファーを解析し、コードでは、 DrawT2Outline 関数です。

ベジエ行の一覧を作成するのには、まずは、リストのバッファーのサイズを決定することです。4 つのポイントは、ベジエ線を定義します。は、 PolyBezier 関数は 1 つの連続した行の次の行の先頭が前の線のエンドポイントに一致するはベジエ セグメントの中では、点の配列を解釈します。したがって、3 つのポイントが追加のベジエ ライン セグメントを作成するが必要です。

ポリライン曲線または二次 b-スプライン曲線、GGO_NATIVE バッファーがあります。B スプライン 3 ポイントを定義するときに 2 つのポイント ライン セグメントを定義します。PolyBezier を使用してベジエ線を描画するのには、それぞれの種類であるため、線分の全体で構成されている 1 つの輪郭を複数の輪を拡大すると、最悪の場合に発生します。

曲線を表すセグメント b-スプライン曲線表現で追加のポイントを 1 つだけ必要であるに注意してください。その点、"B"を明示的に定義オフ曲線ポイントや暗黙的に曲線上の点の追加定義をします。上のカーブ ポイントは、中点を次の"B"です。したがって、追加の直線セグメントまたは、曲線セグメント ベジエ行の 3 つの追加点が展開されます。

コードのネイティブ バッファー全体が構成されることを想定しています。 POINTFX 最大バッファーで表される点の数を決定するための構造です。ないため構造のオーバーヘッドと輪郭曲線の説明に、実際の数が若干少なくなってください。ベジエ リストのバッファーのサイズは、最大のデータ サイズを乗算ポイント数によっては、 ポイント 構造体し、3 を乗算します。3 つの追加の直線セグメントまたは、ベジエへ変換するときに、二次スプライン セグメントごとに必要なその他のポイントの数です。

ベジェのバッファーが割り当てられていると、コードは、ネイティブのバッファーを最初に起動することによって解析します。 TTPOLYGONHEADER.ループの反復処理の実行中にコード 1 つの輪郭を処理し、描画します。内側のループは、2 番目は各曲線タイプを解析します。

ポリライン曲線 (TT_PRIM_LINE) の場合、各線分のポリラインは変換しての輪を一覧に追加、 AppendPolyLineToBezier 関数です。曲線、2 次スプライン (TT_PRIM_QSPLINE) 場合は、 AppendQuadBSplineToBezier 関数は、変換し、二次 b-スプラインを追加します。曲線のセグメントごとに、独立したコントロール ポイントを解析するにはこれらの各関数をループを使用します。スプライン、線、ベジエへ変換あり輪のリストに追加します。

ベジエ行は、簡単に直線を描画できます。だけで、開始と終了ベクトル線のセグメントの反対側の端をポイントします。これ、 MakeBezierFromLine 関数です。

2 次スプラインは三次ベジエ スプラインに変換するのには 3 次曲線のコントロール ポイントの 2 次の制御点を表現する必要があります。制御点に変換する式である、 MakeBezierFromQBSpline 関数です。

輪郭を描画する前に、コードを呼び出すことにより、パスが閉じていることにより、 CloseContour 関数です。始点と終点の輪のシーケンス一致しなくなった場合は、関数が呼び出されます。続いて、 PolyBezier 関数が呼び出されます。

輪郭が描画された後、次の輪郭の TTPOLYGONHEADER 現在の輪郭内のレコードの末尾を超えた lpHeader ポインターを進めるがあります。この結果、ネイティブのバッファーの終わりを超えてのポインターの値にする場合は、コードのすべての輪郭と終了処理します。
/**************************************************************************** *  FUNCTION   : IntFromFixed *  RETURNS    : int value approximating the FIXED value. ****************************************************************************/ int PASCAL NEAR IntFromFixed(FIXED f){    if (f.fract >= 0x8000)    return(f.value + 1);    else    return(f.value);}/**************************************************************************** *  FUNCTION   : fxDiv2 *  RETURNS    : (val1 + val2)/2 for FIXED values ****************************************************************************/ FIXED PASCAL NEAR fxDiv2(FIXED fxVal1, FIXED fxVal2){    long l;    l = (*((long far *)&(fxVal1)) + *((long far *)&(fxVal2)))/2;    return(*(FIXED *)&l);}/**************************************************************************** *  FUNCTION   : MakeBezierFromLine * *  PURPOSE    : Converts a line define by two points to a four point Bezier *               spline representation of the line in pPts. * * *  RETURNS    : number of Bezier points placed into the pPts POINT array. ****************************************************************************/ UINT MakeBezierFromLine( POINT *pPts, POINT startpt, POINT endpt ){    UINT cTotal = 0;    // starting point of Bezier    pPts[cTotal] = startpt;    cTotal++;    // 1rst Control, pt == endpoint makes Bezier a line    pPts[cTotal].x = endpt.x;    pPts[cTotal].y = endpt.y;    cTotal++;    // 2nd Control, pt == startpoint makes Bezier a line    pPts[cTotal].x = startpt.x;    pPts[cTotal].y = startpt.y;    cTotal++;    // ending point of Bezier    pPts[cTotal] = endpt;    cTotal++;        return cTotal;}/**************************************************************************** *  FUNCTION   : MakeBezierFromQBSpline * *  PURPOSE    : Converts a quadratic spline in pSline to a four point Bezier *               spline in pPts. * * *  RETURNS    : number of Bezier points placed into the pPts POINT array. ****************************************************************************/ UINT MakeBezierFromQBSpline( POINT *pPts, POINTFX *pSpline ){    POINT   P0,         // Quadratic on curve start point            P1,         // Quadratic control point            P2;         // Quadratic on curve end point    UINT    cTotal = 0;    // Convert the Quadratic points to integer    P0.x = IntFromFixed( pSpline[0].x );    P0.y = IntFromFixed( pSpline[0].y );    P1.x = IntFromFixed( pSpline[1].x );    P1.y = IntFromFixed( pSpline[1].y );    P2.x = IntFromFixed( pSpline[2].x );    P2.y = IntFromFixed( pSpline[2].y );    // conversion of a quadratic to a cubic    // Cubic P0 is the on curve start point    pPts[cTotal] = P0;    cTotal++;        // Cubic P1 in terms of Quadratic P0 and P1    pPts[cTotal].x = P0.x + 2*(P1.x - P0.x)/3;    pPts[cTotal].y = P0.y + 2*(P1.y - P0.y)/3;    cTotal++;    // Cubic P2 in terms of Qudartic P1 and P2    pPts[cTotal].x = P1.x + 1*(P2.x - P1.x)/3;    pPts[cTotal].y = P1.y + 1*(P2.y - P1.y)/3;    cTotal++;    // Cubic P3 is the on curve end point    pPts[cTotal] = P2;    cTotal++;    return cTotal;}/**************************************************************************** *  FUNCTION   : AppendPolyLineToBezier * *  PURPOSE    : Converts line segments into their Bezier point  *               representation and appends them to a list of Bezier points.  * *               WARNING - The array must have at least one valid *               start point prior to the address of the element passed. * *  RETURNS    : number of Bezier points added to the POINT array. ****************************************************************************/ UINT AppendPolyLineToBezier( LPPOINT pt, POINTFX start, LPTTPOLYCURVE lpCurve ){    int     i;    UINT    cTotal = 0;    POINT   endpt;    POINT   startpt;    POINT   bezier[4];    endpt.x = IntFromFixed(start.x);    endpt.y = IntFromFixed(start.y);    for (i = 0; i < lpCurve->cpfx; i++)    {        // define the line segment        startpt = endpt;        endpt.x = IntFromFixed(lpCurve->apfx[i].x);        endpt.y = IntFromFixed(lpCurve->apfx[i].y);        // convert a line to a bezier representation        MakeBezierFromLine( bezier, startpt, endpt );        // append the Bezier to the existing ones                                    // Point 0 is Point 3 of previous.        pt[cTotal++] = bezier[1];   // Point 1        pt[cTotal++] = bezier[2];   // Point 2        pt[cTotal++] = bezier[3];   // Point 3    }    return cTotal;}/**************************************************************************** *  FUNCTION   : AppendQuadBSplineToBezier * *  PURPOSE    : Converts Quadratic spline segments into their Bezier point  *               representation and appends them to a list of Bezier points.  * *               WARNING - The array must have at least one valid *               start point prior to the address of the element passed. * *  RETURNS    : number of Bezier points added to the POINT array. ****************************************************************************/ UINT AppendQuadBSplineToBezier( LPPOINT pt, POINTFX start, LPTTPOLYCURVE lpCurve ){    WORD                i;    UINT                cTotal = 0;    POINTFX             spline[3];  // a Quadratic is defined by 3 points    POINT               bezier[4];  // a Cubic by 4    // The initial A point is on the curve.    spline[0] = start;    for (i = 0; i < lpCurve->cpfx;)    {        // The B point.        spline[1] = lpCurve->apfx[i++];        // Calculate the C point.        if (i == (lpCurve->cpfx - 1))        {            // The last C point is described explicitly            // i.e. it is on the curve.            spline[2] = lpCurve->apfx[i++];        }             else        {            // C is midpoint between B and next B point            // because that is the on curve point of             // a Quadratic B-Spline.            spline[2].x = fxDiv2(                lpCurve->apfx[i-1].x,                lpCurve->apfx[i].x                );            spline[2].y = fxDiv2(                lpCurve->apfx[i-1].y,                lpCurve->apfx[i].y                );        }        // convert the Q Spline to a Bezier        MakeBezierFromQBSpline( bezier, spline );                // append the Bezier to the existing ones                                    // Point 0 is Point 3 of previous.        pt[cTotal++] = bezier[1];   // Point 1        pt[cTotal++] = bezier[2];   // Point 2        pt[cTotal++] = bezier[3];   // Point 3        // New A point for next slice of spline is the         // on curve C point of this B-Spline        spline[0] = spline[2];    }    return cTotal;}/**************************************************************************** *  FUNCTION   : CloseContour * *  PURPOSE    : Adds a bezier line to close the circuit defined in pt. * * *  RETURNS    : number of points aded to the pt POINT array. ****************************************************************************/ UINT CloseContour( LPPOINT pt, UINT cTotal ){    POINT               endpt,                         startpt;    // definition of a line    POINT               bezier[4];    // connect the first and last points by a line segment    startpt = pt[cTotal-1];    endpt = pt[0];    // convert a line to a bezier representation    MakeBezierFromLine( bezier, startpt, endpt );    // append the Bezier to the existing ones                                // Point 0 is Point 3 of previous.    pt[cTotal++] = bezier[1];   // Point 1    pt[cTotal++] = bezier[2];   // Point 2    pt[cTotal++] = bezier[3];   // Point 3    return 3;}/**************************************************************************** *  FUNCTION   : DrawT2Outline * *  PURPOSE    : Decode the GGO_NATIVE outline, create a sequence of Beziers *               for each contour, draw with PolyBezier.  Color and relative  *               positioning provided by caller. The coordinates of hDC are *               assumed to have MM_TEXT orientation. * *               The outline data is not scaled. To draw a glyph unhinted *               the caller should create the font at its EMSquare size *               and retrieve the outline data. Then setup a mapping mode *               prior to calling this function. * *  RETURNS    : none. ****************************************************************************/ void DrawT2Outline(HDC hDC, LPTTPOLYGONHEADER lpHeader, DWORD size) {    WORD                i;    UINT                cTotal = 0; // Total points in a contour.    LPTTPOLYGONHEADER   lpStart;    // the start of the buffer    LPTTPOLYCURVE       lpCurve;    // the current curve of a contour    LPPOINT             pt;         // the bezier buffer    POINTFX             ptStart;    // The starting point of a curve    DWORD               dwMaxPts = size/size of(POINTFX); // max possible pts.    DWORD               dwBuffSize;    dwBuffSize = dwMaxPts *     // Maximum possible # of contour points.                 sizeof(POINT) * // sizeof buffer element                 3;             // Worst case multiplier of one additional point                                // of line expanding to three points of a bezier   lpStart = lpHeader;   pt = (LPPOINT)malloc( dwBuffSize );    // Loop until we have processed the entire buffer of contours.    // The buffer may contain one or more contours that begin with    // a TTPOLYGONHEADER. We have them all when we the end of the buffer.    while ((DWORD)lpHeader < (DWORD)(((LPSTR)lpStart) + size) && pt != NULL)    {        if (lpHeader->dwType == TT_POLYGON_TYPE)        // Draw each coutour, currently this is the only valid        // type of contour.        {            // Convert the starting point. It is an on curve point.            // All other points are continuous from the "last"             // point of the contour. Thus the start point the next            // bezier is always pt[cTotal-1] - the last point of the             // previous bezier. See PolyBezier.            cTotal = 1;            pt[0].x = IntFromFixed(lpHeader->pfxStart.x);            pt[0].y = IntFromFixed(lpHeader->pfxStart.y);            // Get to first curve of contour -             // it starts at the next byte beyond header            lpCurve = (LPTTPOLYCURVE) (lpHeader + 1);            // Walk this contour and process each curve( or line ) segment             // and add it to the Beziers            while ((DWORD)lpCurve < (DWORD)(((LPSTR)lpHeader) + lpHeader->cb))            {                //**********************************************                // Format assumption:                //   The bytes immediately preceding a POLYCURVE                //   structure contain a valid POINTFX.                //                 //   If this is first curve, this points to the                 //      pfxStart of the POLYGONHEADER.                //   Otherwise, this points to the last point of                //      the previous POLYCURVE.                //                 //   In either case, this is representative of the                //      previous curve's last point.                //**********************************************                ptStart = *(LPPOINTFX)((LPSTR)lpCurve - sizeof(POINTFX));                if (lpCurve->wType == TT_PRIM_LINE)                {                    // convert the line segments to Bezier segments                    cTotal += AppendPolyLineToBezier( &pt[cTotal], ptStart, lpCurve );                    i = lpCurve->cpfx;                }                else if (lpCurve->wType == TT_PRIM_QSPLINE)                {                    // Decode each Quadratic B-Spline segment, convert to bezier,                    // and append to the Bezier segments                    cTotal += AppendQuadBSplineToBezier( &pt[cTotal], ptStart, lpCurve );                    i = lpCurve->cpfx;                }                else                    // Oops! A POLYCURVE format we don't understand.                    ; // error, error, error            // Move on to next curve in the contour.            lpCurve = (LPTTPOLYCURVE)&(lpCurve->apfx[i]);            }            // Add points to close the contour.            // All contours are implied closed by TrueType definition.            // Depending on the specific font and glyph being used, these            // may not always be needed.            if ( pt[cTotal-1].x != pt[0].x || pt[cTotal-1].y != pt[0].y )            {                cTotal += CloseContour( pt, cTotal );            }            // flip coordinates to get glyph right side up (Windows coordinates)            // TT native coordiantes are zero originate at lower-left.            // Windows MM_TEXT are zero originate at upper-left.            for (i = 0; i < cTotal; i++)                pt[i].y = 0 - pt[i].y;            // Draw the contour            PolyBezier( hDC, pt, cTotal );        }        else            // Bad, bail, must have a bogus buffer.            break; // error, error, error        // Move on to next Contour.        // Its header starts immediate after this contour        lpHeader = (LPTTPOLYGONHEADER)(((LPSTR)lpHeader) + lpHeader->cb);    }    free( pt );}				
関連情報
TrueType 仕様の詳細についてをご覧ください。
Microsoft TrueType 仕様 (http://www.microsoft.com/typography/tt/tt.htm)

使用可能で、Microsoft 開発ネットワーク ライブラリ CD の仕様の下で。

警告: この記事は自動翻訳されています

プロパティ

文書番号:243285 - 最終更新日: 07/22/2011 17:58:00 - リビジョン: 3.0

  • kbhowto kbfont kbgdi kbdraw kbdswgdi2003swept kbmt KB243285 KbMtja
フィードバック