mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2025-12-18 15:17:42 +03:00
Compare commits
8 Commits
3a2999cdbd
...
f6f00a5e26
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6f00a5e26 | ||
|
|
c813a2f075 | ||
|
|
424594488f | ||
|
|
57fdb1c0fb | ||
|
|
5e1694748c | ||
|
|
074bab82ff | ||
|
|
13a6c43b87 | ||
|
|
26b84b38a2 |
@ -1,505 +0,0 @@
|
||||
/**
|
||||
* generated by fontconvert.py
|
||||
* name: babyblue
|
||||
* size: 8
|
||||
* mode: 1-bit
|
||||
*/
|
||||
#pragma once
|
||||
#include "EpdFontData.h"
|
||||
|
||||
static const uint8_t babyblueBitmaps[3140] = {
|
||||
0xFF, 0xFF, 0x30, 0xFF, 0xFF, 0xF0, 0x36, 0x1B, 0x0D, 0x9F, 0xFF, 0xF9, 0xB3, 0xFF, 0xFF, 0x36, 0x1B, 0x0D, 0x80,
|
||||
0x18, 0x18, 0x7E, 0xFF, 0xDB, 0xD8, 0xFE, 0x7F, 0x9B, 0xDB, 0xFF, 0x7E, 0x18, 0x00, 0x71, 0x9F, 0x73, 0x6C, 0x6F,
|
||||
0x8F, 0xE0, 0xFF, 0x83, 0xF8, 0xFB, 0x1B, 0x63, 0x7C, 0xC7, 0x00, 0x38, 0x3E, 0x1B, 0x0D, 0x87, 0xC3, 0xEF, 0xBF,
|
||||
0x8E, 0xCF, 0x7F, 0x1E, 0xC0, 0xFF, 0x37, 0xEC, 0xCC, 0xCC, 0xCC, 0xCC, 0x67, 0x20, 0xCE, 0x73, 0x33, 0x33, 0x33,
|
||||
0x33, 0x6C, 0x80, 0x32, 0xFF, 0xDE, 0xFE, 0x30, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0x18, 0x18, 0x18, 0xBF, 0x00, 0xFF,
|
||||
0xC0, 0x30, 0x0C, 0x31, 0xC6, 0x18, 0xE3, 0x1C, 0x63, 0x8C, 0x00, 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
|
||||
0xC7, 0x7E, 0x3C, 0x19, 0xDF, 0xFD, 0x8C, 0x63, 0x18, 0xC6, 0x3C, 0x7E, 0xE7, 0x83, 0x07, 0x0E, 0x1C, 0x38, 0x70,
|
||||
0xFE, 0xFF, 0x7E, 0xFF, 0xC3, 0x07, 0x3E, 0x3E, 0x07, 0x03, 0x83, 0xFF, 0x7E, 0x0E, 0x1E, 0x3E, 0x76, 0xE6, 0xFF,
|
||||
0xFF, 0x06, 0x06, 0x06, 0x06, 0x7F, 0xFF, 0x06, 0x0F, 0xDF, 0xC1, 0x83, 0x87, 0xFD, 0xF0, 0x3E, 0x7F, 0xE3, 0xC0,
|
||||
0xFC, 0xFE, 0xE7, 0xC3, 0xC7, 0x7E, 0x3C, 0xFF, 0xFF, 0xC0, 0xE0, 0xE0, 0x60, 0x70, 0x30, 0x18, 0x1C, 0x0C, 0x06,
|
||||
0x00, 0x3C, 0x7E, 0x66, 0x66, 0x7E, 0x7E, 0xE7, 0xC3, 0xC7, 0x7E, 0x3C, 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC7, 0x7F,
|
||||
0x3F, 0x07, 0x3E, 0x7C, 0xB0, 0x03, 0xB0, 0x03, 0xF8, 0x06, 0x3D, 0xF7, 0x8F, 0x0F, 0x87, 0x03, 0xFF, 0xFF, 0x00,
|
||||
0xFF, 0xFF, 0x81, 0xE1, 0xF0, 0xF1, 0xEF, 0xBC, 0x40, 0x38, 0xFB, 0xBE, 0x30, 0xE3, 0x8E, 0x18, 0x30, 0x00, 0xC0,
|
||||
0x0F, 0xE0, 0x7F, 0xC3, 0x83, 0x9D, 0xE7, 0xEF, 0xCF, 0x73, 0x3D, 0x8C, 0xF6, 0x33, 0xD8, 0xDB, 0x3F, 0xC6, 0x7E,
|
||||
0x0C, 0x03, 0x18, 0x18, 0x7F, 0xE0, 0xFF, 0x00, 0x38, 0xFB, 0xBE, 0x3C, 0x7F, 0xFF, 0xE3, 0xC7, 0x8C, 0xFC, 0xFE,
|
||||
0xC7, 0xC7, 0xFE, 0xFE, 0xC7, 0xC7, 0xFE, 0xFC, 0x3F, 0x3F, 0xF8, 0x78, 0x0C, 0x06, 0x03, 0x01, 0x83, 0x7F, 0x9F,
|
||||
0x80, 0xFC, 0xFE, 0xC7, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0xFE, 0xFC, 0xFF, 0xFF, 0x06, 0x0F, 0xDF, 0xB0, 0x60, 0xFD,
|
||||
0xFC, 0xFF, 0xFF, 0x06, 0x0F, 0xDF, 0xB0, 0x60, 0xC1, 0x80, 0x3F, 0x3F, 0xF8, 0x78, 0x0C, 0x7E, 0x3F, 0x07, 0x83,
|
||||
0x7F, 0x9F, 0x80, 0xC3, 0xC3, 0xC3, 0xC3, 0xFF, 0xFF, 0xC3, 0xC3, 0xC3, 0xC3, 0xFF, 0xFF, 0xF0, 0x0C, 0x30, 0xC3,
|
||||
0x0C, 0x38, 0xF3, 0xFD, 0xE0, 0xC3, 0xC7, 0xCE, 0xDC, 0xF8, 0xF8, 0xDC, 0xCC, 0xC6, 0xC3, 0xC1, 0x83, 0x06, 0x0C,
|
||||
0x18, 0x30, 0x60, 0xFD, 0xFC, 0xE1, 0xF8, 0x7F, 0x3F, 0xCF, 0xFF, 0xF7, 0xBD, 0xEF, 0x7B, 0xCC, 0xF3, 0x30, 0xC3,
|
||||
0xE3, 0xF3, 0xF3, 0xFB, 0xDF, 0xCF, 0xCF, 0xC7, 0xC3, 0x3E, 0x3F, 0xB8, 0xF8, 0x3C, 0x1E, 0x0F, 0x07, 0x87, 0x7F,
|
||||
0x1F, 0x00, 0xFE, 0xFF, 0xC3, 0xC3, 0xFF, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0x3E, 0x3F, 0xB8, 0xF8, 0x3C, 0x1E, 0x0F,
|
||||
0x37, 0x9F, 0x7F, 0x1F, 0xC0, 0xFE, 0xFF, 0xC3, 0xC7, 0xFE, 0xFE, 0xC7, 0xC3, 0xC3, 0xC3, 0x7D, 0xFF, 0x1F, 0x87,
|
||||
0xC3, 0xC1, 0xC3, 0xFE, 0xF8, 0xFF, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xC3, 0xC3, 0xC3, 0xC3,
|
||||
0xC3, 0xC3, 0xC3, 0xC7, 0x7E, 0x3C, 0xC3, 0xC3, 0xC3, 0xE7, 0x66, 0x7E, 0x3C, 0x3C, 0x3C, 0x18, 0x83, 0x0F, 0x0C,
|
||||
0x3C, 0x30, 0xF1, 0xE7, 0x67, 0x99, 0xBF, 0xE3, 0xCF, 0x0F, 0x3C, 0x3C, 0xF0, 0x61, 0x80, 0x80, 0xF8, 0x77, 0x38,
|
||||
0xFC, 0x1E, 0x07, 0x83, 0xF1, 0xCE, 0xE1, 0xB0, 0x30, 0xC3, 0xC3, 0xE7, 0x7E, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0xFF, 0xFF, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xFE, 0xFF, 0xFF, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFE, 0x81, 0xC1,
|
||||
0x83, 0x83, 0x83, 0x06, 0x06, 0x0C, 0x0C, 0xFF, 0x33, 0x33, 0x33, 0x33, 0x33, 0xFE, 0x18, 0x3C, 0x7E, 0x66, 0xE7,
|
||||
0xC3, 0x83, 0xFF, 0xFF, 0x9D, 0x80, 0x7D, 0xFE, 0x1B, 0xFF, 0xF8, 0xFF, 0xBF, 0xC1, 0x83, 0xE7, 0xEC, 0xF8, 0xF1,
|
||||
0xE7, 0xFD, 0xF0, 0x3C, 0xFF, 0x9E, 0x0C, 0x18, 0x9F, 0x9E, 0x06, 0x0C, 0xFB, 0xFE, 0x78, 0xF1, 0xE3, 0x7E, 0x7C,
|
||||
0x3C, 0x7E, 0xE7, 0xFF, 0xFF, 0xC0, 0x7E, 0x3F, 0x3B, 0xD9, 0xFF, 0xB1, 0x8C, 0x63, 0x18, 0x3E, 0xFF, 0x9E, 0x3C,
|
||||
0x78, 0xDF, 0x9F, 0x06, 0x0D, 0xF3, 0xC0, 0xC3, 0x0F, 0xBF, 0xEF, 0x3C, 0xF3, 0xCF, 0x30, 0xFB, 0xFF, 0xF0, 0x6D,
|
||||
0x36, 0xDB, 0x6D, 0xBD, 0x00, 0xC3, 0x0C, 0xF7, 0xFB, 0xCE, 0x3C, 0xDB, 0x30, 0xFF, 0xFF, 0xF0, 0x7F, 0xBF, 0xFC,
|
||||
0xCF, 0x33, 0xCC, 0xF3, 0x3C, 0xCF, 0x33, 0x7B, 0xFC, 0xF3, 0xCF, 0x3C, 0xF3, 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC7,
|
||||
0x7E, 0x3C, 0x79, 0xFB, 0x3E, 0x3C, 0x79, 0xFF, 0x7C, 0xC1, 0x82, 0x00, 0x3C, 0xFF, 0x9E, 0x3C, 0x78, 0xDF, 0x9F,
|
||||
0x06, 0x0C, 0x10, 0x77, 0xF7, 0x8C, 0x63, 0x18, 0x7D, 0xFF, 0x1F, 0xE7, 0xF0, 0xFF, 0xBE, 0x63, 0x3D, 0xE6, 0x31,
|
||||
0x8C, 0x71, 0xC0, 0x8F, 0x3C, 0xF3, 0xCF, 0x3F, 0xDE, 0x83, 0xC3, 0xC7, 0x66, 0x66, 0x6E, 0x3C, 0x18, 0x80, 0xF3,
|
||||
0x3D, 0xFD, 0xFE, 0x7F, 0x9F, 0xE3, 0x30, 0xCC, 0x83, 0xC7, 0x6E, 0x3C, 0x38, 0x7C, 0xE6, 0xC3, 0x83, 0xC7, 0x66,
|
||||
0x6E, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x70, 0x60, 0xFF, 0xFC, 0x71, 0xC7, 0x1C, 0x3F, 0x7F, 0x19, 0xCC, 0x63, 0x3B,
|
||||
0x98, 0x61, 0x8C, 0x63, 0x1C, 0x40, 0xFF, 0xFF, 0xFF, 0xF8, 0x83, 0x87, 0x0C, 0x30, 0xE1, 0xC7, 0x38, 0xC3, 0x0C,
|
||||
0x63, 0x08, 0x00, 0x79, 0xFF, 0xE3, 0xC0, 0xF2, 0xFF, 0xFE, 0x18, 0x30, 0xF3, 0xFF, 0xFB, 0x36, 0x6E, 0x7E, 0x78,
|
||||
0x60, 0xC1, 0x00, 0x3C, 0x7E, 0x66, 0x60, 0xFC, 0xFC, 0x30, 0x72, 0xFF, 0xFE, 0x83, 0xFF, 0x7E, 0x66, 0x66, 0x7E,
|
||||
0xFE, 0x83, 0x83, 0xE7, 0x7E, 0x3C, 0xFF, 0xFF, 0xFF, 0xFF, 0x18, 0x18, 0xFF, 0xFC, 0xBF, 0xF8, 0x3C, 0x7E, 0x66,
|
||||
0x7E, 0x7C, 0xEE, 0xC7, 0xC3, 0x77, 0x3E, 0x0C, 0x66, 0x66, 0x7C, 0x38, 0x9E, 0xE6, 0x3F, 0x1F, 0xEF, 0xFF, 0xFF,
|
||||
0xF3, 0xFC, 0x3F, 0x3F, 0xFF, 0xDF, 0xDF, 0xE3, 0xF0, 0x77, 0xFF, 0xFF, 0xBC, 0x36, 0xFF, 0xF6, 0xCD, 0xCD, 0x8D,
|
||||
0x80, 0xFF, 0xFF, 0x03, 0x03, 0x03, 0x3F, 0x1F, 0xEF, 0xFF, 0xFB, 0xF6, 0xFF, 0xBF, 0xEF, 0xDB, 0xF7, 0xDF, 0xE3,
|
||||
0xF0, 0xFF, 0xFF, 0x6F, 0xFF, 0x60, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0x18, 0x18, 0xFE, 0xFF, 0x77, 0xE6, 0x77, 0x73,
|
||||
0xFF, 0x77, 0xEF, 0x7F, 0xB8, 0x7F, 0x00, 0xCF, 0x3C, 0xF3, 0xCF, 0x3F, 0xFE, 0xC3, 0x0C, 0x20, 0x7F, 0xFF, 0xFE,
|
||||
0xFE, 0xFE, 0x7E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x16, 0xB0, 0x63, 0xEC, 0x37, 0xFB, 0x33, 0x30, 0x7B,
|
||||
0xFC, 0xF3, 0xFD, 0xE0, 0x99, 0xF9, 0xF9, 0xB7, 0xFF, 0xB6, 0x00, 0x30, 0x07, 0x03, 0xF0, 0x7B, 0x0E, 0x31, 0xC3,
|
||||
0x38, 0x37, 0x60, 0xEE, 0x1D, 0xE3, 0xBF, 0x33, 0xF6, 0x06, 0x30, 0x67, 0x0E, 0xF1, 0xCB, 0x38, 0x37, 0x03, 0xEF,
|
||||
0x1D, 0xF3, 0x9F, 0x70, 0xEE, 0x0E, 0xC1, 0xF0, 0x70, 0x6F, 0x8E, 0xB9, 0xCB, 0xB8, 0xFF, 0x07, 0xE6, 0x1C, 0xE3,
|
||||
0x9E, 0x73, 0xFE, 0x3F, 0xC0, 0x60, 0x30, 0x60, 0xC1, 0x87, 0x1C, 0x30, 0x60, 0xC6, 0xD9, 0xE1, 0x80, 0x30, 0x70,
|
||||
0x61, 0xC7, 0xDD, 0xF1, 0xE3, 0xFF, 0xFF, 0x1E, 0x3C, 0x60, 0x18, 0x70, 0xC1, 0xC7, 0xDD, 0xF1, 0xE3, 0xFF, 0xFF,
|
||||
0x1E, 0x3C, 0x60, 0x38, 0xF9, 0xB1, 0xC7, 0xDD, 0xF1, 0xE3, 0xFF, 0xFF, 0x1E, 0x3C, 0x60, 0x3C, 0xF9, 0xE1, 0xC7,
|
||||
0xDD, 0xF1, 0xE3, 0xFF, 0xFF, 0x1E, 0x3C, 0x60, 0x6C, 0xD8, 0xE3, 0xEE, 0xF8, 0xF1, 0xFF, 0xFF, 0x8F, 0x1E, 0x30,
|
||||
0x38, 0xF9, 0xF1, 0xC7, 0xDD, 0xF1, 0xE3, 0xFF, 0xFF, 0x1E, 0x3C, 0x60, 0x0F, 0xF8, 0x7F, 0xC7, 0xC0, 0x36, 0x03,
|
||||
0xB0, 0x19, 0xF9, 0xFF, 0xCF, 0xE0, 0xE3, 0x06, 0x1F, 0xB0, 0xFE, 0x3F, 0x3F, 0xF8, 0x78, 0x0C, 0x06, 0x03, 0x01,
|
||||
0x83, 0x7F, 0x9F, 0x86, 0x01, 0x83, 0x81, 0x80, 0x30, 0x70, 0x67, 0xFF, 0xF8, 0x30, 0x7E, 0xFD, 0x83, 0x07, 0xEF,
|
||||
0xE0, 0x0C, 0x38, 0x67, 0xFF, 0xF8, 0x30, 0x7E, 0xFD, 0x83, 0x07, 0xEF, 0xE0, 0x18, 0x78, 0xF7, 0xFF, 0xF8, 0x30,
|
||||
0x7E, 0xFD, 0x83, 0x07, 0xEF, 0xE0, 0x3C, 0x7B, 0xFF, 0xFC, 0x18, 0x3F, 0x7E, 0xC1, 0x83, 0xF7, 0xF0, 0x9D, 0x36,
|
||||
0xDB, 0x6D, 0xB6, 0x7A, 0x6D, 0xB6, 0xDB, 0x6C, 0x6F, 0xB6, 0x66, 0x66, 0x66, 0x66, 0x60, 0xBB, 0x66, 0x66, 0x66,
|
||||
0x66, 0x66, 0x7E, 0x3F, 0x98, 0xEC, 0x3F, 0xDF, 0xED, 0x86, 0xC7, 0x7F, 0x3F, 0x00, 0x1E, 0x3E, 0x3C, 0xC3, 0xE3,
|
||||
0xF3, 0xF3, 0xFB, 0xDF, 0xCF, 0xCF, 0xC7, 0xC3, 0x18, 0x0E, 0x03, 0x07, 0xC7, 0xF7, 0x1F, 0x07, 0x83, 0xC1, 0xE0,
|
||||
0xF0, 0xEF, 0xE3, 0xE0, 0x0C, 0x0E, 0x06, 0x07, 0xC7, 0xF7, 0x1F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0xEF, 0xE3, 0xE0,
|
||||
0x1C, 0x1F, 0x0D, 0x87, 0xC7, 0xF7, 0x1F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0xEF, 0xE3, 0xE0, 0x1E, 0x1F, 0x0F, 0x07,
|
||||
0xC7, 0xF7, 0x1F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0xEF, 0xE3, 0xE0, 0x36, 0x1B, 0x0F, 0x8F, 0xEE, 0x3E, 0x0F, 0x07,
|
||||
0x83, 0xC1, 0xE1, 0xDF, 0xC7, 0xC0, 0x8F, 0xF7, 0x9E, 0xFF, 0x30, 0x1F, 0xCF, 0xF7, 0x3D, 0x9F, 0x6E, 0xDF, 0x37,
|
||||
0x8D, 0xC7, 0xFF, 0xB7, 0xC0, 0x30, 0x38, 0x18, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7E, 0x3C, 0x0C,
|
||||
0x1C, 0x18, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7E, 0x3C, 0x18, 0x3C, 0x3C, 0xC3, 0xC3, 0xC3, 0xC3,
|
||||
0xC3, 0xC3, 0xC3, 0xC7, 0x7E, 0x3C, 0x3C, 0x3C, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7E, 0x3C, 0x0C,
|
||||
0x1C, 0x18, 0xC3, 0xC3, 0xE7, 0x7E, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0xC0, 0xFC, 0xFE, 0xC7, 0xC3, 0xC7, 0xFE,
|
||||
0xFC, 0xC0, 0xC0, 0x38, 0xFB, 0xB6, 0x6D, 0xDB, 0x37, 0x67, 0xE7, 0xFF, 0x70, 0x30, 0x70, 0x63, 0xEF, 0xF0, 0xDF,
|
||||
0xFF, 0xC7, 0xFD, 0xF8, 0x0C, 0x38, 0x63, 0xEF, 0xF0, 0xDF, 0xFF, 0xC7, 0xFD, 0xF8, 0x18, 0x78, 0xF3, 0xEF, 0xF0,
|
||||
0xDF, 0xFF, 0xC7, 0xFD, 0xF8, 0x3C, 0xF9, 0xE3, 0xEF, 0xF0, 0xDF, 0xFF, 0xC7, 0xFD, 0xF8, 0x3C, 0x79, 0xF7, 0xF8,
|
||||
0x6F, 0xFF, 0xE3, 0xFE, 0xFC, 0x18, 0x78, 0xF0, 0xC7, 0xDF, 0xE1, 0xBF, 0xFF, 0x8F, 0xFB, 0xF0, 0x7F, 0xEF, 0xFF,
|
||||
0x86, 0x37, 0xFF, 0xFF, 0xFC, 0x61, 0xFF, 0xF7, 0xFE, 0x3C, 0xFF, 0x9E, 0x0C, 0x18, 0x9F, 0x9E, 0x18, 0x18, 0xE1,
|
||||
0x80, 0x30, 0x38, 0x18, 0x3C, 0x7E, 0xE7, 0xFF, 0xFF, 0xC0, 0x7E, 0x3F, 0x0C, 0x1C, 0x18, 0x3C, 0x7E, 0xE7, 0xFF,
|
||||
0xFF, 0xC0, 0x7E, 0x3F, 0x18, 0x3C, 0x3C, 0x3C, 0x7E, 0xE7, 0xFF, 0xFF, 0xC0, 0x7E, 0x3F, 0x3C, 0x3C, 0x3C, 0x7E,
|
||||
0xE7, 0xFF, 0xFF, 0xC0, 0x7E, 0x3F, 0x9D, 0xA6, 0xDB, 0x6D, 0x80, 0x7F, 0x4D, 0xB6, 0xDB, 0x00, 0x6F, 0xB4, 0x66,
|
||||
0x66, 0x66, 0x60, 0xBB, 0x46, 0x66, 0x66, 0x66, 0x3E, 0x3E, 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC3, 0xC7, 0x7E, 0x3C,
|
||||
0x3D, 0xF7, 0x9E, 0xFF, 0x3C, 0xF3, 0xCF, 0x3C, 0xC0, 0x30, 0x38, 0x18, 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC7, 0x7E,
|
||||
0x3C, 0x0C, 0x1C, 0x18, 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC7, 0x7E, 0x3C, 0x18, 0x3C, 0x3C, 0x3C, 0x7E, 0xE7, 0xC3,
|
||||
0xC3, 0xC7, 0x7E, 0x3C, 0x1E, 0x3E, 0x3C, 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC7, 0x7E, 0x3C, 0x3C, 0x3C, 0x3C, 0x7E,
|
||||
0xE7, 0xC3, 0xC3, 0xC7, 0x7E, 0x3C, 0x18, 0x18, 0xFF, 0xFF, 0x10, 0x18, 0x3F, 0x7F, 0xEF, 0xDF, 0xFB, 0xF7, 0xFE,
|
||||
0xFC, 0x61, 0xC3, 0x23, 0xCF, 0x3C, 0xF3, 0xCF, 0xF7, 0x80, 0x18, 0xE3, 0x23, 0xCF, 0x3C, 0xF3, 0xCF, 0xF7, 0x80,
|
||||
0x31, 0xE7, 0xA3, 0xCF, 0x3C, 0xF3, 0xCF, 0xF7, 0x80, 0x79, 0xE8, 0xF3, 0xCF, 0x3C, 0xF3, 0xFD, 0xE0, 0x0C, 0x1C,
|
||||
0x18, 0x83, 0xC7, 0x66, 0x6E, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x70, 0x60, 0xC1, 0x83, 0xE7, 0xEE, 0xF8, 0xF1, 0xE7,
|
||||
0xFD, 0xF3, 0x06, 0x08, 0x00, 0x3C, 0x3C, 0x83, 0xC7, 0x66, 0x6E, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x70, 0x60, 0x7C,
|
||||
0xF8, 0xE3, 0xEE, 0xF8, 0xF1, 0xFF, 0xFF, 0x8F, 0x1E, 0x30, 0x7C, 0xF9, 0xF7, 0xF8, 0x6F, 0xFF, 0xE3, 0xFE, 0xFC,
|
||||
0x6C, 0xF8, 0xE1, 0xC7, 0xDD, 0xF1, 0xE3, 0xFF, 0xFF, 0x1E, 0x3C, 0x60, 0x6C, 0xF8, 0xE3, 0xEF, 0xF0, 0xDF, 0xFF,
|
||||
0xC7, 0xFD, 0xF8, 0x38, 0x7C, 0xEE, 0xC6, 0xC6, 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0x0C, 0x0C, 0x0F, 0x07, 0x7C, 0xFE,
|
||||
0x86, 0x7E, 0xFE, 0xC6, 0xFE, 0x7E, 0x06, 0x0C, 0x0F, 0x0F, 0x0C, 0x0E, 0x06, 0x07, 0xE7, 0xFF, 0x0F, 0x01, 0x80,
|
||||
0xC0, 0x60, 0x30, 0x6F, 0xF3, 0xF0, 0x0C, 0x38, 0x61, 0xE7, 0xFC, 0xF0, 0x60, 0xC4, 0xFC, 0xF0, 0x0C, 0x0F, 0x07,
|
||||
0x87, 0xE7, 0xFF, 0x0F, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x6F, 0xF3, 0xF0, 0x18, 0x78, 0xF1, 0xE7, 0xFC, 0xF0, 0x60,
|
||||
0xC4, 0xFC, 0xF0, 0x0C, 0x06, 0x0F, 0xCF, 0xFE, 0x1E, 0x03, 0x01, 0x80, 0xC0, 0x60, 0xDF, 0xE7, 0xE0, 0x18, 0x30,
|
||||
0xF3, 0xFE, 0x78, 0x30, 0x62, 0x7E, 0x78, 0x1E, 0x0F, 0x03, 0x07, 0xE7, 0xFF, 0x0F, 0x01, 0x80, 0xC0, 0x60, 0x30,
|
||||
0x6F, 0xF3, 0xF0, 0x3C, 0x78, 0x61, 0xE7, 0xFC, 0xF0, 0x60, 0xC4, 0xFC, 0xF0, 0x78, 0x78, 0x30, 0xFC, 0xFE, 0xC7,
|
||||
0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0xFE, 0xFC, 0x01, 0x83, 0xC1, 0xE7, 0xC7, 0xE7, 0x33, 0x19, 0x8C, 0xC6, 0x3F, 0x0F,
|
||||
0x80, 0x7E, 0x3F, 0x98, 0xEC, 0x3F, 0xDF, 0xED, 0x86, 0xC7, 0x7F, 0x3F, 0x00, 0x06, 0x1F, 0x1F, 0x3E, 0x7E, 0xE6,
|
||||
0xC6, 0xC6, 0xC6, 0x7E, 0x3E, 0x3C, 0x7B, 0xFF, 0xFC, 0x18, 0x3F, 0x7E, 0xC1, 0x83, 0xF7, 0xF0, 0x3C, 0x3C, 0x3C,
|
||||
0x7E, 0xE7, 0xFF, 0xFF, 0xC0, 0x7E, 0x3F, 0x66, 0xFC, 0xF7, 0xFF, 0xF8, 0x30, 0x7E, 0xFD, 0x83, 0x07, 0xEF, 0xE0,
|
||||
0x66, 0x7E, 0x3C, 0x3C, 0x7E, 0xE7, 0xFF, 0xFF, 0xC0, 0x7E, 0x3F, 0x18, 0x33, 0xFF, 0xFC, 0x18, 0x3F, 0x7E, 0xC1,
|
||||
0x83, 0xF7, 0xF0, 0x18, 0x18, 0x3C, 0x7E, 0xE7, 0xFF, 0xFF, 0xC0, 0x7E, 0x3F, 0xFE, 0xFE, 0xC0, 0xC0, 0xFC, 0xFC,
|
||||
0xC0, 0xC0, 0xFC, 0xFE, 0x06, 0x0C, 0x0F, 0x0F, 0x3C, 0x7E, 0xE7, 0xFF, 0xFF, 0xC0, 0x7E, 0x3F, 0x06, 0x0C, 0x0F,
|
||||
0x07, 0x3C, 0x78, 0x67, 0xFF, 0xF8, 0x30, 0x7E, 0xFD, 0x83, 0x07, 0xEF, 0xE0, 0x3C, 0x3C, 0x18, 0x3C, 0x7E, 0xE7,
|
||||
0xFF, 0xFF, 0xC0, 0x7E, 0x3F, 0x0C, 0x0F, 0x07, 0x87, 0xE7, 0xFF, 0x0F, 0x01, 0x8F, 0xC7, 0xE0, 0xF0, 0x6F, 0xF3,
|
||||
0xF0, 0x18, 0x78, 0xF1, 0xF7, 0xFC, 0xF1, 0xE3, 0xC6, 0xFC, 0xF8, 0x30, 0x6F, 0x9E, 0x00, 0x36, 0x1F, 0x07, 0x07,
|
||||
0xE7, 0xFF, 0x0F, 0x01, 0x8F, 0xC7, 0xE0, 0xF0, 0x6F, 0xF3, 0xF0, 0x36, 0x7C, 0x71, 0xF7, 0xFC, 0xF1, 0xE3, 0xC6,
|
||||
0xFC, 0xF8, 0x30, 0x6F, 0x9E, 0x00, 0x0C, 0x06, 0x0F, 0xCF, 0xFE, 0x1E, 0x03, 0x1F, 0x8F, 0xC1, 0xE0, 0xDF, 0xE7,
|
||||
0xE0, 0x18, 0x30, 0xFB, 0xFE, 0x78, 0xF1, 0xE3, 0x7E, 0x7C, 0x18, 0x37, 0xCF, 0x00, 0x3F, 0x3F, 0xF8, 0x78, 0x0C,
|
||||
0x7E, 0x3F, 0x07, 0x83, 0x7F, 0x9F, 0x83, 0x00, 0xC1, 0xC0, 0xE0, 0x18, 0x30, 0x61, 0xF7, 0xFC, 0xF1, 0xE3, 0xC6,
|
||||
0xFC, 0xF8, 0x30, 0x6F, 0x9E, 0x00, 0x18, 0x3C, 0x3C, 0xC3, 0xC3, 0xC3, 0xC3, 0xFF, 0xFF, 0xC3, 0xC3, 0xC3, 0xC3,
|
||||
0x31, 0xE7, 0xB0, 0xC3, 0xEF, 0xFB, 0xCF, 0x3C, 0xF3, 0xCC, 0x61, 0xBF, 0xFF, 0xFD, 0x86, 0x7F, 0x9F, 0xE6, 0x19,
|
||||
0x86, 0x61, 0x98, 0x60, 0x61, 0xF3, 0xE3, 0xE7, 0xEE, 0xD9, 0xB3, 0x66, 0xCD, 0x98, 0x7F, 0xEC, 0xC6, 0x31, 0x8C,
|
||||
0x63, 0x18, 0xC6, 0x00, 0x7F, 0xEC, 0x86, 0x31, 0x8C, 0x63, 0x18, 0xFF, 0x66, 0x66, 0x66, 0x66, 0x66, 0xFF, 0x46,
|
||||
0x66, 0x66, 0x66, 0x9F, 0xDC, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x00, 0x9F, 0xDC, 0x86, 0x31, 0x8C, 0x63, 0x18,
|
||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x6C, 0xF6, 0x66, 0x46, 0x66, 0x66, 0x66, 0x6C, 0xF6, 0xEF, 0xFF, 0xFF, 0xBF, 0xFF,
|
||||
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE3, 0xF3, 0xFF, 0xDE, 0xDE, 0xE7, 0xBD, 0xEF, 0x7B, 0xDE, 0xC6, 0x33, 0x10,
|
||||
0x0C, 0x3C, 0x78, 0x60, 0xC1, 0x83, 0x06, 0x0D, 0x1B, 0x37, 0xE7, 0x80, 0x6F, 0xB4, 0x66, 0x66, 0x66, 0x66, 0x6C,
|
||||
0x80, 0xC3, 0xC7, 0xCE, 0xDC, 0xF8, 0xF8, 0xDC, 0xCC, 0xC6, 0xC3, 0x38, 0x1C, 0x38, 0x30, 0xC3, 0x0C, 0xF7, 0xFB,
|
||||
0xCE, 0x3C, 0xDB, 0x37, 0x0E, 0x71, 0x80, 0x8F, 0x7F, 0xBC, 0xE3, 0xCD, 0xB3, 0x30, 0xE1, 0x86, 0x0C, 0x18, 0x30,
|
||||
0x60, 0xC1, 0x83, 0x07, 0xEF, 0xE0, 0x7A, 0x6D, 0xB6, 0xDB, 0x6C, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFD,
|
||||
0xFD, 0xC1, 0xC7, 0x0C, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0xEF, 0xEC, 0x0D, 0x9B, 0x36, 0x6C, 0x18, 0x30, 0x60,
|
||||
0xC1, 0xFB, 0xF8, 0x3F, 0xFF, 0xCC, 0xCC, 0xCC, 0xC0, 0xC1, 0x83, 0x06, 0x0C, 0xD9, 0xB0, 0x60, 0xFD, 0xFC, 0xCC,
|
||||
0xCC, 0xFF, 0xCC, 0xCC, 0x60, 0x60, 0x78, 0x78, 0xF0, 0xE0, 0x60, 0x60, 0x7E, 0x7F, 0x66, 0x67, 0xFE, 0x66, 0x66,
|
||||
0x0C, 0x1C, 0x18, 0xC3, 0xE3, 0xF3, 0xF3, 0xFB, 0xDF, 0xCF, 0xCF, 0xC7, 0xC3, 0x18, 0x63, 0x8C, 0x7B, 0xFC, 0xF3,
|
||||
0xCF, 0x3C, 0xF3, 0xC3, 0xE3, 0xF3, 0xF3, 0xFB, 0xDF, 0xCF, 0xCF, 0xC7, 0xC3, 0x38, 0x1C, 0x38, 0x30, 0x7B, 0xFC,
|
||||
0xF3, 0xCF, 0x3C, 0xF3, 0x70, 0xE7, 0x18, 0x3C, 0x3C, 0x18, 0xC3, 0xE3, 0xF3, 0xF3, 0xFB, 0xDF, 0xCF, 0xCF, 0xC7,
|
||||
0xC3, 0x79, 0xE3, 0x1E, 0xFF, 0x3C, 0xF3, 0xCF, 0x3C, 0xC0, 0x81, 0x83, 0x05, 0xE7, 0xEC, 0xD9, 0xB3, 0x66, 0xCD,
|
||||
0x98, 0xC3, 0xE3, 0xF3, 0xF3, 0xFB, 0xDF, 0xCF, 0xCF, 0xC7, 0xC3, 0x03, 0x03, 0x03, 0x7B, 0xFC, 0xF3, 0xCF, 0x3C,
|
||||
0xF3, 0x0C, 0x31, 0x84, 0x3E, 0x1F, 0x0F, 0x8F, 0xEE, 0x3E, 0x0F, 0x07, 0x83, 0xC1, 0xE1, 0xDF, 0xC7, 0xC0, 0x3C,
|
||||
0x3C, 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC7, 0x7E, 0x3C, 0x36, 0x1F, 0x07, 0x07, 0xC7, 0xF7, 0x1F, 0x07, 0x83, 0xC1,
|
||||
0xE0, 0xF0, 0xEF, 0xE3, 0xE0, 0x36, 0x3E, 0x1C, 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC7, 0x7E, 0x3C, 0x1B, 0x1F, 0x8D,
|
||||
0x87, 0xC7, 0xF7, 0x1F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0xEF, 0xE3, 0xE0, 0x1E, 0x3E, 0x3C, 0x3C, 0x7E, 0xE7, 0xC3,
|
||||
0xC3, 0xC7, 0x7E, 0x3C, 0x3F, 0xFB, 0xFF, 0xF9, 0xC1, 0x86, 0x0C, 0x3F, 0x61, 0xFB, 0x0C, 0x18, 0x60, 0xC7, 0x03,
|
||||
0xFF, 0x0F, 0xFC, 0x3D, 0xE3, 0xFF, 0xB9, 0xCF, 0x87, 0xFC, 0x3F, 0xE3, 0x85, 0xFF, 0xE7, 0xBE, 0x18, 0x38, 0x30,
|
||||
0xFE, 0xFF, 0xC3, 0xC7, 0xFE, 0xFE, 0xC7, 0xC3, 0xC3, 0xC3, 0x33, 0x98, 0xEF, 0xEF, 0x18, 0xC6, 0x30, 0xFE, 0xFF,
|
||||
0xC3, 0xC7, 0xFE, 0xFE, 0xC7, 0xC3, 0xC3, 0xC3, 0x38, 0x1C, 0x38, 0x30, 0x77, 0xF7, 0x8C, 0x63, 0x18, 0xE3, 0xB9,
|
||||
0x80, 0x3C, 0x3C, 0x18, 0xFE, 0xFF, 0xC3, 0xC7, 0xFE, 0xFE, 0xC7, 0xC3, 0xC3, 0xC3, 0xF7, 0x98, 0xEF, 0xEF, 0x18,
|
||||
0xC6, 0x30, 0x18, 0x70, 0xC3, 0xEF, 0xF8, 0xFC, 0x3E, 0x1E, 0x0E, 0x1F, 0xF7, 0xC0, 0x18, 0x70, 0xC3, 0xEF, 0xF8,
|
||||
0xFF, 0x3F, 0x87, 0xFD, 0xF0, 0x18, 0x78, 0xF3, 0xEF, 0xF8, 0xFC, 0x3E, 0x1E, 0x0E, 0x1F, 0xF7, 0xC0, 0x18, 0x78,
|
||||
0xF3, 0xEF, 0xF8, 0xFF, 0x3F, 0x87, 0xFD, 0xF0, 0x7D, 0xFF, 0x1F, 0x87, 0xC3, 0xC1, 0xC3, 0xFE, 0xF8, 0xC0, 0xC7,
|
||||
0x0C, 0x00, 0x7D, 0xFF, 0x1F, 0xE7, 0xF0, 0xFF, 0xBE, 0x18, 0x18, 0xE1, 0x80, 0x3C, 0x78, 0x63, 0xEF, 0xF8, 0xFC,
|
||||
0x3E, 0x1E, 0x0E, 0x1F, 0xF7, 0xC0, 0x3C, 0x78, 0x63, 0xEF, 0xF8, 0xFF, 0x3F, 0x87, 0xFD, 0xF0, 0xFF, 0xFF, 0xC6,
|
||||
0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x01, 0x83, 0x81, 0x80, 0x63, 0x3D, 0xE6, 0x31, 0x8C, 0x71,
|
||||
0xCC, 0x37, 0x30, 0x3C, 0x3C, 0x18, 0xFF, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0D, 0xB6, 0xFF,
|
||||
0xF1, 0x86, 0x18, 0x61, 0xC3, 0x80, 0xFF, 0xFF, 0x18, 0x18, 0x7E, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x63, 0x3D, 0xE6,
|
||||
0x73, 0xCC, 0x71, 0xC0, 0x1E, 0x3E, 0x3C, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7E, 0x3C, 0x3D, 0xF7,
|
||||
0xA3, 0xCF, 0x3C, 0xF3, 0xCF, 0xF7, 0x80, 0x3C, 0x3C, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7E, 0x3C,
|
||||
0x79, 0xE8, 0xF3, 0xCF, 0x3C, 0xF3, 0xFD, 0xE0, 0x36, 0x3E, 0x1C, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7,
|
||||
0x7E, 0x3C, 0x6D, 0xF3, 0xA3, 0xCF, 0x3C, 0xF3, 0xCF, 0xF7, 0x80, 0x18, 0x3C, 0x3C, 0xDB, 0xC3, 0xC3, 0xC3, 0xC3,
|
||||
0xC3, 0xC3, 0xC7, 0x7E, 0x3C, 0x31, 0xE7, 0xAF, 0xCF, 0x3C, 0xF3, 0xCF, 0xF7, 0x80, 0x1E, 0x3E, 0x3C, 0xC3, 0xC3,
|
||||
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7E, 0x3C, 0x3D, 0xF7, 0xA3, 0xCF, 0x3C, 0xF3, 0xCF, 0xF7, 0x80, 0xC3, 0xC3,
|
||||
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7E, 0x3C, 0x18, 0x30, 0x3C, 0x1C, 0x8D, 0x9B, 0x36, 0x6C, 0xD9, 0xBF, 0x3E,
|
||||
0x0C, 0x30, 0x78, 0x70, 0x03, 0x00, 0x1E, 0x00, 0x78, 0x20, 0xC3, 0xC3, 0x0F, 0x0C, 0x3C, 0x79, 0xD9, 0xE6, 0x6F,
|
||||
0xF8, 0xF3, 0xC3, 0xCF, 0x0F, 0x3C, 0x18, 0x60, 0x0C, 0x07, 0x81, 0xE2, 0x03, 0xCC, 0xF7, 0xF7, 0xF9, 0xFE, 0x7F,
|
||||
0x8C, 0xC3, 0x30, 0x18, 0x3C, 0x3C, 0xC3, 0xC3, 0xE7, 0x7E, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x3C,
|
||||
0x83, 0xC7, 0x66, 0x6E, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x70, 0x60, 0x3C, 0x3C, 0xC3, 0xC3, 0xE7, 0x7E, 0x3C, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x0C, 0x1C, 0x18, 0xFF, 0xFF, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xFE, 0xFF, 0x0C, 0x38,
|
||||
0x67, 0xFF, 0xE3, 0x8E, 0x38, 0xE1, 0xFB, 0xF8, 0x0C, 0x0C, 0xFF, 0xFF, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xFE,
|
||||
0xFF, 0x18, 0x33, 0xFF, 0xF1, 0xC7, 0x1C, 0x70, 0xFD, 0xFC, 0x3C, 0x3C, 0x18, 0xFF, 0xFF, 0x07, 0x0E, 0x1C, 0x38,
|
||||
0x70, 0xE0, 0xFE, 0xFF, 0x3C, 0x78, 0x67, 0xFF, 0xE3, 0x8E, 0x38, 0xE1, 0xFB, 0xF8, 0x1E, 0x3F, 0x73, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0x62, 0x3F, 0x1E,
|
||||
};
|
||||
|
||||
static const EpdGlyph babyblueGlyphs[] = {
|
||||
{0, 0, 5, 0, 0, 0, 0}, //
|
||||
{2, 10, 3, 1, 10, 3, 0}, // !
|
||||
{4, 5, 5, 1, 11, 3, 3}, // "
|
||||
{9, 11, 10, 0, 11, 13, 6}, // #
|
||||
{8, 14, 9, 0, 12, 14, 19}, // $
|
||||
{11, 11, 13, 1, 11, 16, 33}, // %
|
||||
{9, 11, 11, 1, 11, 13, 49}, // &
|
||||
{2, 4, 3, 1, 11, 1, 62}, // '
|
||||
{4, 15, 5, 1, 11, 8, 63}, // (
|
||||
{4, 15, 5, 1, 11, 8, 71}, // )
|
||||
{6, 6, 6, 0, 11, 5, 79}, // *
|
||||
{8, 8, 9, 0, 9, 8, 84}, // +
|
||||
{2, 5, 3, 1, 3, 2, 92}, // ,
|
||||
{5, 2, 5, 0, 5, 2, 94}, // -
|
||||
{2, 2, 3, 1, 2, 1, 96}, // .
|
||||
{6, 11, 6, 0, 11, 9, 97}, // /
|
||||
{8, 11, 9, 0, 11, 11, 106}, // 0
|
||||
{5, 11, 6, 1, 11, 7, 117}, // 1
|
||||
{8, 11, 9, 0, 11, 11, 124}, // 2
|
||||
{8, 11, 10, 1, 11, 11, 135}, // 3
|
||||
{8, 11, 9, 0, 11, 11, 146}, // 4
|
||||
{7, 11, 9, 1, 11, 10, 157}, // 5
|
||||
{8, 11, 9, 0, 11, 11, 167}, // 6
|
||||
{9, 11, 10, 0, 11, 13, 178}, // 7
|
||||
{8, 11, 9, 0, 11, 11, 191}, // 8
|
||||
{8, 11, 9, 0, 11, 11, 202}, // 9
|
||||
{2, 8, 3, 1, 8, 2, 213}, // :
|
||||
{2, 11, 3, 1, 8, 3, 215}, // ;
|
||||
{7, 8, 9, 1, 9, 7, 218}, // <
|
||||
{8, 5, 9, 0, 8, 5, 225}, // =
|
||||
{7, 8, 7, 0, 9, 7, 230}, // >
|
||||
{7, 11, 9, 1, 11, 10, 237}, // ?
|
||||
{14, 15, 15, 0, 11, 27, 247}, // @
|
||||
{7, 10, 9, 1, 10, 9, 274}, // A
|
||||
{8, 10, 10, 1, 10, 10, 283}, // B
|
||||
{9, 10, 11, 1, 10, 12, 293}, // C
|
||||
{8, 10, 10, 1, 10, 10, 305}, // D
|
||||
{7, 10, 9, 1, 10, 9, 315}, // E
|
||||
{7, 10, 9, 1, 10, 9, 324}, // F
|
||||
{9, 10, 11, 1, 10, 12, 333}, // G
|
||||
{8, 10, 10, 1, 10, 10, 345}, // H
|
||||
{2, 10, 3, 1, 10, 3, 355}, // I
|
||||
{6, 10, 6, 0, 10, 8, 358}, // J
|
||||
{8, 10, 10, 1, 10, 10, 366}, // K
|
||||
{7, 10, 9, 1, 10, 9, 376}, // L
|
||||
{10, 10, 12, 1, 10, 13, 385}, // M
|
||||
{8, 10, 10, 1, 10, 10, 398}, // N
|
||||
{9, 10, 11, 1, 10, 12, 408}, // O
|
||||
{8, 10, 10, 1, 10, 10, 420}, // P
|
||||
{9, 10, 11, 1, 10, 12, 430}, // Q
|
||||
{8, 10, 10, 1, 10, 10, 442}, // R
|
||||
{7, 10, 9, 1, 10, 9, 452}, // S
|
||||
{8, 10, 9, 0, 10, 10, 461}, // T
|
||||
{8, 10, 10, 1, 10, 10, 471}, // U
|
||||
{8, 10, 10, 1, 10, 10, 481}, // V
|
||||
{14, 10, 15, 0, 10, 18, 491}, // W
|
||||
{10, 10, 11, 0, 10, 13, 509}, // X
|
||||
{8, 10, 10, 1, 10, 10, 522}, // Y
|
||||
{8, 10, 9, 0, 10, 10, 532}, // Z
|
||||
{4, 14, 5, 1, 10, 7, 542}, // [
|
||||
{7, 10, 7, 0, 10, 9, 549}, // <backslash>
|
||||
{4, 14, 4, 0, 10, 7, 558}, // ]
|
||||
{8, 7, 9, 0, 11, 7, 565}, // ^
|
||||
{8, 2, 9, 0, -2, 2, 572}, // _
|
||||
{3, 3, 3, 0, 11, 2, 574}, // `
|
||||
{7, 8, 7, 0, 8, 7, 576}, // a
|
||||
{7, 10, 9, 1, 10, 9, 583}, // b
|
||||
{7, 8, 7, 0, 8, 7, 592}, // c
|
||||
{7, 10, 7, 0, 10, 9, 599}, // d
|
||||
{8, 8, 9, 0, 8, 8, 608}, // e
|
||||
{5, 11, 5, 0, 11, 7, 616}, // f
|
||||
{7, 12, 7, 0, 8, 11, 623}, // g
|
||||
{6, 10, 7, 1, 10, 8, 634}, // h
|
||||
{2, 10, 3, 1, 10, 3, 642}, // i
|
||||
{3, 14, 3, 0, 10, 6, 645}, // j
|
||||
{6, 10, 7, 1, 10, 8, 651}, // k
|
||||
{2, 10, 3, 1, 10, 3, 659}, // l
|
||||
{10, 8, 12, 1, 8, 10, 662}, // m
|
||||
{6, 8, 7, 1, 8, 6, 672}, // n
|
||||
{8, 8, 9, 0, 8, 8, 678}, // o
|
||||
{7, 11, 9, 1, 8, 10, 686}, // p
|
||||
{7, 11, 7, 0, 8, 10, 696}, // q
|
||||
{5, 8, 6, 1, 8, 5, 706}, // r
|
||||
{7, 8, 7, 0, 8, 7, 711}, // s
|
||||
{5, 10, 5, 0, 10, 7, 718}, // t
|
||||
{6, 8, 7, 1, 8, 6, 725}, // u
|
||||
{8, 8, 9, 0, 8, 8, 731}, // v
|
||||
{10, 8, 11, 0, 8, 10, 739}, // w
|
||||
{8, 8, 9, 0, 8, 8, 749}, // x
|
||||
{8, 11, 9, 0, 8, 11, 757}, // y
|
||||
{7, 8, 7, 0, 8, 7, 768}, // z
|
||||
{5, 15, 5, 0, 11, 10, 775}, // {
|
||||
{2, 15, 3, 1, 11, 4, 785}, // |
|
||||
{6, 15, 6, 0, 11, 12, 789}, // }
|
||||
{9, 3, 10, 0, 7, 4, 801}, // ~
|
||||
{2, 12, 4, 2, 8, 3, 805}, // ¡
|
||||
{7, 13, 7, 0, 10, 12, 808}, // ¢
|
||||
{8, 10, 9, 0, 10, 10, 820}, // £
|
||||
{8, 8, 9, 0, 9, 8, 830}, // ¤
|
||||
{8, 10, 9, 0, 10, 10, 838}, // ¥
|
||||
{2, 15, 3, 1, 11, 4, 848}, // ¦
|
||||
{8, 15, 9, 0, 11, 15, 852}, // §
|
||||
{5, 3, 5, 0, 11, 2, 867}, // ¨
|
||||
{10, 11, 11, 0, 11, 14, 869}, // ©
|
||||
{5, 6, 5, 0, 11, 4, 883}, // ª
|
||||
{7, 7, 9, 1, 8, 7, 887}, // «
|
||||
{8, 5, 9, 0, 8, 5, 894}, // ¬
|
||||
{10, 11, 11, 0, 11, 14, 899}, // ®
|
||||
{8, 2, 9, 0, 12, 2, 913}, // ¯
|
||||
{4, 5, 5, 1, 11, 3, 915}, // °
|
||||
{8, 9, 9, 0, 9, 9, 918}, // ±
|
||||
{5, 8, 5, 0, 11, 5, 927}, // ²
|
||||
{5, 6, 5, 0, 11, 4, 932}, // ³
|
||||
{3, 3, 4, 1, 11, 2, 936}, // ´
|
||||
{6, 12, 9, 2, 8, 9, 938}, // µ
|
||||
{8, 14, 9, 0, 10, 14, 947}, // ¶
|
||||
{2, 2, 3, 1, 6, 1, 961}, // ·
|
||||
{4, 4, 4, 0, 0, 2, 962}, // ¸
|
||||
{4, 7, 4, 0, 12, 4, 964}, // ¹
|
||||
{6, 6, 6, 0, 11, 5, 968}, // º
|
||||
{7, 7, 9, 1, 8, 7, 973}, // »
|
||||
{12, 12, 13, 0, 12, 18, 980}, // ¼
|
||||
{12, 11, 13, 0, 11, 17, 998}, // ½
|
||||
{12, 11, 13, 0, 11, 17, 1015}, // ¾
|
||||
{7, 12, 9, 1, 8, 11, 1032}, // ¿
|
||||
{7, 13, 9, 1, 13, 12, 1043}, // À
|
||||
{7, 13, 9, 1, 13, 12, 1055}, // Á
|
||||
{7, 13, 9, 1, 13, 12, 1067}, // Â
|
||||
{7, 13, 9, 1, 13, 12, 1079}, // Ã
|
||||
{7, 12, 9, 1, 12, 11, 1091}, // Ä
|
||||
{7, 13, 9, 1, 13, 12, 1102}, // Å
|
||||
{13, 11, 14, 0, 11, 18, 1114}, // Æ
|
||||
{9, 14, 11, 1, 10, 16, 1132}, // Ç
|
||||
{7, 13, 9, 1, 13, 12, 1148}, // È
|
||||
{7, 13, 9, 1, 13, 12, 1160}, // É
|
||||
{7, 13, 9, 1, 13, 12, 1172}, // Ê
|
||||
{7, 12, 9, 1, 12, 11, 1184}, // Ë
|
||||
{3, 13, 3, 0, 13, 5, 1195}, // Ì
|
||||
{3, 13, 4, 1, 13, 5, 1200}, // Í
|
||||
{4, 13, 4, 0, 13, 7, 1205}, // Î
|
||||
{4, 12, 4, 0, 12, 6, 1212}, // Ï
|
||||
{9, 10, 10, 0, 10, 12, 1218}, // Ð
|
||||
{8, 13, 10, 1, 13, 13, 1230}, // Ñ
|
||||
{9, 13, 11, 1, 13, 15, 1243}, // Ò
|
||||
{9, 13, 11, 1, 13, 15, 1258}, // Ó
|
||||
{9, 13, 11, 1, 13, 15, 1273}, // Ô
|
||||
{9, 13, 11, 1, 13, 15, 1288}, // Õ
|
||||
{9, 12, 11, 1, 12, 14, 1303}, // Ö
|
||||
{6, 6, 7, 1, 8, 5, 1317}, // ×
|
||||
{10, 10, 11, 0, 10, 13, 1322}, // Ø
|
||||
{8, 13, 10, 1, 13, 13, 1335}, // Ù
|
||||
{8, 13, 10, 1, 13, 13, 1348}, // Ú
|
||||
{8, 13, 10, 1, 13, 13, 1361}, // Û
|
||||
{8, 12, 10, 1, 12, 12, 1374}, // Ü
|
||||
{8, 13, 10, 1, 13, 13, 1386}, // Ý
|
||||
{8, 10, 10, 1, 10, 10, 1399}, // Þ
|
||||
{7, 11, 9, 1, 11, 10, 1409}, // ß
|
||||
{7, 11, 7, 0, 11, 10, 1419}, // à
|
||||
{7, 11, 7, 0, 11, 10, 1429}, // á
|
||||
{7, 11, 7, 0, 11, 10, 1439}, // â
|
||||
{7, 11, 7, 0, 11, 10, 1449}, // ã
|
||||
{7, 10, 7, 0, 10, 9, 1459}, // ä
|
||||
{7, 12, 7, 0, 12, 11, 1468}, // å
|
||||
{12, 8, 13, 0, 8, 12, 1479}, // æ
|
||||
{7, 12, 7, 0, 8, 11, 1491}, // ç
|
||||
{8, 11, 9, 0, 11, 11, 1502}, // è
|
||||
{8, 11, 9, 0, 11, 11, 1513}, // é
|
||||
{8, 11, 9, 0, 11, 11, 1524}, // ê
|
||||
{8, 10, 9, 0, 10, 10, 1535}, // ë
|
||||
{3, 11, 3, 0, 11, 5, 1545}, // ì
|
||||
{3, 11, 4, 1, 11, 5, 1550}, // í
|
||||
{4, 11, 4, 0, 11, 6, 1555}, // î
|
||||
{4, 10, 4, 0, 10, 5, 1561}, // ï
|
||||
{8, 11, 9, 0, 11, 11, 1566}, // ð
|
||||
{6, 11, 7, 1, 11, 9, 1577}, // ñ
|
||||
{8, 11, 9, 0, 11, 11, 1586}, // ò
|
||||
{8, 11, 9, 0, 11, 11, 1597}, // ó
|
||||
{8, 11, 9, 0, 11, 11, 1608}, // ô
|
||||
{8, 11, 9, 0, 11, 11, 1619}, // õ
|
||||
{8, 10, 9, 0, 10, 10, 1630}, // ö
|
||||
{8, 6, 9, 0, 8, 6, 1640}, // ÷
|
||||
{8, 8, 9, 0, 8, 8, 1646}, // ø
|
||||
{6, 11, 7, 1, 11, 9, 1654}, // ù
|
||||
{6, 11, 7, 1, 11, 9, 1663}, // ú
|
||||
{6, 11, 7, 1, 11, 9, 1672}, // û
|
||||
{6, 10, 7, 1, 10, 8, 1681}, // ü
|
||||
{8, 14, 9, 0, 11, 14, 1689}, // ý
|
||||
{7, 13, 9, 1, 10, 12, 1703}, // þ
|
||||
{8, 13, 9, 0, 10, 13, 1715}, // ÿ
|
||||
{7, 12, 9, 1, 12, 11, 1728}, // Ā
|
||||
{7, 10, 7, 0, 10, 9, 1739}, // ā
|
||||
{7, 13, 9, 1, 13, 12, 1748}, // Ă
|
||||
{7, 11, 7, 0, 11, 10, 1760}, // ă
|
||||
{8, 14, 10, 1, 10, 14, 1770}, // Ą
|
||||
{8, 12, 9, 0, 8, 12, 1784}, // ą
|
||||
{9, 13, 11, 1, 13, 15, 1796}, // Ć
|
||||
{7, 11, 7, 0, 11, 10, 1811}, // ć
|
||||
{9, 13, 11, 1, 13, 15, 1821}, // Ĉ
|
||||
{7, 11, 7, 0, 11, 10, 1836}, // ĉ
|
||||
{9, 12, 11, 1, 12, 14, 1846}, // Ċ
|
||||
{7, 10, 7, 0, 10, 9, 1860}, // ċ
|
||||
{9, 13, 11, 1, 13, 15, 1869}, // Č
|
||||
{7, 11, 7, 0, 11, 10, 1884}, // č
|
||||
{8, 13, 10, 1, 13, 13, 1894}, // Ď
|
||||
{9, 11, 10, 0, 11, 13, 1907}, // ď
|
||||
{9, 10, 10, 0, 10, 12, 1920}, // Đ
|
||||
{8, 11, 9, 0, 11, 11, 1932}, // đ
|
||||
{7, 12, 9, 1, 12, 11, 1943}, // Ē
|
||||
{8, 10, 9, 0, 10, 10, 1954}, // ē
|
||||
{7, 13, 9, 1, 13, 12, 1964}, // Ĕ
|
||||
{8, 11, 9, 0, 11, 11, 1976}, // ĕ
|
||||
{7, 12, 9, 1, 12, 11, 1987}, // Ė
|
||||
{8, 10, 9, 0, 10, 10, 1998}, // ė
|
||||
{8, 14, 10, 1, 10, 14, 2008}, // Ę
|
||||
{8, 12, 9, 0, 8, 12, 2022}, // ę
|
||||
{7, 13, 9, 1, 13, 12, 2034}, // Ě
|
||||
{8, 11, 9, 0, 11, 11, 2046}, // ě
|
||||
{9, 13, 11, 1, 13, 15, 2057}, // Ĝ
|
||||
{7, 15, 7, 0, 11, 14, 2072}, // ĝ
|
||||
{9, 13, 11, 1, 13, 15, 2086}, // Ğ
|
||||
{7, 15, 7, 0, 11, 14, 2101}, // ğ
|
||||
{9, 12, 11, 1, 12, 14, 2115}, // Ġ
|
||||
{7, 14, 7, 0, 10, 13, 2129}, // ġ
|
||||
{9, 14, 11, 1, 10, 16, 2142}, // Ģ
|
||||
{7, 15, 7, 0, 11, 14, 2158}, // ģ
|
||||
{8, 13, 10, 1, 13, 13, 2172}, // Ĥ
|
||||
{6, 13, 7, 1, 13, 10, 2185}, // ĥ
|
||||
{10, 10, 11, 0, 10, 13, 2195}, // Ħ
|
||||
{7, 11, 7, 0, 11, 10, 2208}, // ħ
|
||||
{5, 13, 5, 0, 13, 9, 2218}, // Ĩ
|
||||
{5, 11, 5, 0, 11, 7, 2227}, // ĩ
|
||||
{4, 12, 4, 0, 12, 6, 2234}, // Ī
|
||||
{4, 10, 4, 0, 10, 5, 2240}, // ī
|
||||
{5, 13, 5, 0, 13, 9, 2245}, // Ĭ
|
||||
{5, 11, 5, 0, 11, 7, 2254}, // ĭ
|
||||
{4, 14, 4, 0, 10, 7, 2261}, // Į
|
||||
{4, 14, 4, 0, 10, 7, 2268}, // į
|
||||
{2, 12, 3, 1, 12, 3, 2275}, // İ
|
||||
{2, 8, 3, 1, 8, 2, 2278}, // ı
|
||||
{8, 10, 10, 1, 10, 10, 2280}, // IJ
|
||||
{5, 14, 6, 1, 10, 9, 2290}, // ij
|
||||
{7, 13, 7, 0, 13, 12, 2299}, // Ĵ
|
||||
{4, 15, 4, 0, 11, 8, 2311}, // ĵ
|
||||
{8, 14, 10, 1, 10, 14, 2319}, // Ķ
|
||||
{6, 14, 7, 1, 10, 11, 2333}, // ķ
|
||||
{6, 8, 7, 1, 8, 6, 2344}, // ĸ
|
||||
{7, 13, 9, 1, 13, 12, 2350}, // Ĺ
|
||||
{3, 13, 4, 1, 13, 5, 2362}, // ĺ
|
||||
{7, 14, 9, 1, 10, 13, 2367}, // Ļ
|
||||
{4, 14, 4, 0, 10, 7, 2380}, // ļ
|
||||
{7, 11, 9, 1, 11, 10, 2387}, // Ľ
|
||||
{4, 11, 5, 1, 11, 6, 2397}, // ľ
|
||||
{7, 10, 9, 1, 10, 9, 2403}, // Ŀ
|
||||
{4, 10, 5, 1, 10, 5, 2412}, // ŀ
|
||||
{8, 10, 9, 0, 10, 10, 2417}, // Ł
|
||||
{4, 10, 4, 0, 10, 5, 2427}, // ł
|
||||
{8, 13, 10, 1, 13, 13, 2432}, // Ń
|
||||
{6, 12, 7, 1, 12, 9, 2445}, // ń
|
||||
{8, 14, 10, 1, 10, 14, 2454}, // Ņ
|
||||
{6, 12, 7, 1, 8, 9, 2468}, // ņ
|
||||
{8, 13, 10, 1, 13, 13, 2477}, // Ň
|
||||
{6, 11, 7, 1, 11, 9, 2490}, // ň
|
||||
{7, 11, 7, 0, 11, 10, 2499}, // ʼn
|
||||
{8, 13, 10, 1, 10, 13, 2509}, // Ŋ
|
||||
{6, 12, 7, 1, 8, 9, 2522}, // ŋ
|
||||
{9, 12, 11, 1, 12, 14, 2531}, // Ō
|
||||
{8, 10, 9, 0, 10, 10, 2545}, // ō
|
||||
{9, 13, 11, 1, 13, 15, 2555}, // Ŏ
|
||||
{8, 11, 9, 0, 11, 11, 2570}, // ŏ
|
||||
{9, 13, 11, 1, 13, 15, 2581}, // Ő
|
||||
{8, 11, 9, 0, 11, 11, 2596}, // ő
|
||||
{13, 11, 15, 1, 11, 18, 2607}, // Œ
|
||||
{13, 8, 14, 0, 8, 13, 2625}, // œ
|
||||
{8, 13, 10, 1, 13, 13, 2638}, // Ŕ
|
||||
{5, 11, 6, 1, 11, 7, 2651}, // ŕ
|
||||
{8, 14, 10, 1, 10, 14, 2658}, // Ŗ
|
||||
{5, 12, 6, 1, 8, 8, 2672}, // ŗ
|
||||
{8, 13, 10, 1, 13, 13, 2680}, // Ř
|
||||
{5, 11, 6, 1, 11, 7, 2693}, // ř
|
||||
{7, 13, 9, 1, 13, 12, 2700}, // Ś
|
||||
{7, 11, 7, 0, 11, 10, 2712}, // ś
|
||||
{7, 13, 9, 1, 13, 12, 2722}, // Ŝ
|
||||
{7, 11, 7, 0, 11, 10, 2734}, // ŝ
|
||||
{7, 14, 9, 1, 10, 13, 2744}, // Ş
|
||||
{7, 12, 7, 0, 8, 11, 2757}, // ş
|
||||
{7, 13, 9, 1, 13, 12, 2768}, // Š
|
||||
{7, 11, 7, 0, 11, 10, 2780}, // š
|
||||
{9, 14, 10, 0, 10, 16, 2790}, // Ţ
|
||||
{5, 14, 5, 0, 10, 9, 2806}, // ţ
|
||||
{8, 13, 9, 0, 13, 13, 2815}, // Ť
|
||||
{6, 11, 6, 0, 11, 9, 2828}, // ť
|
||||
{8, 10, 9, 0, 10, 10, 2837}, // Ŧ
|
||||
{5, 10, 5, 0, 10, 7, 2847}, // ŧ
|
||||
{8, 13, 10, 1, 13, 13, 2854}, // Ũ
|
||||
{6, 11, 7, 1, 11, 9, 2867}, // ũ
|
||||
{8, 12, 10, 1, 12, 12, 2876}, // Ū
|
||||
{6, 10, 7, 1, 10, 8, 2888}, // ū
|
||||
{8, 13, 10, 1, 13, 13, 2896}, // Ŭ
|
||||
{6, 11, 7, 1, 11, 9, 2909}, // ŭ
|
||||
{8, 13, 10, 1, 13, 13, 2918}, // Ů
|
||||
{6, 11, 7, 1, 11, 9, 2931}, // ů
|
||||
{8, 13, 10, 1, 13, 13, 2940}, // Ű
|
||||
{6, 11, 7, 1, 11, 9, 2953}, // ű
|
||||
{8, 14, 10, 1, 10, 14, 2962}, // Ų
|
||||
{7, 12, 9, 1, 8, 11, 2976}, // ų
|
||||
{14, 13, 15, 0, 13, 23, 2987}, // Ŵ
|
||||
{10, 11, 11, 0, 11, 14, 3010}, // ŵ
|
||||
{8, 13, 10, 1, 13, 13, 3024}, // Ŷ
|
||||
{8, 14, 9, 0, 11, 14, 3037}, // ŷ
|
||||
{8, 12, 10, 1, 12, 12, 3051}, // Ÿ
|
||||
{8, 13, 9, 0, 13, 13, 3063}, // Ź
|
||||
{7, 11, 7, 0, 11, 10, 3076}, // ź
|
||||
{8, 12, 9, 0, 12, 12, 3086}, // Ż
|
||||
{7, 10, 7, 0, 10, 9, 3098}, // ż
|
||||
{8, 13, 9, 0, 13, 13, 3107}, // Ž
|
||||
{7, 11, 7, 0, 11, 10, 3120}, // ž
|
||||
{8, 10, 9, 0, 10, 10, 3130}, // €
|
||||
};
|
||||
|
||||
static const EpdUnicodeInterval babyblueIntervals[] = {
|
||||
{0x20, 0x7E, 0x0}, {0xA1, 0xAC, 0x5F}, {0xAE, 0xFF, 0x6B}, {0x100, 0x17E, 0xBD}, {0x20AC, 0x20AC, 0x13C},
|
||||
};
|
||||
|
||||
static const EpdFontData babyblue = {
|
||||
babyblueBitmaps, babyblueGlyphs, babyblueIntervals, 5, 17, 13, -4, false,
|
||||
};
|
||||
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
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
File diff suppressed because it is too large
Load Diff
@ -176,7 +176,7 @@ for i_start, i_end in intervals:
|
||||
px = 0
|
||||
|
||||
if is2Bit:
|
||||
# 0 = white, 15 black, 8+ dark grey, 7- light grey
|
||||
# 0-3 white, 4-7 light grey, 8-11 dark grey, 12-15 black
|
||||
# Downsample to 2-bit bitmap
|
||||
pixels2b = []
|
||||
px = 0
|
||||
@ -187,11 +187,11 @@ for i_start, i_end in intervals:
|
||||
bm = pixels4g[y * pitch + (x // 2)]
|
||||
bm = (bm >> ((x % 2) * 4)) & 0xF
|
||||
|
||||
if bm == 15:
|
||||
if bm >= 12:
|
||||
px += 3
|
||||
elif bm >= 8:
|
||||
px += 2
|
||||
elif bm > 0:
|
||||
elif bm >= 4:
|
||||
px += 1
|
||||
|
||||
if (y * bitmap.width + x) % 4 == 3:
|
||||
@ -211,7 +211,7 @@ for i_start, i_end in intervals:
|
||||
# print(line)
|
||||
# print('')
|
||||
else:
|
||||
# Downsample to 1-bit bitmap - treat any non-zero as black
|
||||
# Downsample to 1-bit bitmap - treat any 2+ as black
|
||||
pixelsbw = []
|
||||
px = 0
|
||||
pitch = (bitmap.width // 2) + (bitmap.width % 2)
|
||||
@ -219,7 +219,7 @@ for i_start, i_end in intervals:
|
||||
for x in range(bitmap.width):
|
||||
px = px << 1
|
||||
bm = pixels4g[y * pitch + (x // 2)]
|
||||
px += 1 if ((x & 1) == 0 and bm & 0xF > 0) or ((x & 1) == 1 and bm & 0xF0 > 0) else 0
|
||||
px += 1 if ((x & 1) == 0 and bm & 0xE > 0) or ((x & 1) == 1 and bm & 0xE0 > 0) else 0
|
||||
|
||||
if (y * bitmap.width + x) % 8 == 7:
|
||||
pixelsbw.append(px)
|
||||
|
||||
@ -148,23 +148,54 @@ bool Epub::load() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// determine size of spine items
|
||||
size_t spineItemsCount = getSpineItemsCount();
|
||||
size_t spineItemsSize = 0;
|
||||
for (size_t i = 0; i < spineItemsCount; i++) {
|
||||
std::string spineItem = getSpineItem(i);
|
||||
size_t s = 0;
|
||||
getItemSize(spineItem, &s);
|
||||
spineItemsSize += s;
|
||||
cumulativeSpineItemSize.emplace_back(spineItemsSize);
|
||||
}
|
||||
Serial.printf("[%lu] [EBP] Book size: %u\n", millis(), spineItemsSize);
|
||||
|
||||
initializeSpineItemSizes();
|
||||
Serial.printf("[%lu] [EBP] Loaded ePub: %s\n", millis(), filepath.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Epub::initializeSpineItemSizes() {
|
||||
setupCacheDir();
|
||||
|
||||
size_t spineItemsCount = getSpineItemsCount();
|
||||
size_t cumSpineItemSize = 0;
|
||||
if (SD.exists((getCachePath() + "/spine_size.bin").c_str())) {
|
||||
File f = SD.open((getCachePath() + "/spine_size.bin").c_str());
|
||||
uint8_t data[4];
|
||||
for (size_t i = 0; i < spineItemsCount; i++) {
|
||||
f.read(data, 4);
|
||||
cumSpineItemSize = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
|
||||
cumulativeSpineItemSize.emplace_back(cumSpineItemSize);
|
||||
// Serial.printf("[%lu] [EBP] Loading item %d size %u to %u %u\n", millis(),
|
||||
// i, cumSpineItemSize, data[1], data[0]);
|
||||
}
|
||||
f.close();
|
||||
} else {
|
||||
File f = SD.open((getCachePath() + "/spine_size.bin").c_str(), FILE_WRITE);
|
||||
uint8_t data[4];
|
||||
// determine size of spine items
|
||||
for (size_t i = 0; i < spineItemsCount; i++) {
|
||||
std::string spineItem = getSpineItem(i);
|
||||
size_t s = 0;
|
||||
getItemSize(spineItem, &s);
|
||||
cumSpineItemSize += s;
|
||||
cumulativeSpineItemSize.emplace_back(cumSpineItemSize);
|
||||
|
||||
// and persist to cache
|
||||
data[0] = cumSpineItemSize & 0xFF;
|
||||
data[1] = (cumSpineItemSize >> 8) & 0xFF;
|
||||
data[2] = (cumSpineItemSize >> 16) & 0xFF;
|
||||
data[3] = (cumSpineItemSize >> 24) & 0xFF;
|
||||
// Serial.printf("[%lu] [EBP] Persisting item %d size %u to %u %u\n", millis(),
|
||||
// i, cumSpineItemSize, data[1], data[0]);
|
||||
f.write(data, 4);
|
||||
}
|
||||
|
||||
f.close();
|
||||
}
|
||||
Serial.printf("[%lu] [EBP] Book size: %lu\n", millis(), cumSpineItemSize);
|
||||
}
|
||||
|
||||
bool Epub::clearCache() const {
|
||||
if (!SD.exists(cachePath.c_str())) {
|
||||
Serial.printf("[%lu] [EPB] Cache does not exist, no action needed\n", millis());
|
||||
|
||||
@ -32,6 +32,7 @@ class Epub {
|
||||
bool findContentOpfFile(std::string* contentOpfFile) const;
|
||||
bool parseContentOpf(const std::string& contentOpfFilePath);
|
||||
bool parseTocNcxFile();
|
||||
void initializeSpineItemSizes();
|
||||
|
||||
public:
|
||||
explicit Epub(std::string filepath, const std::string& cacheDir) : filepath(std::move(filepath)) {
|
||||
|
||||
@ -3,11 +3,12 @@
|
||||
#include <GfxRenderer.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "hyphenation/Hyphenator.h"
|
||||
|
||||
constexpr int MAX_COST = std::numeric_limits<int>::max();
|
||||
|
||||
void ParsedText::addWord(std::string word, const EpdFontStyle fontStyle) {
|
||||
@ -24,148 +25,168 @@ void ParsedText::layoutAndExtractLines(const GfxRenderer& renderer, const int fo
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t totalWordCount = words.size();
|
||||
const int pageWidth = renderer.getScreenWidth() - horizontalMargin;
|
||||
if (pageWidth <= 0) {
|
||||
words.clear();
|
||||
wordStyles.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
const int spaceWidth = renderer.getSpaceWidth(fontId);
|
||||
// width of 1em to indent first line of paragraph if Extra Spacing is enabled
|
||||
const int indentWidth = (!extraParagraphSpacing) ? 1 * renderer.getTextWidth(fontId, "m", REGULAR) : 0;
|
||||
const bool allowIndent = !extraParagraphSpacing && (style == TextBlock::JUSTIFIED || style == TextBlock::LEFT_ALIGN);
|
||||
const int indentWidth = allowIndent ? renderer.getTextWidth(fontId, "m", REGULAR) : 0;
|
||||
const int firstLinePageWidth = allowIndent ? std::max(pageWidth - indentWidth, 0) : pageWidth;
|
||||
auto pageWidthForLine = [&](const bool isFirstLine) -> int { return isFirstLine ? firstLinePageWidth : pageWidth; };
|
||||
|
||||
std::vector<uint16_t> wordWidths;
|
||||
wordWidths.reserve(totalWordCount);
|
||||
auto wordIt = words.begin();
|
||||
auto styleIt = wordStyles.begin();
|
||||
auto lineStartWordIt = wordIt;
|
||||
auto lineStartStyleIt = styleIt;
|
||||
|
||||
auto wordsIt = words.begin();
|
||||
auto wordStylesIt = wordStyles.begin();
|
||||
int lineWidthWithSpaces = 0;
|
||||
int lineWordWidthSum = 0;
|
||||
size_t lineWordCount = 0;
|
||||
std::vector<uint16_t> lineWordWidths;
|
||||
lineWordWidths.reserve(16);
|
||||
|
||||
while (wordsIt != words.end()) {
|
||||
wordWidths.push_back(renderer.getTextWidth(fontId, wordsIt->c_str(), *wordStylesIt));
|
||||
|
||||
std::advance(wordsIt, 1);
|
||||
std::advance(wordStylesIt, 1);
|
||||
}
|
||||
|
||||
// DP table to store the minimum badness (cost) of lines starting at index i
|
||||
std::vector<int> dp(totalWordCount);
|
||||
// 'ans[i]' stores the index 'j' of the *last word* in the optimal line starting at 'i'
|
||||
std::vector<size_t> ans(totalWordCount);
|
||||
|
||||
// Base Case
|
||||
dp[totalWordCount - 1] = 0;
|
||||
ans[totalWordCount - 1] = totalWordCount - 1;
|
||||
|
||||
for (int i = totalWordCount - 2; i >= 0; --i) {
|
||||
int currlen = -spaceWidth + indentWidth;
|
||||
dp[i] = MAX_COST;
|
||||
|
||||
for (size_t j = i; j < totalWordCount; ++j) {
|
||||
// Current line length: previous width + space + current word width
|
||||
currlen += wordWidths[j] + spaceWidth;
|
||||
|
||||
if (currlen > pageWidth) {
|
||||
break;
|
||||
}
|
||||
|
||||
int cost;
|
||||
if (j == totalWordCount - 1) {
|
||||
cost = 0; // Last line
|
||||
} else {
|
||||
const int remainingSpace = pageWidth - currlen;
|
||||
// Use long long for the square to prevent overflow
|
||||
const long long cost_ll = static_cast<long long>(remainingSpace) * remainingSpace + dp[j + 1];
|
||||
|
||||
if (cost_ll > MAX_COST) {
|
||||
cost = MAX_COST;
|
||||
} else {
|
||||
cost = static_cast<int>(cost_ll);
|
||||
}
|
||||
}
|
||||
|
||||
if (cost < dp[i]) {
|
||||
dp[i] = cost;
|
||||
ans[i] = j; // j is the index of the last word in this optimal line
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stores the index of the word that starts the next line (last_word_index + 1)
|
||||
std::vector<size_t> lineBreakIndices;
|
||||
size_t currentWordIndex = 0;
|
||||
size_t producedLines = 0;
|
||||
constexpr size_t MAX_LINES = 1000;
|
||||
|
||||
while (currentWordIndex < totalWordCount) {
|
||||
if (lineBreakIndices.size() >= MAX_LINES) {
|
||||
break;
|
||||
auto commitLine = [&](const bool isLastLine) {
|
||||
if (lineWordCount == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t nextBreakIndex = ans[currentWordIndex] + 1;
|
||||
lineBreakIndices.push_back(nextBreakIndex);
|
||||
const bool isFirstLine = producedLines == 0;
|
||||
const int linePageWidth = pageWidthForLine(isFirstLine);
|
||||
|
||||
currentWordIndex = nextBreakIndex;
|
||||
}
|
||||
std::list<std::string> lineWords;
|
||||
std::list<EpdFontStyle> lineStyles;
|
||||
auto wordEndIt = wordIt;
|
||||
auto styleEndIt = styleIt;
|
||||
|
||||
// Initialize iterators for consumption
|
||||
auto wordStartIt = words.begin();
|
||||
auto wordStyleStartIt = wordStyles.begin();
|
||||
size_t wordWidthIndex = 0;
|
||||
lineWords.splice(lineWords.begin(), words, lineStartWordIt, wordEndIt);
|
||||
lineStyles.splice(lineStyles.begin(), wordStyles, lineStartStyleIt, styleEndIt);
|
||||
|
||||
size_t lastBreakAt = 0;
|
||||
for (const size_t lineBreak : lineBreakIndices) {
|
||||
const size_t lineWordCount = lineBreak - lastBreakAt;
|
||||
|
||||
// Calculate end iterators for the range to splice
|
||||
auto wordEndIt = wordStartIt;
|
||||
auto wordStyleEndIt = wordStyleStartIt;
|
||||
std::advance(wordEndIt, lineWordCount);
|
||||
std::advance(wordStyleEndIt, lineWordCount);
|
||||
|
||||
// Calculate total word width for this line
|
||||
int lineWordWidthSum = 0;
|
||||
for (size_t i = 0; i < lineWordCount; ++i) {
|
||||
lineWordWidthSum += wordWidths[wordWidthIndex + i];
|
||||
}
|
||||
|
||||
// Calculate spacing
|
||||
int spareSpace = pageWidth - lineWordWidthSum;
|
||||
if (wordWidthIndex == 0) {
|
||||
spareSpace -= indentWidth;
|
||||
}
|
||||
const int gaps = lineWordCount > 0 ? static_cast<int>(lineWordCount - 1) : 0;
|
||||
const int baseSpaceTotal = spaceWidth * gaps;
|
||||
const int spaceBudget = linePageWidth - lineWordWidthSum;
|
||||
|
||||
int spacing = spaceWidth;
|
||||
const bool isLastLine = lineBreak == totalWordCount;
|
||||
|
||||
if (style == TextBlock::JUSTIFIED && !isLastLine && lineWordCount >= 2) {
|
||||
spacing = spareSpace / (lineWordCount - 1);
|
||||
int spacingRemainder = 0;
|
||||
if (style == TextBlock::JUSTIFIED && !isLastLine && gaps > 0) {
|
||||
const int additional = std::max(0, spaceBudget - baseSpaceTotal);
|
||||
spacing = spaceWidth + (gaps > 0 ? additional / gaps : 0);
|
||||
spacingRemainder = (gaps > 0) ? additional % gaps : 0;
|
||||
}
|
||||
|
||||
// Calculate initial x position
|
||||
uint16_t xpos = (wordWidthIndex == 0) ? indentWidth : 0;
|
||||
int renderedWidth = lineWordWidthSum;
|
||||
if (gaps > 0) {
|
||||
renderedWidth += spacing * gaps;
|
||||
}
|
||||
|
||||
uint16_t xpos = 0;
|
||||
if (style == TextBlock::RIGHT_ALIGN) {
|
||||
xpos = spareSpace - (lineWordCount - 1) * spaceWidth;
|
||||
xpos = renderedWidth < linePageWidth ? linePageWidth - renderedWidth : 0;
|
||||
} else if (style == TextBlock::CENTER_ALIGN) {
|
||||
xpos = (spareSpace - (lineWordCount - 1) * spaceWidth) / 2;
|
||||
xpos = renderedWidth < linePageWidth ? (linePageWidth - renderedWidth) / 2 : 0;
|
||||
} else if (allowIndent && isFirstLine) {
|
||||
xpos = indentWidth;
|
||||
}
|
||||
|
||||
// Pre-calculate X positions for words
|
||||
std::list<uint16_t> lineXPos;
|
||||
for (size_t i = 0; i < lineWordCount; ++i) {
|
||||
const uint16_t currentWordWidth = wordWidths[wordWidthIndex + i];
|
||||
for (size_t idx = 0; idx < lineWordWidths.size(); ++idx) {
|
||||
lineXPos.push_back(xpos);
|
||||
xpos += currentWordWidth + spacing;
|
||||
xpos += lineWordWidths[idx];
|
||||
if (idx + 1 < lineWordWidths.size()) {
|
||||
int gap = spacing;
|
||||
if (spacingRemainder > 0) {
|
||||
gap += 1;
|
||||
spacingRemainder--;
|
||||
}
|
||||
xpos += gap;
|
||||
}
|
||||
}
|
||||
|
||||
// *** CRITICAL STEP: CONSUME DATA USING SPLICE ***
|
||||
std::list<std::string> lineWords;
|
||||
lineWords.splice(lineWords.begin(), words, wordStartIt, wordEndIt);
|
||||
std::list<EpdFontStyle> lineWordStyles;
|
||||
lineWordStyles.splice(lineWordStyles.begin(), wordStyles, wordStyleStartIt, wordStyleEndIt);
|
||||
processLine(std::make_shared<TextBlock>(std::move(lineWords), std::move(lineXPos), std::move(lineStyles), style));
|
||||
|
||||
processLine(
|
||||
std::make_shared<TextBlock>(std::move(lineWords), std::move(lineXPos), std::move(lineWordStyles), style));
|
||||
producedLines++;
|
||||
lineWordWidths.clear();
|
||||
lineWordWidthSum = 0;
|
||||
lineWidthWithSpaces = 0;
|
||||
lineWordCount = 0;
|
||||
lineStartWordIt = wordIt;
|
||||
lineStartStyleIt = styleIt;
|
||||
};
|
||||
|
||||
// Update pointers/indices for the next line
|
||||
wordStartIt = wordEndIt;
|
||||
wordStyleStartIt = wordStyleEndIt;
|
||||
wordWidthIndex += lineWordCount;
|
||||
lastBreakAt = lineBreak;
|
||||
while (wordIt != words.end() && producedLines < MAX_LINES) {
|
||||
const int currentLinePageWidth = pageWidthForLine(producedLines == 0);
|
||||
|
||||
if (lineWordCount == 0) {
|
||||
lineStartWordIt = wordIt;
|
||||
lineStartStyleIt = styleIt;
|
||||
}
|
||||
|
||||
const int wordWidth = renderer.getTextWidth(fontId, wordIt->c_str(), *styleIt);
|
||||
const int gapWidth = (lineWordCount > 0) ? spaceWidth : 0;
|
||||
const int candidateWidth = lineWidthWithSpaces + gapWidth + wordWidth;
|
||||
|
||||
if (candidateWidth <= currentLinePageWidth) {
|
||||
lineWordWidths.push_back(static_cast<uint16_t>(wordWidth));
|
||||
lineWordWidthSum += wordWidth;
|
||||
lineWidthWithSpaces = candidateWidth;
|
||||
lineWordCount++;
|
||||
++wordIt;
|
||||
++styleIt;
|
||||
continue;
|
||||
}
|
||||
|
||||
const int availableWidth = currentLinePageWidth - lineWidthWithSpaces - gapWidth;
|
||||
if (lineWordCount > 0 && availableWidth <= 0) {
|
||||
commitLine(false);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lineWordCount > 0 && availableWidth > 0) {
|
||||
HyphenationResult split;
|
||||
if (Hyphenator::splitWord(renderer, fontId, *wordIt, *styleIt, availableWidth, &split, false)) {
|
||||
*wordIt = std::move(split.head);
|
||||
auto nextWordIt = std::next(wordIt);
|
||||
auto nextStyleIt = std::next(styleIt);
|
||||
words.insert(nextWordIt, std::move(split.tail));
|
||||
wordStyles.insert(nextStyleIt, *styleIt);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (lineWordCount == 0) {
|
||||
HyphenationResult split;
|
||||
if (Hyphenator::splitWord(renderer, fontId, *wordIt, *styleIt, currentLinePageWidth, &split, true)) {
|
||||
*wordIt = std::move(split.head);
|
||||
auto nextWordIt = std::next(wordIt);
|
||||
auto nextStyleIt = std::next(styleIt);
|
||||
words.insert(nextWordIt, std::move(split.tail));
|
||||
wordStyles.insert(nextStyleIt, *styleIt);
|
||||
continue;
|
||||
}
|
||||
|
||||
lineWordWidths.push_back(static_cast<uint16_t>(wordWidth));
|
||||
lineWordWidthSum += wordWidth;
|
||||
lineWidthWithSpaces = candidateWidth;
|
||||
lineWordCount = 1;
|
||||
++wordIt;
|
||||
++styleIt;
|
||||
commitLine(wordIt == words.end());
|
||||
continue;
|
||||
}
|
||||
|
||||
commitLine(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (lineWordCount > 0 && producedLines < MAX_LINES) {
|
||||
commitLine(true);
|
||||
}
|
||||
|
||||
words.clear();
|
||||
wordStyles.clear();
|
||||
}
|
||||
278
lib/Epub/Epub/hyphenation/EnglishHyphenator.cpp
Normal file
278
lib/Epub/Epub/hyphenation/EnglishHyphenator.cpp
Normal file
@ -0,0 +1,278 @@
|
||||
#include "EnglishHyphenator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
char lowerLatinChar(const uint32_t cp) {
|
||||
if (!isLatinLetter(cp)) {
|
||||
return 0;
|
||||
}
|
||||
return static_cast<char>(toLowerLatin(cp));
|
||||
}
|
||||
|
||||
bool isEnglishApproximantChar(const char c) { return c == 'l' || c == 'r' || c == 'w' || c == 'y'; }
|
||||
|
||||
bool isEnglishStopChar(const char c) {
|
||||
switch (c) {
|
||||
case 'p':
|
||||
case 'b':
|
||||
case 't':
|
||||
case 'd':
|
||||
case 'k':
|
||||
case 'g':
|
||||
case 'c':
|
||||
case 'q':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool isEnglishFricativeChar(const char c) {
|
||||
switch (c) {
|
||||
case 'f':
|
||||
case 'v':
|
||||
case 's':
|
||||
case 'z':
|
||||
case 'h':
|
||||
case 'x':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
struct CharPair {
|
||||
char first;
|
||||
char second;
|
||||
};
|
||||
|
||||
bool matchesDigraph(const char first, const char second, const std::initializer_list<CharPair>& pairs) {
|
||||
for (const auto& pair : pairs) {
|
||||
if (pair.first == first && pair.second == second) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isEnglishDiphthong(const uint32_t first, const uint32_t second) {
|
||||
if (!isLatinLetter(first) || !isLatinLetter(second)) {
|
||||
return false;
|
||||
}
|
||||
const auto f = static_cast<char>(toLowerLatin(first));
|
||||
const auto s = static_cast<char>(toLowerLatin(second));
|
||||
switch (f) {
|
||||
case 'a':
|
||||
return s == 'i' || s == 'y' || s == 'u';
|
||||
case 'e':
|
||||
return s == 'a' || s == 'e' || s == 'i' || s == 'o' || s == 'u' || s == 'y';
|
||||
case 'i':
|
||||
return s == 'e' || s == 'u' || s == 'a';
|
||||
case 'o':
|
||||
return s == 'a' || s == 'e' || s == 'i' || s == 'o' || s == 'u' || s == 'y';
|
||||
case 'u':
|
||||
return s == 'i' || s == 'a' || s == 'e';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isValidEnglishOnsetBigram(const uint32_t firstCp, const uint32_t secondCp) {
|
||||
const char first = lowerLatinChar(firstCp);
|
||||
const char second = lowerLatinChar(secondCp);
|
||||
if (!first || !second) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (matchesDigraph(first, second,
|
||||
{{'c', 'h'},
|
||||
{'s', 'h'},
|
||||
{'t', 'h'},
|
||||
{'p', 'h'},
|
||||
{'w', 'h'},
|
||||
{'w', 'r'},
|
||||
{'k', 'n'},
|
||||
{'g', 'n'},
|
||||
{'p', 's'},
|
||||
{'p', 't'},
|
||||
{'p', 'n'},
|
||||
{'r', 'h'}})) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isEnglishStopChar(first) && isEnglishApproximantChar(second)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isEnglishFricativeChar(first) && isEnglishApproximantChar(second)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (first == 's' && (second == 'p' || second == 't' || second == 'k' || second == 'm' || second == 'n' ||
|
||||
second == 'f' || second == 'l' || second == 'w' || second == 'c')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (second == 'y' && (first == 'p' || first == 'b' || first == 't' || first == 'd' || first == 'f' || first == 'k' ||
|
||||
first == 'g' || first == 'h' || first == 'm' || first == 'n' || first == 'l' || first == 's')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isValidEnglishOnsetTrigram(const uint32_t firstCp, const uint32_t secondCp, const uint32_t thirdCp) {
|
||||
const char first = lowerLatinChar(firstCp);
|
||||
const char second = lowerLatinChar(secondCp);
|
||||
const char third = lowerLatinChar(thirdCp);
|
||||
if (!first || !second || !third) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (first == 's') {
|
||||
if (second == 'p' && (third == 'l' || third == 'r' || third == 'w')) {
|
||||
return true;
|
||||
}
|
||||
if (second == 't' && (third == 'r' || third == 'w' || third == 'y')) {
|
||||
return true;
|
||||
}
|
||||
if (second == 'k' && (third == 'l' || third == 'r' || third == 'w')) {
|
||||
return true;
|
||||
}
|
||||
if (second == 'c' && (third == 'l' || third == 'r')) {
|
||||
return true;
|
||||
}
|
||||
if (second == 'f' && third == 'r') {
|
||||
return true;
|
||||
}
|
||||
if (second == 'h' && third == 'r') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (first == 't' && second == 'h' && third == 'r') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool englishClusterIsValidOnset(const std::vector<CodepointInfo>& cps, const size_t start, const size_t end) {
|
||||
if (start >= end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = start; i < end; ++i) {
|
||||
const char ch = lowerLatinChar(cps[i].value);
|
||||
if (!ch) {
|
||||
return false;
|
||||
}
|
||||
if (!isLatinConsonant(cps[i].value) && ch != 'y') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const size_t len = end - start;
|
||||
if (len == 1) {
|
||||
return true;
|
||||
}
|
||||
if (len == 2) {
|
||||
return isValidEnglishOnsetBigram(cps[start].value, cps[start + 1].value);
|
||||
}
|
||||
if (len == 3) {
|
||||
return isValidEnglishOnsetTrigram(cps[start].value, cps[start + 1].value, cps[start + 2].value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t englishOnsetLength(const std::vector<CodepointInfo>& cps, const size_t clusterStart, const size_t clusterEnd) {
|
||||
const size_t clusterLen = clusterEnd - clusterStart;
|
||||
if (clusterLen == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const size_t maxLen = std::min<size_t>(3, clusterLen);
|
||||
for (size_t len = maxLen; len >= 1; --len) {
|
||||
const size_t suffixStart = clusterEnd - len;
|
||||
if (englishClusterIsValidOnset(cps, suffixStart, clusterEnd)) {
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool nextToApostrophe(const std::vector<CodepointInfo>& cps, const size_t index) {
|
||||
if (index == 0 || index >= cps.size()) {
|
||||
return false;
|
||||
}
|
||||
const auto left = cps[index - 1].value;
|
||||
const auto right = cps[index].value;
|
||||
return left == '\'' || right == '\'';
|
||||
}
|
||||
|
||||
std::vector<size_t> englishBreakIndexes(const std::vector<CodepointInfo>& cps) {
|
||||
std::vector<size_t> indexes;
|
||||
if (cps.size() < MIN_PREFIX_CP + MIN_SUFFIX_CP) {
|
||||
return indexes;
|
||||
}
|
||||
|
||||
std::vector<size_t> vowelPositions;
|
||||
vowelPositions.reserve(cps.size());
|
||||
for (size_t i = 0; i < cps.size(); ++i) {
|
||||
if (isLatinVowel(cps[i].value)) {
|
||||
vowelPositions.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (vowelPositions.size() < 2) {
|
||||
return indexes;
|
||||
}
|
||||
|
||||
for (size_t v = 0; v + 1 < vowelPositions.size(); ++v) {
|
||||
const size_t leftVowel = vowelPositions[v];
|
||||
const size_t rightVowel = vowelPositions[v + 1];
|
||||
|
||||
if (rightVowel - leftVowel == 1) {
|
||||
if (!isEnglishDiphthong(cps[leftVowel].value, cps[rightVowel].value) && rightVowel >= MIN_PREFIX_CP &&
|
||||
cps.size() - rightVowel >= MIN_SUFFIX_CP && !nextToApostrophe(cps, rightVowel)) {
|
||||
indexes.push_back(rightVowel);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t clusterStart = leftVowel + 1;
|
||||
const size_t clusterEnd = rightVowel;
|
||||
const size_t onsetLen = englishOnsetLength(cps, clusterStart, clusterEnd);
|
||||
size_t breakIndex = clusterEnd - onsetLen;
|
||||
|
||||
if (breakIndex < MIN_PREFIX_CP || cps.size() - breakIndex < MIN_SUFFIX_CP) {
|
||||
continue;
|
||||
}
|
||||
if (nextToApostrophe(cps, breakIndex)) {
|
||||
continue;
|
||||
}
|
||||
indexes.push_back(breakIndex);
|
||||
}
|
||||
|
||||
std::sort(indexes.begin(), indexes.end());
|
||||
indexes.erase(std::unique(indexes.begin(), indexes.end()), indexes.end());
|
||||
return indexes;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const EnglishHyphenator& EnglishHyphenator::instance() {
|
||||
static EnglishHyphenator instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
Script EnglishHyphenator::script() const { return Script::Latin; }
|
||||
|
||||
std::vector<size_t> EnglishHyphenator::breakIndexes(const std::vector<CodepointInfo>& cps) const {
|
||||
return englishBreakIndexes(cps);
|
||||
}
|
||||
14
lib/Epub/Epub/hyphenation/EnglishHyphenator.h
Normal file
14
lib/Epub/Epub/hyphenation/EnglishHyphenator.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "LanguageHyphenator.h"
|
||||
|
||||
class EnglishHyphenator final : public LanguageHyphenator {
|
||||
public:
|
||||
static const EnglishHyphenator& instance();
|
||||
|
||||
Script script() const override;
|
||||
std::vector<size_t> breakIndexes(const std::vector<CodepointInfo>& cps) const override;
|
||||
|
||||
private:
|
||||
EnglishHyphenator() = default;
|
||||
};
|
||||
82
lib/Epub/Epub/hyphenation/HyphenationCommon.cpp
Normal file
82
lib/Epub/Epub/hyphenation/HyphenationCommon.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
#include "HyphenationCommon.h"
|
||||
|
||||
namespace {
|
||||
|
||||
uint32_t toLowerLatinImpl(const uint32_t cp) {
|
||||
if (cp >= 'A' && cp <= 'Z') {
|
||||
return cp - 'A' + 'a';
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
uint32_t toLowerCyrillicImpl(const uint32_t cp) {
|
||||
if (cp >= 0x0410 && cp <= 0x042F) {
|
||||
return cp + 0x20;
|
||||
}
|
||||
if (cp == 0x0401) {
|
||||
return 0x0451;
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
uint32_t toLowerLatin(const uint32_t cp) { return toLowerLatinImpl(cp); }
|
||||
|
||||
uint32_t toLowerCyrillic(const uint32_t cp) { return toLowerCyrillicImpl(cp); }
|
||||
|
||||
bool isLatinLetter(const uint32_t cp) { return (cp >= 'A' && cp <= 'Z') || (cp >= 'a' && cp <= 'z'); }
|
||||
|
||||
bool isLatinVowel(uint32_t cp) {
|
||||
cp = toLowerLatinImpl(cp);
|
||||
return cp == 'a' || cp == 'e' || cp == 'i' || cp == 'o' || cp == 'u' || cp == 'y';
|
||||
}
|
||||
|
||||
bool isLatinConsonant(const uint32_t cp) { return isLatinLetter(cp) && !isLatinVowel(cp); }
|
||||
|
||||
bool isCyrillicLetter(const uint32_t cp) { return (cp >= 0x0400 && cp <= 0x052F); }
|
||||
|
||||
bool isCyrillicVowel(uint32_t cp) {
|
||||
cp = toLowerCyrillicImpl(cp);
|
||||
switch (cp) {
|
||||
case 0x0430: // а
|
||||
case 0x0435: // е
|
||||
case 0x0451: // ё
|
||||
case 0x0438: // и
|
||||
case 0x043E: // о
|
||||
case 0x0443: // у
|
||||
case 0x044B: // ы
|
||||
case 0x044D: // э
|
||||
case 0x044E: // ю
|
||||
case 0x044F: // я
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool isCyrillicConsonant(const uint32_t cp) { return isCyrillicLetter(cp) && !isCyrillicVowel(cp); }
|
||||
|
||||
bool isAlphabetic(const uint32_t cp) { return isLatinLetter(cp) || isCyrillicLetter(cp); }
|
||||
|
||||
bool isVowel(const uint32_t cp) { return isLatinVowel(cp) || isCyrillicVowel(cp); }
|
||||
|
||||
Script detectScript(const std::vector<CodepointInfo>& cps) {
|
||||
bool hasLatin = false;
|
||||
bool hasCyrillic = false;
|
||||
for (const auto& info : cps) {
|
||||
if (isLatinLetter(info.value)) {
|
||||
hasLatin = true;
|
||||
} else if (isCyrillicLetter(info.value)) {
|
||||
hasCyrillic = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasLatin && !hasCyrillic) {
|
||||
return Script::Latin;
|
||||
}
|
||||
if (!hasLatin && hasCyrillic) {
|
||||
return Script::Cyrillic;
|
||||
}
|
||||
return Script::Mixed;
|
||||
}
|
||||
31
lib/Epub/Epub/hyphenation/HyphenationCommon.h
Normal file
31
lib/Epub/Epub/hyphenation/HyphenationCommon.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
struct CodepointInfo {
|
||||
uint32_t value;
|
||||
size_t byteOffset;
|
||||
};
|
||||
|
||||
enum class Script { Latin, Cyrillic, Mixed };
|
||||
|
||||
constexpr size_t MIN_PREFIX_CP = 3;
|
||||
constexpr size_t MIN_SUFFIX_CP = 2;
|
||||
|
||||
uint32_t toLowerLatin(uint32_t cp);
|
||||
uint32_t toLowerCyrillic(uint32_t cp);
|
||||
|
||||
bool isLatinLetter(uint32_t cp);
|
||||
bool isLatinVowel(uint32_t cp);
|
||||
bool isLatinConsonant(uint32_t cp);
|
||||
|
||||
bool isCyrillicLetter(uint32_t cp);
|
||||
bool isCyrillicVowel(uint32_t cp);
|
||||
bool isCyrillicConsonant(uint32_t cp);
|
||||
|
||||
bool isAlphabetic(uint32_t cp);
|
||||
bool isVowel(uint32_t cp);
|
||||
|
||||
Script detectScript(const std::vector<CodepointInfo>& cps);
|
||||
158
lib/Epub/Epub/hyphenation/Hyphenator.cpp
Normal file
158
lib/Epub/Epub/hyphenation/Hyphenator.cpp
Normal file
@ -0,0 +1,158 @@
|
||||
#include "Hyphenator.h"
|
||||
|
||||
#include <GfxRenderer.h>
|
||||
#include <Utf8.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include "EnglishHyphenator.h"
|
||||
#include "HyphenationCommon.h"
|
||||
#include "LanguageHyphenator.h"
|
||||
#include "RussianHyphenator.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const std::array<const LanguageHyphenator*, 2>& registeredHyphenators() {
|
||||
static const std::array<const LanguageHyphenator*, 2> hyphenators = {
|
||||
&EnglishHyphenator::instance(),
|
||||
&RussianHyphenator::instance(),
|
||||
};
|
||||
return hyphenators;
|
||||
}
|
||||
|
||||
const LanguageHyphenator* hyphenatorForScript(const Script script) {
|
||||
for (const auto* hyphenator : registeredHyphenators()) {
|
||||
if (hyphenator->script() == script) {
|
||||
return hyphenator;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<CodepointInfo> collectCodepoints(const std::string& word) {
|
||||
std::vector<CodepointInfo> cps;
|
||||
cps.reserve(word.size());
|
||||
|
||||
const unsigned char* base = reinterpret_cast<const unsigned char*>(word.c_str());
|
||||
const unsigned char* ptr = base;
|
||||
while (*ptr != 0) {
|
||||
const unsigned char* current = ptr;
|
||||
const uint32_t cp = utf8NextCodepoint(&ptr);
|
||||
cps.push_back({cp, static_cast<size_t>(current - base)});
|
||||
}
|
||||
|
||||
return cps;
|
||||
}
|
||||
|
||||
bool hasOnlyAlphabetic(const std::vector<CodepointInfo>& cps) {
|
||||
if (cps.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& info : cps) {
|
||||
if (!isAlphabetic(info.value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<size_t> collectBreakIndexes(const std::vector<CodepointInfo>& cps) {
|
||||
if (cps.size() < MIN_PREFIX_CP + MIN_SUFFIX_CP) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const Script script = detectScript(cps);
|
||||
if (const auto* hyphenator = hyphenatorForScript(script)) {
|
||||
auto indexes = hyphenator->breakIndexes(cps);
|
||||
return indexes;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
size_t byteOffsetForIndex(const std::vector<CodepointInfo>& cps, const size_t index) {
|
||||
if (index >= cps.size()) {
|
||||
return cps.empty() ? 0 : cps.back().byteOffset;
|
||||
}
|
||||
return cps[index].byteOffset;
|
||||
}
|
||||
|
||||
std::string slice(const std::string& word, const size_t startByte, const size_t endByte) {
|
||||
if (startByte >= endByte || startByte >= word.size()) {
|
||||
return std::string();
|
||||
}
|
||||
const size_t boundedEnd = std::min(endByte, word.size());
|
||||
return word.substr(startByte, boundedEnd - startByte);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool Hyphenator::splitWord(const GfxRenderer& renderer, const int fontId, const std::string& word,
|
||||
const EpdFontStyle style, const int availableWidth, HyphenationResult* result,
|
||||
const bool force) {
|
||||
if (!result || word.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto cps = collectCodepoints(word);
|
||||
if (cps.size() < MIN_PREFIX_CP + MIN_SUFFIX_CP) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!force && !hasOnlyAlphabetic(cps)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto breakIndexes = collectBreakIndexes(cps);
|
||||
const int hyphenWidth = renderer.getTextWidth(fontId, "-", style);
|
||||
const int adjustedWidth = availableWidth - hyphenWidth;
|
||||
|
||||
size_t chosenIndex = std::numeric_limits<size_t>::max();
|
||||
|
||||
if (adjustedWidth > 0) {
|
||||
for (const size_t idx : breakIndexes) {
|
||||
const size_t byteOffset = byteOffsetForIndex(cps, idx);
|
||||
const std::string prefix = word.substr(0, byteOffset);
|
||||
const int prefixWidth = renderer.getTextWidth(fontId, prefix.c_str(), style);
|
||||
if (prefixWidth <= adjustedWidth) {
|
||||
chosenIndex = idx;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (chosenIndex == std::numeric_limits<size_t>::max() && force) {
|
||||
for (size_t idx = MIN_PREFIX_CP; idx + MIN_SUFFIX_CP <= cps.size(); ++idx) {
|
||||
const size_t byteOffset = byteOffsetForIndex(cps, idx);
|
||||
const std::string prefix = word.substr(0, byteOffset);
|
||||
const int prefixWidth = renderer.getTextWidth(fontId, prefix.c_str(), style);
|
||||
if (adjustedWidth <= 0 || prefixWidth <= adjustedWidth) {
|
||||
chosenIndex = idx;
|
||||
if (adjustedWidth > 0 && prefixWidth > adjustedWidth) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (chosenIndex == std::numeric_limits<size_t>::max()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t splitByte = byteOffsetForIndex(cps, chosenIndex);
|
||||
const std::string head = word.substr(0, splitByte);
|
||||
const std::string tail = slice(word, splitByte, word.size());
|
||||
|
||||
if (head.empty() || tail.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result->head = head + "-";
|
||||
result->tail = tail;
|
||||
return true;
|
||||
}
|
||||
18
lib/Epub/Epub/hyphenation/Hyphenator.h
Normal file
18
lib/Epub/Epub/hyphenation/Hyphenator.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <EpdFontFamily.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
class GfxRenderer;
|
||||
|
||||
struct HyphenationResult {
|
||||
std::string head;
|
||||
std::string tail;
|
||||
};
|
||||
|
||||
class Hyphenator {
|
||||
public:
|
||||
static bool splitWord(const GfxRenderer& renderer, int fontId, const std::string& word, EpdFontStyle style,
|
||||
int availableWidth, HyphenationResult* result, bool force);
|
||||
};
|
||||
12
lib/Epub/Epub/hyphenation/LanguageHyphenator.h
Normal file
12
lib/Epub/Epub/hyphenation/LanguageHyphenator.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "HyphenationCommon.h"
|
||||
|
||||
class LanguageHyphenator {
|
||||
public:
|
||||
virtual ~LanguageHyphenator() = default;
|
||||
virtual Script script() const = 0;
|
||||
virtual std::vector<size_t> breakIndexes(const std::vector<CodepointInfo>& cps) const = 0;
|
||||
};
|
||||
199
lib/Epub/Epub/hyphenation/RussianHyphenator.cpp
Normal file
199
lib/Epub/Epub/hyphenation/RussianHyphenator.cpp
Normal file
@ -0,0 +1,199 @@
|
||||
#include "RussianHyphenator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
bool isSoftOrHardSign(const uint32_t cp) { return cp == 0x044C || cp == 0x042C || cp == 0x044A || cp == 0x042A; }
|
||||
|
||||
bool isRussianPrefixConsonant(uint32_t cp) {
|
||||
cp = toLowerCyrillic(cp);
|
||||
return cp == 0x0432 || cp == 0x0437 || cp == 0x0441; // в, з, с
|
||||
}
|
||||
|
||||
bool isRussianSibilant(uint32_t cp) {
|
||||
cp = toLowerCyrillic(cp);
|
||||
switch (cp) {
|
||||
case 0x0437: // з
|
||||
case 0x0441: // с
|
||||
case 0x0436: // ж
|
||||
case 0x0448: // ш
|
||||
case 0x0449: // щ
|
||||
case 0x0447: // ч
|
||||
case 0x0446: // ц
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool isRussianStop(uint32_t cp) {
|
||||
cp = toLowerCyrillic(cp);
|
||||
switch (cp) {
|
||||
case 0x0431: // б
|
||||
case 0x0433: // г
|
||||
case 0x0434: // д
|
||||
case 0x043F: // п
|
||||
case 0x0442: // т
|
||||
case 0x043A: // к
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int russianSonority(uint32_t cp) {
|
||||
cp = toLowerCyrillic(cp);
|
||||
switch (cp) {
|
||||
case 0x043B: // л
|
||||
case 0x0440: // р
|
||||
case 0x0439: // й
|
||||
return 4;
|
||||
case 0x043C: // м
|
||||
case 0x043D: // н
|
||||
return 3;
|
||||
case 0x0432: // в
|
||||
case 0x0437: // з
|
||||
case 0x0436: // ж
|
||||
return 2;
|
||||
case 0x0444: // ф
|
||||
case 0x0441: // с
|
||||
case 0x0448: // ш
|
||||
case 0x0449: // щ
|
||||
case 0x0447: // ч
|
||||
case 0x0446: // ц
|
||||
case 0x0445: // х
|
||||
return 1;
|
||||
case 0x0431: // б
|
||||
case 0x0433: // г
|
||||
case 0x0434: // д
|
||||
case 0x043F: // п
|
||||
case 0x0442: // т
|
||||
case 0x043A: // к
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool russianClusterIsValidOnset(const std::vector<CodepointInfo>& cps, const size_t start, const size_t end) {
|
||||
if (start >= end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = start; i < end; ++i) {
|
||||
const auto cp = cps[i].value;
|
||||
if (!isCyrillicConsonant(cp) || isSoftOrHardSign(cp)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (end - start == 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (size_t i = start; i + 1 < end; ++i) {
|
||||
const uint32_t current = cps[i].value;
|
||||
const uint32_t next = cps[i + 1].value;
|
||||
const int currentRank = russianSonority(current);
|
||||
const int nextRank = russianSonority(next);
|
||||
if (currentRank > nextRank) {
|
||||
const bool atClusterStart = (i == start);
|
||||
const bool prefixAllowance = atClusterStart && isRussianPrefixConsonant(current);
|
||||
const bool sibilantAllowance = isRussianSibilant(current) && isRussianStop(next);
|
||||
if (!prefixAllowance && !sibilantAllowance) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t russianOnsetLength(const std::vector<CodepointInfo>& cps, const size_t clusterStart, const size_t clusterEnd) {
|
||||
const size_t clusterLen = clusterEnd - clusterStart;
|
||||
if (clusterLen == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const size_t maxLen = std::min<size_t>(4, clusterLen);
|
||||
for (size_t len = maxLen; len >= 1; --len) {
|
||||
const size_t suffixStart = clusterEnd - len;
|
||||
if (russianClusterIsValidOnset(cps, suffixStart, clusterEnd)) {
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool nextToSoftSign(const std::vector<CodepointInfo>& cps, const size_t index) {
|
||||
if (index == 0 || index >= cps.size()) {
|
||||
return false;
|
||||
}
|
||||
const auto left = cps[index - 1].value;
|
||||
const auto right = cps[index].value;
|
||||
return isSoftOrHardSign(left) || isSoftOrHardSign(right);
|
||||
}
|
||||
|
||||
std::vector<size_t> russianBreakIndexes(const std::vector<CodepointInfo>& cps) {
|
||||
std::vector<size_t> indexes;
|
||||
if (cps.size() < MIN_PREFIX_CP + MIN_SUFFIX_CP) {
|
||||
return indexes;
|
||||
}
|
||||
|
||||
std::vector<size_t> vowelPositions;
|
||||
vowelPositions.reserve(cps.size());
|
||||
for (size_t i = 0; i < cps.size(); ++i) {
|
||||
if (isCyrillicVowel(cps[i].value)) {
|
||||
vowelPositions.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (vowelPositions.size() < 2) {
|
||||
return indexes;
|
||||
}
|
||||
|
||||
for (size_t v = 0; v + 1 < vowelPositions.size(); ++v) {
|
||||
const size_t leftVowel = vowelPositions[v];
|
||||
const size_t rightVowel = vowelPositions[v + 1];
|
||||
|
||||
if (rightVowel - leftVowel == 1) {
|
||||
if (rightVowel >= MIN_PREFIX_CP && cps.size() - rightVowel >= MIN_SUFFIX_CP && !nextToSoftSign(cps, rightVowel)) {
|
||||
indexes.push_back(rightVowel);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t clusterStart = leftVowel + 1;
|
||||
const size_t clusterEnd = rightVowel;
|
||||
const size_t onsetLen = russianOnsetLength(cps, clusterStart, clusterEnd);
|
||||
size_t breakIndex = clusterEnd - onsetLen;
|
||||
|
||||
if (breakIndex < MIN_PREFIX_CP || cps.size() - breakIndex < MIN_SUFFIX_CP) {
|
||||
continue;
|
||||
}
|
||||
if (nextToSoftSign(cps, breakIndex)) {
|
||||
continue;
|
||||
}
|
||||
indexes.push_back(breakIndex);
|
||||
}
|
||||
|
||||
std::sort(indexes.begin(), indexes.end());
|
||||
indexes.erase(std::unique(indexes.begin(), indexes.end()), indexes.end());
|
||||
return indexes;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const RussianHyphenator& RussianHyphenator::instance() {
|
||||
static RussianHyphenator instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
Script RussianHyphenator::script() const { return Script::Cyrillic; }
|
||||
|
||||
std::vector<size_t> RussianHyphenator::breakIndexes(const std::vector<CodepointInfo>& cps) const {
|
||||
return russianBreakIndexes(cps);
|
||||
}
|
||||
14
lib/Epub/Epub/hyphenation/RussianHyphenator.h
Normal file
14
lib/Epub/Epub/hyphenation/RussianHyphenator.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "LanguageHyphenator.h"
|
||||
|
||||
class RussianHyphenator final : public LanguageHyphenator {
|
||||
public:
|
||||
static const RussianHyphenator& instance();
|
||||
|
||||
Script script() const override;
|
||||
std::vector<size_t> breakIndexes(const std::vector<CodepointInfo>& cps) const override;
|
||||
|
||||
private:
|
||||
RussianHyphenator() = default;
|
||||
};
|
||||
@ -211,8 +211,6 @@ void EpubReaderActivity::renderScreen() {
|
||||
Serial.printf("[%lu] [ERS] Cache not found, building...\n", millis());
|
||||
|
||||
{
|
||||
renderer.grayscaleRevert();
|
||||
|
||||
const int textWidth = renderer.getTextWidth(READER_FONT_ID, "Indexing...");
|
||||
constexpr int margin = 20;
|
||||
// Round all coordinates to 8 pixel boundaries
|
||||
@ -220,11 +218,10 @@ void EpubReaderActivity::renderScreen() {
|
||||
constexpr int y = 56;
|
||||
const int w = (textWidth + margin * 2 + 7) / 8 * 8;
|
||||
const int h = (renderer.getLineHeight(READER_FONT_ID) + margin * 2 + 7) / 8 * 8;
|
||||
renderer.fillRect(x, y, w, h, false);
|
||||
renderer.clearScreen();
|
||||
renderer.drawText(READER_FONT_ID, x + margin, y + margin, "Indexing...");
|
||||
renderer.drawRect(x + 5, y + 5, w - 10, h - 10);
|
||||
// EXPERIMENTAL: Still suffers from ghosting
|
||||
renderer.displayWindow(x, y, w, h);
|
||||
renderer.displayBuffer();
|
||||
pagesUntilFullRefresh = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
* "./lib/EpdFont/builtinFonts/bookerly_italic_2b.h",
|
||||
* ].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
|
||||
*/
|
||||
#define READER_FONT_ID 828106571
|
||||
#define READER_FONT_ID 1818981670
|
||||
|
||||
/**
|
||||
* Generated with:
|
||||
@ -18,7 +18,7 @@
|
||||
* "./lib/EpdFont/builtinFonts/ubuntu_bold_10.h",
|
||||
* ].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
|
||||
*/
|
||||
#define UI_FONT_ID -56235187
|
||||
#define UI_FONT_ID (-1619831379)
|
||||
|
||||
/**
|
||||
* Generated with:
|
||||
@ -26,4 +26,4 @@
|
||||
* "./lib/EpdFont/builtinFonts/pixelarial14.h",
|
||||
* ].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
|
||||
*/
|
||||
#define SMALL_FONT_ID -1952330053
|
||||
#define SMALL_FONT_ID (-139796914)
|
||||
|
||||
@ -216,7 +216,7 @@ void loop() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (inputManager.wasReleased(InputManager::BTN_POWER) && inputManager.getHeldTime() > POWER_BUTTON_WAKEUP_MS) {
|
||||
if (inputManager.wasReleased(InputManager::BTN_POWER) && inputManager.getHeldTime() > POWER_BUTTON_SLEEP_MS) {
|
||||
enterDeepSleep();
|
||||
// This should never be hit as `enterDeepSleep` calls esp_deep_sleep_start
|
||||
return;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user