Add all files for building the charset table and the tutorial (alpha)
This commit is contained in:
parent
23e74f7c00
commit
66fb17b753
|
@ -0,0 +1,3 @@
|
|||
casio_charset/
|
||||
casio_charset_table.md
|
||||
*.html
|
|
@ -0,0 +1,26 @@
|
|||
MDS=casio_charset_table.md casio_encoding_tutorial.md
|
||||
HTMLS=$(MDS:.md=.html)
|
||||
|
||||
CSS=github-pandoc.css custom.css
|
||||
|
||||
|
||||
all: $(MDS) $(HTMLS)
|
||||
|
||||
%.html: %.md $(CSS)
|
||||
pandoc $< $(patsubst %,-c %, $(CSS)) -H reload_img_onerror.html -o $@
|
||||
|
||||
casio_charset_table.md: reload_img_onerror.html $(CSS)
|
||||
cd util; python3 generate_charset_imgs.py
|
||||
cd util; python3 generate_charset_table.py >../casio_charset_table.md
|
||||
|
||||
|
||||
%.css:
|
||||
|
||||
clean:
|
||||
rm -fv $(HTMLS)
|
||||
rm -fv casio_charset_table.md
|
||||
rm -frv casio_charset/
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
# Casio Encoding
|
||||
|
||||
One of the most important aspects about creating Add-ins is wo write text on the display. The Casio SDK provides us with a very unflexible way of doing that:
|
||||
|
||||
```c
|
||||
Print("Hello World");
|
||||
```
|
||||
|
||||
As you might already know, the standard C library has a much more elegant solution which is much more flexible:
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
printf("Hello World");
|
||||
```
|
||||
|
||||
No matter which way we want to use to print letters, numbers or special symbols, we need to understand how all these characters are represented internally.
|
||||
|
||||
## Basics
|
||||
|
||||
### Strings
|
||||
|
||||
A *string* is an group of *characters*, e.g. "Hello World" contains the characters 'H', 'a', 'l', etc. As you might have notices, strings are enclosed by "..." while we use '...' for characters.
|
||||
|
||||
More technically speaking, a string is an array of multiple `char`s.
|
||||
|
||||
```c
|
||||
char message[] = "Hello World";
|
||||
printf(message);
|
||||
```
|
||||
|
||||
### Characters
|
||||
|
||||
Actually the type `char` is a number which indicates, which letter/symbol is meant. E.g. 98 means 'a', 99 means 'b', 100 means 'c' etc.
|
||||
|
||||
There is a whole table of 127 number/character pairs which is called the ASCII table.
|
||||
|
||||
## ASCII
|
||||
|
||||
The way of mapping numbers to characters is called *encoding*. The most basic encoding is called ASCII. Note that the C compiler and the underlying operating system do not have to comply with ASCII, but generally they do (except CASIO of course). I'll come to that in a second.
|
||||
|
||||
Here you see a part of the ASCII table. In the Internet, you also find the [whole ASCII table](https://www.rapidtables.com/code/text/ascii-table.html).
|
||||
|
||||
| Number | Character |
|
||||
| ------ | --------- |
|
||||
| ...|...|
|
||||
| 88 | X |
|
||||
| 89 | Y |
|
||||
| 90 | Z |
|
||||
| 91 | [ |
|
||||
| 92 | \ |
|
||||
| 93 | ] |
|
||||
| 94 | ^ |
|
||||
| 95 | _ |
|
||||
| 96 | ` |
|
||||
| 97 | a |
|
||||
| 98 | b |
|
||||
| 99 | c |
|
||||
| ...|...|
|
||||
|
||||
To print an ASCII character using its number, you must convert this number into hexadecimal first. For example, `'o'` = `111` = `0x6F` = `'\x6F'`:
|
||||
|
||||
```c
|
||||
|
||||
printf("Hell\x6F World");
|
||||
```
|
||||
|
||||
In fact, 'o', 111, 0x6F and '\x6F' are *really* the same for the C compiler. As a consequence, `'o' == 111` will always be true (as long as the C compiler complies to ASCII).
|
||||
|
||||
|
||||
Note that ASCII only covers the characters for 0-127 and is de-facto standard for all platforms. The characters 128-255 are sometimes referred to as *extended ASCII*. However, extended ASCII is non-standard and should be avoided if possible.
|
||||
|
||||
## Unicode
|
||||
|
||||
Of course there are much more symbols than 256 if we think about the chinese alphabet, greek letters etc. To be able to use them in C, we need another encoding which is called *Unicode*. While each character in ACSII requires one byte of memory, Unicode needs more.
|
||||
|
||||
Since the data type `char` is not sufficient for Unicode anymore, `char16_t`, `char32_t` or `wchar_t` are used. I do not want to go too much into detail here, because Casio does **not** support Unicode anyway. If you are interested, however, in the Internet you will find many good [examples](http://doc.bccnsoft.com/docs/cppreference2015/en/c/language/string_literal.html).
|
||||
|
||||
## Casio encoding
|
||||
|
||||
The Casio encoding is partly ASCII-compliant and not Unicode-compliant at all. All printable characters (32-126) of ASCII have the same value in the Casio encoding and can be used without care:
|
||||
|
||||
```
|
||||
!"#$%&'()*+,-./
|
||||
0123456789
|
||||
:;<=>?@
|
||||
ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
[\]^_`
|
||||
abcdefghijklmnopqrstuvwxyz
|
||||
{|}~
|
||||
```
|
||||
|
||||
However, Casio decided to replace the non-printable characters with their own symbols. E.g. what is in ASCII the formfeed character `'\f'` = `12` = `0x0C` = `'\x0C'` was replaced by the character `'◢'`. That means that `Print("\x0C")` will now print `◢`.
|
||||
|
||||
Casio also added characters to the extended ASCII section 128-255. Details to all characters can be looked up in the [Casio charset table](casio_charset_table.md).
|
||||
|
||||
### Multi-byte Characters
|
||||
|
||||
Additionally, certain combinations of values print special characters, e.g. `Print("\xE5\x51")` will print the greek capital *sigma* (also known as sum sign) `'Σ'`. The two bytes `\E5` and `\x51` will be evaluated as *one character* here. In the [Casio charset table](casio_charset_table.md), this character can be found as `0xE551`.
|
||||
|
||||
Note that the first byte of two-byte characters can be either `0x7F`, `0xF7`, `0xF9`, `0xE5`, `0xE6` or `0xE7`. The second byte can be anything from `0x00` to `0xFF`.
|
||||
|
||||
### Casio charset table
|
||||
|
||||
Please have a look at the [Casio charset table](casio_charset_table.md) for details to all characters Casio is capable to handle. Some of them are not printable. We do not need to care about them.
|
|
@ -0,0 +1,38 @@
|
|||
/* all images showing the Casio font */
|
||||
.pixelated {
|
||||
/* do not blur the pixels into each other when scaling up */
|
||||
image-rendering: -moz-crisp-edges; /* Firefox */
|
||||
image-rendering: -o-crisp-edges; /* Opera */
|
||||
image-rendering: -webkit-optimize-contrast;/* Webkit (non-standard naming) */
|
||||
image-rendering: crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
-ms-interpolation-mode: nearest-neighbor; /* IE (non-standard property) */
|
||||
|
||||
/* speed of the hover effect */
|
||||
transition: -webkit-transform 0.25s ease;
|
||||
}
|
||||
|
||||
.pixelated:hover {
|
||||
/* hover effect: zoom in */
|
||||
-webkit-transform: scale(7);
|
||||
}
|
||||
|
||||
/* the images showing the normal font */
|
||||
.normal_font {
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
/* the images showing the mini font */
|
||||
.mini_font {
|
||||
height: 0.71em;
|
||||
}
|
||||
|
||||
|
||||
/* increase the width of the whole body */
|
||||
html {
|
||||
max-width: 70em !important;
|
||||
}
|
||||
|
||||
body {
|
||||
max-width: 70em !important;
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,57 @@
|
|||
import os, errno
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def generate_imgs(inpath, outpath, prefixes, w, h):
|
||||
try:
|
||||
os.makedirs(os.getcwd() + "/../" + outpath)
|
||||
except OSError as e:
|
||||
if e.errno != errno.EEXIST:
|
||||
raise
|
||||
|
||||
img_filename = "XX.pbm";
|
||||
|
||||
for pre in prefixes:
|
||||
img = Image.open(os.getcwd() + "/../" + inpath + "/" + pre + img_filename)
|
||||
|
||||
# add alpha channel
|
||||
img = img.convert("RGBA")
|
||||
|
||||
# for every char (w x h pixels)
|
||||
for col in range(0, 16):
|
||||
for row in range(0, 16):
|
||||
bounds = (col*w, row*h, (col+1)*w, (row+1)*h)
|
||||
sec = img.crop(bounds)
|
||||
|
||||
# turn all white pixels transparent
|
||||
isallalpha = True
|
||||
pixdata = sec.load()
|
||||
for y in range(h):
|
||||
for x in range(w):
|
||||
if pixdata[x, y] == (255, 255, 255, 255):
|
||||
pixdata[x, y] = (255, 255, 255, 0)
|
||||
else:
|
||||
isallalpha = False
|
||||
|
||||
# skip all alpha chars (non-printable)
|
||||
if isallalpha:
|
||||
continue
|
||||
|
||||
filename = pre + "%X%X.png" % (row, col)
|
||||
|
||||
if sec.getbbox() is not None:
|
||||
print(os.getcwd() + "/../" + outpath + filename)
|
||||
sec.save(os.getcwd() + "/../" + outpath + filename)
|
||||
|
||||
|
||||
# mini
|
||||
inpath = "fontcharacter/reference/mini/"
|
||||
outpath = "casio_charset/mini/"
|
||||
prefixes = ("0x", "0x7F", "0xE5", "0xE6")
|
||||
generate_imgs(inpath, outpath, prefixes, 5, 5)
|
||||
|
||||
# normal
|
||||
inpath = "fontcharacter/reference/normal/"
|
||||
outpath = "casio_charset/normal/"
|
||||
prefixes = ("0x", "0x7F", "0xE5", "0xE6", "0xE7")
|
||||
generate_imgs(inpath, outpath, prefixes, 5, 7)
|
|
@ -0,0 +1,72 @@
|
|||
import os
|
||||
import yaml
|
||||
import cgi
|
||||
from pathlib import Path
|
||||
|
||||
stream = open(os.getcwd() + "/../fontcharacter/reference/characters.yml", "r")
|
||||
docs = yaml.load_all(stream)
|
||||
|
||||
print("# Casio Charset\n")
|
||||
print("|Casio value|Casio font (normal) |Casio font (mini) |Unicode character|Meaning <span style=\"visibility: hidden;\">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</span>|ASCII value|Unicode value|");
|
||||
print("|-----------|:----------------------------------------------------------------------:|:----------------------------------------------------------------------:|:---------------:|----------------------------------------------------|-----------|-------------|")
|
||||
|
||||
for doc in docs:
|
||||
for charspec in doc:
|
||||
#print(charspec)
|
||||
code = charspec.get("code")
|
||||
name = charspec.get("name")
|
||||
category = charspec.get("category")
|
||||
unicode = charspec.get("unicode")
|
||||
multi = charspec.get("multi")
|
||||
tokens = charspec.get("tokens")
|
||||
id_ = charspec.get("id")
|
||||
|
||||
args = charspec.get("args")
|
||||
action = charspec.get("action")
|
||||
return_ = charspec.get("return")
|
||||
flags = charspec.get("flags")
|
||||
ascii_ = charspec.get("ascii")
|
||||
|
||||
tab_code = ("0x%02X" % code)
|
||||
|
||||
if Path(os.getcwd() + "/../casio_charset/normal/0x%02X.png" % code).exists():
|
||||
tab_pic_normal = "![ ](casio_charset/normal/0x%02X.png){class=\"normal_font pixelated\" onerror=\"reload_img(this);\"}" % code
|
||||
else:
|
||||
tab_pic_normal = ""
|
||||
|
||||
if Path(os.getcwd() + "/../casio_charset/mini/0x%02X.png" % code).exists():
|
||||
tab_pic_mini = "![ ](casio_charset/mini/0x%02X.png){class=\"mini_font pixelated\" onerror=\"reload_img(this);\"}" % code
|
||||
else:
|
||||
tab_pic_mini = ""
|
||||
|
||||
tab_char = ""
|
||||
if code == 0x0D:
|
||||
tab_char = "" # '\n'
|
||||
elif code == 0x20:
|
||||
tab_char = " " # ' '
|
||||
elif code == 0x7c:
|
||||
tab_char = "|" # '|'
|
||||
elif unicode is not None:
|
||||
for u in unicode:
|
||||
tab_char = tab_char + chr(u).encode("ascii", "xmlcharrefreplace").decode('utf-8')
|
||||
|
||||
tab_meaning = name
|
||||
if args is not None:
|
||||
tab_meaning = tab_meaning + "<br/>args: " + ",".join(args)
|
||||
if return_ is not None:
|
||||
tab_meaning = tab_meaning + "<br/>return: " + return_
|
||||
|
||||
tab_ascii = []
|
||||
tab_unicode = []
|
||||
|
||||
if unicode is not None:
|
||||
for u in unicode:
|
||||
if u <= 0xFF:
|
||||
tab_ascii.append("0x%02X" % u)
|
||||
else:
|
||||
tab_unicode.append("0x%02X" % u)
|
||||
tab_ascii = ",".join(tab_ascii)
|
||||
tab_unicode = ",".join(tab_unicode)
|
||||
|
||||
print("| %9s | %70s | %70s | %15s | %50s | %9s | %11s |" % (tab_code, tab_pic_normal, tab_pic_mini, tab_char, tab_meaning, tab_ascii, tab_unicode))
|
||||
|
Loading…
Reference in New Issue