プログラミングメモ →目次

文字の輪郭を描画する方法(VC++)

TrueTypeフォントの文字の輪郭を取り出して、文字の輪郭だけを描画することができます。輪郭を取得するには、BOOL BeginPath( )を使います。デバイス コンテキストのパス ブラケットを開きます。パス ブラケットを開いた後、アプリケーションは GDI 描画関数の呼び出しを開始し、パス内の点を定義(記録)できます。アプリケーションは EndPath( ) メンバ関数を呼び出して開いたパス ブラケットを閉じられます。

例:

void CDrawTextOutlineView::DrawOutlineOfText(CDC* pDC, CString strText)
{
    CRect r;
    GetClientRect(&r);
    CDC dc;
//メモリDCを作ります。
    BOOL bRet = dc.CreateCompatibleDC(pDC);
    CBitmap bmpBack;
    bRet = bmpBack.CreateCompatibleBitmap(pDC, r.right, r.bottom);
    CBitmap* pOldBmp = dc.SelectObject(&bmpBack);
//やや大きめにフォントを設定しました。
    CFont font;
    LOGFONT logfont;
    memset(&logfont, 0, sizeof(logfont));
    logfont.lfHeight = 64;
    logfont.lfWidth = 0;
    logfont.lfWeight = 600;
    logfont.lfCharSet = SHIFTJIS_CHARSET;
    strcpy(logfont.lfFaceName, "MS P明朝");
    font.CreateFontIndirect(&logfont);
    CFont* pOldFont = dc.SelectObject(&font);
//メモリDC上の描画の記録を開始します。
    dc.BeginPath();
    dc.SetBkMode(TRANSPARENT);
//メモリDC上で文字列を描画します。
    dc.TextOut(0, 0, strText);
//メモリDC上の描画の記録を終了します。
    dc.EndPath();
//記録した描画情報の中にある曲線を直線(線分)に直す。
    dc.FlattenPath();
//記録した描画情報の点数を取得します。
    int nCount = dc.GetPath(NULL, NULL, 0);
    if (nCount <= 0)
        return;
    LPPOINT lpPoints = new POINT [nCount];
    LPBYTE lpTypes = new BYTE [nCount];
//記録した描画情報を取得します。
    dc.GetPath(lpPoints, lpTypes, nCount);

//記録した描画情報を利用して、ViewのDCに線分を描画します。
    POINT pntStart;
    for (int i = 0; i < nCount; i ++)
    {
//MoveToの描画
        if (lpTypes[i] == PT_MOVETO)
        {
            pDC->MoveTo(lpPoints[i].x, lpPoints[i].y);
            pntStart = lpPoints[i];
        }
//LineToの描画
        else if (lpTypes[i] == PT_LINETO)
        {
            pDC->LineTo(lpPoints[i].x, lpPoints[i].y);
        }
//頭と末尾を繋ぐ
        if (lpTypes[i] & PT_CLOSEFIGURE)
        {
            pDC->LineTo(pntStart.x, pntStart.y);
        }
    }
    delete lpPoints;
    delete lpTypes;
}