[2.0.x] UTF-8 language translation support (#10213)
This commit is contained in:
committed by
Scott Lahteine
parent
daa712455b
commit
c96412a78f
2736
buildroot/share/fonts/ISO10646-0-1.bdf
Normal file
2736
buildroot/share/fonts/ISO10646-0-1.bdf
Normal file
File diff suppressed because it is too large
Load Diff
6932
buildroot/share/fonts/ISO10646-0-2.bdf
Normal file
6932
buildroot/share/fonts/ISO10646-0-2.bdf
Normal file
File diff suppressed because it is too large
Load Diff
547085
buildroot/share/fonts/ISO10646-0-3.bdf
Normal file
547085
buildroot/share/fonts/ISO10646-0-3.bdf
Normal file
File diff suppressed because it is too large
Load Diff
75
buildroot/share/fonts/genallfont.sh
Executable file
75
buildroot/share/fonts/genallfont.sh
Executable file
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#####################################################################
|
||||
# genallfont.sh for Marlin
|
||||
#
|
||||
# This script will generates font data for language headers
|
||||
#
|
||||
# Copyright 2015-2016 Yunhui Fu <yhfudev@gmail.com>
|
||||
# License: GPL/BSD
|
||||
#####################################################################
|
||||
my_getpath () {
|
||||
PARAM_DN="$1"
|
||||
shift
|
||||
#readlink -f
|
||||
DN="${PARAM_DN}"
|
||||
FN=
|
||||
if [ ! -d "${DN}" ]; then
|
||||
FN=$(basename "${DN}")
|
||||
DN=$(dirname "${DN}")
|
||||
fi
|
||||
cd "${DN}" > /dev/null 2>&1
|
||||
DN=$(pwd)
|
||||
cd - > /dev/null 2>&1
|
||||
echo "${DN}/${FN}"
|
||||
}
|
||||
#DN_EXEC=`echo "$0" | ${EXEC_AWK} -F/ '{b=$1; for (i=2; i < NF; i ++) {b=b "/" $(i)}; print b}'`
|
||||
DN_EXEC=$(dirname $(my_getpath "$0") )
|
||||
if [ ! "${DN_EXEC}" = "" ]; then
|
||||
DN_EXEC="$(my_getpath "${DN_EXEC}")/"
|
||||
else
|
||||
DN_EXEC="${DN_EXEC}/"
|
||||
fi
|
||||
#####################################################################
|
||||
EXEC_WXGGEN="${DN_EXEC}/uxggenpages.sh"
|
||||
|
||||
EXEC_BDF2U8G=`which bdf2u8g`
|
||||
echo "0 set EXEC_BDF2U8G=$EXEC_BDF2U8G"
|
||||
if [ ! -x "${EXEC_BDF2U8G}" ]; then
|
||||
EXEC_BDF2U8G="${DN_EXEC}/bdf2u8g"
|
||||
echo "1 set EXEC_BDF2U8G=$EXEC_BDF2U8G"
|
||||
fi
|
||||
if [ ! -x "${EXEC_BDF2U8G}" ]; then
|
||||
EXEC_BDF2U8G="${PWD}/bdf2u8g"
|
||||
echo "2 set EXEC_BDF2U8G=$EXEC_BDF2U8G"
|
||||
fi
|
||||
if [ ! -x "${EXEC_BDF2U8G}" ]; then
|
||||
echo "Not found bdf2u8g!"
|
||||
echo "plaese compile u8blib/tools/font/bdf2u8g/bdf2u8g and link to it from here!"
|
||||
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FN_NEWFONT="${DN_EXEC}/ISO10646-0-3.bdf"
|
||||
if [ ! "$1" = "" ]; then
|
||||
FN_NEWFONT="$1"
|
||||
fi
|
||||
|
||||
DN_WORK=./tmp1
|
||||
|
||||
(cd ${DN_EXEC}; gcc -o genpages genpages.c getline.c)
|
||||
|
||||
LANGS="an bg ca zh_CN zh_TW cz da de el el-gr en es eu fi fr gl hr it jp-kana nl pl pt pt-br ru sk tr uk test"
|
||||
|
||||
for LANG in ${LANGS} ; do
|
||||
rm -rf ${DN_WORK}/
|
||||
mkdir -p ${DN_WORK}
|
||||
cp Configuration.h ${DN_WORK}/
|
||||
cp src/lcd/language/language_${LANG}.h ${DN_WORK}/
|
||||
cd ${DN_WORK}/
|
||||
${EXEC_WXGGEN} "${FN_NEWFONT}"
|
||||
cd ../
|
||||
mv ${DN_WORK}/fontutf8-data.h src/lcd/dogm/language_data_${LANG}.h
|
||||
rm -rf ${DN_WORK}/
|
||||
done
|
||||
|
207
buildroot/share/fonts/genpages.c
Normal file
207
buildroot/share/fonts/genpages.c
Normal file
@ -0,0 +1,207 @@
|
||||
/**
|
||||
* @file genpages.c
|
||||
* @brief generate required font page files
|
||||
* @author Yunhui Fu (yhfudev@gmail.com)
|
||||
* @version 1.0
|
||||
* @date 2015-02-19
|
||||
* @copyright Yunhui Fu (2015)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h> /* uint8_t */
|
||||
#include <stdlib.h> /* size_t */
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "getline.h"
|
||||
|
||||
wchar_t get_val_utf82uni(uint8_t *pstart) {
|
||||
size_t cntleft;
|
||||
wchar_t retval = 0;
|
||||
|
||||
if (0 == (0x80 & *pstart)) return *pstart;
|
||||
|
||||
if (((*pstart & 0xE0) ^ 0xC0) == 0) {
|
||||
cntleft = 1;
|
||||
retval = *pstart & ~0xE0;
|
||||
}
|
||||
else if (((*pstart & 0xF0) ^ 0xE0) == 0) {
|
||||
cntleft = 2;
|
||||
retval = *pstart & ~0xF0;
|
||||
}
|
||||
else if (((*pstart & 0xF8) ^ 0xF0) == 0) {
|
||||
cntleft = 3;
|
||||
retval = *pstart & ~0xF8;
|
||||
}
|
||||
else if (((*pstart & 0xFC) ^ 0xF8) == 0) {
|
||||
cntleft = 4;
|
||||
retval = *pstart & ~0xFC;
|
||||
}
|
||||
else if (((*pstart & 0xFE) ^ 0xFC) == 0) {
|
||||
cntleft = 5;
|
||||
retval = *pstart & ~0xFE;
|
||||
}
|
||||
else {
|
||||
/* encoding error */
|
||||
cntleft = 0;
|
||||
retval = 0;
|
||||
}
|
||||
pstart++;
|
||||
for (; cntleft > 0; cntleft --) {
|
||||
retval <<= 6;
|
||||
retval |= *pstart & 0x3F;
|
||||
pstart++;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 转换 UTF-8 编码的一个字符为本地的 Unicode 字符(wchar_t)
|
||||
*
|
||||
* @param pstart : 存储 UTF-8 字符的指针
|
||||
* @param pval : 需要返回的 Unicode 字符存放地址指针
|
||||
*
|
||||
* @return 成功返回下个 UTF-8 字符的位置
|
||||
*
|
||||
* 转换 UTF-8 编码的一个字符为本地的 Unicode 字符(wchar_t)
|
||||
*/
|
||||
uint8_t* get_utf8_value(uint8_t *pstart, wchar_t *pval) {
|
||||
uint32_t val = 0;
|
||||
uint8_t *p = pstart;
|
||||
/*size_t maxlen = strlen(pstart);*/
|
||||
|
||||
assert(NULL != pstart);
|
||||
|
||||
if (0 == (0x80 & *p)) {
|
||||
val = (size_t)*p;
|
||||
p++;
|
||||
}
|
||||
else if (0xC0 == (0xE0 & *p)) {
|
||||
val = *p & 0x1F;
|
||||
val <<= 6;
|
||||
p++;
|
||||
val |= (*p & 0x3F);
|
||||
p++;
|
||||
assert((wchar_t)val == get_val_utf82uni(pstart));
|
||||
}
|
||||
else if (0xE0 == (0xF0 & *p)) {
|
||||
val = *p & 0x0F;
|
||||
val <<= 6; p++;
|
||||
val |= (*p & 0x3F);
|
||||
val <<= 6; p++;
|
||||
val |= (*p & 0x3F);
|
||||
p++;
|
||||
assert((wchar_t)val == get_val_utf82uni(pstart));
|
||||
}
|
||||
else if (0xF0 == (0xF8 & *p)) {
|
||||
val = *p & 0x07;
|
||||
val <<= 6; p++;
|
||||
val |= (*p & 0x3F);
|
||||
val <<= 6; p++;
|
||||
val |= (*p & 0x3F);
|
||||
val <<= 6; p++;
|
||||
val |= (*p & 0x3F);
|
||||
p++;
|
||||
assert((wchar_t)val == get_val_utf82uni(pstart));
|
||||
}
|
||||
else if (0xF8 == (0xFC & *p)) {
|
||||
val = *p & 0x03;
|
||||
val <<= 6; p++;
|
||||
val |= (*p & 0x3F);
|
||||
val <<= 6; p++;
|
||||
val |= (*p & 0x3F);
|
||||
val <<= 6; p++;
|
||||
val |= (*p & 0x3F);
|
||||
val <<= 6; p++;
|
||||
val |= (*p & 0x3F);
|
||||
p++;
|
||||
assert((wchar_t)val == get_val_utf82uni(pstart));
|
||||
}
|
||||
else if (0xFC == (0xFE & *p)) {
|
||||
val = *p & 0x01;
|
||||
val <<= 6; p++;
|
||||
val |= (*p & 0x3F);
|
||||
val <<= 6; p++;
|
||||
val |= (*p & 0x3F);
|
||||
val <<= 6; p++;
|
||||
val |= (*p & 0x3F);
|
||||
val <<= 6; p++;
|
||||
val |= (*p & 0x3F);
|
||||
val <<= 6; p++;
|
||||
val |= (*p & 0x3F);
|
||||
p++;
|
||||
assert((wchar_t)val == get_val_utf82uni(pstart));
|
||||
}
|
||||
else if (0x80 == (0xC0 & *p)) {
|
||||
/* error? */
|
||||
for (; 0x80 == (0xC0 & *p); p++);
|
||||
}
|
||||
else {
|
||||
/* error */
|
||||
for (; ((0xFE & *p) > 0xFC); p++);
|
||||
}
|
||||
/*
|
||||
if (val == 0) {
|
||||
p = NULL;
|
||||
*/
|
||||
/*
|
||||
}
|
||||
else if (pstart + maxlen < p) {
|
||||
p = pstart;
|
||||
if (pval) *pval = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
if (pval) *pval = val;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void usage(char* progname) {
|
||||
fprintf(stderr, "Usage: %s\n", progname);
|
||||
fprintf(stderr, " read data from stdin\n");
|
||||
}
|
||||
|
||||
void utf8_parse(const char* msg, unsigned int len) {
|
||||
uint8_t *pend = NULL;
|
||||
uint8_t *p;
|
||||
uint8_t *pre;
|
||||
wchar_t val;
|
||||
int page;
|
||||
|
||||
pend = (uint8_t *)msg + len;
|
||||
for (pre = (uint8_t *)msg; pre < pend;) {
|
||||
val = 0;
|
||||
p = get_utf8_value(pre, &val);
|
||||
if (NULL == p) break;
|
||||
page = val / 128;
|
||||
if (val >= 256) {
|
||||
fprintf(stdout, "%d %d ", page, (val % 128));
|
||||
for (; pre < p; pre++) fprintf(stdout, "%c", *pre);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
pre = p;
|
||||
}
|
||||
}
|
||||
|
||||
int load_file(FILE *fp) {
|
||||
char * buffer = NULL;
|
||||
size_t szbuf = 0;
|
||||
|
||||
szbuf = 10000;
|
||||
buffer = (char*)malloc(szbuf);
|
||||
if (NULL == buffer) return -1;
|
||||
//pos = ftell (fp);
|
||||
while (getline( &buffer, &szbuf, fp ) > 0)
|
||||
utf8_parse((const char*)buffer, (unsigned int)strlen ((char *)buffer));
|
||||
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
if (argc > 1) {
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
load_file(stdin);
|
||||
}
|
126
buildroot/share/fonts/getline.c
Normal file
126
buildroot/share/fonts/getline.c
Normal file
@ -0,0 +1,126 @@
|
||||
/**
|
||||
* getline.c --- Based on...
|
||||
*
|
||||
* getdelim.c --- Implementation of replacement getdelim function.
|
||||
* Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005 Free
|
||||
* Software Foundation, 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 2, 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/* Ported from glibc by Simon Josefsson. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#if !HAVE_GETLINE
|
||||
|
||||
//#include "getdelim.h"
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
#define SIZE_MAX ((size_t) -1)
|
||||
#endif
|
||||
#ifndef SSIZE_MAX
|
||||
#define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
|
||||
#endif
|
||||
#if !HAVE_FLOCKFILE
|
||||
#undef flockfile
|
||||
#define flockfile(x) ((void)0)
|
||||
#endif
|
||||
#if !HAVE_FUNLOCKFILE
|
||||
#undef funlockfile
|
||||
#define funlockfile(x) ((void)0)
|
||||
#endif
|
||||
|
||||
/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and
|
||||
NUL-terminate it). *LINEPTR is a pointer returned from malloc (or
|
||||
NULL), pointing to *N characters of space. It is realloc'ed as
|
||||
necessary. Returns the number of characters read (not including
|
||||
the null terminator), or -1 on error or EOF. */
|
||||
|
||||
ssize_t
|
||||
getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) {
|
||||
ssize_t result;
|
||||
size_t cur_len = 0;
|
||||
|
||||
if (lineptr == NULL || n == NULL || fp == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
flockfile (fp);
|
||||
|
||||
if (*lineptr == NULL || *n == 0) {
|
||||
*n = 120;
|
||||
*lineptr = (char *) malloc(*n);
|
||||
if (*lineptr == NULL) {
|
||||
result = -1;
|
||||
goto unlock_return;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
int i;
|
||||
|
||||
i = getc(fp);
|
||||
if (i == EOF) {
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make enough space for len+1 (for final NUL) bytes. */
|
||||
if (cur_len + 1 >= *n) {
|
||||
size_t needed_max =
|
||||
SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
|
||||
size_t needed = 2 * *n + 1; /* Be generous. */
|
||||
char *new_lineptr;
|
||||
|
||||
if (needed_max < needed)
|
||||
needed = needed_max;
|
||||
if (cur_len + 1 >= needed) {
|
||||
result = -1;
|
||||
goto unlock_return;
|
||||
}
|
||||
|
||||
new_lineptr = (char *) realloc (*lineptr, needed);
|
||||
if (new_lineptr == NULL) {
|
||||
result = -1;
|
||||
goto unlock_return;
|
||||
}
|
||||
|
||||
*lineptr = new_lineptr;
|
||||
*n = needed;
|
||||
}
|
||||
|
||||
(*lineptr)[cur_len] = i;
|
||||
cur_len++;
|
||||
|
||||
if (i == delimiter) break;
|
||||
}
|
||||
(*lineptr)[cur_len] = '\0';
|
||||
result = cur_len ? (int) cur_len : (int) result;
|
||||
|
||||
unlock_return:
|
||||
funlockfile(fp);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
14
buildroot/share/fonts/getline.h
Normal file
14
buildroot/share/fonts/getline.h
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
#ifndef MYGETLINE_H
|
||||
#define MYGETLINE_H 1
|
||||
|
||||
//#include "config.h"
|
||||
|
||||
#if !HAVE_GETLINE
|
||||
#include <stdio.h>
|
||||
ssize_t getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp);
|
||||
#define getline(lineptr, n, stream) getdelim (lineptr, n, '\n', stream)
|
||||
#endif
|
||||
|
||||
#endif // MYGETLINE_H
|
||||
|
47
buildroot/share/fonts/u8glib-bdf2u8g.patch
Normal file
47
buildroot/share/fonts/u8glib-bdf2u8g.patch
Normal file
@ -0,0 +1,47 @@
|
||||
--- tools/font/bdf2u8g/bdf2u8g.c 2017-04-08 01:04:48.000000000 -0400
|
||||
+++ tools/font/bdf2u8g/bdf2u8g.c 2018-02-24 17:24:26.368926703 -0500
|
||||
@@ -175,9 +175,9 @@
|
||||
for( i = 0; i < data_pos; i++ )
|
||||
{
|
||||
#ifdef BDF2U8G_COMPACT_OUTPUT
|
||||
- fprintf(out_fp, "%d", data_buf[i]);
|
||||
+ fprintf(out_fp, "0x%02x", data_buf[i]);
|
||||
#else
|
||||
- fprintf(out_fp, "%3d", data_buf[i]);
|
||||
+ fprintf(out_fp, "0x%02x", data_buf[i]);
|
||||
#endif
|
||||
if ( i+1 != data_pos )
|
||||
fprintf(out_fp, ",");
|
||||
@@ -484,7 +484,8 @@
|
||||
int bdf_char_max_y;
|
||||
int bdf_char_min_y;
|
||||
|
||||
-int bdf_delta_x; /* DWIDTH arg 1 */
|
||||
+int bdf_delta_x_default = -1;
|
||||
+int bdf_delta_x = -1; /* DWIDTH arg 1 */
|
||||
int bdf_delta_max_x;
|
||||
int bdf_delta_min_x;
|
||||
int bdf_delta_y; /* DWIDTH arg 2 */
|
||||
@@ -1095,6 +1096,22 @@
|
||||
bdf_char_ascent = bdf_char_height + bdf_char_y;
|
||||
//printf("h:%d w:%d ascent: %d\n", bdf_char_height, bdf_char_width, bdf_char_ascent);
|
||||
}
|
||||
+ else if ( strcmp(p_buf, "CHARS") == 0 )
|
||||
+ {
|
||||
+ if (bdf_delta_x < 0) {
|
||||
+ bdf_delta_x = 0;
|
||||
+ }
|
||||
+ if (bdf_delta_x_default < 0) {
|
||||
+ bdf_delta_x_default = bdf_delta_x;
|
||||
+ }
|
||||
+ }
|
||||
+ else if ( strcmp(p_buf, "STARTCHAR") == 0 )
|
||||
+ {
|
||||
+ if (bdf_delta_x_default < 0) {
|
||||
+ bdf_delta_x_default = 0;
|
||||
+ }
|
||||
+ bdf_delta_x = bdf_delta_x_default;
|
||||
+ }
|
||||
else if ( strcmp(p_buf, "BITMAP") == 0 )
|
||||
{
|
||||
bdf_line_state = BDF_LINE_STATE_BITMAP;
|
137
buildroot/share/fonts/uxggenpages.md
Normal file
137
buildroot/share/fonts/uxggenpages.md
Normal file
@ -0,0 +1,137 @@
|
||||
## Language engine and tools
|
||||
|
||||
### Supported hardware
|
||||
|
||||
Marlin supports HD44780 character LCD and 128x64 graphical LCD via U8GLIB.
|
||||
Because of the limitation of HD44780 hardware, Marlin can only support three
|
||||
character sets for that hardware:
|
||||
Japanese (kana_utf8), Russian/Cyrillic (ru), or Western (Roman characters)
|
||||
|
||||
For the graphical LCD modules, there's far less limitation. Users and language
|
||||
maintainers can easily change the language translation strings if they save
|
||||
with UTF-8 encoding. The only extra step is to regenerate the font data from
|
||||
an existing BDF font file.
|
||||
|
||||
|
||||
### How to support a new language?
|
||||
|
||||
1. prepare the translation source file
|
||||
|
||||
You need to add a language header file language_xx.h,
|
||||
where xx is the language/country code, for example en is for English.
|
||||
You may start with a existing language file by copying it to a new location:
|
||||
|
||||
```bash
|
||||
cp language_zh_CN.h language_zh_TW.h
|
||||
```
|
||||
|
||||
Then you can replace the strings in the macro _UxGT().
|
||||
|
||||
Make sure the file is saved as UTF-8 encoded.
|
||||
|
||||
|
||||
2. Generate the font data file
|
||||
|
||||
This step is to gather the glyph appearing in the language file from a 9pt bitmap font,
|
||||
and save the data in a language_data_xx.h file. So the font used for conversion should
|
||||
contain all the characters in your language file.
|
||||
|
||||
The default bitmap font is WQY's 9pt bitmap font. You may download from
|
||||
|
||||
http://wenq.org/daily/wqy-bitmapfont-bdf-gb18030-nightly_build.tar.gz
|
||||
|
||||
or install in Debian/Ubuntu system:
|
||||
|
||||
```
|
||||
sudo apt-get install xfonts-wqy
|
||||
```
|
||||
|
||||
You need also compile the bdf2u8g which convert the BDF font file to U8glib supported data structures.
|
||||
Before you compile bdf2u8g, it would better to patch the source file bdf2u8g.c.
|
||||
|
||||
```
|
||||
cd marlin-git/buildroot/share/fonts/
|
||||
wget https://github.com/olikraus/u8glib/archive/master.zip
|
||||
unzip master.zip
|
||||
cd u8glib-master/
|
||||
patch -p0 < ../u8glib-bdf2u8g.patch
|
||||
make -C tools/font/bdf2u8g/
|
||||
cd -
|
||||
ln -s u8glib-master/tools/font/bdf2u8g/bdf2u8g
|
||||
```
|
||||
|
||||
The 'genallfont.sh' script will generate the font data for all of the
|
||||
language translation files. You may edit the script to change the variable
|
||||
LANGS to the list of languages you want to process. For example:
|
||||
|
||||
```bash
|
||||
LANGS="zh_TW"
|
||||
```
|
||||
|
||||
and then run the script to generate the font data (`language_data_xx.h`):
|
||||
|
||||
```bash
|
||||
cd marlin-git/Marlin/
|
||||
../buildroot/share/fonts/genallfont.sh
|
||||
```
|
||||
|
||||
3. Change the language settings
|
||||
|
||||
To compile the firmware for your language, you need choose a language
|
||||
in `Configuration.h`. For Chinese (Taiwan) you would use:
|
||||
|
||||
```cpp
|
||||
#define LCD_LANGUAGE zh_TW
|
||||
```
|
||||
|
||||
4. Compile and Upload the firmware
|
||||
|
||||
Open `Marlin.ino` in your IDE and compile the firmware. If it's compiled succeeds, upload it to your Arduino hardware.
|
||||
|
||||
|
||||
### Update the language translation
|
||||
|
||||
If you change the language files, you need to run the script `genallfont.sh`
|
||||
again to update the font data file.
|
||||
|
||||
|
||||
### Use a cool font
|
||||
|
||||
You may need to use a different font to support your own language, because the
|
||||
default 9pt font is not complete. (You may also support them by adding the missing
|
||||
glyphs to the font.)
|
||||
|
||||
After you've prepared your font, specify the font file path as an argument to
|
||||
`genallfont.sh`, so that the font used for your language is your new font. For
|
||||
example, your new font file name is `newfont.bdf`, then run the following command:
|
||||
|
||||
```bash
|
||||
cd Marlin/
|
||||
../buildroot/share/fonts/genallfont.sh ./newfont.bdf
|
||||
```
|
||||
|
||||
### Suggestions for Maintainers
|
||||
|
||||
Even the tool and the language engine can be easily updated,
|
||||
since it use the common bitmap font files and UTF-8 text,
|
||||
the maintainer need to confirm that the fonts contains the glyph
|
||||
in the language files.
|
||||
|
||||
The font file currently used to generate the font data is the file ISO10646-0-3.bdf,
|
||||
which is combined with the Marlin's ISO10646-1 fonts and WQY 9pt bitmap font.
|
||||
|
||||
### Related resources
|
||||
|
||||
#### Fonts
|
||||
|
||||
- [WQY](http://wenq.org/)
|
||||
- [WQY 9pt bitmap font](http://wenq.org/daily/wqy-bitmapfont-bdf-gb18030-nightly_build.tar.gz)
|
||||
- [unifont (16x8 or 16x16)](http://unifoundry.com/unifont.html)
|
||||
|
||||
Documents related to the old version of the language engine:
|
||||
|
||||
- [Marlin Fonts Documentation](http://www.marlinfw.org/docs/development/fonts.html)
|
||||
- [Marlin LCD Language](https://github.com/MarlinFirmware/Marlin/wiki/LCD-Language)
|
||||
- [U8GLIB](https://github.com/olikraus/u8glib.git)
|
||||
- [UTF-8 for U8GLIB](https://github.com/yhfudev/u8glib-fontutf8.git)
|
||||
- [Standalone test project for the Marlin UTF-8 language engine](https://github.com/yhfudev/marlin-fontutf8.git)
|
167
buildroot/share/fonts/uxggenpages.sh
Executable file
167
buildroot/share/fonts/uxggenpages.sh
Executable file
@ -0,0 +1,167 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#####################################################################
|
||||
# genpages.sh for u8g
|
||||
#
|
||||
# This script will generate u8g c files for specified fonts
|
||||
#
|
||||
# Copyright 2015-2016 Yunhui Fu <yhfudev@gmail.com>
|
||||
# License: GPL/BSD
|
||||
#####################################################################
|
||||
my_getpath () {
|
||||
PARAM_DN="$1"
|
||||
shift
|
||||
#readlink -f
|
||||
DN="${PARAM_DN}"
|
||||
FN=
|
||||
if [ ! -d "${DN}" ]; then
|
||||
FN=$(basename "${DN}")
|
||||
DN=$(dirname "${DN}")
|
||||
fi
|
||||
cd "${DN}" > /dev/null 2>&1
|
||||
DN=$(pwd)
|
||||
cd - > /dev/null 2>&1
|
||||
echo "${DN}/${FN}"
|
||||
}
|
||||
#DN_EXEC=`echo "$0" | ${EXEC_AWK} -F/ '{b=$1; for (i=2; i < NF; i ++) {b=b "/" $(i)}; print b}'`
|
||||
DN_EXEC=$(dirname $(my_getpath "$0") )
|
||||
if [ ! "${DN_EXEC}" = "" ]; then
|
||||
DN_EXEC="$(my_getpath "${DN_EXEC}")/"
|
||||
else
|
||||
DN_EXEC="${DN_EXEC}/"
|
||||
fi
|
||||
#####################################################################
|
||||
EXEC_GENPAGES=${DN_EXEC}/genpages
|
||||
[ -x "${EXEC_GENPAGES}" ] || EXEC_GENPAGES="$(my_getpath ${DN_EXEC}/../../../genpages)"
|
||||
[ -x "${EXEC_GENPAGES}" ] || EXEC_GENPAGES=$(which genpages)
|
||||
[ -x "${EXEC_GENPAGES}" ] || { echo "Error: genpages not found!" ; exit 1; }
|
||||
|
||||
echo "EXEC_GENPAGES=${EXEC_GENPAGES}"
|
||||
|
||||
EXEC_BDF2U8G=${DN_EXEC}/bdf2u8g
|
||||
[ -x "${EXEC_BDF2U8G}" ] || EXEC_BDF2U8G="${DN_EXEC}/../../../bdf2u8g"
|
||||
[ -x "${EXEC_BDF2U8G}" ] || EXEC_BDF2U8G=$(which bdf2u8g)
|
||||
[ -x "${EXEC_BDF2U8G}" ] || { echo "Error: bdf2u8g not found!" ; echo "Please compile u8blib/tools/font/bdf2u8g/bdf2u8g and link to it from here!"; exit 1; }
|
||||
|
||||
DN_CUR=$(pwd)
|
||||
DN_DATA=$(pwd)/datatmp
|
||||
mkdir -p "${DN_DATA}"
|
||||
|
||||
#####################################################################
|
||||
FONTHOME=/usr/share/fonts
|
||||
|
||||
FN_FONT_BASE="ISO10646-0-1"
|
||||
#FN_FONT_BASE=unifont
|
||||
#FN_FONT_BASE=wenquanyi_12pt
|
||||
#FN_FONT_BASE=wenquanyi_9pt
|
||||
|
||||
FN_FONT="${1:-}"
|
||||
[ -z "${FN_FONT}" ] && FN_FONT=${DN_DATA}/../${FN_FONT_BASE}.bdf
|
||||
[ -f "${FN_FONT}" ] || FN_FONT=${DN_EXEC}/${FN_FONT_BASE}.bdf
|
||||
[ -f "${FN_FONT}" ] || FN_FONT="$FONTHOME/wenquanyi/${FN_FONT_BASE}.bdf"
|
||||
[ -f "${FN_FONT}" ] || FN_FONT="$FONTHOME/X11/misc/${FN_FONT_BASE}.bdf"
|
||||
echo "FN_FONT=${FN_FONT}"
|
||||
[ -f "${FN_FONT}" ] || FN_FONT="$FONTHOME/misc/${FN_FONT_BASE}.bdf"
|
||||
echo "FN_FONT2=${FN_FONT}"
|
||||
if [ ! -f "${FN_FONT}" ]; then
|
||||
FN_FONT_PCF="$FONTHOME/X11/misc/${FN_FONT_BASE}.pcf"
|
||||
[ -f "${FN_FONT_PCF}" ] || FN_FONT_PCF="$FONTHOME/misc/${FN_FONT_BASE}.pcf"
|
||||
[ -f "${FN_FONT_PCF}" ] || FN_FONT_PCF="$FONTHOME/wenquanyi/${FN_FONT_BASE}.pcf"
|
||||
if [ -f "${FN_FONT_PCF}" ]; then
|
||||
EXEC_PCF2BDF=$(which pcf2bdf)
|
||||
if [ ! -x "${EXEC_PCF2BDF}" ]; then
|
||||
echo "Error: not found pcf2bdf!"
|
||||
echo " Please install pcf2bdf."
|
||||
exit 1
|
||||
fi
|
||||
FN_FONT="./${FN_FONT_BASE}.bdf"
|
||||
echo ${EXEC_PCF2BDF} -o "${FN_FONT}" "${FN_FONT_PCF}"
|
||||
${EXEC_PCF2BDF} -o "${FN_FONT}" "${FN_FONT_PCF}"
|
||||
fi
|
||||
fi
|
||||
|
||||
[ -f "${FN_FONT}" ] || { echo "Error: can't find font ${FN_FONT}!" ; exit 1; }
|
||||
|
||||
#####################################################################
|
||||
|
||||
#(cd ${DN_EXEC}; gcc -o genpages genpages.c getline.c)
|
||||
|
||||
rm -f tmpa tmpb
|
||||
#rm -f ${DN_EXEC}/fontpage_*.h
|
||||
rm -f fontpage_*.h
|
||||
|
||||
cat << EOF > tmp-proc-page.awk
|
||||
BEGIN {
|
||||
cur_page=0;
|
||||
val_begin=0;
|
||||
val_pre=0;
|
||||
utf8_pre="";
|
||||
utf8_begin="";
|
||||
}{
|
||||
page=\$1;
|
||||
val_real=\$2;
|
||||
utf8=\$3;
|
||||
# assert (val_real < 128);
|
||||
val=val_real + 128;
|
||||
if (cur_page != page) {
|
||||
if (cur_page != 0) {
|
||||
if (val_begin != 0) {
|
||||
print cur_page " " val_begin " " val_pre " " utf8_begin " " utf8_pre;
|
||||
}
|
||||
}
|
||||
cur_page=page;
|
||||
val_begin=val;
|
||||
val_pre=val;
|
||||
utf8_begin=utf8;
|
||||
utf8_pre=utf8;
|
||||
} else {
|
||||
if (val_pre + 1 != val) {
|
||||
if (cur_page != 0) {
|
||||
print cur_page " " val_begin " " val_pre " " utf8_begin " " utf8_pre;
|
||||
}
|
||||
val_begin=val;
|
||||
val_pre=val;
|
||||
utf8_begin=utf8;
|
||||
utf8_pre=utf8;
|
||||
} else {
|
||||
val_pre = val;
|
||||
utf8_pre=utf8;
|
||||
}
|
||||
}
|
||||
} END {
|
||||
if (cur_page != 0) {
|
||||
print cur_page " " val_begin " " val_pre " " utf8_begin " " utf8_pre;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
grep -Hrn _UxGT . | grep '"' | \
|
||||
sed 's/_UxGT("/\n&/g;s/[^\n]*\n_UxGT("\([^"]*\)[^\n]*/\1 /g;s/.$//' | \
|
||||
${EXEC_GENPAGES} | \
|
||||
sort -k 1n -k 2n | uniq | \
|
||||
gawk -v EXEC_PREFIX=${DN_EXEC} -f tmp-proc-page.awk | \
|
||||
while read PAGE BEGIN END UTF8BEGIN UTF8END; do \
|
||||
if [ ! -f ${DN_DATA}/fontpage_${PAGE}_${BEGIN}_${END}.h ]; then \
|
||||
${EXEC_BDF2U8G} -u ${PAGE} -b ${BEGIN} -e ${END} ${FN_FONT} fontpage_${PAGE}_${BEGIN}_${END} ${DN_DATA}/fontpage_${PAGE}_${BEGIN}_${END}.h > /dev/null 2>&1 ;
|
||||
#sed -i 's|#include "u8g.h"|#include "utility/u8g.h"|' ${DN_DATA}/fontpage_${PAGE}_${BEGIN}_${END}.h ;
|
||||
fi ;\
|
||||
grep -A 10000000000 u8g_fntpgm_uint8_t ${DN_DATA}/fontpage_${PAGE}_${BEGIN}_${END}.h >> tmpa ;\
|
||||
echo " FONTDATA_ITEM(${PAGE}, ${BEGIN}, ${END}, fontpage_${PAGE}_${BEGIN}_${END}), // '${UTF8BEGIN}' -- '${UTF8END}'" >> tmpb ;\
|
||||
done
|
||||
|
||||
rm -f fontutf8-data.h
|
||||
echo "/* Generated by $0 */" >> fontutf8-data.h
|
||||
echo "/* This file is generated automatically, any changes to the file may be REPLACED by future processing. */" >> fontutf8-data.h
|
||||
echo "/* Please turn to the tools call this script to change the contents! */" >> fontutf8-data.h
|
||||
echo "" >> fontutf8-data.h
|
||||
echo "#include <u8g.h>" >> fontutf8-data.h
|
||||
#echo "#include \"fontutf8u8g.h\"" >> fontutf8-data.h
|
||||
echo "" >> fontutf8-data.h
|
||||
cat tmpa >> fontutf8-data.h
|
||||
echo "" >> fontutf8-data.h
|
||||
echo "#define FONTDATA_ITEM(page, begin, end, data) {page, begin, end, NUM_ARRAY(data), data}" >> fontutf8-data.h
|
||||
echo "static const uxg_fontinfo_t g_fontinfo[] PROGMEM = {" >> fontutf8-data.h
|
||||
cat tmpb >> fontutf8-data.h
|
||||
echo "};" >> fontutf8-data.h
|
||||
|
||||
rm -f tmpa tmpb tmp-proc-page.awk
|
Reference in New Issue
Block a user