My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

western_char_set.cpp 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /************************
  2. * western_char_set.cpp *
  3. ************************/
  4. /****************************************************************************
  5. * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
  6. * *
  7. * This program is free software: you can redistribute it and/or modify *
  8. * it under the terms of the GNU General Public License as published by *
  9. * the Free Software Foundation, either version 3 of the License, or *
  10. * (at your option) any later version. *
  11. * *
  12. * This program is distributed in the hope that it will be useful, *
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  15. * GNU General Public License for more details. *
  16. * *
  17. * To view a copy of the GNU General Public License, go to the following *
  18. * location: <http://www.gnu.org/licenses/>. *
  19. ****************************************************************************/
  20. #include "../ftdi_extended.h"
  21. #if defined(FTDI_EXTENDED) && BOTH(TOUCH_UI_USE_UTF8, TOUCH_UI_UTF8_WESTERN_CHARSET)
  22. #include "western_char_set_bitmap_31.h"
  23. #define NUM_ELEMENTS(a) (sizeof(a)/sizeof(a[0]))
  24. using namespace FTDI;
  25. constexpr static uint8_t std_font = 31;
  26. constexpr static uint8_t alt_font = 1;
  27. static uint32_t bitmap_addr;
  28. /* Glyphs in the WesternCharSet bitmap */
  29. enum {
  30. GRAVE,
  31. ACUTE,
  32. CIRCUMFLEX,
  33. TILDE,
  34. DIAERESIS,
  35. DOT_ABOVE,
  36. CEDILLA,
  37. NO_DOT_I,
  38. #if ENABLED(TOUCH_UI_UTF8_GERMANIC)
  39. SHARP_S,
  40. #endif
  41. #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
  42. LRG_O_STROKE,
  43. SML_O_STROKE,
  44. LRG_AE,
  45. SML_AE,
  46. LRG_ETH,
  47. SML_ETH,
  48. LRG_THORN,
  49. SML_THORN,
  50. #endif
  51. #if ENABLED(TOUCH_UI_UTF8_PUNCTUATION)
  52. LEFT_DBL_QUOTE,
  53. RIGHT_DBL_QUOTE,
  54. INV_EXCLAMATION,
  55. INV_QUESTION,
  56. #endif
  57. #if ENABLED(TOUCH_UI_UTF8_CURRENCY)
  58. CENT_SIGN,
  59. POUND_SIGN,
  60. CURRENCY_SIGN,
  61. YEN_SIGN,
  62. #endif
  63. #if ENABLED(TOUCH_UI_UTF8_SUPERSCRIPTS)
  64. SUPERSCRIPT_ONE,
  65. SUPERSCRIPT_TWO,
  66. SUPERSCRIPT_THREE,
  67. #endif
  68. #if ENABLED(TOUCH_UI_UTF8_ORDINALS)
  69. MASCULINE_ORDINAL,
  70. FEMININE_ORDINAL,
  71. #endif
  72. #if ENABLED(TOUCH_UI_UTF8_COPYRIGHT)
  73. COPYRIGHT_SIGN,
  74. REGISTERED_SIGN,
  75. #endif
  76. #if ENABLED(TOUCH_UI_UTF8_MATHEMATICS)
  77. PLUS_MINUS_SIGN,
  78. MULTIPLICATION_SIGN,
  79. DIVISION_SIGN,
  80. #endif
  81. #if ENABLED(TOUCH_UI_UTF8_FRACTIONS)
  82. FRACTION_QUARTER,
  83. FRACTION_HALF,
  84. FRACTION_THREE_FOURTHS,
  85. #endif
  86. #if ENABLED(TOUCH_UI_UTF8_SYMBOLS)
  87. MICRON_SIGN,
  88. PILCROW_SIGN,
  89. BROKEN_BAR,
  90. SECTION_SIGN,
  91. NOT_SIGN
  92. #endif
  93. };
  94. /* Centerline of characters that can take accents */
  95. constexpr int8_t mid_a = 12;
  96. constexpr int8_t mid_e = 12;
  97. constexpr int8_t mid_i = 5;
  98. constexpr int8_t mid_o = 12;
  99. constexpr int8_t mid_u = 12;
  100. constexpr int8_t mid_y = 11;
  101. constexpr int8_t mid_n = 12;
  102. constexpr int8_t mid_c = 12;
  103. constexpr int8_t mid_A = 13;
  104. constexpr int8_t mid_E = 13;
  105. constexpr int8_t mid_I = 6;
  106. constexpr int8_t mid_O = 14;
  107. constexpr int8_t mid_U = 14;
  108. constexpr int8_t mid_Y = 13;
  109. constexpr int8_t mid_N = 15;
  110. constexpr int8_t mid_C = 13;
  111. /* Centerline of accent glyphs */
  112. constexpr int8_t mid_accent = 16;
  113. /* When reusing the DOT_ABOVE accent glyph for the degree sign, we need to trim the leading space */
  114. constexpr uint8_t deg_sign_leading = 9;
  115. /* Look-up table for constructing characters (must be ordered by unicode)
  116. *
  117. * Characters are either complete symbols from the Western Char Set bitmap,
  118. * or they are constructed using a standard letter from the romfont and
  119. * drawing an accent from the Western Char Set bitmap over it.
  120. */
  121. #define UTF8(A) uint16_t(utf8(U##A))
  122. PROGMEM constexpr struct {
  123. uint16_t unicode;
  124. uint8_t std_char; // Glyph from standard ROMFONT (zero if none)
  125. uint8_t alt_char; // Glyph from Western Char Set bitmap
  126. uint8_t alt_data; // For accented characters, the centerline; else char width
  127. } char_recipe[] = {
  128. {0, 0, NO_DOT_I, 10 },
  129. #if ENABLED(TOUCH_UI_UTF8_PUNCTUATION)
  130. {UTF8('¡'), 0 , INV_EXCLAMATION, 13 },
  131. #endif
  132. #if ENABLED(TOUCH_UI_UTF8_CURRENCY)
  133. {UTF8('¢'), 0 , CENT_SIGN, 23 },
  134. {UTF8('£'), 0 , POUND_SIGN, 24 },
  135. {UTF8('¤'), 0 , CURRENCY_SIGN, 26 },
  136. {UTF8('¥'), 0 , YEN_SIGN, 26 },
  137. #endif
  138. #if ENABLED(TOUCH_UI_UTF8_SYMBOLS)
  139. {UTF8('¦'), 0 , BROKEN_BAR, 11 },
  140. {UTF8('§'), 0 , SECTION_SIGN, 21 },
  141. #endif
  142. #if ENABLED(TOUCH_UI_UTF8_COPYRIGHT)
  143. {UTF8('©'), 0 , COPYRIGHT_SIGN, 38 },
  144. #endif
  145. #if ENABLED(TOUCH_UI_UTF8_ORDINALS)
  146. {UTF8('ª'), 0 , FEMININE_ORDINAL, 19 },
  147. #endif
  148. #if ENABLED(TOUCH_UI_UTF8_PUNCTUATION)
  149. {UTF8('«'), 0 , LEFT_DBL_QUOTE, 23 },
  150. #endif
  151. #if ENABLED(TOUCH_UI_UTF8_SYMBOLS)
  152. {UTF8('¬'), 0 , NOT_SIGN, 32 },
  153. #endif
  154. #if ENABLED(TOUCH_UI_UTF8_COPYRIGHT)
  155. {UTF8('®'), 0 , REGISTERED_SIGN, 38 },
  156. #endif
  157. {UTF8('°'), 0 , DOT_ABOVE, 24 },
  158. #if ENABLED(TOUCH_UI_UTF8_MATHEMATICS)
  159. {UTF8('±'), 0 , NOT_SIGN, 32 },
  160. #endif
  161. #if ENABLED(TOUCH_UI_UTF8_SUPERSCRIPTS)
  162. {UTF8('²'), 0 , SUPERSCRIPT_TWO, 16 },
  163. {UTF8('³'), 0 , SUPERSCRIPT_THREE, 16 },
  164. #endif
  165. #if ENABLED(TOUCH_UI_UTF8_SYMBOLS)
  166. {UTF8('µ'), 0 , MICRON_SIGN, 28 },
  167. {UTF8('¶'), 0 , PILCROW_SIGN, 24 },
  168. #endif
  169. #if ENABLED(TOUCH_UI_UTF8_SUPERSCRIPTS)
  170. {UTF8('¹'), 0 , SUPERSCRIPT_ONE, 16 },
  171. #endif
  172. #if ENABLED(TOUCH_UI_UTF8_ORDINALS)
  173. {UTF8('º'), 0 , MASCULINE_ORDINAL, 19 },
  174. #endif
  175. #if ENABLED(TOUCH_UI_UTF8_PUNCTUATION)
  176. {UTF8('»'), 0 , RIGHT_DBL_QUOTE, 24 },
  177. #endif
  178. #if ENABLED(TOUCH_UI_UTF8_FRACTIONS)
  179. {UTF8('¼'), 0 , FRACTION_QUARTER, 40 },
  180. {UTF8('½'), 0 , FRACTION_HALF, 40 },
  181. {UTF8('¾'), 0 , FRACTION_THREE_FOURTHS, 40 },
  182. #endif
  183. #if ENABLED(TOUCH_UI_UTF8_PUNCTUATION)
  184. {UTF8('¿'), 0 , INV_QUESTION, 21 },
  185. #endif
  186. {UTF8('À'), 'A', GRAVE, mid_A},
  187. {UTF8('Á'), 'A', ACUTE, mid_A},
  188. {UTF8('Â'), 'A', CIRCUMFLEX, mid_A},
  189. {UTF8('Ã'), 'A', TILDE, mid_A},
  190. {UTF8('Ä'), 'A', DIAERESIS, mid_A},
  191. {UTF8('Å'), 'A', DOT_ABOVE, mid_A},
  192. #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
  193. {UTF8('Æ'), 0 , LRG_AE, 40},
  194. #endif
  195. {UTF8('Ç'), 'C', CEDILLA, mid_C},
  196. {UTF8('È'), 'E', GRAVE, mid_E},
  197. {UTF8('É'), 'E', ACUTE, mid_E},
  198. {UTF8('Ê'), 'E', CIRCUMFLEX, mid_E},
  199. {UTF8('Ë'), 'E', DIAERESIS, mid_E},
  200. {UTF8('Ì'), 'I', GRAVE, mid_I},
  201. {UTF8('Í'), 'I', ACUTE, mid_I},
  202. {UTF8('Î'), 'I', CIRCUMFLEX, mid_I},
  203. {UTF8('Ï'), 'I', DIAERESIS, mid_I},
  204. #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
  205. {UTF8('Ð'), 0, LRG_ETH, 31 },
  206. #endif
  207. {UTF8('Ñ'), 'N', TILDE, mid_N},
  208. {UTF8('Ò'), 'O', GRAVE, mid_O},
  209. {UTF8('Ó'), 'O', ACUTE, mid_O},
  210. {UTF8('Ô'), 'O', CIRCUMFLEX, mid_O},
  211. {UTF8('Õ'), 'O', TILDE, mid_O},
  212. {UTF8('Ö'), 'O', DIAERESIS, mid_O},
  213. #if ENABLED(TOUCH_UI_UTF8_MATHEMATICS)
  214. {UTF8('×'), 0 , MULTIPLICATION_SIGN, 32 },
  215. #endif
  216. #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
  217. {UTF8('Ø'), 0 , LRG_O_STROKE, 32 },
  218. #endif
  219. {UTF8('Ù'), 'U', GRAVE, mid_U},
  220. {UTF8('Ú'), 'U', ACUTE, mid_U},
  221. {UTF8('Û'), 'U', CIRCUMFLEX, mid_U},
  222. {UTF8('Ü'), 'U', DIAERESIS, mid_U},
  223. {UTF8('Ý'), 'Y', ACUTE, mid_Y},
  224. #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
  225. {UTF8('Þ'), 0 , LRG_THORN, 25 },
  226. #endif
  227. #if ENABLED(TOUCH_UI_UTF8_GERMANIC)
  228. {UTF8('ß'), 0 , SHARP_S, 26 },
  229. #endif
  230. {UTF8('à'), 'a', GRAVE, mid_a},
  231. {UTF8('á'), 'a', ACUTE, mid_a},
  232. {UTF8('â'), 'a', CIRCUMFLEX, mid_a},
  233. {UTF8('ã'), 'a', TILDE, mid_a},
  234. {UTF8('ä'), 'a', DIAERESIS, mid_a},
  235. {UTF8('å'), 'a', DOT_ABOVE, mid_a},
  236. #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
  237. {UTF8('æ'), 0 , SML_AE, 40 },
  238. #endif
  239. {UTF8('ç'), 'c', CEDILLA, mid_c},
  240. {UTF8('è'), 'e', GRAVE, mid_e},
  241. {UTF8('é'), 'e', ACUTE, mid_e},
  242. {UTF8('ê'), 'e', CIRCUMFLEX, mid_e},
  243. {UTF8('ë'), 'e', DIAERESIS, mid_e},
  244. {UTF8('ì'), 'i', GRAVE, mid_i},
  245. {UTF8('í'), 'i', ACUTE, mid_i},
  246. {UTF8('î'), 'i', CIRCUMFLEX, mid_i},
  247. {UTF8('ï'), 'i', DIAERESIS, mid_i},
  248. #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
  249. {UTF8('ð'), 0, SML_ETH, 24 },
  250. #endif
  251. {UTF8('ñ'), 'n', TILDE, mid_n},
  252. {UTF8('ò'), 'o', GRAVE, mid_o},
  253. {UTF8('ó'), 'o', ACUTE, mid_o},
  254. {UTF8('ô'), 'o', CIRCUMFLEX, mid_o},
  255. {UTF8('õ'), 'o', TILDE, mid_o},
  256. {UTF8('ö'), 'o', DIAERESIS, mid_o},
  257. #if ENABLED(TOUCH_UI_UTF8_MATHEMATICS)
  258. {UTF8('÷'), 0 , DIVISION_SIGN, 32 },
  259. #endif
  260. #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
  261. {UTF8('ø'), 0 , SML_O_STROKE, 25 },
  262. #endif
  263. {UTF8('ù'), 'u', GRAVE, mid_u},
  264. {UTF8('ú'), 'u', ACUTE, mid_u},
  265. {UTF8('û'), 'u', CIRCUMFLEX, mid_u},
  266. {UTF8('ü'), 'u', DIAERESIS, mid_u},
  267. {UTF8('ý'), 'y', ACUTE, mid_y},
  268. #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
  269. {UTF8('þ'), 0 , SML_THORN, 25 },
  270. #endif
  271. {UTF8('ÿ'), 'y', DIAERESIS, mid_y}
  272. };
  273. static_assert(UTF8('¡') == 0xC2A1, "Incorrect encoding for character");
  274. /* Compile-time check that the table is in sorted order */
  275. constexpr bool is_sorted(size_t n) {
  276. return n < 2 ? true : char_recipe[n-2].unicode < char_recipe[n-1].unicode && is_sorted(n-1);
  277. }
  278. static_assert(is_sorted(NUM_ELEMENTS(char_recipe)), "The table must be sorted by unicode value");
  279. /* Performs a binary search to find a unicode character in the table */
  280. static int8_t find_char_data(FTDI::utf8_char_t c) {
  281. int8_t min = 0, max = NUM_ELEMENTS(char_recipe), index;
  282. for (;;) {
  283. index = (min + max)/2;
  284. const uint16_t char_at = pgm_read_word(&char_recipe[index].unicode);
  285. if (char_at == c) break;
  286. if (min == max) return -1;
  287. if (c > char_at)
  288. min = index + 1;
  289. else
  290. max = index;
  291. }
  292. return index;
  293. }
  294. static void get_char_data(uint8_t index, uint8_t &std_char, uint8_t &alt_char, uint8_t &alt_data) {
  295. std_char = pgm_read_byte(&char_recipe[index].std_char);
  296. alt_char = pgm_read_byte(&char_recipe[index].alt_char);
  297. alt_data = pgm_read_byte(&char_recipe[index].alt_data);
  298. }
  299. /**
  300. * Load bitmap data into RAMG. This function is called once at the start
  301. * of the program.
  302. *
  303. * Parameters:
  304. *
  305. * addr - Address in RAMG where the font data is written
  306. */
  307. void FTDI::WesternCharSet::load_data(uint32_t addr) {
  308. // Load the alternative font metrics
  309. CLCD::FontMetrics alt_fm;
  310. alt_fm.ptr = addr + 148;
  311. alt_fm.format = L4;
  312. alt_fm.stride = 19;
  313. alt_fm.width = 38;
  314. alt_fm.height = 49;
  315. LOOP_L_N(i, 127)
  316. alt_fm.char_widths[i] = 0;
  317. // For special characters, copy the character widths from the char tables
  318. LOOP_L_N(i, NUM_ELEMENTS(char_recipe)) {
  319. uint8_t std_char, alt_char, alt_data;
  320. get_char_data(i, std_char, alt_char, alt_data);
  321. if (std_char == 0)
  322. alt_fm.char_widths[alt_char] = alt_data;
  323. }
  324. CLCD::mem_write_bulk(addr, &alt_fm, 148);
  325. // Decode the RLE data and load it into RAMG as a bitmap
  326. write_rle_data(addr + 148, font, sizeof(font));
  327. bitmap_addr = addr;
  328. }
  329. /**
  330. * Populates the bitmap handles for the custom into the display list.
  331. * This function is called once at the start of each display list.
  332. *
  333. * Parameters:
  334. *
  335. * cmd - Object used for writing to the FTDI chip command queue.
  336. */
  337. void FTDI::WesternCharSet::load_bitmaps(CommandProcessor& cmd) {
  338. CLCD::FontMetrics alt_fm;
  339. alt_fm.ptr = bitmap_addr + 148;
  340. alt_fm.format = L4;
  341. alt_fm.stride = 19;
  342. alt_fm.width = 38;
  343. alt_fm.height = 49;
  344. set_font_bitmap(cmd, alt_fm, alt_font);
  345. }
  346. /**
  347. * Renders a character at location x and y. The x position is incremented
  348. * by the width of the character.
  349. *
  350. * Parameters:
  351. *
  352. * cmd - If non-NULL the symbol is drawn to the screen.
  353. * If NULL, only increment position for text measurement.
  354. *
  355. * x, y - The location at which to draw the character. On output,
  356. * incremented to the location of the next character.
  357. *
  358. * fs - A scaling object used to scale the font. The display will
  359. * already be configured to scale bitmaps, but positions
  360. * must be scaled using fs.scale()
  361. *
  362. * c - The unicode code point to draw. If the renderer does not
  363. * support the character, it should return false.
  364. * Returns: Whether the character was supported.
  365. */
  366. bool FTDI::WesternCharSet::render_glyph(CommandProcessor* cmd, int &x, int &y, font_size_t fs, utf8_char_t c) {
  367. // A supported character?
  368. if (c < UTF8('¡') || c > UTF8('ÿ')) return false;
  369. int8_t index = find_char_data(c);
  370. if (index == -1) return false;
  371. // Determine character characteristics
  372. uint8_t std_char, alt_char, alt_data;
  373. get_char_data(index, std_char, alt_char, alt_data);
  374. bool base_special;
  375. uint8_t base_width;
  376. uint8_t base_char;
  377. uint8_t accent_char;
  378. int8_t accent_dx, accent_dy;
  379. if (std_char == 0) {
  380. // Special character, non-accented
  381. base_width = alt_data;
  382. base_special = true;
  383. base_char = alt_char;
  384. accent_char = 0;
  385. if (c == UTF8('°'))
  386. x -= fs.scale(deg_sign_leading);
  387. } else {
  388. // Regular character with accent:
  389. accent_dx = alt_data - mid_accent;
  390. accent_dy = isupper(std_char) ? -7 : 0;
  391. accent_char = alt_char;
  392. base_width = StandardCharSet::std_char_width(std_char);
  393. base_special = std_char == 'i';
  394. base_char = base_special ? NO_DOT_I : std_char;
  395. }
  396. // If cmd != NULL, draw the glyph to the screen
  397. if (cmd) {
  398. ext_vertex2ii(*cmd, x, y, base_special ? alt_font : std_font, base_char);
  399. if (accent_char)
  400. ext_vertex2ii(*cmd, x + fs.scale(accent_dx), y + fs.scale(accent_dy), alt_font, accent_char);
  401. }
  402. // Increment X to the next character position
  403. x += fs.scale(base_width);
  404. return true;
  405. }
  406. #endif // FTDI_EXTENDED && TOUCH_UI_USE_UTF8 && TOUCH_UI_UTF8_WESTERN_CHARSET