truetypefont:自己绘制True type font字体



  直以来我都是用点阵写字现在尝试直接使用True type font内容显示由曲线构成字体没想到居然成功了源代码如下:

# <windows.h>
# <vector>

/////////////////////////////////////////////////////////////////////////////
//
CTTFOutline
{
public:
typedef struct
{
std::vector<POINT> vectorPo;
} Contour;

public:
CTTFOutline;
~CTTFOutline;

BOOL Create( LPTTPOLYGONHEADER lpHeader, DWORD size );
void Destroy{ m_vectorContour.clear; }

GetContourCount{ m_vectorContour.size; }
Contour* GetContour( nContourId ){ &m_vectorContour[nContourId]; }

protected:
std::vector<Contour> m_vectorContour;
};

这个类用来作为ttf字体轮廓容器接下来这些代码用来获取TTF曲线信息

/****************************************************************************
* FUNCTION : IntFromFixed
* RETURNS : value approximating the FIXED value.
****************************************************************************/
PASCAL NEAR IntFromFixed(FIXED f)
{
(f.fract >= 0x8000)
(f.value + 1);

(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;
(*(FIXED *)&l);
}

/****************************************************************************
* FUNCTION : MakeBezierFromLine
*
* PURPOSE : Converts a line by two pos to a four po Bezier
* spline representation of the line in pPts.
*
*
* RETURNS : number of Bezier pos placed o the pPts POINT .gif' />.
****************************************************************************/
UINT MakeBezierFromLine( POINT *pPts, POINT startpt, POINT endpt )
{
UINT cTotal = 0; // starting po of Bezier
pPts[cTotal] = startpt;
cTotal; // 1rst Control, pt endpo makes Bezier a line
//pPts[cTotal].x = endpt.x;
//pPts[cTotal].y = endpt.y;
pPts[cTotal] = endpt;
cTotal; // 2nd Control, pt startpo makes Bezier a line
//pPts[cTotal].x = startpt.x;
//pPts[cTotal].y = startpt.y;
pPts[cTotal] = startpt;
cTotal; // ending po of Bezier
pPts[cTotal] = endpt;
cTotal;

cTotal;
}

/****************************************************************************
* FUNCTION : MakeBezierFromQBSpline
*
* PURPOSE : Converts a quadratic spline in pSline to a four po Bezier
* spline in pPts.
*
*
* RETURNS : number of Bezier pos placed o the pPts POINT .gif' />.
****************************************************************************/
UINT MakeBezierFromQBSpline( POINT *pPts, POINTFX *pSpline )
{
POINT P0, // Quadratic _disibledevent=>// Quadratic control po
P2; // Quadratic _disibledevent=>// Convert the Quadratic pos to eger
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 _disibledevent=>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 _disibledevent=>cTotal;
cTotal;
}

/****************************************************************************
* FUNCTION : AppendPolyLineToBezier
*
* PURPOSE : Converts line segments o their Bezier po
* representation and appends them to a list of Bezier pos.
*
* WARNING - The .gif' /> must have at least _disibledevent=>


* RETURNS : number of Bezier pos added to the POINT .gif' />.
****************************************************************************/
UINT AppendPolyLineToBezier( LPPOINT pt, POINTFX start, LPTTPOLYCURVE lpCurve )
{
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)
{
// 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 _disibledevent=>// Po 0 is Po 3 of previous.
pt[cTotal] = bezier[1]; // Po 1
pt[cTotal] = bezier[2]; // Po 2
pt[cTotal] = bezier[3]; // Po 3
}
cTotal;
}

/****************************************************************************
* FUNCTION : AppendQuadBSplineToBezier
*
* PURPOSE : Converts Quadratic spline segments o their Bezier po
* representation and appends them to a list of Bezier pos.
*
* WARNING - The .gif' /> must have at least _disibledevent=>POINTFX spline[3]; // a Quadratic is d by 3 pos
POINT bezier[4]; // a Cubic by 4 // The initial A po is _disibledevent=>for (i = 0; i < lpCurve->cpfx;)
{
// The B po.
spline[1] = lpCurve->apfx[i]; // Calculate the C po.
(i (lpCurve->cpfx - 1))
{
// The last C po is described explicitly
// i.e. it is _disibledevent=>}

{
// C is midpo between B and next B po
// because that is the _disibledevent=>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 _disibledevent=>// Po 1
pt[cTotal] = bezier[2]; // Po 2
pt[cTotal] = bezier[3]; // Po 3 // New A po for next slice of spline is the
// _disibledevent=>}
cTotal;
}

/****************************************************************************
* FUNCTION : CloseContour
*
* PURPOSE : Adds a bezier line to close the circuit d in pt.
*
*
* RETURNS : number of pos aded to the pt POINT .gif' />.
****************************************************************************/
UINT CloseContour( LPPOINT pt, UINT cTotal )
{
POINT endpt,
startpt; // definition of a line
POINT bezier[4]; // connect the first and last pos 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 _disibledevent=>// Po 0 is Po 3 of previous.
pt[cTotal] = bezier[1]; // Po 1
pt[cTotal] = bezier[2]; // Po 2
pt[cTotal] = bezier[3]; // Po 3
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 unhed
* the caller should create the font at its EMSquare size
* and retrieve the outline data. Then up a mapping mode
* prior to calling this function.
*
* RETURNS : none.
****************************************************************************/
CTTFOutline::CTTFOutline
{


}

CTTFOutline::~CTTFOutline
{
assert( m_vectorContour.empty );
}


BOOL CTTFOutline::Create( LPTTPOLYGONHEADER lpHeader, DWORD size )
{
WORD i;
UINT cTotal = 0; // Total pos 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 po of a curve
DWORD dwMaxPts = size/(POINTFX); // max possible pts.
DWORD dwBuffSize;
dwBuffSize = dwMaxPts * // Maximum possible # of contour pos.
(POINT) * // buffer element
3; // Worst multiplier of _disibledevent=>// of line expanding to three pos of a bezier
lpStart = lpHeader;
//pt = (LPPOINT)malloc( dwBuffSize ); // Loop until we have processed the entire buffer of contours.
pt = (LPPOINT) BYTE[dwBuffSize];
// The buffer may contain _disibledevent=>{
(lpHeader->dwType TT_POLYGON_TYPE)
// Draw each coutour, currently this is the _disibledevent=>// Convert the starting po. It is an _disibledevent=>// All other pos are continuous from the \"last\"
// po of the contour. Thus the start po the next
// bezier is always pt[cTotal-1] - the last po 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 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 s immediately preceding a POLYCURVE
// structure contain a valid POINTFX.
//
// If this is first curve, this pos to the
// pfxStart of the POLYGONHEADER.
// Otherwise, this pos to the last po of
// the previous POLYCURVE.
//
// In either , this is representative of the
// previous curve\'s last po.
//**********************************************
ptStart = *(LPPOINTFX)((LPSTR)lpCurve - (POINTFX));
(lpCurve->wType TT_PRIM_LINE)
{
// convert the line segments to Bezier segments
cTotal AppendPolyLineToBezier( &pt[cTotal], ptStart, lpCurve );
i = lpCurve->cpfx;
}
(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;
}

// Oops! A POLYCURVE format we don\'t understand.
; // error, error, error // Move _disibledevent=>} // Add pos to close the contour.

// All contours are implied closed by TrueType definition.
// Depending _disibledevent=>{
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
}
// RealRender added
Contour contour;
for( i = 0; i < cTotal; i )
{
contour.vectorPo.push_back( pt[i] );
}
m_vectorContour.push_back( contour );
}



// Bad, bail, must have a bogus buffer.
; // error, error, error // Move _disibledevent=>}

delete pt;
TRUE;
}



这段代码在指定位置把ttf轮廓画出来

void DrawTTFOutline( CTTFOutline* pOutline, x, y, DWORD color )
{
for( nContourId = 0; nContourId < pOutline->GetContourCount; nContourId )
{
CTTFOutline::Contour* pContour = pOutline->GetContour( nContourId );
POINT* pt = &pContour->vectorPo[0];
for( i = 0; i < pContour->vectorPo.size-1; i )
{
DrawLine( x+pt[i].x, y+pt[i].y, x+pt[i+1].x, y+pt[i+1].y, 0xffffffff );
}
}
}


根据这段代码不仅自己绘制ttf字体轮廓而且略加修改可以生成全 3维ttf mesh用d3d渲染看起来感觉不错
下次把代码提上来


CTTFOutline* CreateOutline( const char* pChar )
{
unsigned nChar;
( strlen( pChar ) 2 )
{
nChar = *(*)pChar;
nChar = (nChar>>8)|((nChar&0x00ff)<<8);
}

nChar = *pChar;

GLYPHMETRICS gmm;
MAT2 mat;
mat.eM11.value = 1;mat.eM11.fract = 0;
mat.eM12.value = 0;mat.eM12.fract = 0;
mat.eM21.value = 0;mat.eM21.fract = 0;
mat.eM22.value = 1;mat.eM22.fract = 0;


DWORD dwSize = GetGlyphOutline( m_hDC, nChar, GGO_NATIVE , &gmm, 0, 0, &mat );
( dwSize GDI_ERROR )
NULL;

BYTE* pBuffer = BYTE[dwSize];
( GetGlyphOutline( m_hDC, nChar, GGO_NATIVE, &gmm, dwSize, pBuffer, &mat ) GDI_ERROR )
{
delete pBuffer;
NULL;
}

TTPOLYGONHEADER* pHeader = (TTPOLYGONHEADER*)pBuffer;
CTTFOutline* pOutline = CTTFOutline;
( pOutline->Create( pHeader, dwSize ) )
{
delete pBuffer;
pOutline;
}
delete pBuffer;
delete pOutline;
NULL;
}


LOGFONT lf;

ZeroMemory(&lf, (lf));
lf.lfHeight = 160;
lf.lfEscapement = 0;
lf.lfOrientation = 0;
lf.lfWeight = FW_NORMAL;
lf.lfItalic = 0;
lf.lfUnderline = 1;
lf.lfStrikeOut = 1;
lf.lfCharSet = GB2312_CHARSET;
lf.lfOutPrecision = 1;
lf.lfClipPrecision = 0;
lf.lfQuality = 0;
lf.lfPitchAndFamily = 0;

lstrcpy(lf.lfFaceName, \"黑体\" );

CTTFOutline* outline = CreateOutline( \"哪\" );

通过这段代码就创建了个outline


有了ttf字体轮廓我想主要应用在3d渲染上比较有用比如些专门 3维字体制作工具或者用在游戏特殊效果中
比如说旋转“临兵斗者皆阵列在前”

希望对感兴趣朋友有用
qq:122045058

Tags:  truetype truetype字体 truetype字体文件 truetypefont

延伸阅读

最新评论

发表评论