mactype/ft.h

409 lines
11 KiB
C
Raw Normal View History

#ifndef FT_H
#define FT_H
#define FTO_MONO 0x0001
#define FTO_SIZE_ONLY 0x0002
#define CACHE_SIZE 20
#define MAX_CACHE_SIZE 1024
#define CNTRL_UNICODE_PLANE 2
#define CNTRL_COMPLEX_TEXT 1
#define CNTRL_ZERO_WIDTH 4
typedef char (*COLORCACHE)[3][256][256];
#include "fteng.h"
enum FT_DRAW_STATE{
FT_DRAW_NORMAL = 0,
FT_DRAW_EMBEDDED_BITMAP = 1,
FT_DRAW_NOTFOUND = 2
};
BOOL FontLInit(void);
void FontLFree(void);
COLORREF GetPaletteColor(HDC hdc, UINT paletteindex);
2020-04-13 11:23:59 +08:00
#define ROUND(x) ((x)>0? int(x+0.5):int(x-0.5)) // a special round method used by windows
class CDCTransformer {
private:
float fXZoomFactor, fYZoomFactor;
XFORM m_xfm;
bool bZoomMode;
bool bMirrorX, bMirrorY;
public:
CDCTransformer():bMirrorY(false), bMirrorX(false), bZoomMode(false), fXZoomFactor(0), fYZoomFactor(0) {};
void init(XFORM& xfm)
{
memcpy(&m_xfm, &xfm, sizeof(XFORM));
if (xfm.eM11<0)
{
bMirrorX = true;
m_xfm.eM11 = -m_xfm.eM11;
}
if (xfm.eM22<0)
{
bMirrorY = true;
m_xfm.eM11 = -m_xfm.eM22;
}
fXZoomFactor = m_xfm.eM11;
fYZoomFactor = m_xfm.eM22;
m_xfm.eDx=0;
m_xfm.eDy=0;
bZoomMode = fXZoomFactor==fYZoomFactor;
}
void SetSourceOffset(int X, int Y)
{
float temp = float(X)*m_xfm.eM11+m_xfm.eDx;
m_xfm.eDx = temp-(int)temp;
2020-04-13 11:23:59 +08:00
if (ROUND(m_xfm.eDx)<0) // change negive offset to positive
m_xfm.eDx+=1;
temp = float(Y)*m_xfm.eM22+m_xfm.eDy;
m_xfm.eDy = temp-(int)temp;
if (ROUND(m_xfm.eDy)<0)
m_xfm.eDy+=1;
}
int XInit() {return ROUND(m_xfm.eDx);}
int YInit() {return ROUND(m_xfm.eDy);}
int GetXCeilingIntAB(int X)
{
return ROUND(ROUND((X-m_xfm.eDx)/m_xfm.eM11)*m_xfm.eM11+m_xfm.eDx);
}
int GetYCeilingIntAB(int Y)
{
return ROUND(ROUND((Y-m_xfm.eDy)/m_xfm.eM22)*m_xfm.eM22+m_xfm.eDy);
}
~CDCTransformer() {};
void TransformRectAB(const RECT* lpInRect, PRECT lpOutRect)
{
lpOutRect->bottom = TransformYCoordinateAB(lpInRect->bottom);
lpOutRect->left = TransformXCoordinateAB(lpInRect->left);
lpOutRect->right = TransformXCoordinateAB(lpInRect->right);
lpOutRect->top = TransformYCoordinateAB(lpInRect->top);
}
void TransformRectBA(const RECT* lpInRect, PRECT lpOutRect)
{
lpOutRect->bottom = ROUND(lpInRect->bottom/fYZoomFactor);
lpOutRect->left = ROUND(lpInRect->left/fXZoomFactor);
lpOutRect->right = ROUND(lpInRect->right/fXZoomFactor);
lpOutRect->top = ROUND(lpInRect->top/fYZoomFactor);
}
int TransformXAB(int nX)
{
return ROUND(nX*fXZoomFactor);
}
int TransformXCoordinateAB(int nX)
{
return ROUND((float(nX))*fXZoomFactor/*+m_xfm.eDx*/);
}
int TransformXBA(int nX)
{
return ROUND(nX/fXZoomFactor);
}
int TransformXCoordinateBA(int nX)
{
return ROUND((float(nX)/*-m_xfm.eDx*/)/fXZoomFactor);
}
int TransformYAB(int nY)
{
return ROUND(nY*fYZoomFactor);
}
int TransformYCoordinateAB(int nY)
{
return ROUND((float(nY))*fYZoomFactor/*+m_xfm.eDy*/);
}
int TransformYBA(int nY)
{
return ROUND(nY/fYZoomFactor);
}
int TransformYCoordinateBA(int nY)
{
return ROUND((float(nY)/*-m_xfm.eDy*/)/fYZoomFactor);
}
void TransformlpDx(const int* lpDx, int* outlpDx, int szDx)
{
int LastPos = 0, LPCurPos = 0;
double fDPLastPos = 0, fDPCurPos = 0;
for (;szDx>0;--szDx)
{
2020-04-13 11:23:59 +08:00
LPCurPos += *lpDx++; // the logical position the letter belongs to
fDPCurPos = LPCurPos*fXZoomFactor; // the device position the letter belongs to
*outlpDx = ROUND(fDPCurPos-fDPLastPos); // the device coord
fDPLastPos += *outlpDx++; // the coord after this letter is painted. In order to calculate the pos of the next letter.
}
}
bool TransformMode() { return bZoomMode; }
XFORM* GetTransform() { return &m_xfm; }
bool MirrorX() { return bMirrorX; }
bool MirrorY() { return bMirrorY; }
};
class ControlIder
{
private:
char* unicode;
public:
ControlIder()
{
unicode = new char[0xffff];
2020-04-13 11:23:59 +08:00
memset(unicode, 0, sizeof(char)*0xffff); // non-control char by default
//memset(unicode, 2, sizeof(char)*32);
for (int i=0;i<0x3000;i++)
unicode[i]=!!iswcntrl(i);
for (int i=0xa000;i<0xffff;i++)
2020-04-13 11:23:59 +08:00
unicode[i]=!!iswcntrl(i); // Chinese
memset(&unicode[0xd800],CNTRL_UNICODE_PLANE,sizeof(char)*(0xdfff-0xd800+1)); //unicode plane
memset(&unicode[0x0590],CNTRL_COMPLEX_TEXT,sizeof(char)*(0x05FF-0x0590+1)); //hebrew
memset(&unicode[0x0600],CNTRL_COMPLEX_TEXT,sizeof(char)*(0x06FF-0x0600+1)); //arabic
memset(&unicode[0xFB50],CNTRL_COMPLEX_TEXT,sizeof(char)*(0xFDFF-0xFB50+1)); //Arabic Presentation Forms-A
memset(&unicode[0xFE70],CNTRL_COMPLEX_TEXT,sizeof(char)*(0xFEFF-0xFE70+1)); //Arabic Presentation Forms-B
memset(&unicode[0x0E00],CNTRL_COMPLEX_TEXT,sizeof(char)*(0x0E7F-0x0E00+1)); //thai
// unicode[0xa] = 0;
// unicode[0xd] = 0;
// unicode[0x9] = 0;
2020-04-13 11:23:59 +08:00
// Set width for some special control chars. They have zero width, but GetCharABCWidth gives wrong results for them.
}
~ControlIder()
{
delete unicode;
}
void setcntrlAttribute(WCHAR wch, int cnType)
{
unicode[wch] = cnType;
}
char myiswcntrl(WCHAR str)
{
return unicode[str];
}
bool myiscomplexscript(LPCWSTR lpString, int cbString)
{
for (;cbString>0;++lpString,--cbString)
{
if (unicode[*lpString]==CNTRL_COMPLEX_TEXT)
return true;
}
return false;
}
};
struct FREETYPE_PARAMS
{
UINT etoOptions;
UINT ftOptions;
int charExtra;
COLORREF color;
int alpha;
BYTE alphatuner;
LOGFONTW* lplf;
OUTLINETEXTMETRIC* otm;
wstring strFamilyName, strFullName;
FREETYPE_PARAMS()
{
ZeroMemory(this, sizeof(*this));
}
//FreeTypeTextOut用 (サイズ計算+文字描画)
FREETYPE_PARAMS(UINT eto, HDC hdc, LOGFONTW* p, OUTLINETEXTMETRIC* lpotm = NULL)
: etoOptions(eto)
, ftOptions(0)
, charExtra(GetTextCharacterExtra(hdc))
, color(GetTextColor(hdc))
, alpha(0)
, lplf(p)
, otm(lpotm)
, alphatuner(1)
{
if ((color>>24)%2 || (color>>28)%2)
{
color = GetPaletteColor(hdc, color);
}
if (otm)
{
strFamilyName = (LPWSTR)((DWORD_PTR)otm + (DWORD_PTR)otm->otmpFamilyName);
strFullName = wstring((LPWSTR)((DWORD_PTR)otm + (DWORD_PTR)otm->otmpFullName));
std::wstring strStyleName = wstring((LPWSTR)((DWORD_PTR)otm + (DWORD_PTR)otm->otmpStyleName));
strFullName = MakeUniqueFontName(strFullName, strFamilyName, strStyleName);
if (strFamilyName.size() > 0 && strFamilyName.c_str()[0] == L'@')
strFullName = L'@' + strFullName;
}
}
bool IsMono() const
{
return (ftOptions & FTO_MONO);
}
};
class CGGOKerning : public CMap<DWORD, int>
{
private:
DWORD makekey(WORD first, WORD second) {
return ((DWORD)first << 16) | second;
}
public:
void init(HDC hdc)
{
DWORD rc;
rc = GetKerningPairs(hdc, 0, NULL);
if (rc <= 0) return;
DWORD kpcnt = rc;
LPKERNINGPAIR kpp = (LPKERNINGPAIR)calloc(kpcnt, sizeof *kpp);
if (!kpp) return;
rc = GetKerningPairs(hdc, kpcnt, kpp);
for (DWORD i = 0; i < rc; ++i) {
Add(makekey(kpp[i].wFirst, kpp[i].wSecond), kpp[i].iKernAmount);
}
free(kpp);
}
int get(WORD first, WORD second) {
DWORD key = makekey(first, second);
int x = FindKey(key);
return (x >= 0) ? GetValueAt(x) : 0;
}
};
2020-04-13 11:23:59 +08:00
//fteng.cpp variables
// forward declaration
extern FT_Library freetype_library;
extern FTC_Manager cache_man;
extern FTC_CMapCache cmap_cache;
extern FTC_ImageCache image_cache;
struct FreeTypeDrawInfo
{
FT_FaceRec_ dummy_freetype_face;
//FreeTypePrepareが設定する
int sx,sy;
FT_Face freetype_face;
FT_Int cmap_index;
FT_Bool useKerning;
FT_Render_Mode render_mode;
FTC_ImageTypeRec font_type;
FTC_ScalerRec scaler;
FreeTypeFontInfo* pfi;
const CFontSettings* pfs;
FreeTypeFontCache* pftCache;
FTC_FaceID* face_id_list;
2020-04-13 11:23:59 +08:00
HFONT* ggo_font_list; // for faster GGO fontlinking
FTC_FaceID face_id_simsun;
2020-04-13 11:23:59 +08:00
FT_Face freetype_face_list[CFontLinkInfo::FONTMAX * 2 + 1]; // in order to solve italic issues.
int face_id_list_num;
int* Dx;
int* Dy;
//呼び出し前に自分で設定する
HDC hdc;
int xBase;
2020-04-13 11:23:59 +08:00
int y;//coord height, calculated by ETO_PDY, 0 if not provided
int x;//coord width, calculated by win32 API
int px; //x of paint, the real text width
int yBase;
int yTop;
2020-04-13 11:23:59 +08:00
int height; //original width
int width;
2020-04-13 11:23:59 +08:00
const int* lpDx;
CBitmapCache* pCache;
FREETYPE_PARAMS* params;
int* AAModes;
FreeTypeDrawInfo(FREETYPE_PARAMS& fp, HDC dc, LOGFONTW* lf = NULL, CBitmapCache* ca = NULL, const int* dx = NULL, int cbString =0, int xs=0, int ys = 0)
: freetype_face(&dummy_freetype_face), cmap_index(0), useKerning(0)
, pfi(NULL), pfs(NULL), pftCache(NULL), face_id_list_num(0), ggo_font_list(NULL)
, hdc(dc), x(0), y(0), yBase(0), yTop(0), face_id_simsun(NULL), px(0), xBase(0)
{
render_mode = FT_RENDER_MODE_NORMAL;
ZeroMemory(&scaler, sizeof(scaler));
ZeroMemory(&font_type, sizeof(font_type));
ZeroMemory(&face_id_list, sizeof face_id_list);
2020-04-13 11:23:59 +08:00
// init face list
ZeroMemory(&freetype_face_list, sizeof freetype_face_list);
lpDx = dx;
pCache = ca;
params = &fp;
height = 0;
width = 0;
sx = xs;
sy = ys;
if(lf) params->lplf = lf;
memset(&dummy_freetype_face, 0, sizeof dummy_freetype_face);
Dx = new int[cbString];
Dy = new int[cbString];
AAModes = new int[cbString];
scaler.height = 12;
scaler.width = 12;
scaler.pixel = 1;
}
~FreeTypeDrawInfo()
{
delete Dx;
delete Dy;
delete[] AAModes;
}
const LOGFONTW& LogFont() const { return *params->lplf; }
COLORREF Color() const { return params->color; }
UINT GetETO() const { return params->etoOptions; }
bool IsGlyphIndex() const { return !!(params->etoOptions & ETO_GLYPH_INDEX); }
bool IsMono() const { return !!(params->ftOptions & FTO_MONO); }
bool IsSizeOnly() const { return !!(params->ftOptions & FTO_SIZE_ONLY); }
CGGOKerning ggokerning;
2020-04-13 11:23:59 +08:00
FT_Face GetFace(int index) // get face list
{
if (!freetype_face_list[index])
{
CCriticalSectionLock __lock(CCriticalSectionLock::CS_MANAGER);
FT_Size font_size;
//FTC_ScalerRec fscaler={face_id_list[index], 1,1,1,0,0};
scaler.face_id = face_id_list[index];
if (FTC_Manager_LookupSize(cache_man, &scaler, &font_size))
//if (FTC_Manager_LookupFace(cache_man, face_id_list[index], &freetype_face_list[index]))
freetype_face_list[index] = NULL;
else {
if (scaler.height == 0)
return font_size->face; // return without save, because the scaler is not prepared yet.
freetype_face_list[index] = font_size->face;
}
}
return freetype_face_list[index];
}
#ifdef _DEBUG
void Validate()
{
Assert(params->lplf);
};
#endif
};
BOOL FreeTypeTextOut(
const HDC hdc,
CBitmapCache& cache,
LPCWSTR lpString,
int cbString,
FreeTypeDrawInfo& FTInfo,
FT_Referenced_Glyph * Glyphs,
FT_DRAW_STATE* drState
);
2020-04-13 11:23:59 +08:00
BOOL FreeTypeGetGlyph( // Get all the glyphs and widths needed.
FreeTypeDrawInfo& FTInfo,
LPCWSTR lpString,
int cbString,
int& width,
FT_Referenced_Glyph* Glyphs,
FT_DRAW_STATE* drState
);
void RefreshAlphaTable();
#endif