加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
fteng.cpp 27.74 KB
一键复制 编辑 原始数据 按行查看 历史
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
#include "override.h"
#include "ft.h"
#include <windows.h>
#include <tchar.h>
#include "fteng.h"
#ifdef _DLL
#pragma comment(linker, "/nod:msvcprt.lib /nod:msvcprtd.lib")
#endif
#if 0
#define FREETYPE_REQCOUNTMAX 10
#define GC_TRACE TRACE
#define FREETYPE_GC_COUNTER 128
#else
#define FREETYPE_REQCOUNTMAX 2048//トャネマ4096,テソサコエ貂テハチソオトホトラヨスォヒ「ミツサコエ貎オオヘトレエ贏シモテ
#define GC_TRACE NOP_FUNCTION
#define FREETYPE_GC_COUNTER 1024//ヒ「ミツサコエ貅」チトラヨハチソ
#endif
FreeTypeFontEngine* g_pFTEngine;
FT_Library freetype_library;
FTC_Manager cache_man;
FTC_CMapCache cmap_cache;
FTC_ImageCache image_cache;
CTLSDCArray TLSDCArray;
int CALLBACK EnumFontCallBack(const LOGFONT *lplf, const TEXTMETRIC *lptm, DWORD /*FontType*/, LPARAM lParam)
{
LOGFONT * lf=(LOGFONT *)lParam;
StringCchCopy(lf->lfFaceName, LF_FACESIZE, lplf->lfFaceName);
lf->lfQuality=0x2d; //magic number
return 0;
}
bool GetFontLocalName(TCHAR* pszFontName, __out TCHAR* pszNameOut) //サテラヨフ蠏トアセオリサッテニ,キオサリヨオホェラヨフ衞ヌキ贇レ
{
LOGFONT lf = {0};
TCHAR* ret;
lf.lfQuality = 0x2d;
if (!(ret = FontNameCache.Find((TCHAR*)pszFontName)))
{
StringCchCopy(lf.lfFaceName, LF_FACESIZE, pszFontName);
lf.lfCharSet=DEFAULT_CHARSET;
HDC dc=GetDC(NULL);
lf.lfQuality=0;
EnumFontFamiliesEx(dc, &lf, &EnumFontCallBack, (LPARAM)&lf, 0);
ReleaseDC(NULL, dc);
if (lf.lfQuality==0x2d)
FontNameCache.Add((TCHAR*)pszFontName, lf.lfFaceName);
ret=lf.lfFaceName;
}
StringCchCopy(pszNameOut, LF_FACESIZE, ret);
return lf.lfQuality == 0x2d;
}
LOGFONTW* GetFontNameFromFile(LPCWSTR Filename) //サテメサクヨフ衾トシトレーャオトヒミラヨフ蠹ニs
{
LOGFONTW* logfonts = NULL;
DWORD bufsize=0;
if (GetFontResourceInfo(Filename, &bufsize, NULL, 2))
{
logfonts = (LOGFONTW*)malloc(bufsize+1);
if (GetFontResourceInfo(Filename, &bufsize, logfonts, 2))
{
((char*)logfonts)[bufsize]=0;
return logfonts;
}
else
{
free(logfonts);
return NULL;
}
}
else
{
AddFontResourceW(Filename);
if (GetFontResourceInfo(Filename, &bufsize, NULL, 2))
{
logfonts = (LOGFONTW*)malloc(bufsize+1);
if (GetFontResourceInfo(Filename, &bufsize, logfonts, 2))
{
((char*)logfonts)[bufsize]=0;
ORIG_RemoveFontResourceExW(Filename,0,NULL);
return logfonts;
}
else
{
free(logfonts);
ORIG_RemoveFontResourceExW(Filename,0,NULL);
return NULL;
}
}
ORIG_RemoveFontResourceExW(Filename,0,NULL);
return NULL;
}
}
template <class T>
struct GCCounterSortFunc : public std::binary_function<const T*, const T*, bool>
{
bool operator()(const T* arg1, const T* arg2) const
{
const int cnt1 = arg1 ? arg1->GetMruCounter() : -1;
const int cnt2 = arg2 ? arg2->GetMruCounter() : -1;
return cnt1 > cnt2;
}
};
struct DeleteCharFunc : public std::unary_function<FreeTypeCharData*&, void>
{
void operator()(FreeTypeCharData*& arg) const
{
if (!arg)
return;
delete arg;
arg = NULL;
}
};
template <class T>
void CompactMap(T& pp, int count, int reduce)
{
CCriticalSectionLock __lock(CCriticalSectionLock::CS_FONTCACHE);
int reducecount = pp.size() - reduce;
T::iterator it= pp.begin();
for (int i=0;i<reducecount;i++) //ノセウウャケFREETYPE_GC_COUNTERヨョコトサコエ
{
//it->second->Erase();
delete it->second;
pp.erase(it++);
}
return;
}
template <class T>
void Compact(T** pp, int count, int reduce)
{
Assert(count >= 0);
Assert(reduce > 0);
if (!pp || !count || count < reduce) {
return;
}
CCriticalSectionLock __lock(CCriticalSectionLock::CS_FONTCACHE);
TRACE(_T("Compact(0x%p, %d, %d)\n"), pp, count, reduce);
//GCモドキ
//T::m_mrucounterの降順に並ぶので
//reduceを超える部分を削除する
T** ppTemp = (T**)malloc(sizeof(T*) * count);
if (!ppTemp) {
return;
}
memcpy(ppTemp, pp, sizeof(T*) * count);
std::sort(ppTemp, ppTemp + count, GCCounterSortFunc<T>());
int i;
for (i=0; i<reduce; i++) {
if (!ppTemp[i])
break;
ppTemp[i]->ResetMruCounter();
}
//GC_TRACE(_T("GC:"));
for (i=reduce; i<count; i++) {
if (!ppTemp[i])
break;
//GC_TRACE(_T(" %wc"), ppTemp[i]->GetChar());
ppTemp[i]->Erase();
}
//GC_TRACE(_T("\n"));
free(ppTemp);
}
//FreeTypeCharData
FreeTypeCharData::FreeTypeCharData(FreeTypeCharData** ppCh, FreeTypeCharData** ppGl, WCHAR wch, UINT glyphindex, int width, int mru, int gdiWidth, int AAMode)
: m_ppSelfGlyph(ppGl), m_glyphindex(glyphindex), m_width(width)
, m_glyph(NULL), m_glyphMono(NULL), m_bmpSize(0), m_bmpMonoSize(0)
, FreeTypeMruCounter(mru), m_gdiWidth(gdiWidth), m_AAMode(AAMode)
{
g_pFTEngine->AddMemUsedObj(this);
AddChar(ppCh);
#ifdef _DEBUG
m_wch = wch;
#endif
}
FreeTypeCharData::~FreeTypeCharData()
{
CharDataArray& arr = m_arrSelfChar;
int n = arr.GetSize();
while (n--) {
FreeTypeCharData** pp = arr[n];
Assert(*pp == this);
*pp = NULL;
}
if(m_ppSelfGlyph) {
Assert(*m_ppSelfGlyph == this);
*m_ppSelfGlyph = NULL;
}
if(m_glyph){
FT_Done_Ref_Glyph((FT_Referenced_Glyph*)&m_glyph);
}
if(m_glyphMono){
FT_Done_Ref_Glyph((FT_Referenced_Glyph*)&m_glyphMono);
}
g_pFTEngine->SubMemUsed(m_bmpSize);
g_pFTEngine->SubMemUsed(m_bmpMonoSize);
g_pFTEngine->SubMemUsedObj(this);
}
void FreeTypeCharData::SetGlyph(FT_Render_Mode render_mode, FT_Referenced_BitmapGlyph glyph)
{
const bool bMono = (render_mode == FT_RENDER_MODE_MONO);
FT_Referenced_BitmapGlyph& gl = bMono ? m_glyphMono : m_glyph;
if (gl)
FT_Done_Ref_Glyph((FT_Referenced_Glyph*)&gl);
{
FT_Glyph_Ref_Copy((FT_Referenced_Glyph)glyph, (FT_Referenced_Glyph*)&gl);
if (gl) {
int& size = bMono ? m_bmpMonoSize : m_bmpSize;
size = FT_Bitmap_CalcSize(gl->ft_glyph);
size += sizeof(FT_BitmapGlyphRec);
g_pFTEngine->AddMemUsed(size);
}
}
}
//FreeTypeFontCache
FreeTypeFontCache::FreeTypeFontCache(/*int px, int weight, bool italic, */int mru)
: /*m_px(px), m_weight(weight), m_italic(italic), */m_active(false)
, FreeTypeMruCounter(mru)
{
#ifdef _USE_ARRAY
ZeroMemory(&m_tm, sizeof(TEXTMETRIC));
ZeroMemory(m_chars, sizeof(m_chars));
ZeroMemory(m_glyphs, sizeof(m_glyphs));
#else
m_GlyphCache.clear();
#endif
g_pFTEngine->AddMemUsedObj(this);
}
FreeTypeFontCache::~FreeTypeFontCache()
{
Erase();
g_pFTEngine->SubMemUsedObj(this);
}
void FreeTypeFontCache::Compact()
{
//TRACE(_T("FreeTypeFontCache::Compact: %d > %d\n"), countof(m_chars), FREETYPE_GC_COUNTER);
ResetGCCounter();
#ifdef _USE_ARRAY
::Compact(m_glyphs, countof(m_glyphs), FREETYPE_GC_COUNTER);
#else
::CompactMap(m_GlyphCache, m_GlyphCache.size(), FREETYPE_GC_COUNTER);
#endif
//GlyphCache::const_iterator it=m_GlyphCache.begin();
}
void FreeTypeFontCache::Erase()
{
m_active = false;
#ifdef _USE_ARRAY
std::for_each(m_chars, m_chars + FT_MAX_CHARS, DeleteCharFunc());
std::for_each(m_glyphs, m_glyphs + FT_MAX_CHARS, DeleteCharFunc());
#else
GlyphCache::iterator it=m_GlyphCache.begin();
for (;it!=m_GlyphCache.end();++it)
delete it->second;
m_GlyphCache.clear();
#endif
}
void FreeTypeFontCache::AddCharData(WCHAR wch, UINT glyphindex, int width, int gdiWidth, FT_Referenced_BitmapGlyph glyph, FT_Render_Mode render_mode, int AAMode)
{
if (glyphindex & 0xffff0000 /*|| !g_ccbCache*/) {
return;
}
if (AddIncrement() >= FREETYPE_REQCOUNTMAX) { //マネムケヒャアワテ簷ケヒェハァオトホハフ
Compact();
}
#ifdef _USE_ARRAY
FreeTypeCharData** ppChar = _GetChar(wch);
if (*ppChar) {
(*ppChar)->SetGlyph(render_mode, glyph);
(*ppChar)->SetMruCounter(this);
return;
}
#else
GlyphCache::iterator it=m_GlyphCache.find(wch);
if (it!=m_GlyphCache.end()) //ユメオスチヒセノハセン
{
FreeTypeCharData* ppChar = it->second;
if (ppChar) {
ppChar->SetGlyph(render_mode, glyph);
ppChar->SetMruCounter(this);
ppChar->SetWidth(width);
ppChar->SetGDIWidth(gdiWidth);
return;
}
}
#endif
FreeTypeCharData* p = new FreeTypeCharData(/*ppChar*/NULL, NULL, wch, glyphindex, width, MruIncrement(), gdiWidth, AAMode);
if (p == NULL) {
return;
}
p->SetGlyph(render_mode, glyph);
#ifdef _USE_ARRAY
*ppChar = p;
#else
m_GlyphCache[wch]=p;
#endif
}
void FreeTypeFontCache::AddGlyphData(UINT glyphindex, int width, int gdiWidth, FT_Referenced_BitmapGlyph glyph, FT_Render_Mode render_mode, int AAMode)
{
if (glyphindex & 0xffff0000 /*|| !g_ccbCache*/) {
return;
}
//GC
if (AddIncrement() >= FREETYPE_REQCOUNTMAX) {
//TRACE(_T("Compact(0x%p)\n"), this);
Compact();
}
#ifdef _USE_ARRAY
FreeTypeCharData** ppGlyph = _GetGlyph(glyphindex);
if (*ppGlyph) {
(*ppGlyph)->SetGlyph(render_mode, glyph);
(*ppGlyph)->SetMruCounter(this);
return;
}
#else
GlyphCache::iterator it=m_GlyphCache.find(-(int)glyphindex);
if (it!=m_GlyphCache.end()) //ユメオスチヒセノハセン
{
FreeTypeCharData* ppChar = it->second;
if (ppChar) {
(ppChar)->SetGlyph(render_mode, glyph);
(ppChar)->SetMruCounter(this);
ppChar->SetWidth(width);
ppChar->SetGDIWidth(gdiWidth);
return;
}
}
#endif
//追加(glyphのみ)
FreeTypeCharData* p = new FreeTypeCharData(NULL, /*ppGlyph*/NULL, 0, glyphindex, width, MruIncrement(), gdiWidth, AAMode);
if (p == NULL) {
return;
}
p->SetGlyph(render_mode, glyph);
#ifdef _USE_ARRAY
*ppGlyph = p;
#else
m_GlyphCache[-(int)glyphindex]=p;
#endif
}
//FreeTypeFontInfo
void FreeTypeFontInfo::Compact()
{
//TRACE(_T("FreeTypeFontInfo::Compact: %d > %d\n"), m_cache.GetSize(), m_nMaxSizes);
ResetGCCounter();
::CompactMap(m_cache, m_cache.size(), m_nMaxSizes);
CacheArray::const_iterator it=m_cache.begin();
for (;it!=m_cache.end();++it)
it->second->Deactive();
}
void FreeTypeFontInfo::Createlink()
{
CFontFaceNamesEnumerator fn(m_hash.c_str(), m_nFontFamily);
std::set<int> linkset; //チエスモラヨフ蠑ッコマ」ャキタヨケヨリクエチエスモ」ャスオオヘミァツハ
linkset.insert(m_id);
face_id_link[m_linknum] = (FTC_FaceID)m_id;
ggo_link[m_linknum++] = m_ggoFont; //オレメサクエスモメサカィハヌラヤシコ」ャイサミ靨ェサ。
LOGFONT lf;
BOOL IsSimSun = false;
memset(&lf, 0, sizeof(LOGFONT));
lf.lfCharSet=DEFAULT_CHARSET;
const CGdippSettings* pSettings = CGdippSettings::GetInstance();
for (fn.next() ; !fn.atend(); fn.next()) { //フオレメサクエスモ
//FreeTypeFontInfo* pfitemp = g_pFTEngine->FindFont(fn, m_weight, m_italic);
//if (pfitemp && pfitemp->m_isSimSun)
// IsSimSun = true;
if (!m_SimSunID)
IsSimSun = (_wcsicmp(fn,L"ヒホフ")==0 || _wcsicmp(fn,L"SimSun")==0);
StringCchCopy(lf.lfFaceName, LF_FACESIZE, fn);
pSettings->CopyForceFont(lf,lf);
FreeTypeFontInfo* pfitemp = g_pFTEngine->FindFont(lf.lfFaceName, /*m_weight*/0, /*m_italic*/false);
if (pfitemp && linkset.find(pfitemp->GetId())==linkset.end()) {
linkset.insert(pfitemp->GetId());
face_id_link[m_linknum] = (FTC_FaceID)pfitemp->GetId();
ggo_link[m_linknum++] = pfitemp->GetGGOFont();
if (!m_SimSunID && IsSimSun)
m_SimSunID = (FTC_FaceID)pfitemp->GetId();
}
}
}
bool FreeTypeFontInfo::EmbeddedBmpExist(int px)
{
if (px>=256 || px<0)
return false;
if (m_ebmps[px]!=-1)
return !!m_ebmps[px];
CCriticalSectionLock __lock(CCriticalSectionLock::CS_MANAGER);
FTC_ImageTypeRec imgtype={(FTC_FaceID)m_id, px, px, FT_LOAD_DEFAULT}; //ケケヤサクアヌーエ。オトimagetype
FT_Glyph temp_glyph=NULL;
FT_UInt gindex = FTC_CMapCache_Lookup(cmap_cache, (FTC_FaceID)m_id, -1, FT_UInt32(L'0')); //サテ0オトヒヨオ
FTC_ImageCache_Lookup(image_cache, &imgtype, gindex, &temp_glyph, NULL);
if (temp_glyph && temp_glyph->format==FT_GLYPH_FORMAT_BITMAP) //ネ郢ノメヤカチオス0オトオ耻
m_ebmps[px]=1; //ヤテラヨコナエ贇レオ耻
else
{
gindex = FTC_CMapCache_Lookup(cmap_cache, (FTC_FaceID)m_id, -1, FT_UInt32(L'オト')); //サテ"オト"オトヒヨオ
if (gindex)
FTC_ImageCache_Lookup(image_cache, &imgtype, gindex, &temp_glyph, NULL); //カチネ。。ーオト。アオトオ耻
if (temp_glyph && temp_glyph->format==FT_GLYPH_FORMAT_BITMAP) //ネ郢ノメヤカチオス0オトオ耻
m_ebmps[px]=1; //ヤテラヨコナエ贇レオ耻
else
m_ebmps[px]=0;
}
return !!m_ebmps[px];
}
FreeTypeFontCache* FreeTypeFontInfo::GetCache(FTC_ScalerRec& scaler, const LOGFONT& lf)
{
CCriticalSectionLock __lock(CCriticalSectionLock::CS_FONTCACHE);
if (AddIncrement() > m_nMaxSizes) { //マネムケヒ
Compact();
}
int weight = lf.lfWeight;
weight = weight < FW_BOLD ? 0: 1/*FW_BOLD*/;
const bool italic = !!lf.lfItalic;
if (scaler.height>0xfff || scaler.width>0xfff/* || scaler.height<0 || scaler.width<0*/) //ウャエヨフ蟯サ葷ネセ
return NULL;
FreeTypeFontCache* p = NULL;
UINT hash=getCacheHash(scaler.height, weight, italic, lf.lfWidth ? scaler.width : 0); //シニヒ緝ash
CacheArray::iterator it=m_cache.find(hash); //ムーユメcache
if (it!=m_cache.end())//cacheエ贇レ
{
p = it->second;
goto OK; //キオサリcache
}
p = new FreeTypeFontCache(/*scaler.height, weight, italic,*/ MruIncrement());
if (!p) {
return NULL;
}
if (m_cache[hash]=p) {
goto OK;
}
delete p;
return NULL;
OK:
Assert(p != NULL);
if (p && p->Activate()) {
DecIncrement(); //ヨリクエハケモテヤニハヨオ
}
return p;
}
//FreeTypeFontEngine
void FreeTypeFontEngine::Compact()
{
CCriticalSectionLock __lock(CCriticalSectionLock::CS_FONTENG);
TRACE(_T("FreeTypeFontEngine::Compact: %d > %d\n"), m_mfontMap.size(), m_nMaxFaces);
ResetGCCounter();
//memset(m_arrFace, 0, sizeof(FT_Face)*m_nFaceCount); //ウャケラaceハチヒ」ャタマオトfaceサ盂サftハヘキナオャヒヤミ靨ェネォイソヨリミツサ。
//FontListArray& arr = m_arrFontList;
//::Compact(arr.GetData(), arr.GetSize(), m_nMaxFaces);
}
BOOL FreeTypeFontEngine::RemoveFont(FreeTypeFontInfo* fontinfo)
{
CCriticalSectionLock __lock(CCriticalSectionLock::CS_FONTMAP);
{
FontMap::const_iterator iter=m_mfontMap.begin(); //ア鯊ontmap
while (iter!=m_mfontMap.end())
{
FreeTypeFontInfo* p = iter->second;
if (p==fontinfo)
m_mfontMap.erase(iter++); //ノセウメモテ
else
++iter;
}
}
{
FullNameMap::const_iterator iter=m_mfullMap.begin(); //ア鯊ullmap
while (iter!=m_mfullMap.end())
{
FreeTypeFontInfo* p = iter->second;
if (p==fontinfo)
m_mfullMap.erase(iter++); //ノセウメモテ
else
{
iter->second->UpdateFontSetting();
++iter;
}
}
}
delete fontinfo;
return true;
}
BOOL FreeTypeFontEngine::RemoveThisFont(FreeTypeFontInfo* fontinfo, LOGFONT* lg)
{
CCriticalSectionLock __lock(CCriticalSectionLock::CS_FONTMAP);
{
FontMap::const_iterator iter=m_mfontMap.find(myfont(lg->lfFaceName, CalcBoldWeight(lg->lfWeight), lg->lfItalic)); //ア鯊ontmap
if (iter!=m_mfontMap.end())
m_mfontMap.erase(iter); //ノセウメモテ
}
{
FullNameMap::const_iterator iter=m_mfullMap.find(fontinfo->GetFullName()); //ア鯊ullmap
if (iter!=m_mfullMap.end())
m_mfullMap.erase(iter); //ノセウメモテ
}
delete fontinfo;
return true;
}
BOOL FreeTypeFontEngine::RemoveFont(LPCWSTR FontName)
{
if (!FontName) return false;
LOGFONTW* fontarray = GetFontNameFromFile(FontName);
LOGFONTW* c_fontarray = fontarray; //シヌツシヤュハシヨクユ
if (!fontarray) return false;
FTC_FaceID fid = NULL;
BOOL bIsFontLoaded, bIsFontFileLoaded = false;
COwnedCriticalSectionLock __lock2(2, COwnedCriticalSectionLock::OCS_DC); //サ。ヒミネィ」ャマヨヤレメェエヲタC」ャスケヒミサ賚シコッハキテホハ
CCriticalSectionLock __lock(CCriticalSectionLock::CS_MANAGER);
while (*(char*)fontarray)
{
bIsFontLoaded = false;
FreeTypeFontInfo* result = FindFont(fontarray->lfFaceName, fontarray->lfWeight, !!fontarray->lfItalic, false, &bIsFontLoaded);
if (result)
{
fid = (FTC_FaceID)result->GetId();
if (bIsFontLoaded) //クテラヨフ袵ムセュアサハケモテケ
{
RemoveFont(result); //テカセルラヨフ衵ナマ「ネォイソノセウ
bIsFontFileLoaded = true; //ノ靹テラヨフ衾トシメイアサハケモテケ
}
else
RemoveThisFont(result, fontarray);
CCriticalSectionLock __lock(CCriticalSectionLock::CS_FONTENG);
FTC_Manager_RemoveFaceID(cache_man, fid);
m_mfontList[(int)fid-1]=NULL;
}
fontarray++;
}
free(c_fontarray); //タテヤュハシヨクユヘキナ
if (bIsFontFileLoaded) //ネヨフ衾トシアサハケモテケ」ャヤ靨ェヌ蟲ヒミDC
{
CTLSDCArray::iterator iter = TLSDCArray.begin();
while (iter!=TLSDCArray.end())
{
((CBitmapCache*)*iter)->~CBitmapCache(); //ヌ蟲オミハケモテヨミオトDC
++iter;
}
}
return true;
}
static int FaceIDHolder = 0;
int GetFaceID(void)
{
return (int)InterlockedIncrement((LONG volatile*)&FaceIDHolder);
}
void ReleaseFaceID(void)
{
InterlockedDecrement((LONG volatile*)&FaceIDHolder);
}
FreeTypeFontInfo* FreeTypeFontEngine::AddFont(void* lpparams)
{
FREETYPE_PARAMS* params = (FREETYPE_PARAMS*)lpparams;
CCriticalSectionLock __lock(CCriticalSectionLock::CS_FONTENG);
const LOGFONT& lplf = *params->lplf;
if(!*lplf.lfFaceName || _tcslen(lplf.lfFaceName) == 0)
return NULL;
const CGdippSettings* pSettings = CGdippSettings::GetInstance();
//const CFontSettings& fs = pSettings->FindIndividual(params->strFamilyName.c_str());
FreeTypeFontInfo* pfi = new FreeTypeFontInfo(/*m_mfullMap.size() + 1*/GetFaceID(), lplf.lfFaceName, lplf.lfWeight, !!lplf.lfItalic, MruIncrement(), params->strFullName, params->strFamilyName);
if (!pfi)
return NULL;
if (pfi->GetFullName().size()==0) //オ耻ヨ
{
delete pfi;
ReleaseFaceID();
return NULL;
}
/*
TCHAR buff[255]={0};
if (params->strFamilyName.length()==8)
{
wsprintf(buff, L"Adding familiyname \"%s\" fullname \"%s\" weight %d\n\result: \"%s\"\n", params->strFamilyName.c_str(), params->strFullName.c_str(),
params->lplf->lfWeight, pfi->GetFullName().c_str());
Log(buff);
}*/
FullNameMap::const_iterator it = m_mfullMap.find(pfi->GetFullName());
if (it!=m_mfullMap.end()) //ハヌメムセュエ贇レオトラヨフ蠱ヒ,ヤュメヌラヨフ衫貊サハケチスヨヨテヨヨクマサクヨフ
{
delete pfi; //ノセウクユイナエエスィオトラヨフ
ReleaseFaceID();
pfi = it->second;//ヨクマュラヨフ
}
else
{
m_mfullMap[pfi->GetFullName()]=pfi; //イサエ贇レ」ャフモオスmapア
m_mfontList.push_back(pfi);
}
if (pfi->GetFullName()!=params->strFullName) //ネ郢ソアヨフ蠏トユ賁オテニコヘミ靨ェオトテニイサメサムャヒオテヌラヨフ衫貊サ
{
pfi->AddRef(); //ヤモメモテシニハ
m_mfullMap[params->strFullName] = pfi; //ヒォヨリメモテ」ャヨクマャメサクヨフ
}
//bool ret = !!arr.Add(pfi);
//weight = weight < FW_BOLD ? 0: FW_BOLD;
myfont font(lplf.lfFaceName, lplf.lfWeight, !!params->otm->otmTextMetrics.tmItalic);
/*
FontMap::const_iterator it = m_mfontMap.find(font);
if (it!=m_mfontMap.end())
{
it->second->Release();
}*/
m_mfontMap[font]=pfi;
/*
if (!ret) {
delete pfi;
return NULL;
}*/
#ifdef _DEBUG
{
const CFontSettings& fs = pfi->GetFontSettings();
TRACE(_T("AddFont: %s, %d, %d, %d, %d, %d, %d\n"), pfi->GetName(),
fs.GetParam(0), fs.GetParam(1), fs.GetParam(2), fs.GetParam(3), fs.GetParam(4), fs.GetParam(5));
}
#endif
return pfi;
}
FreeTypeFontInfo* FreeTypeFontEngine::AddFont(LPCTSTR lpFaceName, int weight, bool italic, BOOL* bIsFontLoaded)
{
CCriticalSectionLock __lock(CCriticalSectionLock::CS_FONTENG);
if(lpFaceName == NULL || _tcslen(lpFaceName) == 0/* || FontExists(lpFaceName, weight, italic)*/)
return NULL;
//FontListArray& arr = m_arrFontList;
const CGdippSettings* pSettings = CGdippSettings::GetInstance();
//const CFontSettings& fs = pSettings->FindIndividual(lpFaceName);
wstring dumy;
//dumy.clear();
FreeTypeFontInfo* pfi = new FreeTypeFontInfo(/*m_mfullMap.size() + 1*/GetFaceID(), lpFaceName, weight, italic, MruIncrement(), dumy, dumy);
if (!pfi)
return NULL;
if (pfi->GetFullName().size()==0) //オ耻ヨ
{
delete pfi;
ReleaseFaceID();
return NULL;
}
FullNameMap::const_iterator it = m_mfullMap.find(pfi->GetFullName()); //ハヌキレヨapアミエ贇レチヒ
if (it!=m_mfullMap.end()) //メムセュエ贇レ
{
delete pfi; //ノセウエエスィウエオトラヨフ
ReleaseFaceID();
pfi = it->second; //ヨクマムセュエ贇レオトラヨフ
if (bIsFontLoaded)
*bIsFontLoaded = true;
//pfi->AddRef();
}
else
{
m_mfullMap[pfi->GetFullName()]=pfi; //イサエ贇レ」ャフモオスmapア
m_mfontList.push_back(pfi);
if (bIsFontLoaded)
*bIsFontLoaded = false;
}
//bool ret = !!arr.Add(pfi);
//weight = weight < FW_BOLD ? 0: FW_BOLD;
myfont font(lpFaceName, weight, italic);
m_mfontMap[font]=pfi; //フモヤレエホメェmapア
/*
if (!ret) {
delete pfi;
return NULL;
}*/
#ifdef _DEBUG
{
const CFontSettings& fs = pfi->GetFontSettings();
TRACE(_T("AddFont: %s, %d, %d, %d, %d, %d, %d\n"), pfi->GetName(),
fs.GetParam(0), fs.GetParam(1), fs.GetParam(2), fs.GetParam(3), fs.GetParam(4), fs.GetParam(5));
}
#endif
return pfi;
}
int FreeTypeFontEngine::GetFontIdByName(LPCTSTR lpFaceName, int weight, bool italic)
{
const FreeTypeFontInfo* pfi = FindFont(lpFaceName, weight, italic);
return pfi ? pfi->GetId() : 0;
}
/*
LPCTSTR FreeTypeFontEngine::GetFontById(int faceid, int& weight, bool& italic)
{
CCriticalSectionLock __lock;
FreeTypeFontInfo** pp = m_arrFontList.Begin();
FreeTypeFontInfo** end = m_arrFontList.End();
for(; pp != end; ++pp) {
FreeTypeFontInfo* p = *pp;
if (p->GetId() == faceid) {
p->SetMruCounter(this);
weight = p->GetWeight();
italic = p->IsItalic();
return p->GetName();
}
}
return NULL;
}
*/
FreeTypeFontInfo* FreeTypeFontEngine::FindFont(void* lpparams)
{
FREETYPE_PARAMS* params = (FREETYPE_PARAMS*)lpparams;
CCriticalSectionLock __lock(CCriticalSectionLock::CS_FONTMAP);
FullNameMap::const_iterator iter=m_mfullMap.find(params->strFullName);
if (iter!=m_mfullMap.end())
{
FreeTypeFontInfo* p = iter->second;
if (p->GetFullName()!=params->strFullName) //ハレフ貊サラヨフ
return FindFont(params->lplf->lfFaceName, params->lplf->lfWeight, !!params->lplf->lfItalic);
p->SetMruCounter(this);
return p;
}
//m_bAddOnFind = true;
return AddFont(params);
}
FreeTypeFontInfo* FreeTypeFontEngine::FindFont(LPCTSTR lpFaceName, int weight, bool italic, bool AddOnFind, BOOL* bIsFontLoaded)
{
/*
if (m_bAddOnFind)
{
m_bAddOnFind = false;
return NULL;
}*/
CCriticalSectionLock __lock(CCriticalSectionLock::CS_FONTMAP);
weight = CalcBoldWeight(weight);
myfont font(lpFaceName, weight, italic);
FontMap::const_iterator iter=m_mfontMap.find(font);
if (iter!=m_mfontMap.end())
{
FreeTypeFontInfo* p = iter->second;
p->SetMruCounter(this);
/*
TCHAR buff[255]={0};
if (wcslen(lpFaceName)==8)
{
wsprintf(buff, L"Finding familiyname \"%s\" weight %d\n\tFound: \"%s\"\n", lpFaceName,
weight, p->GetFullName().c_str());
Log(buff);
}*/
if (bIsFontLoaded)
*bIsFontLoaded = true;
return p;
}
//m_bAddOnFind = true;
return AddFont(lpFaceName, weight, italic, bIsFontLoaded);
}
FreeTypeFontInfo* FreeTypeFontEngine::FindFont(int faceid)
{
CCriticalSectionLock __lock(CCriticalSectionLock::CS_FONTMAP);
if (faceid>m_mfontList.size())
return NULL;
else
return m_mfontList[faceid-1]; //エ贇レbug」。」。」。
/*
FullNameMap::const_iterator iter=m_mfullMap.begin();
for(; iter != m_mfullMap.end(); ++iter) {
FreeTypeFontInfo* p = iter->second;
if (p->GetId() == faceid) {
p->SetMruCounter(this);
return p;
}
}
return NULL;*/
}
//FreeTypeSysFontData
// http://kikyou.info/diary/?200510#i10 を参考にした
#include <freetype/tttables.h> // FT_TRUETYPE_TABLES_H
#include <mmsystem.h> //mmioFOURCC
#define TVP_TT_TABLE_ttcf mmioFOURCC('t', 't', 'c', 'f')
#define TVP_TT_TABLE_name mmioFOURCC('n', 'a', 'm', 'e')
// Windowsに登録されているフォントのバイナリデータを名称から取得
FreeTypeSysFontData* FreeTypeSysFontData::CreateInstance(LPCTSTR name, int weight, bool italic)
{
FreeTypeSysFontData* pData = new FreeTypeSysFontData;
if (!pData) {
return NULL;
}
if (!pData->Init(name, weight, italic)) {
delete pData;
return NULL;
}
return pData;
}
bool FreeTypeSysFontData::Init(LPCTSTR name, int weight, bool italic)
{
const CGdippSettings* pSettings = CGdippSettings::GetInstance();
void* pNameFromGDI = NULL; // Windows から取得した name タグの内容
void* pNameFromFreeType = NULL; // FreeType から取得した name タグの内容
HFONT hf = NULL;
DWORD cbNameTable;
DWORD cbFontData;
int index;
DWORD buf;
FT_StreamRec& fsr = m_ftStream;
m_name.assign(name);
m_hdc = CreateCompatibleDC(NULL);
if(m_hdc == NULL) {
return false;
}
// 名前以外適当
if (pSettings->FontSubstitutes() < SETTING_FONTSUBSTITUTE_ALL)
{
hf = CreateFont(
12, 0, 0, 0, weight,
italic, FALSE, FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
FONT_MAGIC_NUMBER,
DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE,
name);
}
else
hf = CreateFont(
12, 0, 0, 0, weight,
italic, FALSE, FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE,
name);
if(hf == NULL){
return false;
}
m_hOldFont = SelectFont(m_hdc, hf);
// フォントデータが得られそうかチェック
cbNameTable = ::GetFontData(m_hdc, TVP_TT_TABLE_name, 0, NULL, 0);
if(cbNameTable == GDI_ERROR){
goto ERROR_Init;
}
pNameFromGDI = malloc(cbNameTable);
if (!pNameFromGDI) {
goto ERROR_Init;
}
pNameFromFreeType = malloc(cbNameTable);
if (!pNameFromFreeType) {
goto ERROR_Init;
}
//- name タグの内容をメモリに読み込む
if(GetFontData(m_hdc, TVP_TT_TABLE_name, 0, pNameFromGDI, cbNameTable) == GDI_ERROR){
goto ERROR_Init;
}
// フォントサイズ取得処理
cbFontData = ::GetFontData(m_hdc, TVP_TT_TABLE_ttcf, 0, &buf, 1);
if(cbFontData == 1){
// TTC ファイルだと思われる
cbFontData = ::GetFontData(m_hdc, TVP_TT_TABLE_ttcf, 0, NULL, 0);
m_isTTC = true;
}
else{
cbFontData = ::GetFontData(m_hdc, 0, 0, NULL, 0);
}
if(cbFontData == GDI_ERROR){
// エラー; GetFontData では扱えなかった
goto ERROR_Init;
}
if (pSettings->UseMapping()) {
HANDLE hmap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT | SEC_NOCACHE, 0, cbFontData, NULL);
if (!hmap) {
goto ERROR_Init;
}
m_pMapping = MapViewOfFile(hmap, FILE_MAP_ALL_ACCESS, 0, 0, cbFontData);
m_dwSize = cbFontData;
CloseHandle(hmap);
if (m_pMapping) {
::GetFontData(m_hdc, m_isTTC ? TVP_TT_TABLE_ttcf : 0, 0, m_pMapping, cbFontData);
}
}
// FT_StreamRec の各フィールドを埋める
fsr.base = 0;
fsr.size = cbFontData;
fsr.pos = 0;
fsr.descriptor.pointer = this;
fsr.pathname.pointer = NULL;
fsr.read = IoFunc;
fsr.close = CloseFunc;
index = 0;
m_locked = true;
if(!OpenFaceByIndex(index)){
goto ERROR_Init;
}
for(;;) {
// FreeType から、name タグのサイズを取得する
FT_ULong length = 0;
FT_Error err = FT_Load_Sfnt_Table(m_ftFace, TTAG_name, 0, NULL, &length);
if(err){
goto ERROR_Init;
}
// FreeType から得た name タグの長さを Windows から得た長さと比較
if(length == cbNameTable){
// FreeType から name タグを取得
err = FT_Load_Sfnt_Table(m_ftFace, TTAG_name, 0, (unsigned char*)pNameFromFreeType, &length);
if(err){
goto ERROR_Init;
}
// FreeType から読み込んだ name タグの内容と、Windows から読み込んだ
// name タグの内容を比較する。
// 一致していればその index のフォントを使う。
if(!memcmp(pNameFromGDI, pNameFromFreeType, cbNameTable)){
// 一致した
// face は開いたまま
break; // ループを抜ける
}
}
// 一致しなかった
// インデックスを一つ増やし、その face を開く
index ++;
if(!OpenFaceByIndex(index)){
// 一致する face がないまま インデックスが範囲を超えたと見られる
// index を 0 に設定してその index を開き、ループを抜ける
index = 0;
if(!OpenFaceByIndex(index)){
goto ERROR_Init;
}
break;
}
}
free(pNameFromGDI);
free(pNameFromFreeType);
m_locked = false;
return true;
ERROR_Init:
m_locked = false;
if (hf) {
SelectFont(m_hdc, m_hOldFont);
DeleteFont(hf);
m_hOldFont = NULL;
}
free(pNameFromGDI);
free(pNameFromFreeType);
return false;
}
unsigned long FreeTypeSysFontData::IoFunc(
FT_Stream stream,
unsigned long offset,
unsigned char* buffer,
unsigned long count )
{
if(count == 0){
return 0;
}
FreeTypeSysFontData * pThis = reinterpret_cast<FreeTypeSysFontData*>(stream->descriptor.pointer);
Assert(pThis != NULL);
DWORD result = 0;
if (pThis->m_pMapping) {
result = Min(pThis->m_dwSize - offset, count);
memcpy(buffer, (const BYTE*)pThis->m_pMapping + offset, result);
} else {
result = ::GetFontData(pThis->m_hdc, pThis->m_isTTC ? TVP_TT_TABLE_ttcf : 0, offset, buffer, count);
if(result == GDI_ERROR) {
// エラー
return 0;
}
}
return result;
}
void FreeTypeSysFontData::CloseFunc(FT_Stream stream)
{
FreeTypeSysFontData * pThis = reinterpret_cast<FreeTypeSysFontData*>(stream->descriptor.pointer);
Assert(pThis != NULL);
if(!pThis->m_locked)
delete pThis;
}
bool FreeTypeSysFontData::OpenFaceByIndex(int index)
{
if(m_ftFace) {
FT_Done_Face(m_ftFace);
m_ftFace = NULL;
}
FT_Open_Args args = { 0 };
args.flags = FT_OPEN_STREAM;
args.stream = &m_ftStream;
// FreeType で扱えるか?
FT_Error ftErrCode = FT_Open_Face(freetype_library, &args, index, &m_ftFace);
#ifdef DEBUG
if (ftErrCode!=0)
TRACE(L"Open face failed, error = %d\n", ftErrCode);
#endif
return (ftErrCode == 0);
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化