?? fonttext.h
字號:
#pragma once
//-----------------------------------------------------------------------------------//
// Windows Graphics Programming: Win32 GDI and DirectDraw //
// ISBN 0-13-086985-6 //
// //
// Written by Yuan, Feng www.fengyuan.com //
// Copyright (c) 2000 by Hewlett-Packard Company www.hp.com //
// Published by Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com //
// //
// FileName : fonttext.h //
// Description: Font & text routines and classes //
// Version : 1.00.000, May 31, 2000 //
//-----------------------------------------------------------------------------------//
// convert point size to logical coordinate space size
int PointSizetoLogical(HDC hDC, int points, int divisor=1);
// Create a font as large as EM square size for accurate metrics
HFONT CreateReferenceFont(HFONT hFont, int & emsquare);
// justify text string within a left..right margin
BOOL TextOutJust(HDC hDC, int left, int right, int y, LPCTSTR lpStr, int nCount, bool bAllowNegative=false, TCHAR cBreakChar=' ');
// ABC extent of a text string
// ( A0, B0, C0 ) + ( A1, B1, C1 ) = ( A0, B0+C0+A1+B1, C1 }
BOOL GetTextABCExtent(HDC hDC, LPCTSTR lpString, int cbString, long * pHeight, ABC * pABC);
BOOL GetOpaqueBox(HDC hDC, LPCTSTR lpString, int cbString, RECT * pRect, int x, int y);
// Pixel-level precise text alignment
BOOL PreciseTextOut(HDC hDC, int x, int y, LPCTSTR lpString, int cbString);
class KLogFont
{
public:
LOGFONT m_lf;
KLogFont(int height, const TCHAR * typeface=NULL)
{
m_lf.lfHeight = height;
m_lf.lfWidth = 0;
m_lf.lfEscapement = 0;
m_lf.lfOrientation = 0;
m_lf.lfWeight = FW_NORMAL;
m_lf.lfItalic = FALSE;
m_lf.lfUnderline = FALSE;
m_lf.lfStrikeOut = FALSE;
m_lf.lfCharSet = ANSI_CHARSET;
m_lf.lfOutPrecision = OUT_TT_PRECIS;
m_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
m_lf.lfQuality = DEFAULT_QUALITY;
m_lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
if ( typeface )
_tcsncpy(m_lf.lfFaceName, typeface, LF_FACESIZE-1);
else
m_lf.lfFaceName[0] = 0;
}
HFONT CreateFont(void)
{
return ::CreateFontIndirect(& m_lf);
}
int GetObject(HFONT hFont)
{
return ::GetObject(hFont, sizeof(m_lf), & m_lf);
}
};
template <int maxlength>
class KPlacement
{
public:
GCP_RESULTS m_gcp;
TCHAR m_strOut[maxlength];
int m_dx [maxlength];
unsigned m_order [maxlength];
int m_caret [maxlength];
char m_class [maxlength];
WORD m_glyphs[maxlength];
DWORD GetPlacement(HDC hDC, const TCHAR * mess, DWORD flags=0, int maxextent=0)
{
memset(&m_gcp, 0, sizeof(m_gcp));
m_gcp.lStructSize = sizeof(GCP_RESULTS);
m_gcp.lpOutString = m_strOut;
m_gcp.lpOrder = m_order;
m_gcp.lpDx = m_dx;
m_gcp.lpCaretPos = m_caret;
m_gcp.lpClass = m_class;
m_gcp.lpGlyphs = m_glyphs;
m_gcp.nGlyphs = maxlength;
return GetCharacterPlacement(hDC, mess, _tcslen(mess), maxextent, & m_gcp, flags);
}
BOOL GlyphTextOut(HDC hDC, int x, int y)
{
return ExtTextOut(hDC, x, y, ETO_GLYPH_INDEX, NULL, (LPCTSTR) m_glyphs, m_gcp.nGlyphs, m_dx);
}
};
class KKerningPair
{
public:
KERNINGPAIR * m_pKerningPairs;
int m_nPairs;
KKerningPair(HDC hDC)
{
m_nPairs = GetKerningPairs(hDC, 0, NULL);
if ( m_nPairs==0 )
m_pKerningPairs = NULL;
else
{
m_pKerningPairs = new KERNINGPAIR[m_nPairs];
assert(m_pKerningPairs);
GetKerningPairs(hDC, m_nPairs, m_pKerningPairs);
}
}
int GetKerning(TCHAR first, TCHAR second)
{
for (int i=0; i<m_nPairs; i++)
if ( (m_pKerningPairs[i].wFirst ==first) &&
(m_pKerningPairs[i].wSecond==second) )
return m_pKerningPairs[i].iKernAmount;
return 0;
}
~KKerningPair(void)
{
if ( m_pKerningPairs )
{
delete m_pKerningPairs;
m_pKerningPairs = NULL;
}
}
};
class KGlyph
{
public:
GLYPHMETRICS m_metrics;
BYTE * m_pPixels;
DWORD m_nAllocSize;
DWORD m_nDataSize;
int m_uFormat;
KGlyph()
{
m_pPixels = NULL;
}
~KGlyph(void);
DWORD GetGlyph(HDC hDC, UINT uChar, UINT uFormat, const MAT2 * pMat2=NULL);
BOOL DrawGlyphROP(HDC HDC, int x, int y, DWORD rop, COLORREF crBack, COLORREF crFore);
BOOL DrawGlyph(HDC HDC, int x, int y, int & dx, int & dy);
};
template <int MAX_POINTS>
class KGlyphOutline
{
public:
POINT m_Point[MAX_POINTS];
BYTE m_Flag [MAX_POINTS];
int m_nPoints;
private:
void AddPoint(int x, int y, BYTE flag)
{
if ( m_nPoints < MAX_POINTS )
{
m_Point[m_nPoints].x = x;
m_Point[m_nPoints].y = y;
m_Flag [m_nPoints] = flag;
m_nPoints ++;
}
else
assert(false);
}
void AddQSpline(int x1, int y1, int x2, int y2)
{
assert(m_nPoints);
// p0 p1 p2 -> p0 (p0+2p1)/3 (2p1+p2)/3, p2
int x0 = m_Point[m_nPoints-1].x;
int y0 = m_Point[m_nPoints-1].y;
AddCSpline((x0+2*x1)/3, (y0+2*y1)/3, (2*x1+x2)/3, (2*y1+y2)/3, x2, y2);
}
void AddCSpline(int x1, int y1, int x2, int y2, int x3, int y3)
{
assert(m_nPoints);
AddPoint(x1, y1, PT_BEZIERTO);
AddPoint(x2, y2, PT_BEZIERTO);
AddPoint(x3, y3, PT_BEZIERTO);
}
void MarkLast(BYTE flag)
{
assert(m_nPoints);
m_Flag[m_nPoints-1] |= flag;
}
void Transform(int dx, int dy)
{
for (int i=0; i<m_nPoints; i++)
{
m_Point[i].x = ( m_Point[i].x + 32768 ) / 65536 + dx;
m_Point[i].y = ( - m_Point[i].y + 32768 ) / 65536 + dy;
}
}
public:
int DecodeTTPolygon(const TTPOLYGONHEADER * lpHeader, int size);
BOOL Draw(HDC hDC, int x, int y)
{
Transform(x, y);
return PolyDraw(hDC, m_Point, m_Flag, m_nPoints);
}
int DecodeOutline(KGlyph & glyph)
{
if ( (glyph.m_uFormat==GGO_NATIVE) || (glyph.m_uFormat==GGO_BEZIER) )
return DecodeTTPolygon((const TTPOLYGONHEADER *) glyph.m_pPixels, glyph.m_nDataSize);
else
return 0;
}
};
template <int MAX_POINTS>
int KGlyphOutline<MAX_POINTS>::DecodeTTPolygon(const TTPOLYGONHEADER * pHeader, int size)
{
m_nPoints = 0;
while ( size>sizeof(TTPOLYGONHEADER) )
{
int curvesize = pHeader->cb;
size -= curvesize;
if ( size<0 )
{
assert(false);
break;
}
if (pHeader->dwType != TT_POLYGON_TYPE)
{
assert(false);
break;
}
const POINT * p = (const POINT *) & pHeader->pfxStart;
AddPoint(p[0].x, p[0].y, PT_MOVETO);
const TTPOLYCURVE * pCurve = (const TTPOLYCURVE *) & pHeader[1];
while ( (unsigned) pCurve < ( ((unsigned) pHeader) + curvesize) )
{
int i;
p = (const POINT *) pCurve->apfx;
switch ( pCurve->wType )
{
case TT_PRIM_LINE: // polyline.
for (i=0; i<pCurve->cpfx; i++)
AddPoint(p[i].x, p[i].y, PT_LINETO);
break;
case TT_PRIM_QSPLINE: // quadratic B閦ier spline.
assert(pCurve->cpfx>=2);
for (i=0; i<(pCurve->cpfx-1); i++)
if ( i==(pCurve->cpfx-2) )
AddQSpline(p[i].x, p[i].y, p[i+1].x, p[i+1].y);
else
AddQSpline(
p[i].x,
p[i].y,
( p[i].x + p[i+1].x ) / 2,
( p[i].y + p[i+1].y ) / 2);
break;
case TT_PRIM_CSPLINE: // cubic Bezier spline
assert((pCurve->cpfx % 3) ==0);
for (i=0; i<pCurve->cpfx; i+=3)
AddCSpline(p[i].x, p[i].y, p[i+1].x, p[i+1].y, p[i+2].x, p[i+2].y);
break;
default:
assert(false);
return 0;
}
pCurve = (const TTPOLYCURVE *) & pCurve->apfx[pCurve->cpfx];
}
MarkLast(PT_CLOSEFIGURE);
pHeader = (const TTPOLYGONHEADER *) ((unsigned) pHeader + curvesize);
}
return m_nPoints;
}
BOOL BitmapTextOut(HDC hDC, int x, int y, const TCHAR * str, int count, int format = GGO_BITMAP);
BOOL BitmapTextOutROP(HDC hDC, int x, int y, const TCHAR * str, int count, DWORD rop);
BOOL OutlineTextOut(HDC hDC, int x, int y, const TCHAR * str, int count);
///////////////////////////////////////////////////////////
class KTextFormator
{
typedef enum { MaxCharNo = 256 };
float m_fCharWidth[MaxCharNo];
float m_fHeight;
float m_fLinespace;
public:
BOOL SetupPixel(HDC hDC, HFONT hFont, float pixelsize);
BOOL Setup(HDC hDC, HFONT hFont, float pointsize);
float GetLinespace(void) const
{
return m_fLinespace;
}
BOOL GetTextExtent(HDC hdc, LPCTSTR pString, int cbString, float & width, float & height);
BOOL TextOut(HDC hDC, int x, int y, LPCTSTR pString, int nCount);
DWORD DrawText(HDC hDC, LPCTSTR pString, int nCount, const RECT * pRect, UINT uFormat);
};
BOOL ColorText(HDC hDC, int x, int y, LPCTSTR pString, int nCount, HBRUSH hFore);
BOOL BitmapText(HDC hDC, int x, int y, LPCTSTR pString, int nCount, HBITMAP hBmp);
BOOL BitmapText2(HDC hDC, int x, int y, LPCTSTR pString, int nCount, HBITMAP hBmp);
BOOL OffsetTextOut(HDC hDC, int x, int y, LPCTSTR pStr, int nCount,
int dx1, int dy1, COLORREF cr1,
int dx2, int dy2, COLORREF cr2);
BOOL DrawChar(HDC hDC, double x0, double y0, double x1, double y1, TCHAR ch);
void PathTextOut(HDC hDC, LPCTSTR pString, POINT point[], int no);
BOOL PathTextOut(HDC hDC, LPCTSTR pString);
// 3x3 average filter for any 8-bpp, 24-bpp, or 32-bpp frame buffer
template <int bytepp>
void Average(BYTE * pBits, int pitch, int width, int height)
{
BYTE * buffer = new BYTE[pitch*2];
for (int y=1; y<height; y++)
{
pBits += pitch; // first channel of pixel 0
if ( y<(height-1) )
{
BYTE * P = pBits + bytepp; // pixel 1
BYTE * B = buffer + pitch * (y & 1); // pixel 1..n-2
for (int x=1; x<(width-1); x++)
{
for (int b=0; b<bytepp; b++)
{
B[0] = ( P[-pitch-bytepp] + P[-pitch] + P[-pitch+bytepp] +
P[ -bytepp] + P[ 0] + P[ bytepp] +
P[ pitch-bytepp] + P[ pitch] + P[ pitch+bytepp])/9;
P ++;
B ++;
}
}
}
if ( y>=2 )
{
memcpy(pBits-pitch+bytepp, buffer + pitch * ( 1 - (y & 1)), (width-2) * bytepp);
}
}
delete [] buffer;
}
// Conver text string to bitmap
class KTextBitmap
{
public:
HBITMAP m_hBitmap;
HDC m_hMemDC;
HGDIOBJ m_hOldBmp;
int m_width;
int m_height;
int m_dx;
int m_dy;
BYTE * m_pBits;
BOOL Convert(HDC hDC, LPCTSTR pString, int nCount, int extra);
void ReleaseBitmap(void)
{
if ( m_hOldBmp )
{
SelectObject(m_hMemDC, m_hOldBmp);
m_hOldBmp = NULL;
}
if ( m_hBitmap )
{
DeleteObject(m_hBitmap);
m_hBitmap = NULL;
}
}
KTextBitmap()
{
m_hBitmap = NULL;
m_hMemDC = NULL;
m_hOldBmp = NULL;
}
~KTextBitmap()
{
if ( m_hMemDC )
{
DeleteObject(m_hMemDC);
m_hMemDC = NULL;
}
}
void Blur(void);
BOOL Draw(HDC hDC, int x, int y, int rop=SRCCOPY)
{
return BitBlt(hDC, x - m_dx, y - m_dy, m_width, m_height,
m_hMemDC, 0, 0, rop);
}
BOOL RenderText(HDC hDC, int x, int y, const TCHAR * pString, int nCount);
};
// Embossing or Engraving by change edges only, good for non-solod background
void TransparentEmboss(HDC hDC, const TCHAR * pString, int nCount, COLORREF crTL, COLORREF crBR, int offset, int x, int y);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -