bitmapfont.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. #include "precomp.h"
  2. // ============================================================================================================================================================
  3. // Font abstract class + statics to install TT fonts and Bitmap fonts
  4. // ============================================================================================================================================================
  5. #include "bitmapfont.h"
  6. #include <api/wnd/fontdef.h>
  7. #include <api/config/items/cfgitem.h>
  8. #ifdef WASABI_COMPILE_SKIN
  9. #include <api/skin/skin.h>
  10. #endif
  11. #ifdef WA3COMPATIBILITY
  12. #endif
  13. #include <tataki/canvas/ifc_canvas.h>
  14. #include <tataki/region/api_region.h>
  15. #include <api/skin/skinparse.h>
  16. // ============================================================================================================================================================
  17. // BitmapFont implementation.
  18. // ============================================================================================================================================================
  19. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  20. BitmapFont::BitmapFont() : scriptid(0), char_width(0), char_height(0), hor_spacing(0), vert_spacing(0) {
  21. }
  22. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  23. BitmapFont::~BitmapFont() {
  24. }
  25. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  26. int BitmapFont::isBitmap() {
  27. return 1;
  28. }
  29. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  30. const wchar_t *BitmapFont::getFaceName() {
  31. return getFontId();
  32. }
  33. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  34. 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) {
  35. do_textOut(this, c, x+xoffset, y+yoffset, -1, -1, txt, size, bold, opaque, underline, italic, STDFONT_LEFT, color, WA_FONT_TEXTOUT_NORMAL);
  36. }
  37. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  38. 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) {
  39. 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);
  40. }
  41. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  42. 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) {
  43. 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);
  44. }
  45. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  46. 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) {
  47. 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);
  48. }
  49. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  50. 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) {
  51. do_textOut(this, c, x+xoffset, y+yoffset, x+xoffset+w, -1, txt, size, bold, opaque, underline, italic, align, color, WA_FONT_TEXTOUT_WRAPPEDPATHED);
  52. }
  53. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  54. 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) {
  55. 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);
  56. }
  57. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  58. int BitmapFont::getTextWidth(ifc_canvas *c, const wchar_t *text, int size, int bold, int underline, int italic, int antialiased)
  59. {
  60. return wcslen(text) * char_width + wcslen(text)*hor_spacing;
  61. }
  62. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  63. int BitmapFont::getTextHeight(ifc_canvas *c, const wchar_t *text, int size, int bold, int underline, int italic, int antialiased)
  64. {
  65. return char_height;
  66. }
  67. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  68. int BitmapFont::getTextHeight2(ifc_canvas *c, int size, int bold, int underline, int italic, int antialiased)
  69. {
  70. return char_height;
  71. }
  72. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  73. void BitmapFont::getTextExtent(ifc_canvas *c, const wchar_t *text, int *w, int *h, int size, int bold, int underline, int italic, int antialiased)
  74. {
  75. if (w) *w = getTextWidth(c, text, size, bold, underline, italic, antialiased);
  76. if (h) *h = char_height;
  77. }
  78. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  79. void BitmapFont::setFontBitmap(const wchar_t *name_or_element, const wchar_t *path)
  80. {
  81. StringW pathfile;
  82. if (!wcschr(name_or_element, L':'))
  83. {
  84. pathfile = path;
  85. pathfile.AddBackslash();
  86. }
  87. pathfile.cat(name_or_element);
  88. if (!WACCESS(pathfile, 0))
  89. table = pathfile;
  90. else
  91. table = name_or_element;
  92. }
  93. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  94. void BitmapFont::setFontMetrics(int _char_width, int _char_height, int _hor_spacing, int _vert_spacing) {
  95. char_width = _char_width;
  96. char_height = _char_height;
  97. hor_spacing = _hor_spacing;
  98. vert_spacing = _vert_spacing;
  99. }
  100. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  101. int BitmapFont::getHorizontalSpacing() {
  102. return hor_spacing;
  103. }
  104. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  105. int BitmapFont::getVerticalSpacing() {
  106. return vert_spacing;
  107. }
  108. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  109. int BitmapFont::getCharWidth() {
  110. return char_width;
  111. }
  112. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  113. int BitmapFont::getCharHeight() {
  114. return char_height;
  115. }
  116. AutoSkinBitmap *BitmapFont::getCharTable() {
  117. return &table;
  118. }
  119. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  120. void BitmapFont::getXYfromChar(wchar_t ic, int *x, int *y)
  121. {
  122. int c,c2=0;
  123. switch (ic)
  124. {
  125. case L'\u00B0': /*¡*/ ic = L'0'; break;
  126. case L'\u00C6':/*®*/ ic = L'A'; break;
  127. // case '\u00C1':/*ç*/ ic = L'A'; break;
  128. // case '\u00C2': ic = L'A'; break;
  129. case L'\u00C7': /*‚*/ ic = L'C'; break;
  130. case L'\u00C9':/*ƒ*/ ic = L'E'; break;
  131. case L'\u00E0': /*ˆ*/ case L'\u00E1': /*‡*/ case L'\u00E2': /*‰*/ ic = L'a'; break;
  132. case L'\u00E6':/*¾*/ ic = L'a'; break;
  133. case L'\u00E7': /*�*/ ic = L'c'; break;
  134. case L'\u00E8': /*�*/ case L'\u00E9': /*Ž*/ case L'\u00EB': /*‘*/case L'\u00EA':/*�*/ ic = L'e'; break;
  135. case L'\u00EC':/*“*/ case L'\u00ED':/*’*/ case L'\u00EE':/*”*/ case L'\u00EF':/*•*/ ic = L'i'; break;
  136. #ifdef _WIN32
  137. case L'—':/*—*/ case L'˜':/*˜*/ case L'™':/*™*/ ic = L'o'; break;
  138. case L'œ':/*œ*/ case L'�':/*�*/ case L'ž':/*ž*/ ic = L'u'; break;
  139. case L'Ø':/*Ø*/ ic = L'y'; break;
  140. case L'†':/*†*/ ic = L'U'; break;
  141. #else
  142. #warning change these to \u
  143. #endif
  144. case L'\u00D1':/*„*/ ic = L'N'; break;
  145. case L'\u00F1':/*–*/ ic = L'n'; break;
  146. case L'\u00FC': /*Ÿ*/ ic = L'u'; break;
  147. case L'\u0192':/*Ä*/ ic = L'f'; break;
  148. default: break;
  149. } // quick relocations
  150. if (ic <= L'Z' && ic >= L'A') c = (ic-'A');
  151. else if (ic <= L'z' && ic >= L'a') c = (ic-'a');
  152. else if (ic == L' ') c = 30;
  153. else {
  154. c2 += char_height;
  155. if (ic == L'\1') c=10;
  156. else if (ic == L'.') c = 11;
  157. else if (ic <= L'9' && ic >= L'0') c = ic - L'0';
  158. else if (ic == L':') c = 12;
  159. else if (ic == L'(') c = 13;
  160. else if (ic == L')') c = 14;
  161. else if (ic == L'-') c = 15;
  162. else if (ic == L'\'' || ic=='`') c = 16;
  163. else if (ic == L'!') c = 17;
  164. else if (ic == L'_') c = 18;
  165. else if (ic == L'+') c = 19;
  166. else if (ic == L'\\') c = 20;
  167. else if (ic == L'/') c = 21;
  168. else if (ic == L'[' || ic == L'{' || ic == L'<') c = 22;
  169. else if (ic == L']' || ic == L'}' || ic == L'>') c = 23;
  170. else if (ic == L'~' || ic == L'^') c = 24;
  171. else if (ic == L'&') c = 25;
  172. else if (ic == L'%') c = 26;
  173. else if (ic == L',') c = 27;
  174. else if (ic == L'=') c = 28;
  175. else if (ic == L'$') c = 29;
  176. else if (ic == L'#') c = 30;
  177. else
  178. {
  179. c2 += char_height;
  180. #ifdef _WIN32
  181. if (ic == L'�' || ic == L'Œ') c = 0;
  182. else if (ic == L'…' || ic == L'š') c = 1;
  183. else if (ic == L'€' || ic == L'Š') c = 2;
  184. else
  185. #else
  186. #warning change these to \u
  187. #endif
  188. if (ic == L'?') c = 3;
  189. else if (ic == L'*') c = 4;
  190. else {
  191. c2 = 0;
  192. if (ic == L'"') c = 26;
  193. else if (ic == L'@') c = 27;
  194. else c = 30;
  195. }
  196. }
  197. }
  198. c*=char_width;
  199. *x=c;
  200. *y=c2;
  201. }
  202. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  203. int BitmapFont::getWordLength(const wchar_t *p) {
  204. int n=0;
  205. while (p && *p && *p != L' ') {
  206. p++;
  207. n++;
  208. }
  209. return n;
  210. }
  211. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  212. wchar_t *BitmapFont::makeLine(const wchar_t *t, BitmapFont *font, int line, int width, int style) {
  213. static wchar_t str[4096];
  214. wchar_t *p = (wchar_t *)t;
  215. size_t len = wcslen(t);
  216. switch (style) {
  217. case WA_FONT_TEXTOUT_NORMAL:
  218. case WA_FONT_TEXTOUT_RECT:
  219. case WA_FONT_TEXTOUT_ELLIPSED:
  220. case WA_FONT_TEXTOUT_CENTERED:
  221. return line == 0 ? (wchar_t *)t : NULL;
  222. case WA_FONT_TEXTOUT_WRAPPEDPATHED:
  223. case WA_FONT_TEXTOUT_WRAPPED: {
  224. size_t maxchar = width / (font->getCharWidth() + font->getVerticalSpacing());
  225. for (int i = 0; i < line; i++) {
  226. wchar_t *oldp = p;
  227. p += maxchar;
  228. if ((size_t)(p-t) >= len) return NULL;
  229. while (p >= t) {
  230. if (p == t || *(p-1) == L' ')
  231. break;
  232. p--;
  233. }
  234. if (p == oldp) {
  235. p += maxchar;
  236. while (p && *p && *p != L' ')
  237. p++;
  238. }
  239. }
  240. WCSCPYN(str, p, maxchar);
  241. wchar_t *d = &str[maxchar-1];
  242. int wr=0;
  243. if (wcslen(p) > maxchar && *(p+maxchar) != L' ' && wcschr(str, L' '))
  244. while (d >= str) {
  245. if (*d == L' ') {
  246. *d = 0;
  247. wr=1;
  248. }
  249. else {
  250. if (wr) break;
  251. d--;
  252. }
  253. }
  254. return str;
  255. }
  256. }
  257. return NULL;
  258. }
  259. // -------------------------------------------------------------------------------------------------------------------------------------------------------------
  260. 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)
  261. {
  262. static wchar_t *dotdotdot=L"...";
  263. if (!text) return;
  264. BaseCloneCanvas canvas;
  265. int ret = canvas.clone(c);
  266. if (!ret) return;
  267. RECT bounds;
  268. RECT defbounds={x,y,x2,y2};
  269. int __w, __h;
  270. c->getDim(&__w, &__h, NULL);
  271. if (x2 == -1) defbounds.right = defbounds.left + __w;
  272. if (y2 == -1) defbounds.bottom = defbounds.top + __h;
  273. #ifdef _WIN32
  274. RegionI oldclip(&canvas, &defbounds); // get clipping region in oldclip
  275. RegionI *andclip=NULL;
  276. oldclip.getBox(&bounds); // get boundaries
  277. #else
  278. bounds = defbounds;
  279. #warning port me
  280. #endif
  281. /* if (x2 != -1 && y2 != -1) {
  282. andclip = new RegionI(x, y, x2, y2); // create region for rect
  283. andclip->andRegion(oldclip); // and them
  284. canvas.selectClipRgn(andclip); // select new clipping rect
  285. andclip->getBox(&bounds); // update boundaries
  286. }*/
  287. int lc=-1;
  288. wchar_t *p = dotdotdot+3; // just a zero to triger next line
  289. int _x = x+(font->getHorizontalSpacing()/2);
  290. int _y = y;
  291. if (style == WA_FONT_TEXTOUT_CENTERED) {
  292. _y += (y2 - y - font->getCharHeight()) / 2;
  293. }
  294. _y -= font->getCharHeight() + font->getVerticalSpacing();
  295. int xp, yp;
  296. while (p) {
  297. if (!*p) {
  298. lc++;
  299. p = makeLine(text, font, lc, x2-x, style);
  300. if (!p || !*p) break;
  301. _x = x+(font->getHorizontalSpacing()/2);
  302. _y += font->getCharHeight() + font->getVerticalSpacing();
  303. if ((align == STDFONT_RIGHT || align == STDFONT_CENTER) && x2 != -1) {
  304. int l = wcslen(p);
  305. _x -= l * (font->getCharWidth() + font->getHorizontalSpacing()) - (x2-x);
  306. }
  307. if (align == STDFONT_CENTER)
  308. _x = x + (_x - x) / 2;
  309. }
  310. if ((style == WA_FONT_TEXTOUT_ELLIPSED || style == WA_FONT_TEXTOUT_WRAPPEDPATHED) && x2 != -1) {
  311. if (_x > x2 - 4 * (font->getCharWidth() + font->getHorizontalSpacing()) && wcslen(p) > 3) {
  312. p = dotdotdot;
  313. }
  314. }
  315. font->getXYfromChar(*p, &xp, &yp);
  316. RECT r;
  317. r.left = xp;
  318. r.top = yp;
  319. r.right = xp + font->getCharWidth();
  320. r.bottom = yp + font->getCharHeight();
  321. RECT dst;
  322. dst.left = _x;
  323. dst.top = _y;
  324. dst.right = _x + font->getCharWidth();
  325. dst.bottom = _y + font->getCharHeight();
  326. if (Wasabi::Std::rectIntersect(dst, bounds))
  327. // if (IntersectRect(&dummy, &dst, &bounds)) // port me / checks clipping, not passed x,y,x2,y2
  328. font->getCharTable()->stretchToRectAlpha(&canvas, &r, &dst, 255);
  329. p++;
  330. _x += font->getCharWidth();
  331. _x += font->getHorizontalSpacing();
  332. }
  333. #ifdef _WIN32
  334. if (andclip) {
  335. canvas.selectClipRgn(&oldclip); // restore previously saved clipping region
  336. delete andclip;
  337. }
  338. #else
  339. #warning port me
  340. #endif
  341. }