mactype/override.cpp

1685 lines
53 KiB
C++
Raw Permalink Normal View History

// override.cpp - キレイなTextOut
2016-09-02 17:29:33 +08:00
// 2006/09/27
#include "override.h"
#include "ft.h"
#include "fteng.h"
#include "supinfo.h"
#include "undocAPI.h"
2018-05-04 15:41:10 +08:00
//#include "lrucache.hpp"
2016-09-02 17:29:33 +08:00
#include <malloc.h> // _alloca
#include <mbctype.h> // _getmbcp
#pragma comment(lib, "Gdi32.lib")
#pragma comment(lib, "User32.lib")
#pragma comment(lib, "WindowsCodecs.lib")
#pragma comment (lib, "dwrite.lib")
#if defined(_DEBUG)
void Dbg_TractGetTextExtent(LPCSTR lpString, int cbString, LPSIZE lpSize);
void Dbg_TractGetTextExtent(LPCWSTR lpString, int cbString, LPSIZE lpSize);
void Dbg_TraceExtTextOutW(int nXStart, int nYStart, UINT fuOptions, LPCWSTR lpString, int cbString, const int* lpDx);
void Dbg_TraceScriptItemize(const WCHAR* pwcInChars, int cInChars);
void Dbg_TraceScriptShape(const WCHAR* pwcChars, int cChars, const SCRIPT_ANALYSIS* psa, const WORD* pwOutGlyphs, int cGlyphs);
#else
#define Dbg_TraceExtTextOutW(x,y,f,s,c,p)
#define Dbg_TractGetTextExtent(s,c,p)
#define Dbg_TraceScriptItemize(s,c)
#define Dbg_TraceScriptShape(s,c,p,g,o)
#endif
#define CCH_MAX_STACK 256
typedef HRESULT (WINAPI * __D2D1CreateFactory)(
D2D1_FACTORY_TYPE factoryType,
REFIID riid,
const D2D1_FACTORY_OPTIONS *pFactoryOptions,
void **ppIFactory);
typedef HRESULT (WINAPI* __DWriteCreateFactory)(
__in DWRITE_FACTORY_TYPE factoryType,
__in REFIID iid,
__out IUnknown **factory
);
CFontCache FontCache;
CDCArray DCArray;
wstring nullstring;
BOOL g_ccbRender = true;
BOOL g_ccbCache = true;
HFONT g_alterGUIFont = NULL;
HFONT g_alterSysFont = NULL;
//BOOL FreeTypeGetTextExtentPoint(HDC hdc, LPCSTR lpString, int cbString, LPSIZE lpSize, const FREETYPE_PARAMS* params);
HFONT GetCurrentFont(HDC hdc)
{
HFONT hCurFont = (HFONT)GetCurrentObject(hdc, OBJ_FONT);
if (!hCurFont) {
// NULLの場合はSystemを設定しておく
2016-09-02 17:29:33 +08:00
hCurFont = (HFONT)GetStockObject(SYSTEM_FONT);
}
return hCurFont;
}
//判断是否是有效普通显示DC用于跳过字幕
2016-09-02 17:29:33 +08:00
BOOL IsValidDC(HDC hdc)
{
if (GetDeviceCaps(hdc, TECHNOLOGY) != DT_RASDISPLAY) {
return FALSE;
}
return TRUE;
}
BOOL IsProcessExcluded()
{
// if (GetModuleHandle(NULL) == GetModuleHandle(_T("gdi++.exe"))) {
// return TRUE;
// }
2016-09-27 15:02:20 +08:00
const CGdippSettings* pSettings = CGdippSettings::GetInstanceNoInit();
2016-09-02 17:29:33 +08:00
if (pSettings->IsInclude()) {
if (pSettings->IsProcessIncluded()) {
return FALSE;
}
return TRUE;
}
if (pSettings->IsProcessExcluded()) {
return TRUE;
}
return FALSE;
}
BOOL IsProcessUnload()
{
// if (GetModuleHandle(NULL) == GetModuleHandle(_T("gdi++.exe"))) {
// return TRUE;
// }
2016-09-27 15:02:20 +08:00
const CGdippSettings* pSettings = CGdippSettings::GetInstanceNoInit();
2016-09-02 17:29:33 +08:00
if (pSettings->IsInclude()) {
if (pSettings->IsProcessIncluded()) {
return FALSE;
}
return TRUE;
}
if (pSettings->IsProcessUnload()) {
return TRUE;
}
return FALSE;
}
BOOL IsExeUnload(LPCTSTR lpApp)
{
2016-09-27 15:02:20 +08:00
const CGdippSettings* pSettings = CGdippSettings::GetInstanceNoInit();
2016-09-02 17:29:33 +08:00
if (pSettings->IsInclude()) {
if (pSettings->IsExeInclude(lpApp)) {
return FALSE;
}
return TRUE;
}
if (pSettings->IsExeUnload(lpApp)) {
return TRUE;
}
return FALSE;
}
//切り上げ除算
2016-09-02 17:29:33 +08:00
int div_ceil(int a, int b)
{
if(a % b)
return (a>0)? (a/b+1): (a/b-1);
return a / b;
}
template <typename _TCHAR> //修改这个函数使它在失败的时候返回false由调用者负责调用Windows原函数实现线程安全。
2016-09-02 17:29:33 +08:00
BOOL _GetTextExtentPoint32AorW(HDC hdc, _TCHAR* lpString, int cbString, LPSIZE lpSize)
{
const CGdippSettings* pSettings = CGdippSettings::GetInstance();
if (pSettings->WidthMode() == SETTING_WIDTHMODE_GDI32
|| !IsValidDC(hdc) || !lpString || cbString <= 0) {
return false;
}
FREETYPE_PARAMS params(0, hdc);
if(FreeTypeGetTextExtentPoint(hdc, lpString, cbString, lpSize, &params)) {
Dbg_TractGetTextExtent(lpString, cbString, lpSize);
return TRUE;
}
else
return false;
}
//firefox
/*
BOOL WINAPI IMPL_GetTextExtentPoint32A(HDC hdc, LPCSTR lpString, int cbString, LPSIZE lpSize)
{
//CThreadCounter __counter;
//CCriticalSectionLock __lock;
return _GetTextExtentPoint32AorW(hdc, lpString, cbString, lpSize) || ORIG_GetTextExtentPoint32A(hdc, lpString, cbString, lpSize);
}
BOOL WINAPI IMPL_GetTextExtentPoint32W(HDC hdc, LPCWSTR lpString, int cbString, LPSIZE lpSize)
{
//CThreadCounter __counter;
//CCriticalSectionLock __lock;
return _GetTextExtentPoint32AorW(hdc, lpString, cbString, lpSize) || ORIG_GetTextExtentPoint32W(hdc, lpString, cbString, lpSize);
}
BOOL WINAPI IMPL_GetTextExtentPointA(HDC hdc, LPCSTR lpString, int cbString, LPSIZE lpSize)
{
//CThreadCounter __counter;
//CCriticalSectionLock __lock;
return _GetTextExtentPoint32AorW(hdc, lpString, cbString, lpSize) || ORIG_GetTextExtentPoint32A(hdc, lpString, cbString, lpSize);
}
BOOL WINAPI IMPL_GetTextExtentPointW(HDC hdc, LPCWSTR lpString, int cbString, LPSIZE lpSize)
{
//CThreadCounter __counter;
//CCriticalSectionLock __lock;
return _GetTextExtentPoint32AorW(hdc, lpString, cbString, lpSize) || ORIG_GetTextExtentPoint32W(hdc, lpString, cbString, lpSize);
}
BOOL WINAPI IMPL_GetCharWidthW(HDC hdc, UINT iFirstChar, UINT iLastChar, LPINT lpBuffer)
{
//CThreadCounter __counter;
const CGdippSettings* pSettings = CGdippSettings::GetInstance();
if (pSettings->WidthMode() == SETTING_WIDTHMODE_GDI32
|| !IsValidDC(hdc) || !lpBuffer || !FreeTypeGetCharWidth(hdc, iFirstChar, iLastChar, lpBuffer)) {
return ORIG_GetCharWidthW(hdc, iFirstChar, iLastChar, lpBuffer);
}
return TRUE;
}
BOOL WINAPI IMPL_GetCharWidth32W(HDC hdc, UINT iFirstChar, UINT iLastChar, LPINT lpBuffer)
{
//CThreadCounter __counter;
TRACE(_T("GetCharWidth32W(%u, %u, {...})\n"), iFirstChar, iLastChar);
const CGdippSettings* pSettings = CGdippSettings::GetInstance();
if (pSettings->WidthMode() == SETTING_WIDTHMODE_GDI32
|| !IsValidDC(hdc) || !lpBuffer || !FreeTypeGetCharWidth(hdc, iFirstChar, iLastChar, lpBuffer)) {
return ORIG_GetCharWidth32W(hdc, iFirstChar, iLastChar, lpBuffer);
}
return TRUE;
}*/
/*
extern PFNLdrGetProcedureAddress LdrGetProcedureAddress;
int MyGetProcAddress(HMODULE dll, LPSTR funcname)
{
ANSI_STRING dumy;
dumy.Length = strlen(funcname);
dumy.MaximumLength = strlen(funcname);
dumy.Buffer = funcname;
int nRet;
LdrGetProcedureAddress(dll,&dumy,0,(void**)&nRet);
return nRet;
}*/
/*
LONG WINAPI IMPL_LdrLoadDll(IN PWCHAR PathToFile OPTIONAL, IN ULONG Flags OPTIONAL, IN UNICODE_STRING2* ModuleFileName, OUT HANDLE* ModuleHandle)
{
static bool bFisrtTimeHook = GetModuleHandle(_T("d2d1.dll"))!=0;
if (!bD2D1Loaded)
{
wstring filename = wstring(ModuleFileName->Buffer);
int last_slash=filename.find_last_of('\\');
if (last_slash!=-1)
filename.erase(0,last_slash+1); //删除路径
if (_wcsicmp(filename.c_str(), L"d2d1.dll")==0) //正在载入d2d1.dll
2016-09-02 17:29:33 +08:00
{
bD2D1Loaded = true;
LONG result = ORIG_LdrLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle);
HookD2D1((HMODULE)*ModuleHandle);
return result;
}
if (bFisrtTimeHook)
{
bFisrtTimeHook = false;
bD2D1Loaded = true;
HookD2D1(GetModuleHandle(_T("d2d1.dll")));
}
}
return ORIG_LdrLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle);
}*/
/*
2016-09-02 17:29:33 +08:00
BOOL WINAPI IMPL_CreateProcessInternalW( HANDLE hToken, LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, \
DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation , PHANDLE hNewToken)
{
//CThreadCounter __counter;
CCriticalSectionLock __lock;
return _CreateProcessInternalW(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken, ORIG_CreateProcessInternalW);
}*/
2016-09-02 17:29:33 +08:00
/*
BOOL WINAPI IMPL_nCreateProcessA(LPCSTR lpApp, LPSTR lpCmd, LPSECURITY_ATTRIBUTES pa, LPSECURITY_ATTRIBUTES ta, BOOL bInherit, DWORD dwFlags, LPVOID lpEnv, LPCSTR lpDir, LPSTARTUPINFOA psi, LPPROCESS_INFORMATION ppi)
{
//CThreadCounter __counter;
CCriticalSectionLock __lock;
TRACE(_T("CreateProcessA(\"%hs\", \"%hs\", ...)\n"), lpApp, lpCmd);
return _CreateProcessAorW(lpApp, lpCmd, pa, ta, bInherit, dwFlags, lpEnv, lpDir, psi, ppi, ORIG_nCreateProcessA);
}
BOOL WINAPI IMPL_nCreateProcessW(LPCWSTR lpApp, LPWSTR lpCmd, LPSECURITY_ATTRIBUTES pa, LPSECURITY_ATTRIBUTES ta, BOOL bInherit, DWORD dwFlags, LPVOID lpEnv, LPCWSTR lpDir, LPSTARTUPINFOW psi, LPPROCESS_INFORMATION ppi)
{
//CThreadCounter __counter;
CCriticalSectionLock __lock;
TRACE(_T("CreateProcessW(\"%ls\", \"%ls\", ...)\n"), lpApp, lpCmd);
return _CreateProcessAorW(lpApp, lpCmd, pa, ta, bInherit, dwFlags, lpEnv, lpDir, psi, ppi, ORIG_nCreateProcessW);
}
BOOL WINAPI IMPL_CreateProcessAsUserA(HANDLE hToken, LPCSTR lpApp, LPSTR lpCmd, LPSECURITY_ATTRIBUTES pa, LPSECURITY_ATTRIBUTES ta, BOOL bInherit, DWORD dwFlags, LPVOID lpEnv, LPCSTR lpDir, LPSTARTUPINFOA psi, LPPROCESS_INFORMATION ppi)
{
//CThreadCounter __counter;
CCriticalSectionLock __lock;
TRACE(_T("CreateProcessA(\"%hs\", \"%hs\", ...)\n"), lpApp, lpCmd);
return _CreateProcessAsUserAorW(hToken, lpApp, lpCmd, pa, ta, bInherit, dwFlags, lpEnv, lpDir, psi, ppi, ORIG_CreateProcessAsUserA);
}
BOOL WINAPI IMPL_CreateProcessAsUserW(HANDLE hToken, LPCWSTR lpApp, LPWSTR lpCmd, LPSECURITY_ATTRIBUTES pa, LPSECURITY_ATTRIBUTES ta, BOOL bInherit, DWORD dwFlags, LPVOID lpEnv, LPCWSTR lpDir, LPSTARTUPINFOW psi, LPPROCESS_INFORMATION ppi)
{
//CThreadCounter __counter;
CCriticalSectionLock __lock;
TRACE(_T("CreateProcessW(\"%ls\", \"%ls\", ...)\n"), lpApp, lpCmd);
return _CreateProcessAsUserAorW(hToken, lpApp, lpCmd, pa, ta, bInherit, dwFlags, lpEnv, lpDir, psi, ppi, ORIG_CreateProcessAsUserW);
}*/
/*
HOOK_DEFINE(user32.dll, DWORD, GetTabbedTextExtentA, (HDC hdc, LPCSTR lpString, int nCount, int nTabPositions, CONST LPINT lpnTabStopPositions), (hdc, lpString, nCount, nTabPositions, lpnTabStopPositions))
HOOK_DEFINE(user32.dll, DWORD, GetTabbedTextExtentW, (HDC hdc, LPCWSTR lpString, int nCount, int nTabPositions, CONST LPINT lpnTabStopPositions), (hdc, lpString, nCount, nTabPositions, lpnTabStopPositions))
HOOK_DEFINE(gdi32.dll, BOOL, GetTextExtentExPointA, (HDC hdc, LPCSTR lpszStr, int cchString, int nMaxExtent, LPINT lpnFit, LPINT lpDx, LPSIZE lpSize), (hdc, lpszStr, cchString, nMaxExtent, lpnFit, lpDx, lpSize))
HOOK_DEFINE(gdi32.dll, BOOL, GetTextExtentExPointW, (HDC hdc, LPCWSTR lpszStr, int cchString, int nMaxExtent, LPINT lpnFit, LPINT lpDx, LPSIZE lpSize), (hdc, lpszStr, cchString, nMaxExtent, lpnFit, lpDx, lpSize))
HOOK_DEFINE(gdi32.dll, BOOL, GetTextExtentExPointI, (HDC hdc, LPWORD pgiIn, int cgi, int nMaxExtent, LPINT lpnFit, LPINT lpDx, LPSIZE lpSize), (hdc, pgiIn, cgi, nMaxExtent, lpnFit, lpDx, lpSize))
HOOK_DEFINE(gdi32.dll, BOOL, GetTextExtentPointA, (HDC hdc, LPCSTR lpString, int cbString, LPSIZE lpSize), (hdc, lpString, cbString, lpSize))
HOOK_DEFINE(gdi32.dll, BOOL, GetTextExtentPointW, (HDC hdc, LPCWSTR lpString, int cbString, LPSIZE lpSize), (hdc, lpString, cbString, lpSize))
HOOK_DEFINE(gdi32.dll, BOOL, GetTextExtentPointI, (HDC hdc, LPWORD pgiIn, int cgi, LPSIZE lpSize), (hdc, pgiIn, cgi, lpSize))
*/
/*
HFONT WINAPI IMPL_CreateFontA(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD fdwItalic, DWORD fdwUnderline, DWORD fdwStrikeOut, DWORD fdwCharSet, DWORD fdwOutputPrecision, DWORD fdwClipPrecision, DWORD fdwQuality, DWORD fdwPitchAndFamily, LPCSTR lpszFace)
{
LOGFONTA lf = {
nHeight,
nWidth,
nEscapement,
nOrientation,
fnWeight,
!!fdwItalic,
!!fdwUnderline,
!!fdwStrikeOut,
(BYTE)fdwCharSet,
(BYTE)fdwOutputPrecision,
(BYTE)fdwClipPrecision,
(BYTE)fdwQuality,
(BYTE)fdwPitchAndFamily,
};
if (lpszFace)
strncpy(lf.lfFaceName, lpszFace, LF_FACESIZE - 1);
return IMPL_CreateFontIndirectA(&lf);
}
HFONT WINAPI IMPL_CreateFontW(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD fdwItalic, DWORD fdwUnderline, DWORD fdwStrikeOut, DWORD fdwCharSet, DWORD fdwOutputPrecision, DWORD fdwClipPrecision, DWORD fdwQuality, DWORD fdwPitchAndFamily, LPCWSTR lpszFace)
{
LOGFONTW lf = {
nHeight,
nWidth,
nEscapement,
nOrientation,
fnWeight,
!!fdwItalic,
!!fdwUnderline,
!!fdwStrikeOut,
(BYTE)fdwCharSet,
(BYTE)fdwOutputPrecision,
(BYTE)fdwClipPrecision,
(BYTE)fdwQuality,
(BYTE)fdwPitchAndFamily,
};
if (lpszFace)
wcsncpy(lf.lfFaceName, lpszFace, LF_FACESIZE - 1);
return IMPL_CreateFontIndirectW(&lf);
}
HFONT WINAPI IMPL_CreateFontIndirectA(CONST LOGFONTA *lplfA)
{
if(!lplfA) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
const CGdippSettings* pSettings = CGdippSettings::GetInstance();
if (pSettings->IsFontExcluded(lplfA->lfFaceName)) {
return ORIG_CreateFontIndirectA(lplfA);
}
LOGFONT lf = {
lplfA->lfHeight,
lplfA->lfWidth,
lplfA->lfEscapement,
lplfA->lfOrientation,
lplfA->lfWeight,
lplfA->lfItalic,
lplfA->lfUnderline,
lplfA->lfStrikeOut,
lplfA->lfCharSet,
lplfA->lfOutPrecision,
lplfA->lfClipPrecision,
lplfA->lfQuality,
lplfA->lfPitchAndFamily,
};
MultiByteToWideChar(CP_ACP, 0, lplfA->lfFaceName, LF_FACESIZE, lf.lfFaceName, LF_FACESIZE);
LOGFONT* lplf = &lf;
if (pSettings->CopyForceFont(lf, lf)) {
lplf = &lf;
}
HFONT hf = IMPL_CreateFontIndirectW(lplf);
// if(hf && lplf && !pSettings->LoadOnDemand()) {
// AddFontToFT(lplf->lfFaceName, lplf->lfWeight, !!lplf->lfItalic);
// }
return hf;
}
*/
//Snowie!!
LPCWSTR GetCachedFont(HFONT lFont)
{
CFontCache::const_iterator it= FontCache.find(lFont);
if (it==FontCache.end())
return NULL;
else
return it->second->lpRealName;
}
LPCWSTR GetCachedFontLocale(HFONT lFont)
{
CFontCache::const_iterator it= FontCache.find(lFont);
if (it==FontCache.end())
return NULL;
else
return it->second->lpGDIName;
}
void AddToCachedFont(HFONT lfont, LPWSTR lpFaceName, LPWSTR lpGDIName)
{
if (!lfont) return; //不可以添加空节点
2016-09-02 17:29:33 +08:00
CCriticalSectionLock __lock(CCriticalSectionLock::CS_CACHEDFONT);
if (GetCachedFont(lfont)) return; //已经存在的字体
2016-09-02 17:29:33 +08:00
FontCache[lfont] = new CFontSubResult(lpFaceName, lpGDIName);
}
void DeleteCachedFont(HFONT lfont)
{
if (!lfont) return; //不可以删除头结点
2016-09-02 17:29:33 +08:00
CCriticalSectionLock __lock(CCriticalSectionLock::CS_CACHEDFONT);
CFontCache::iterator it= FontCache.find(lfont);
if (it!=FontCache.end())
{
delete it->second;
FontCache.erase(it);
}
}
int WINAPI IMPL_GetTextFaceAliasW(HDC hdc, int nLen, LPWSTR lpAliasW)
2016-09-02 17:29:33 +08:00
{
//CThreadCounter __counter;
int bResult = ORIG_GetTextFaceAliasW(hdc, nLen, lpAliasW);
2016-09-02 17:29:33 +08:00
//LOGFONT lf, lf2;
//StringCchCopy(lf.lfFaceName, LF_FACESIZE, lpAliasW);
//LOGFONT * lplf = &lf;
LPCWSTR fontcache=GetCachedFont(GetCurrentFont(hdc));
if (fontcache){
if (lpAliasW)
StringCchCopy(lpAliasW, LF_FACESIZE, fontcache);
2016-09-02 17:29:33 +08:00
bResult = wcslen(fontcache)+1;
}
return bResult;
}
2018-05-04 15:41:10 +08:00
// Won't get any better for clipbox, obsolete.
/*
cache::lru_cache<HFONT, int> FontHeightCache(200); // cache 200 most frequently used fonts' height
const WCHAR TEST_ALPHABET_SEQUENCE[] = L"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int GetFontMaxAlphabetHeight(HDC dc, MAT2 *lpmt2) {
HFONT ft = GetCurrentFont(dc);
if (FontHeightCache.exists(ft))
return FontHeightCache.get(ft);
GLYPHMETRICS lppm = { 0 };
int nHeight = 0;
for (int i = 0; i < 26; ++i) {
ORIG_GetGlyphOutlineW(dc, TEST_ALPHABET_SEQUENCE[i], GGO_METRICS, &lppm, 0, 0, lpmt2);
if (lppm.gmptGlyphOrigin.y>nHeight)
nHeight = lppm.gmptGlyphOrigin.y;
}
FontHeightCache.put(ft, nHeight);
return nHeight;
}*/
2016-09-02 17:29:33 +08:00
DWORD WINAPI IMPL_GetGlyphOutlineW(__in HDC hdc, __in UINT uChar, __in UINT fuFormat, __out LPGLYPHMETRICS lpgm, __in DWORD cjBuffer, __out_bcount_opt(cjBuffer) LPVOID pvBuffer, __in CONST MAT2 *lpmat2)
{
const CGdippSettings* pSettings = CGdippSettings::GetInstance();
DWORD ret= ORIG_GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cjBuffer, pvBuffer, lpmat2);
if (pSettings->EnableClipBoxFix() && (!cjBuffer || !pvBuffer)) {
if (!(fuFormat & (GGO_BITMAP | GGO_GRAY2_BITMAP | GGO_GRAY4_BITMAP | GGO_GRAY8_BITMAP | GGO_NATIVE))) {
//lpgm->gmptGlyphOrigin.x -= 1;
//lpgm->gmptGlyphOrigin.y += 1;
//lpgm->gmBlackBoxX += 3;
//lpgm->gmBlackBoxY += 2;
static int n = (int)floor(1.5*pSettings->ScreenDpi() / 96);
int nDeltaY = n, nDeltaBlackY = n;
TEXTMETRIC tm = { 0 };
GetTextMetrics(hdc, &tm);
if (lpgm->gmptGlyphOrigin.y < tm.tmAscent) { // origin out of the top of the box
if (lpgm->gmptGlyphOrigin.y + nDeltaY>tm.tmAscent) {
nDeltaY = tm.tmAscent - lpgm->gmptGlyphOrigin.y; // limit the top position of the origin
}
}
2018-05-04 15:41:10 +08:00
else nDeltaY = 0;
lpgm->gmptGlyphOrigin.y += nDeltaY;
/*if (lpgm->gmptGlyphOrigin.x > 0)
lpgm->gmBlackBoxX += n; // increase blackbox width if it's not a ligature
if (lpgm->gmBlackBoxX > tm.tmMaxCharWidth) {
lpgm->gmBlackBoxX = tm.tmMaxCharWidth;
}*/
lpgm->gmBlackBoxY += nDeltaY;
if (tm.tmAscent - lpgm->gmptGlyphOrigin.y + lpgm->gmBlackBoxY - 1 < tm.tmHeight) // still has some room to scale up
{
if (tm.tmAscent - lpgm->gmptGlyphOrigin.y + lpgm->gmBlackBoxY + 1 + nDeltaBlackY > tm.tmHeight)
lpgm->gmBlackBoxY = tm.tmHeight - tm.tmAscent + lpgm->gmptGlyphOrigin.y + 1;
else
lpgm->gmBlackBoxY += nDeltaBlackY;
}
2016-09-02 17:29:33 +08:00
}
}
// TEXTMETRIC tm;
// GetTextMetrics(hdc, &tm);
return ret;
}
DWORD WINAPI IMPL_GetGlyphOutlineA(__in HDC hdc, __in UINT uChar, __in UINT fuFormat, __out LPGLYPHMETRICS lpgm, __in DWORD cjBuffer, __out_bcount_opt(cjBuffer) LPVOID pvBuffer, __in CONST MAT2 *lpmat2)
{
//fuFormat |= GGO_UNHINTED;
const CGdippSettings* pSettings = CGdippSettings::GetInstance();
DWORD ret= ORIG_GetGlyphOutlineA(hdc, uChar, fuFormat, lpgm, cjBuffer, pvBuffer, lpmat2);
// if (pSettings->EnableClipBoxFix())
// {
// lpgm->gmptGlyphOrigin.y+=1;
// lpgm->gmBlackBoxY+=1;
// }
if (pSettings->EnableClipBoxFix() && (!cjBuffer || !pvBuffer)) {
if (!(fuFormat & (GGO_BITMAP | GGO_GRAY2_BITMAP | GGO_GRAY4_BITMAP | GGO_GRAY8_BITMAP | GGO_NATIVE))) {
static int n = (int)floor(1.5*pSettings->ScreenDpi() / 96);
int nDeltaY = n, nDeltaBlackY = n;
TEXTMETRIC tm = { 0 };
GetTextMetrics(hdc, &tm);
if (lpgm->gmptGlyphOrigin.y < tm.tmAscent) { // origin out of the top of the box
if (lpgm->gmptGlyphOrigin.y + nDeltaY>tm.tmAscent) {
nDeltaY = tm.tmAscent - lpgm->gmptGlyphOrigin.y; // limit the top position of the origin
}
}
2018-05-04 15:41:10 +08:00
else nDeltaY = 0;
/*if (lpgm->gmptGlyphOrigin.x > 0)
lpgm->gmBlackBoxX += n; // increase blackbox width if it's not a ligature
if (lpgm->gmBlackBoxX > tm.tmMaxCharWidth) {
lpgm->gmBlackBoxX = tm.tmMaxCharWidth;
}*/
lpgm->gmptGlyphOrigin.y += nDeltaY;
lpgm->gmBlackBoxY += nDeltaY;
if (tm.tmAscent - lpgm->gmptGlyphOrigin.y + lpgm->gmBlackBoxY - 1 < tm.tmHeight)
{
if (tm.tmAscent - lpgm->gmptGlyphOrigin.y + lpgm->gmBlackBoxY + 1 + nDeltaBlackY > tm.tmHeight)
lpgm->gmBlackBoxY = tm.tmHeight - tm.tmAscent + lpgm->gmptGlyphOrigin.y + 1;
else
lpgm->gmBlackBoxY += nDeltaBlackY;
}
2016-09-02 17:29:33 +08:00
}
}
return ret;
}
int WINAPI IMPL_GetTextFaceW( __in HDC hdc, __in int c, __out_ecount_part_opt(c, return) LPWSTR lpName)
{
int nSize = ORIG_GetTextFaceW(hdc, c, lpName);
LPCWSTR fontcache=GetCachedFontLocale(GetCurrentFont(hdc));
if (fontcache){
if (lpName) {
int len = Min(LF_FACESIZE, c);
StringCchCopy(lpName, len, fontcache);
nSize = (int)wcslen(fontcache) > len ? len : wcslen(fontcache) + 1;
}
else {
// a request for the size of font
nSize = Min(LF_FACESIZE, (int)wcslen(fontcache)+1);
}
2016-09-02 17:29:33 +08:00
}
return nSize;
}
int WINAPI IMPL_GetTextFaceA( __in HDC hdc, __in int c, __out_ecount_part_opt(c, return) LPSTR lpName)
{
int nSize = ORIG_GetTextFaceA(hdc, c, lpName);
LPCWSTR fontcache=GetCachedFontLocale(GetCurrentFont(hdc));
if (fontcache){
//int len=Min(LF_FACESIZE, c);
size_t _Dsize = 2 * wcslen(fontcache) + 1;
char *_Dest = new char[_Dsize];
memset(_Dest,0,_Dsize);
int len =wcstombs(_Dest, fontcache, _Dsize);
if (lpName)
StringCchCopyA(lpName, LF_FACESIZE, _Dest);
2016-09-02 17:29:33 +08:00
delete[] _Dest;
nSize = len+1;
}
return nSize;
}
HGDIOBJ WINAPI IMPL_GetStockObject(__in int i)
{
switch (i)
{
case DEFAULT_GUI_FONT:
{
static const CGdippSettings* pSetting = CGdippSettings::GetInstance();
if (g_alterGUIFont)
return g_alterGUIFont;
else
return ORIG_GetStockObject(i);
}
/*
case SYSTEM_FONT:
{
if (g_alterSysFont)
return g_alterSysFont;
break;
}*/
default: return ORIG_GetStockObject(i);
}
return ORIG_GetStockObject(i);
}
BOOL WINAPI IMPL_BeginPath(HDC hdc)
{
//CThreadCounter __counter;
BOOL ret=ORIG_BeginPath(hdc);
if (ret)
{
DCArray.insert(hdc);
}
return ret;
}
BOOL WINAPI IMPL_EndPath(HDC hdc)
{
//CThreadCounter __counter;
BOOL ret=ORIG_EndPath(hdc);
if (ret)
{
DCArray.erase(hdc);
}
return ret;
}
BOOL WINAPI IMPL_AbortPath(HDC hdc)
{
//CThreadCounter __counter;
BOOL ret=ORIG_AbortPath(hdc);
if (ret)
{
DCArray.erase(hdc);
}
return ret;
}
int WINAPI IMPL_GetObjectA(__in HANDLE h, __in int c, __out_bcount_opt(c) LPVOID pv)
{
int ret = ORIG_GetObjectA(h, c, pv);
if (ret==sizeof(LOGFONTA))
{
LPCWSTR fontcache = GetCachedFont((HFONT)h);
if (fontcache && pv)
{
size_t _Dsize = 2 * wcslen(fontcache) + 1;
char *_Dest = new char[_Dsize];
memset(_Dest,0,_Dsize);
wcstombs(_Dest,fontcache,_Dsize);
StringCchCopyA(((LOGFONTA*)pv)->lfFaceName, LF_FACESIZE, _Dest);
delete []_Dest;
}
}
return ret;
}
int WINAPI IMPL_GetObjectW(__in HANDLE h, __in int c, __out_bcount_opt(c) LPVOID pv)
{
int ret = ORIG_GetObjectW(h, c, pv);
if (ret==sizeof(LOGFONTW))
{
LPCWSTR fontcache = GetCachedFont((HFONT)h);
if (fontcache && pv)
{
StringCchCopyW(((LOGFONTW*)pv)->lfFaceName, LF_FACESIZE, fontcache);
}
}
return ret;
}
HFONT WINAPI IMPL_CreateFontIndirectExW(CONST ENUMLOGFONTEXDV *penumlfex)
{
if (!penumlfex) return NULL;
2016-09-02 17:29:33 +08:00
TRACE(L"Creating font \"%s\"\n", penumlfex->elfEnumLogfontEx.elfLogFont.lfFaceName);
{
if (penumlfex->elfEnumLogfontEx.elfLogFont.lfClipPrecision == FONT_MAGIC_NUMBER)
{
TRACE(L"Engine font, Ignored, ");
((ENUMLOGFONTEXDV *)penumlfex)->elfEnumLogfontEx.elfLogFont.lfClipPrecision = 0;
return ORIG_CreateFontIndirectExW(penumlfex);
}
}
/*
GetEnvironmentVariableW(L"MACTYPE_FONTSUBSTITUTES_ENV", NULL, 0);
if (GetLastError()!=ERROR_ENVVAR_NOT_FOUND)
return ORIG_CreateFontIndirectExW(penumlfex);*/
if(!penumlfex) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
const CGdippSettings* pSettings = CGdippSettings::GetInstance();
if (pSettings->IsFontExcluded(penumlfex->elfEnumLogfontEx.elfLogFont.lfFaceName)) {
TRACE(L"Font exception! ");
return ORIG_CreateFontIndirectExW(penumlfex);
//TRACE(L"Handle = %x\n" , (int)h);
}
ENUMLOGFONTEXDV mfont(*penumlfex);
LOGFONT& lf = mfont.elfEnumLogfontEx.elfLogFont;
LOGFONT lfOrg(lf);
BOOL bForced = false;
if (bForced = pSettings->CopyForceFont(lf, lfOrg)) {
/*
mfont->elfEnumLogfontEx.elfLogFont.lfHeight = lf.lfHeight;
// mfont->elfEnumLogfontEx.elfLogFont.lfWidth = lfOrg.lfWidth;
mfont->elfEnumLogfontEx.elfLogFont.lfWidth = lf.lfWidth;
mfont->elfEnumLogfontEx.elfLogFont.lfEscapement = lf.lfEscapement;
mfont->elfEnumLogfontEx.elfLogFont.lfOrientation = lf.lfOrientation;
mfont->elfEnumLogfontEx.elfLogFont.lfWeight = lf.lfWeight;
mfont->elfEnumLogfontEx.elfLogFont.lfItalic = lf.lfItalic;
mfont->elfEnumLogfontEx.elfLogFont.lfUnderline = lf.lfUnderline;
mfont->elfEnumLogfontEx.elfLogFont.lfStrikeOut = lf.lfStrikeOut;
mfont->elfEnumLogfontEx.elfLogFont.lfCharSet = lf.lfCharSet;
mfont->elfEnumLogfontEx.elfLogFont.lfOutPrecision = 0;
mfont->elfEnumLogfontEx.elfLogFont.lfClipPrecision = 0;
mfont->elfEnumLogfontEx.elfLogFont.lfQuality = 0;
mfont->elfEnumLogfontEx.elfLogFont.lfPitchAndFamily = 0;
StringCchCopy(mfont->elfEnumLogfontEx.elfLogFont.lfFaceName, LF_FACESIZE, lf.lfFaceName);*/
TRACE(L"Font substitutes to \"%s\"\n", lf.lfFaceName);
}
else
TRACE(L"Normal font\n");
//bypass = true;
HFONT hf = ORIG_CreateFontIndirectExW(&mfont);
//ORIG_CreateFontIndirectExW(
//if(hf && lplf && !pSettings->LoadOnDemand()) {
// AddFontToFT(lplf->lfFaceName, lplf->lfWeight, !!lplf->lfItalic);
//}
if (hf && bForced) {
AddToCachedFont(hf, (WCHAR*)penumlfex->elfEnumLogfontEx.elfLogFont.lfFaceName, (WCHAR *)lfOrg.lfFaceName);
}
//bypass = false;
TRACE(L"Create font %s handle %x\n", lfOrg.lfFaceName, (int)hf);
return hf;
}
BOOL WINAPI IMPL_DeleteObject(HGDIOBJ hObject)
{
//CThreadCounter __counter;
if (hObject == g_alterGUIFont) //我的系统字体,不可以释放掉
2016-09-02 17:29:33 +08:00
return true;
BOOL bResult = ORIG_DeleteObject(hObject);
if (bResult) DeleteCachedFont((HFONT)hObject);
return bResult;
}
HFONT WINAPI IMPL_CreateFontIndirectW(CONST LOGFONTW *lplf) //重新启用这个hook只为兼容搜狗输入法
2016-09-02 17:29:33 +08:00
{
ENUMLOGFONTEXDVW envlf = {0};
memcpy(&envlf.elfEnumLogfontEx.elfLogFont, lplf, sizeof(LOGFONTW));
return IMPL_CreateFontIndirectExW(&envlf);
}
/*
BOOL WINAPI IMPL_DrawStateA(HDC hdc, HBRUSH hbr, DRAWSTATEPROC lpOutputFunc, LPARAM lData, WPARAM wData, int x, int y, int cx, int cy, UINT uFlags)
{
//CThreadCounter __counter;
int cchW;
LPWSTR lpStringW;
if(lData && uFlags & DSS_DISABLED) {
switch(uFlags & 0x0f) {
case DST_TEXT:
case DST_PREFIXTEXT:
lpStringW = _StrDupAtoW((LPCSTR)lData, wData ? wData : -1, &cchW);
if(lpStringW) {
BOOL ret = IMPL_DrawStateW(hdc, hbr, lpOutputFunc, (LPARAM)lpStringW, cchW, x, y, cx, cy, uFlags);
free(lpStringW);
return ret;
}
break;
}
}
return ORIG_DrawStateA(hdc, hbr, lpOutputFunc, lData, wData, x, y, cx, cy, uFlags);
}
//灰色描画をDrawTextへ投げる
//DrawTextは内部でExtTextOutしてくれるので問題なし
2016-09-02 17:29:33 +08:00
BOOL WINAPI IMPL_DrawStateW(HDC hdc, HBRUSH hbr, DRAWSTATEPROC lpOutputFunc, LPARAM lData, WPARAM wData, int x, int y, int cx, int cy, UINT uFlags)
{
//CThreadCounter __counter;
if(lData && uFlags & DSS_DISABLED) {
switch(uFlags & 0x0f) {
case DST_TEXT:
case DST_PREFIXTEXT:
{
//wData==0の時に文字数自動計算
//他のAPIと違って-1の時ではない
2016-09-02 17:29:33 +08:00
if(wData == 0) {
wData = wcslen((LPCWSTR)lData);
}
RECT rect = { x, y, x + 10000, y + 10000 };
//どうやら3DHighLightの上に1pxずらして3DShadowを重ねてるらしい
2016-09-02 17:29:33 +08:00
int oldbm = SetBkMode(hdc, TRANSPARENT);
COLORREF oldfg = SetTextColor(hdc, GetSysColor(COLOR_3DHIGHLIGHT));
//DrawStateとDrawTextではprefixのフラグが逆(APIの設計ダメすぎ)
2016-09-02 17:29:33 +08:00
const UINT uDTFlags = DT_SINGLELINE | DT_NOCLIP | (uFlags & DST_PREFIXTEXT ? 0 : DT_NOPREFIX);
OffsetRect(&rect, 1, 1);
DrawTextW(hdc, (LPCWSTR)lData, wData, &rect, uDTFlags);
SetTextColor(hdc, GetSysColor(COLOR_3DSHADOW));
OffsetRect(&rect, -1, -1);
DrawTextW(hdc, (LPCWSTR)lData, wData, &rect, uDTFlags);
SetTextColor(hdc, oldfg);
SetBkMode(hdc, oldbm);
}
return TRUE;
}
}
return ORIG_DrawStateW(hdc, hbr, lpOutputFunc, lData, wData, x, y, cx, cy, uFlags);
}*/
class FreeTypeFontEngine;
extern FreeTypeFontEngine* g_pFTEngine;
BOOL __stdcall IMPL_RemoveFontResourceExW(__in LPCWSTR name, __in DWORD fl, __reserved PVOID pdv)
{
g_pFTEngine->RemoveFont(name);
return ORIG_RemoveFontResourceExW(name, fl, pdv);
}
/*
BOOL __stdcall IMPL_RemoveFontResourceW(__in LPCWSTR lpFileName)
{
g_pFTEngine->RemoveFont(lpFileName);
return ORIG_RemoveFontResourceW(lpFileName);
}*/
BOOL WINAPI IMPL_TextOutA(HDC hdc, int nXStart, int nYStart, LPCSTR lpString, int cbString)
{
//CThreadCounter __counter;
return IMPL_ExtTextOutA(hdc, nXStart, nYStart, NULL, NULL, lpString, cbString, NULL);
}
BOOL WINAPI IMPL_TextOutW(HDC hdc, int nXStart, int nYStart, LPCWSTR lpString, int cbString)
{
//CThreadCounter __counter;
return IMPL_ExtTextOutW(hdc, nXStart, nYStart, NULL, NULL, lpString, cbString, NULL);
}
void AnsiDxToUnicodeDx(LPCSTR lpStringA, int cbString, const int* lpDxA, int* lpDxW, int ACP)
{
LPCSTR lpEndA = lpStringA + cbString;
while(lpStringA < lpEndA) {
*lpDxW = *lpDxA++;
if(IsDBCSLeadByteEx(ACP, *lpStringA)) {
*lpDxW += *lpDxA++;
lpStringA++;
}
lpDxW++;
lpStringA++;
}
}
// ANSI->Unicodeに変換してExtTextOutWに投げるExtTextOutA
2016-09-02 17:29:33 +08:00
BOOL WINAPI IMPL_ExtTextOutA(HDC hdc, int nXStart, int nYStart, UINT fuOptions, CONST RECT *lprc, LPCSTR lpString, UINT cbString, CONST INT *lpDx)
{
//CThreadCounter __counter;
if (!hdc || !lpString || !cbString || !g_ccbRender || !(fuOptions & ETO_IGNORELANGUAGE)) {
return ORIG_ExtTextOutA(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);
}
//However, if the ANSI version of ExtTextOut is called with ETO_GLYPH_INDEX,
//the function returns TRUE even though the function does nothing.
//とりあえずオリジナルに飛ばす
2016-09-02 17:29:33 +08:00
if (fuOptions & ETO_GLYPH_INDEX)
return ORIG_ExtTextOutA(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);
//HDBENCHチート
2016-09-02 17:29:33 +08:00
// if (lpString && cbString == 7 && pSettings->IsHDBench() && (memcmp(lpString, "HDBENCH", 7) == 0 || memcmp(lpString, " ", 7) == 0))
// return ORIG_ExtTextOutA(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);
LPWSTR lpszUnicode;
int bufferLength;
BOOL result;
WCHAR szStack[CCH_MAX_STACK];
int dxStack[CCH_MAX_STACK];
int nACP = GdiGetCodePage(hdc);//CP_ACP;
//DWORD nCharset = GetTextCharsetInfo(hdc, NULL, 0);
/*
switch (nCharset)
{
case 0:
{
break;
}
case SYMBOL_CHARSET:
{
nACP = CP_SYMBOL;
break;
}
case MAC_CHARSET:
{
nACP = CP_MACCP;
break;
}
case OEM_CHARSET:
{
nACP = CP_OEMCP;
break;
}
default:
{
CHARSETINFO Cs={0,CP_ACP,0};
TranslateCharsetInfo((DWORD*)nCharset, &Cs, TCI_SRCCHARSET);
nACP = Cs.ciACP;
}
}*/
lpszUnicode = _StrDupExAtoW(lpString, cbString, szStack, CCH_MAX_STACK, &bufferLength, nACP);
if(!lpszUnicode) {
//メモリ不足: 一応オリジナルに投げとく
2016-09-02 17:29:33 +08:00
return ORIG_ExtTextOutA(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);
}
int* lpDxW = NULL;
result = FALSE;
if(lpDx && cbString && _getmbcp()) {
if (cbString < CCH_MAX_STACK) {
lpDxW = dxStack;
ZeroMemory(lpDxW, sizeof(int) * cbString);
} else {
lpDxW = (int*)calloc(sizeof(int), cbString);
if (!lpDxW) {
goto CleanUp;
}
}
if (nACP!=CP_SYMBOL)
{
AnsiDxToUnicodeDx(lpString, cbString, lpDx, lpDxW, nACP);
lpDx = lpDxW;
}
}
result = IMPL_ExtTextOutW(hdc, nXStart, nYStart, fuOptions, lprc, (LPCWSTR)lpszUnicode, bufferLength, lpDx);
CleanUp:
if (lpszUnicode != szStack)
free(lpszUnicode);
if (lpDxW != dxStack)
free(lpDxW);
return result;
}
typedef enum {
ETOE_OK = 0,
ETOE_CREATEDC = 1,
ETOE_SETFONT = 2,
ETOE_CREATEDIB = 3,
ETOE_FREETYPE = 4,
ETOE_INVALIDARG = 11,
ETOE_ROTATION = 12,
ETOE_LARGESIZE = 13,
ETOE_INVALIDHDC = 14,
ETOE_ROTATEFONT = 15,
ETOE_NOAREA = 16,
ETOE_GETTEXTEXTENT = 17,
ETOE_MONO = 18,
ETOE_GENERAL = 19,
} ExtTextOut_ErrorCode;
//例外モドキ
2016-09-02 17:29:33 +08:00
#define ETO_TRY() ExtTextOut_ErrorCode error = ETOE_OK; {
#define ETO_THROW(code) error = (code); goto _EXCEPTION_THRU
#define ETO_CATCH() } _EXCEPTION_THRU:
/*
BOOL FreeTypeGetTextExtentPoint(HDC hdc, LPCSTR lpString, int cbString, LPSIZE lpSize, const FREETYPE_PARAMS* params)
{
WCHAR szStack[CCH_MAX_STACK];
int cchStringW;
LPWSTR lpStringW = _StrDupExAtoW(lpString, cbString, szStack, CCH_MAX_STACK, &cchStringW);
if(!lpStringW) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
BOOL ret = FreeTypeGetTextExtentPoint(hdc, lpStringW, cchStringW, lpSize, params);
if (lpStringW != szStack)
free(lpStringW);
return ret;
}*/
class CETOBitmap
{
private:
CBitmapCache& m_cache;
HDC m_hdc;
HBITMAP m_hPrevBmp;
HBITMAP m_hBmp;
BYTE* m_lpPixels;
public:
CETOBitmap(CBitmapCache& cache)
: m_cache(cache)
, m_hdc(NULL)
, m_hPrevBmp(NULL)
, m_hBmp(NULL)
, m_lpPixels(NULL)
{
}
HDC CreateDC(HDC dc)
{
m_hdc = m_cache.CreateDC(dc);
return m_hdc;
}
bool CreateDIBandSelect(int cx, int cy)
{
m_hBmp = m_cache.CreateDIB(cx, cy, &m_lpPixels);
if (!m_hBmp) {
return false;
}
m_hPrevBmp = SelectBitmap(m_hdc, m_hBmp);
return true;
}
void RestoreBitmap()
{
if (m_hPrevBmp) {
SelectBitmap(m_hdc, m_hPrevBmp);
m_hPrevBmp = NULL;
}
}
};
extern ControlIder CID;
// 取代Windows的ExtTextOutW
BOOL WINAPI IMPL_ExtTextOutW(HDC hdc, int nXStart, int nYStart, UINT fuOptions, CONST RECT *lprc, LPCWSTR lpString, UINT cbString, CONST INT *SyslpDx)
2016-09-02 17:29:33 +08:00
{
//CThreadCounter __counter; //用于安全退出的计数器
INT* lpDx = const_cast<INT*>(SyslpDx);
if (!hdc || !lpString || !cbString || !g_ccbRender || cbString>8192) { //no valid param or rendering is disabled from control center.
2016-09-02 17:29:33 +08:00
return ORIG_ExtTextOutW(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);
}
if (!(fuOptions & ETO_GLYPH_INDEX) && cbString==1 && *lpString==32) //空格
return ORIG_ExtTextOutW(hdc, nXStart, nYStart, fuOptions | ETO_IGNORELANGUAGE, lprc, lpString, cbString, lpDx); //空格就不用处理了。。。反正都一样
2016-09-02 17:29:33 +08:00
CThreadLocalInfo* pTLInfo = g_TLInfo.GetPtr();
if(!pTLInfo) {
return ORIG_ExtTextOutW(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);
}
if (DCArray.find(hdc)!=DCArray.end())
return ORIG_ExtTextOutW(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);
CAutoVectorPtr<INT> newdx;
if (!lpDx) {
newdx.Allocate(cbString);
SIZE p = { 0 };
BOOL r = false;
if (fuOptions & ETO_GLYPH_INDEX)
r = GetTextExtentExPointI(hdc, (LPWORD)lpString, cbString, 0, NULL, newdx, &p);
else
r = GetTextExtentExPointW(hdc, lpString, cbString, 0, NULL, newdx, &p);
if (r) {
for (int i = cbString - 1; i > 0; --i) {
newdx[i] -= newdx[i - 1];
}
lpDx = newdx;
}
else{
newdx.Free();
}
}
2016-09-02 17:29:33 +08:00
if (!(fuOptions & ETO_GLYPH_INDEX) && !(fuOptions & ETO_IGNORELANGUAGE) && !lpDx && CID.myiscomplexscript(lpString,cbString)) //complex script
return ORIG_ExtTextOutW(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);
CGdippSettings* pSettings = CGdippSettings::GetInstance(); //获得一个配置文件实例
2016-09-02 17:29:33 +08:00
/*
#ifndef _DEBUG //debug模式下此参数有问题
2016-09-02 17:29:33 +08:00
if (pSettings->FontLoader()==SETTING_FONTLOADER_WIN32)
{
if (!(fuOptions & ETO_GLYPH_INDEX) //复杂文件,不进行渲染
2016-09-02 17:29:33 +08:00
&& !(fuOptions & ETO_IGNORELANGUAGE) && ScriptIsComplex(lpString, cbString, SIC_COMPLEX) == S_OK) {
return ORIG_ExtTextOutW(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);
}
}
else
if (!(fuOptions & ETO_GLYPH_INDEX) && / *iswcntrl(lpString[0])* /CID.myiswcntrl(lpString[0])) {
return ORIG_ExtTextOutW(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);
}
#endif
*/
if (pTLInfo->InExtTextOut()) { //是异常之后的自动还原执行
2016-09-02 17:29:33 +08:00
return ORIG_ExtTextOutW(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);
}
XFORM xfm;
static XFORM stdXfm = {1.0,0,0,1.0,0,0};
bool bZoomedDC = false;
CDCTransformer* DCTrans = NULL;
if (GetTransform)
{
GetTransform(hdc, GT_WORLD_TO_DEVICE, &xfm);
if (memcmp(&xfm, &stdXfm, sizeof(XFORM)-sizeof(FLOAT)*2)) //(xfm.eM11!=1.0 || xfm.eM22!=1.0) //如果存在坐标转换
2016-09-02 17:29:33 +08:00
{
bool bZoomInOut = (xfm.eM12==0 && xfm.eM21==0 && xfm.eM11>0 && xfm.eM22>0); //只是缩放,且是正数缩放
2016-09-02 17:29:33 +08:00
if (!bZoomInOut)
return ORIG_ExtTextOutW(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx); //放弃渲染
2016-09-02 17:29:33 +08:00
else
{
bZoomedDC = true;
DCTrans = new CDCTransformer;
DCTrans->init(xfm);
}
}
}
/*
int mm = GetMapMode(hdc);
if (mm!=MM_TEXT)
{
SIZE size;
GetWindowExtEx(hdc, &size);
if (size.cx!=1 || size.cy!=1)
return ORIG_ExtTextOutW(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);
}
if (GetGraphicsMode(hdc)==GM_ADVANCED)
{
XFORM xfm;
GetWorldTransform(hdc, &xfm);
if (xfm.eM11!=1.0 || xfm.eM22!=1.0)
return ORIG_ExtTextOutW(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);
}*/
//if (GetROP2(hdc)!=13)
// return ORIG_ExtTextOutW(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);
//if (GetStretchBltMode(hdc)!=BLACKONWHITE)
// return ORIG_ExtTextOutW(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);
/*
SIZE size;
if (fuOptions & ETO_GLYPH_INDEX)
GetTextExtentPointI(hdc,(LPWORD)lpString, cbString,&size);
else
GetTextExtentPoint(hdc, lpString, cbString, &size);
if (!size.cx)
return ORIG_ExtTextOutW(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);*/
COwnedCriticalSectionLock __lock2(1, COwnedCriticalSectionLock::OCS_DC); //获取所有权,防止冲突
2016-09-02 17:29:33 +08:00
CBitmapCache& cache = pTLInfo->BitmapCache();
CETOBitmap bmp(cache);
HDC hCanvasDC = NULL;
HFONT hPrevFont = NULL;
HFONT hMyCurFont = NULL;
HFONT hZoomedFont = NULL, hOldMDCFont = NULL;
BOOL bForceFont = false;
int * outlpDx = NULL;
FT_Referenced_Glyph* GlyphArray = new FT_Referenced_Glyph[cbString];
FT_DRAW_STATE* ftDrawState = new FT_DRAW_STATE[cbString];
memset(GlyphArray, 0, sizeof(FT_Referenced_Glyph)*cbString);
memset(ftDrawState, 0, sizeof(FT_DRAW_STATE)*cbString);
OUTLINETEXTMETRIC* otm = NULL;
ETO_TRY();
//设置标志,
2016-09-02 17:29:33 +08:00
pTLInfo->InExtTextOut(true);
POINT curPos = { nXStart, nYStart }; //记录开始的位置
2016-09-02 17:29:33 +08:00
POINT destPos;
SIZE drawSize;
HFONT hCurFont = NULL;
BOOL bShadow = FALSE;
UINT align;
SIZE textSize;
SIZE realSize = { 0 };
2020-04-13 11:23:59 +08:00
//================ Is valid DC? =====================
2016-09-02 17:29:33 +08:00
if (!IsValidDC(hdc)) {
ETO_THROW(ETOE_INVALIDHDC); // hdc is invalid
}
int nSize=GetOutlineTextMetrics(hdc, 0, NULL);
if (!nSize) {
//nSize = sizeof(OUTLINETEXTMETRIC);
ETO_THROW(ETOE_INVALIDHDC);
} //耗时50-100ms
2016-09-02 17:29:33 +08:00
otm = (OUTLINETEXTMETRIC*)malloc(nSize);
memset(otm, 0, nSize);
otm->otmSize = nSize;
TEXTMETRIC& tm = otm->otmTextMetrics;
LOGFONT lf = { 0 };
wstring strFamilyName;
GetOutlineTextMetrics(hdc, nSize, otm);
2020-04-13 11:23:59 +08:00
strFamilyName = (LPWSTR)((DWORD_PTR)otm+(DWORD_PTR)otm->otmpFamilyName); //Get TTF font info
2016-09-02 17:29:33 +08:00
const bool bVertical = pSettings->FontLoader()==SETTING_FONTLOADER_FREETYPE? strFamilyName.c_str()[0]==L'@' :false;
int nFontHeight = bZoomedDC ? DCTrans->TransformYAB(tm.tmHeight) : tm.tmHeight;
if ((pSettings->MaxHeight() && nFontHeight > pSettings->MaxHeight()) || (pSettings->MinHeight() && nFontHeight < pSettings->MinHeight())) {
ETO_THROW(ETOE_INVALIDHDC); //Font size too small or too big.
2016-09-02 17:29:33 +08:00
}
2020-04-13 11:23:59 +08:00
if (pSettings->IsFontExcluded(strFamilyName.c_str())) { // check if it's excluded
2016-09-02 17:29:33 +08:00
ETO_THROW(ETOE_INVALIDHDC);
} //20-50ms
// check pitch to make sure it's truetype or opentype
if ((otm->otmTextMetrics.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)) == 0) { //opentype (collection) sets the vector bit, truetype sets the truetype bit
pSettings->AddFontExclude(strFamilyName.c_str());
ETO_THROW(ETOE_INVALIDHDC); // set the font as an exclusion and exit
}
2016-09-02 17:29:33 +08:00
//====================end================================
hCanvasDC = bmp.CreateDC(hdc);
if(!hCanvasDC) {
ETO_THROW(ETOE_CREATEDC);
} //0ms
2020-04-13 11:23:59 +08:00
align = GetTextAlign(hdc); // Get align
2016-09-02 17:29:33 +08:00
//if (pTLInfo->InUniscribe() && !(fuOptions & ETO_IGNORELANGUAGE))
// align &= ~TA_UPDATECP;
if(align & TA_UPDATECP) {
GetCurrentPositionEx(hdc, &curPos);
}
/*
if (!align && lpDx && !fuOptions) //optimized
{
// ETO_THROW(ETOE_FREETYPE);
}//0ms*/
2020-04-13 11:23:59 +08:00
hCurFont = GetCurrentFont(hdc); // get font name of current DC, warning: the font name is potaintially incorrect.
if (!hCurFont) { // failed
2016-09-02 17:29:33 +08:00
ETO_THROW(ETOE_SETFONT);
}
TRACE(L"Draw text \"%s\", font=\"%s\", handle=%x\n", lpString, strFamilyName.c_str(), (int)hCurFont);
if (!ORIG_GetObjectW(hCurFont, sizeof(LOGFONT), &lf)) {
ETO_THROW(ETOE_SETFONT);
}//30ms
2020-04-13 11:23:59 +08:00
StringCchCopy(lf.lfFaceName, LF_FACESIZE, (LPWSTR)((DWORD_PTR)otm+(DWORD_PTR)otm->otmpFamilyName)); // copy the correct font name from otm info to lf
2016-09-02 17:29:33 +08:00
if (lf.lfEscapement != 0) {
ETO_THROW(ETOE_ROTATEFONT);// rotated font
}
hPrevFont = SelectFont(hCanvasDC, hCurFont);
if (!hPrevFont)
{
hMyCurFont = CreateFontIndirect(&lf);
hPrevFont = SelectFont(hCanvasDC, hMyCurFont);
}
if (lf.lfHeight >= 0) {
2020-04-13 11:23:59 +08:00
// use height from tm if not specified in lf
2016-09-02 17:29:33 +08:00
lf.lfHeight = -(tm.tmHeight-tm.tmInternalLeading); //optimized
}
if (bZoomedDC)
{
//DCTrans->SetSourceOffset(curPos.x, curPos.y);
curPos.x = DCTrans->TransformXAB(curPos.x);
curPos.y = DCTrans->TransformYAB(curPos.y);
lf.lfHeight = DCTrans->TransformYAB(lf.lfHeight);
lf.lfWidth = DCTrans->TransformXAB(lf.lfWidth);
tm.tmHeight = abs(DCTrans->TransformYAB(tm.tmHeight));
tm.tmInternalLeading = abs(DCTrans->TransformYAB(tm.tmInternalLeading));
tm.tmAscent = DCTrans->TransformYAB(tm.tmAscent);
tm.tmDescent = DCTrans->TransformYAB(tm.tmDescent);
tm.tmAveCharWidth = DCTrans->TransformXAB(tm.tmAveCharWidth);
// if (!DCTrans->TransformMode() && !lf.lfWidth && DCTrans->MirrorX())
// lf.lfWidth = tm.tmAveCharWidth;
2020-04-13 11:23:59 +08:00
if (lpDx && cbString) //firefox uses coord Y of ETO_PDY to print vertical text
2016-09-02 17:29:33 +08:00
{
int szDx=fuOptions&ETO_PDY ? cbString*2:cbString;
2016-09-02 17:29:33 +08:00
outlpDx = new int[szDx];
DCTrans->TransformlpDx(lpDx, outlpDx, szDx); //lpDx has a size of cbString -1
2016-09-02 17:29:33 +08:00
}
}
FREETYPE_PARAMS params(fuOptions & ~ETO_OPAQUE, hdc, &lf, otm);
2016-09-02 17:29:33 +08:00
if (bZoomedDC)
params.charExtra = DCTrans->TransformXAB(params.charExtra);
SetTextCharacterExtra(hCanvasDC, params.charExtra);
BITMAP bm;
HBITMAP hbmpSrc = (HBITMAP)GetCurrentObject(hdc, OBJ_BITMAP);
if(hbmpSrc && ORIG_GetObjectW(hbmpSrc, sizeof(BITMAP), &bm) && bm.bmBitsPixel <= 16) {
2020-04-13 11:23:59 +08:00
ETO_THROW(ETOE_MONO); // ignore monochrome font, since freetype has really bad support of it.
2016-09-02 17:29:33 +08:00
//params.ftOptions |= FTO_MONO;
}
if(!params.IsMono() && pSettings->EnableShadow()) {
bShadow = true;
}
int xs = 0, ys=0;
if (bShadow) {
const int* shadow = pSettings->GetShadowParams();
xs = shadow[0], ys = shadow[1];
params.alpha = shadow[2] | shadow[3];
}
else
params.alpha = 1;
int width=0;
FreeTypeDrawInfo FTInfo(params, bZoomedDC ? hCanvasDC : hdc, (LOGFONT*)&lf, &cache, bZoomedDC ? outlpDx : lpDx, cbString, xs, ys);
lf.lfQuality = 0; //magic number means this is a non scaled font;
if (lf.lfWidth)
++lf.lfQuality;
if (bZoomedDC)
{
hZoomedFont = CreateFontIndirect(&lf);
if (!DCTrans->TransformMode() || lf.lfWidth)
++lf.lfQuality; //scaled font
hOldMDCFont = SelectFont(hCanvasDC, hZoomedFont);
SetGraphicsMode(hCanvasDC, GM_ADVANCED);
}
if (!FreeTypeGetGlyph(FTInfo, lpString, cbString, width, GlyphArray, ftDrawState))
{
ETO_THROW(ETOE_FREETYPE);
}
2020-04-13 11:23:59 +08:00
if (FTInfo.xBase<0) // Change start position if diacritics are found
2016-09-02 17:29:33 +08:00
{
2020-04-13 11:23:59 +08:00
width-=FTInfo.xBase; // increase width
FTInfo.x -= FTInfo.xBase; // increase width for cursor
curPos.x+=FTInfo.xBase; // change cursor position
2016-09-02 17:29:33 +08:00
for (int i=0;i<cbString;++i)
2020-04-13 11:23:59 +08:00
FTInfo.Dx[i]-=FTInfo.xBase; // modify the start position of painting
2016-09-02 17:29:33 +08:00
}
/*if (bZoomedDC && DCTrans->MirrorX()) //左右反向RGB和BGR要相反
2016-09-02 17:29:33 +08:00
for (int i=0; i<cbString; ++i)
{
switch (FTInfo.AAModes[i])
{
case 2:
FTInfo.AAModes[i] = 3;
break;
case 3:
FTInfo.AAModes[i] = 2;
break;
case 4:
FTInfo.AAModes[i] = 5;
break;
case 5:
FTInfo.AAModes[i] = 4;
break;
}
}*/
//POINT destSize; //LP下的大小和起始位置
2016-09-02 17:29:33 +08:00
/*
if (bZoomedDC)
{
if (hOldMDCFont)
{
SelectFont(hCanvasDC, hOldMDCFont);
DeleteFont(hZoomedFont);
hZoomedFont = NULL;
hOldMDCFont = NULL;
}
}*/
textSize.cx = width;
textSize.cy = FTInfo.y + tm.tmHeight;
realSize.cx = FTInfo.x;
realSize.cy = FTInfo.y + tm.tmHeight;
//******************
{
RECT rc = { 0 };
const UINT horiz = align & (TA_LEFT|TA_RIGHT|TA_CENTER);
const UINT vert = align & (TA_BASELINE|TA_TOP|TA_BOTTOM);
switch (horiz) {
case TA_CENTER:
rc.left = curPos.x - div_ceil(textSize.cx, 2);
rc.right = curPos.x + div_ceil(textSize.cx, 2);
//no move
break;
case TA_RIGHT:
rc.left = curPos.x - textSize.cx;
rc.right = curPos.x;
curPos.x -= realSize.cx;//move pos
break;
default:
rc.left = curPos.x;
rc.right = curPos.x + textSize.cx;
curPos.x += realSize.cx;//move pos
break;
}
switch (vert) {
case TA_BASELINE:
rc.top = curPos.y - tm.tmAscent;
rc.bottom = curPos.y + tm.tmDescent + FTInfo.y;
//trace(L"ascent=%d descent=%d\n", metric.tmAscent, metric.tmDescent);
break;
case TA_BOTTOM:
rc.top = curPos.y - textSize.cy;
rc.bottom = curPos.y;
break;
default:
rc.top = curPos.y;
rc.bottom = curPos.y + textSize.cy;
break;
}
//rc.bottom++;
destPos.x = rc.left;
destPos.y = rc.top;
drawSize.cx = textSize.cx;
drawSize.cy = rc.bottom - rc.top;
}
//trace(L"MovedCursor=%d %d\n", curPos.x, curPos.y);
//trace(L"TargetRect=%d %d %d %d\n", rc.left, rc.top, rc.right, rc.bottom);
//trace(L"DestPos=%dx%d Size=%dx%d\n", destPos.x, destPos.y, destSize.cx, destSize.cy);
//trace(L"CanvasPos=%dx%d Size=%dx%d\n", canvasPos.x, canvasPos.y, canvasSize.cx, canvasSize.cy);
if(drawSize.cx < 1 || drawSize.cy < 1) {
ETO_THROW(ETOE_NOAREA); //throw no area
}
//drawSize.cx += tm.tmMaxCharWidth; //加上一个最大字体宽度
2016-09-02 17:29:33 +08:00
//bitmap
if (!bmp.CreateDIBandSelect(drawSize.cx+4, drawSize.cy+4)) {
ETO_THROW(ETOE_CREATEDIB);
}
int xorg=0, yorg=0;
if (lprc && (fuOptions & ETO_CLIPPED)) {
const RECT rcBlt = { destPos.x, destPos.y, destPos.x + drawSize.cx, destPos.y + drawSize.cy };
RECT rcClip = { 0 };
if (bZoomedDC)
{
RECT rcTrans;
DCTrans->TransformRectAB(lprc, &rcTrans);
IntersectRect(&rcClip, &rcBlt, &rcTrans);
}
else
IntersectRect(&rcClip, &rcBlt, lprc);
xorg = rcClip.left-destPos.x; //计算偏移
2016-09-02 17:29:33 +08:00
yorg = rcClip.top-destPos.y;
destPos.x = rcClip.left;
destPos.y = rcClip.top;
drawSize.cx = rcClip.right-rcClip.left;
drawSize.cy = rcClip.bottom-rcClip.top;
}
{
const BOOL fillrect = (lprc && (fuOptions & ETO_OPAQUE));
//clear bitmap
if(fillrect || GetBkMode(hdc) == OPAQUE) {
COLORREF bgcolor = GetBkColor(hdc); //両方とも同じ背景色に
2016-09-02 17:29:33 +08:00
//if ((bgcolor>>24)%2 || (bgcolor>>28)%2)
// bgcolor = 0;
if ((bgcolor>>24)%2 || (bgcolor>>28)%2)
bgcolor = GetPaletteColor(hdc, bgcolor);
SetBkMode(hCanvasDC, OPAQUE);
SetBkColor(hCanvasDC, bgcolor);
RECT rc = { xorg, yorg, drawSize.cx+ xorg, drawSize.cy+ yorg };
if (bZoomedDC)
{
rc.right+=2;
rc.bottom+=2;
}
cache.FillSolidRect(bgcolor, &rc);
if(fillrect) {
//FillRect(hdc, lprc, (HBRUSH)GetCurrentObject(hdc, OBJ_BRUSH));
ORIG_ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, lprc, NULL, 0, NULL);
}
}
else
{
if (!bZoomedDC)
{
if (!(BitBlt(hCanvasDC, xorg, yorg, drawSize.cx, drawSize.cy, hdc, destPos.x, destPos.y, SRCCOPY)))
{
ETO_THROW(ETOE_FREETYPE);
}
}
else
{
SetWorldTransform(hCanvasDC, DCTrans->GetTransform());
if (!(BitBlt(hCanvasDC, DCTrans->TransformXCoordinateBA(xorg), DCTrans->TransformYCoordinateBA(yorg),
DCTrans->TransformXCoordinateBA(drawSize.cx+4), DCTrans->TransformYCoordinateBA(drawSize.cy+4), hdc,
DCTrans->TransformXCoordinateBA(destPos.x), DCTrans->TransformYCoordinateBA(destPos.y), SRCCOPY)))
{
SetWorldTransform(hCanvasDC, &stdXfm);
ETO_THROW(ETOE_FREETYPE);
}
SetWorldTransform(hCanvasDC, &stdXfm);
}
}
}
//setup
SetTextAlign(hCanvasDC, TA_LEFT | TA_TOP);
//debug
//Dbg_TraceExtTextOutW(nXStart, nYStart, fuOptions, lpString, cbString, lpDx);
//textout
SetTextColor(hCanvasDC, FTInfo.params->color);
SetBkMode(hCanvasDC, TRANSPARENT);
FTInfo.hdc = hCanvasDC;
if (!FreeTypeTextOut(hCanvasDC, cache, lpString, cbString, FTInfo, GlyphArray, ftDrawState)) {
ETO_THROW(ETOE_FREETYPE);
}
//blt + clipping
/*
if(lprc && (fuOptions & ETO_CLIPPED)) {
//TRACE(_T("ClipRect={%d %d %d %d}, pos = (%d,%d)\n"), lprc->left, lprc->top, lprc->right, lprc->bottom,
// nXStart, nYStart);
//trace(L"ClipRect=%d %d %d %d\n", lprc->left, lprc->top, lprc->right, lprc->bottom);
const RECT rcBlt = { destPos.x, destPos.y, destPos.x + drawSize.cx, destPos.y + drawSize.cy };
RECT rcClip = { 0 };
IntersectRect(&rcClip, &rcBlt, lprc);
BitBlt(hdc, rcClip.left, rcClip.top, rcClip.right - rcClip.left, rcClip.bottom - rcClip.top,
hCanvasDC, rcClip.left - rcBlt.left, rcClip.top - rcBlt.top, SRCCOPY);
} else {*/
if (!bZoomedDC)
BitBlt(hdc, destPos.x, destPos.y, drawSize.cx, drawSize.cy, hCanvasDC, xorg, yorg, SRCCOPY);
else
{
SetWorldTransform(hCanvasDC, DCTrans->GetTransform());
BitBlt(hdc, DCTrans->TransformXCoordinateBA(destPos.x), DCTrans->TransformYCoordinateBA(destPos.y),
DCTrans->TransformXCoordinateBA(drawSize.cx), DCTrans->TransformYCoordinateBA(drawSize.cy), hCanvasDC,
DCTrans->TransformXCoordinateBA(xorg), DCTrans->TransformYCoordinateBA(yorg), SRCCOPY);
SetWorldTransform(hCanvasDC, &stdXfm);
}
//}
//GdiFlush();
if(align & TA_UPDATECP) {
if (!bZoomedDC)
MoveToEx(hdc, curPos.x, curPos.y, NULL);
else
MoveToEx(hdc, DCTrans->TransformXCoordinateBA(curPos.x), DCTrans->TransformYCoordinateBA(curPos.y), NULL);
}
ETO_CATCH();
if (otm)
free(otm);
bmp.RestoreBitmap();
if (hOldMDCFont)
{
SelectFont(hCanvasDC, hOldMDCFont);
DeleteFont(hZoomedFont);
hZoomedFont = NULL;
hOldMDCFont = NULL;
}
if(hPrevFont) {
SelectFont(hCanvasDC, hPrevFont);
}
if (hMyCurFont)
DeleteFont(hMyCurFont);
{
//CCriticalSectionLock __lock;
for (UINT i=0;i<cbString;i++)
{
if (GlyphArray[i])
{
FT_Done_Ref_Glyph(&GlyphArray[i]);
}
}
}
delete[] GlyphArray;
delete[] ftDrawState;
if (DCTrans)
delete DCTrans;
if (outlpDx)
delete[] outlpDx;
if(error == ETOE_OK) {
pTLInfo->InExtTextOut(false);
return TRUE;
}
int ret = ORIG_ExtTextOutW(hdc, nXStart, nYStart, fuOptions, lprc, lpString, cbString, lpDx);
pTLInfo->InExtTextOut(false);
return ret;
}
BOOL WINAPI IMPL_MySetProcessMitigationPolicy(
_In_ PROCESS_MITIGATION_POLICY MitigationPolicy,
_In_ PVOID lpBuffer,
2016-09-02 17:29:33 +08:00
_In_ SIZE_T dwLength
)
{
if (MitigationPolicy == ProcessDynamicCodePolicy) {
PPROCESS_MITIGATION_DYNAMIC_CODE_POLICY(lpBuffer)->ProhibitDynamicCode = false;
}
return ORIG_MySetProcessMitigationPolicy(MitigationPolicy, lpBuffer, dwLength);
}
//HFONT dummy=NULL;
/*
int WINAPI IMPL_GdipCreateFontFamilyFromName(const WCHAR *name, void *fontCollection, void **FontFamily)
{
LOGFONT lf={};
memset(&lf, 0, sizeof lf);
StringCchCopy(lf.lfFaceName, LF_FACESIZE, name);
const CGdippSettings* pSettings = CGdippSettings::GetInstance();
if (pSettings->CopyForceFont(lf, lf))
{
//dummy = CreateFont(1,0,0,0,0,0,0,0,DEFAULT_CHARSET,0,0,0,0,lf.lfFaceName);
return ORIG_GdipCreateFontFamilyFromName(lf.lfFaceName, fontCollection, FontFamily);
}
return ORIG_GdipCreateFontFamilyFromName(name, fontCollection, FontFamily);
}*/
DWORD WINAPI IMPL_GetFontData(_In_ HDC hdc,
_In_ DWORD dwTable,
_In_ DWORD dwOffset,
_Out_writes_bytes_to_opt_(cjBuffer, return) PVOID pvBuffer,
_In_ DWORD cjBuffer
2016-09-02 17:29:33 +08:00
) {
if (dwTable != 0x656d616e) // we only simulate the name table, for other tables, use the substituted font data
return ORIG_GetFontData(hdc, dwTable, dwOffset, pvBuffer, cjBuffer);
DWORD ret = GDI_ERROR;
ENUMLOGFONTEXDVW envlf = { 0 };
HFONT hCurFont = GetCurrentFont(hdc);
if (GetCachedFontLocale(hCurFont) && GetObjectW(hCurFont, sizeof(LOGFONT), &envlf.elfEnumLogfontEx.elfLogFont)) {// call hooked version of GetObject to retrieve font info that the app originally want to create
HDC memdc = CreateCompatibleDC(hdc);
HFONT hRealFont = ORIG_CreateFontIndirectExW(&envlf); // create memorydc and a real font so that we can run GetFontData on it
if (hRealFont) {
HFONT hOldFont = SelectFont(memdc, hRealFont);
ret = ORIG_GetFontData(memdc, dwTable, dwOffset, pvBuffer, cjBuffer); // get font data from the real font
SelectFont(memdc, hOldFont);
DeleteFont(hRealFont);
}
DeleteDC(memdc);
2016-09-02 17:29:33 +08:00
}
if (ret == GDI_ERROR) // any of the above operations failed or the font is not substituted
ret = ORIG_GetFontData(hdc, dwTable, dwOffset, pvBuffer, cjBuffer); // fallback to original
return ret;
2016-09-02 17:29:33 +08:00
}
//EOF