311 lines
8.5 KiB
C
311 lines
8.5 KiB
C
|
/*
|
||
|
* @doc INTERNAL
|
||
|
*
|
||
|
* @module _FONT.H -- Declaration of classes comprising font caching |
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Font cache
|
||
|
*
|
||
|
* Owner: <nl>
|
||
|
* David R. Fulmer (original RE 1.0 code)<nl>
|
||
|
* Christian Fortini (initial conversion to C++)<nl>
|
||
|
* Jon Matousek <nl>
|
||
|
*
|
||
|
* History: <nl>
|
||
|
* 8/6/95 jonmat Devised dynamic expanding cache for widths.
|
||
|
*
|
||
|
* Copyright (c) 1995-1998 Microsoft Corporation. All rights reserved.
|
||
|
*/
|
||
|
|
||
|
#ifndef _FONT_H
|
||
|
#define _FONT_H
|
||
|
|
||
|
// Forwards
|
||
|
class CFontCache;
|
||
|
class CDevDesc;
|
||
|
class CDisplay;
|
||
|
// ============================= CCcs ========================
|
||
|
// CCcs - caches font metrics and character size for one font
|
||
|
|
||
|
#define DEFAULTCACHESIZE 0 // size - 1
|
||
|
#define INITIALCACHESIZE 7 // size - 1 = 7; 2^n-1; size = 8
|
||
|
#define PERFCHECKEPOCH 64 // If changed, you must recalc
|
||
|
// and change COLLISION_SHIFT below.
|
||
|
|
||
|
#define COLLISION_SHIFT 3 // log(PERFCHECKEPOCH) / log(2) - 3
|
||
|
|
||
|
static const INT maxCacheSize = 511;
|
||
|
|
||
|
SHORT GetFontNameIndex(const WCHAR *pFontName);
|
||
|
BYTE GetFontLegitimateSize(LONG iFont, BOOL fUIFont, int cpg);
|
||
|
BOOL SetFontLegitimateSize(LONG iFont, BOOL fUIFont, BYTE bSize, int cpg);
|
||
|
const WCHAR *GetFontName(LONG iFont);
|
||
|
UINT GetTextCharsetInfoPri(HDC hdc, FONTSIGNATURE* pcsi, DWORD dwFlags);
|
||
|
DWORD GetFontSignatureFromFace(int ifont, DWORD* pdwFontSig = NULL);
|
||
|
void FreeFontNames();
|
||
|
|
||
|
enum FONTINDEX
|
||
|
{
|
||
|
IFONT_ARIAL = 0,
|
||
|
IFONT_TMSNEWRMN = 1,
|
||
|
IFONT_SYMBOL = 2,
|
||
|
IFONT_SYSTEM = 3
|
||
|
};
|
||
|
|
||
|
typedef unsigned int CCSHASHKEY;
|
||
|
|
||
|
extern const WCHAR *szArial;
|
||
|
extern const WCHAR *szTimesNewRoman;
|
||
|
extern const WCHAR *szSymbol;
|
||
|
extern const WCHAR *szSystem;
|
||
|
extern const WCHAR *szWingdings;
|
||
|
|
||
|
//Not automatically added to font table
|
||
|
extern const WCHAR *szMicrosSansSerif;
|
||
|
extern const WCHAR *szMSSansSerif;
|
||
|
extern const WCHAR *szMangal;
|
||
|
extern const WCHAR *szLatha;
|
||
|
extern const WCHAR *szCordiaNew;
|
||
|
extern const WCHAR *szTahoma;
|
||
|
extern const WCHAR *szArialUnicode;
|
||
|
|
||
|
/*
|
||
|
* CWidthCache
|
||
|
*
|
||
|
* @class Lightweight Unicode width cache.
|
||
|
*
|
||
|
* @devnote Initial size is 52 bytes, 1st step is 100, and exponentially
|
||
|
* growing (currently) to 4660 bytes; NOTE, this can be reduced
|
||
|
* to 28, 60 and 3100 bytes if shorts are used and appropriate
|
||
|
* guarantees are placed on the range of width values.
|
||
|
*
|
||
|
* Owner: <nl>
|
||
|
* Jon Matousek (jonmat) <nl>
|
||
|
*/
|
||
|
class CWidthCache
|
||
|
{
|
||
|
//@access Private methods and data
|
||
|
private:
|
||
|
|
||
|
INT _cacheSize; //@cmember size is total cache slots - 1.
|
||
|
|
||
|
INT _cacheUsed; //@cmember for statistics, num slots in use.
|
||
|
INT _collisions; //@cmember for statistics, num fetches required.
|
||
|
INT _accesses; //@cmember for statistics, total num accesses.
|
||
|
BOOL _fMaxPerformance; //@cmember for statistics, TRUE if grown to max.
|
||
|
|
||
|
struct CacheEntry
|
||
|
{
|
||
|
WCHAR ch;
|
||
|
SHORT width;
|
||
|
};
|
||
|
|
||
|
SHORT _dxpHangul;
|
||
|
SHORT _dxpHan;
|
||
|
//@cmember default storage for widths.
|
||
|
CacheEntry _defaultWidthCache[DEFAULTCACHESIZE+1];
|
||
|
//@cmember pointers to storage for widths.
|
||
|
CacheEntry *(_pWidthCache);
|
||
|
|
||
|
inline BOOL FLookasideCharacter(WCHAR ch)
|
||
|
{
|
||
|
if (ch < 0x4E00)
|
||
|
return FALSE;
|
||
|
|
||
|
if (IN_RANGE(0x4E00, ch, 0x9FFF) || // CJK ideograph
|
||
|
IN_RANGE(0xF900, ch, 0xFAFF) || // CJK compatibility ideograph
|
||
|
IN_RANGE(0xAC00, ch, 0xD7FF)) // Hangul
|
||
|
return TRUE;
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
void FetchLookasideWidth(WCHAR ch, LONG &dxp)
|
||
|
{
|
||
|
BOOL fHangul = IN_RANGE(0xAC00, ch, 0xD7FF);
|
||
|
|
||
|
dxp = fHangul ? _dxpHangul : _dxpHan;
|
||
|
}
|
||
|
|
||
|
//@cmember Get location where width is stored.
|
||
|
inline CacheEntry * GetEntry( const WCHAR ch )
|
||
|
{ // logical & is really a MOD, as all of the bits
|
||
|
// of cacheSize are turned on; the value of cacheSize is
|
||
|
// required to be of the form 2^n-1.
|
||
|
return &_pWidthCache[ ch & _cacheSize ];
|
||
|
}
|
||
|
|
||
|
//@cmember See if cache is performing within spec.
|
||
|
void CheckPerformance();
|
||
|
//@cmember Increase width cache size.
|
||
|
BOOL GrowCache( CacheEntry **widthCache, INT *cacheSize, INT *cacheUsed);
|
||
|
|
||
|
//@access Public Methods
|
||
|
public:
|
||
|
//@cmember Called before GetWidth
|
||
|
BOOL CheckWidth (const WCHAR ch, LONG &dxp);
|
||
|
//@cmember Fetch width if CheckWidth ret FALSE.
|
||
|
BOOL FillWidth (
|
||
|
HDC hdc,
|
||
|
const WCHAR ch,
|
||
|
const SHORT xOverhang,
|
||
|
LONG &dxp,
|
||
|
UINT uiCodePage,
|
||
|
INT iDefWidth);
|
||
|
|
||
|
//@cmember Fetch char width.
|
||
|
INT GetWidth(const WCHAR ch);
|
||
|
|
||
|
void Free(); //@cmember Recycle width cache
|
||
|
|
||
|
CWidthCache(); //@cmember Construct width cache
|
||
|
~CWidthCache(); //@cmember Free dynamic mem
|
||
|
};
|
||
|
|
||
|
|
||
|
class CCcs
|
||
|
{
|
||
|
friend class CFontCache;
|
||
|
|
||
|
private:
|
||
|
CCSHASHKEY _ccshashkey; // Hash key
|
||
|
DWORD _dwAge; // for LRU algorithm
|
||
|
SHORT _iFont; // Index into FONTNAME table
|
||
|
SHORT _cRefs; // ref. count
|
||
|
|
||
|
class CWidthCache _widths;
|
||
|
|
||
|
public:
|
||
|
DWORD _dwFontSig; // Flags from low 32 bits of FONTSIGNATURE fsCsb member
|
||
|
|
||
|
HDC _hdc; // HDC font is selected into
|
||
|
HFONT _hfont; // Windows font handle
|
||
|
void* _sc; // A handle to the Uniscribe glyph width/font cmap information
|
||
|
|
||
|
//REVIEW (keithcu) We should make these into at least 24 bit or possibly 32 bit values,
|
||
|
//or at least use unsigned values so that we don't overflow as easily.
|
||
|
SHORT _yHeightRequest;// Font height requested (logical units)
|
||
|
SHORT _yHeight; // Total height of char cell (logical units)
|
||
|
SHORT _yDescent; // Distance from baseline to char cell bottom (logical units)
|
||
|
|
||
|
SHORT _xAveCharWidth; // Average character width in logical units
|
||
|
SHORT _xOverhangAdjust;// Overhang for synthesized fonts in logical units
|
||
|
SHORT _xOverhang; // Font overhang.
|
||
|
SHORT _xUnderhang; // Font underhang.
|
||
|
|
||
|
SHORT _dyULOffset; // Underline offset
|
||
|
SHORT _dyULWidth; // Underline width
|
||
|
SHORT _dySOOffset; // Strikeout offset
|
||
|
SHORT _dySOWidth; // Strikeout width
|
||
|
|
||
|
SHORT _yOffsetSuperscript; //Amount raised if superscipt (positive)
|
||
|
SHORT _yOffsetSubscript;//Amount lowered if subscript (negative)
|
||
|
|
||
|
USHORT _weight; // Font weight
|
||
|
USHORT _wCodePage; // Font code page
|
||
|
|
||
|
BYTE _bCharSetRequest; //Requested charset
|
||
|
BYTE _bCharSet; // Font CharSet
|
||
|
BYTE _bCMDefault; // Used in calculation of _bConvertMode
|
||
|
BYTE _bConvertMode; // CONVERTMODE: CVT_NONE, CVT_WCTMB, CVT_LOWBYTE
|
||
|
BYTE _bPitchAndFamily;// Font pitch and family
|
||
|
|
||
|
BYTE _fValid:1; // CCcs is valid
|
||
|
BYTE _fFixPitchFont:1;// Font has fixed character width
|
||
|
BYTE _fItalic:1; // Font is italic
|
||
|
BYTE _fFECharSet:1; // Font has FE charset
|
||
|
BYTE _fForceTrueType:1;// Font has been forced to be truetype
|
||
|
|
||
|
private:
|
||
|
|
||
|
BOOL Compare (const CCharFormat * const pCF, HDC hdc);
|
||
|
BOOL MakeFont(const CCharFormat * const pCF);
|
||
|
void DestroyFont();
|
||
|
BOOL GetMetrics(WCHAR *szNewFaceName = 0);
|
||
|
HFONT GetFontWithMetrics(LOGFONT *plf, WCHAR* szNewFaceName);
|
||
|
BOOL FillWidth(WCHAR ch, LONG &dxp);
|
||
|
|
||
|
public:
|
||
|
CCcs () {_fValid = FALSE;}
|
||
|
~CCcs () {if(_fValid) Free();}
|
||
|
|
||
|
void GetOffset(const CCharFormat * const pCF, LONG dypInch,
|
||
|
LONG *pyOffset, LONG *pyAdjust);
|
||
|
|
||
|
BOOL Init(const CCharFormat * const pCF);
|
||
|
void Free();
|
||
|
void AddRef() {_cRefs++;}
|
||
|
void Release() {if(_cRefs) _cRefs--;}
|
||
|
|
||
|
BOOL Include(WCHAR ch, LONG &dxp)
|
||
|
{
|
||
|
if(!_widths.CheckWidth(ch, dxp))
|
||
|
return FillWidth(ch, dxp);
|
||
|
return TRUE;
|
||
|
}
|
||
|
BYTE BestCharSet(BYTE bCharSet, BYTE bCharSetDefault, int fFontMatching);
|
||
|
|
||
|
SHORT AdjustFEHeight(BOOL fAjdust)
|
||
|
{
|
||
|
return ((fAjdust && _fFECharSet) ? MulDiv(_yHeight, 15, 100) : 0);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
// FONTINFO cache
|
||
|
|
||
|
typedef union
|
||
|
{
|
||
|
WORD wFlags;
|
||
|
struct
|
||
|
{
|
||
|
WORD fCached :1; // Font signature was already cached
|
||
|
WORD fBadFaceName :1; // Face is junk or doesnt exist in the system
|
||
|
WORD fTrueType :1; // Font is TrueType
|
||
|
WORD fBitmap :1; // Font is Bitmap
|
||
|
WORD fNonBiDiAscii :1; // Font is non-BiDi, single charset and support ASCII
|
||
|
WORD fScaleByCpg :1; // Scale the font based on given codepage
|
||
|
WORD fThaiDTP :1; // Thai DTP font
|
||
|
};
|
||
|
} FONTINFO_FLAGS;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
const WCHAR *szFontName;
|
||
|
DWORD dwFontSig; // font signature
|
||
|
BYTE bSizeUI; // UI font legitimate size (in point)
|
||
|
BYTE bSizeNonUI; // Non-UI font legitimate size
|
||
|
FONTINFO_FLAGS ff; // flags
|
||
|
} FONTINFO;
|
||
|
|
||
|
|
||
|
|
||
|
// ============================= CFontCache =====================================================
|
||
|
// CFontCache - maintains up to FONTCACHESIZE font caches
|
||
|
|
||
|
class CFontCache
|
||
|
{
|
||
|
friend class CCcs;
|
||
|
|
||
|
private:
|
||
|
CCcs _rgccs[FONTCACHESIZE];
|
||
|
DWORD _dwAgeNext;
|
||
|
struct {
|
||
|
CCSHASHKEY ccshashkey;
|
||
|
CCcs *pccs;
|
||
|
} quickHashSearch[CCSHASHSEARCHSIZE+1];
|
||
|
|
||
|
private:
|
||
|
CCcs* GrabInitNewCcs(const CCharFormat * const pCF, HDC hdc);
|
||
|
CCSHASHKEY MakeHashKey(const CCharFormat *pCF);
|
||
|
public:
|
||
|
void Init();
|
||
|
|
||
|
CCcs* GetCcs(const CCharFormat * const pCF, const LONG dypInch, HDC hdc = 0, BOOL fForceTrueType = 0);
|
||
|
FONTINFO_FLAGS GetInfoFlags(int ifont);
|
||
|
};
|
||
|
|
||
|
extern CFontCache & fc(); // font cache manager
|
||
|
|
||
|
#endif
|