BCB ���������������
// .h

    inline double __fastcall getY(double pos)
    {
        // Bitmap は Y が逆転するため
        return(outlineBitmap->Height - pos);
    };

// .cpp

//---------------------------------------------------------------------------
// POINTFX->double 型変換
//---------------------------------------------------------------------------
void __fastcall TMainForm::cmnPointfx2double(POINTFX pfx, double* x, double* y)
{
    *x = pfx.x.value + pfx.x.fract / 65536;
    *y = pfx.y.value + pfx.y.fract / 65536;
}

//---------------------------------------------------------------------------
// outline 画像、txt データ生成
//---------------------------------------------------------------------------
int __fastcall TMainForm::cmnMakeTxt(void)
{
    TxtMemo->Clear();

    // TBitmap初期化
    if(outlineBitmap == NULL)
    {
        outlineBitmap = new Graphics::TBitmap;
    }

    // サイズ初期化
    outlineBitmap->Width  = FontPaintBox->Width;
    outlineBitmap->Height = FontPaintBox->Height;

    // 背景初期化
    outlineBitmap->Canvas->Brush->Color = ConfigForm->OutlineBmpBgJvColorComboBox->ColorValue;
    outlineBitmap->Canvas->Brush->Style = bsSolid;
    outlineBitmap->Canvas->FillRect(ClientRect);
    outlineBitmap->Canvas->Brush->Style = bsClear;

    // ペン初期化
    outlineBitmap->Canvas->Pen->Color = ConfigForm->OutlineBmpLineJvColorComboBox->ColorValue;
    outlineBitmap->Canvas->Pen->Width = ConfigForm->OutlineBmpLineWidthJvEdit->Text.ToInt();

    // AnsiString を C 文字列化
    char* str = (char*)malloc(StringEdit->Text.Length() + 1);

    if(str == NULL)
    {
        cmnShowError();
        return(S2N_NG);
    }

    memset(str, 0x00, StringEdit->Text.Length() + 1);
    strncpy(str, StringEdit->Text.c_str(), StringEdit->Text.Length());
    char* ptr = str;

    baseX = baseY = 0;

    // 文字列終端まで文字単位にループ
    while(UINT asciiOfChar = _mbsnextc(ptr))
    {
        GLYPHMETRICS glyphMetrics;
        memset(&glyphMetrics, 0x00, sizeof(GLYPHMETRICS));
        MAT2         mat2 = {{0,1}, {0,0}, {0,0}, {0,1}};  // value は 1, 0, 0, 1 で固定

        // バッファサイズ取得
        DWORD bufSize = GetGlyphOutline(
                            fontBitmap->Canvas->Handle,  // DCハンドル
                            asciiOfChar,                  // 対象文字
                            GGO_NATIVE,                   // ベクター情報の取得
                            &glyphMetrics,                // 取得データ
                            0,                            // 0 だと必要なバッファサイズを返す
                            NULL,                         // NULL だと必要なバッファサイズを返す
                            &mat2);                       // 変換マトリクス

        if(bufSize == GDI_ERROR)
        {
            cmnShowError();
            return(S2N_NG);
        }

        char* buf = new BYTE[bufSize];
        char* pos = buf;

        // バッファ取得
        DWORD rtn = GetGlyphOutline(
                        fontBitmap->Canvas->Handle,  // DCハンドル
                        asciiOfChar,                  // 対象文字
                        GGO_NATIVE,                   // ベクター情報の取得
                        &glyphMetrics,                // 取得データ
                        bufSize,                      // バッファサイズ
                        (LPVOID)buf,                  // バッファ
                        &mat2);                       // 変換マトリクス

        if(rtn == GDI_ERROR)
        {
            cmnShowError();
            return(S2N_NG);
        }

        // アウトラインのヘッダーを取得
        TTPOLYGONHEADER* header = (TTPOLYGONHEADER*)pos;

        if(str == ptr)   // 文字列の最初なら
        {
            baseX = glyphMetrics.gmptGlyphOrigin.x;
            baseY = glyphMetrics.gmptGlyphOrigin.y;
        }

        double x, y, aX, aY, bX, bY, cX, cY;

        while(header->dwType == TT_POLYGON_TYPE)  // ヘッダタイプ(現状 TT_POLYGON_TYPE 固定))
        {
            // アウトラインの開始座標
            cmnPointfx2double(header->pfxStart, &x, &y);
            double startX = x;
            double startY = y;

            outlineBitmap->Canvas->MoveTo(baseX + x, getY(baseY + y));

            // アウトラインの本体を取得
            pos += sizeof(TTPOLYGONHEADER);
            TTPOLYCURVE* curve = (TTPOLYCURVE*)pos;
            POINTFX* pfx;

            aX = aY = bX = bY = cX = cY = 0;

            signed int remainSize = header->cb - sizeof(TTPOLYGONHEADER);  // 残りサイズ

            while(remainSize > 0)
            {
                // カーブの開始座標(アウトラインの開始座標 or 前回の最後の座標)
                TxtMemo->Lines->Add(AnsiString(baseX + x) + " " + AnsiString(baseY + y) + " ");
                outlineBitmap->Canvas->LineTo(baseX + x, getY(baseY + y));

                WORD type = curve->wType;

                if((type != TT_PRIM_LINE) &&   // 直線
                   (type != TT_PRIM_QSPLINE))  // 曲線
                {
                    return(S2N_NG);
                }

                if((type == TT_PRIM_QSPLINE) && (aX == 0) && (aY == 0))
                {
                    aX = x;
                    aY = y;
                }

                WORD num = curve->cpfx;

                if(num > 0)
                {
                    pos = (char*)(&(curve->apfx)[0]);
                    pfx = (POINTFX*)pos;

                    for(int i = 0; i < num; i++)
                    {
                        // 直線なら x,y をそのまま描画座標にする
                        if(type == TT_PRIM_LINE)
                        {
                            cmnPointfx2double(*pfx, &x, &y);
                            TxtMemo->Lines->Add(AnsiString(baseX + x) + " " + AnsiString(baseY + y) + " ");
                            outlineBitmap->Canvas->LineTo(baseX + x, getY(baseY + y));
                        }
                        else if(type == TT_PRIM_QSPLINE)
                        {
                            if((bX == 0) && (bY == 0))
                            {
                                cmnPointfx2double(*pfx, &x, &y);
                                bX = x;
                                bY = y;

                                // b を出力しないと曲線補間なし
                                if(ConfigForm->TxtCurve3PointRadioButton->Checked)
                                {
                                    TxtMemo->Lines->Add(AnsiString(baseX + x) + " " + AnsiString(baseY + y) + " ");
                                    outlineBitmap->Canvas->LineTo(baseX + x, getY(baseY + y));
                                }
                            }
                            else
                            {
                                cmnPointfx2double(*pfx, &x, &y);
                                cX = x;
                                cY = y;

                                // 曲線を二次スプライン化
                                if(ConfigForm->TxtCurveSplineRadioButton->Checked)
                                {
                                    // 取得された曲線の 3 点に対して t (0.0~1.0)を変化させて得た点でプロットする
                                    // x(t) = (xA-2xB+xC)*(t^2) + (2xB-2xA)*t + xA
                                    // y(t) = (yA-2yB+yC)*(t^2) + (2yB-2yA)*t + yA

                                    int splineDivNum = ConfigForm->TxtSplineDivNumJvEdit->Text.ToInt();

                                    for(int i = 0; i < (splineDivNum + 1); i++)
                                    {
                                        double t = (1.0 / splineDivNum) * i;

                                        x = ((aX - (bX * 2) + cX) * pow(t, 2)) + (((bX * 2) - (aX * 2)) * t) + aX;
                                        y = ((aY - (bY * 2) + cY) * pow(t, 2)) + (((bY * 2) - (aY * 2)) * t) + aY;

                                        TxtMemo->Lines->Add(FormatFloat("0.###", x + baseX) + " " + FormatFloat("0.###", baseY + y) + " ");
                                        outlineBitmap->Canvas->LineTo(baseX + x, getY(baseY + y));
                                    }
                                }
                                else
                                {
                                    TxtMemo->Lines->Add(AnsiString(baseX + x) + " " + AnsiString(baseY + y) + " ");
                                    outlineBitmap->Canvas->LineTo(baseX + x, getY(baseY + y));
                                }
                            }
                        }

                        pos += sizeof(POINTFX);
                        pfx = (POINTFX*)pos;
                    }
                }

                curve = (TTPOLYCURVE*)pos;
                remainSize -= (sizeof(TTPOLYCURVE) + (sizeof(POINTFX) * (num - 1)));

                aX = aY = bX = bY = cX = cY = 0;
            }

            // 最後の座標が始点と一致しなければ矩形の始点に戻る線を書く
            if((startX != x) || (startY != y))
            {
                TxtMemo->Lines->Add(AnsiString(baseX + startX) + " " + AnsiString(baseY + startY) + " ");
                outlineBitmap->Canvas->LineTo(baseX + startX, getY(baseY + startY));
            }

            header = (TTPOLYGONHEADER*)pfx;
            TxtMemo->Lines->Add("");
        }

	    ptr = _mbsinc(ptr);  // 次の文字の取得

        baseX += glyphMetrics.gmCellIncX;
        baseY += glyphMetrics.gmCellIncY;

        delete [] buf;
    }

    delete [] str;

    // Canvas のコピー
    OutlinePaintBox->Canvas->CopyRect(
        Rect(0, 0, OutlinePaintBox->Width, OutlinePaintBox->Height),
        outlineBitmap->Canvas,
        Rect(0, 0, outlineBitmap->Width, outlineBitmap->Height));

    return(S2N_OK);
}