录十六

持之以恒

字体轮廓线提取【Windows平台】

22.png

/**
 * DrawFontGlyph:获取字符轮廓线,并填充字符
 * @gfx: 绘图设备上下文指针
 * @hFonDC: 文字相关的设备DC
 * @chCode: 字符的UTF8编码值
 **/
void DrawFontGlyph(GfxContext* gfx, HDC hFontDC, UINT chCode)
{
    UINT fuFmt = GGO_NATIVE;

    MAT2 mat;
    memset(&mat, 0, sizeof(mat));
    mat.eM11.value = mat.eM22.value = 1; 

    GLYPHMETRICS gm;
    memset(&gm, 0, sizeof(GLYPHMETRICS));

    DWORD dwSize = GetGlyphOutlineW(hFontDC, chCode, fuFmt, &gm, 0, NULL, &mat);
    if (dwSize > 0 && dwSize != GDI_ERROR)
    {
        LPBYTE pBuf = new unsigned char[dwSize];
        DWORD ret = GetGlyphOutlineW(hFontDC, chCode, fuFmt, &gm, dwSize, pBuf, &mat);
        if (ret != GDI_ERROR)
        {
            unsigned char* Buffer = pBuf;
            unsigned int   Count  = dwSize;

            while (Count > 0)
            {
                //轮廓信息头
                TTPOLYGONHEADER* Header = (TTPOLYGONHEADER*)Buffer;

                //轮廓的起始数据地址
                LPBYTE Start = Buffer + sizeof(TTPOLYGONHEADER); 

                //---------------------------------------
                //闭合轮廓的起点 
                POINTFX StartPoint = Header->pfxStart;

                double s_x = FixedToDBL(StartPoint.x);
                double s_y = FixedToDBL(StartPoint.y);  

                gfx->move_to(s_x, s_y);

                //--------------------------------------------

                DWORD Remain = Header->cb - sizeof(TTPOLYGONHEADER);
                while (Remain>0)
                {
                    TTPOLYCURVE* Curve = (TTPOLYCURVE*)Start;
                    switch (Curve->wType)
                    {
                    case TT_PRIM_LINE:   //折线
                        {
                            POINTFX* pPoints =  Curve->apfx;
                            for(int i=0; i<Curve->cpfx; i++)
                            {
                                double x = FixedToDBL(pPoints[i].x);
                                double y = FixedToDBL(pPoints[i].y);

                                gfx->line_to(x, y);
                            }
                        }
                        break;
                    case  TT_PRIM_QSPLINE: //二次贝塞尔曲线
                        {                         
                            POINTFX* pPoints =  Curve->apfx;

                            double x1 = FixedToDBL(pPoints[0].x);
                            double y1 = FixedToDBL(pPoints[0].y);
                            double x2 = FixedToDBL(pPoints[1].x);
                            double y2 = FixedToDBL(pPoints[1].y);

                            gfx->quad_to(x1, y1, x2, y2); 
                        }
                        break;
                    case  TT_PRIM_CSPLINE : //三次贝塞尔曲线
                        {
                            POINTFX* pPoints =  Curve->apfx;

                            double x1 = FixedToDBL(pPoints[0].x);
                            double y1 = FixedToDBL(pPoints[0].y);
                            double x2 = FixedToDBL(pPoints[1].x);
                            double y2 = FixedToDBL(pPoints[1].y);
                            double x3 = FixedToDBL(pPoints[2].x);
                            double y3 = FixedToDBL(pPoints[2].y);

                            gfx->cubic_to(x1, y1, x2, y2, x3, y3);
                        }
                        break;
                    }

                    Start += sizeof(TTPOLYCURVE) + (Curve->cpfx - 1)*sizeof(POINTFX);
                    Remain -= sizeof(TTPOLYCURVE) + (Curve->cpfx - 1)*sizeof(POINTFX); 
                }

                //绘制闭合轮廓 
                gfx->close_path();

                Buffer += Header->cb;
                Count -= Header->cb;
            }
                     
            gfx->stroke_preserve(1.0, 0.0, 0.0, 1.0);     
            gfx->fill(0.4, 1.0, 0.0,0.2); 
        }

        delete[] pBuf;
    }
}


发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Copyright © 1999-2019, lu16.com, All Rights Reserved