2020-12-06 18:38:08 +08:00
// 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 ) {
2020-12-06 18:38:08 +08:00
// NULLの場合はSystemを設定しておく
2016-09-02 17:29:33 +08:00
hCurFont = ( HFONT ) GetStockObject ( SYSTEM_FONT ) ;
}
return hCurFont ;
}
2020-12-06 17:00:05 +08:00
//判断是否是有效普通显示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 ;
}
2020-12-06 18:38:08 +08:00
//切り上げ除算
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 ;
}
2020-12-06 17:00:05 +08:00
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 )
2020-12-06 17:00:05 +08:00
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 ) ;
} */
2017-03-23 10:18:56 +08:00
/*
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 ) ;
2017-03-23 10:18:56 +08:00
} */
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 )
{
2020-12-06 17:00:05 +08:00
if ( ! lfont ) return ; //不可以添加空节点
2016-09-02 17:29:33 +08:00
CCriticalSectionLock __lock ( CCriticalSectionLock : : CS_CACHEDFONT ) ;
2020-12-06 17:00:05 +08:00
if ( GetCachedFont ( lfont ) ) return ; //已经存在的字体
2016-09-02 17:29:33 +08:00
FontCache [ lfont ] = new CFontSubResult ( lpFaceName , lpGDIName ) ;
}
void DeleteCachedFont ( HFONT lfont )
{
2020-12-06 17:00:05 +08:00
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 ) ;
}
}
2016-09-08 13:45:52 +08:00
int WINAPI IMPL_GetTextFaceAliasW ( HDC hdc , int nLen , LPWSTR lpAliasW )
2016-09-02 17:29:33 +08:00
{
//CThreadCounter __counter;
2016-09-08 13:45:52 +08:00
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 ) {
2019-05-21 10:50:40 +08:00
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;
2018-04-13 14:05:08 +08:00
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 ;
2018-04-13 14:05:08 +08:00
lpgm - > gmptGlyphOrigin . y + = nDeltaY ;
2018-09-08 21:31:48 +08:00
/*if (lpgm->gmptGlyphOrigin.x > 0)
2018-08-02 11:07:50 +08:00
lpgm - > gmBlackBoxX + = n ; // increase blackbox width if it's not a ligature
if ( lpgm - > gmBlackBoxX > tm . tmMaxCharWidth ) {
lpgm - > gmBlackBoxX = tm . tmMaxCharWidth ;
2018-09-08 21:31:48 +08:00
} */
2018-04-13 14:05:08 +08:00
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 ) ) ) {
2018-04-13 14:05:08 +08:00
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 ;
2018-09-08 21:31:48 +08:00
/*if (lpgm->gmptGlyphOrigin.x > 0)
2018-08-02 11:07:50 +08:00
lpgm - > gmBlackBoxX + = n ; // increase blackbox width if it's not a ligature
if ( lpgm - > gmBlackBoxX > tm . tmMaxCharWidth ) {
lpgm - > gmBlackBoxX = tm . tmMaxCharWidth ;
2018-09-08 21:31:48 +08:00
} */
2018-04-13 14:05:08 +08:00
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 ) {
2019-05-21 10:50:40 +08:00
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 ) ;
2019-05-21 10:50:40 +08:00
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 )
{
2016-09-08 13:45:52 +08:00
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;
2020-12-06 17:00:05 +08:00
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 ;
}
2020-12-06 17:00:05 +08:00
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 ) ;
}
2020-12-06 18:38:08 +08:00
//灰色描画を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 :
{
2020-12-06 18:38:08 +08:00
//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 } ;
2020-12-06 18:38:08 +08:00
//どうやら3DHighLightの上に1pxずらして3DShadowを重ねてるらしい
2016-09-02 17:29:33 +08:00
int oldbm = SetBkMode ( hdc , TRANSPARENT ) ;
COLORREF oldfg = SetTextColor ( hdc , GetSysColor ( COLOR_3DHIGHLIGHT ) ) ;
2020-12-06 18:38:08 +08:00
//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 + + ;
}
}
2020-12-06 18:38:08 +08:00
// 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.
2020-12-06 18:38:08 +08:00
//とりあえずオリジナルに飛ばす
2016-09-02 17:29:33 +08:00
if ( fuOptions & ETO_GLYPH_INDEX )
return ORIG_ExtTextOutA ( hdc , nXStart , nYStart , fuOptions , lprc , lpString , cbString , lpDx ) ;
2020-12-06 18:38:08 +08:00
//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 ) {
2020-12-06 18:38:08 +08:00
//メモリ不足: 一応オリジナルに投げとく
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 ;
2020-12-06 18:38:08 +08:00
//例外モドキ
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 ;
2020-12-06 18:38:08 +08:00
// 取代Windows的ExtTextOutW
2016-10-26 15:04:17 +08:00
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
{
2020-12-06 17:00:05 +08:00
//CThreadCounter __counter; //用于安全退出的计数器
2016-10-26 15:04:17 +08:00
INT * lpDx = const_cast < INT * > ( SyslpDx ) ;
2018-09-25 15:14:49 +08:00
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 ) ;
}
2020-12-06 17:00:05 +08:00
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 ) ;
2016-10-26 15:04:17 +08:00
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 ) ;
2020-12-06 17:00:05 +08:00
CGdippSettings * pSettings = CGdippSettings : : GetInstance ( ) ; //获得一个配置文件实例
2016-09-02 17:29:33 +08:00
/*
2020-12-06 17:00:05 +08:00
# ifndef _DEBUG //debug模式下此参数有问题
2016-09-02 17:29:33 +08:00
if ( pSettings - > FontLoader ( ) = = SETTING_FONTLOADER_WIN32 )
{
2020-12-06 17:00:05 +08:00
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
*/
2020-12-06 17:00:05 +08:00
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 ) ;
2020-12-06 17:00:05 +08:00
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
{
2020-12-06 17:00:05 +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 )
2020-12-06 18:38:08 +08:00
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 ) ; */
2020-12-06 18:38:08 +08:00
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 ( ) ;
2020-12-06 17:00:05 +08:00
//设置标志,
2016-09-02 17:29:33 +08:00
pTLInfo - > InExtTextOut ( true ) ;
2020-12-06 18:38:08 +08:00
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 ) ;
2020-12-06 18:38:08 +08:00
} //耗时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 ;
2016-09-08 13:45:52 +08:00
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
2019-11-29 15:09:40 +08:00
// 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
{
2016-09-27 10:24:48 +08:00
int szDx = fuOptions & ETO_PDY ? cbString * 2 : cbString ;
2016-09-02 17:29:33 +08:00
outlpDx = new int [ szDx ] ;
2016-09-27 10:24:48 +08:00
DCTrans - > TransformlpDx ( lpDx , outlpDx , szDx ) ; //lpDx has a size of cbString -1
2016-09-02 17:29:33 +08:00
}
}
2019-02-28 16:57:42 +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 ) ;
2018-10-09 21:00:20 +08:00
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
}
2020-12-06 18:38:08 +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 ;
}
} */
2020-12-06 18:38:08 +08:00
//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
}
2020-12-06 18:38:08 +08:00
//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 ) ;
2020-12-06 18:38:08 +08:00
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 ) {
2020-12-06 18:38:08 +08:00
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 (
2016-09-01 14:59:16 +08:00
_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 ) ;
} */
2020-04-30 16:51:21 +08:00
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
) {
2020-10-20 14:59:26 +08:00
if ( dwTable ! = 0x656d616e ) // we only simulate the name table, for other tables, use the substituted font data
2020-05-08 10:47:25 +08:00
return ORIG_GetFontData ( hdc , dwTable , dwOffset , pvBuffer , cjBuffer ) ;
2022-07-20 17:52:47 +08:00
DWORD ret = GDI_ERROR ;
2020-04-30 16:51:21 +08:00
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
}
2022-07-20 17:52:47 +08:00
if ( ret = = GDI_ERROR ) // any of the above operations failed or the font is not substituted
2020-04-30 16:51:21 +08:00
ret = ORIG_GetFontData ( hdc , dwTable , dwOffset , pvBuffer , cjBuffer ) ; // fallback to original
return ret ;
2016-09-02 17:29:33 +08:00
}
//EOF