Skip to content
Snippets Groups Projects
Select Git revision
1 result

LCDLanguageFont.md

LCDLanguageFont.md 12.90 KiB

LCD Language Font System

We deal with a variety of different displays. And we try to display a lot of different languages in different scripts on them. This system is ought to solve some of the related problems.

The Displays

We have two different technologies for the displays:

  • Character based displays: Have a fixed set of symbols (charset - font) in their ROM. All of them have a similar but not identical symbol set at the positions 0 to 127 similar to US-ASCII. On the other hand symbols at places higher than 127 have mayor differences. Until now we know of (and support):

    At all of them you can define 8 different symbols by yourself. In Marlin they are used for the Feedrate-, Thermometer-, ... symbols

  • Full graphic displays: Where we have the full freedom to display whatever we want, when we can make a program for it. Currently we deal with 128x64 Pixel Displays and divide this area in about 5 Lines with about 22 columns. Therefore we need fonts with a bounding box of about 6x10. Until now we used a

    • 1.) Marlin-font similar to ISO10646-1 but with special Symbols at the end, what made 'ü' and 'ä' inaccessible, in the size 6x10.
    • 2.) Because these letters where to big for some locations on the info-screen we use a full ISO10646-1 font in the size of 6x9.(3200 byte)
    • 3.) When we define USE_BIG_EDIT_FONT we use an additional ISO10646-1 font with 9x18, eating up another 3120 bytes of progmem - but readable without glasses.

The Languages

For the moment Marlin wants to support a lot of languages:

  • en English
  • pl Polish
  • fr French
  • de German
  • es Spanish
  • ru Russian
  • it Italian
  • pt Portuguese
  • pt-br Portuguese (Brazil)
  • fi Finnish
  • an Aragonese
  • nl Dutch
  • ca Catalan
  • eu Basque-Euskera

and recently on Thingiverse a new port to

appeared.

The Problem

All of this languages, except the English, normally use extended symbol sets, not contained in US-ASCII. Even the English translation uses some Symbols not in US-ASCII. ( '\002' for Thermometer, STR_h3 for '³') And worse, in the code itself symbols are used, not taking in account, on what display they are written. (This is true only for Displays with Japanese charset on Western displays you'll see a '~' and on Cyrillic an 'arrow coming from top - pointing to left', what is quite the opposite of what the programmer wanted.) The Germans want to use "ÄäÖöÜüß" the Finnish at least "äö". Other European languages want to see their accents on their letters. For other scripts like Cyrillic, Japanese, Greek, Hebrew, ... you have to find totally different symbol sets.

Until now the problems where ignored widely. The German translation used utf8 'ä' and 'ö' and did not care about showing garbage on ALL displays. The Russian translators new that their system only works on the Cyrillic character displays and relied on special LCD routines (LiquidCrystalRus.cpp) to handle UTF8 but missed to implement a proper strlen(). The Japanese translator dealed with to scripts. He introduced a very special font for the full graphic displays and made use of the Japanese version of the character displays. Therefore he ended up with two pretty unreadable language.h files full of '\xxx' definitions. Other languages ether tried to avoid wording with their special symbols or ignored the problem at all and used the basic symbols without the accents, dots, ... whatever.

The (partial) Solution

On a 'perfect' system like Windows or Linux we'd dig out unifont.ttf and some code from the libraries and they'd do what we want. But we are on a embedded system with very limited resources. So we had to find ways to limit the used space (Alone unifont.ttf is about 12MB) and have to make some compromise.

Aims:

  • 1.) Make the input for translators as convenient as possible. (Unicode UTF8)
  • 2.) Make the displays show the scripts as good as they can. (fonts, mapping tables)
  • 3.) Don't destroy the existing language files.
  • 3.) Don't loose to much speed
  • 4.) Don't loose to much memory.

Actions:

  • a.) Declare the display hardware we use. (Configuration.h)
  • b.) Declare the language ore script we use. (Configuration.h)
  • c.) Declare the kind of input we use. Ether direct pointers to the font (\xxx) or UTF8 and the font to use on graphic displays. (language_xx.h)
  • d.) Declare the needed translations. (language_xx.h)
  • e.) Make strlen() work with UTF8. (ultralcd.cpp)
  • f.) Seperate the Marlin Symbols to their own font. (dogm_font_data_Marlin_symbols.h)
  • g.) Make the fontswitch function remember the last used font. (dogm_lcd_implementation.h)
  • h.) Make output functions that count the number of written chars and switch the font to Marlin symbols and back when needed. (dogm_lcd_implementation.h) (ultralcd_implementation_hitachi_HD44780.h)
  • i.) Make three fonts to simulate the HD44780 charsets on dogm-displays. With this fonts the translator can check how his translation will look on the character based displays.
  • j.) Make ISO fonts for Cyrillic and Katakana because they do not need a mapping table and are faster to deal with and have a better charset (less compromises) than the HD44780 fonts.
  • k.) Make mapping functions and tables to convert from UTF8 to the fonts and integrate in the new output functions. (utf_mapper.h)
  • l.) Delete the not needed any more 'LiquidCrystalRus.xxx' files and their calls in 'ultralcd_implementation_hitachi_HD44780.h'.
  • m.) Split 'dogm_font_data_Marlin.h' into separate fonts and delete. (+dogm_font_data_6x9_marlin.h , +dogm_font_data_Marlin_symbols.h, -dogm_font_data_Marlin.h)
  • n.) Do a bit of preprocessor magic to match displays - fonts and mappers in 'utf_mapper.h'.