diff options
Diffstat (limited to 'Src/Wasabi/api/font')
-rw-r--r-- | Src/Wasabi/api/font/FontCreator.h | 7 | ||||
-rw-r--r-- | Src/Wasabi/api/font/FontSvcEnum.h | 18 | ||||
-rw-r--r-- | Src/Wasabi/api/font/api_font.cpp | 11 | ||||
-rw-r--r-- | Src/Wasabi/api/font/api_font.h | 36 | ||||
-rw-r--r-- | Src/Wasabi/api/font/bitmapfont.cpp | 394 | ||||
-rw-r--r-- | Src/Wasabi/api/font/bitmapfont.h | 70 | ||||
-rw-r--r-- | Src/Wasabi/api/font/font.cpp | 637 | ||||
-rw-r--r-- | Src/Wasabi/api/font/font.h | 55 | ||||
-rw-r--r-- | Src/Wasabi/api/font/fontapi.cpp | 32 | ||||
-rw-r--r-- | Src/Wasabi/api/font/fontapi.h | 20 | ||||
-rw-r--r-- | Src/Wasabi/api/font/linux/truetypefont_linux.cpp | 472 | ||||
-rw-r--r-- | Src/Wasabi/api/font/linux/truetypefont_linux.h | 65 | ||||
-rw-r--r-- | Src/Wasabi/api/font/skinfont.cpp | 43 | ||||
-rw-r--r-- | Src/Wasabi/api/font/skinfont.h | 17 | ||||
-rw-r--r-- | Src/Wasabi/api/font/svc_fontI.h | 39 | ||||
-rw-r--r-- | Src/Wasabi/api/font/truetypefontdef.h | 56 | ||||
-rw-r--r-- | Src/Wasabi/api/font/win32/truetypefont_win32.cpp | 561 | ||||
-rw-r--r-- | Src/Wasabi/api/font/win32/truetypefont_win32.h | 61 |
18 files changed, 2594 insertions, 0 deletions
diff --git a/Src/Wasabi/api/font/FontCreator.h b/Src/Wasabi/api/font/FontCreator.h new file mode 100644 index 00000000..086ea933 --- /dev/null +++ b/Src/Wasabi/api/font/FontCreator.h @@ -0,0 +1,7 @@ +#include <api/service/svcs/svc_font.h> +template <class T> +class FontCreator : public waServiceFactoryT<svc_font, T> +{ +public: + FontCreator(GUID myGuid = INVALID_GUID) : waServiceFactoryT<svc_font, T>(myGuid) {} +}; diff --git a/Src/Wasabi/api/font/FontSvcEnum.h b/Src/Wasabi/api/font/FontSvcEnum.h new file mode 100644 index 00000000..c01cc9cc --- /dev/null +++ b/Src/Wasabi/api/font/FontSvcEnum.h @@ -0,0 +1,18 @@ +#include <bfc/string/StringW.h> +#include <api/service/svc_enum.h> + +class FontSvcEnum : public SvcEnumT<svc_font> { +public: + FontSvcEnum(const wchar_t *_svc_name = NULL) : svc_name(_svc_name) {} +protected: + virtual int testService(svc_font *svc) + { + if (!svc_name.len()) + return 1; // blank name returns all services. + return (!WCSICMP(svc->getFontSvcName(),svc_name)); + } +private: + StringW svc_name; +}; + + diff --git a/Src/Wasabi/api/font/api_font.cpp b/Src/Wasabi/api/font/api_font.cpp new file mode 100644 index 00000000..1fd7c551 --- /dev/null +++ b/Src/Wasabi/api/font/api_font.cpp @@ -0,0 +1,11 @@ +#include <precomp.h> +#include "api_font.h" + +#ifdef CBCLASS +#undef CBCLASS +#endif +#define CBCLASS api_fontI +START_DISPATCH; + VCB(API_FONT_FONT_TEXTOUT, font_textOut); + CB(API_FONT_FONT_GETINFO, font_getInfo); +END_DISPATCH; diff --git a/Src/Wasabi/api/font/api_font.h b/Src/Wasabi/api/font/api_font.h new file mode 100644 index 00000000..cea0bac1 --- /dev/null +++ b/Src/Wasabi/api/font/api_font.h @@ -0,0 +1,36 @@ +#ifndef __API_FONT_H +#define __API_FONT_H + +#include <bfc/dispatch.h> + +class ifc_canvas; + +class NOVTABLE api_font : public Dispatchable +{ + public: + void font_textOut(ifc_canvas *c, int style, int x, int y, int w, int h, const wchar_t *txt); + int font_getInfo(ifc_canvas *c, const wchar_t *font, int infoid, const wchar_t *txt, int *w, int *h); + + enum { + API_FONT_FONT_TEXTOUT = 0, + API_FONT_FONT_GETINFO = 10, + }; +}; + +inline void api_font::font_textOut(ifc_canvas *c, int style, int x, int y, int w, int h, const wchar_t *txt) +{ + _voidcall(API_FONT_FONT_TEXTOUT, c, style, x, y, w, h, txt); +} + +inline int api_font::font_getInfo(ifc_canvas *c, const wchar_t *font, int infoid, const wchar_t *txt, int *w, int *h) +{ + return _call(API_FONT_FONT_GETINFO, (int)0, c, font, infoid, txt, w, h); +} + +// {1FCA9C7E-5923-4b9c-8906-0F8C331DF21C} +static const GUID fontApiServiceGuid = +{ 0x1fca9c7e, 0x5923, 0x4b9c, { 0x89, 0x6, 0xf, 0x8c, 0x33, 0x1d, 0xf2, 0x1c } }; + +extern api_font *fontApi; + +#endif diff --git a/Src/Wasabi/api/font/bitmapfont.cpp b/Src/Wasabi/api/font/bitmapfont.cpp new file mode 100644 index 00000000..fe85abda --- /dev/null +++ b/Src/Wasabi/api/font/bitmapfont.cpp @@ -0,0 +1,394 @@ +#include "precomp.h" +// ============================================================================================================================================================ +// Font abstract class + statics to install TT fonts and Bitmap fonts +// ============================================================================================================================================================ +#include "bitmapfont.h" +#include <api/wnd/fontdef.h> +#include <api/config/items/cfgitem.h> +#ifdef WASABI_COMPILE_SKIN +#include <api/skin/skin.h> +#endif +#ifdef WA3COMPATIBILITY +#endif + +#include <tataki/canvas/ifc_canvas.h> +#include <tataki/region/api_region.h> +#include <api/skin/skinparse.h> + +// ============================================================================================================================================================ +// BitmapFont implementation. +// ============================================================================================================================================================ + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +BitmapFont::BitmapFont() : scriptid(0), char_width(0), char_height(0), hor_spacing(0), vert_spacing(0) { +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +BitmapFont::~BitmapFont() { + +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int BitmapFont::isBitmap() { + return 1; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +const wchar_t *BitmapFont::getFaceName() { + return getFontId(); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void BitmapFont::textOut(ifc_canvas *c, int x, int y, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased) { + do_textOut(this, c, x+xoffset, y+yoffset, -1, -1, txt, size, bold, opaque, underline, italic, STDFONT_LEFT, color, WA_FONT_TEXTOUT_NORMAL); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void BitmapFont::textOut2(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased) { + do_textOut(this, c, x+xoffset, y+yoffset, x+xoffset+w, y+yoffset+h, txt, size, bold, opaque, underline, italic, align, color, WA_FONT_TEXTOUT_RECT); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void BitmapFont::textOutEllipsed(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased) { + do_textOut(this, c, x+xoffset, y+yoffset, x+xoffset+w, y+yoffset+h, txt, size, bold, opaque, underline, italic, align, color, WA_FONT_TEXTOUT_ELLIPSED); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void BitmapFont::textOutWrapped(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased) { + do_textOut(this, c, x+xoffset, y+yoffset, x+xoffset+w, y+yoffset+h, txt, size, bold, opaque, underline, italic, align, color, WA_FONT_TEXTOUT_WRAPPED); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void BitmapFont::textOutWrappedPathed(ifc_canvas *c, int x, int y, int w, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased) { + do_textOut(this, c, x+xoffset, y+yoffset, x+xoffset+w, -1, txt, size, bold, opaque, underline, italic, align, color, WA_FONT_TEXTOUT_WRAPPEDPATHED); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void BitmapFont::textOutCentered(ifc_canvas *c, RECT *r, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased) { + do_textOut(this, c, r->left, r->top, r->right-r->left, r->bottom-r->top, txt, size, bold, opaque, underline, italic, align, color, WA_FONT_TEXTOUT_CENTERED); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int BitmapFont::getTextWidth(ifc_canvas *c, const wchar_t *text, int size, int bold, int underline, int italic, int antialiased) +{ + return wcslen(text) * char_width + wcslen(text)*hor_spacing; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int BitmapFont::getTextHeight(ifc_canvas *c, const wchar_t *text, int size, int bold, int underline, int italic, int antialiased) +{ + return char_height; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int BitmapFont::getTextHeight2(ifc_canvas *c, int size, int bold, int underline, int italic, int antialiased) +{ + return char_height; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void BitmapFont::getTextExtent(ifc_canvas *c, const wchar_t *text, int *w, int *h, int size, int bold, int underline, int italic, int antialiased) +{ + if (w) *w = getTextWidth(c, text, size, bold, underline, italic, antialiased); + if (h) *h = char_height; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void BitmapFont::setFontBitmap(const wchar_t *name_or_element, const wchar_t *path) +{ + StringW pathfile; + if (!wcschr(name_or_element, L':')) + { + pathfile = path; + pathfile.AddBackslash(); + } + pathfile.cat(name_or_element); + if (!WACCESS(pathfile, 0)) + table = pathfile; + else + table = name_or_element; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void BitmapFont::setFontMetrics(int _char_width, int _char_height, int _hor_spacing, int _vert_spacing) { + char_width = _char_width; + char_height = _char_height; + hor_spacing = _hor_spacing; + vert_spacing = _vert_spacing; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int BitmapFont::getHorizontalSpacing() { + return hor_spacing; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int BitmapFont::getVerticalSpacing() { + return vert_spacing; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int BitmapFont::getCharWidth() { + return char_width; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int BitmapFont::getCharHeight() { + return char_height; +} + +AutoSkinBitmap *BitmapFont::getCharTable() { + return &table; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void BitmapFont::getXYfromChar(wchar_t ic, int *x, int *y) +{ + int c,c2=0; + switch (ic) + { + case L'\u00B0': /**/ ic = L'0'; break; + case L'\u00C6':/**/ ic = L'A'; break; + // case '\u00C1':/**/ ic = L'A'; break; + // case '\u00C2': ic = L'A'; break; + case L'\u00C7': /**/ ic = L'C'; break; + case L'\u00C9':/**/ ic = L'E'; break; + + case L'\u00E0': /**/ case L'\u00E1': /**/ case L'\u00E2': /**/ ic = L'a'; break; + case L'\u00E6':/**/ ic = L'a'; break; + case L'\u00E7': /**/ ic = L'c'; break; + case L'\u00E8': /**/ case L'\u00E9': /**/ case L'\u00EB': /**/case L'\u00EA':/**/ ic = L'e'; break; + case L'\u00EC':/**/ case L'\u00ED':/**/ case L'\u00EE':/**/ case L'\u00EF':/**/ ic = L'i'; break; + +#ifdef _WIN32 + case L'':/**/ case L'':/**/ case L'':/**/ ic = L'o'; break; + case L'':/**/ case L'':/**/ case L'':/**/ ic = L'u'; break; + case L'':/**/ ic = L'y'; break; + case L'':/**/ ic = L'U'; break; +#else +#warning change these to \u +#endif + case L'\u00D1':/**/ ic = L'N'; break; + case L'\u00F1':/**/ ic = L'n'; break; + case L'\u00FC': /**/ ic = L'u'; break; + case L'\u0192':/**/ ic = L'f'; break; + default: break; + } // quick relocations + if (ic <= L'Z' && ic >= L'A') c = (ic-'A'); + else if (ic <= L'z' && ic >= L'a') c = (ic-'a'); + else if (ic == L' ') c = 30; + else { + c2 += char_height; + if (ic == L'\1') c=10; + else if (ic == L'.') c = 11; + else if (ic <= L'9' && ic >= L'0') c = ic - L'0'; + else if (ic == L':') c = 12; + else if (ic == L'(') c = 13; + else if (ic == L')') c = 14; + else if (ic == L'-') c = 15; + else if (ic == L'\'' || ic=='`') c = 16; + else if (ic == L'!') c = 17; + else if (ic == L'_') c = 18; + else if (ic == L'+') c = 19; + else if (ic == L'\\') c = 20; + else if (ic == L'/') c = 21; + else if (ic == L'[' || ic == L'{' || ic == L'<') c = 22; + else if (ic == L']' || ic == L'}' || ic == L'>') c = 23; + else if (ic == L'~' || ic == L'^') c = 24; + else if (ic == L'&') c = 25; + else if (ic == L'%') c = 26; + else if (ic == L',') c = 27; + else if (ic == L'=') c = 28; + else if (ic == L'$') c = 29; + else if (ic == L'#') c = 30; + else + { + c2 += char_height; +#ifdef _WIN32 + if (ic == L'' || ic == L'') c = 0; + else if (ic == L'' || ic == L'') c = 1; + else if (ic == L'' || ic == L'') c = 2; + else +#else +#warning change these to \u +#endif + if (ic == L'?') c = 3; + else if (ic == L'*') c = 4; + else { + c2 = 0; + if (ic == L'"') c = 26; + else if (ic == L'@') c = 27; + else c = 30; + } + } + } + c*=char_width; + *x=c; + *y=c2; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int BitmapFont::getWordLength(const wchar_t *p) { + int n=0; + while (p && *p && *p != L' ') { + p++; + n++; + } + return n; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +wchar_t *BitmapFont::makeLine(const wchar_t *t, BitmapFont *font, int line, int width, int style) { + + static wchar_t str[4096]; + wchar_t *p = (wchar_t *)t; + size_t len = wcslen(t); + + switch (style) { + case WA_FONT_TEXTOUT_NORMAL: + case WA_FONT_TEXTOUT_RECT: + case WA_FONT_TEXTOUT_ELLIPSED: + case WA_FONT_TEXTOUT_CENTERED: + return line == 0 ? (wchar_t *)t : NULL; + case WA_FONT_TEXTOUT_WRAPPEDPATHED: + case WA_FONT_TEXTOUT_WRAPPED: { + size_t maxchar = width / (font->getCharWidth() + font->getVerticalSpacing()); + for (int i = 0; i < line; i++) { + wchar_t *oldp = p; + p += maxchar; + if ((size_t)(p-t) >= len) return NULL; + while (p >= t) { + if (p == t || *(p-1) == L' ') + break; + p--; + } + if (p == oldp) { + p += maxchar; + while (p && *p && *p != L' ') + p++; + } + } + WCSCPYN(str, p, maxchar); + wchar_t *d = &str[maxchar-1]; + int wr=0; + if (wcslen(p) > maxchar && *(p+maxchar) != L' ' && wcschr(str, L' ')) + while (d >= str) { + if (*d == L' ') { + *d = 0; + wr=1; + } + else { + if (wr) break; + d--; + } + } + return str; + } + } + return NULL; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void BitmapFont::do_textOut(BitmapFont *font, ifc_canvas *c, int x, int y, int x2, int y2, const wchar_t *text, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, int style) +{ + static wchar_t *dotdotdot=L"..."; + if (!text) return; + + BaseCloneCanvas canvas; + int ret = canvas.clone(c); + if (!ret) return; + + RECT bounds; + + RECT defbounds={x,y,x2,y2}; + int __w, __h; + c->getDim(&__w, &__h, NULL); + if (x2 == -1) defbounds.right = defbounds.left + __w; + if (y2 == -1) defbounds.bottom = defbounds.top + __h; +#ifdef _WIN32 + RegionI oldclip(&canvas, &defbounds); // get clipping region in oldclip + RegionI *andclip=NULL; + oldclip.getBox(&bounds); // get boundaries +#else + bounds = defbounds; +#warning port me +#endif + +/* if (x2 != -1 && y2 != -1) { + andclip = new RegionI(x, y, x2, y2); // create region for rect + andclip->andRegion(oldclip); // and them + canvas.selectClipRgn(andclip); // select new clipping rect + andclip->getBox(&bounds); // update boundaries + }*/ + + int lc=-1; + wchar_t *p = dotdotdot+3; // just a zero to triger next line + + int _x = x+(font->getHorizontalSpacing()/2); + int _y = y; + + if (style == WA_FONT_TEXTOUT_CENTERED) { + _y += (y2 - y - font->getCharHeight()) / 2; + } + + _y -= font->getCharHeight() + font->getVerticalSpacing(); + + int xp, yp; + + while (p) { + + if (!*p) { + lc++; + p = makeLine(text, font, lc, x2-x, style); + if (!p || !*p) break; + + _x = x+(font->getHorizontalSpacing()/2); + _y += font->getCharHeight() + font->getVerticalSpacing(); + if ((align == STDFONT_RIGHT || align == STDFONT_CENTER) && x2 != -1) { + int l = wcslen(p); + _x -= l * (font->getCharWidth() + font->getHorizontalSpacing()) - (x2-x); + } + if (align == STDFONT_CENTER) + _x = x + (_x - x) / 2; + + } + + if ((style == WA_FONT_TEXTOUT_ELLIPSED || style == WA_FONT_TEXTOUT_WRAPPEDPATHED) && x2 != -1) { + if (_x > x2 - 4 * (font->getCharWidth() + font->getHorizontalSpacing()) && wcslen(p) > 3) { + p = dotdotdot; + } + } + + font->getXYfromChar(*p, &xp, &yp); + + RECT r; + r.left = xp; + r.top = yp; + r.right = xp + font->getCharWidth(); + r.bottom = yp + font->getCharHeight(); + + RECT dst; + dst.left = _x; + dst.top = _y; + dst.right = _x + font->getCharWidth(); + dst.bottom = _y + font->getCharHeight(); + + if (Wasabi::Std::rectIntersect(dst, bounds)) +// if (IntersectRect(&dummy, &dst, &bounds)) // port me / checks clipping, not passed x,y,x2,y2 + font->getCharTable()->stretchToRectAlpha(&canvas, &r, &dst, 255); + + p++; + _x += font->getCharWidth(); + _x += font->getHorizontalSpacing(); + } + +#ifdef _WIN32 + if (andclip) { + canvas.selectClipRgn(&oldclip); // restore previously saved clipping region + delete andclip; + } +#else +#warning port me +#endif +} + diff --git a/Src/Wasabi/api/font/bitmapfont.h b/Src/Wasabi/api/font/bitmapfont.h new file mode 100644 index 00000000..0bedae86 --- /dev/null +++ b/Src/Wasabi/api/font/bitmapfont.h @@ -0,0 +1,70 @@ +#ifndef __BITMAPFONT_H +#define __BITMAPFONT_H + +#include <api/font/svc_fonti.h> + +//#include "font.h" + +#include <bfc/platform/platform.h> +#include <bfc/ptrlist.h> +#include <bfc/stack.h> +#include <tataki/bitmap/autobitmap.h> +#include <bfc/string/StringW.h> + +class Font; + +class BitmapFont : public svc_fontI +{ +friend class Font; + public: + + virtual void textOut(ifc_canvas *c, int x, int y, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased); + virtual void textOut2(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased); + virtual void textOutEllipsed(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased); + virtual void textOutWrapped(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased); + virtual void textOutWrappedPathed(ifc_canvas *c, int x, int y, int w, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased); + virtual void textOutCentered(ifc_canvas *c, RECT *r, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased); + virtual int getTextWidth(ifc_canvas *c, const wchar_t *text, int size, int bold, int underline, int italic, int antialiased); + virtual int getTextHeight(ifc_canvas *c, const wchar_t *text, int size, int bold, int underline, int italic, int antialiased); + virtual int getTextHeight2(ifc_canvas *c, int size, int bold, int underline, int italic, int antialiased); + virtual void getTextExtent(ifc_canvas *c, const wchar_t *text, int *w, int *h, int size, int bold, int underline, int italic, int antialiased); + virtual int isBitmap(); + + virtual void setFontBitmap(const wchar_t *name_or_element, const wchar_t *path); + virtual void setFontMetrics(int char_width, int char_height, int hor_spacing, int vert_spacing); + virtual const wchar_t *getFaceName(); + + virtual void setFontId(const wchar_t *id) { font_id = id; } + virtual const wchar_t *getFontId() { return font_id; } + virtual int getScriptId() { return scriptid; } + virtual void setScriptId(int id) { scriptid = id; } + virtual void setFontFace(const wchar_t *face) {} + virtual int addFontResource(OSFILETYPE f, const wchar_t *name) { return 0; /*failure*/} + virtual int addFontResource2(void *mem, int datalen, const wchar_t *name) { return 0; /*failure*/} + + virtual const wchar_t *getFontSvcName() { return L"Bitmap Font"; } + + protected: + BitmapFont(); + virtual ~BitmapFont(); + + AutoSkinBitmap *getCharTable(); + int getCharWidth(); + int getCharHeight(); + int getHorizontalSpacing(); + int getVerticalSpacing(); + void getXYfromChar(wchar_t ic, int *x, int *y); + + protected: + StringW font_id; + int scriptid; + + private: + AutoSkinBitmap table; + int char_width, char_height, hor_spacing, vert_spacing; + static void do_textOut(BitmapFont *font, ifc_canvas *c, int x, int y, int x2, int y2, const wchar_t *text, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, int style); + static int getWordLength(const wchar_t *p); + static wchar_t *makeLine(const wchar_t *t, BitmapFont *font, int line, int physwidth, int style); +}; + +#endif diff --git a/Src/Wasabi/api/font/font.cpp b/Src/Wasabi/api/font/font.cpp new file mode 100644 index 00000000..e45994ce --- /dev/null +++ b/Src/Wasabi/api/font/font.cpp @@ -0,0 +1,637 @@ +#include "precomp.h" +// ============================================================================================================================================================ +// Font abstract class + statics to install TT fonts and Bitmap fonts +// ============================================================================================================================================================ + +#include <api/font/font.h> +#include <api/font/bitmapfont.h> +#include <bfc/parse/pathparse.h> + +#ifdef WASABI_COMPILE_SKIN + #include <api/skin/skin.h> + #include <api/skin/skinparse.h> +#endif + +#include <tataki/canvas/ifc_canvas.h> +#include <api/wnd/fontdef.h> + +#ifdef WASABI_COMPILE_FONT +#include <api/service/svcs/svc_font.h> +//#include "services/svc_fontmaker.h" +#endif + +#ifdef WASABI_API_CONFIG +#include <api/config/options.h> +#include <api/config/items/attrint.h> +#include <api/config/items/attrstr.h> +#include <api/config/items/attrbool.h> +#endif +#include <api/memmgr/api_memmgr.h> +#include <api/font/FontSvcEnum.h> + +extern _bool cfg_options_usefontmapper; +extern _string cfg_options_ttfoverridefont; +extern _int cfg_options_defaultfontscale; + +PtrList<svc_font> Font::fontlist; +PtrList<FontDef> Font::fontdefs; + +void Font::init() +{ +#ifdef WASABI_API_CONFIG + Wasabi::Std::setDefaultFont(cfg_options_defaultfont.getValue()); + Wasabi::Std::setDefaultFontScale(cfg_options_defaultfontscale.getValueAsInt()); +#endif +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void Font::dispatchTextOut(ifc_canvas *c, int style, int x, int y, int w, int h, const wchar_t *txt) +{ + int isoverride = 0; + if (WASABI_API_APP->main_isShuttingDown()) return; + + int size = c->getTextSize(); + + svc_font *f = requestSkinFont(c->getTextFont(), &size); + + ASSERT(f != NULL); + + // After we get the font we want, check to see if it is bitmap. + // If bitmap fonts are disallowed, use the truetype override font. + if (f->isBitmap() && useTrueTypeOverride(txt)) + { + int gotdefault=0; + svc_font *ttFont = requestSkinFont(getTrueTypeOverride(), &size, &gotdefault); + if (ttFont != NULL) + { + if (!gotdefault) + isoverride = 1; + f = ttFont; + } + } + + if (isoverride) + { + double f = (double)getTrueTypeOverrideScale() / 100.0f; + size = (int)(size*f); + } + int bold = c->getTextBold(); + int opaque = c->getTextOpaque(); + int underline = c->getTextUnderline(); + int italic = c->getTextItalic(); + int align = c->getTextAlign(); + int antialiased = c->getTextAntialias(); + ARGB32 color = c->getTextColor(); + ARGB32 bkcolor = c->getTextBkColor(); + int xoffset=0, yoffset=0; + c->getOffsets(&xoffset, &yoffset); +/* if (!f->isBitmap() && _intVal(Main::enumRootCfgItem(0), "Force antialias on all TTF")) + antialiased = 1;*/ + switch (style) + { + case WA_FONT_TEXTOUT_NORMAL: + f->textOut(c, x, y, txt, size, bold, opaque, underline, italic, color, bkcolor, xoffset, yoffset, antialiased); + break; + case WA_FONT_TEXTOUT_RECT: + f->textOut(c, x, y, w, h, txt, size, bold, opaque, underline, italic, align, color, bkcolor, xoffset, yoffset, antialiased); + break; + case WA_FONT_TEXTOUT_ELLIPSED: + f->textOutEllipsed(c, x, y, w, h, txt, size, bold, opaque, underline, italic, align, color, bkcolor, xoffset, yoffset, antialiased); + break; + case WA_FONT_TEXTOUT_WRAPPED: + f->textOutWrapped(c, x, y, w, h, txt, size, bold, opaque, underline, italic, align, color, bkcolor, xoffset, yoffset, antialiased); + break; + case WA_FONT_TEXTOUT_WRAPPEDPATHED: + f->textOutWrappedPathed(c, x, y, w, txt, size, bold, opaque, underline, italic, align, color, bkcolor, xoffset, yoffset, antialiased); + break; + case WA_FONT_TEXTOUT_CENTERED: + RECT r; + r.left = x; + r.top = y; + r.right = w; + r.bottom = h; + f->textOutCentered(c, &r, txt, size, bold, opaque, underline, italic, align, color, bkcolor, xoffset, yoffset, antialiased); + break; + } +} + + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int Font::dispatchGetInfo(ifc_canvas *c, const wchar_t *font, int infoid, const wchar_t *txt, int *w, int *h) +{ + int isoverride = 0; + if (WASABI_API_APP->main_isShuttingDown()) return 0; + // mig: Let's not crash if we want to see how big a NULL pointer is. + if (txt == NULL) { + if ( infoid == WA_FONT_GETINFO_WIDTHHEIGHT ) { + if (w != NULL) { + *w = 0; + } + if (h != NULL) { + *h = 0; + } + } + return 0; + } + + int size = c->getTextSize(); + + svc_font *f = requestSkinFont(font, &size); + ASSERT(f != NULL); + + // After we get the font we want, check to see if it is bitmap. + // If bitmap fonts are disallowed, use the truetype override font. + if (f->isBitmap() && useTrueTypeOverride(txt)) + { + int gotdefault = 0; + svc_font *ttFont = requestSkinFont(getTrueTypeOverride(), &size, &gotdefault); + if (ttFont != NULL) + { + if (!gotdefault) + isoverride = 1; + f = ttFont; + } + } + + if (isoverride) { + double f = (double)getTrueTypeOverrideScale() / 100.0f; + size = (int)(size*f); + } + int bold = c->getTextBold(); + int underline = c->getTextUnderline(); + int italic = c->getTextItalic(); + int antialiased = c->getTextAntialias(); + switch (infoid) { + case WA_FONT_GETINFO_WIDTH: + return f->getTextWidth(c, txt, size, bold, underline, italic, antialiased); + case WA_FONT_GETINFO_HEIGHT: + return f->getTextHeight(c, txt, size, bold, underline, italic, antialiased); + case WA_FONT_GETINFO_WIDTHHEIGHT: + f->getTextExtent(c, txt, w, h, size, bold, underline, italic, antialiased); + return 0; + } + return 0; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Install a truetype font from its filename and associate a script_id to it +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +svc_font *Font::installTrueTypeFont(const wchar_t *filename, const wchar_t *path, const wchar_t *id, int scriptid, int allowmapping, int isttfreload) { + + if (!isttfreload) + { + FontDef *fd = new FontDef; + fd->filename = filename; + fd->path = path; + fd->id = id; + fd->scriptid = scriptid; + fd->isbitmap = 0; + fd->allowmapping = allowmapping; + fontdefs.addItem(fd); + } + + StringW file; + + OSFILETYPE ff=OPEN_FAILED; + if (wcschr(filename, ':')) + ff = WFOPEN(filename, WF_READONLY_BINARY); + + if (ff == OPEN_FAILED) + { + file = StringPathCombine(path, filename); + ff = WFOPEN(file, WF_READONLY_BINARY); + } +#ifdef WASABI_COMPILE_SKIN + if (ff == OPEN_FAILED) + { + file = StringPathCombine(SkinParser::getXmlRootPath(), filename); + ff = WFOPEN(file, WF_READONLY_BINARY); + if (ff == OPEN_FAILED) + { + file = StringPathCombine(Skin::getDefaultSkinPath(), filename); + ff = WFOPEN(file, WF_READONLY_BINARY); + if (ff == OPEN_FAILED) + { + DebugString("Font not found %s\n", filename); + // todo: do something if still not found + } + } + } +#endif + if (ff == OPEN_FAILED) { + DebugString("Could not install font %s\n", filename); + return 0; + } + + StringW fs = filename; + wchar_t *p = wcschr(fs.getNonConstVal(), '.'); + if (p) + *p = 0; + PathParserW pp(fs); + fs = pp.getLastString(); + + svc_font *f = newTrueTypeFont(); + if (f && f->addFontResource( ff, fs) ) + { + f->setFontId(id); + f->setScriptId(scriptid); + fontlist.addItem(f); + } else { + DebugString("font.cpp ====== CAN'T LOAD FONT FILE.\n"); + } + + FCLOSE(ff); + return f; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Uninstall all installed fonts +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void Font::uninstallAll(int ttfreload) { + int i; + // delete all by hand + for (i = 0; i < fontlist.getNumItems(); i++) { + svc_font *f = fontlist.enumItem(i); + if (ttfreload && f->isBitmap()) continue; + deleteFont(f); + fontlist.removeByPos(i); + i--; + } + if (!ttfreload) fontdefs.deleteAll(); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Uninstall by scriptid +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void Font::uninstallByScriptId(int scriptid) { + for (int i=0;i<fontlist.getNumItems();i++) { + svc_font *f = fontlist.enumItem(i); + if (f->getScriptId() == scriptid) { + fontlist.removeByPos(i); + deleteFont(f); + i--; + } + } + for (int i=0;i<fontdefs.getNumItems();i++) { + FontDef *fd = fontdefs.enumItem(i); + if (fd->scriptid == scriptid) { + fontdefs.removeByPos(i); + delete fd; + i--; + } + } +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Install a bitmap font and associates a script_id to it +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void Font::installBitmapFont(const wchar_t *filename, const wchar_t *path, const wchar_t *id, int cw, int ch, int hs, int vs, int scriptid, int allowmapping) +{ + FontDef *fd = new FontDef; + fd->filename = filename; + fd->path = path; + fd->id = id; + fd->scriptid = scriptid; + fd->isbitmap = 1; + fd->allowmapping = allowmapping; + fontdefs.addItem(fd); + + BitmapFont *f = new BitmapFont; + f->setFontBitmap(filename, path); + f->setFontId(id); + f->setFontMetrics(cw, ch, hs, vs); + f->setScriptId(scriptid); + fontlist.addItem(f); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Requests a Font* from its id +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +svc_font *Font::requestSkinFont(const wchar_t *id, int *size, int *gotdefault) +{ + if (gotdefault) *gotdefault = 0; + int oldsize = size ? *size : -1; + const wchar_t *mapped_id = getFontMapping(id, size); + if (mapped_id != NULL) + id = mapped_id; + + // First try to get a font by that id + foreach_reverse(fontlist) + const wchar_t *thisid = fontlist.getfor()->getFontId(); + if (thisid && !WCSICMP(thisid, id)) + return fontlist.getfor(); + endfor + // if it wasnt found, try to load a wa-installed ttfont with this face name + foreach_reverse(fontlist) + const wchar_t *facename=fontlist.getfor()->getFaceName(); + if (facename && !WCSICMP(facename, id)) return fontlist.getfor(); + endfor + + // not found, try to reload it front the list of fonts defined by the skin + foreach(fontdefs) + FontDef *fd = fontdefs.getfor(); + if (!WCSICMP(fd->id, id)) + { + if (!fd->isbitmap) + { + svc_font *f = installTrueTypeFont(fd->filename, fd->path, fd->id, fd->scriptid, fd->allowmapping, 1); + if (f) return f; + } + } + endfor; + + /* + for (i=fontlist.getNumItems()-1;i>=0;i--) { + const char *thisid = fontlist.enumItem(i)->getFontId(); + if (thisid && STRCASEEQL(thisid, "wasabi.font.ttf.default" )) + return fontlist.enumItem(i); + } + */ + + // not found ? try to find it in the windows fonts directory + { + wchar_t *fp = WMALLOC(WA_MAX_PATH); + Wasabi::Std::getFontPath(WA_MAX_PATH, fp); + StringW file; + file.own(fp); +// FREE(fp); // benski> no need because we now own it + file.AppendPath(StringPrintfW(L"%s%s", id, WCSCASESTR(id, L".ttf") == NULL ? L".ttf":L"")); + + if (!WACCESS(file, 0)) + { + svc_font *f = newTrueTypeFont(); + f->setFontFace(id); + f->setFontId(id); + OSFILETYPE ff = WFOPEN(file, WF_READONLY_BINARY); + if (ff != OPEN_FAILED) + { + if (f->addFontResource(ff, id)) + { + DebugStringW(L"font.cpp ====== FONT FOR ID=%s NOT FOUND. USING WIN FONT FILE:\n%s\n", id, file.getValue()); + fontlist.addItem(f); + } + } else { + DebugStringW(L"font.cpp ====== FONT FOR ID=%s NOT FOUND. CANNOT OPEN WIN FONT FILE:\n%s\n", id, file.getValue()); + delete f; + f = NULL; + } + return f; + } + } + + // not found ? ask the Std:: interface for the folder and the + // default fontname (ie: one you know will always be in the OS) + svc_font *f = newTrueTypeFont(); + if (f) { + if (gotdefault) *gotdefault = 1; + if (oldsize != -1 && size) { + *size = oldsize; + double f = (double)Wasabi::Std::getDefaultFontScale() / 100.0; + *size = (int)(*size*f); + } + // Query Std:: and build the path to the default font file. + wchar_t *fontPath = WMALLOC(WA_MAX_PATH); + Wasabi::Std::getFontPath(WA_MAX_PATH, fontPath); + wchar_t fontFile[WA_MAX_PATH] = {0}; + Wasabi::Std::getDefaultFont(WA_MAX_PATH, fontFile); + StringW defaultFont; + defaultFont.own(fontPath); + defaultFont.AppendPath(fontFile); +// FREE(fontFile); + StringW fs = defaultFont; + wchar_t *p = wcschr(fs.getNonConstVal(), '.'); + if (p) *p = 0; + PathParserW pp(fs); + fs = pp.getLastString(); + f->setFontFace(fs); + f->setFontId(id); + // Open it and load it as the font resource. + OSFILETYPE ff = WFOPEN(defaultFont, WF_READONLY_BINARY); + if (ff != OPEN_FAILED) { + if (f->addFontResource(ff, fs)) + { + DebugStringW(L"font.cpp ====== FONT FOR ID=%s NOT FOUND. USING DEFAULT FONT FILE:\n%s\n", id, defaultFont); + fontlist.addItem(f); + } + } else { + DebugStringW(L"font.cpp ====== FONT FOR ID=%s NOT FOUND. CANNOT OPEN FONT FILE:\n%s\n", id, defaultFont); + delete f; + f = NULL; + } + } else { + DebugString("font.cpp ====== CAN'T GET NEW FONT FILE.\n"); + delete f; + f = NULL; + } + + +#ifdef _WIN32 + if (f == NULL) { + // not found :((((( grab the default font data and use this, whatever it is + f = newTrueTypeFont(); + if (f) + { + HDC dc = GetDC(GetDesktopWindow()); + HDC dc2 = CreateCompatibleDC(dc); + SelectObject(dc2, GetStockObject(DEFAULT_GUI_FONT)); + + int datalen = GetFontData(dc2, 0, 0, NULL, 0); + if (datalen > 0) { + void *mem = WASABI_API_MEMMGR->sysMalloc(datalen+1); // freed by the service !! + ASSERT(mem != NULL); + GetFontData(dc2, 0, 0, mem, datalen); + + f->setFontFace(id); + f->setFontId(id); + f->addFontResource2(mem, datalen, id); + + ReleaseDC(GetDesktopWindow(), dc); + DeleteDC(dc2); + fontlist.addItem(f); + return f; + } + delete f; + f = NULL; + } + } +#else +#warning port me +#endif + + if (f == NULL) { + // ok, NOW I'm getting pissed + wchar_t fp[WA_MAX_PATH] = {0}; + Wasabi::Std::getFontPath(WA_MAX_PATH, fp); +#ifdef _WIN32 + Wasabi::Std::messageBox(StringPrintfW(L"Fatal error trying to load truetype fonts.\n\nYou need arial.ttf at the very least, but it does not appear to be in %s", fp), L"Fatal Error", MB_ICONERROR); +#else +#warning port me +#endif + } + + //if (f == NULL) DebugString("font.cpp ====== FALLBACK FOR FONT %s CANNOT BE FOUND IN OUR LISTS.\n",f->getFontId()); + + return f; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Intelligently delete the font +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void Font::deleteFont(svc_font *f) +{ + if (f) + { + if (f->isBitmap()) + { + delete static_cast<BitmapFont *>(f); // we delete our own bitmap fonts. + } + else + { + SvcEnum::release(f); + } + } +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Intelligently make a new truetype font from the service interfaces +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +svc_font *Font::newTrueTypeFont() +{ +/*#ifdef WASABI_COMPILE_CONFIG + const GUID options_guid = + { 0x280876cf, 0x48c0, 0x40bc, { 0x8e, 0x86, 0x73, 0xce, 0x6b, 0xb4, 0x62, 0xe5 } }; + CfgItem *options = WASABI_API_CONFIG->config_getCfgItemByGuid(options_guid); +#endif*/ + + svc_font *retval = NULL; + const wchar_t *name = NULL; + +#ifdef WASABI_COMPILE_CONFIG + //const wchar_t *attr = L"Font Renderer"; + // First, try to find a font service that matches the attribute. +// if (options) { +// char buf[256]; // WHEEE for stack arrays +// if (options->getData(attr, buf, sizeof buf)) { + if (WASABI_API_SKIN->skin_getVersion() >= 1.3) // hardcode win32 renderer for v1.3+ skins + retval = FontSvcEnum(L"Win32 TextOut").getFirst(); + else + retval = FontSvcEnum(cfg_options_fontrenderer.getValue()).getFirst(); + +#else +#ifndef WASABI_FONT_RENDERER +#error You need to define WASABI_FONT_RENDERER (ie: #define WASABI_FONT_RENDERER "Freetype") +#endif + retval = FontSvcEnum(WASABI_FONT_RENDERER).getFirst(); +#endif +#ifdef WASABI_COMPILE_CONFIG +// } +// } + + // If we can't find one, fallback and just take the first. + if (!retval) + { + retval = FontSvcEnum().getFirst(); + if (retval != NULL) + name = retval->getFontSvcName(); + } + + // If we had to fallback, remember the fallback service in the attribute. + if (name/* && options*/) + { + //options->setData(attr, name); + cfg_options_fontrenderer.setValue(name); + } +#endif + + return retval; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Test whether to forbid bitmap fonts. +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int Font::useTrueTypeOverride(const wchar_t *txt) + +{ + if (cfg_options_no7bitsttfoverride.getValueAsInt()) + { + const wchar_t *p = (const wchar_t *)txt; + while (p && *p) + { + // TODO: benski> some characters above 127 can be handled by the bitmap fonts - it might be worth checking those explicitly + if (*p & 0xFF80) + break; + p++; + } + if (!*p) return 0; + } +#ifdef WASABI_COMPILE_CONFIG +/* // {280876CF-48C0-40bc-8E86-73CE6BB462E5} + const GUID options_guid = + { 0x280876cf, 0x48c0, 0x40bc, { 0x8e, 0x86, 0x73, 0xce, 0x6b, 0xb4, 0x62, 0xe5 } }; + return !_intVal(WASABI_API_CONFIG->config_getCfgItemByGuid(options_guid), "Use bitmap fonts (no international support)", 1);*/ + return !cfg_options_allowbitmapfonts.getValueAsInt(); +#else + return WASABI_FONT_TTFOVERRIDE; +#endif +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Get the font to be used to override bitmap fonts. +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +const wchar_t *Font::getTrueTypeOverride() +{ +#ifdef WASABI_COMPILE_CONFIG + return cfg_options_ttfoverridefont.getValue(); +#else + return L"Arial"; +#warning TODO +#endif +} + +int Font::getTrueTypeOverrideScale() +{ +#ifdef WASABI_COMPILE_CONFIG + return cfg_options_ttfoverridescale.getValueAsInt(); +#else + return 1; +#warning TODO +#endif +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Returns the font mapping for this font & skin, if font mapper is on and if there is a mapping, otherwise returns null +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +const wchar_t *Font::getFontMapping(const wchar_t *id, int *size) +{ + if (cfg_options_usefontmapper.getValueAsInt()) + { + wchar_t t[256]=L""; + StringW tmp; + tmp.printf(L"Skin:%s/Font Mapping/%s",WASABI_API_SKIN->getSkinName(), id); + WASABI_API_CONFIG->getStringPrivate(tmp, t, 256, L""); + + tmp.printf(L"Skin:%s/Font Mapping/%s_scale",WASABI_API_SKIN->getSkinName(), id); + int v = WASABI_API_CONFIG->getIntPrivate(tmp, -1); + if (!*t) + { + tmp.printf(L"Font Mapping/%s", id); + WASABI_API_CONFIG->getStringPrivate(tmp, t, 256, L""); + tmp.printf(L"Font Mapping/%s_scale", id); + v = WASABI_API_CONFIG->getIntPrivate(tmp, -1); + } + mapping = t; + if (mapping.isempty()) return NULL; + if (size != NULL) + { + if (v != -1) + { + double f = (double)v / 100.0; + *size = (int)((double)*size * f); + } + } + return mapping; + } + return NULL; +} + +StringW Font::mapping;
\ No newline at end of file diff --git a/Src/Wasabi/api/font/font.h b/Src/Wasabi/api/font/font.h new file mode 100644 index 00000000..8e1f15f2 --- /dev/null +++ b/Src/Wasabi/api/font/font.h @@ -0,0 +1,55 @@ +#ifndef __FONT_H +#define __FONT_H + +#include <bfc/ptrlist.h> +#include <bfc/string/StringW.h> + +class ifc_canvas; +class svc_font; +class svc_fontMaker; + +class FontDef { + public: + StringW filename; + StringW path; + StringW id; + int allowmapping; + int isbitmap; + int scriptid; +}; + +class Font { + public: + static void init(); + + static svc_font *installTrueTypeFont(const wchar_t *filename, const wchar_t *path, const wchar_t *id, int scriptid, int allowmapping, int isreload); // call this to install a new font + static void installBitmapFont(const wchar_t *filename, const wchar_t *path, const wchar_t *id, int charwidth, int charheight, int hspacing, int vspacing, int scriptid, int allowmapping); + static void uninstallAll(int isttfreload=0); + static void uninstallByScriptId(int scriptid); + + static svc_font *requestSkinFont(const wchar_t *id, int *size=NULL, int *gotdefault=NULL); // call this to get a Font pointer to a font id, pass your size if you have one, so that the mapper can do its job. + static void dispatchTextOut(ifc_canvas *c, int style, int x, int y, int w, int h, const wchar_t *txt); + static int dispatchGetInfo(ifc_canvas *c, const wchar_t *font, int infoid, const wchar_t *txt, int *w, int *h); + + static int useTrueTypeOverride(const wchar_t *txt); + static const wchar_t *getTrueTypeOverride(); + static int getTrueTypeOverrideScale(); + static int getNumFonts() { return fontlist.getNumItems(); } + + static FontDef *enumFontDef(int n) { return fontdefs.enumItem(n); } + static int getNumFontDefs() { return fontdefs.getNumItems(); } + + static const wchar_t *getFontMapping(const wchar_t *id, int *size); + + private: + static void deleteFont(svc_font *font); + static svc_font *newTrueTypeFont(); + + static PtrList<svc_font> fontlist; + static PtrList<FontDef> fontdefs; + StringW font_id; + int scriptid; + static StringW mapping; +}; + +#endif diff --git a/Src/Wasabi/api/font/fontapi.cpp b/Src/Wasabi/api/font/fontapi.cpp new file mode 100644 index 00000000..c004c65c --- /dev/null +++ b/Src/Wasabi/api/font/fontapi.cpp @@ -0,0 +1,32 @@ +#include <precomp.h> +#include "fontapi.h" +#include <api/font/font.h> + +api_font *fontApi = NULL; + +FontApi::FontApi() +{ + Font::init(); +} + +FontApi::~FontApi() +{ + Font::uninstallAll(); +} + +void FontApi::font_textOut(ifc_canvas *c, int style, int x, int y, int w, int h, const wchar_t *txt) +{ + Font::dispatchTextOut(c, style, x, y, w, h, txt); +} + +int FontApi::font_getInfo(ifc_canvas *c, const wchar_t *font, int infoid, const wchar_t *txt, int *w, int *h) +{ + return Font::dispatchGetInfo(c, font, infoid, txt, w, h); +} + +#define CBCLASS FontApi +START_DISPATCH; + VCB(API_FONT_FONT_TEXTOUT, font_textOut); + CB(API_FONT_FONT_GETINFO, font_getInfo); +END_DISPATCH; +#undef CBCLASS
\ No newline at end of file diff --git a/Src/Wasabi/api/font/fontapi.h b/Src/Wasabi/api/font/fontapi.h new file mode 100644 index 00000000..3a169ac3 --- /dev/null +++ b/Src/Wasabi/api/font/fontapi.h @@ -0,0 +1,20 @@ +#ifndef __FONTAPI_H +#define __FONTAPI_H + +#include <api/font/api_font.h> + +class FontApi : public api_font +{ +public: + FontApi(); + ~FontApi(); + void font_textOut(ifc_canvas *c, int style, int x, int y, int w, int h, const wchar_t *txt); + int font_getInfo(ifc_canvas *c, const wchar_t *font, int infoid, const wchar_t *txt, int *w, int *h); + +protected: + RECVS_DISPATCH; +}; + +extern api_font *fontApi; + +#endif diff --git a/Src/Wasabi/api/font/linux/truetypefont_linux.cpp b/Src/Wasabi/api/font/linux/truetypefont_linux.cpp new file mode 100644 index 00000000..188d09b6 --- /dev/null +++ b/Src/Wasabi/api/font/linux/truetypefont_linux.cpp @@ -0,0 +1,472 @@ +// ============================================================================================================================================================ +// Font abstract class + statics to install TT fonts and Bitmap fonts +// ============================================================================================================================================================ + +// what other linux headers need be made? + +#include "truetypefont_linux.h" + +#include <tataki/canvas/ifc_canvas.h> +#include "../../bitmap.h" + +// ============================================================================================================================================================ +// TrueTypeFont_Linux implementation. +// ============================================================================================================================================================ + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +TrueTypeFont_Linux::TrueTypeFont_Linux() { + font = NULL; + antialias_canvas = NULL; + DColdstate = NULL; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +TrueTypeFont_Linux::~TrueTypeFont_Linux() { + ASSERT(fontstack.isempty()); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int TrueTypeFont_Linux::isBitmap() { + return 0; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Linux::addFontResource(FILE *in){ + ASSERT(in != NULL); + OutputDebugString( "portme -- TrueTypeFont_Linux::addFontResource\n" ); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Linux::setFontFace(const char *face) { + face_name = face; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +const char *TrueTypeFont_Linux::getFaceName() { + return face_name; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Linux::prepareCanvas(ifc_canvas *c, int size, int bold, int opaque, int underline, int italic, COLORREF color, COLORREF bkcolor) { + String fontname = StringPrintf( "-*-%s-%s-%s-*--%d-*-*-*-*-*-*-*", + (const char *)face_name, + bold?"bold":"medium", + italic?"i":"r", size * 3/4 ); + font = XLoadQueryFont( Linux::getDisplay(), (const char *)fontname ); + if ( font == NULL ) { + fontname = StringPrintf( "-*-arial-%s-%s-*--%d-*-*-*-*-*-*-*", + bold?"bold":"medium", + italic?"i":"r", size * 3/4 ); + font = XLoadQueryFont( Linux::getDisplay(), (const char *)fontname ); + + if ( font == NULL ) { + fontname = StringPrintf( "-*-courier-%s-%s-*--%d-*-*-*-*-*-*-*", + bold?"bold":"medium", + italic?"i":"r", size * 3/4 ); + font = XLoadQueryFont( Linux::getDisplay(), (const char *)fontname ); + } + } + ASSERTPR( font != NULL, fontname ); + XSetFont( Linux::getDisplay(), c->getHDC()->gc, font->fid ); + XSetForeground( Linux::getDisplay(), c->getHDC()->gc, color ); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Linux::restoreCanvas(ifc_canvas *c) { + if ( font != NULL ) { + XFreeFont( Linux::getDisplay(), font ); + font = NULL; + } +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +ifc_canvas *TrueTypeFont_Linux::prepareAntialias(ifc_canvas *c, int x, int y, const char *txt, int size, int bold, int opaque, int underline, int italic, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int w, int h) { + ASSERT(antialias_canvas == NULL); + BaseCloneCanvas canvas(c); + prepareCanvas(&canvas, size, bold, opaque, underline, italic, color, bkcolor); + al_w = MAX(2,canvas.getTextWidth(txt) * 2 + xoffset*2); + al_h = MAX(2,canvas.getTextHeight()*2 + yoffset*2); + restoreCanvas(&canvas); + if (w != -1) { + al_w = w * 2; + al_dw = w; + } else al_dw = w; + if (h != -1) { + al_h = h * 2; + al_dh = h; + } else al_dh = h; + al_mask=RGB(0,0,0); + if (color == al_mask) al_mask=RGB(255,255,255); + antialias_canvas = new BltCanvas(al_w, al_h); + antialias_canvas->fillBits(0); + prepareCanvas(antialias_canvas, size*2, bold, opaque, underline, italic, color, bkcolor); + if (al_mask != 0) antialias_canvas->fillBits(al_mask); + al_x = x; al_y = y; al_xo = xoffset; al_yo = yoffset; + return antialias_canvas; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Linux::completeAntialias(ifc_canvas *c) { + BaseCloneCanvas canvas(c); + antialias_canvas->maskColor(al_mask, RGB(0,0,0)); + BltCanvas *ac = new BltCanvas(al_w/2, al_h/2); + antialias_canvas->antiAliasTo(ac, al_w/2, al_h/2, 2); + SkinBitmap *b = ac->getSkinBitmap(); + RECT src={0,0,al_w/2,al_h/2}; + RECT dst={al_x+al_xo,al_y+al_yo,al_x+al_xo+al_dw,al_y+al_yo+al_dh}; + b->blitToRect(&canvas, &src, &dst); + delete ac; + restoreCanvas(antialias_canvas); + delete antialias_canvas; + antialias_canvas = NULL; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Linux::textOut(ifc_canvas *c, int x, int y, const char *txt, int size, int bold, int opaque, int underline, int italic, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialiased) { + if (antialiased) { + ifc_canvas *canvas = prepareAntialias(c, x, y, txt, size, bold, opaque, underline, italic, color, bkcolor, xoffset, yoffset, -1, -1); + + HDC hdc = c->getHDC(); + XDrawString( Linux::getDisplay(), hdc->d, hdc->gc, 0, 0, txt, STRLEN(txt) ); + + completeAntialias(c); + } else { + prepareCanvas(c, size, bold, opaque, underline, italic, color, bkcolor); + + int dir, ascent, descent; + XCharStruct overall; + XTextExtents( font, txt, STRLEN( txt ), &dir, &ascent, &descent, &overall ); + + HDC hdc = c->getHDC(); + XDrawString( Linux::getDisplay(), hdc->d, hdc->gc, x+xoffset, y+yoffset+ascent, txt, STRLEN(txt) ); + + + restoreCanvas(c); + } +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Linux::textOut(ifc_canvas *c, int x, int y, int w, int h, const char *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialiased) { + if (antialiased) { + ifc_canvas *canvas = prepareAntialias(c, x, y, txt, size, bold, opaque, underline, italic, color, bkcolor, xoffset, yoffset, w, h); + RECT al_r={0,0,w*2,h*2}; + + HDC hdc = c->getHDC(); + XDrawString( Linux::getDisplay(), hdc->d, hdc->gc, al_r.left, al_r.top, txt, STRLEN(txt) ); + + completeAntialias(c); + } else { + RECT r; + r.left = x+xoffset; + r.top = y+yoffset; + r.right = r.left + w; + r.bottom = r.top + h; + prepareCanvas(c, size, bold, opaque, underline, italic, color, bkcolor); + + int dir, ascent, descent; + XCharStruct overall; + XTextExtents( font, txt, STRLEN( txt ), &dir, &ascent, &descent, &overall ); + int xstart = r.left; + + if ( align == DT_RIGHT ) { + int width = XTextWidth( font, txt, STRLEN( txt ) ); + xstart = r.right - width; + + } else if ( align == DT_CENTER ) { + int width = XTextWidth( font, txt, STRLEN( txt ) ); + xstart = (r.right + r.left - width) / 2; + } + + HDC hdc = c->getHDC(); + XDrawString( Linux::getDisplay(), hdc->d, hdc->gc, xstart, r.top + ascent, txt, STRLEN(txt) ); + + restoreCanvas(c); + } +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Linux::textOutEllipsed(ifc_canvas *c, int x, int y, int w, int h, const char *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialiased) { + if (antialiased) { + ifc_canvas *canvas = prepareAntialias(c, x, y, txt, size, bold, opaque, underline, italic, color, bkcolor, xoffset, yoffset, w, h); + RECT al_r={0,0,w*2,h*2}; + + OutputDebugString( "portme -- TrueTypeFont_Linux::textoutEllipsed (antialiased)\n" ); + + completeAntialias(c); + } else { + RECT r; + r.left = x+xoffset; + r.top = y+yoffset; + r.right = r.left + w; + r.bottom = r.top + h; + prepareCanvas(c, size, bold, opaque, underline, italic, color, bkcolor); + + if ( txt == NULL ) + return; + + int dir, ascent, descent; + XCharStruct overall; + XTextExtents( font, txt, STRLEN( txt ), &dir, &ascent, &descent, &overall ); + + char *tmp = (char *)MALLOC( STRLEN( txt ) + 3 ); + STRCPY( tmp, txt ); + + if ( XTextWidth( font, tmp, STRLEN( tmp ) ) > r.right - r.left ) { + int len = STRLEN( tmp ); + char *p = tmp + len; + int width = r.right - r.left - XTextWidth( font, "...", 3 ); + while( XTextWidth( font, tmp, len ) > width ) { + *p-- = '\0'; + len--; + } + STRCPY( p, "..." ); + } + + HDC hdc = c->getHDC(); + XDrawString( Linux::getDisplay(), hdc->d, hdc->gc, r.left, r.top + ascent, tmp, STRLEN(tmp) ); + + FREE( tmp ); + + restoreCanvas(c); + } +} + +const char *find_break( int (*width_func)(void *, const char *, int ), + void *f, const char *str, int width ) { + const char *softret, *lastsoft, *hardret; + + if ( width_func( f, str, STRLEN( str ) ) <= width ) + return str + STRLEN( str ); + + for( hardret = str; *hardret; hardret ++ ) + if ( *hardret == '\r' || *hardret == '\n' ) + break; + + if ( hardret && width_func( f, str, hardret - str ) <= width ) { + return hardret; + } + for( softret = str; *softret && !isspace( *softret ); softret++ ) + ; + + if ( width_func( f, str, softret - str ) <= width ) { + do { + lastsoft = softret; + + for( softret = lastsoft+1; *softret && !isspace( *softret ); softret++ ) + ; + + } while ( *lastsoft && width_func( f, str, softret - str ) <= width ); + + softret = lastsoft; + } else { + for( softret = str; *softret; softret++ ) + if ( width_func( f, str, softret - str ) > width ) + break; + + softret--; + } + + return softret; +} + +int xlib_width( void *data, const char *str, int len ) { + return XTextWidth( (XFontStruct *)data, str, len ); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Linux::textOutWrapped(ifc_canvas *c, int x, int y, int w, int h, const char *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialiased) { + if (antialiased) { + ifc_canvas *canvas = prepareAntialias(c, x, y, txt, size, bold, opaque, underline, italic, color, bkcolor, xoffset, yoffset, w, h); + RECT al_r={0,0,w*2,h*2}; + + OutputDebugString( "portme -- TrueTypeFont_Linux::textoutWrapped (antialiased)\n" ); + + completeAntialias(c); + } else { + RECT r; + r.left = x+xoffset; + r.top = y+yoffset; + r.right = r.left + w; + r.bottom = r.top + h; + prepareCanvas(c, size, bold, opaque, underline, italic, color, bkcolor); + + + int dir, ascent, descent; + XCharStruct overall; + XTextExtents( font, txt, STRLEN( txt ), &dir, &ascent, &descent, &overall ); + HDC hdc = c->getHDC(); + + int yoff = r.top + ascent; + const char *cur = txt, *next; + int length = STRLEN( txt ); + for (int yoff = r.top + ascent; yoff < r.bottom - descent; yoff += ascent + descent) { + next = find_break(xlib_width, font, cur, r.right - r.left); + XDrawString( Linux::getDisplay(), hdc->d, hdc->gc, r.left, yoff, cur, next - cur ); + for ( cur = next; *cur && isspace( *cur ); cur++ ) + ; + if ( cur >= txt + length ) + break; + } + + + restoreCanvas(c); + } +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Linux::textOutWrappedPathed(ifc_canvas *c, int x, int y, int w, const char *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialiased) { + prepareCanvas(c, size, bold, opaque, underline, italic, color, bkcolor); + RECT r; + char *ptr, *d; + const char *s; + ptr = (char *)MALLOC(STRLEN(txt)+1+4); + for (s = txt, d = ptr; *s; s++, d++) { + if (*s == '/') *d = '\\'; + else *d = *s; + } + r.left = x+xoffset; + r.top = y+yoffset; + r.right = r.left + w; + r.bottom = r.top + getTextHeight(c, size, bold, underline, italic, antialiased); + + OutputDebugString( "portme -- TrueTypeFont_Linux::textoutWrappedPathed\n" ); + + for (d = ptr; *d; d++) { + if (*d == '\\') *d = '/'; + } + + if (antialiased) { + restoreCanvas(c); + + ifc_canvas *canvas = prepareAntialias(c, x, y, txt, size, bold, opaque, underline, italic, color, bkcolor, xoffset, yoffset, w, -1); + RECT al_r={0,0,w*2,al_h}; + + OutputDebugString( "portme -- TrueTypeFont_Linux::textoutWrappedPathed (antialised)\n" ); + + completeAntialias(c); + } else { + int dir, ascent, descent; + XCharStruct overall; + XTextExtents( font, txt, STRLEN( txt ), &dir, &ascent, &descent, &overall ); + + HDC hdc = c->getHDC(); + XDrawString( Linux::getDisplay(), hdc->d, hdc->gc, r.left, r.top + ascent, txt, STRLEN(txt) ); + OutputDebugString( "portme -- TrueTypeFont_Linux::textoutWrappedPathed\n" ); + + restoreCanvas(c); + } + + FREE(ptr); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Linux::textOutCentered(ifc_canvas *c, RECT *r, const char *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialiased) { + ASSERT(r != NULL); + ASSERT(txt != NULL); + RECT rr=*r; + rr.left += xoffset; + rr.right += xoffset; + rr.top += yoffset; + rr.bottom += yoffset; + + if (antialiased) { + ifc_canvas *canvas = prepareAntialias(c, r->left, r->top, txt, size, bold, opaque, underline, italic, color, bkcolor, xoffset, yoffset, r->right-r->left, r->bottom-r->top); + RECT al_r={0,0,(r->right-r->left)*2,(r->bottom-r->top)*2}; + + OutputDebugString( "portme -- TrueTypeFont_Linux::textoutCentered (antialiased)\n" ); + + completeAntialias(c); + } else { + prepareCanvas(c, size, bold, opaque, underline, italic, color, bkcolor); + + int dir, ascent, descent, width; + XCharStruct overall; + XTextExtents( font, txt, STRLEN( txt ), &dir, &ascent, &descent, &overall ); + width = XTextWidth( font, txt, STRLEN( txt ) ); + + HDC hdc = c->getHDC(); + XDrawString( Linux::getDisplay(), hdc->d, hdc->gc, (rr.right + rr.left - width) / 2, rr.top + ascent, txt, STRLEN(txt) ); + + restoreCanvas(c); + } +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int TrueTypeFont_Linux::getTextWidth(ifc_canvas *c, const char *text, int size, int bold, int underline, int italic, int antialiased) { + int w; + getTextExtent(c, text, &w, NULL, size, bold, underline, italic, antialiased); + return w; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int TrueTypeFont_Linux::getTextHeight(ifc_canvas *c, const char *text, int size, int bold, int underline, int italic, int antialiased) { + int h; + getTextExtent(c, text, NULL, &h, size, bold, underline, italic, antialiased); + { + // calcul for multiline text + const char *p=text; + int n=0; + while(*p!=0) if(*p++=='\n') n++; + if(n) h*=(n+1); + } + return h; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Linux::getTextExtent(ifc_canvas *c, const char *txt, int *w, int *h, int size, int bold, int underline, int italic, int antialiased) { + SIZE rsize={0,0}; + ASSERT(txt != NULL); + if (*txt == 0) { + if (w != NULL) *w = 0; + if (h != NULL) *h = 0; + return; + } + + if (antialiased) + prepareCanvas(c, size*2, bold, 0, underline, italic, 0, 0); + else + prepareCanvas(c, size, bold, 0, underline, italic, 0, 0); + + int dir, ascent, descent; + XCharStruct overall; + XTextExtents( font, txt, STRLEN( txt ), &dir, &ascent, &descent, &overall ); + rsize.cy = ascent + descent; + rsize.cx = XTextWidth( font, txt, STRLEN( txt ) ); + + if (w != NULL) *w = rsize.cx; + if (h != NULL) *h = rsize.cy; + + if (antialiased) { + if (w != NULL) *w /= 2; + if (h != NULL) *h /= 2; + } + + restoreCanvas(c); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int TrueTypeFont_Linux::getTextHeight(ifc_canvas *c, int size, int bold, int underline, int italic, int antialiased) { + return getTextHeight(c, "My", size, bold, underline, italic, antialiased); +} + + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +// code from ftp.microsoft.com/Softlib/MSLFILES/FONTINST.EXE +// retrieves the friendly font name from its filename +char *TrueTypeFont_Linux::filenameToFontFace(const char *pszFile) { + static char lpszLongName[256]; + unsigned i; + char namebuf[255]; + int fp; + unsigned short numNames; + long curseek; + unsigned cTables; + sfnt_OffsetTable OffsetTable; + sfnt_DirectoryEntry Table; + sfnt_NamingTable NamingTable; + sfnt_NameRecord NameRecord; + + OutputDebugString( "portme -- TrueTypeFont_Linux::filenameToFontFace\n" ); + + return FALSE; +} diff --git a/Src/Wasabi/api/font/linux/truetypefont_linux.h b/Src/Wasabi/api/font/linux/truetypefont_linux.h new file mode 100644 index 00000000..b98046c5 --- /dev/null +++ b/Src/Wasabi/api/font/linux/truetypefont_linux.h @@ -0,0 +1,65 @@ +#ifndef __TRUETYPEFONT_LINUX_H +#define __TRUETYPEFONT_LINUX_H + +#include "../../../studio/services/svc_font.h" + +#include "../../string.h" +#include "../../stack.h" +#include "../truetypefontdef.h" + +class ifc_canvas; +class BltCanvas; + +class TrueTypeFont_Linux : public svc_fontI { + public: + TrueTypeFont_Linux(); + virtual ~TrueTypeFont_Linux(); + + virtual void textOut(ifc_canvas *c, int x, int y, const char *txt, int size, int bold, int opaque, int underline, int italic, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialias); + virtual void textOut2(ifc_canvas *c, int x, int y, int w, int h, const char *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialias); + virtual void textOutEllipsed(ifc_canvas *c, int x, int y, int w, int h, const char *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialias); + virtual void textOutWrapped(ifc_canvas *c, int x, int y, int w, int h, const char *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialias); + virtual void textOutWrappedPathed(ifc_canvas *c, int x, int y, int w, const char *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialias); + virtual void textOutCentered(ifc_canvas *c, RECT *r, const char *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialias); + virtual int getTextWidth(ifc_canvas *c, const char *text, int size, int bold, int underline, int italic, int antialias); + virtual int getTextHeight(ifc_canvas *c, const char *text, int size, int bold, int underline, int italic, int antialias); + virtual int getTextHeight2(ifc_canvas *c, int size, int bold, int underline, int italic, int antialias); + virtual void getTextExtent(ifc_canvas *c, const char *text, int *w, int *h, int size, int bold, int underline, int italic, int antialias); + + virtual void setFontId(const char *id) { font_id = id; } + virtual const char *getFontId() { return font_id; } + virtual int getScriptId() { return scriptid; } + virtual void setScriptId(int id) { scriptid = id; } + + virtual int isBitmap(); + virtual void setFontFace(const char *face); + virtual int addFontResource(FILE *f); + virtual const char *getFaceName(); + + virtual const wchar_t *getFontSvcName() { return "Linux"; } + static const char *getServiceName() { return "Linux font renderer"; } + + protected: + static char *filenameToFontFace(const wchar_t *filename); + void prepareCanvas(ifc_canvas *c, int size, int bold, int opaque, int underline, int italic, COLORREF color, COLORREF bkcolor); + void restoreCanvas(ifc_canvas *c); + + protected: + String font_id; + int scriptid; + + private: + ifc_canvas *prepareAntialias(ifc_canvas *c, int x, int y, const char *txt, int size, int bold, int opaque, int underline, int italic, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int w, int h); + void completeAntialias(ifc_canvas *c); + + String face_name; + String tmpfilename; + int DColdstate; + XFontStruct *font; + Stack<fontslot*> fontstack; + BltCanvas *antialias_canvas; + int al_w, al_h, al_x, al_y, al_xo, al_yo, al_dw, al_dh; + COLORREF al_mask; +}; + +#endif diff --git a/Src/Wasabi/api/font/skinfont.cpp b/Src/Wasabi/api/font/skinfont.cpp new file mode 100644 index 00000000..d1987dfa --- /dev/null +++ b/Src/Wasabi/api/font/skinfont.cpp @@ -0,0 +1,43 @@ +#include "precomp.h" +#include "skinfont.h" +#include "api.h" +#include "../bfc/std.h" + +SkinFont::SkinFont() { +} + +SkinFont::~SkinFont() { + if (!tempFn.isempty()) { +#ifdef WIN32 + RemoveFontResource(tempFn); +#else + DebugString( "portme -- SkinFont::~SkinFont\n" ); +#endif + UNLINK(tempFn); + } +} + +int SkinFont::setXmlOption(const char *paramname, const char *strvalue) { + return 0; +} + +void SkinFont::installFont(OSFNSTR filename, OSFNSTR path) { + FILE *in,*out; + StringPrintf temp("%s%s", path, filename); + in = WFOPEN(temp, L"rb"); + if (!in) return; + int len = FGETSIZE(in); + MemBlock<char> m(len); + FREAD(m.getMemory(), len, 1, in); + tempFn = TMPNAM(NULL); + out = FOPEN(tempFn, "wb"); + ASSERT(out); + FWRITE(m.getMemory(), len, 1, out); + FCLOSE(out); + FCLOSE(in); +#ifdef WIN32 + AddFontResource(tempFn); +#else + DebugString( "portme -- SkinFont::installFont\n" ); +#endif +} diff --git a/Src/Wasabi/api/font/skinfont.h b/Src/Wasabi/api/font/skinfont.h new file mode 100644 index 00000000..4780c136 --- /dev/null +++ b/Src/Wasabi/api/font/skinfont.h @@ -0,0 +1,17 @@ +#ifndef _SKINFONT_H +#define _SKINFONT_H + +#include <api/skin/xmlobject.h> + +class SkinFont : public XmlObjectI +{ +public: + SkinFont(); + ~SkinFont(); + void installFont(const wchar_t *filename, const wchar_t *path); + virtual int setXmlOption(const wchar_t *name, const wchar_t *val); +private: + StringW tempFn; +}; + +#endif diff --git a/Src/Wasabi/api/font/svc_fontI.h b/Src/Wasabi/api/font/svc_fontI.h new file mode 100644 index 00000000..76a9ad9c --- /dev/null +++ b/Src/Wasabi/api/font/svc_fontI.h @@ -0,0 +1,39 @@ +#ifndef NULLSOFT_WASABI_SVC_FONTI_H +#define NULLSOFT_WASABI_SVC_FONTI_H + +#include <api/service/svcs/svc_font.h> +//#include <tataki/canvas/canvas.h> +class ifc_canvas; +// implementor derives from this one +class NOVTABLE svc_fontI : public svc_font { +public: + + virtual void textOut(ifc_canvas *c, int x, int y, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialias)=0; // abstract interface + virtual void textOut2(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialias)=0; + virtual void textOutEllipsed(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialias)=0; + virtual void textOutWrapped(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialias)=0; + virtual void textOutWrappedPathed(ifc_canvas *c, int x, int y, int w, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialias)=0; + virtual void textOutCentered(ifc_canvas *c, RECT *r, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialias)=0; + virtual int getTextWidth(ifc_canvas *c, const wchar_t *text, int size, int bold, int underline, int italic, int antialias)=0; + virtual int getTextHeight(ifc_canvas *c, const wchar_t *text, int size, int bold, int underline, int italic, int antialias)=0; + virtual int getTextHeight2(ifc_canvas *c, int size, int bold, int underline, int italic, int antialias)=0; + virtual void getTextExtent(ifc_canvas *c, const wchar_t *text, int *w, int *h, int size, int bold, int underline, int italic, int antialias)=0; + + virtual void setFontId(const wchar_t *id)=0; + virtual const wchar_t *getFontId()=0; + virtual const wchar_t *getFaceName()=0; + virtual int isBitmap()=0; + virtual int getScriptId()=0; + virtual void setScriptId(int id)=0; + + virtual void setFontFace(const wchar_t *face)=0; + virtual int addFontResource(OSFILETYPE f, const wchar_t *name)=0; + virtual int addFontResource2(void *mem, int datalen, const wchar_t *name)=0; + + virtual const wchar_t * getFontSvcName()=0; + +protected: + RECVS_DISPATCH; +}; + +#endif
\ No newline at end of file diff --git a/Src/Wasabi/api/font/truetypefontdef.h b/Src/Wasabi/api/font/truetypefontdef.h new file mode 100644 index 00000000..2b54a045 --- /dev/null +++ b/Src/Wasabi/api/font/truetypefontdef.h @@ -0,0 +1,56 @@ +#ifndef __TRUETYPEFONTDEF_H +#define __TRUETYPEFONTDEF_H + +// Macros for TrueType portability +#define FS_2BYTE(p) ( ((unsigned short)((p)[0]) << 8) | (p)[1]) +#define FS_4BYTE(p) ( FS_2BYTE((p)+2) | ( (FS_2BYTE(p)+0L) << 16) ) +#define SWAPW(a) ((short) FS_2BYTE( (unsigned char FAR*)(&a) )) +#define SWAPL(a) ((long) FS_4BYTE( (unsigned char FAR*)(&a) )) + +typedef short int16; +typedef unsigned short uint16; +typedef long int32; +typedef unsigned long uint32; +typedef long sfnt_TableTag; + +typedef struct { + uint16 platformID; + uint16 specificID; + uint16 languageID; + uint16 nameID; + uint16 length; + uint16 offset; +} sfnt_NameRecord; + +typedef struct { + uint16 format; + uint16 count; + uint16 stringOffset; +} sfnt_NamingTable; + +typedef struct { + sfnt_TableTag tag; + uint32 checkSum; + uint32 offset; + uint32 length; +} sfnt_DirectoryEntry; + +typedef struct { + int32 version; + uint16 numOffsets; + uint16 searchRange; + uint16 entrySelector; + uint16 rangeShift; + sfnt_DirectoryEntry table[1]; +} sfnt_OffsetTable; +#define OFFSETTABLESIZE 12 + +typedef struct { + int dcstate; + HFONT font; + HFONT prevfont; +} fontslot; + +#define tag_NamingTable 0x656d616e /* 'name' */ + +#endif
\ No newline at end of file diff --git a/Src/Wasabi/api/font/win32/truetypefont_win32.cpp b/Src/Wasabi/api/font/win32/truetypefont_win32.cpp new file mode 100644 index 00000000..46c41ce7 --- /dev/null +++ b/Src/Wasabi/api/font/win32/truetypefont_win32.cpp @@ -0,0 +1,561 @@ +#include "precomp.h" +// ============================================================================================================================================================ +// Font abstract class + statics to install TT fonts and Bitmap fonts +// ============================================================================================================================================================ +#define WIN32_LEAN_AND_MEAN +#include <fcntl.h> +#include "../nu/ns_wc.h" +#include "truetypefont_win32.h" + +#include <tataki/canvas/bltcanvas.h> +#include <tataki/bitmap/bitmap.h> +#include <bfc/file/tmpnamestr.h> +#include <api/memmgr/api_memmgr.h> +#if UTF8 +#ifdef WANT_UTF8_WARNINGS +#pragma CHAT("mig", "all", "UTF8 is enabled in std.cpp -- Things might be screwy till it's all debugged?") +#endif +# include <bfc/string/encodedstr.h> +#endif +#define VERTICAL_LPADDING 0 +#define VERTICAL_RPADDING 2 +#define VERTICAL_TPADDING 1 +#define VERTICAL_BPADDING 1 + +/** ============================================================================================================================================================ + ** TrueTypeFont_Win32 implementation. + ** + ** TODO: + ** use GDI transformation to draw in 72 DPI + ** fractional point sizes? + ** =========================================================================================================================================================== + */ + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +TrueTypeFont_Win32::TrueTypeFont_Win32() +{ + scriptid = 0; + font = oldFont = NULL; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +TrueTypeFont_Win32::~TrueTypeFont_Win32() +{ + if (!tmpfilename.isempty()) + { + RemoveFontResourceW(tmpfilename); + // explict call to this instead of UNLINK allows correct removal of the temp files + _wunlink(tmpfilename); + } +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int TrueTypeFont_Win32::isBitmap() +{ + return 0; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int TrueTypeFont_Win32::addFontResource(OSFILETYPE in, const wchar_t *name) +{ + ASSERT(in != NULL); + + int len = (int)FGETSIZE(in); + OSFILETYPE out; + char *m = (char *)MALLOC(len); + ASSERT(m != NULL); + FREAD(m, len, 1, in); + TmpNameStrW tempfn; + out = WFOPEN(tempfn, L"wb"); + ASSERT(out != OPEN_FAILED); + FWRITE(m, len, 1, out); + FCLOSE(out); + AddFontResourceW(tempfn); + FREE(m); + tmpfilename = tempfn; + setFontFace(filenameToFontFace(tempfn)); + return 1; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int TrueTypeFont_Win32::addFontResource2(void *data, int datalen, const wchar_t *name) +{ + TmpNameStrW tempfn; + OSFILETYPE out = WFOPEN(tempfn, L"wb"); + ASSERT(out != OPEN_FAILED); + FWRITE(data, datalen, 1, out); + FCLOSE(out); + AddFontResourceW(tempfn); + tmpfilename = tempfn; + setFontFace(filenameToFontFace(tempfn)); + + WASABI_API_MEMMGR->sysFree(data); + + return 1; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Win32::setFontFace(const wchar_t *face) +{ + face_name = face; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +const wchar_t *TrueTypeFont_Win32::getFaceName() +{ + return face_name; +} + +static int IsXp_or_higher() +{ + static int checked=0; + static int isXp=0; + if (!checked) + { + OSVERSIONINFO osver; + osver.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); + isXp = ( ::GetVersionEx(&osver) && osver.dwPlatformId == VER_PLATFORM_WIN32_NT && (osver.dwMajorVersion >= 5 )) ? 1 : 0; + checked=1; + } + return isXp; +} + +#ifndef CLEARTYPE_QUALITY +#define CLEARTYPE_QUALITY 5 +#endif +HFONT TrueTypeFont_Win32::MakeFont(int size, int bold, int underline, int italic, int antialiased) +{ + // TODO: we got the height to be in 72 DPI, but how can we get the width??? + int nHeight = MulDiv(size, 72, 96); // this is lame, but we have to do it to match freetype + + int quality; + if (antialiased) + { + if (IsXp_or_higher()) + quality=CLEARTYPE_QUALITY; + else + quality=ANTIALIASED_QUALITY; + } + else + quality=NONANTIALIASED_QUALITY; + + return CreateFontW(-nHeight, 0, 0, 0, bold ? FW_BOLD : FW_NORMAL, + italic, underline, FALSE, DEFAULT_CHARSET, + OUT_TT_ONLY_PRECIS, + CLIP_DEFAULT_PRECIS, + quality, + DEFAULT_PITCH | FF_DONTCARE, face_name); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Win32::prepareCanvas(BltCanvas *canvas, int size, int bold, int opaque, int underline, int italic, int antialiased) +{ + HDC canvasHDC = canvas->getHDC(); + + font = MakeFont(size, bold, underline, italic, antialiased); + oldFont = (HFONT)SelectObject(canvasHDC, font); + + SetBkColor(canvasHDC, RGB(0, 0, 0)); + //SetBkMode(canvasHDC, TRANSPARENT); + SetTextColor(canvasHDC, RGB(255, 255, 255)); +} + +typedef DWORD ARGB; + +#define MIN_TONE 100.0 +//BYTE min = 255, max=0; +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Win32::restoreCanvas(BltCanvas *canvas, ifc_canvas *dest, int w, int h, COLORREF color, COLORREF bkcolor, int antialiased, int _x, int _y) +{ +#ifndef FE_FONTSMOOTHINGCLEARTYPE +#define FE_FONTSMOOTHINGCLEARTYPE 0x0002 +#endif + +#ifndef SPI_GETFONTSMOOTHINGTYPE +#define SPI_GETFONTSMOOTHINGTYPE 0x200A +#endif + + bool clearType = false; + UINT fontSmoothing; + if (antialiased && SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &fontSmoothing, 0)) + clearType = fontSmoothing == FE_FONTSMOOTHINGCLEARTYPE; + + ARGB32 *buf = static_cast<ARGB32 *>(canvas->getBits()); + + for (int y = 0; y < h; y++) + { + int linewidth = y * w; + + for (int x = 0; x < w; x++) + { + + ARGB32* prgb = &buf[linewidth + x]; + unsigned char *pixel = (unsigned char *)prgb; + if (*prgb == 0) + { + // Do nothing + } + else + { + BYTE alpha = 255; + BYTE rAlpha = 255; + BYTE gAlpha = 255; + BYTE bAlpha = 255; + + if (*prgb != 0xFFFFFF) + { + if (clearType) + { + rAlpha = pixel[2]; + gAlpha = pixel[1]; + bAlpha = pixel[0]; + } + + UINT value = pixel[0] + pixel[1] + pixel[2]; + value = value / 3; + alpha = (BYTE)value; + + if (!clearType) + { + rAlpha = alpha; + gAlpha = alpha; + bAlpha = alpha; + } + + //alpha=pixel[0]; + //alpha = (((float)pixel[0] - MIN_TONE) / (255.0 - MIN_TONE)) * 255 ; + + //min = (min > value) ? value : min; + //max = (max < value) ? value : max; + } + + pixel[3] = (BYTE)alpha; + pixel[2] = ((GetRValue(color) * rAlpha) + 128) / 255; + pixel[1] = ((GetGValue(color) * gAlpha) + 128) / 255; + pixel[0] = ((GetBValue(color) * bAlpha) + 128) / 255; + } + } + } + + canvas->blitAlpha(dest, _x + VERTICAL_LPADDING, _y + VERTICAL_TPADDING); + //SkinBitmap *bitmap = canvas->getSkinBitmap(); + //bitmap->blitAlpha(dest, _x + VERTICAL_LPADDING, _y + VERTICAL_TPADDING); + + SelectObject(canvas->getHDC(), oldFont); + oldFont = 0; + DeleteObject(font); + font = 0; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Win32::textOut(ifc_canvas *c, int x, int y, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialiased) +{ + int w, h; + c->getDim(&w, &h); + + if (!h || !w) return; + + BltCanvas canvas; + prepareCanvas(&canvas, size, bold, opaque, underline, italic, antialiased); + canvas.DestructiveResize(w, h); + + TextOutW(canvas.getHDC(), x + xoffset, y + yoffset, txt, wcslen(txt)); + + restoreCanvas(&canvas, c, w, h, color, bkcolor, antialiased); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Win32::textOut2(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialiased) +{ + if (!h || !w) return; + + BltCanvas canvas; + prepareCanvas(&canvas, size, bold, opaque, underline, italic, antialiased); + canvas.DestructiveResize(/*x +*/ w, /*y +*/ h); + + RECT r = { + /*x +*/ xoffset, + /*y + */yoffset, + /*x + */w, + /*y + */h + }; + + DrawTextW(canvas.getHDC(), txt, -1, &r, align | DT_NOPREFIX | DT_NOCLIP); + + restoreCanvas(&canvas, c, /*x + */w, /*y + */h, color, bkcolor, antialiased, x, y); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Win32::textOutEllipsed(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialiased) +{ + if (!h || !w) return; + + BltCanvas canvas; + prepareCanvas(&canvas, size, bold, opaque, underline, italic, antialiased); + canvas.DestructiveResize(/*x + */w, /*y + */h); + + RECT r = { + /*x + */xoffset, + /*y + */yoffset, + /*x + */w, + /*y + */ h + }; + + DrawTextW(canvas.getHDC(), txt, -1, &r, align | DT_NOPREFIX | DT_END_ELLIPSIS | DT_NOCLIP); + restoreCanvas(&canvas, c,/* x + */w, /*y + */h, color, bkcolor, antialiased, x, y); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Win32::textOutWrapped(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialiased) +{ + if (!h || !w) return; + + BltCanvas canvas; + prepareCanvas(&canvas, size, bold, opaque, underline, italic, antialiased); + canvas.DestructiveResize(w, h); + + RECT r; + r.left = x + xoffset; + r.top = y + yoffset; + r.right = r.left + w; + r.bottom = r.top + h; + + DrawTextW(canvas.getHDC(), txt, -1, &r, align | DT_NOPREFIX | DT_WORDBREAK); + + restoreCanvas(&canvas, c, w, h, color, bkcolor, antialiased); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Win32::textOutWrappedPathed(ifc_canvas *c, int x, int y, int w, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialiased) +{ + int w_dummy, h; + c->getDim(&w_dummy, &h); + + if (!h || !w) return; + + BltCanvas canvas; + prepareCanvas(&canvas, size, bold, opaque, underline, italic, antialiased); + canvas.DestructiveResize(w, h); + + RECT r; + wchar_t *ptr, *d; + const wchar_t *s; + ptr = (wchar_t *)MALLOC(sizeof(wchar_t) * (wcslen(txt) + 1 + 4)); + for (s = txt, d = ptr; *s; s++, d++) + { + if (*s == '/') *d = '\\'; + else *d = *s; + } + r.left = x + xoffset; + r.top = y + yoffset; + r.right = r.left + w; + r.bottom = r.top + getTextHeight2(c, size, bold, underline, italic, antialiased); + + DrawTextW(canvas.getHDC(), ptr, -1, &r, align | DT_NOPREFIX | DT_PATH_ELLIPSIS | DT_SINGLELINE | DT_MODIFYSTRING | DT_CALCRECT); + + for (d = ptr; *d; d++) + { + if (*d == '\\') *d = '/'; + } + + DrawTextW(canvas.getHDC(), ptr, -1, &r, align | DT_NOPREFIX | DT_PATH_ELLIPSIS | DT_SINGLELINE); + restoreCanvas(&canvas, c, w, h, color, bkcolor, antialiased); + + FREE(ptr); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Win32::textOutCentered(ifc_canvas *c, RECT *r, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialiased) +{ + yoffset += 1; + ASSERT(r != NULL); + ASSERT(txt != NULL); + RECT rr = *r; + rr.left += xoffset; + rr.right += xoffset; + rr.top += yoffset; + rr.bottom += yoffset; + + int w = rr.right - rr.left; + int h = rr.bottom - rr.top; + + RECT r2 = {0, 0, w, h}; + + BltCanvas canvas; + prepareCanvas(&canvas, size, bold, opaque, underline, italic, antialiased); + canvas.DestructiveResize(w, h); + + DrawTextW(canvas.getHDC(), txt, -1, &r2, align | DT_CENTER | /*DT_VCENTER | */DT_NOPREFIX | DT_WORDBREAK | DT_SINGLELINE); + + restoreCanvas(&canvas, c, w, h, color, bkcolor, antialiased, rr.left, rr.top); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int TrueTypeFont_Win32::getTextWidth(ifc_canvas *c, const wchar_t *text, int size, int bold, int underline, int italic, int antialiased) +{ + int w = 0; + getTextExtent(c, text, &w, NULL, size, bold, underline, italic, antialiased); + return w; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int TrueTypeFont_Win32::getTextHeight(ifc_canvas *c, const wchar_t *text, int size, int bold, int underline, int italic, int antialiased) +{ + int h = 0; + getTextExtent(c, text, NULL, &h, size, bold, underline, italic, antialiased); + { + // calcul for multiline text + const wchar_t *p = text; + int n = 0; + while (p && *p != 0) if (*p++ == '\n') n++; + if (n) h *= (n + 1); + } + return h ; +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +void TrueTypeFont_Win32::getTextExtent(ifc_canvas *c, const wchar_t *txt, int *w, int *h, int size, int bold, int underline, int italic, int antialiased) +{ + SIZE rsize = {0, 0}; + ASSERT(txt != NULL); + if (*txt == 0) + { + if (w != NULL) *w = 0; + if (h != NULL) *h = 0; + return ; + } + + HFONT newFont = MakeFont(size, bold, underline, italic, antialiased); + HFONT theOldFont = (HFONT)SelectObject(c->getHDC(), newFont); + GetTextExtentPoint32W(c->getHDC(), txt, wcslen(txt), &rsize); + + SelectObject(c->getHDC(), theOldFont); + DeleteObject(newFont); + + if (w != NULL) *w = rsize.cx + VERTICAL_LPADDING + VERTICAL_RPADDING; + if (h != NULL) *h = rsize.cy + VERTICAL_TPADDING + VERTICAL_BPADDING; + +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +int TrueTypeFont_Win32::getTextHeight2(ifc_canvas *c, int size, int bold, int underline, int italic, int antialiased) +{ + return getTextHeight(c, L"Mg", size, bold, underline, italic, antialiased); +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------------------- +// code from ftp.microsoft.com/Softlib/MSLFILES/FONTINST.EXE +// retrieves the friendly font name from its filename +wchar_t *TrueTypeFont_Win32::filenameToFontFace(const wchar_t *pszFile) +{ + static wchar_t lpszLongName[256]; + unsigned i; + char namebuf[255] = {0}; + int fp; + unsigned short numNames; + long curseek; + unsigned cTables; + sfnt_OffsetTable OffsetTable; + sfnt_DirectoryEntry Table; + sfnt_NamingTable NamingTable; + sfnt_NameRecord NameRecord; + + + lpszLongName[0] = '\0'; + if ((fp = _wopen(pszFile, O_RDONLY | O_BINARY)) == -1) + return NULL; + + /* First off, read the initial directory header on the TTF. We're only + * interested in the "numOffsets" variable to tell us how many tables + * are present in this file. + * + * Remember to always convert from Motorola format (Big Endian to + * Little Endian). + */ + _read(fp, &OffsetTable, sizeof(OffsetTable) - sizeof + (sfnt_DirectoryEntry)); + cTables = (int) SWAPW(OffsetTable.numOffsets); + + for (i = 0; i < cTables && i < 40; i++) + { + if ((read(fp, &Table, sizeof(Table))) != sizeof(Table)) return NULL; + if (Table.tag == tag_NamingTable) /* defined in sfnt_en.h */ { + /* Now that we've found the entry for the name table, seek to that * position in the file and read in the initial header for this * particular table. See "True Type Font Files" for information * on this record layout. + */ + lseek(fp, SWAPL(Table.offset), SEEK_SET); + read(fp, &NamingTable, sizeof(NamingTable)); + numNames = SWAPW(NamingTable.count); + while (numNames--) + { + read(fp, &NameRecord, sizeof(NameRecord)); + curseek = tell(fp); + if (SWAPW(NameRecord.platformID) == 1 && + SWAPW(NameRecord.nameID) == 4) + { + lseek(fp, SWAPW(NameRecord.offset) + + SWAPW(NamingTable.stringOffset) + + SWAPL(Table.offset), SEEK_SET); + read(fp, &namebuf, MIN(255, (int)SWAPW(NameRecord.length))); + namebuf[MIN(255, (int)SWAPW(NameRecord.length))] = '\0'; + MultiByteToWideCharSZ(1252, 0, namebuf, -1, lpszLongName, 256); // TODO: benski> what codepage is TTF using internally? + //CUT: lstrcpy(lpszLongName, namebuf); + lseek(fp, curseek, SEEK_SET); + } + } + close(fp); + return lpszLongName; + } + } + close(fp); + + return NULL; +} + + +/* +TODO: +in order to do anti-aliased stuff, we need to draw onto a Compatible Bitmap, and then get the DIB bits out +we might also be able to create a Compatible HBITMAP and then pass it as the constructor parameter to SkinBitmap + +sample code: +void RenderFont(int x, int y, int size, char *str, char *fontname, + void *buf, int w, int h) + { + + HDC hdc=GetDC(NULL); + HDC mdc = CreateCompatibleDC(hdc); + HBITMAP bm = CreateCompatibleBitmap(hdc,w,h); + + HFONT hf=CreateFont(size, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, + ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + ANTIALIASED_QUALITY, DEFAULT_PITCH, fontname); + + RECT r; + r.top=0; + r.left=0; + r.right=w; + r.bottom=h; + + SelectObject(mdc, bm); + FillRect(mdc, &r, (HBRUSH)GetStockObject(BLACK_BRUSH)); + + SelectObject(mdc, hf); + SetBkMode(mdc, TRANSPARENT); + SetTextColor(mdc, 0xFFFFFF); + TextOut(mdc, 0, 0, str, strlen(str)); + + BITMAPINFO bmi; + + bmi.bmiHeader.biSize=sizeof(bmi.bmiHeader); + bmi.bmiHeader.biWidth=256; + bmi.bmiHeader.biHeight=256; + bmi.bmiHeader.biPlanes=1; + bmi.bmiHeader.biBitCount=32; + bmi.bmiHeader.biCompression=BI_RGB; + + GetDIBits(mdc,bm,0,256,buf,&bmi,DIB_RGB_COLORS); + + DeleteObject(hf); + DeleteObject(bm); +} +*/
\ No newline at end of file diff --git a/Src/Wasabi/api/font/win32/truetypefont_win32.h b/Src/Wasabi/api/font/win32/truetypefont_win32.h new file mode 100644 index 00000000..e8afff21 --- /dev/null +++ b/Src/Wasabi/api/font/win32/truetypefont_win32.h @@ -0,0 +1,61 @@ +#ifndef __TRUETYPEFONT_WN32_H +#define __TRUETYPEFONT_WN32_H + +#include <api/font/svc_fonti.h> + +#include <bfc/stack.h> +#include <api/font/truetypefontdef.h> +#include <tataki/canvas/bltcanvas.h> +class ifc_canvas; +class BltCanvas; + +class TrueTypeFont_Win32 : public svc_fontI { + public: + TrueTypeFont_Win32(); + virtual ~TrueTypeFont_Win32(); + + virtual void textOut(ifc_canvas *c, int x, int y, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialias); + virtual void textOut2(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialias); + virtual void textOutEllipsed(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialias); + virtual void textOutWrapped(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialias); + virtual void textOutWrappedPathed(ifc_canvas *c, int x, int y, int w, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialias); + virtual void textOutCentered(ifc_canvas *c, RECT *r, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, COLORREF color, COLORREF bkcolor, int xoffset, int yoffset, int antialias); + virtual int getTextWidth(ifc_canvas *c, const wchar_t *text, int size, int bold, int underline, int italic, int antialias); + virtual int getTextHeight(ifc_canvas *c, const wchar_t *text, int size, int bold, int underline, int italic, int antialias); + virtual int getTextHeight2(ifc_canvas *c, int size, int bold, int underline, int italic, int antialias); + virtual void getTextExtent(ifc_canvas *c, const wchar_t *text, int *w, int *h, int size, int bold, int underline, int italic, int antialias); + + virtual void setFontId(const wchar_t *id) { font_id = id; } + virtual const wchar_t *getFontId() { return font_id; } + virtual int getScriptId() { return scriptid; } + virtual void setScriptId(int id) { scriptid = id; } + + virtual int isBitmap(); + virtual void setFontFace(const wchar_t *face); + virtual int addFontResource(OSFILETYPE f, const wchar_t *name); + virtual int addFontResource2( void *data, int datalen, const wchar_t *name ); + virtual const wchar_t *getFaceName(); + + virtual const wchar_t *getFontSvcName() { return L"Win32 TextOut"; } + static const char *getServiceName() { return "Win32 Truetype font renderer"; } + + static wchar_t *filenameToFontFace(const wchar_t *filename); + + protected: + void prepareCanvas(BltCanvas *canvas, int size, int bold, int opaque, int underline, int italic, int antialiased); + void restoreCanvas(BltCanvas *canvas, ifc_canvas *dest, int w, int h, COLORREF color, COLORREF bkcolor, int antialiased, int x=0, int y=0); + HFONT MakeFont(int size, int bold, int underline, int italic, int antialiased); + + protected: + StringW font_id; + int scriptid; + + private: + StringW face_name; + StringW tmpfilename; + + HFONT font, oldFont; + +}; + +#endif
\ No newline at end of file |