PageRenderTime 25ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/qc-example/dlib/gui_widgets/fonts.cpp

https://bitbucket.org/Wane/comp6009-irp
C++ | 671 lines | 551 code | 59 blank | 61 comment | 113 complexity | fd99386a778960b3634b2965e8263217 MD5 | raw file
  1. // Copyright (C) 2005 Davis E. King (davis@dlib.net), and Nils Labugt, Keita Mochizuki
  2. // License: Boost Software License See LICENSE.txt for the full license.
  3. #ifndef DLIB_FONTs_CPP_
  4. #define DLIB_FONTs_CPP_
  5. #include "fonts.h"
  6. #include "../serialize.h"
  7. #include <sstream>
  8. #include "../base64.h"
  9. #include "../compress_stream.h"
  10. #include <fstream>
  11. #include "../tokenizer.h"
  12. #include "nativefont.h"
  13. namespace dlib
  14. {
  15. // ----------------------------------------------------------------------------------------
  16. const std::string get_decoded_string_with_default_font_data()
  17. {
  18. dlib::base64::kernel_1a base64_coder;
  19. dlib::compress_stream::kernel_1ea compressor;
  20. std::ostringstream sout;
  21. std::istringstream sin;
  22. /*
  23. SOURCE BDF FILE (helvR12.bdf) COMMENTS
  24. COMMENT $XConsortium: helvR12.bdf,v 1.15 95/01/26 18:02:58 gildea Exp $
  25. COMMENT $Id: helvR12.bdf,v 1.26 2004-11-28 20:08:46+00 mgk25 Rel $
  26. COMMENT
  27. COMMENT +
  28. COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated.
  29. COMMENT Copyright 1988, 1994 Digital Equipment Corporation.
  30. COMMENT
  31. COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be
  32. COMMENT registered in certain jurisdictions.
  33. COMMENT Permission to use these trademarks is hereby granted only in
  34. COMMENT association with the images described in this file.
  35. COMMENT
  36. COMMENT Permission to use, copy, modify, distribute and sell this software
  37. COMMENT and its documentation for any purpose and without fee is hereby
  38. COMMENT granted, provided that the above copyright notices appear in all
  39. COMMENT copies and that both those copyright notices and this permission
  40. COMMENT notice appear in supporting documentation, and that the names of
  41. COMMENT Adobe Systems and Digital Equipment Corporation not be used in
  42. COMMENT advertising or publicity pertaining to distribution of the software
  43. COMMENT without specific, written prior permission. Adobe Systems and
  44. COMMENT Digital Equipment Corporation make no representations about the
  45. COMMENT suitability of this software for any purpose. It is provided "as
  46. COMMENT is" without express or implied warranty.
  47. COMMENT -
  48. */
  49. // The base64 encoded data we want to decode and return.
  50. sout << "AXF+zOQzCgGitrKiOCGEL4hlIv1ZenWJyjMQ4rJ6f/oPMeHqsZn+8XnpehwFQTz3dtUGlZRAUoOa";
  51. sout << "uVo8UiplcFxuK69A+94rpMCMAyEeeOwZ/tRzkX4eKuU3L4xtsJDknMiYUNKaMrYimb1QJ0E+SRqQ";
  52. sout << "wATrMTecYNZvJJm02WibiwE4cJ5scvkHNl4KJT5QfdwRdGopTyUVdZvRvtbTLLjsJP0fQEQLqemf";
  53. sout << "qPE4kDD79ehrBIwLO1Y6TzxtrrIoQR57zlwTUyLenqRtSN3VLtjWYd82cehRIlTLtuxBg2s+zZVq";
  54. sout << "jNlNnYTSM+Swy06qnQgg+Dt0lhtlB9shR1OAlcfCtTW6HKoBk/FGeDmjTGW4bNCGv7RjgM6TlLDg";
  55. sout << "ZYSSA6ZCCAKBgE++U32gLHCCiVkPTkkp9P6ioR+e3SSKRNm9p5MHf+ZQ3LJkW8KFJ/K9gKT1yvyv";
  56. sout << "F99pAvOOq16tHRFvzBs+xZj/mUpH0lGIS7kLWr9oP2KuccVrz25aJn3kDruwTYoD+CYlOqtPO0Mv";
  57. sout << "dEI0LUR0Ykp1M2rWo76fJ/fpzHjV7737hjkNPJ13nO72RMDr4R5V3uG7Dw7Ng+vGX3WgJZ4wh1JX";
  58. sout << "pl2VMqC5JXccctzvnQvnuvBvRm7THgwQUgMKKT3WK6afUUVlJy8DHKuU4k1ibfVMxAmrwKdTUX2w";
  59. sout << "cje3A05Qji3aop65qEdwgI5O17HIVoRQOG/na+XRMowOfUvI4H8Z4+JGACfRrQctgYDAM9eJzm8i";
  60. sout << "PibyutmJfZBGg0a3oC75S5R9lTxEjPocnEyJRYNnmVnVAmKKbTbTsznuaD+D1XhPdr2t3A4bRTsp";
  61. sout << "toKKtlFnd9YGwLWwONDwLnoQ/IXwyF7txrRHNSVToh772U0Aih/yn5vnmcMF750eiMzRAgXu5sbR";
  62. sout << "VXEOVCiLgVevN5umkvjZt1eGTSSzDMrIvnv4nyOfaFsD+I76wQfgLqd71rheozGtjNc0AOTx4Ggc";
  63. sout << "eUSFHTDAVfTExBzckurtyuIAqF986a0JLHCtsDpBa2wWNuiQYOH3/LX1zkdU2hdamhBW774bpEwr";
  64. sout << "dguMxxOeDGOBgIlM5gxXGYXSf5IN3fUAEPfOPRxB7T+tpjFnWd7cg+JMabci3zhJ9ANaYT7HGeTX";
  65. sout << "bulKnGHjYrR1BxdK3YeliogQRU4ytmxlyL5zlNFU/759mA8XSfIPMEZn9Vxkb00q1htF7REiDcr3";
  66. sout << "kW1rtPAc7VQNEhT54vK/YF6rMvjO7kBZ/vLYo7E8e8hDKEnY8ucrC3KGmeo31Gei74BBcEbvJBd3";
  67. sout << "/YAaIKgXWwU2wSUw9wLq2RwGwyguvKBx0J/gn27tjcVAHorRBwxzPpk8r+YPyN+SifSzEL7LEy1G";
  68. sout << "lPHxmXTrcqnH9qraeAqXJUJvU8SJJpf/tmsAE+XSKD/kpVBnT5qXsJ1SRFS7MtfPjE1j/NYbaQBI";
  69. sout << "bOrh81zaYCEJR0IKHWCIsu/MC3zKXfkxFgQ9XpYAuWjSSK64YpgkxSMe8VG8yYvigOw2ODg/z4FU";
  70. sout << "+HpnEKF/M/mKfLKK1i/8BV7xcYVHrhEww1QznoFklJs/pEg3Kd5PE1lRii6hvTn6McVAkw+YbH9q";
  71. sout << "/sg4gFIAvai64hMcZ1oIZYppj3ZN6KMdyhK5s4++ZS/YOV2nNhW73ovivyi2Tjg7lxjJJtsYrLKb";
  72. sout << "zIN1slOICKYwBq42TFBcFXaZ6rf0Czd09tL+q6A1Ztgr3BNuhCenjhWN5ji0LccGYZo6bLTggRG/";
  73. sout << "Uz6K3CBBU/byLs79c5qCohrr7rlpDSdbuR+aJgNiWoU6T0i2Tvua6h51LcWEHy5P2n146/Ae2di4";
  74. sout << "eh20WQvclrsgm1oFTGD0Oe85GKOTA7vvwKmLBc1wwA0foTuxzVgj0TMTFBiYLTLG4ujUyBYy1N6e";
  75. sout << "H8EKi8H+ZAlqezrjABO3BQr33ewdZL5IeJ4w7gdGUDA6+P+7cODcBW50X9++6YTnKctuEw6aXBpy";
  76. sout << "GgcMfPE61G8YKBbFGFic3TVvGCLvre1iURv+F+hU4/ee6ILuPnpYnSXX2iCIK/kmkBse8805d4Qe";
  77. sout << "DG/8rBW9ojvAgc0jX7CatPEMHGkcz+KIZoKMI7XXK4PJpGQUdq6EdIhJC4koXEynjwwXMeC+jJqH";
  78. sout << "agwrlDNssq/8AA==";
  79. // Put the data into the istream sin
  80. sin.str(sout.str());
  81. sout.str("");
  82. // Decode the base64 text into its compressed binary form
  83. base64_coder.decode(sin,sout);
  84. sin.clear();
  85. sin.str(sout.str());
  86. sout.str("");
  87. // Decompress the data into its original form
  88. compressor.decompress(sin,sout);
  89. // Return the decoded and decompressed data
  90. return sout.str();
  91. }
  92. default_font::
  93. default_font (
  94. )
  95. {
  96. using namespace std;
  97. l = new letter[256];
  98. try
  99. {
  100. istringstream sin(get_decoded_string_with_default_font_data());
  101. for (int i = 0; i < 256; ++i)
  102. {
  103. deserialize(l[i],sin);
  104. }
  105. }
  106. catch (...)
  107. {
  108. delete [] l;
  109. throw;
  110. }
  111. }
  112. // ----------------------------------------------------------------------------------------
  113. void serialize (
  114. const letter& item,
  115. std::ostream& out
  116. )
  117. {
  118. try
  119. {
  120. serialize(item.w,out);
  121. serialize(item.count,out);
  122. for (unsigned long i = 0; i < item.count; ++i)
  123. {
  124. serialize(item.points[i].x,out);
  125. serialize(item.points[i].y,out);
  126. }
  127. }
  128. catch (serialization_error e)
  129. {
  130. throw serialization_error(e.info + "\n while serializing object of type letter");
  131. }
  132. }
  133. void deserialize (
  134. letter& item,
  135. std::istream& in
  136. )
  137. {
  138. try
  139. {
  140. if (item.points)
  141. delete [] item.points;
  142. deserialize(item.w,in);
  143. deserialize(item.count,in);
  144. if (item.count > 0)
  145. item.points = new letter::point[item.count];
  146. else
  147. item.points = 0;
  148. for (unsigned long i = 0; i < item.count; ++i)
  149. {
  150. deserialize(item.points[i].x,in);
  151. deserialize(item.points[i].y,in);
  152. }
  153. }
  154. catch (serialization_error e)
  155. {
  156. item.w = 0;
  157. item.count = 0;
  158. item.points = 0;
  159. throw serialization_error(e.info + "\n while deserializing object of type letter");
  160. }
  161. }
  162. // ----------------------------------------------------------------------------------------
  163. // ----------------------------------------------------------------------------------------
  164. // ----------------------------------------------------------------------------------------
  165. // ----------------------------------------------------------------------------------------
  166. namespace bdf_font_helpers
  167. {
  168. class bdf_parser
  169. {
  170. public:
  171. bdf_parser( std::istream& in ) : in_( in )
  172. {
  173. std::string str_tmp;
  174. int int_tmp;
  175. str_tmp = "STARTFONT"; int_tmp = STARTFONT; keyword_map.add( str_tmp, int_tmp );
  176. str_tmp = "FONTBOUNDINGBOX";int_tmp = FONTBOUNDINGBOX; keyword_map.add( str_tmp, int_tmp );
  177. str_tmp = "DWIDTH"; int_tmp = DWIDTH; keyword_map.add( str_tmp, int_tmp );
  178. str_tmp = "CHARS"; int_tmp = CHARS; keyword_map.add( str_tmp, int_tmp );
  179. str_tmp = "STARTCHAR"; int_tmp = STARTCHAR; keyword_map.add( str_tmp, int_tmp );
  180. str_tmp = "ENCODING"; int_tmp = ENCODING; keyword_map.add( str_tmp, int_tmp );
  181. str_tmp = "BBX"; int_tmp = BBX; keyword_map.add( str_tmp, int_tmp );
  182. str_tmp = "BITMAP"; int_tmp = BITMAP; keyword_map.add( str_tmp, int_tmp );
  183. str_tmp = "ENDCHAR"; int_tmp = ENDCHAR; keyword_map.add( str_tmp, int_tmp );
  184. str_tmp = "ENDFONT"; int_tmp = ENDFONT; keyword_map.add( str_tmp, int_tmp );
  185. str_tmp = "DEFAULT_CHAR"; int_tmp = DEFAULT_CHAR; keyword_map.add( str_tmp, int_tmp );
  186. tokzr.set_identifier_token( tokzr.uppercase_letters(), tokzr.uppercase_letters() + "_" );
  187. tokzr.set_stream( in );
  188. }
  189. enum bdf_enums
  190. {
  191. NO_KEYWORD = 0,
  192. STARTFONT = 1,
  193. FONTBOUNDINGBOX = 2,
  194. DWIDTH = 4,
  195. DEFAULT_CHAR = 8,
  196. CHARS = 16,
  197. STARTCHAR = 32,
  198. ENCODING = 64,
  199. BBX = 128,
  200. BITMAP = 256,
  201. ENDCHAR = 512,
  202. ENDFONT = 1024
  203. };
  204. struct header_info
  205. {
  206. int FBBx, FBBy, Xoff, Yoff;
  207. int dwx0, dwy0;
  208. bool has_global_dw;
  209. long default_char;
  210. };
  211. struct char_info
  212. {
  213. int dwx0, dwy0;
  214. int BBw, BBh, BBxoff0x, BByoff0y;
  215. array2d<char> bitmap;
  216. bool has_dw;
  217. };
  218. bool parse_header( header_info& info )
  219. {
  220. if ( required_keyword( STARTFONT ) == false )
  221. return false; // parse_error: required keyword missing
  222. info.has_global_dw = false;
  223. int find = FONTBOUNDINGBOX | DWIDTH | DEFAULT_CHAR;
  224. int stop = CHARS | STARTCHAR | ENCODING | BBX | BITMAP | ENDCHAR | ENDFONT;
  225. int res;
  226. while ( 1 )
  227. {
  228. res = find_keywords( find | stop );
  229. if ( res & FONTBOUNDINGBOX )
  230. {
  231. in_ >> info.FBBx >> info.FBBy >> info.Xoff >> info.Yoff;
  232. if ( in_.fail() )
  233. return false; // parse_error
  234. find &= ~FONTBOUNDINGBOX;
  235. continue;
  236. }
  237. if ( res & DWIDTH )
  238. {
  239. in_ >> info.dwx0 >> info.dwy0;
  240. if ( in_.fail() )
  241. return false; // parse_error
  242. find &= ~DWIDTH;
  243. info.has_global_dw = true;
  244. continue;
  245. }
  246. if ( res & DEFAULT_CHAR )
  247. {
  248. in_ >> info.default_char;
  249. if ( in_.fail() )
  250. return false; // parse_error
  251. find &= ~DEFAULT_CHAR;
  252. continue;
  253. }
  254. if ( res & NO_KEYWORD )
  255. return false; // parse_error: unexpected EOF
  256. break;
  257. }
  258. if ( res != CHARS || ( find & FONTBOUNDINGBOX ) )
  259. return false; // parse_error: required keyword missing or unexpeced keyword
  260. return true;
  261. }
  262. int parse_glyph( char_info& info, unichar& enc )
  263. {
  264. info.has_dw = false;
  265. int e;
  266. int res;
  267. while ( 1 )
  268. {
  269. res = find_keywords( ENCODING );
  270. if ( res != ENCODING )
  271. return 0; // no more glyphs
  272. in_ >> e;
  273. if ( in_.fail() )
  274. return -1; // parse_error
  275. if ( e >= static_cast<int>(enc) )
  276. break;
  277. }
  278. int find = BBX | DWIDTH;
  279. int stop = STARTCHAR | ENCODING | BITMAP | ENDCHAR | ENDFONT;
  280. while ( 1 )
  281. {
  282. res = find_keywords( find | stop );
  283. if ( res & BBX )
  284. {
  285. in_ >> info.BBw >> info.BBh >> info.BBxoff0x >> info.BByoff0y;
  286. if ( in_.fail() )
  287. return -1; // parse_error
  288. find &= ~BBX;
  289. continue;
  290. }
  291. if ( res & DWIDTH )
  292. {
  293. in_ >> info.dwx0 >> info.dwy0;
  294. if ( in_.fail() )
  295. return -1; // parse_error
  296. find &= ~DWIDTH;
  297. info.has_dw = true;
  298. continue;
  299. }
  300. if ( res & NO_KEYWORD )
  301. return -1; // parse_error: unexpected EOF
  302. break;
  303. }
  304. if ( res != BITMAP || ( find != NO_KEYWORD ) )
  305. return -1; // parse_error: required keyword missing or unexpeced keyword
  306. unsigned h = info.BBh;
  307. unsigned w = ( info.BBw + 7 ) / 8 * 2;
  308. info.bitmap.set_size( h, w );
  309. for ( unsigned r = 0;r < h;r++ )
  310. {
  311. trim();
  312. std::string str = "";
  313. extract_hex(str);
  314. if(str.size() < w)
  315. return -1; // parse_error
  316. for ( unsigned c = 0;c < w;c++ )
  317. info.bitmap[r][c] = str[c];
  318. }
  319. if ( in_.fail() )
  320. return -1; // parse_error
  321. if ( required_keyword( ENDCHAR ) == false )
  322. return -1; // parse_error: required keyword missing
  323. enc = e;
  324. return 1;
  325. }
  326. private:
  327. map<std::string, int>::kernel_1a_c keyword_map;
  328. tokenizer::kernel_1a_c tokzr;
  329. std::istream& in_;
  330. void extract_hex(std::string& str)
  331. {
  332. int type;
  333. std::string token;
  334. while ( 1 )
  335. {
  336. type = tokzr.peek_type();
  337. if ( type == tokenizer::kernel_1a_c::IDENTIFIER || type == tokenizer::kernel_1a_c::NUMBER )
  338. {
  339. tokzr.get_token( type, token );
  340. str += token;
  341. continue;
  342. }
  343. break;
  344. }
  345. }
  346. void trim()
  347. {
  348. int type;
  349. std::string token;
  350. while ( 1 )
  351. {
  352. type = tokzr.peek_type();
  353. if ( type == tokenizer::kernel_1a_c::WHITE_SPACE || type == tokenizer::kernel_1a_c::END_OF_LINE )
  354. {
  355. tokzr.get_token( type, token );
  356. continue;
  357. }
  358. break;
  359. }
  360. }
  361. bool required_keyword( int kw )
  362. {
  363. int type;
  364. std::string token;
  365. while ( 1 )
  366. {
  367. tokzr.get_token( type, token );
  368. if ( type == tokenizer::kernel_1a_c::WHITE_SPACE || type == tokenizer::kernel_1a_c::END_OF_LINE )
  369. continue;
  370. if ( type != tokenizer::kernel_1a_c::IDENTIFIER || keyword_map.is_in_domain( token ) == false || ( keyword_map[token] & kw ) == 0 )
  371. return false;
  372. break;
  373. }
  374. return true;
  375. }
  376. int find_keywords( int find )
  377. {
  378. int type;
  379. std::string token;
  380. while ( 1 )
  381. {
  382. tokzr.get_token( type, token );
  383. if ( type == tokenizer::kernel_1a_c::END_OF_FILE )
  384. return NO_KEYWORD;
  385. if ( type == tokenizer::kernel_1a_c::IDENTIFIER && keyword_map.is_in_domain( token ) == true )
  386. {
  387. int kw = keyword_map[token];
  388. if ( kw & find )
  389. return kw;
  390. }
  391. }
  392. return true;
  393. }
  394. };
  395. }
  396. // ----------------------------------------------------------------------------------------
  397. // ----------------------------------------------------------------------------------------
  398. // bdf_font functions
  399. // ----------------------------------------------------------------------------------------
  400. // ----------------------------------------------------------------------------------------
  401. bdf_font::bdf_font(
  402. long default_char_
  403. ) :
  404. default_char(0),
  405. is_initialized( false ),
  406. right_overflow_( 0 ),
  407. has_global_width( false ),
  408. specified_default_char( default_char_ )
  409. {
  410. // make sure gl contains at least one letter
  411. gl.resize(1);
  412. }
  413. // ----------------------------------------------------------------------------------------
  414. void bdf_font::adjust_metrics(
  415. )
  416. {
  417. if ( is_initialized == false )
  418. return;
  419. // set starting values for fbb
  420. if ( gl[default_char].num_of_points() > 0 )
  421. {
  422. letter& g = gl[default_char];
  423. fbb.set_top( g[0].y );
  424. fbb.set_bottom( g[0].y );
  425. fbb.set_left( g[0].x );
  426. fbb.set_right( g[0].x );
  427. }
  428. else
  429. {
  430. // ok, the default char was a space
  431. // let's just choose some safe arbitrary values then...
  432. fbb.set_top( 10000 );
  433. fbb.set_bottom( -10000 );
  434. fbb.set_left( 10000 );
  435. fbb.set_right( -10000 );
  436. }
  437. right_overflow_ = 0;
  438. for ( unichar n = 0; n < gl.size(); n++ )
  439. {
  440. letter& g = gl[n];
  441. unsigned short nr_pts = g.num_of_points();
  442. for ( unsigned short k = 0;k < nr_pts;k++ )
  443. {
  444. fbb.set_top( std::min( fbb.top(), (long)g[k].y ) );
  445. fbb.set_left( std::min( fbb.left(), (long)g[k].x ) );
  446. fbb.set_bottom( std::max( fbb.bottom(), (long)g[k].y ) );
  447. fbb.set_right( std::max( fbb.right(), (long)g[k].x ) );
  448. right_overflow_ = std::max( right_overflow_, (unsigned long)(g[k].x - g.width()) ); // superfluous?
  449. }
  450. }
  451. }
  452. // ----------------------------------------------------------------------------------------
  453. long bdf_font::
  454. read_bdf_file(
  455. std::istream& in,
  456. unichar max_enc,
  457. unichar min_enc
  458. )
  459. {
  460. using namespace bdf_font_helpers;
  461. bdf_parser parser( in );
  462. bdf_parser::header_info hinfo;
  463. bdf_parser::char_info cinfo;
  464. gl.resize(max_enc+1);
  465. hinfo.default_char = - 1;
  466. if ( is_initialized == false || static_cast<std::streamoff>(in.tellg()) == std::ios::beg )
  467. {
  468. if ( parser.parse_header( hinfo ) == false )
  469. return 0; // parse_error: invalid or missing header
  470. }
  471. else
  472. {
  473. // not start of file, so use values from previous read.
  474. hinfo.has_global_dw = has_global_width;
  475. hinfo.dwx0 = global_width;
  476. }
  477. int res;
  478. unichar nr_letters_added = 0;
  479. unsigned width;
  480. for ( unichar n = min_enc; n <= max_enc; n++ )
  481. {
  482. if ( in.eof() )
  483. break;
  484. long pos = in.tellg();
  485. res = parser.parse_glyph( cinfo, n );
  486. if ( res < 0 )
  487. return 0; // parse_error
  488. if ( res == 0 )
  489. continue;
  490. if ( n > max_enc )
  491. {
  492. in.seekg( pos );
  493. break;
  494. }
  495. if ( cinfo.has_dw == false )
  496. {
  497. if ( hinfo.has_global_dw == false )
  498. return 0; // neither width info for the glyph, nor for the font as a whole (monospace).
  499. width = hinfo.dwx0;
  500. }
  501. else
  502. width = cinfo.dwx0;
  503. if ( bitmap_to_letter( cinfo.bitmap, n, width, cinfo.BBxoff0x, cinfo.BByoff0y ) == false )
  504. return 0;
  505. nr_letters_added++;
  506. if ( is_initialized == false )
  507. {
  508. // Bonding rectangle for the font.
  509. fbb.set_top( -( hinfo.Yoff + hinfo.FBBy - 1 ) );
  510. fbb.set_bottom( -hinfo.Yoff );
  511. fbb.set_left( hinfo.Xoff );
  512. fbb.set_right( hinfo.Xoff + hinfo.FBBx - 1 );
  513. // We need to compute this after all the glyphs are loaded.
  514. right_overflow_ = 0;
  515. // set this to something valid now, just in case.
  516. default_char = n;
  517. // Save any global width in case we later read from the same file.
  518. has_global_width = hinfo.has_global_dw;
  519. if ( has_global_width )
  520. global_width = hinfo.dwx0;
  521. // dont override value specified in the constructor with value specified in the file
  522. if ( specified_default_char < 0 && hinfo.default_char >= 0 )
  523. specified_default_char = hinfo.default_char;
  524. is_initialized = true;
  525. }
  526. }
  527. if ( is_initialized == false )
  528. return 0; // Not a single glyph was found within the specified range.
  529. if ( specified_default_char >= 0 )
  530. default_char = specified_default_char;
  531. // no default char specified, try find something sane.
  532. else
  533. default_char = 0;
  534. return nr_letters_added;
  535. }
  536. // ----------------------------------------------------------------------------------------
  537. bool bdf_font::
  538. bitmap_to_letter(
  539. array2d<char>& bitmap,
  540. unichar enc,
  541. unsigned long width,
  542. int x_offset,
  543. int y_offset
  544. )
  545. {
  546. unsigned nr_points = 0;
  547. bitmap.reset();
  548. while ( bitmap.move_next() )
  549. {
  550. unsigned char ch = bitmap.element();
  551. if ( ch > '9' )
  552. ch -= 'A' - '9' - 1;
  553. ch -= '0';
  554. if ( ch > 0xF )
  555. return false; // parse error: invalid hex digit
  556. bitmap.element() = ch;
  557. if ( ch & 8 )
  558. nr_points++;
  559. if ( ch & 4 )
  560. nr_points++;
  561. if ( ch & 2 )
  562. nr_points++;
  563. if ( ch & 1 )
  564. nr_points++;
  565. }
  566. letter( width, nr_points ).swap(gl[enc]);
  567. unsigned index = 0;
  568. for ( int r = 0;r < bitmap.nr();r++ )
  569. {
  570. for ( int c = 0;c < bitmap.nc();c++ )
  571. {
  572. int x = x_offset + c * 4;
  573. int y = -( y_offset + bitmap.nr() - r - 1 );
  574. char ch = bitmap[r][c];
  575. letter& glyph = gl[enc];
  576. if ( ch & 8 )
  577. {
  578. glyph[index] = letter::point( x, y );
  579. right_overflow_ = std::max( right_overflow_, x - width );
  580. index++;
  581. }
  582. if ( ch & 4 )
  583. {
  584. glyph[index] = letter::point( x + 1, y );
  585. right_overflow_ = std::max( right_overflow_, x + 1 - width );
  586. index++;
  587. }
  588. if ( ch & 2 )
  589. {
  590. glyph[index] = letter::point( x + 2, y );
  591. right_overflow_ = std::max( right_overflow_, x + 2 - width );
  592. index++;
  593. }
  594. if ( ch & 1 )
  595. {
  596. glyph[index] = letter::point( x + 3, y );
  597. right_overflow_ = std::max( right_overflow_, x + 3 - width );
  598. index++;
  599. }
  600. }
  601. }
  602. return true;
  603. }
  604. // ----------------------------------------------------------------------------------------
  605. const shared_ptr_thread_safe<font> get_native_font (
  606. )
  607. {
  608. return nativefont::native_font::get_font();
  609. }
  610. // ----------------------------------------------------------------------------------------
  611. }
  612. #endif // DLIB_FONTs_CPP_