mirror of
https://github.com/snowie2000/mactype.git
synced 2025-01-05 10:17:02 +08:00
702 lines
20 KiB
C++
702 lines
20 KiB
C++
#pragma once
|
||
|
||
#include <ft2build.h>
|
||
#include <freetype/freetype.h> /* FT_FREETYPE_H */
|
||
#include <freetype/ftcache.h> /* FT_CACHE_H */
|
||
#include <freetype/tttables.h>
|
||
#include <freetype/tttags.h> // FT_TRUETYPE_TAGS_H
|
||
#include <freetype/ftoutln.h>
|
||
#include <vector>
|
||
#include "ftref.h"
|
||
#include <math.h>
|
||
#include "undocAPI.h"
|
||
|
||
class FreeTypeFontEngine;
|
||
extern FreeTypeFontEngine* g_pFTEngine;
|
||
extern BOOL g_ccbCache;
|
||
extern BOOL g_ccbIndividual;
|
||
extern FTC_Manager cache_man;
|
||
|
||
typedef set<CBitmapCache*> CTLSDCArray;
|
||
extern CTLSDCArray TLSDCArray;
|
||
|
||
LOGFONTW* GetFontNameFromFile(LPCTSTR Filename);
|
||
bool GetFontLocalName(TCHAR* pszFontName, __out TCHAR* pszNameOut); //获得字体的本地化名称
|
||
|
||
struct CFontSetCache
|
||
{
|
||
const CFontSettings** fontsetlist;
|
||
int fontsetsize;
|
||
CFontSetCache()
|
||
:fontsetsize(0)
|
||
{
|
||
fontsetsize=64;
|
||
fontsetlist = (const CFontSettings**)malloc(fontsetsize * sizeof(void*));
|
||
}
|
||
~CFontSetCache()
|
||
{
|
||
free(fontsetlist);
|
||
}
|
||
void Set(FTC_FaceID faceid, const CFontSettings& fset)
|
||
{
|
||
while ((INT_PTR)faceid>=fontsetsize)
|
||
{
|
||
fontsetsize+=64;
|
||
fontsetlist = (const CFontSettings**)realloc(fontsetlist, fontsetsize);
|
||
}
|
||
fontsetlist[(INT_PTR)faceid]=&fset;
|
||
}
|
||
const CFontSettings*& Get(FTC_FaceID faceid) const
|
||
{
|
||
return fontsetlist[(INT_PTR)faceid];
|
||
}
|
||
};
|
||
|
||
struct myfont
|
||
{
|
||
wstring name;
|
||
int hash;
|
||
bool operator < (const myfont& mf) const {
|
||
return name==mf.name? hash<mf.hash: name<mf.name;
|
||
}
|
||
public:
|
||
myfont(LPCWSTR lpFaceName, int nweight, int nitalic):
|
||
name(lpFaceName),hash((nitalic<<31) | nweight)
|
||
{}
|
||
};
|
||
|
||
enum FT_EngineConstants {
|
||
FT_MAX_CHARS = 65536,
|
||
};
|
||
|
||
/*
|
||
FreeTypeに文字幅、太字、斜体をキャッシュする機構が無いのでそれらを補う
|
||
|
||
1. まずDllMain(DLL_PROCESS_ATTACH)でFreeTypeFontEngineのインスタンスが生成される。
|
||
(順番はCGdiPPSettings→FontLInit(FreeType)→FreeTypeFontEngine→フック)
|
||
ForceChangeFontもここで処理する。
|
||
|
||
2. CreateFontでFreeTypeFontEngine::AddFontが呼び出され、FreeTypeFontInfoと
|
||
フォント名を結びつける。
|
||
ついでにFreeTypeFontInfoはIndividualの設定をコピーして持つ。
|
||
|
||
3. ExtTextOutやGetTextExtentなどからFreeTypePrepare関数が呼び出されると
|
||
さらに内部でFreeTypeFontInfo::GetCacheが呼び出され、フォントサイズなどから
|
||
FreeTypeFontCacheを得る。無ければ生成する。
|
||
FreeTypeFontCacheは内部にFreeTypeCharDataのテーブル(UCS2なので2^16個)を
|
||
持っていて、FreeTypeCharDataには文字毎にキャッシュデータを保管する。
|
||
|
||
4. FreeTypeFontCacheから、文字またはグリフ番号を元にFreeTypeCharDataを得る。
|
||
キャッシュがあれば(メモリ中に残っていれば)、MRUカウンタをセットする。
|
||
無い場合は一旦スルーし、後でAddCharDataでキャッシュを追加する。
|
||
|
||
5. 追加しまくるとメモリを喰らうので、追加が一定数(FREETYPE_REQCOUNTMAX)を超えると
|
||
GCモドキで最近参照されたキャッシュデータをFREETYPE_GC_COUNTER個だけ残し、
|
||
それ以外のデータ(FreeTypeCharData)は開放される。
|
||
この2つの定数はiniで設定変更できた方がいいような気もする。
|
||
|
||
6. 最後に、DllMain(DLL_PROCESS_DETACH)でFreeTypeFontEngineのインスタンスが破棄され、
|
||
全てのキャッシュメモリが開放される。
|
||
|
||
*/
|
||
|
||
class FreeTypeGCCounter
|
||
{
|
||
private:
|
||
int m_addcount; //追加用
|
||
int m_mrucount; //MRU用
|
||
|
||
public:
|
||
FreeTypeGCCounter()
|
||
: m_addcount(0), m_mrucount(0)
|
||
{
|
||
}
|
||
int AddIncrement() { return ++m_addcount; }
|
||
int DecIncrement() { return --m_addcount; }
|
||
int MruIncrement() { return ++m_mrucount; }
|
||
|
||
void ResetGCCounter()
|
||
{
|
||
m_mrucount = 0;
|
||
m_addcount = 0;
|
||
}
|
||
};
|
||
|
||
class FreeTypeMruCounter
|
||
{
|
||
private:
|
||
int m_mrucounter; //GC用
|
||
|
||
public:
|
||
FreeTypeMruCounter(int n)
|
||
: m_mrucounter(n)
|
||
{
|
||
}
|
||
|
||
//GC用MRUカウンタ
|
||
int GetMruCounter() const { return m_mrucounter; }
|
||
void ResetMruCounter() { m_mrucounter = 0; }
|
||
void SetMruCounter(FreeTypeGCCounter* p) { m_mrucounter = p->MruIncrement(); }
|
||
};
|
||
|
||
//文字幅、(glyph index)、FT_BitmapGlyph(太字、斜体のみ)をキャッシュする
|
||
class FreeTypeCharData : public FreeTypeMruCounter
|
||
{
|
||
private:
|
||
typedef CValArray<FreeTypeCharData**> CharDataArray;
|
||
CharDataArray m_arrSelfChar; //自分自身の保存元(Char)
|
||
FreeTypeCharData** m_ppSelfGlyph; //(Glyph)
|
||
UINT m_glyphindex; //グリフ番号
|
||
int m_width; //文字幅
|
||
int m_gdiWidth; //使用GetCharWidth获得的GDI宽度
|
||
FT_Referenced_BitmapGlyph m_glyph; //カラー用
|
||
FT_Referenced_BitmapGlyph m_glyphMono; //モノクロ用
|
||
int m_bmpSize; //ビットマップサイズ
|
||
int m_bmpMonoSize; // 〃
|
||
int m_AAMode;
|
||
// LONG m_refcounter; //参照カウンタ
|
||
|
||
#ifdef _DEBUG
|
||
WCHAR m_wch; //UCS2文字
|
||
#endif
|
||
NOCOPY(FreeTypeCharData);
|
||
|
||
//FT_Bitmap::bufferのサイズを返す
|
||
static inline int FT_Bitmap_CalcSize(FT_BitmapGlyph gl)
|
||
{
|
||
return gl->bitmap.pitch * gl->bitmap.rows;
|
||
}
|
||
|
||
public:
|
||
FreeTypeCharData(FreeTypeCharData** ppCh, FreeTypeCharData** ppGl, WCHAR wch, UINT glyphindex, int width, int mru, int gdiWidth, int AAMode);
|
||
~FreeTypeCharData();
|
||
|
||
#ifdef _DEBUG
|
||
WCHAR GetChar() const { return m_wch; }
|
||
#else
|
||
WCHAR GetChar() const { return L'?'; }
|
||
#endif
|
||
UINT GetGlyphIndex() const { return m_glyphindex; }
|
||
int GetWidth() const { return m_width; }
|
||
void SetWidth(int width) { m_width = width; }
|
||
void SetGDIWidth(int width) { m_gdiWidth = width; }
|
||
int GetGDIWidth() const {return m_gdiWidth; }
|
||
int GetAAMode() const {return m_AAMode; }
|
||
void AddChar(FreeTypeCharData** ppCh)
|
||
{
|
||
if (ppCh)
|
||
m_arrSelfChar.Add(ppCh);
|
||
}
|
||
FT_Referenced_BitmapGlyph GetGlyph(FT_Render_Mode render_mode) const
|
||
{
|
||
return (render_mode == FT_RENDER_MODE_MONO) ? m_glyphMono : m_glyph;
|
||
}
|
||
void SetGlyph(FT_Render_Mode render_mode, FT_Referenced_BitmapGlyph glyph);
|
||
|
||
void Erase()
|
||
{
|
||
//delete this;
|
||
}
|
||
};
|
||
static INT_PTR NULL_INT = NULL;
|
||
class FreeTypeFontCache : public FreeTypeMruCounter, public FreeTypeGCCounter
|
||
{
|
||
typedef map<int, FreeTypeCharData*> GlyphCache;
|
||
|
||
private:
|
||
int m_px;
|
||
int m_weight;
|
||
bool m_italic;
|
||
bool m_active;
|
||
TEXTMETRIC m_tm;
|
||
|
||
//4×65536×2=512KBぐらいたかが知れてるので固定配列で問題無し
|
||
#ifdef _USE_ARRAY
|
||
FreeTypeCharData* m_chars[FT_MAX_CHARS];
|
||
FreeTypeCharData* m_glyphs[FT_MAX_CHARS];
|
||
#else
|
||
GlyphCache m_GlyphCache;
|
||
#endif
|
||
NOCOPY(FreeTypeFontCache);
|
||
void Compact();
|
||
|
||
FreeTypeCharData** _GetChar(WCHAR wch)
|
||
{
|
||
#ifdef _USE_ARRAY
|
||
return m_chars + wch;
|
||
#else
|
||
GlyphCache::iterator it=m_GlyphCache.find(wch);
|
||
return it==m_GlyphCache.end()? reinterpret_cast<FreeTypeCharData**>(&NULL_INT): &(it->second);
|
||
#endif
|
||
}
|
||
FreeTypeCharData** _GetGlyph(UINT glyph)
|
||
{
|
||
#ifdef _USE_ARRAY
|
||
return m_glyphs + glyph;
|
||
#else
|
||
GlyphCache::iterator it=m_GlyphCache.find(-(int)glyph);
|
||
return it == m_GlyphCache.end() ? reinterpret_cast<FreeTypeCharData**>(&NULL_INT) : &(it->second);
|
||
#endif
|
||
}
|
||
|
||
public:
|
||
FreeTypeFontCache(/*int px, int weight, bool italic, */int mru);
|
||
~FreeTypeFontCache();
|
||
|
||
const TEXTMETRIC& GetTextMetric(HDC hdc)
|
||
{
|
||
if (m_tm.tmHeight == 0) {
|
||
::GetTextMetrics(hdc, &m_tm);
|
||
}
|
||
return m_tm;
|
||
}
|
||
|
||
bool Equals(int px, int weight, bool italic) const
|
||
{
|
||
return (m_px == px && m_weight == weight && m_italic == italic);
|
||
}
|
||
FreeTypeCharData* FindChar(WCHAR wch)
|
||
{
|
||
/*if (!g_ccbCache) return NULL;*/
|
||
FreeTypeCharData* p = *_GetChar(wch);
|
||
if(p) {
|
||
p->SetMruCounter(this);
|
||
}
|
||
return p;
|
||
}
|
||
|
||
FreeTypeCharData* FindGlyphIndex(UINT glyph)
|
||
{
|
||
/*if (!g_ccbCache) return NULL;*/
|
||
FreeTypeCharData* p = (glyph & 0xffff0000) ? NULL : *_GetGlyph(glyph);
|
||
if(p) {
|
||
p->SetMruCounter(this);
|
||
}
|
||
return p;
|
||
}
|
||
|
||
bool Activate()
|
||
{
|
||
if (!m_active) {
|
||
m_active = true;
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
void Erase();
|
||
void Deactive() { m_active = false; };
|
||
void AddCharData(WCHAR wch, UINT glyphindex, int width, int gdiWidth, FT_Referenced_BitmapGlyph glyph, FT_Render_Mode render_mode, int AAMode);
|
||
void AddGlyphData(UINT glyphindex, int width, int gdiWidth, FT_Referenced_BitmapGlyph glyph, FT_Render_Mode render_mode, int AAMode);
|
||
};
|
||
|
||
|
||
// フォント名とFaceID(intを使うことにする)
|
||
//extern CFontSetCache g_fsetcache;
|
||
extern CHashedStringList FontNameCache;
|
||
class FreeTypeFontInfo : public FreeTypeMruCounter, public FreeTypeGCCounter
|
||
{
|
||
private:
|
||
INT_PTR m_id;
|
||
int m_weight;
|
||
bool m_italic;
|
||
char m_hashinting;
|
||
int m_ftWeight;
|
||
int m_os2Weight;
|
||
int m_nMaxSizes;
|
||
int m_nFontFamily;
|
||
HFONT m_ggoFont;
|
||
TT_OS2* m_OS2Table;
|
||
char m_ebmps[256];
|
||
LONG volatile count;
|
||
CFontSettings m_set;
|
||
StringHashFont m_hash;
|
||
wstring m_fullname, m_familyname;
|
||
typedef map<UINT, FreeTypeFontCache*> CacheArray;
|
||
CacheArray m_cache;
|
||
//快速链接
|
||
FTC_FaceID face_id_link[CFontLinkInfo::FONTMAX * 2 + 1];
|
||
HFONT ggo_link[CFontLinkInfo::FONTMAX * 2 + 1];
|
||
bool m_linkinited;
|
||
int m_linknum;
|
||
FTC_FaceID m_SimSunID;
|
||
NOCOPY(FreeTypeFontInfo);
|
||
void Compact();
|
||
void Createlink();
|
||
|
||
public:
|
||
void AddRef() {InterlockedIncrement(&count);};
|
||
void Release() {
|
||
if (InterlockedDecrement(&count)==0)
|
||
delete this;
|
||
}
|
||
TT_OS2* GetOS2Table()
|
||
{
|
||
if (!m_OS2Table)
|
||
{
|
||
TT_OS2 * os2_table = NULL;
|
||
FT_Face freetype_face;
|
||
CCriticalSectionLock __lock(CCriticalSectionLock::CS_MANAGER);
|
||
if (FTC_Manager_LookupFace(cache_man, (FTC_FaceID)m_id, &freetype_face))
|
||
return NULL;
|
||
os2_table = (TT_OS2*) FT_Get_Sfnt_Table(freetype_face, ft_sfnt_os2);
|
||
if (!os2_table) return NULL;
|
||
m_OS2Table = new TT_OS2;
|
||
memcpy(m_OS2Table, os2_table, sizeof(TT_OS2));
|
||
}
|
||
return m_OS2Table;
|
||
}
|
||
BOOL FontHasHinting()
|
||
{
|
||
if (m_hashinting==3)
|
||
{
|
||
FT_Face freetype_face;
|
||
CCriticalSectionLock __lock(CCriticalSectionLock::CS_MANAGER);
|
||
if (FTC_Manager_LookupFace(cache_man, (FTC_FaceID)m_id, &freetype_face)) //查询ft face
|
||
{
|
||
m_hashinting = false;
|
||
return NULL;
|
||
}
|
||
FT_ULong length = 0;
|
||
FT_Error err = FT_Load_Sfnt_Table(freetype_face, TTAG_fpgm, 0, NULL, &length); //获取fpgm表长度
|
||
if (!err && length>50) //成功读取表,并且长度较长
|
||
m_hashinting = true; //字体存在hinting
|
||
else
|
||
m_hashinting = false;
|
||
}
|
||
return m_hashinting;
|
||
}
|
||
wstring GetFullName() {return m_fullname;};
|
||
bool m_isSimSun;
|
||
bool IsPixel;
|
||
UINT getCacheHash(int px, int weight, bool italic, int width) {return ((px<<20)|(width<<8)|(weight<<1)|(int)italic); }; //计算一个hash值来定位cache
|
||
FreeTypeFontInfo(int n, LPCTSTR name, int weight, bool italic, int mru, wstring fullname, wstring familyname)
|
||
: m_id(n), m_weight(weight), m_italic(italic), m_OS2Table(NULL), IsPixel(false)
|
||
, FreeTypeMruCounter(mru), m_isSimSun(false), m_ggoFont(NULL), m_linkinited(false), m_linknum(0), m_os2Weight(0)
|
||
, m_SimSunID(0), count(1), m_fullname(fullname), m_familyname(familyname), m_hashinting(3), m_nFontFamily(0)
|
||
{
|
||
//m_set = set;
|
||
memset(m_ebmps, 0xff, sizeof(m_ebmps));
|
||
|
||
enum { FTC_MAX_SIZES_DEFAULT = 4 };
|
||
const CGdippSettings* pSettings = CGdippSettings::GetInstance();
|
||
m_nMaxSizes = pSettings->CacheMaxSizes();
|
||
if (!m_nMaxSizes)
|
||
m_nMaxSizes = FTC_MAX_SIZES_DEFAULT;
|
||
//extern BOOL g_EngineCreateFont;
|
||
if (pSettings->FontSubstitutes() < SETTING_FONTSUBSTITUTE_ALL)
|
||
m_ggoFont = CreateFont(10,0,0,0,weight,italic,0,0,DEFAULT_CHARSET,0,FONT_MAGIC_NUMBER,0,0,name);
|
||
//use magic number to create unsubstitud font
|
||
else
|
||
m_ggoFont = CreateFont(10,0,0,0,weight,italic,0,0,DEFAULT_CHARSET,0,0,0,0,name);
|
||
HDC hdc = CreateCompatibleDC(NULL);
|
||
HFONT old = SelectFont(hdc, m_ggoFont);
|
||
//获得字体的全称
|
||
|
||
int nSize=GetOutlineTextMetrics(hdc, 0, NULL);
|
||
if (nSize==0)
|
||
m_fullname = L"";
|
||
else
|
||
//if (m_fullname.size()==0) //构造函数中不提供,自己获取
|
||
{
|
||
LPOUTLINETEXTMETRIC otm = (LPOUTLINETEXTMETRIC)malloc(nSize);
|
||
memset(otm, 0, nSize);
|
||
otm->otmSize = nSize;
|
||
GetOutlineTextMetrics(hdc, nSize, otm);
|
||
m_fullname = (wstring)(LPWSTR)((DWORD_PTR)otm + (DWORD_PTR)otm->otmpFullName);
|
||
TCHAR * localname = (LPWSTR)((DWORD_PTR)otm+(DWORD_PTR)otm->otmpFamilyName);
|
||
wstring styleName = (wstring)(LPWSTR)((DWORD_PTR)otm + (DWORD_PTR)otm->otmpStyleName);
|
||
m_fullname = MakeUniqueFontName(m_fullname, localname, styleName);
|
||
|
||
TCHAR buff[LF_FACESIZE+1];
|
||
GetFontLocalName(localname, buff);
|
||
m_nFontFamily = otm->otmTextMetrics.tmPitchAndFamily & 0xF0; //获取字体家族,家族对应使用什么默认链接字体
|
||
m_familyname = (wstring)buff;
|
||
m_set = pSettings->FindIndividual(m_familyname.c_str());
|
||
m_ftWeight = CalcBoldWeight(/*weight*/700);
|
||
m_hash = StringHashFont(name);
|
||
if (m_familyname.size()>0 && m_familyname.c_str()[0]==L'@') //附加一个@
|
||
m_fullname = L'@'+m_fullname;
|
||
free(otm);
|
||
}
|
||
SelectFont(hdc, old);
|
||
DeleteDC(hdc);
|
||
|
||
//完成
|
||
// g_EngineCreateFont = false;
|
||
face_id_link[0]=(FTC_FaceID)NULL;
|
||
ggo_link[0] = NULL;
|
||
//g_fsetcache.Set((FTC_FaceID)n, set);
|
||
}
|
||
~FreeTypeFontInfo()
|
||
{
|
||
Erase();
|
||
DeleteFont(m_ggoFont);
|
||
if (m_OS2Table)
|
||
delete m_OS2Table;
|
||
}
|
||
|
||
HFONT GetGGOFont(){return m_ggoFont;};
|
||
int CalcNormalWeight() const
|
||
{
|
||
return m_set.GetNormalWeight();
|
||
}
|
||
int CalcBoldWeight(int weight) const
|
||
{
|
||
// return weight - FW_NORMAL) / 8;
|
||
// return ((weight - FW_NORMAL) / 12) + (m_set.GetBoldWeight() << 2);
|
||
weight = weight < FW_BOLD ? 0: /*(weight > FW_BOLD ?*/ 612;
|
||
if (weight <= FW_NORMAL) {
|
||
return 0;
|
||
}
|
||
return ((weight - FW_NORMAL) / 8) + (m_set.GetBoldWeight() << 2);
|
||
}
|
||
int CalcBoldWeight(const LOGFONT& lf) const
|
||
{
|
||
return CalcBoldWeight(lf.lfWeight);
|
||
}
|
||
void CalcItalicSlant(FT_Matrix& matrix) const
|
||
{
|
||
matrix.xx = 1 << 16;
|
||
// matrix.xy = 0x5800;
|
||
matrix.xy = (5 + m_set.GetItalicSlant()) << 12;
|
||
matrix.yx = 0;
|
||
matrix.yy = 1 << 16;
|
||
}
|
||
|
||
bool Equals(const StringHashFont& hash, int weight, bool italic) const
|
||
{
|
||
weight = CalcBoldWeight(weight);
|
||
return (m_ftWeight == weight && m_italic == italic && m_hash == hash);
|
||
}
|
||
void UpdateFontSetting()
|
||
{
|
||
m_ftWeight = CalcBoldWeight(700/*m_weight*/);
|
||
//清除字体链接
|
||
face_id_link[0]=NULL;
|
||
ggo_link[0]=NULL;
|
||
m_linknum = 0;
|
||
m_linkinited = false;
|
||
m_SimSunID = 0;
|
||
}
|
||
int GetFTLink(FTC_FaceID** llplink)
|
||
{
|
||
CCriticalSectionLock __lock(CCriticalSectionLock::CS_FONTLINK);
|
||
if (!*face_id_link)
|
||
Createlink();
|
||
*llplink = face_id_link;
|
||
return m_linknum;
|
||
}
|
||
int GetGGOLink(HFONT** llplink)
|
||
{
|
||
CCriticalSectionLock __lock(CCriticalSectionLock::CS_FONTLINK);
|
||
if (!*ggo_link)
|
||
Createlink();
|
||
*llplink = ggo_link;
|
||
return m_linknum;
|
||
}
|
||
FTC_FaceID GetSimSunID() {return m_SimSunID;}
|
||
|
||
INT_PTR GetId() const { return m_id; }
|
||
LPCTSTR GetName() const { return m_hash.c_str(); }
|
||
int GetFontWeight() const { return m_weight; }
|
||
int GetExactBoldWeight() const {return m_set.GetBoldWeight(); }
|
||
int GetFTWeight() const { return m_ftWeight; }
|
||
bool IsItalic() const { return m_italic; }
|
||
const StringHashFont& GetHash() const { return m_hash; }
|
||
|
||
const CFontSettings& GetFontSettings() const { return m_set; }
|
||
void SetFontSettings(const CFontSettings& set) { m_set = set;};
|
||
bool operator ==(const FreeTypeFontInfo& x) const { return (m_hash == x.m_hash); }
|
||
|
||
FreeTypeFontCache* GetCache(FTC_ScalerRec& scaler, const LOGFONT& lf);
|
||
bool EmbeddedBmpExist(int px);
|
||
void Erase()
|
||
{
|
||
CCriticalSectionLock __lock(CCriticalSectionLock::CS_FONTCACHE);
|
||
CacheArray::iterator it = m_cache.begin();
|
||
for (;it!=m_cache.end();++it)
|
||
{
|
||
delete it->second;
|
||
}
|
||
m_cache.clear();
|
||
}
|
||
};
|
||
|
||
class FreeTypeFontEngine : public FreeTypeGCCounter
|
||
{
|
||
private:
|
||
//typedef CArray<FreeTypeFontInfo*> FontListArray;
|
||
typedef map<myfont, FreeTypeFontInfo*> FontMap;
|
||
typedef map<wstring, FreeTypeFontInfo*> FullNameMap;
|
||
typedef vector<FreeTypeFontInfo*> FontList;
|
||
//FontListArray m_arrFontList;
|
||
int m_nMaxFaces;
|
||
int m_nMemUsed;
|
||
bool m_bAddOnFind;
|
||
FontMap m_mfontMap;
|
||
FullNameMap m_mfullMap;
|
||
FontList m_mfontList;
|
||
FT_Face* m_arrFace;
|
||
int m_nFaceCount;
|
||
void Compact();
|
||
int GrowFace()
|
||
{
|
||
FT_Face* a=(FT_Face*)malloc(m_nFaceCount*sizeof(FT_Face));
|
||
memcpy(a, m_arrFace, sizeof(FT_Face)*m_nFaceCount);
|
||
m_nFaceCount+=64;
|
||
m_arrFace = (FT_Face*)realloc(m_arrFace, sizeof(FT_Face) * m_nFaceCount);
|
||
memset(m_arrFace+m_nFaceCount-64, 0, sizeof(FT_Face)*64);
|
||
for (int i=0;i<m_nFaceCount-64;i++)
|
||
Assert(a[i]==m_arrFace[i]);
|
||
free(a);
|
||
return m_nFaceCount;
|
||
}
|
||
|
||
public:
|
||
FreeTypeFontEngine()
|
||
: m_nMemUsed(0), m_nMaxFaces(0), m_bAddOnFind(false), m_nFaceCount(64)
|
||
{
|
||
enum { FTC_MAX_FACES_DEFAULT = 2 };
|
||
const CGdippSettings* pSettings = CGdippSettings::GetInstanceNoInit();
|
||
m_nMaxFaces = pSettings->CacheMaxFaces();
|
||
if (m_nMaxFaces == 0)
|
||
m_nMaxFaces = FTC_MAX_FACES_DEFAULT;
|
||
//m_arrFace = (FT_Face*)malloc(m_nFaceCount*sizeof(FT_Face));
|
||
//memset(m_arrFace, 0, sizeof(FT_Face)*m_nFaceCount);
|
||
}
|
||
~FreeTypeFontEngine()
|
||
{
|
||
TRACE(_T("MaxFaces: %d\n"), m_mfontMap.size());
|
||
TRACE(_T("MemUsed : %d\n"), m_nMemUsed);
|
||
//FontListArray& arr = m_arrFontList;
|
||
FullNameMap::const_iterator iter=m_mfullMap.begin();
|
||
for (;iter!=m_mfullMap.end();++iter)
|
||
iter->second->Release();
|
||
//free(m_arrFace);
|
||
}
|
||
int CalcBoldWeight(int weight) const
|
||
{
|
||
return weight < FW_BOLD ? 0: FW_BOLD;
|
||
}
|
||
FreeTypeFontInfo* AddFont(LPCTSTR lpFaceName, int weight, bool italic, BOOL* bIsFontLoaded = NULL);
|
||
FreeTypeFontInfo* AddFont(void* lpparams);
|
||
int GetFontIdByName(LPCTSTR lpFaceName, int weight, bool italic);
|
||
// LPCTSTR GetFontById(int faceid, int& weight, bool& italic);
|
||
FreeTypeFontInfo* FindFont(LPCTSTR lpFaceName, int weight, bool italic, bool AddOnFind = true, BOOL* bIsFontLoaded=NULL);
|
||
FreeTypeFontInfo* FindFont(int faceid);
|
||
FreeTypeFontInfo* FindFont(void* lpparams);
|
||
|
||
bool FontExists(LPCTSTR lpFaceName, int weight, bool italic)
|
||
{
|
||
return !!FindFont(lpFaceName, weight, italic);
|
||
}
|
||
BOOL RemoveFont(LPCWSTR FontName);
|
||
BOOL RemoveFont(FreeTypeFontInfo* fontinfo);
|
||
BOOL RemoveThisFont(FreeTypeFontInfo* fontinfo, LOGFONT* lg);
|
||
//メモリ使用量カウンタ
|
||
void AddMemUsed(int x)
|
||
{
|
||
m_nMemUsed += x;
|
||
}
|
||
void SubMemUsed(int x)
|
||
{
|
||
m_nMemUsed -= x;
|
||
if (m_nMemUsed < 0)
|
||
m_nMemUsed = 0;
|
||
}
|
||
template <class T>
|
||
void AddMemUsedObj(T* /*p*/)
|
||
{
|
||
AddMemUsed(sizeof(T));
|
||
}
|
||
template <class T>
|
||
void SubMemUsedObj(T* /*p*/)
|
||
{
|
||
SubMemUsed(sizeof(T));
|
||
}
|
||
void ReloadAll()
|
||
{
|
||
//重新载入全部字体,即清空所有字体缓存
|
||
COwnedCriticalSectionLock __olock(2);
|
||
CCriticalSectionLock __lock;
|
||
CGdippSettings* pSettings = CGdippSettings::GetInstance();
|
||
|
||
FullNameMap::const_iterator iter=m_mfullMap.begin();
|
||
for (;iter!=m_mfullMap.end();)
|
||
{
|
||
FreeTypeFontInfo* p =iter->second;
|
||
if (p)
|
||
{
|
||
/*
|
||
if (p->GetFullName()!=iter->first) //是替换字体
|
||
{
|
||
p->Release(); //释放掉多重引用
|
||
m_mfullMap.erase(iter++);
|
||
continue;
|
||
}*/
|
||
|
||
p->Erase();
|
||
p->SetFontSettings(pSettings->FindIndividual(p->GetName()));
|
||
p->UpdateFontSetting();
|
||
}
|
||
++iter;
|
||
}
|
||
//m_mfontMap.clear();
|
||
}
|
||
};
|
||
|
||
//GetFontDataのメモリストリーム
|
||
class FreeTypeSysFontData
|
||
{
|
||
private:
|
||
HDC m_hdc;
|
||
HFONT m_hOldFont;
|
||
bool m_isTTC;
|
||
bool m_locked;
|
||
void* m_pMapping;
|
||
DWORD m_dwSize;
|
||
FT_Face m_ftFace;
|
||
wstring m_name;
|
||
FT_StreamRec m_ftStream;
|
||
|
||
FreeTypeSysFontData()
|
||
: m_hdc(NULL)
|
||
, m_hOldFont(NULL)
|
||
, m_isTTC(false)
|
||
, m_locked(false)
|
||
, m_pMapping(NULL)
|
||
, m_dwSize(0)
|
||
, m_ftFace(NULL)
|
||
{
|
||
ZeroMemory(&m_ftStream, sizeof(FT_StreamRec));
|
||
}
|
||
|
||
static unsigned long IoFunc(FT_Stream stream, unsigned long offset, unsigned char* buffer, unsigned long count);
|
||
static void CloseFunc(FT_Stream stream);
|
||
bool OpenFaceByIndex(int index);
|
||
bool Init(LPCTSTR name, int weight, bool italic);
|
||
|
||
public:
|
||
static FreeTypeSysFontData* CreateInstance(LPCTSTR name, int weight, bool italic);
|
||
~FreeTypeSysFontData()
|
||
{
|
||
if (m_pMapping) {
|
||
UnmapViewOfFile(m_pMapping);
|
||
}
|
||
if (m_hOldFont) {
|
||
DeleteFont(SelectFont(m_hdc, m_hOldFont));
|
||
}
|
||
if (m_hdc) {
|
||
DeleteDC(m_hdc);
|
||
}
|
||
}
|
||
|
||
FT_Face GetFace()
|
||
{
|
||
FT_Face face = m_ftFace;
|
||
m_ftFace = NULL;
|
||
return face;
|
||
}
|
||
};
|