123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449 |
- /************************
- * western_char_set.cpp *
- ************************/
-
- /****************************************************************************
- * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
- * *
- * This program is free software: you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation, either version 3 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * To view a copy of the GNU General Public License, go to the following *
- * location: <http://www.gnu.org/licenses/>. *
- ****************************************************************************/
-
- #include "../ftdi_extended.h"
-
- #if defined(FTDI_EXTENDED) && BOTH(TOUCH_UI_USE_UTF8, TOUCH_UI_UTF8_WESTERN_CHARSET)
-
- #include "western_char_set_bitmap_31.h"
-
- #define NUM_ELEMENTS(a) (sizeof(a)/sizeof(a[0]))
-
- using namespace FTDI;
-
- constexpr static uint8_t std_font = 31;
- constexpr static uint8_t alt_font = 1;
-
- static uint32_t bitmap_addr;
-
- /* Glyphs in the WesternCharSet bitmap */
-
- enum {
- GRAVE,
- ACUTE,
- CIRCUMFLEX,
- TILDE,
- DIAERESIS,
- DOT_ABOVE,
- CEDILLA,
- NO_DOT_I,
- #if ENABLED(TOUCH_UI_UTF8_GERMANIC)
- SHARP_S,
- #endif
- #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
- LRG_O_STROKE,
- SML_O_STROKE,
- LRG_AE,
- SML_AE,
- LRG_ETH,
- SML_ETH,
- LRG_THORN,
- SML_THORN,
- #endif
- #if ENABLED(TOUCH_UI_UTF8_PUNCTUATION)
- LEFT_DBL_QUOTE,
- RIGHT_DBL_QUOTE,
- INV_EXCLAMATION,
- INV_QUESTION,
- #endif
- #if ENABLED(TOUCH_UI_UTF8_CURRENCY)
- CENT_SIGN,
- POUND_SIGN,
- CURRENCY_SIGN,
- YEN_SIGN,
- #endif
- #if ENABLED(TOUCH_UI_UTF8_SUPERSCRIPTS)
- SUPERSCRIPT_ONE,
- SUPERSCRIPT_TWO,
- SUPERSCRIPT_THREE,
- #endif
- #if ENABLED(TOUCH_UI_UTF8_ORDINALS)
- MASCULINE_ORDINAL,
- FEMININE_ORDINAL,
- #endif
- #if ENABLED(TOUCH_UI_UTF8_COPYRIGHT)
- COPYRIGHT_SIGN,
- REGISTERED_SIGN,
- #endif
- #if ENABLED(TOUCH_UI_UTF8_MATHEMATICS)
- PLUS_MINUS_SIGN,
- MULTIPLICATION_SIGN,
- DIVISION_SIGN,
- #endif
- #if ENABLED(TOUCH_UI_UTF8_FRACTIONS)
- FRACTION_QUARTER,
- FRACTION_HALF,
- FRACTION_THREE_FOURTHS,
- #endif
- #if ENABLED(TOUCH_UI_UTF8_SYMBOLS)
- MICRON_SIGN,
- PILCROW_SIGN,
- BROKEN_BAR,
- SECTION_SIGN,
- NOT_SIGN
- #endif
- };
-
- /* Centerline of characters that can take accents */
-
- constexpr int8_t mid_a = 12;
- constexpr int8_t mid_e = 12;
- constexpr int8_t mid_i = 5;
- constexpr int8_t mid_o = 12;
- constexpr int8_t mid_u = 12;
- constexpr int8_t mid_y = 11;
- constexpr int8_t mid_n = 12;
- constexpr int8_t mid_c = 12;
- constexpr int8_t mid_A = 13;
- constexpr int8_t mid_E = 13;
- constexpr int8_t mid_I = 6;
- constexpr int8_t mid_O = 14;
- constexpr int8_t mid_U = 14;
- constexpr int8_t mid_Y = 13;
- constexpr int8_t mid_N = 15;
- constexpr int8_t mid_C = 13;
-
- /* Centerline of accent glyphs */
-
- constexpr int8_t mid_accent = 16;
-
- /* When reusing the DOT_ABOVE accent glyph for the degree sign, we need to trim the leading space */
- constexpr uint8_t deg_sign_leading = 9;
-
- /* Look-up table for constructing characters (must be ordered by unicode)
- *
- * Characters are either complete symbols from the Western Char Set bitmap,
- * or they are constructed using a standard letter from the romfont and
- * drawing an accent from the Western Char Set bitmap over it.
- */
-
- #define UTF8(A) uint16_t(utf8(U##A))
-
- PROGMEM constexpr struct {
- uint16_t unicode;
- uint8_t std_char; // Glyph from standard ROMFONT (zero if none)
- uint8_t alt_char; // Glyph from Western Char Set bitmap
- uint8_t alt_data; // For accented characters, the centerline; else char width
- } char_recipe[] = {
- {0, 0, NO_DOT_I, 10 },
- #if ENABLED(TOUCH_UI_UTF8_PUNCTUATION)
- {UTF8('¡'), 0 , INV_EXCLAMATION, 13 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_CURRENCY)
- {UTF8('¢'), 0 , CENT_SIGN, 23 },
- {UTF8('£'), 0 , POUND_SIGN, 24 },
- {UTF8('¤'), 0 , CURRENCY_SIGN, 26 },
- {UTF8('¥'), 0 , YEN_SIGN, 26 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_SYMBOLS)
- {UTF8('¦'), 0 , BROKEN_BAR, 11 },
- {UTF8('§'), 0 , SECTION_SIGN, 21 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_COPYRIGHT)
- {UTF8('©'), 0 , COPYRIGHT_SIGN, 38 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_ORDINALS)
- {UTF8('ª'), 0 , FEMININE_ORDINAL, 19 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_PUNCTUATION)
- {UTF8('«'), 0 , LEFT_DBL_QUOTE, 23 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_SYMBOLS)
- {UTF8('¬'), 0 , NOT_SIGN, 32 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_COPYRIGHT)
- {UTF8('®'), 0 , REGISTERED_SIGN, 38 },
- #endif
- {UTF8('°'), 0 , DOT_ABOVE, 24 },
- #if ENABLED(TOUCH_UI_UTF8_MATHEMATICS)
- {UTF8('±'), 0 , NOT_SIGN, 32 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_SUPERSCRIPTS)
- {UTF8('²'), 0 , SUPERSCRIPT_TWO, 16 },
- {UTF8('³'), 0 , SUPERSCRIPT_THREE, 16 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_SYMBOLS)
- {UTF8('µ'), 0 , MICRON_SIGN, 28 },
- {UTF8('¶'), 0 , PILCROW_SIGN, 24 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_SUPERSCRIPTS)
- {UTF8('¹'), 0 , SUPERSCRIPT_ONE, 16 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_ORDINALS)
- {UTF8('º'), 0 , MASCULINE_ORDINAL, 19 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_PUNCTUATION)
- {UTF8('»'), 0 , RIGHT_DBL_QUOTE, 24 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_FRACTIONS)
- {UTF8('¼'), 0 , FRACTION_QUARTER, 40 },
- {UTF8('½'), 0 , FRACTION_HALF, 40 },
- {UTF8('¾'), 0 , FRACTION_THREE_FOURTHS, 40 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_PUNCTUATION)
- {UTF8('¿'), 0 , INV_QUESTION, 21 },
- #endif
- {UTF8('À'), 'A', GRAVE, mid_A},
- {UTF8('Á'), 'A', ACUTE, mid_A},
- {UTF8('Â'), 'A', CIRCUMFLEX, mid_A},
- {UTF8('Ã'), 'A', TILDE, mid_A},
- {UTF8('Ä'), 'A', DIAERESIS, mid_A},
- {UTF8('Å'), 'A', DOT_ABOVE, mid_A},
- #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
- {UTF8('Æ'), 0 , LRG_AE, 40},
- #endif
- {UTF8('Ç'), 'C', CEDILLA, mid_C},
- {UTF8('È'), 'E', GRAVE, mid_E},
- {UTF8('É'), 'E', ACUTE, mid_E},
- {UTF8('Ê'), 'E', CIRCUMFLEX, mid_E},
- {UTF8('Ë'), 'E', DIAERESIS, mid_E},
- {UTF8('Ì'), 'I', GRAVE, mid_I},
- {UTF8('Í'), 'I', ACUTE, mid_I},
- {UTF8('Î'), 'I', CIRCUMFLEX, mid_I},
- {UTF8('Ï'), 'I', DIAERESIS, mid_I},
- #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
- {UTF8('Ð'), 0, LRG_ETH, 31 },
- #endif
- {UTF8('Ñ'), 'N', TILDE, mid_N},
- {UTF8('Ò'), 'O', GRAVE, mid_O},
- {UTF8('Ó'), 'O', ACUTE, mid_O},
- {UTF8('Ô'), 'O', CIRCUMFLEX, mid_O},
- {UTF8('Õ'), 'O', TILDE, mid_O},
- {UTF8('Ö'), 'O', DIAERESIS, mid_O},
- #if ENABLED(TOUCH_UI_UTF8_MATHEMATICS)
- {UTF8('×'), 0 , MULTIPLICATION_SIGN, 32 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
- {UTF8('Ø'), 0 , LRG_O_STROKE, 32 },
- #endif
- {UTF8('Ù'), 'U', GRAVE, mid_U},
- {UTF8('Ú'), 'U', ACUTE, mid_U},
- {UTF8('Û'), 'U', CIRCUMFLEX, mid_U},
- {UTF8('Ü'), 'U', DIAERESIS, mid_U},
- {UTF8('Ý'), 'Y', ACUTE, mid_Y},
- #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
- {UTF8('Þ'), 0 , LRG_THORN, 25 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_GERMANIC)
- {UTF8('ß'), 0 , SHARP_S, 26 },
- #endif
- {UTF8('à'), 'a', GRAVE, mid_a},
- {UTF8('á'), 'a', ACUTE, mid_a},
- {UTF8('â'), 'a', CIRCUMFLEX, mid_a},
- {UTF8('ã'), 'a', TILDE, mid_a},
- {UTF8('ä'), 'a', DIAERESIS, mid_a},
- {UTF8('å'), 'a', DOT_ABOVE, mid_a},
- #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
- {UTF8('æ'), 0 , SML_AE, 40 },
- #endif
- {UTF8('ç'), 'c', CEDILLA, mid_c},
- {UTF8('è'), 'e', GRAVE, mid_e},
- {UTF8('é'), 'e', ACUTE, mid_e},
- {UTF8('ê'), 'e', CIRCUMFLEX, mid_e},
- {UTF8('ë'), 'e', DIAERESIS, mid_e},
- {UTF8('ì'), 'i', GRAVE, mid_i},
- {UTF8('í'), 'i', ACUTE, mid_i},
- {UTF8('î'), 'i', CIRCUMFLEX, mid_i},
- {UTF8('ï'), 'i', DIAERESIS, mid_i},
- #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
- {UTF8('ð'), 0, SML_ETH, 24 },
- #endif
- {UTF8('ñ'), 'n', TILDE, mid_n},
- {UTF8('ò'), 'o', GRAVE, mid_o},
- {UTF8('ó'), 'o', ACUTE, mid_o},
- {UTF8('ô'), 'o', CIRCUMFLEX, mid_o},
- {UTF8('õ'), 'o', TILDE, mid_o},
- {UTF8('ö'), 'o', DIAERESIS, mid_o},
- #if ENABLED(TOUCH_UI_UTF8_MATHEMATICS)
- {UTF8('÷'), 0 , DIVISION_SIGN, 32 },
- #endif
- #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
- {UTF8('ø'), 0 , SML_O_STROKE, 25 },
- #endif
- {UTF8('ù'), 'u', GRAVE, mid_u},
- {UTF8('ú'), 'u', ACUTE, mid_u},
- {UTF8('û'), 'u', CIRCUMFLEX, mid_u},
- {UTF8('ü'), 'u', DIAERESIS, mid_u},
- {UTF8('ý'), 'y', ACUTE, mid_y},
- #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
- {UTF8('þ'), 0 , SML_THORN, 25 },
- #endif
- {UTF8('ÿ'), 'y', DIAERESIS, mid_y}
- };
-
- static_assert(UTF8('¡') == 0xC2A1, "Incorrect encoding for character");
-
- /* Compile-time check that the table is in sorted order */
-
- constexpr bool is_sorted(size_t n) {
- return n < 2 ? true : char_recipe[n-2].unicode < char_recipe[n-1].unicode && is_sorted(n-1);
- }
-
- static_assert(is_sorted(NUM_ELEMENTS(char_recipe)), "The table must be sorted by unicode value");
-
- /* Performs a binary search to find a unicode character in the table */
-
- static int8_t find_char_data(FTDI::utf8_char_t c) {
- int8_t min = 0, max = NUM_ELEMENTS(char_recipe), index;
- for (;;) {
- index = (min + max)/2;
- const uint16_t char_at = pgm_read_word(&char_recipe[index].unicode);
- if (char_at == c) break;
- if (min == max) return -1;
- if (c > char_at)
- min = index + 1;
- else
- max = index;
- }
- return index;
- }
-
- static void get_char_data(uint8_t index, uint8_t &std_char, uint8_t &alt_char, uint8_t &alt_data) {
- std_char = pgm_read_byte(&char_recipe[index].std_char);
- alt_char = pgm_read_byte(&char_recipe[index].alt_char);
- alt_data = pgm_read_byte(&char_recipe[index].alt_data);
- }
-
- /**
- * Load bitmap data into RAMG. This function is called once at the start
- * of the program.
- *
- * Parameters:
- *
- * addr - Address in RAMG where the font data is written
- */
-
- void FTDI::WesternCharSet::load_data(uint32_t addr) {
- // Load the alternative font metrics
- CLCD::FontMetrics alt_fm;
- alt_fm.ptr = addr + 148;
- alt_fm.format = L4;
- alt_fm.stride = 19;
- alt_fm.width = 38;
- alt_fm.height = 49;
- LOOP_L_N(i, 127)
- alt_fm.char_widths[i] = 0;
-
- // For special characters, copy the character widths from the char tables
- LOOP_L_N(i, NUM_ELEMENTS(char_recipe)) {
- uint8_t std_char, alt_char, alt_data;
- get_char_data(i, std_char, alt_char, alt_data);
- if (std_char == 0)
- alt_fm.char_widths[alt_char] = alt_data;
- }
- CLCD::mem_write_bulk(addr, &alt_fm, 148);
-
- // Decode the RLE data and load it into RAMG as a bitmap
- write_rle_data(addr + 148, font, sizeof(font));
-
- bitmap_addr = addr;
- }
-
- /**
- * Populates the bitmap handles for the custom into the display list.
- * This function is called once at the start of each display list.
- *
- * Parameters:
- *
- * cmd - Object used for writing to the FTDI chip command queue.
- */
-
- void FTDI::WesternCharSet::load_bitmaps(CommandProcessor& cmd) {
- CLCD::FontMetrics alt_fm;
- alt_fm.ptr = bitmap_addr + 148;
- alt_fm.format = L4;
- alt_fm.stride = 19;
- alt_fm.width = 38;
- alt_fm.height = 49;
- set_font_bitmap(cmd, alt_fm, alt_font);
- }
-
- /**
- * Renders a character at location x and y. The x position is incremented
- * by the width of the character.
- *
- * Parameters:
- *
- * cmd - If non-NULL the symbol is drawn to the screen.
- * If NULL, only increment position for text measurement.
- *
- * x, y - The location at which to draw the character. On output,
- * incremented to the location of the next character.
- *
- * fs - A scaling object used to scale the font. The display will
- * already be configured to scale bitmaps, but positions
- * must be scaled using fs.scale()
- *
- * c - The unicode code point to draw. If the renderer does not
- * support the character, it should return false.
-
- * Returns: Whether the character was supported.
- */
-
- bool FTDI::WesternCharSet::render_glyph(CommandProcessor* cmd, int &x, int &y, font_size_t fs, utf8_char_t c) {
-
- // A supported character?
- if (c < UTF8('¡') || c > UTF8('ÿ')) return false;
-
- int8_t index = find_char_data(c);
- if (index == -1) return false;
-
- // Determine character characteristics
- uint8_t std_char, alt_char, alt_data;
- get_char_data(index, std_char, alt_char, alt_data);
-
- bool base_special;
- uint8_t base_width;
- uint8_t base_char;
- uint8_t accent_char;
- int8_t accent_dx, accent_dy;
-
- if (std_char == 0) {
- // Special character, non-accented
- base_width = alt_data;
- base_special = true;
- base_char = alt_char;
- accent_char = 0;
- if (c == UTF8('°'))
- x -= fs.scale(deg_sign_leading);
- } else {
- // Regular character with accent:
- accent_dx = alt_data - mid_accent;
- accent_dy = isupper(std_char) ? -7 : 0;
- accent_char = alt_char;
- base_width = StandardCharSet::std_char_width(std_char);
- base_special = std_char == 'i';
- base_char = base_special ? NO_DOT_I : std_char;
- }
-
- // If cmd != NULL, draw the glyph to the screen
- if (cmd) {
- ext_vertex2ii(*cmd, x, y, base_special ? alt_font : std_font, base_char);
- if (accent_char)
- ext_vertex2ii(*cmd, x + fs.scale(accent_dx), y + fs.scale(accent_dy), alt_font, accent_char);
- }
-
- // Increment X to the next character position
- x += fs.scale(base_width);
- return true;
- }
-
- #endif // FTDI_EXTENDED && TOUCH_UI_USE_UTF8 && TOUCH_UI_UTF8_WESTERN_CHARSET
|