PageRenderTime 31ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/ports/dingux/tags/v2-20101104/Source_Files/RenderOther/sdl_fonts.cpp

#
C++ | 786 lines | 615 code | 99 blank | 72 comment | 128 complexity | 2e98a9601d2223d37672897f722abe56 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, BSD-3-Clause, GPL-3.0, LGPL-3.0, MPL-2.0-no-copyleft-exception, Zlib, GPL-2.0
  1. /*
  2. Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
  3. and the "Aleph One" developers.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. This license is contained in the file "COPYING",
  13. which is included with this source code; it is available online at
  14. http://www.gnu.org/licenses/gpl.html
  15. */
  16. /*
  17. * sdl_fonts.cpp - SDL font handling
  18. *
  19. * Written in 2000 by Christian Bauer
  20. */
  21. #include "cseries.h"
  22. #include "sdl_fonts.h"
  23. #include "byte_swapping.h"
  24. #include "resource_manager.h"
  25. #include "FileHandler.h"
  26. #include "Logging.h"
  27. #include <SDL_endian.h>
  28. #include <vector>
  29. #include <map>
  30. #include <boost/tokenizer.hpp>
  31. #include <string>
  32. #ifndef NO_STD_NAMESPACE
  33. using std::vector;
  34. using std::pair;
  35. using std::map;
  36. #endif
  37. #ifdef HAVE_SDL_TTF
  38. #include <boost/tuple/tuple_comparison.hpp>
  39. #include "preferences.h" // smooth_font
  40. #include "AlephSansMono-Bold.h"
  41. #endif
  42. // Global variables
  43. typedef pair<int, int> id_and_size_t;
  44. typedef map<id_and_size_t, sdl_font_info *> font_list_t;
  45. static font_list_t font_list; // List of all loaded fonts
  46. #ifdef HAVE_SDL_TTF
  47. typedef pair<TTF_Font *, int> ref_counted_ttf_font_t;
  48. typedef map<ttf_font_key_t, ref_counted_ttf_font_t> ttf_font_list_t;
  49. static ttf_font_list_t ttf_font_list;
  50. #endif
  51. // From shell_sdl.cpp
  52. extern vector<DirectorySpecifier> data_search_path;
  53. /*
  54. * Initialize font management
  55. */
  56. #ifdef HAVE_SDL_TTF
  57. extern void fix_missing_overhead_map_fonts();
  58. extern void fix_missing_interface_fonts();
  59. #endif
  60. void initialize_fonts(void)
  61. {
  62. logContext("initializing fonts");
  63. // Open font resource files
  64. bool found = false;
  65. vector<DirectorySpecifier>::const_iterator i = data_search_path.begin(), end = data_search_path.end();
  66. while (i != end) {
  67. FileSpecifier fonts = *i + "Fonts";
  68. if (open_res_file(fonts))
  69. found = true;
  70. if (!found)
  71. {
  72. fonts = *i + "Fonts.fntA";
  73. if (open_res_file(fonts))
  74. found = true;
  75. }
  76. i++;
  77. }
  78. if (!found) {
  79. #ifdef HAVE_SDL_TTF
  80. // use our own built-in font
  81. fix_missing_overhead_map_fonts();
  82. fix_missing_interface_fonts();
  83. #else
  84. logFatal("Can't open font resource file");
  85. /*
  86. vector<DirectorySpecifier>::const_iterator i = data_search_path.begin(), end = data_search_path.end();
  87. while (i != end) {
  88. FileSpecifier fonts = *i + "Fonts";
  89. fdprintf(fonts.GetPath());
  90. i++;
  91. }
  92. */
  93. exit(1);
  94. #endif
  95. }
  96. }
  97. /*
  98. * Load font from resources and allocate sdl_font_info
  99. */
  100. sdl_font_info *load_sdl_font(const TextSpec &spec)
  101. {
  102. sdl_font_info *info = NULL;
  103. // Look for ID/size in list of loaded fonts
  104. id_and_size_t id_and_size(spec.font, spec.size);
  105. font_list_t::const_iterator it = font_list.find(id_and_size);
  106. if (it != font_list.end()) { // already loaded
  107. info = it->second;
  108. info->ref_count++;
  109. return info;
  110. }
  111. // Load font family resource
  112. LoadedResource fond;
  113. if (!get_resource(FOUR_CHARS_TO_INT('F', 'O', 'N', 'D'), spec.font, fond)) {
  114. fprintf(stderr, "Font family resource for font ID %d not found\n", spec.font);
  115. return NULL;
  116. }
  117. SDL_RWops *p = SDL_RWFromMem(fond.GetPointer(), (int)fond.GetLength());
  118. assert(p);
  119. // Look for font size in association table
  120. SDL_RWseek(p, 52, SEEK_SET);
  121. int num_assoc = SDL_ReadBE16(p) + 1;
  122. while (num_assoc--) {
  123. int size = SDL_ReadBE16(p);
  124. SDL_ReadBE16(p); // skip style
  125. int id = SDL_ReadBE16(p);
  126. if (size == spec.size) {
  127. // Size found, load bitmap font resource
  128. info = new sdl_font_info;
  129. if (!get_resource(FOUR_CHARS_TO_INT('N', 'F', 'N', 'T'), id, info->rsrc))
  130. get_resource(FOUR_CHARS_TO_INT('F', 'O', 'N', 'T'), id, info->rsrc);
  131. if (info->rsrc.IsLoaded()) {
  132. // Found, switch stream to font resource
  133. SDL_RWclose(p);
  134. p = SDL_RWFromMem(info->rsrc.GetPointer(), (int)info->rsrc.GetLength());
  135. assert(p);
  136. void *font_ptr = info->rsrc.GetPointer(true);
  137. // Read font information
  138. SDL_RWseek(p, 2, SEEK_CUR);
  139. info->first_character = static_cast<uint8>(SDL_ReadBE16(p));
  140. info->last_character = static_cast<uint8>(SDL_ReadBE16(p));
  141. SDL_RWseek(p, 2, SEEK_CUR);
  142. info->maximum_kerning = SDL_ReadBE16(p);
  143. SDL_RWseek(p, 2, SEEK_CUR);
  144. info->rect_width = SDL_ReadBE16(p);
  145. info->rect_height = SDL_ReadBE16(p);
  146. SDL_RWseek(p, 2, SEEK_CUR);
  147. info->ascent = SDL_ReadBE16(p);
  148. info->descent = SDL_ReadBE16(p);
  149. info->leading = SDL_ReadBE16(p);
  150. int bytes_per_row = SDL_ReadBE16(p) * 2;
  151. //printf(" first %d, last %d, max_kern %d, rect_w %d, rect_h %d, ascent %d, descent %d, leading %d, bytes_per_row %d\n",
  152. // info->first_character, info->last_character, info->maximum_kerning,
  153. // info->rect_width, info->rect_height, info->ascent, info->descent, info->leading, bytes_per_row);
  154. // Convert bitmap to pixmap (1 byte/pixel)
  155. info->bytes_per_row = bytes_per_row * 8;
  156. uint8 *src = (uint8 *)font_ptr + SDL_RWtell(p);
  157. uint8 *dst = info->pixmap = (uint8 *)malloc(info->rect_height * info->bytes_per_row);
  158. assert(dst);
  159. for (int y=0; y<info->rect_height; y++) {
  160. for (int x=0; x<bytes_per_row; x++) {
  161. uint8 b = *src++;
  162. *dst++ = (b & 0x80) ? 0xff : 0x00;
  163. *dst++ = (b & 0x40) ? 0xff : 0x00;
  164. *dst++ = (b & 0x20) ? 0xff : 0x00;
  165. *dst++ = (b & 0x10) ? 0xff : 0x00;
  166. *dst++ = (b & 0x08) ? 0xff : 0x00;
  167. *dst++ = (b & 0x04) ? 0xff : 0x00;
  168. *dst++ = (b & 0x02) ? 0xff : 0x00;
  169. *dst++ = (b & 0x01) ? 0xff : 0x00;
  170. }
  171. }
  172. SDL_RWseek(p, info->rect_height * bytes_per_row, SEEK_CUR);
  173. // Set table pointers
  174. int table_size = info->last_character - info->first_character + 3; // Tables contain 2 additional entries
  175. info->location_table = (uint16 *)((uint8 *)font_ptr + SDL_RWtell(p));
  176. byte_swap_memory(info->location_table, _2byte, table_size);
  177. SDL_RWseek(p, table_size * 2, SEEK_CUR);
  178. info->width_table = (int8 *)font_ptr + SDL_RWtell(p);
  179. // Add font information to list of known fonts
  180. info->ref_count++;
  181. font_list[id_and_size] = info;
  182. } else {
  183. delete info;
  184. info = NULL;
  185. fprintf(stderr, "Bitmap font resource ID %d not found\n", id);
  186. }
  187. }
  188. }
  189. // Free resources
  190. SDL_RWclose(p);
  191. return info;
  192. }
  193. #ifdef HAVE_SDL_TTF
  194. static TTF_Font *load_ttf_font(const std::string& path, uint16 style, int16 size)
  195. {
  196. // already loaded? increment reference counter and return pointer
  197. ttf_font_key_t search_key(path, style, size);
  198. ttf_font_list_t::iterator it = ttf_font_list.find(search_key);
  199. if (it != ttf_font_list.end())
  200. {
  201. TTF_Font *font = it->second.first;
  202. it->second.second++;
  203. return font;
  204. }
  205. TTF_Font *font;
  206. if (path == "mono")
  207. {
  208. font = TTF_OpenFontRW(SDL_RWFromConstMem(aleph_sans_mono_bold, sizeof(aleph_sans_mono_bold)), 0, size);
  209. }
  210. else
  211. {
  212. font = TTF_OpenFont(path.c_str(), size);
  213. }
  214. if (font)
  215. {
  216. int ttf_style = TTF_STYLE_NORMAL;
  217. if (style & styleBold)
  218. ttf_style |= TTF_STYLE_BOLD;
  219. if (style & styleItalic)
  220. ttf_style |= TTF_STYLE_ITALIC;
  221. TTF_SetFontStyle(font, ttf_style);
  222. #ifdef TTF_HINTING_LIGHT
  223. if (environment_preferences->smooth_text)
  224. TTF_SetFontHinting(font, TTF_HINTING_LIGHT);
  225. else
  226. TTF_SetFontHinting(font, TTF_HINTING_MONO);
  227. #endif
  228. ttf_font_key_t key(path, style, size);
  229. ref_counted_ttf_font_t value(font, 1);
  230. ttf_font_list[key] = value;
  231. }
  232. return font;
  233. }
  234. static const char *locate_font(const std::string& path)
  235. {
  236. if (path == "mono" || path == "")
  237. {
  238. return path.c_str();
  239. }
  240. else
  241. {
  242. static FileSpecifier file;
  243. if (file.SetNameWithPath(path.c_str()))
  244. return file.GetPath();
  245. else
  246. return "";
  247. }
  248. }
  249. #endif
  250. font_info *load_font(const TextSpec &spec) {
  251. // return static_cast<font_info*>(load_font(spec));
  252. #ifdef HAVE_SDL_TTF
  253. if (spec.normal != "")
  254. {
  255. std::string file;
  256. file = locate_font(spec.normal);
  257. TTF_Font *font = load_ttf_font(file, 0, spec.size);
  258. if (font)
  259. {
  260. ttf_font_info *info = new ttf_font_info;
  261. info->m_adjust_height = spec.adjust_height;
  262. info->m_styles[styleNormal] = font;
  263. info->m_keys[styleNormal] = ttf_font_key_t(file, 0, spec.size);
  264. // load bold face
  265. file = locate_font(spec.bold);
  266. font = load_ttf_font(file, styleNormal, spec.size);
  267. if (font)
  268. {
  269. info->m_styles[styleBold] = font;
  270. info->m_keys[styleBold] = ttf_font_key_t(file, styleNormal, spec.size);
  271. }
  272. else
  273. {
  274. file = locate_font(spec.normal);
  275. font = load_ttf_font(file, styleBold, spec.size);
  276. assert(font); // I loaded you once, you should load again
  277. info->m_styles[styleBold] = font;
  278. info->m_keys[styleBold] = ttf_font_key_t(file, styleBold, spec.size);
  279. }
  280. // oblique
  281. file = locate_font(spec.oblique);
  282. font = load_ttf_font(file, styleNormal, spec.size);
  283. if (font)
  284. {
  285. info->m_styles[styleItalic] = font;
  286. info->m_keys[styleItalic] = ttf_font_key_t(file, styleNormal, spec.size);
  287. }
  288. else
  289. {
  290. file = locate_font(spec.normal);
  291. font = load_ttf_font(file, styleItalic, spec.size);
  292. assert(font); // same as above
  293. info->m_styles[styleItalic] = font;
  294. info->m_keys[styleItalic] = ttf_font_key_t(file, styleItalic, spec.size);
  295. }
  296. // bold oblique
  297. file = locate_font(spec.bold_oblique);
  298. font = load_ttf_font(file, styleNormal, spec.size);
  299. if (font)
  300. {
  301. info->m_styles[styleBold | styleItalic] = font;
  302. info->m_keys[styleBold | styleItalic] = ttf_font_key_t(file, styleNormal, spec.size);
  303. }
  304. else
  305. {
  306. // try boldening the oblique
  307. file = locate_font(spec.oblique);
  308. font = load_ttf_font(file, styleBold, spec.size);
  309. if (font)
  310. {
  311. info->m_styles[styleBold | styleItalic] = font;
  312. info->m_keys[styleBold | styleItalic] = ttf_font_key_t(file, styleBold, spec.size);
  313. }
  314. else
  315. {
  316. // try obliquing the bold!
  317. file = locate_font(spec.bold);
  318. font = load_ttf_font(file, styleItalic, spec.size);
  319. if (font)
  320. {
  321. info->m_styles[styleBold | styleItalic] = font;
  322. info->m_keys[styleBold | styleItalic] = ttf_font_key_t(file, styleItalic, spec.size);
  323. }
  324. else
  325. {
  326. file = locate_font(spec.normal);
  327. font = load_ttf_font(file, styleBold | styleItalic, spec.size);
  328. assert(font);
  329. info->m_styles[styleBold | styleItalic] = font;
  330. info->m_keys[styleBold | styleItalic] = ttf_font_key_t(file, styleBold | styleItalic, spec.size);
  331. }
  332. }
  333. }
  334. return info;
  335. }
  336. else if (spec.font != -1)
  337. {
  338. return static_cast<font_info *>(load_sdl_font(spec));
  339. }
  340. else
  341. return 0;
  342. }
  343. else
  344. #endif
  345. if (spec.font != -1)
  346. {
  347. return static_cast<font_info *>(load_sdl_font(spec));
  348. }
  349. else
  350. return 0;
  351. }
  352. /*
  353. * Unload font, free sdl_font_info
  354. */
  355. void sdl_font_info::_unload()
  356. {
  357. // Look for font in list of loaded fonts
  358. font_list_t::const_iterator i = font_list.begin(), end = font_list.end();
  359. while (i != end) {
  360. if (i->second == this) {
  361. // Found, decrement reference counter and delete
  362. ref_count--;
  363. if (ref_count <= 0) {
  364. delete this; // !
  365. font_list.erase(i->first);
  366. return;
  367. }
  368. }
  369. i++;
  370. }
  371. }
  372. #ifdef HAVE_SDL_TTF
  373. void ttf_font_info::_unload()
  374. {
  375. for (int i = 0; i < styleUnderline; ++i)
  376. {
  377. ttf_font_list_t::iterator it = ttf_font_list.find(m_keys[i]);
  378. if (it != ttf_font_list.end())
  379. {
  380. --(it->second.second);
  381. if (it->second.second <= 0)
  382. {
  383. TTF_CloseFont(it->second.first);
  384. ttf_font_list.erase(m_keys[i]);
  385. }
  386. }
  387. m_styles[i] = 0;
  388. }
  389. delete this;
  390. }
  391. #endif
  392. void unload_font(font_info *info)
  393. {
  394. info->_unload();
  395. }
  396. int8 sdl_font_info::char_width(uint8 c, uint16 style) const
  397. {
  398. if (c < first_character || c > last_character)
  399. return 0;
  400. int8 width = width_table[(c - first_character) * 2 + 1] + ((style & styleBold) ? 1 : 0);
  401. if (width == -1) // non-existant character
  402. width = width_table[(last_character - first_character + 1) * 2 + 1] + ((style & styleBold) ? 1 : 0);
  403. return width;
  404. }
  405. uint16 sdl_font_info::_text_width(const char *text, uint16 style, bool) const
  406. {
  407. int width = 0;
  408. char c;
  409. while ((c = *text++) != 0)
  410. width += char_width(c, style);
  411. assert(0 <= width);
  412. assert(width == static_cast<int>(static_cast<uint16>(width)));
  413. return width;
  414. }
  415. uint16 sdl_font_info::_text_width(const char *text, size_t length, uint16 style, bool) const
  416. {
  417. int width = 0;
  418. while (length--)
  419. width += char_width(*text++, style);
  420. assert(0 <= width);
  421. assert(width == static_cast<int>(static_cast<uint16>(width)));
  422. return width;
  423. }
  424. int sdl_font_info::_trunc_text(const char *text, int max_width, uint16 style) const
  425. {
  426. int width = 0;
  427. int num = 0;
  428. char c;
  429. while ((c = *text++) != 0) {
  430. width += char_width(c, style);
  431. if (width > max_width)
  432. break;
  433. num++;
  434. }
  435. return num;
  436. }
  437. // sdl_font_info::_draw_text is in screen_drawing.cpp
  438. #ifdef HAVE_SDL_TTF
  439. int8 ttf_font_info::char_width(uint8 c, uint16 style) const
  440. {
  441. int advance;
  442. TTF_GlyphMetrics(get_ttf(style), mac_roman_to_unicode(static_cast<char>(c)), 0, 0, 0, 0, &advance);
  443. return advance;
  444. }
  445. uint16 ttf_font_info::_text_width(const char *text, uint16 style, bool utf8) const
  446. {
  447. return _text_width(text, strlen(text), style, utf8);
  448. }
  449. uint16 ttf_font_info::_text_width(const char *text, size_t length, uint16 style, bool utf8) const
  450. {
  451. int width = 0;
  452. if (utf8)
  453. {
  454. char *temp = process_printable(text, length);
  455. TTF_SizeUTF8(get_ttf(style), temp, &width, 0);
  456. }
  457. else
  458. {
  459. uint16 *temp = process_macroman(text, length);
  460. TTF_SizeUNICODE(get_ttf(style), temp, &width, 0);
  461. }
  462. return width;
  463. }
  464. int ttf_font_info::_trunc_text(const char *text, int max_width, uint16 style) const
  465. {
  466. int width;
  467. static uint16 temp[1024];
  468. mac_roman_to_unicode(text, temp, 1024);
  469. TTF_SizeUNICODE(get_ttf(style), temp, &width, 0);
  470. if (width < max_width) return strlen(text);
  471. int num = strlen(text) - 1;
  472. while (num > 0 && width > max_width)
  473. {
  474. num--;
  475. temp[num] = 0x0;
  476. TTF_SizeUNICODE(get_ttf(style), temp, &width, 0);
  477. }
  478. return num;
  479. }
  480. // ttf_font_info::_draw_text is in screen_drawing.cpp
  481. char *ttf_font_info::process_printable(const char *src, int len) const
  482. {
  483. static char dst[1024];
  484. if (len > 1023) len = 1023;
  485. char *p = dst;
  486. while (*src && len-- > 0)
  487. {
  488. if ((unsigned char) *src >= ' ') *p++ = *src;
  489. *src++;
  490. }
  491. *p = '\0';
  492. return dst;
  493. }
  494. uint16 *ttf_font_info::process_macroman(const char *src, int len) const
  495. {
  496. static uint16 dst[1024];
  497. if (len > 1023) len = 1023;
  498. uint16 *p = dst;
  499. while (*src && len-- > 0)
  500. {
  501. if ((unsigned char) *src >= ' ') *p++ = mac_roman_to_unicode(*src);
  502. else if ((unsigned char) *src == '\t')
  503. *p++ = ' ';
  504. *src++;
  505. }
  506. *p = 0x0;
  507. return dst;
  508. }
  509. #endif
  510. uint16 font_info::text_width(const char *text, uint16 style, bool utf8) const
  511. {
  512. if (style & styleShadow)
  513. return _text_width(text, style, utf8) + 1;
  514. else
  515. return _text_width(text, style, utf8);
  516. }
  517. uint16 font_info::text_width(const char *text, size_t length, uint16 style, bool utf8) const
  518. {
  519. if (style & styleShadow)
  520. return _text_width(text, length, style, utf8) + 1;
  521. else
  522. return _text_width(text, length, style, utf8);
  523. }
  524. static inline bool style_code(char c)
  525. {
  526. switch(tolower(c)) {
  527. case 'p':
  528. case 'b':
  529. case 'i':
  530. case 'l':
  531. case 'r':
  532. case 'c':
  533. case 's':
  534. return true;
  535. default:
  536. return false;
  537. }
  538. }
  539. class style_separator
  540. {
  541. public:
  542. bool operator() (std::string::const_iterator& next, std::string::const_iterator end, std::string& token)
  543. {
  544. if (next == end) return false;
  545. token = std::string();
  546. // if we start with a token, return it
  547. if (*next == '|' && next + 1 != end && style_code(*(next + 1)))
  548. {
  549. token += *next;
  550. ++next;
  551. token += *next;
  552. ++next;
  553. return true;
  554. }
  555. token += *next;
  556. ++next;
  557. // add characters until we hit a token
  558. for (;next != end && !(*next == '|' && next + 1 != end && style_code(*(next + 1))); ++next)
  559. {
  560. token += *next;
  561. }
  562. return true;
  563. }
  564. void reset() { }
  565. };
  566. static inline bool is_style_token(const std::string& token)
  567. {
  568. return (token.size() == 2 && token[0] == '|' && style_code(token[1]));
  569. }
  570. static void update_style(uint16& style, const std::string& token)
  571. {
  572. if (tolower(token[1]) == 'p')
  573. style &= ~(styleBold | styleItalic);
  574. else if (tolower(token[1]) == 'b')
  575. {
  576. style |= styleBold;
  577. style &= ~styleItalic;
  578. }
  579. else if (tolower(token[1]) == 'i')
  580. {
  581. style |= styleItalic;
  582. style &= ~styleBold;
  583. }
  584. }
  585. int font_info::draw_styled_text(SDL_Surface *s, const std::string& text, size_t length, int x, int y, uint32 pixel, uint16 style, bool utf8) const
  586. {
  587. int width = 0;
  588. boost::tokenizer<style_separator> tok(text.begin(), text.begin() + length);
  589. for (boost::tokenizer<style_separator>::iterator it = tok.begin(); it != tok.end(); ++it)
  590. {
  591. if (is_style_token(*it))
  592. {
  593. update_style(style, *it);
  594. }
  595. else
  596. {
  597. if (style & styleShadow)
  598. {
  599. _draw_text(s, it->c_str(), it->size(), x + width + 1, y + 1, SDL_MapRGB(s->format, 0x0, 0x0, 0x0), style, utf8);
  600. }
  601. width += _draw_text(s, it->c_str(), it->size(), x + width, y, pixel, style, utf8);
  602. }
  603. }
  604. return width;
  605. }
  606. int font_info::styled_text_width(const std::string& text, size_t length, uint16 style, bool utf8) const
  607. {
  608. int width = 0;
  609. boost::tokenizer<style_separator> tok(text.begin(), text.begin() + length);
  610. for (boost::tokenizer<style_separator>::iterator it = tok.begin(); it != tok.end(); ++it)
  611. {
  612. if (is_style_token(*it))
  613. {
  614. update_style(style, *it);
  615. }
  616. else
  617. {
  618. width += _text_width(it->c_str(), it->length(), style, utf8);
  619. }
  620. }
  621. if (style & styleShadow)
  622. return width + 1;
  623. else
  624. return width;
  625. }
  626. int font_info::trunc_styled_text(const std::string& text, int max_width, uint16 style) const
  627. {
  628. if (style & styleShadow)
  629. {
  630. max_width -= 1;
  631. style &= (~styleShadow);
  632. }
  633. int length = 0;
  634. boost::tokenizer<style_separator> tok(text);
  635. for (boost::tokenizer<style_separator>::iterator it = tok.begin(); it != tok.end(); ++it)
  636. {
  637. if (is_style_token(*it))
  638. {
  639. update_style(style, *it);
  640. length += 2;
  641. }
  642. else
  643. {
  644. int additional_length = _trunc_text(it->c_str(), max_width, style);
  645. max_width -= _text_width(it->c_str(), additional_length, style);
  646. length += additional_length;
  647. if (additional_length < it->size())
  648. return length;
  649. }
  650. }
  651. return length;
  652. }
  653. std::string font_info::style_at(const std::string& text, std::string::const_iterator pos, uint16 style) const
  654. {
  655. boost::tokenizer<style_separator> tok(text.begin(), pos);
  656. for (boost::tokenizer<style_separator>::iterator it = tok.begin(); it != tok.end(); ++it)
  657. {
  658. if (is_style_token(*it))
  659. update_style(style, *it);
  660. }
  661. if (style & styleBold)
  662. return string("|b");
  663. else if (style & styleItalic)
  664. return string("|i");
  665. else
  666. return string();
  667. }
  668. int font_info::draw_text(SDL_Surface *s, const char *text, size_t length, int x, int y, uint32 pixel, uint16 style, bool utf8) const
  669. {
  670. if (style & styleShadow)
  671. {
  672. _draw_text(s, text, length, x + 1, y + 1, SDL_MapRGB(s->format, 0x0, 0x0, 0x0), style, utf8);
  673. }
  674. return _draw_text(s, text, length, x, y, pixel, style, utf8);
  675. }
  676. int font_info::trunc_text(const char *text, int max_width, uint16 style) const
  677. {
  678. if (style & styleShadow)
  679. return _trunc_text(text, max_width - 1, style);
  680. else
  681. return _trunc_text(text, max_width, style);
  682. }