[2.0.x] UTF-8 language translation support (#10213)
This commit is contained in:
committed by
Scott Lahteine
parent
daa712455b
commit
c96412a78f
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Executable
+75
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
@@ -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)
|
||||
Executable
+167
@@ -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