Compare commits

...
24 Commits
Author SHA1 Message Date
Dave Allie 5d68c8b305 Cut release 0.6.0
Compile Release / build-release (push) Canceled after 0s
2025-12-16 23:15:47 +11:00
Jonas Diemer def7abbd60 Improve indent (#28)
* add horizontal indent in first line of paragraph in case Extra Paragraph Spacing is OFF

* Treat tabs as whitespace (so they are properly stripped)

* Changed size of indent to 1 em.

* Fixed calculation of space when indenting (avoiding squeezed text).

* Source code formatting
2025-12-16 23:02:32 +11:00
Jonas Diemer 9ad8111ce7 Wrap-around navigation in Settings. (#31) 2025-12-16 22:54:16 +11:00
Arthur Tazhitdinov 57d1939be7 Add Cyrillic range to fonts (#27)
* Enhance TOC parsing and chapter selection logic

- Update .gitignore to include additional paths
- Refactor Epub::parseContentOpf to improve NCX item retrieval
- Modify ContentOpfParser to store media type in ManifestItem
- Implement rebuildVisibleSpineIndices in EpubReaderChapterSelectionScreen for better chapter navigation
- Adjust rendering logic to handle empty chapter lists gracefully

* Refactor TOC parsing logic to streamline cover image and NCX item retrieval

* add cyrillic ranges

* revert

* clang format fix
2025-12-16 22:52:49 +11:00
Jonas Diemer 012992f904 Feature/auto poweroff (#32)
* Automatically deep sleep after 10 minutes of inactivity.

* formatting.
2025-12-16 22:49:31 +11:00
Dave Allie c262f222de Parse cover image path from content.opf file (#24) 2025-12-16 03:15:54 +11:00
Dave Allie 449b3ca161 Fixed light gray text rendering 2025-12-16 02:16:38 +11:00
Dave Allie 6989035ef8 Run CI action on PR as well as push 2025-12-15 23:17:35 +11:00
Dave Allie 108cf57202 Fix formatting 2025-12-15 23:17:23 +11:00
Jonas Diemer a640fbecf8 Settings Screen and first 2 settings (#18)
* white sleep screen

* quicker pwr button

* no extra spacing between paragraphs

* Added settings class with de/serialization and whiteSleepScreen setting to control inverting the sleep screen

* Added Settings screen for real, made settings a global singleton

* Added setting for extra paragraph spacing.

* fixed typo

* Rework after feedback

* Fixed type from bool to uint8
2025-12-15 23:16:46 +11:00
Dave Allie 7a5719b46d Upgrade open-x4-sdk to fix white streaks on sleep screen (#21)
https://github.com/open-x4-epaper/community-sdk/pull/6 fixes a power down issue with the display which was causing streaks to appear on the sleep screen
2025-12-15 22:27:27 +11:00
Dave Allie 8c3576e397 Add Github Action to build release firmware on tag (#20) 2025-12-15 20:00:34 +11:00
Dave Allie fdb5634ea6 Add cppcheck and formatter to CI (#19)
* Add cppcheck and formatter to CI

* Checkout submodules

* Install matching clang-format version in CI
2025-12-15 19:46:52 +11:00
Dave Allie 5cabba7712 Add Github templates
Added Github templates for PRs and bugs
Also added one for funding, please do not feel obligated to
donate to the project, this is not a for-profit endevour, I
just had someone ask where they could send a few dollars so
I have set it up
2025-12-15 08:16:59 +11:00
Dave Allie a86d405fb0 Add comparison images 2025-12-14 13:46:15 +11:00
Dave Allie e4b5dc0e6a Update contribution instructions 2025-12-14 13:46:03 +11:00
Dave Allie dfc74f94c2 Cut release 0.5.1 2025-12-13 21:52:48 +11:00
Dave Allie 3518cbb56d Add user guide 2025-12-13 21:52:03 +11:00
Dave Allie 8994953254 Add chapter selection screen 2025-12-13 21:17:34 +11:00
Dave Allie ead39fd04b Return -1 from getTocIndexForSpineIndex if TOC item does not exist 2025-12-13 21:17:22 +11:00
Dave Allie 5a7381a0eb Cut release 0.5.0 2025-12-13 20:16:12 +11:00
Dave Allie f69fc90b5c Show end of book screen when navigating past last page 2025-12-13 20:10:38 +11:00
Dave Allie 5bae283838 Process lines into pages as they are built 2025-12-13 20:10:16 +11:00
Dave Allie c7a32fe41f Remove tinyxml2 dependency replace with expat parsers (#9) 2025-12-13 19:36:01 +11:00
57 changed files with 20572 additions and 11395 deletions
+2
View File
@@ -0,0 +1,2 @@
github: [daveallie]
ko_fi: daveallie
+54
View File
@@ -0,0 +1,54 @@
name: Bug Report
description: Report an issue or unexpected behavior
title: "Short, descriptive title of the issue"
labels: ["bug", "triage"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to report this bug! Please fill out the details below.
- type: input
id: version
attributes:
label: Affected Version
description: What version of the project/library are you using? (e.g., v1.2.3, master branch commit SHA)
placeholder: Ex. v1.2.3
validations:
required: true
- type: textarea
id: bug-description
attributes:
label: Describe the Bug
description: A clear and concise description of what the bug is.
placeholder:
validations:
required: true
- type: textarea
id: steps-to-reproduce
attributes:
label: Steps to Reproduce
description: Clearly list the steps necessary to reproduce the unexpected behavior.
placeholder: |
1. Go to '...'
2. Select '...'
3. Crash
validations:
required: true
- type: textarea
id: expected-behavior
attributes:
label: Expected Behavior
description: A clear and concise description of what you expected to happen.
validations:
required: true
- type: textarea
id: logs
attributes:
label: Relevant Log Output/Screenshots
description: If applicable, error messages, or log output to help explain your problem. You can drag and drop images here.
render: shell
+9
View File
@@ -0,0 +1,9 @@
## Summary
* **What is the goal of this PR?** (e.g., Fixes a bug in the user authentication module, Implements the new feature for
file uploading.)
* **What changes are included?**
## Additional Context
* Add any other information that might be helpful for the reviewer (e.g., performance implications, potential risks, specific areas to focus on).
+43
View File
@@ -0,0 +1,43 @@
name: CI
'on':
push:
branches: [master]
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- uses: actions/cache@v5
with:
path: |
~/.cache/pip
~/.platformio/.cache
key: ${{ runner.os }}-pio
- uses: actions/setup-python@v6
with:
python-version: '3.14'
- name: Install PlatformIO Core
run: pip install --upgrade platformio
- name: Install clang-format-21
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 21
sudo apt-get update
sudo apt-get install -y clang-format-21
- name: Run cppcheck
run: pio check --fail-on-defect medium --fail-on-defect high
- name: Run clang-format
run: PATH="/usr/lib/llvm-21/bin:$PATH" ./bin/clang-format-fix && git diff --exit-code || (echo "Please run 'bin/clang-format-fix' to fix formatting issues" && exit 1)
- name: Build CrossPoint
run: pio run
+40
View File
@@ -0,0 +1,40 @@
name: Compile Release
on:
push:
tags:
- '*'
jobs:
build-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- uses: actions/cache@v5
with:
path: |
~/.cache/pip
~/.platformio/.cache
key: ${{ runner.os }}-pio
- uses: actions/setup-python@v6
with:
python-version: '3.14'
- name: Install PlatformIO Core
run: pip install --upgrade platformio
- name: Build CrossPoint
run: pio run -e gh_release
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: CrossPoint-${{ github.ref_name }}
path: |
.pio/build/gh_release/bootloader.bin
.pio/build/gh_release/firmware.bin
.pio/build/gh_release/firmware.elf
.pio/build/gh_release/firmware.map
.pio/build/gh_release/partitions.bin
+2
View File
@@ -1,3 +1,5 @@
.pio .pio
.idea .idea
.DS_Store .DS_Store
.vscode
lib/EpdFont/fontsrc
+8 -1
View File
@@ -6,7 +6,7 @@ Built using **PlatformIO** and targeting the **ESP32-C3** microcontroller.
CrossPoint Reader is a purpose-built firmware designed to be a drop-in, fully open-source replacement for the official CrossPoint Reader is a purpose-built firmware designed to be a drop-in, fully open-source replacement for the official
Xteink firmware. It aims to match or improve upon the standard EPUB reading experience. Xteink firmware. It aims to match or improve upon the standard EPUB reading experience.
![](./docs/cover.jpg) ![](./docs/images/cover.jpg)
## Motivation ## Motivation
@@ -59,6 +59,10 @@ back to the other partition using the "Swap boot partition" button here https://
See [Development](#development) below. See [Development](#development) below.
## Usage
See [the user guide](./USER_GUIDE.md) for instructions on operating CrossPoint.
## Development ## Development
### Prerequisites ### Prerequisites
@@ -127,6 +131,9 @@ EPUB file will reset the reading progress.
Contributions are very welcome! Contributions are very welcome!
If you're looking for a way to help out, take a look at the [ideas discussion board](https://github.com/daveallie/crosspoint-reader/discussions/categories/ideas).
If there's something there you'd like to work on, leave a comment so that we can avoid duplicated effort.
### To submit a contribution: ### To submit a contribution:
1. Fork the repo 1. Fork the repo
+78
View File
@@ -0,0 +1,78 @@
# CrossPoint User Guide
Welcome to the **CrossPoint** firmware. This guide outlines the hardware controls, navigation, and reading features of
the device.
## 1. Hardware Overview
The device utilises the standard buttons on the Xtink X4 in the same layout:
### Button Layout
| Location | Buttons |
|-----------------|--------------------------------------------|
| **Bottom Edge** | **Back**, **Confirm**, **Left**, **Right** |
| **Right Side** | **Power**, **Volume Up**, **Volume Down** |
---
## 2. Power & Startup
### Power On / Off
To turn the device on or off, **press and hold the Power button for 1 full second**.
### First Launch
Upon turning the device on for the first time, you will be placed on the **Book Selection Screen** (File Browser).
> **Note:** On subsequent restarts, the firmware will automatically reopen the last book you were reading.
---
## 3. Book Selection
The Home Screen acts as a folder and file browser.
* **Navigate List:** Use **Left** (or **Volume Up**), or **Right** (or **Volume Down**) to move the selection cursor up
and down through folders and books.
* **Open Selection:** Press **Confirm** to open a folder or read a selected book.
---
## 4. Reading Mode
Once you have opened a book, the button layout changes to facilitate reading.
### Page Turning
| Action | Buttons |
|-------------------|--------------------------------------|
| **Previous Page** | Press **Left** _or_ **Volume Up** |
| **Next Page** | Press **Right** _or_ **Volume Down** |
### Chapter Navigation
* **Next Chapter:** Press and **hold** the **Right** (or **Volume Down**) button briefly, then release.
* **Previous Chapter:** Press and **hold** the **Left** (or **Volume Up**) button briefly, then release.
### System Navigation
* **Return to Home:** Press **Back** to close the book and return to the Book Selection screen.
* **Chapter Menu:** Press **Confirm** to open the Table of Contents/Chapter Selection screen.
---
## 5. Chapter Selection Screen
Accessible by pressing **Confirm** while inside a book.
1. Use **Left** (or **Volume Up**), or **Right** (or **Volume Down**) to highlight the desired chapter.
2. Press **Confirm** to jump to that chapter.
3. *Alternatively, press **Back** to cancel and return to your current page.*
---
## 6. Current Limitations & Roadmap
Please note that this firmware is currently in active development. The following features are **not yet supported** but
are planned for future updates:
* **Images:** Embedded images in e-books will not render.
* **Text Formatting:** There are currently no settings to adjust font type, size, line spacing, or margins.
+19
View File
@@ -0,0 +1,19 @@
# CrossPoint vs XTOS
Below is like for like comparison of CrossPoint (version 0.5.1) and XTOS (version 3.1.1). CrossPoint is on the left,
XTOS is on the right. CrossPoint does not currently support all features of XTOS, so this comparison is just of key
features which both firmwares support.
## EPUB reading
![](./images/comparison/reading-1.jpg)
![](./images/comparison/reading-2.jpg)
![](./images/comparison/reading-3.jpg)
## Menus
![](./images/comparison/menu.jpg)
![](./images/comparison/chapter-menu.jpg)
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Before

Width:  |  Height:  |  Size: 2.2 MiB

After

Width:  |  Height:  |  Size: 2.2 MiB

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
+868 -11
View File
@@ -7,7 +7,7 @@
#pragma once #pragma once
#include "EpdFontData.h" #include "EpdFontData.h"
static const uint8_t pixelarial14Bitmaps[1145] = { static const uint8_t pixelarial14Bitmaps[8296] = {
0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0x1C, 0x63, 0x8C, 0xF7, 0x98, 0xCF, 0xFF, 0xFF, 0xDC, 0xE7, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0x1C, 0x63, 0x8C, 0xF7, 0x98, 0xCF, 0xFF, 0xFF, 0xDC, 0xE7, 0xFE, 0xFF,
0xFF, 0xFB, 0x9C, 0x63, 0x0C, 0x60, 0x30, 0xF3, 0xFF, 0xBF, 0x1F, 0x9F, 0x9B, 0x37, 0xEF, 0xFB, 0xE3, 0x00, 0x70, 0xFF, 0xFB, 0x9C, 0x63, 0x0C, 0x60, 0x30, 0xF3, 0xFF, 0xBF, 0x1F, 0x9F, 0x9B, 0x37, 0xEF, 0xFB, 0xE3, 0x00, 0x70,
0x67, 0xCF, 0x37, 0x61, 0xBB, 0x0D, 0xF0, 0x7D, 0x81, 0xDD, 0xC0, 0xDF, 0x07, 0x98, 0xFC, 0xC7, 0x66, 0x7B, 0xF3, 0x67, 0xCF, 0x37, 0x61, 0xBB, 0x0D, 0xF0, 0x7D, 0x81, 0xDD, 0xC0, 0xDF, 0x07, 0x98, 0xFC, 0xC7, 0x66, 0x7B, 0xF3,
@@ -67,11 +67,392 @@ static const uint8_t pixelarial14Bitmaps[1145] = {
0x66, 0x66, 0x7E, 0x3C, 0x3C, 0x7E, 0x66, 0xE7, 0xC3, 0xC1, 0xE0, 0xF0, 0x7C, 0x76, 0x33, 0xB8, 0xD8, 0x6C, 0x36, 0x66, 0x66, 0x7E, 0x3C, 0x3C, 0x7E, 0x66, 0xE7, 0xC3, 0xC1, 0xE0, 0xF0, 0x7C, 0x76, 0x33, 0xB8, 0xD8, 0x6C, 0x36,
0x1F, 0x07, 0x03, 0x81, 0xC3, 0xE1, 0xC0, 0xFF, 0xFF, 0x06, 0x1E, 0x1C, 0x1C, 0x30, 0x30, 0x70, 0xFF, 0xFF, 0x37, 0x1F, 0x07, 0x03, 0x81, 0xC3, 0xE1, 0xC0, 0xFF, 0xFF, 0x06, 0x1E, 0x1C, 0x1C, 0x30, 0x30, 0x70, 0xFF, 0xFF, 0x37,
0x66, 0x66, 0x6E, 0xCE, 0x66, 0x66, 0x67, 0x30, 0xFF, 0xFF, 0xFF, 0xC0, 0xCE, 0x66, 0x66, 0x67, 0x37, 0x66, 0x66, 0x66, 0x66, 0x6E, 0xCE, 0x66, 0x66, 0x67, 0x30, 0xFF, 0xFF, 0xFF, 0xC0, 0xCE, 0x66, 0x66, 0x67, 0x37, 0x66, 0x66,
0x6E, 0xC0, 0xC3, 0x9B, 0xFF, 0xF9, 0xB8, 0x30, 0xDB, 0x66, 0xC0, 0x6D, 0xBD, 0x80, 0x7F, 0xEF, 0x3C, 0xF3, 0xC0, 0x6E, 0xC0, 0xC3, 0x9B, 0xFF, 0xF9, 0xB8, 0x30, 0xFC, 0x0D, 0xBF, 0xFF, 0xF0, 0x1C, 0x1C, 0x3E, 0x7E, 0xE0, 0xE0,
0x7D, 0xF7, 0xDF, 0xF3, 0xC0, 0xE0, 0xE0, 0xE0, 0x7A, 0x3E, 0x1C, 0x1C, 0x3F, 0x3B, 0x70, 0x70, 0x70, 0x70, 0xFE, 0x70, 0x70, 0x70, 0x60, 0x7F,
0x61, 0xBF, 0xDF, 0xCC, 0x66, 0x33, 0x19, 0xFC, 0xFF, 0x61, 0x80, 0xE1, 0xD8, 0xE7, 0x30, 0xDC, 0x3E, 0x07, 0x87,
0xF8, 0x30, 0x0C, 0x1F, 0xE0, 0xC0, 0x30, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0x3F, 0x70, 0x60, 0x70, 0x7C, 0x6F,
0xE3, 0xE3, 0x7F, 0x3E, 0x07, 0x07, 0x6E, 0xFE, 0xEF, 0xB0, 0x1F, 0x87, 0x1C, 0x66, 0x6D, 0xFF, 0xD8, 0x3F, 0x83,
0xD8, 0x3D, 0x83, 0xDF, 0xF6, 0x66, 0x71, 0xE1, 0xF8, 0x7D, 0x37, 0xFB, 0xED, 0xF0, 0x3B, 0x77, 0x7E, 0xEE, 0x7E,
0x77, 0x3B, 0xFF, 0x80, 0xC0, 0x60, 0x30, 0x18, 0xF8, 0x1F, 0x87, 0x1C, 0x60, 0x6D, 0xF7, 0xDB, 0xBD, 0xBB, 0xDF,
0x3D, 0xB3, 0xD9, 0xF6, 0x06, 0x71, 0xE1, 0xF8, 0xFC, 0x7B, 0xEC, 0xFE, 0x78, 0x0C, 0x06, 0x03, 0x1F, 0xF0, 0xC0,
0x60, 0x30, 0x00, 0x00, 0x7F, 0xC0, 0xFB, 0x61, 0x8E, 0x71, 0x8F, 0xC0, 0xF9, 0x61, 0x9E, 0x1F, 0x7F, 0x80, 0x6E,
0xC0, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xE7, 0xF7, 0xFF, 0xC0, 0xC0, 0xC0, 0x3F, 0xDF, 0x77, 0xDF, 0xF7, 0xFD,
0xDF, 0x77, 0xDC, 0x77, 0x0D, 0xC3, 0x70, 0xDC, 0x37, 0x0D, 0xC3, 0x70, 0xDC, 0x77, 0x67, 0xF0, 0x73, 0x8C, 0x63,
0x18, 0xC0, 0x7C, 0xDF, 0x9F, 0x36, 0xEF, 0x80, 0xEC, 0x6E, 0x77, 0x3F, 0x77, 0x6E, 0xEC, 0x70, 0x70, 0xE0, 0xC0,
0xC3, 0x81, 0x86, 0x03, 0x18, 0x06, 0x73, 0x8C, 0xCF, 0x03, 0x9E, 0x06, 0x6C, 0x1C, 0xFC, 0x30, 0x30, 0xE0, 0x60,
0x70, 0x60, 0xE1, 0xC0, 0xC3, 0x01, 0x8E, 0x03, 0x18, 0x06, 0x7F, 0x8C, 0xDB, 0x03, 0x06, 0x0E, 0x1C, 0x18, 0x70,
0x71, 0xC0, 0xC3, 0xE0, 0xF8, 0x70, 0xB0, 0xC0, 0x63, 0x83, 0xC6, 0x01, 0xDC, 0x1B, 0xB3, 0xBE, 0xEF, 0x01, 0x9E,
0x07, 0x6C, 0x1C, 0xFC, 0x30, 0x30, 0xE0, 0x60, 0x38, 0x70, 0x00, 0x01, 0x87, 0x0E, 0x38, 0xE1, 0xC3, 0xFB, 0xF0,
0x1C, 0x01, 0xE0, 0x06, 0x00, 0x00, 0x0E, 0x00, 0xE0, 0x1F, 0x01, 0xB0, 0x1B, 0x83, 0xB8, 0x31, 0xC7, 0x1C, 0x7F,
0xC6, 0x0E, 0xE0, 0xEE, 0x06, 0x03, 0x00, 0xF0, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0xE0, 0x1F, 0x01, 0xB0, 0x1B, 0x83,
0xB8, 0x31, 0xC7, 0x1C, 0x7F, 0xC6, 0x0E, 0xE0, 0xEE, 0x06, 0x0E, 0x01, 0xF0, 0x1B, 0x00, 0x00, 0x0E, 0x00, 0xE0,
0x1F, 0x01, 0xB0, 0x1B, 0x83, 0xB8, 0x31, 0xC7, 0x1C, 0x7F, 0xC6, 0x0E, 0xE0, 0xEE, 0x06, 0x1F, 0x81, 0xF0, 0x00,
0x00, 0x00, 0x0E, 0x00, 0xE0, 0x1F, 0x01, 0xB0, 0x1B, 0x83, 0xB8, 0x31, 0xC7, 0x1C, 0x7F, 0xC6, 0x0E, 0xE0, 0xEE,
0x06, 0x1B, 0x81, 0xB8, 0x00, 0x00, 0xE0, 0x0E, 0x01, 0xF0, 0x1B, 0x01, 0xB8, 0x3B, 0x83, 0x1C, 0x71, 0xC7, 0xFC,
0x60, 0xEE, 0x0E, 0xE0, 0x60, 0x0E, 0x01, 0xF0, 0x0F, 0x00, 0xE0, 0x0F, 0x01, 0xF0, 0x1B, 0x01, 0xB8, 0x3B, 0x83,
0x1C, 0x71, 0xC7, 0xFC, 0x60, 0xEE, 0x0E, 0xE0, 0x60, 0x03, 0xFE, 0x03, 0xC0, 0x07, 0xC0, 0x06, 0xC0, 0x0E, 0xC0,
0x1C, 0xFE, 0x18, 0xC0, 0x38, 0xC0, 0x3F, 0xC0, 0x70, 0xC0, 0xE0, 0xC0, 0xE0, 0xFF, 0x02, 0x03, 0xF8, 0xF3, 0x38,
0x07, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0E, 0x01, 0xC0, 0x1E, 0x61, 0xFC, 0x0E, 0x01, 0xC0, 0x78, 0x38, 0x1E,
0x07, 0x00, 0x0F, 0xF7, 0x03, 0x81, 0xC0, 0xE0, 0x7F, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xFF, 0x0E, 0x0F, 0x06,
0x00, 0x0F, 0xF7, 0x03, 0x81, 0xC0, 0xE0, 0x7F, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xFF, 0x18, 0x1E, 0x19, 0x80,
0x0F, 0xF7, 0x03, 0x81, 0xC0, 0xE0, 0x7F, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xFF, 0x7E, 0x3F, 0x00, 0x1F, 0xEE,
0x07, 0x03, 0x81, 0xC0, 0xFE, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0xFE, 0xCF, 0x70, 0x77, 0x77, 0x77, 0x77, 0x77,
0x77, 0x6E, 0xC0, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x31, 0xE6, 0xC0, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0x8E, 0x38,
0xE3, 0x8E, 0xEF, 0xB0, 0x0E, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0x80, 0x7F, 0x87, 0x3C, 0x70, 0xE7,
0x06, 0x70, 0x7F, 0xC7, 0x70, 0x77, 0x07, 0x70, 0x67, 0x0E, 0x73, 0xC7, 0xF8, 0x3F, 0x0F, 0xC0, 0x00, 0x00, 0xE0,
0xF8, 0x3F, 0x0F, 0xE3, 0xEC, 0xFB, 0x3E, 0x6F, 0x9B, 0xE3, 0xF8, 0x7E, 0x1F, 0x83, 0x0E, 0x00, 0x78, 0x00, 0xC0,
0x00, 0x01, 0xFC, 0x1E, 0xF1, 0xC1, 0xCE, 0x06, 0x60, 0x3B, 0x01, 0xD8, 0x0E, 0xC0, 0x77, 0x03, 0x38, 0x38, 0xF7,
0x83, 0xF8, 0x03, 0x80, 0x3C, 0x01, 0xC0, 0x00, 0x01, 0xFC, 0x1E, 0xF1, 0xC1, 0xCE, 0x06, 0x60, 0x3B, 0x01, 0xD8,
0x0E, 0xC0, 0x77, 0x03, 0x38, 0x38, 0xF7, 0x83, 0xF8, 0x07, 0x00, 0x7C, 0x03, 0x60, 0x00, 0x01, 0xFC, 0x1E, 0xF1,
0xC1, 0xCE, 0x06, 0x60, 0x3B, 0x01, 0xD8, 0x0E, 0xC0, 0x77, 0x03, 0x38, 0x38, 0xF7, 0x83, 0xF8, 0x0F, 0xC0, 0x7C,
0x00, 0x00, 0x00, 0x01, 0xFC, 0x1E, 0xF1, 0xC1, 0xCE, 0x06, 0x60, 0x3B, 0x01, 0xD8, 0x0E, 0xC0, 0x77, 0x03, 0x38,
0x38, 0xF7, 0x83, 0xF8, 0x0D, 0xC0, 0x6E, 0x00, 0x00, 0x3F, 0x83, 0xDE, 0x38, 0x39, 0xC0, 0xCC, 0x07, 0x60, 0x3B,
0x01, 0xD8, 0x0E, 0xE0, 0x67, 0x07, 0x1E, 0xF0, 0x7F, 0x00, 0x42, 0xEE, 0x7E, 0x3C, 0x7E, 0xEE, 0x42, 0x1F, 0xF1,
0xEF, 0x9C, 0x3C, 0xE3, 0xE6, 0x3B, 0xB1, 0x9D, 0x9C, 0xED, 0xC7, 0x7C, 0x33, 0xE3, 0x8F, 0x78, 0xFF, 0x80, 0x18,
0x07, 0x00, 0xC0, 0x00, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xE1, 0xF8, 0x67, 0xF8, 0xFC,
0x06, 0x03, 0x80, 0xC0, 0x00, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xE1, 0xF8, 0x67, 0xF8,
0xFC, 0x0C, 0x07, 0x83, 0x20, 0x00, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xE1, 0xF8, 0x67,
0xF8, 0xFC, 0x3F, 0x0F, 0xC0, 0x03, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x87, 0xE1, 0x9F,
0xE3, 0xF0, 0x06, 0x01, 0xC0, 0x30, 0x00, 0x0E, 0x1D, 0xC3, 0x9C, 0xE1, 0xDC, 0x3F, 0x03, 0xC0, 0x78, 0x06, 0x00,
0xC0, 0x18, 0x03, 0x00, 0x60, 0xE0, 0x70, 0x3F, 0x9D, 0xEE, 0x3F, 0x0F, 0x87, 0xC7, 0xEF, 0x7F, 0x38, 0x1C, 0x00,
0x7E, 0x7B, 0xB9, 0xD8, 0xEC, 0xE6, 0xE3, 0x71, 0x9E, 0xC7, 0xE0, 0xF0, 0x7B, 0x7D, 0xF0, 0x38, 0x3C, 0x0C, 0x00,
0x7E, 0x2F, 0x03, 0x7F, 0x77, 0xE3, 0xE3, 0x73, 0x7F, 0x0E, 0x1E, 0x18, 0x00, 0x7E, 0x2F, 0x03, 0x7F, 0x77, 0xE3,
0xE3, 0x73, 0x7F, 0x1C, 0x3E, 0x36, 0x00, 0x7E, 0x2F, 0x03, 0x7F, 0x77, 0xE3, 0xE3, 0x73, 0x7F, 0x3F, 0x7E, 0x00,
0x00, 0x7E, 0x2F, 0x03, 0x7F, 0x77, 0xE3, 0xE3, 0x73, 0x7F, 0x36, 0x36, 0x00, 0x7E, 0x2F, 0x03, 0x7F, 0x77, 0xE3,
0xE3, 0x73, 0x7F, 0x1C, 0x36, 0x36, 0x1C, 0x00, 0x7E, 0x2F, 0x03, 0x7F, 0x77, 0xE3, 0xE3, 0x73, 0x7F, 0x7F, 0xF8,
0xBF, 0xF0, 0x79, 0xC0, 0xC3, 0x7F, 0xFF, 0xDC, 0x0E, 0x38, 0x1D, 0xF6, 0x7F, 0xF8, 0x3F, 0x7A, 0x60, 0x60, 0xE0,
0x60, 0x60, 0x7B, 0x3F, 0x0C, 0x0E, 0x1C, 0x18, 0x0E, 0x03, 0x00, 0x03, 0xF3, 0xF9, 0x8E, 0xC7, 0xFF, 0xB0, 0x18,
0x0F, 0x63, 0xF0, 0x06, 0x07, 0x03, 0x00, 0x03, 0xF3, 0xF9, 0x8E, 0xC7, 0xFF, 0xB0, 0x18, 0x0F, 0x63, 0xF0, 0x0C,
0x0F, 0x0C, 0x80, 0x03, 0xF3, 0xF9, 0x8E, 0xC7, 0xFF, 0xB0, 0x18, 0x0F, 0x63, 0xF0, 0x3F, 0x1F, 0x80, 0x07, 0xE7,
0xF3, 0x1D, 0x8F, 0xFF, 0x60, 0x30, 0x1E, 0xC7, 0xE0, 0xCE, 0x60, 0x66, 0x66, 0x66, 0x66, 0x60, 0x6E, 0xC0, 0xCC,
0xCC, 0xCC, 0xCC, 0xC0, 0x31, 0xE6, 0xC0, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xFF, 0xF0, 0x0C, 0x30, 0xC3,
0x0C, 0x30, 0xC3, 0x0C, 0x0F, 0xC3, 0xF0, 0xF8, 0x0E, 0x01, 0x8F, 0xE7, 0xF9, 0x86, 0xE1, 0x98, 0x66, 0x39, 0xFC,
0x3F, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0xFE, 0xEE, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0x18, 0x07, 0x00, 0xC0,
0x00, 0x3F, 0x1F, 0xE6, 0x19, 0x86, 0xE1, 0xD8, 0x66, 0x19, 0xFE, 0x3F, 0x00, 0x06, 0x03, 0x80, 0xC0, 0x00, 0x3F,
0x1F, 0xE6, 0x19, 0x86, 0xE1, 0xD8, 0x66, 0x19, 0xFE, 0x3F, 0x00, 0x0C, 0x07, 0x83, 0x30, 0x00, 0x3F, 0x1F, 0xE6,
0x19, 0x86, 0xE1, 0xD8, 0x66, 0x19, 0xFE, 0x3F, 0x00, 0x3F, 0x0F, 0xC0, 0x00, 0x00, 0x3F, 0x1F, 0xE6, 0x19, 0x86,
0xE1, 0xD8, 0x66, 0x19, 0xFE, 0x3F, 0x00, 0x3F, 0x0F, 0xC0, 0x00, 0xFC, 0x7F, 0x98, 0x66, 0x1B, 0x87, 0x61, 0x98,
0x67, 0xF8, 0xFC, 0x1C, 0x0E, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x38, 0x1C, 0x00, 0x3F, 0x9F, 0xE6, 0x79, 0xBE,
0xED, 0xDF, 0x67, 0x99, 0xFE, 0x7F, 0x00, 0x30, 0x38, 0x18, 0x00, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xE7, 0xF7,
0x7F, 0x0C, 0x1C, 0x18, 0x00, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xE7, 0xF7, 0x7F, 0x18, 0x3C, 0x6C, 0x00, 0xC7,
0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xE7, 0xF7, 0x7F, 0x7E, 0x7E, 0x00, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xE7, 0xF7,
0x7F, 0x0E, 0x0F, 0x06, 0x00, 0x0E, 0x37, 0x19, 0x9C, 0xCE, 0x76, 0x1B, 0x0F, 0x83, 0x81, 0xC0, 0xE2, 0xE1, 0xE0,
0xC0, 0x60, 0x30, 0x18, 0x0F, 0xE7, 0x7B, 0x0D, 0x86, 0xC3, 0xE1, 0xB0, 0xDF, 0xEF, 0xE6, 0x03, 0x01, 0x80, 0x36,
0x1B, 0x00, 0x1C, 0x6E, 0x33, 0x39, 0x9C, 0xEC, 0x36, 0x1F, 0x07, 0x03, 0x81, 0xC5, 0xC3, 0xC0, 0x1F, 0x00, 0x00,
0x00, 0x00, 0xE0, 0x0E, 0x01, 0xF0, 0x1B, 0x01, 0xB8, 0x3B, 0x83, 0x1C, 0x71, 0xC7, 0xFC, 0x60, 0xEE, 0x0E, 0xE0,
0x60, 0x3E, 0x00, 0x00, 0x7E, 0x2F, 0x03, 0x7F, 0x77, 0xE3, 0xE3, 0x73, 0x7F, 0x1B, 0x01, 0xF0, 0x00, 0x00, 0xE0,
0x0E, 0x01, 0xF0, 0x1B, 0x01, 0xB8, 0x3B, 0x83, 0x1C, 0x71, 0xC7, 0xFC, 0x60, 0xEE, 0x0E, 0xE0, 0x60, 0x36, 0x3E,
0x00, 0x7E, 0x2F, 0x03, 0x7F, 0x77, 0xE3, 0xE3, 0x73, 0x7F, 0x0E, 0x00, 0xE0, 0x1F, 0x01, 0xB0, 0x1B, 0x83, 0xB8,
0x31, 0xC7, 0x1C, 0x7F, 0xC6, 0x0E, 0xE0, 0xEE, 0x06, 0x00, 0xE0, 0x0C, 0x00, 0xF0, 0x7E, 0x2F, 0x03, 0x7F, 0x77,
0xE3, 0xE3, 0x73, 0x7F, 0x06, 0x0E, 0x0F, 0x03, 0x00, 0xE0, 0x18, 0x01, 0x01, 0xFC, 0x79, 0x9C, 0x03, 0x80, 0x60,
0x0C, 0x01, 0x80, 0x30, 0x07, 0x00, 0xE0, 0x0F, 0x30, 0xFE, 0x06, 0x0E, 0x0C, 0x00, 0x3F, 0x7A, 0x60, 0x60, 0xE0,
0x60, 0x60, 0x7B, 0x3F, 0x06, 0x01, 0xE0, 0x36, 0x01, 0x01, 0xFC, 0x79, 0x9C, 0x03, 0x80, 0x60, 0x0C, 0x01, 0x80,
0x30, 0x07, 0x00, 0xE0, 0x0F, 0x30, 0xFE, 0x0C, 0x1E, 0x32, 0x00, 0x3F, 0x7A, 0x60, 0x60, 0xE0, 0x60, 0x60, 0x7B,
0x3F, 0x07, 0x00, 0xE0, 0x08, 0x0F, 0xE3, 0xCC, 0xE0, 0x1C, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x38, 0x07, 0x00,
0x79, 0x87, 0xF0, 0x0C, 0x0C, 0x00, 0x3F, 0x7A, 0x60, 0x60, 0xE0, 0x60, 0x60, 0x7B, 0x3F, 0x0D, 0x81, 0xE0, 0x18,
0x01, 0x01, 0xFC, 0x79, 0x9C, 0x03, 0x80, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x07, 0x00, 0xE0, 0x0F, 0x30, 0xFE, 0x32,
0x1E, 0x0C, 0x00, 0x3F, 0x7A, 0x60, 0x60, 0xE0, 0x60, 0x60, 0x7B, 0x3F, 0x36, 0x07, 0xC0, 0x70, 0x00, 0x0F, 0xF1,
0xCF, 0x38, 0x77, 0x0E, 0xE0, 0xDC, 0x1F, 0x83, 0xF0, 0x6E, 0x1D, 0xC3, 0xB9, 0xE7, 0xF8, 0x01, 0xF0, 0x1F, 0x01,
0xF0, 0x1E, 0x3F, 0x87, 0xF8, 0x61, 0x86, 0x18, 0xE1, 0x86, 0x18, 0x61, 0x87, 0xB8, 0x3F, 0x80, 0x7F, 0x87, 0x3C,
0x70, 0xE7, 0x06, 0x70, 0x7F, 0xC7, 0x70, 0x77, 0x07, 0x70, 0x67, 0x0E, 0x73, 0xC7, 0xF8, 0x01, 0x80, 0x60, 0xFC,
0x06, 0x3F, 0x9F, 0xE6, 0x19, 0x86, 0xE1, 0x98, 0x66, 0x19, 0xEE, 0x3F, 0x80, 0x7E, 0x00, 0x00, 0x1F, 0xEE, 0x07,
0x03, 0x81, 0xC0, 0xFE, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0xFE, 0x3F, 0x00, 0x00, 0x07, 0xE7, 0xF3, 0x1D, 0x8F,
0xFF, 0x60, 0x30, 0x1E, 0xC7, 0xE0, 0x7E, 0x1E, 0x00, 0x1F, 0xEE, 0x07, 0x03, 0x81, 0xC0, 0xFE, 0x70, 0x38, 0x1C,
0x0E, 0x07, 0x03, 0xFE, 0x36, 0x0F, 0x00, 0x07, 0xE7, 0xF3, 0x1D, 0x8F, 0xFF, 0x60, 0x30, 0x1E, 0xC7, 0xE0, 0x18,
0x0C, 0x00, 0x1F, 0xEE, 0x07, 0x03, 0x81, 0xC0, 0xFE, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0xFE, 0x0C, 0x06, 0x00,
0x07, 0xE7, 0xF3, 0x1D, 0x8F, 0xFF, 0x60, 0x30, 0x1E, 0xC7, 0xE0, 0xFF, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0xF3, 0x81,
0xC0, 0xE0, 0x70, 0x38, 0x1F, 0xF0, 0x70, 0x30, 0x1E, 0x3F, 0x3F, 0x98, 0xEC, 0x7F, 0xFB, 0x01, 0x80, 0xF6, 0x3F,
0x03, 0x83, 0x80, 0xE0, 0x64, 0x1E, 0x06, 0x00, 0x0F, 0xF7, 0x03, 0x81, 0xC0, 0xE0, 0x7F, 0x38, 0x1C, 0x0E, 0x07,
0x03, 0x81, 0xFF, 0x32, 0x0F, 0x03, 0x00, 0x00, 0x01, 0xF9, 0xFC, 0xC7, 0x63, 0xFF, 0xD8, 0x0C, 0x07, 0xB1, 0xF8,
0x07, 0x01, 0xF0, 0x36, 0x00, 0x01, 0xFC, 0x7B, 0x9C, 0x03, 0x80, 0x60, 0x0C, 0x01, 0x83, 0xB0, 0x77, 0x0E, 0xE1,
0xCF, 0x38, 0xFF, 0x0C, 0x0F, 0x06, 0xC0, 0x03, 0xFB, 0xDD, 0x8E, 0xC7, 0xE3, 0xF1, 0xD8, 0xEF, 0xF3, 0xF8, 0x1D,
0xDC, 0xFE, 0x0D, 0x81, 0xF0, 0x00, 0x0F, 0xE3, 0xDC, 0xE0, 0x1C, 0x03, 0x00, 0x60, 0x0C, 0x1D, 0x83, 0xB8, 0x77,
0x0E, 0x79, 0xC7, 0xF8, 0x1F, 0x0F, 0x00, 0x07, 0xF7, 0xBB, 0x1D, 0x8F, 0xC7, 0xE3, 0xB1, 0xDF, 0xE7, 0xF0, 0x3B,
0xB9, 0xFC, 0x07, 0x00, 0xE0, 0x00, 0x0F, 0xE3, 0xDC, 0xE0, 0x1C, 0x03, 0x00, 0x60, 0x0C, 0x1D, 0x83, 0xB8, 0x77,
0x0E, 0x79, 0xC7, 0xF8, 0x0C, 0x06, 0x00, 0x07, 0xF7, 0xBB, 0x1D, 0x8F, 0xC7, 0xE3, 0xB1, 0xDF, 0xE7, 0xF0, 0x3B,
0xB9, 0xFC, 0x1F, 0xC7, 0xB9, 0xC0, 0x38, 0x06, 0x00, 0xC0, 0x18, 0x3B, 0x07, 0x70, 0xEE, 0x1C, 0xF3, 0x8F, 0xF0,
0x00, 0x0E, 0x03, 0x80, 0x06, 0x07, 0x03, 0x00, 0x03, 0xFB, 0xDD, 0x8E, 0xC7, 0xE3, 0xF1, 0xD8, 0xEF, 0xF3, 0xF8,
0x1D, 0xDC, 0xFE, 0x0C, 0x07, 0x83, 0x30, 0x00, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xFF, 0xFE, 0x1F, 0x87, 0xE1,
0xF8, 0x7E, 0x1F, 0x87, 0x78, 0x3C, 0x00, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xFE, 0x77, 0x31, 0xD8, 0xEC, 0x76, 0x3B,
0x1D, 0x8E, 0xC7, 0x70, 0x63, 0x83, 0x3F, 0xFE, 0xE0, 0xC7, 0x06, 0x3F, 0xF1, 0xC1, 0x8E, 0x0C, 0x70, 0x63, 0x83,
0x1C, 0x18, 0xE0, 0xC0, 0x60, 0x30, 0x3F, 0x0C, 0x07, 0xF3, 0xB9, 0x8E, 0xC7, 0x63, 0xB1, 0xD8, 0xEC, 0x76, 0x38,
0x7D, 0xF8, 0x00, 0x03, 0x87, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0xFF, 0xF0, 0x00, 0x30, 0xC3,
0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xFC, 0x00, 0x0E, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0x80, 0xFC, 0x00,
0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0xDF, 0x80, 0xE7, 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xC0, 0x7D, 0xE0,
0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0xEC, 0xF0, 0x66, 0x00, 0x66, 0x66,
0x66, 0x66, 0x6E, 0xCF, 0xFC, 0x7F, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xC0, 0xE0, 0x7C, 0x0F, 0x81, 0xF0, 0x3E,
0x07, 0xC0, 0xF8, 0x1F, 0x03, 0xE0, 0x7C, 0x1F, 0xB7, 0xF7, 0xE0, 0xCF, 0x9C, 0x00, 0x0C, 0xF9, 0xF3, 0xE7, 0xCF,
0x9F, 0x3E, 0x7C, 0xE1, 0xC3, 0x1E, 0x06, 0x07, 0x83, 0x60, 0x00, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0,
0xE0, 0x60, 0x33, 0xB9, 0xF8, 0x18, 0x78, 0xD8, 0x01, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x0E, 0x38,
0xE3, 0xB9, 0xCE, 0xF3, 0xF8, 0xFC, 0x3E, 0x0F, 0xC3, 0xF8, 0xEF, 0x39, 0xCE, 0x3B, 0x87, 0x00, 0x07, 0x03, 0xC0,
0xC0, 0xC0, 0xC0, 0xC0, 0xCE, 0xCE, 0xDC, 0xF8, 0xF8, 0xFC, 0xDC, 0xCE, 0xC7, 0x00, 0x38, 0x78, 0xC7, 0xCE, 0xDC,
0xF8, 0xF8, 0xFC, 0xDE, 0xCE, 0xC7, 0x30, 0xF0, 0xE0, 0x00, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
0xE0, 0xE0, 0xFF, 0xEE, 0x0C, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xEF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
0xE0, 0xE0, 0xE0, 0xFF, 0x00, 0x18, 0x38, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xE7, 0x81, 0xDC, 0xFC, 0xF8,
0xF8, 0xF8, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xFF, 0xDE, 0xF7, 0xBC, 0x63, 0x18, 0xC6, 0x31, 0xCF, 0x00,
0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xEE, 0xEE, 0xE0, 0xE0, 0xE0, 0xE0, 0xFF, 0xC3, 0x0C, 0x30, 0xC3, 0x0D, 0xF7, 0xC3,
0x0C, 0x38, 0xF0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x3E, 0x0F, 0x07, 0x81, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xFF, 0x73,
0x9C, 0xE7, 0xBF, 0xDE, 0x73, 0x9C, 0xE3, 0x80, 0x06, 0x03, 0x80, 0xC0, 0x00, 0xE0, 0xF8, 0x3F, 0x0F, 0xE3, 0xEC,
0xFB, 0x3E, 0x6F, 0x9B, 0xE3, 0xF8, 0x7E, 0x1F, 0x83, 0x0C, 0x1C, 0x18, 0x00, 0xFE, 0xEE, 0xC7, 0xC7, 0xC7, 0xC7,
0xC7, 0xC7, 0xC7, 0xE0, 0xF8, 0x3F, 0x0F, 0xE3, 0xEC, 0xFB, 0x3E, 0x6F, 0x9B, 0xE3, 0xF8, 0x7E, 0x1F, 0x83, 0x00,
0x03, 0x01, 0xC0, 0xFE, 0xEE, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0x00, 0x18, 0x38, 0x1B, 0x07, 0x80, 0xC0,
0x00, 0xE0, 0xF8, 0x3F, 0x0F, 0xE3, 0xEC, 0xFB, 0x3E, 0x6F, 0x9B, 0xE3, 0xF8, 0x7E, 0x1F, 0x83, 0x66, 0x3C, 0x18,
0x00, 0xFE, 0xEE, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xE0, 0x70, 0x30, 0x18, 0x00, 0x03, 0xF9, 0xDC, 0xC7,
0x63, 0xB1, 0xD8, 0xEC, 0x76, 0x3B, 0x1C, 0xE0, 0xF8, 0x3F, 0x0F, 0xE3, 0xEC, 0xFB, 0x3E, 0x6F, 0x9B, 0xE3, 0xF8,
0x7E, 0x1F, 0x83, 0x00, 0xC0, 0x70, 0x3C, 0xFE, 0xEE, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0x07, 0x07, 0x0E,
0x0F, 0x80, 0x00, 0x00, 0x00, 0x3F, 0x83, 0xDE, 0x38, 0x39, 0xC0, 0xCC, 0x07, 0x60, 0x3B, 0x01, 0xD8, 0x0E, 0xE0,
0x67, 0x07, 0x1E, 0xF0, 0x7F, 0x00, 0x3F, 0x00, 0x00, 0x00, 0xFC, 0x7F, 0x98, 0x66, 0x1B, 0x87, 0x61, 0x98, 0x67,
0xF8, 0xFC, 0x0D, 0x80, 0x7C, 0x00, 0x00, 0x3F, 0x83, 0xDE, 0x38, 0x39, 0xC0, 0xCC, 0x07, 0x60, 0x3B, 0x01, 0xD8,
0x0E, 0xE0, 0x67, 0x07, 0x1E, 0xF0, 0x7F, 0x00, 0x3F, 0x07, 0x80, 0x00, 0xFC, 0x7F, 0x98, 0x66, 0x1B, 0x87, 0x61,
0x98, 0x67, 0xF8, 0xFC, 0x07, 0xC0, 0x7E, 0x03, 0x60, 0x00, 0x01, 0xFC, 0x1E, 0xF1, 0xC1, 0xCE, 0x06, 0x60, 0x3B,
0x01, 0xD8, 0x0E, 0xC0, 0x77, 0x03, 0x38, 0x38, 0xF7, 0x83, 0xF8, 0x0D, 0x87, 0xE1, 0xB0, 0x00, 0x3F, 0x1F, 0xE6,
0x19, 0x86, 0xE1, 0xD8, 0x66, 0x19, 0xFE, 0x3F, 0x00, 0x1F, 0xFF, 0x1F, 0x70, 0x1C, 0x38, 0x0E, 0x1C, 0x06, 0x0E,
0x03, 0x07, 0xF9, 0x83, 0x80, 0xC1, 0xC0, 0x70, 0xE0, 0x38, 0x70, 0x0F, 0xB8, 0x03, 0xFF, 0xF0, 0x3F, 0x7C, 0x7F,
0xEE, 0x61, 0xC6, 0x61, 0xC7, 0xE1, 0xFF, 0x61, 0xC0, 0x61, 0xC0, 0x7F, 0xF6, 0x3F, 0x7E, 0x0C, 0x07, 0x01, 0x80,
0x00, 0xFF, 0x3B, 0xEE, 0x3B, 0x8E, 0xE3, 0xBB, 0xEF, 0xF3, 0xB8, 0xE7, 0x38, 0xEE, 0x3B, 0x87, 0x18, 0xE3, 0x00,
0xFF, 0xAC, 0x30, 0xC3, 0x0C, 0x30, 0xC0, 0xFF, 0x3B, 0xEE, 0x3B, 0x8E, 0xE3, 0xBB, 0xEF, 0xF3, 0xB8, 0xE7, 0x38,
0xEE, 0x3B, 0x87, 0x00, 0x07, 0x03, 0x80, 0x7E, 0xE9, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x01, 0x87, 0x00, 0x66,
0x0F, 0x01, 0x80, 0x00, 0xFF, 0x3B, 0xEE, 0x3B, 0x8E, 0xE3, 0xBB, 0xEF, 0xF3, 0xB8, 0xE7, 0x38, 0xEE, 0x3B, 0x87,
0xC9, 0xE3, 0x00, 0xFF, 0xAC, 0x30, 0xC3, 0x0C, 0x30, 0xC0, 0x06, 0x0F, 0x07, 0x00, 0x03, 0xF3, 0xBB, 0x81, 0xC0,
0x70, 0x1E, 0x03, 0xC0, 0x70, 0x38, 0x1F, 0x9F, 0xFE, 0x0C, 0x38, 0x60, 0x07, 0xEE, 0xF8, 0x38, 0x3C, 0x1C, 0x1B,
0x7F, 0xE0, 0x0C, 0x0F, 0x0D, 0x80, 0x03, 0xF3, 0xBB, 0x81, 0xC0, 0x70, 0x1E, 0x03, 0xC0, 0x70, 0x38, 0x1F, 0x9F,
0xFE, 0x18, 0x79, 0x90, 0x07, 0xEE, 0xF8, 0x38, 0x3C, 0x1C, 0x1B, 0x7F, 0xE0, 0x3F, 0x3B, 0xB8, 0x1C, 0x07, 0x01,
0xE0, 0x3C, 0x07, 0x03, 0x81, 0xF9, 0xFF, 0xE1, 0xC0, 0xE0, 0xF0, 0x7E, 0xEF, 0x83, 0x83, 0xC1, 0xC1, 0xB7, 0xFE,
0x70, 0xE1, 0xC0, 0x36, 0x0F, 0x03, 0x00, 0x03, 0xF3, 0xBB, 0x81, 0xC0, 0x70, 0x1E, 0x03, 0xC0, 0x70, 0x38, 0x1F,
0x9F, 0xFE, 0x6C, 0x78, 0x60, 0x07, 0xEE, 0xF8, 0x38, 0x3C, 0x1C, 0x1B, 0x7F, 0xE0, 0xFF, 0xC3, 0x00, 0xC0, 0x30,
0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x1C, 0x07, 0x03, 0xC0, 0xC3, 0x0C, 0x3F, 0xC3, 0x0C,
0x30, 0xC3, 0x0E, 0xDF, 0x30, 0xE7, 0x80, 0x36, 0x07, 0x80, 0xC0, 0x00, 0xFF, 0xC3, 0x00, 0xC0, 0x30, 0x0C, 0x03,
0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x1B, 0x6D, 0xB0, 0xFF, 0x0C, 0x30, 0xC3, 0x0C, 0x38, 0x7C, 0xFF,
0xC3, 0x00, 0xC0, 0x30, 0x0C, 0x1F, 0xC0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0xC3, 0x0C, 0x3F, 0xC3, 0x0C,
0x3F, 0xC3, 0x0E, 0x1F, 0x3F, 0x0F, 0xC0, 0x00, 0x00, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07,
0xE1, 0xF8, 0x67, 0xF8, 0xFC, 0x7E, 0x7E, 0x00, 0x00, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xE7, 0xF7, 0x7F, 0x3F,
0x00, 0x00, 0x03, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x87, 0xE1, 0x9F, 0xE3, 0xF0, 0x7E,
0x00, 0x00, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xE7, 0xF7, 0x7F, 0x3E, 0x07, 0x80, 0x03, 0x07, 0xC1, 0xF0, 0x7C,
0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x87, 0xE1, 0x9F, 0xE3, 0xF0, 0x7C, 0x3C, 0x00, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
0xC7, 0xE7, 0xF7, 0x7F, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0x00, 0x30, 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07,
0xC1, 0xF8, 0x7E, 0x19, 0xFE, 0x3F, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xE7,
0xF7, 0x7F, 0x0F, 0x87, 0xE1, 0xF0, 0x00, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xE1, 0xF8,
0x67, 0xF8, 0xFC, 0x1F, 0x3F, 0x3C, 0x00, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xE7, 0xF7, 0x7F, 0xC1, 0xF0, 0x7C,
0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xE1, 0xF8, 0x67, 0xF8, 0xFC, 0x0E, 0x03, 0x00, 0xE0, 0xC7, 0xC7, 0xC7,
0xC7, 0xC7, 0xC7, 0xE7, 0xF7, 0x7F, 0x0F, 0x0E, 0x0F, 0x01, 0x80, 0x03, 0xC0, 0x06, 0x40, 0x00, 0x00, 0xE0, 0x07,
0xE1, 0x86, 0xE3, 0xC6, 0x63, 0xC6, 0x73, 0xCE, 0x77, 0xCE, 0x76, 0xEC, 0x36, 0x6C, 0x3E, 0x7C, 0x3C, 0x7C, 0x3C,
0x38, 0x1C, 0x38, 0x07, 0x00, 0x7C, 0x03, 0x60, 0x00, 0x0E, 0x71, 0xF3, 0x9D, 0x9C, 0xEC, 0xF6, 0x7D, 0xB3, 0xEF,
0x8F, 0x78, 0x79, 0xC1, 0x8E, 0x00, 0x0C, 0x03, 0xC0, 0x4C, 0x00, 0x0E, 0x1D, 0xC3, 0x9C, 0xE1, 0xDC, 0x3F, 0x03,
0xC0, 0x78, 0x06, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x1C, 0x1F, 0x0D, 0x80, 0x0E, 0x37, 0x19, 0x9C, 0xCE, 0x76,
0x1B, 0x0F, 0x83, 0x81, 0xC0, 0xE2, 0xE1, 0xE0, 0x3F, 0x07, 0xE0, 0x00, 0x70, 0xEE, 0x1C, 0xE7, 0x0E, 0xE1, 0xF8,
0x1E, 0x03, 0xC0, 0x30, 0x06, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x06, 0x03, 0x80, 0xC0, 0x00, 0xFF, 0x80, 0xE0, 0x38,
0x1C, 0x0E, 0x07, 0x01, 0xC0, 0xE0, 0x70, 0x1C, 0x0E, 0x03, 0xFF, 0x0C, 0x1C, 0x18, 0x00, 0xFF, 0x0E, 0x0E, 0x1C,
0x38, 0x38, 0x70, 0xE0, 0xFF, 0x0C, 0x03, 0x00, 0x03, 0xFE, 0x03, 0x80, 0xE0, 0x70, 0x38, 0x1C, 0x07, 0x03, 0x81,
0xC0, 0x70, 0x38, 0x0F, 0xFC, 0x18, 0x18, 0x00, 0xFF, 0x0E, 0x0E, 0x1C, 0x38, 0x38, 0x70, 0xE0, 0xFF, 0x33, 0x07,
0x80, 0xC0, 0x00, 0xFF, 0x80, 0xE0, 0x38, 0x1C, 0x0E, 0x07, 0x01, 0xC0, 0xE0, 0x70, 0x1C, 0x0E, 0x03, 0xFF, 0x66,
0x3C, 0x18, 0x00, 0xFF, 0x0E, 0x0E, 0x1C, 0x38, 0x38, 0x70, 0xE0, 0xFF, 0x1D, 0xFE, 0x30, 0xC3, 0x0C, 0x30, 0xC3,
0x0C, 0x30, 0xC3, 0x00, 0x79, 0xF0, 0x38, 0x1E, 0x07, 0x00, 0x0F, 0xF7, 0x03, 0x81, 0xC0, 0xE0, 0x7F, 0x38, 0x1C,
0x0E, 0x07, 0x03, 0x81, 0xFF, 0x7E, 0x3F, 0x00, 0x1F, 0xEE, 0x07, 0x03, 0x81, 0xC0, 0xFE, 0x70, 0x38, 0x1C, 0x0E,
0x07, 0x03, 0xFE, 0xFF, 0xC0, 0xE0, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0F, 0xF0, 0x7B, 0xC3, 0x86, 0x1C, 0x38, 0xE1,
0x87, 0x1C, 0x3B, 0xC0, 0x0C, 0x1C, 0x18, 0x00, 0xFF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
0xE0, 0x1F, 0xC7, 0x99, 0xC0, 0x38, 0x06, 0x00, 0xFE, 0x18, 0x03, 0x00, 0x70, 0x0E, 0x00, 0xF3, 0x0F, 0xE0, 0x3F,
0x3B, 0xB8, 0x1C, 0x07, 0x01, 0xE0, 0x3C, 0x07, 0x03, 0x81, 0xF9, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xEF,
0xB0, 0x0E, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0x80, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x06, 0x06, 0xEE, 0xFC, 0x1F, 0xE0, 0x07, 0x38, 0x01, 0xCE, 0x00, 0x73, 0x80, 0x1C, 0xE0, 0x07, 0x3F, 0xC1, 0xCE,
0x78, 0x63, 0x86, 0x18, 0xE1, 0xCE, 0x38, 0x67, 0x0E, 0x7B, 0x83, 0xFC, 0x00, 0x00, 0x00, 0xE1, 0xC0, 0xE1, 0xC0,
0xE1, 0xC0, 0xE1, 0xC0, 0xE1, 0xC0, 0xFF, 0xFE, 0xE1, 0xDF, 0xE1, 0xC7, 0xE1, 0xC3, 0xE1, 0xC7, 0xE1, 0xCF, 0xE1,
0xFE, 0xFF, 0xC1, 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x01, 0xFE, 0x1F, 0xF1, 0xC7, 0x1C, 0x31, 0xC3, 0x1C, 0x31, 0xC3,
0x0E, 0x07, 0x81, 0xC0, 0x00, 0xE3, 0xB9, 0xCE, 0xF3, 0xF8, 0xFC, 0x3E, 0x0F, 0xC3, 0xF8, 0xEF, 0x39, 0xCE, 0x3B,
0x87, 0x18, 0x07, 0x00, 0xE0, 0x00, 0xE0, 0xF8, 0x7E, 0x3F, 0x9F, 0xE6, 0xFB, 0xBE, 0xCF, 0xE3, 0xF8, 0xFC, 0x3E,
0x0F, 0x83, 0x3B, 0x07, 0xC0, 0x03, 0x87, 0xE1, 0xDC, 0x77, 0x18, 0xEE, 0x3B, 0x07, 0xC1, 0xF0, 0x38, 0x0E, 0x17,
0x0F, 0x80, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0xFF, 0x0C, 0x03,
0x00, 0xC0, 0x0E, 0x00, 0xE0, 0x1F, 0x01, 0xB0, 0x1B, 0x83, 0xB8, 0x31, 0xC7, 0x1C, 0x7F, 0xC6, 0x0E, 0xE0, 0xEE,
0x06, 0xFF, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0xFB, 0xBF, 0xC7, 0xE1, 0xF1, 0xF9, 0xFF, 0xE0, 0xFF, 0x3B, 0xEE, 0x3B,
0x8E, 0xE7, 0xBF, 0xCE, 0x7B, 0x86, 0xE1, 0xB8, 0x6E, 0x7B, 0xFC, 0xFF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
0xE0, 0xE0, 0xE0, 0xE0, 0x1F, 0xE1, 0xCE, 0x1C, 0xE1, 0xCE, 0x1C, 0xE1, 0xCE, 0x18, 0xE1, 0x8E, 0x38, 0xE3, 0x8E,
0x70, 0xEF, 0xFF, 0xC0, 0x3C, 0x03, 0xC0, 0x30, 0xFF, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0xF3, 0x81, 0xC0, 0xE0, 0x70,
0x38, 0x1F, 0xF0, 0xF3, 0x8E, 0xE7, 0x38, 0xEE, 0xE0, 0xFF, 0x80, 0xFF, 0x00, 0xFC, 0x03, 0xFC, 0x0D, 0xDC, 0x3B,
0x98, 0xE7, 0x39, 0xCE, 0x3F, 0x1C, 0x70, 0x7F, 0x3B, 0x80, 0xE0, 0x70, 0xF1, 0xF8, 0x3E, 0x07, 0x01, 0x81, 0xF9,
0xFF, 0xE0, 0xE0, 0xF8, 0x7E, 0x3F, 0x9F, 0xE6, 0xFB, 0xBE, 0xCF, 0xE3, 0xF8, 0xFC, 0x3E, 0x0F, 0x83, 0x3F, 0x07,
0xC0, 0x03, 0x83, 0xE1, 0xF8, 0xFE, 0x7F, 0x9B, 0xEE, 0xFB, 0x3F, 0x8F, 0xE3, 0xF0, 0xF8, 0x3E, 0x0C, 0xE3, 0xB9,
0xCE, 0xF3, 0xF8, 0xFC, 0x3E, 0x0F, 0xC3, 0xF8, 0xEF, 0x39, 0xCE, 0x3B, 0x87, 0x1F, 0xE3, 0x9C, 0x73, 0x8E, 0x71,
0xCE, 0x39, 0xC7, 0x38, 0xC7, 0x18, 0xE7, 0x1D, 0xC3, 0xF0, 0x70, 0x60, 0x37, 0x83, 0xBC, 0x1D, 0xF1, 0xFD, 0x8F,
0xE4, 0xDF, 0x36, 0xF9, 0xA7, 0xC7, 0x3E, 0x38, 0xF0, 0x07, 0x80, 0x30, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xFF,
0xFE, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0x1F, 0xC1, 0xEF, 0x1C, 0x1C, 0xE0, 0x66, 0x03, 0xB0, 0x1D, 0x80,
0xEC, 0x07, 0x70, 0x33, 0x83, 0x8F, 0x78, 0x3F, 0x80, 0xFF, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0x87,
0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xFE, 0x77, 0xB8, 0xFC, 0x3E, 0x1F, 0x1F, 0xBD, 0xFC, 0xE0, 0x70, 0x38, 0x1C, 0x00,
0x02, 0x03, 0xF8, 0xF3, 0x38, 0x07, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0E, 0x01, 0xC0, 0x1E, 0x61, 0xFC, 0xFF,
0xC3, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0xE1, 0xF8, 0x77, 0x1D, 0xC6,
0x3B, 0x8E, 0xC1, 0xF0, 0x7C, 0x0E, 0x03, 0x85, 0xC3, 0xE0, 0x03, 0x80, 0x7F, 0x83, 0xBF, 0x9C, 0xE6, 0x63, 0x9D,
0x8E, 0x76, 0x38, 0xD8, 0xE7, 0x63, 0x9D, 0xCE, 0x63, 0xBF, 0x87, 0xFC, 0x03, 0x80, 0xE1, 0xCE, 0x38, 0xEE, 0x1F,
0x81, 0xF0, 0x1C, 0x07, 0x80, 0xF8, 0x3B, 0x8E, 0x71, 0xC7, 0x70, 0x70, 0xE1, 0xDC, 0x3B, 0x87, 0x70, 0xEE, 0x1D,
0xC3, 0xB8, 0x77, 0x0E, 0xE1, 0xDC, 0x3B, 0x87, 0x7F, 0xF0, 0x06, 0x00, 0xC0, 0x18, 0x61, 0xD8, 0x76, 0x1D, 0x87,
0x61, 0xD8, 0x77, 0xBC, 0xFF, 0x01, 0xC0, 0x70, 0x1C, 0x07, 0xE3, 0x8F, 0xC7, 0x1F, 0x8E, 0x3F, 0x1C, 0x7E, 0x38,
0xFC, 0x71, 0xF8, 0xE3, 0xF1, 0xC7, 0xE3, 0x8F, 0xC7, 0x1F, 0x8E, 0x3F, 0xFF, 0xF0, 0xE3, 0x8E, 0xE3, 0x8E, 0xE3,
0x8E, 0xE3, 0x8E, 0xE3, 0x8E, 0xE3, 0x8E, 0xE3, 0x8E, 0xE3, 0x8E, 0xE3, 0x8E, 0xE3, 0x8E, 0xE3, 0x8E, 0xFF, 0xFF,
0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0xF8, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0xFE, 0x19, 0xF1, 0x87, 0x18,
0x31, 0x87, 0x19, 0xF1, 0xFE, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xFF, 0x9F, 0xBE, 0xFC, 0x77, 0xE3,
0xBF, 0x1D, 0xFB, 0xEF, 0xFE, 0x70, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0xFB, 0xBF, 0xC7, 0xE1, 0xF1, 0xFB, 0xFF,
0xE0, 0xFE, 0x3B, 0xE0, 0x38, 0x07, 0x01, 0xCF, 0xF0, 0x1C, 0x07, 0x01, 0xC0, 0xEC, 0x7B, 0xF8, 0xE1, 0xF8, 0xE3,
0xDC, 0xE7, 0x0E, 0xE6, 0x07, 0xEE, 0x07, 0xFE, 0x07, 0xEE, 0x07, 0xE6, 0x07, 0xE6, 0x07, 0xE7, 0x0E, 0xE3, 0xDE,
0xE1, 0xF8, 0x3F, 0xDE, 0x76, 0x1D, 0x87, 0x61, 0xDE, 0x73, 0xFC, 0xE7, 0x39, 0xDC, 0x77, 0x1F, 0x87, 0x7E, 0x2F,
0x03, 0x7F, 0x77, 0xE3, 0xE3, 0x73, 0x7F, 0x1F, 0x3F, 0x18, 0x1C, 0x0F, 0xE7, 0xBB, 0x0D, 0x87, 0xC3, 0xE1, 0xF8,
0xDE, 0xE7, 0xE0, 0xFE, 0xCE, 0xC7, 0xCE, 0xFE, 0xCF, 0xC3, 0xCF, 0xFE, 0xFF, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC0,
0x3F, 0x8E, 0x63, 0x98, 0xE6, 0x31, 0x8C, 0x67, 0x19, 0xC6, 0xFF, 0xF0, 0x3C, 0x0C, 0x3F, 0x3F, 0x98, 0xEC, 0x7F,
0xFB, 0x01, 0x80, 0xF6, 0x3F, 0x00, 0x67, 0x33, 0xBB, 0x8F, 0xF8, 0x3F, 0x81, 0xFC, 0x0F, 0xE0, 0xDD, 0x8C, 0xE6,
0xE7, 0x38, 0x7E, 0x6E, 0x07, 0x0E, 0x3E, 0x0F, 0x07, 0x6F, 0xFE, 0xC7, 0xC7, 0xCF, 0xCF, 0xDB, 0xF3, 0xF3, 0xE3,
0xE3, 0x7E, 0x3C, 0x00, 0xC7, 0xC7, 0xCF, 0xCF, 0xDB, 0xF3, 0xF3, 0xE3, 0xE3, 0xC7, 0xCE, 0xDC, 0xF8, 0xF8, 0xFC,
0xDE, 0xCE, 0xC7, 0x3F, 0x9C, 0xCE, 0x67, 0x33, 0x99, 0x8C, 0xC6, 0xE3, 0xE1, 0x80, 0xE1, 0xDC, 0x3B, 0xC7, 0x69,
0xED, 0xBD, 0xBD, 0xF3, 0xBE, 0x67, 0xC0, 0xE0, 0xC3, 0xC3, 0xC3, 0xC3, 0xFF, 0xC3, 0xC3, 0xC3, 0xC3, 0x3F, 0x1F,
0xE6, 0x19, 0x86, 0xE1, 0xD8, 0x66, 0x19, 0xFE, 0x3F, 0x00, 0xFF, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
0xFE, 0x77, 0xB0, 0xD8, 0x6C, 0x3E, 0x1B, 0x0D, 0xFE, 0xFE, 0x60, 0x30, 0x18, 0x00, 0x3F, 0x7A, 0x60, 0x60, 0xE0,
0x60, 0x60, 0x7B, 0x3F, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xE3, 0x71, 0x99, 0xCC, 0xE7, 0x61,
0xB0, 0xF8, 0x38, 0x1C, 0x0E, 0x2E, 0x1E, 0x00, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x1F, 0x03, 0xFE, 0x3F, 0xF9, 0xDC,
0xCC, 0xE7, 0xE7, 0x3B, 0x39, 0x99, 0xCC, 0xFF, 0xE3, 0xFE, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0xE3, 0x3B, 0x8F, 0x87,
0x81, 0xC1, 0xF1, 0xF8, 0xCE, 0xE3, 0x80, 0xC7, 0x63, 0xB1, 0xD8, 0xEC, 0x76, 0x3B, 0x1D, 0x8E, 0xFF, 0x80, 0xC0,
0x60, 0xE3, 0xE3, 0xE3, 0xE3, 0x7F, 0x3F, 0x03, 0x03, 0x03, 0xC6, 0x3C, 0x63, 0xC6, 0x3C, 0x63, 0xC6, 0x3C, 0x63,
0xC6, 0x3C, 0x63, 0xFF, 0xF0, 0xC6, 0x36, 0x31, 0xB1, 0x8D, 0x8C, 0x6C, 0x63, 0x63, 0x1B, 0x18, 0xD8, 0xC6, 0xFF,
0xF8, 0x00, 0xC0, 0x06, 0xF8, 0x0E, 0x03, 0x80, 0xFE, 0x3B, 0xCE, 0x33, 0x8C, 0xEF, 0x3F, 0x80, 0xC0, 0xF8, 0x1F,
0x03, 0xFF, 0x7E, 0xEF, 0x8F, 0xF1, 0xFE, 0x77, 0xFE, 0xE0, 0xC0, 0xC0, 0xC0, 0xFE, 0xEF, 0xC7, 0xC7, 0xCF, 0xFE,
0x7C, 0x6E, 0x07, 0x07, 0x3F, 0x07, 0x07, 0xDE, 0xFC, 0xC7, 0xEC, 0xFE, 0xCC, 0x7C, 0xC3, 0xFC, 0x3D, 0xC3, 0xCC,
0x7C, 0xFE, 0xC7, 0xE0, 0x3F, 0x73, 0x63, 0x63, 0x73, 0x3F, 0x33, 0x73, 0xE3, 0x18, 0x0E, 0x03, 0x00, 0x03, 0xF3,
0xF9, 0x8E, 0xC7, 0xFF, 0xB0, 0x18, 0x0F, 0x63, 0xF0, 0x3F, 0x1F, 0x80, 0x07, 0xE7, 0xF3, 0x1D, 0x8F, 0xFF, 0x60,
0x30, 0x1E, 0xC7, 0xE0, 0x60, 0x30, 0x3F, 0x0C, 0x07, 0xF3, 0xB9, 0x8E, 0xC7, 0x63, 0xB1, 0xD8, 0xEC, 0x76, 0x38,
0x1C, 0x0E, 0x0E, 0x1C, 0xF3, 0x80, 0xFF, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC0, 0x3F, 0x7B, 0x60, 0x60, 0xFE, 0x60,
0x60, 0x7B, 0x3F, 0x7E, 0xEF, 0x83, 0x83, 0xC1, 0xC1, 0xB7, 0xFE, 0xD8, 0x0D, 0xB6, 0xDB, 0x6C, 0xFF, 0xF0, 0x0C,
0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x18, 0x60, 0x00, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x63, 0x9C, 0x3F,
0x80, 0x73, 0x00, 0xE6, 0x01, 0xCF, 0xE3, 0x99, 0xC6, 0x31, 0xCC, 0x63, 0xB8, 0xCE, 0xE1, 0xFC, 0xC3, 0x06, 0x18,
0x30, 0xC1, 0xFF, 0xEC, 0x33, 0xE1, 0x8F, 0x0C, 0x78, 0x67, 0xC3, 0xF0, 0x60, 0x30, 0x3F, 0x0C, 0x07, 0xF3, 0xB9,
0x8E, 0xC7, 0x63, 0xB1, 0xD8, 0xEC, 0x76, 0x38, 0x0C, 0x1C, 0x18, 0x00, 0xC7, 0xCE, 0xDC, 0xF8, 0xF8, 0xFC, 0xDE,
0xCE, 0xC7, 0x30, 0x38, 0x18, 0x00, 0xC7, 0xC7, 0xCF, 0xCF, 0xDB, 0xF3, 0xF3, 0xE3, 0xE3, 0x36, 0x1F, 0x00, 0x1C,
0x6E, 0x33, 0x39, 0x9C, 0xEC, 0x36, 0x1F, 0x07, 0x03, 0x81, 0xC5, 0xC3, 0xC0, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
0xC7, 0xC7, 0xFF, 0x18, 0x18, 0x18, 0x01, 0x80, 0xFF, 0x81, 0x80, 0x18, 0x01, 0x80, 0x1F, 0xE1, 0x9F, 0x18, 0x71,
0x83, 0x18, 0x71, 0x9F, 0x1F, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0xFF, 0x0E, 0x03, 0x80, 0xFE, 0x3B, 0xCE, 0x33,
0x8C, 0xEF, 0x3F, 0x80, 0x1F, 0xC1, 0xE7, 0x1C, 0x1C, 0xE0, 0x66, 0x03, 0xBF, 0xFD, 0xDF, 0xEC, 0x07, 0x70, 0x33,
0x83, 0x8F, 0x38, 0x3F, 0x80, 0x3F, 0x1F, 0xE6, 0x19, 0xF6, 0xFF, 0xD8, 0x66, 0x19, 0xCE, 0x3F, 0x00, 0xE0, 0x7B,
0x83, 0xE6, 0x0C, 0x1C, 0x70, 0x71, 0xC0, 0xC6, 0x03, 0xB8, 0x0E, 0xE0, 0x1F, 0x00, 0x7C, 0x00, 0xE0, 0x03, 0x80,
0xE3, 0xF8, 0xC6, 0x71, 0x98, 0x76, 0x0F, 0x83, 0xC0, 0xF0, 0x1C, 0x00, 0x3F, 0x01, 0xE0, 0x00, 0x0E, 0x0C, 0xE1,
0xCE, 0x3C, 0xE7, 0xCE, 0x6C, 0xEE, 0xCE, 0xCC, 0xF8, 0xCF, 0x8C, 0xF0, 0xCE, 0x0C, 0xE0, 0xF0, 0x07, 0x00, 0xE0,
0x0E, 0x7E, 0x0F, 0x00, 0x03, 0x1C, 0xC7, 0x33, 0xCC, 0xF3, 0x6C, 0xF3, 0x3C, 0xCE, 0x33, 0x8F, 0x01, 0xC0, 0xE0,
0x38, 0x70, 0x1F, 0x81, 0xC0, 0x38, 0x07, 0x00, 0xFF, 0x1D, 0xF3, 0x8E, 0x70, 0xCE, 0x19, 0xC7, 0x39, 0xE7, 0xF8,
0x70, 0x38, 0x3F, 0x0E, 0x07, 0xF3, 0xBD, 0xCE, 0xEF, 0x7F, 0x00, 0xFE, 0x77, 0xB8, 0xFC, 0x3E, 0x9F, 0xFF, 0xBF,
0xFE, 0xE7, 0x71, 0xB8, 0x1C, 0x00, 0xFE, 0x77, 0xB0, 0xD8, 0x6C, 0x3E, 0x1B, 0x7D, 0xFE, 0xFE, 0x63, 0x30, 0xD8,
0x00, 0x07, 0x07, 0xFF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x0C, 0x3F, 0xF0, 0xC3,
0x0C, 0x30, 0xC3, 0x0C, 0x00, 0x7F, 0xB8, 0x1C, 0x0E, 0x07, 0x07, 0xE1, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x00,
0x7E, 0xE1, 0xC3, 0x8F, 0xCE, 0x1C, 0x38, 0x70, 0xFF, 0x70, 0x38, 0x1C, 0x0F, 0xE7, 0x3B, 0x8F, 0xC3, 0xE1, 0xF0,
0xF8, 0x7C, 0x30, 0x38, 0x38, 0x78, 0xFE, 0xC0, 0xC0, 0xFE, 0xEE, 0xC7, 0xC3, 0xC3, 0xC7, 0x07, 0x0E, 0x1E, 0xF3,
0x8E, 0x73, 0x9C, 0x3B, 0xB8, 0x1F, 0xF0, 0x0F, 0xF0, 0x07, 0xE0, 0x0F, 0xF0, 0x1B, 0xB0, 0x3B, 0x98, 0x73, 0x9C,
0x73, 0x8C, 0xE3, 0x8F, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x67, 0x31, 0xDD, 0xC3, 0xFE, 0x07, 0xF0, 0x1F, 0x80,
0x7F, 0x03, 0x7E, 0x19, 0xDC, 0xE7, 0x3C, 0x00, 0x70, 0x01, 0xC0, 0x7F, 0x3B, 0x80, 0xE0, 0x70, 0xF1, 0xF8, 0x3E,
0x07, 0x01, 0x81, 0xF9, 0xFF, 0xE1, 0xC0, 0xE0, 0xF0, 0x7E, 0x6E, 0x07, 0x0E, 0x3E, 0x0F, 0x07, 0x6F, 0xFE, 0x18,
0x1C, 0x38, 0xE3, 0x9C, 0xE3, 0x98, 0x76, 0x0F, 0xC1, 0xF0, 0x3E, 0x07, 0x60, 0xEE, 0x1C, 0xE3, 0x8E, 0x70, 0xE0,
0x0C, 0x01, 0x80, 0x30, 0xC7, 0x67, 0x37, 0x1F, 0x0F, 0x06, 0xC3, 0x71, 0x9C, 0xC7, 0x81, 0xC0, 0xE0, 0x70, 0xE0,
0xFC, 0x3B, 0xEE, 0x7F, 0x8F, 0xE1, 0xF8, 0x3F, 0x87, 0xF8, 0xFB, 0x9C, 0x33, 0x87, 0x70, 0x70, 0xC3, 0xB1, 0xCD,
0xE3, 0x78, 0xFC, 0x37, 0x8D, 0xF3, 0x0E, 0xC1, 0x80, 0x71, 0xFF, 0x79, 0xDE, 0x3F, 0x87, 0xE0, 0xF8, 0x1F, 0x83,
0xF8, 0x77, 0x8E, 0x79, 0xC7, 0x38, 0x70, 0x73, 0xBF, 0xC7, 0xE1, 0xF0, 0x7C, 0x1F, 0x87, 0x71, 0xCE, 0x73, 0x80,
0xF8, 0x70, 0xC7, 0x06, 0x70, 0x37, 0x01, 0xF0, 0x0F, 0x80, 0x7E, 0x03, 0x78, 0x19, 0xE0, 0xC7, 0x06, 0x1C, 0x30,
0x70, 0xF9, 0xC7, 0x70, 0xFC, 0x1F, 0x03, 0xE0, 0x7E, 0x0F, 0xE1, 0xDE, 0x39, 0xC0, 0xE1, 0xDC, 0x3B, 0x87, 0x70,
0xEE, 0x1D, 0xFF, 0xB8, 0x77, 0x0E, 0xE1, 0xDC, 0x3B, 0x87, 0x70, 0xF0, 0x06, 0x00, 0xC0, 0x18, 0xC3, 0x61, 0xB0,
0xD8, 0x6F, 0xF6, 0x1B, 0x0D, 0x86, 0xC3, 0x80, 0xC0, 0x60, 0xE1, 0xFF, 0x0E, 0x38, 0x71, 0xC3, 0x8E, 0x1C, 0x7F,
0xE3, 0x87, 0x1C, 0x38, 0xE1, 0xC7, 0x0E, 0x38, 0x71, 0xC3, 0x80, 0xC3, 0xF0, 0xCC, 0x33, 0x0C, 0xFF, 0x30, 0xCC,
0x33, 0x0C, 0xC3, 0x00, 0xFF, 0xC0, 0xE1, 0xC0, 0xE1, 0xC0, 0xE1, 0xC0, 0xE1, 0xFC, 0xE1, 0xFE, 0xE1, 0xC7, 0xE1,
0xC3, 0xE1, 0xC3, 0xE1, 0xC3, 0xE1, 0xC3, 0xE1, 0xC7, 0x00, 0x07, 0x00, 0x0E, 0x00, 0x3C, 0xFF, 0x03, 0x1C, 0x0C,
0x70, 0x31, 0xFC, 0xC7, 0x7B, 0x1C, 0x6C, 0x71, 0xB1, 0xC7, 0xC7, 0x18, 0x00, 0x60, 0x03, 0x80, 0x3C, 0x1F, 0xC1,
0xE6, 0x1C, 0x00, 0xE0, 0x06, 0x1E, 0x31, 0xF9, 0x9C, 0xEC, 0xE7, 0x77, 0x3B, 0xB9, 0x8F, 0xDC, 0x3F, 0xC0, 0x38,
0x00, 0xF0, 0x03, 0xC0, 0x3E, 0x1E, 0x06, 0x79, 0xBF, 0xEC, 0xDB, 0x36, 0xDD, 0xFE, 0x3F, 0x01, 0xE0, 0x3C, 0x02,
0x03, 0xF8, 0xF3, 0x38, 0x07, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0E, 0x01, 0xC0, 0x1E, 0x61, 0xFC, 0x0E, 0x01,
0xC0, 0x78, 0x3F, 0x7A, 0x60, 0x60, 0xE0, 0x60, 0x60, 0x7B, 0x3F, 0x0C, 0x0E, 0x1C, 0xFF, 0xC3, 0x00, 0xC0, 0x30,
0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x3C, 0x07, 0x01, 0xC0, 0x70, 0xFF, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x1C, 0x0C, 0x0C, 0xE1, 0xDC, 0x39, 0xCE, 0x1D, 0xC3, 0xF0, 0x3C, 0x07, 0x80, 0x60, 0x0C, 0x01,
0x80, 0x30, 0x06, 0x00, 0xE3, 0xF1, 0x99, 0xCC, 0xE7, 0x61, 0xF0, 0xF8, 0x78, 0x1C, 0x0C, 0x06, 0x03, 0x00, 0xE1,
0xDC, 0x39, 0xCE, 0x19, 0xC3, 0xF0, 0x3C, 0x07, 0x83, 0xFC, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xE3, 0xF1, 0x99,
0xCE, 0xE7, 0x61, 0xF0, 0xF8, 0x78, 0x7F, 0x0C, 0x06, 0x03, 0x00, 0xE1, 0xCE, 0x38, 0xEE, 0x1F, 0x81, 0xF0, 0x1C,
0x07, 0x80, 0xF8, 0x3B, 0x8E, 0x71, 0xC7, 0x70, 0x70, 0x06, 0x00, 0xC0, 0x18, 0xE3, 0x3B, 0x8F, 0x87, 0x81, 0xC1,
0xF1, 0xF8, 0xCE, 0xE3, 0x80, 0xC0, 0x60, 0xFF, 0x98, 0x38, 0x30, 0x70, 0x60, 0xE0, 0xC1, 0xC1, 0x83, 0x83, 0x07,
0x06, 0x0E, 0x0C, 0x1C, 0x18, 0x38, 0x30, 0x70, 0x60, 0xFF, 0xF0, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0xFE, 0xC7,
0x18, 0xE3, 0x1C, 0x63, 0x8C, 0x71, 0x8E, 0x31, 0xC6, 0x3F, 0xE0, 0x0C, 0x01, 0x80, 0x61, 0xCC, 0x39, 0x87, 0x30,
0xE6, 0x1C, 0xC3, 0x9E, 0xF1, 0xFE, 0x01, 0xC0, 0x38, 0x07, 0x00, 0xF0, 0x06, 0x00, 0xC0, 0x18, 0x03, 0xE3, 0x71,
0xB8, 0xDC, 0x67, 0xF1, 0xF8, 0x0C, 0x06, 0x03, 0x80, 0xC0, 0x60, 0x61, 0xD8, 0x76, 0x1D, 0x87, 0x61, 0xDB, 0x77,
0xFC, 0xFF, 0x0D, 0xC3, 0x70, 0x1C, 0x07, 0xE3, 0xE3, 0xFB, 0xFB, 0x7F, 0x7F, 0x1B, 0x1B, 0x03, 0xE0, 0x70, 0x38,
0x1C, 0x0F, 0xF7, 0xBF, 0x8F, 0xC3, 0xE1, 0xF0, 0xF8, 0x7C, 0x30, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0xEE, 0xC7, 0xC7,
0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0x07, 0xF0, 0x3F, 0xE0, 0xC3, 0xB7, 0x06, 0xFC, 0x1D, 0xFF, 0xF1, 0x80, 0x07, 0x00,
0x1C, 0x00, 0x30, 0x00, 0xF3, 0x81, 0xFE, 0x0F, 0xC3, 0xBB, 0x63, 0xFC, 0x7F, 0xFE, 0x70, 0x06, 0x00, 0xF6, 0x0F,
0xC0, 0x07, 0xF0, 0x3F, 0xE0, 0xC3, 0xB7, 0x06, 0xFC, 0x1D, 0xFF, 0xF1, 0x80, 0x07, 0x00, 0x1C, 0x00, 0x30, 0x00,
0xF3, 0x81, 0xFE, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x0F, 0xC3, 0xBB, 0x63, 0xFC, 0x7F, 0xFE, 0x70, 0x06, 0x00,
0xF6, 0x0F, 0xC0, 0x60, 0x0C, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x06, 0xE0, 0x0F, 0x80, 0x00, 0x07, 0x9C, 0x77,
0x39, 0xC7, 0x77, 0x07, 0xFC, 0x07, 0xF8, 0x07, 0xE0, 0x1F, 0xE0, 0x6E, 0xE1, 0xDC, 0xC7, 0x39, 0xCE, 0x71, 0xF8,
0xE3, 0x80, 0x0D, 0x80, 0x7C, 0x00, 0x00, 0xCE, 0x67, 0x77, 0x1F, 0xF0, 0x7F, 0x03, 0xF8, 0x1F, 0xC1, 0xBB, 0x19,
0xCD, 0xCE, 0x70, 0xE3, 0xF3, 0xBB, 0x9F, 0x8F, 0xC7, 0xF3, 0xBD, 0xC7, 0xE1, 0xF0, 0xF8, 0x7C, 0x30, 0x38, 0xF8,
0x78, 0xC7, 0xCE, 0xDC, 0xF8, 0xFE, 0xDE, 0xC7, 0xC3, 0xC3, 0x07, 0x0E, 0x1E, 0x1F, 0xE0, 0xE7, 0x07, 0x38, 0x39,
0xC1, 0xCE, 0x0E, 0x70, 0x73, 0x83, 0x1C, 0x18, 0xE1, 0xC7, 0x1C, 0x39, 0xC1, 0xE0, 0x03, 0x00, 0x38, 0x01, 0x80,
0x3F, 0x87, 0x30, 0xE6, 0x1C, 0xC3, 0x98, 0x63, 0x0C, 0x63, 0x8C, 0xE1, 0xE0, 0x1C, 0x07, 0x00, 0xE0, 0xE1, 0xF8,
0x7E, 0x1F, 0x87, 0xE1, 0xFF, 0xFE, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0x01, 0xC0, 0x70, 0x38, 0xC3, 0xC3,
0xC3, 0xC3, 0xFF, 0xC3, 0xC3, 0xC3, 0xC3, 0x03, 0x07, 0x0E, 0xE1, 0xCE, 0x1C, 0xE1, 0xCE, 0x1C, 0xE1, 0xCF, 0xFC,
0xE1, 0xCE, 0x1C, 0xE1, 0xCE, 0x1C, 0xE1, 0xCE, 0x1E, 0x00, 0x60, 0x0E, 0x00, 0xC0, 0xC3, 0x30, 0xCC, 0x33, 0x0C,
0xFF, 0x30, 0xCC, 0x33, 0x0C, 0xC3, 0x80, 0x60, 0x38, 0x0C, 0xC3, 0xE1, 0xF0, 0xF8, 0x7C, 0x3E, 0x1F, 0xDE, 0xFF,
0x03, 0x81, 0xC0, 0xE0, 0xF0, 0x60, 0x30, 0x18, 0xE3, 0xE3, 0xE3, 0xE3, 0x7F, 0x3F, 0x03, 0x03, 0x0F, 0x0E, 0x0E,
0x60, 0x31, 0xE0, 0xE3, 0xC1, 0xC7, 0xC7, 0xCD, 0x8F, 0x99, 0x37, 0x33, 0x6E, 0x66, 0x9C, 0xC7, 0x39, 0x8E, 0x33,
0x00, 0x66, 0x00, 0xF0, 0x00, 0xC0, 0x03, 0x80, 0x06, 0x00, 0xE1, 0xCE, 0x1C, 0xF1, 0xCD, 0x3C, 0xDB, 0xCD, 0xEE,
0xCE, 0xEC, 0xCE, 0xC0, 0xF0, 0x07, 0x00, 0x70, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x1B, 0x01, 0xF0, 0x00, 0x00,
0xE0, 0x0E, 0x01, 0xF0, 0x1B, 0x01, 0xB8, 0x3B, 0x83, 0x1C, 0x71, 0xC7, 0xFC, 0x60, 0xEE, 0x0E, 0xE0, 0x60, 0x36,
0x3E, 0x00, 0x7E, 0x2F, 0x03, 0x7F, 0x77, 0xE3, 0xE3, 0x73, 0x7F, 0x1B, 0x81, 0xB8, 0x00, 0x00, 0xE0, 0x0E, 0x01,
0xF0, 0x1B, 0x01, 0xB8, 0x3B, 0x83, 0x1C, 0x71, 0xC7, 0xFC, 0x60, 0xEE, 0x0E, 0xE0, 0x60, 0x36, 0x36, 0x00, 0x7E,
0x2F, 0x03, 0x7F, 0x77, 0xE3, 0xE3, 0x73, 0x7F, 0x03, 0xFE, 0x03, 0xC0, 0x07, 0xC0, 0x06, 0xC0, 0x0E, 0xC0, 0x1C,
0xFE, 0x18, 0xC0, 0x38, 0xC0, 0x3F, 0xC0, 0x70, 0xC0, 0xE0, 0xC0, 0xE0, 0xFF, 0x7F, 0xF8, 0xBF, 0xF0, 0x79, 0xC0,
0xC3, 0x7F, 0xFF, 0xDC, 0x0E, 0x38, 0x1D, 0xF6, 0x7F, 0xF8, 0x7E, 0x1E, 0x00, 0x1F, 0xEE, 0x07, 0x03, 0x81, 0xC0,
0xFE, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0xFE, 0x3F, 0x0F, 0x00, 0x07, 0xE7, 0xF3, 0x1D, 0x8F, 0xFF, 0x60, 0x30,
0x1E, 0xC7, 0xE0, 0x3F, 0x86, 0x78, 0x03, 0x80, 0x70, 0x06, 0x00, 0xDF, 0xFB, 0x03, 0x60, 0xEE, 0x1C, 0xEF, 0x0F,
0xC0, 0x7E, 0x37, 0x80, 0xE0, 0x7F, 0xFB, 0x1D, 0x8E, 0xFE, 0x3E, 0x00, 0x1B, 0x83, 0x70, 0x00, 0x1F, 0xC3, 0x3C,
0x01, 0xC0, 0x38, 0x03, 0x00, 0x6F, 0xFD, 0x81, 0xB0, 0x77, 0x0E, 0x77, 0x87, 0xE0, 0x37, 0x1B, 0x80, 0x0F, 0xC6,
0xF0, 0x1C, 0x0F, 0xFF, 0x63, 0xB1, 0xDF, 0xC7, 0xC0, 0x06, 0xE0, 0x0D, 0xC0, 0x00, 0x07, 0x9C, 0x77, 0x39, 0xC7,
0x77, 0x07, 0xFC, 0x07, 0xF8, 0x07, 0xE0, 0x1F, 0xE0, 0x6E, 0xE1, 0xDC, 0xC7, 0x39, 0xCE, 0x71, 0xF8, 0xE3, 0x80,
0x0D, 0x80, 0x6C, 0x00, 0x00, 0xCE, 0x67, 0x77, 0x1F, 0xF0, 0x7F, 0x03, 0xF8, 0x1F, 0xC1, 0xBB, 0x19, 0xCD, 0xCE,
0x70, 0x76, 0x3B, 0x00, 0x0F, 0xE7, 0x70, 0x1C, 0x0E, 0x1E, 0x3F, 0x07, 0xC0, 0xE0, 0x30, 0x3F, 0x3F, 0xFC, 0x7E,
0x7E, 0x00, 0x7E, 0x6E, 0x07, 0x0E, 0x3E, 0x0F, 0x07, 0x6F, 0xFE, 0x7F, 0x83, 0x81, 0xC1, 0xC1, 0xC0, 0xF8, 0x3E,
0x07, 0x01, 0x81, 0xF9, 0xFF, 0xE0, 0x7F, 0x03, 0x81, 0x81, 0xC0, 0xC0, 0xF0, 0x3C, 0x07, 0x03, 0x81, 0xDB, 0xCF,
0xC0, 0x3F, 0x00, 0x00, 0x03, 0x83, 0xE1, 0xF8, 0xFE, 0x7F, 0x9B, 0xEE, 0xFB, 0x3F, 0x8F, 0xE3, 0xF0, 0xF8, 0x3E,
0x0C, 0x7E, 0x00, 0x00, 0xC7, 0xC7, 0xCF, 0xCF, 0xDB, 0xF3, 0xF3, 0xE3, 0xE3, 0x3F, 0x0F, 0xC0, 0x03, 0x83, 0xE1,
0xF8, 0xFE, 0x7F, 0x9B, 0xEE, 0xFB, 0x3F, 0x8F, 0xE3, 0xF0, 0xF8, 0x3E, 0x0C, 0x7E, 0x7E, 0x00, 0xC7, 0xC7, 0xCF,
0xCF, 0xDB, 0xF3, 0xF3, 0xE3, 0xE3, 0x0D, 0xC0, 0x6E, 0x00, 0x00, 0x3F, 0x83, 0xDE, 0x38, 0x39, 0xC0, 0xCC, 0x07,
0x60, 0x3B, 0x01, 0xD8, 0x0E, 0xE0, 0x67, 0x07, 0x1E, 0xF0, 0x7F, 0x00, 0x3F, 0x0F, 0xC0, 0x00, 0xFC, 0x7F, 0x98,
0x66, 0x1B, 0x87, 0x61, 0x98, 0x67, 0xF8, 0xFC, 0x1F, 0xC1, 0xEF, 0x1C, 0x1C, 0xE0, 0x66, 0x03, 0xBF, 0xFD, 0x80,
0xEC, 0x07, 0x70, 0x73, 0x83, 0x8F, 0x78, 0x3F, 0x80, 0x3F, 0x1F, 0xE6, 0x19, 0x86, 0xFF, 0xD8, 0x66, 0x19, 0xFE,
0x3F, 0x00, 0x0D, 0xC0, 0x6E, 0x00, 0x00, 0x3F, 0x83, 0xDE, 0x38, 0x39, 0xC0, 0xCC, 0x07, 0x7F, 0xFB, 0x01, 0xD8,
0x0E, 0xE0, 0xE7, 0x07, 0x1E, 0xF0, 0x7F, 0x00, 0x3F, 0x0F, 0xC0, 0x00, 0xFC, 0x7F, 0x98, 0x66, 0x1B, 0xFF, 0x61,
0x98, 0x67, 0xF8, 0xFC, 0x76, 0x1D, 0x80, 0x03, 0xF8, 0xEF, 0x80, 0xE0, 0x1C, 0x07, 0x3F, 0xC0, 0x70, 0x1C, 0x07,
0x03, 0xB1, 0xEF, 0xE0, 0x6C, 0x6C, 0x00, 0x7C, 0x6E, 0x07, 0x07, 0x3F, 0x07, 0x07, 0xDE, 0xFC, 0x3F, 0x00, 0x00,
0x03, 0x87, 0xE1, 0xDC, 0x77, 0x18, 0xEE, 0x3B, 0x07, 0xC1, 0xF0, 0x38, 0x0E, 0x17, 0x0F, 0x80, 0x3E, 0x00, 0x00,
0x1C, 0x6E, 0x33, 0x39, 0x9C, 0xEC, 0x36, 0x1F, 0x07, 0x03, 0x81, 0xC5, 0xC3, 0xC0, 0x3B, 0x0E, 0xC0, 0x03, 0x87,
0xE1, 0xDC, 0x77, 0x18, 0xEE, 0x3B, 0x07, 0xC1, 0xF0, 0x38, 0x0E, 0x17, 0x0F, 0x80, 0x36, 0x1B, 0x00, 0x1C, 0x6E,
0x33, 0x39, 0x9C, 0xEC, 0x36, 0x1F, 0x07, 0x03, 0x81, 0xC5, 0xC3, 0xC0, 0x0D, 0x87, 0xE1, 0xB0, 0x00, 0xE1, 0xF8,
0x77, 0x1D, 0xC6, 0x3B, 0x8E, 0xC1, 0xF0, 0x7C, 0x0E, 0x03, 0x85, 0xC3, 0xE0, 0x1B, 0x1F, 0x8D, 0x80, 0x0E, 0x37,
0x19, 0x9C, 0xCE, 0x76, 0x1B, 0x0F, 0x83, 0x81, 0xC0, 0xE2, 0xE1, 0xE0, 0x3B, 0x0E, 0xC0, 0x01, 0x87, 0x61, 0xD8,
0x76, 0x1D, 0x87, 0x61, 0xDE, 0xF3, 0xFC, 0x07, 0x01, 0xC0, 0x70, 0x1C, 0x76, 0x76, 0x00, 0xE3, 0xE3, 0xE3, 0xE3,
0x7F, 0x3F, 0x03, 0x03, 0x03, 0xFF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xF0, 0x30, 0x30,
0x30, 0xFF, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xF1, 0xC7, 0x00, 0x1D, 0x80, 0xEC, 0x00, 0x01, 0xC0, 0x7E, 0x03, 0xF0,
0x1F, 0x80, 0xFC, 0x07, 0xFF, 0x3F, 0x7D, 0xF8, 0xEF, 0xC7, 0x7E, 0x3B, 0xF7, 0xDF, 0xFC, 0xE0, 0x1B, 0x03, 0x60,
0x00, 0x60, 0x7C, 0x0F, 0x81, 0xFF, 0xBF, 0x77, 0xC7, 0xF8, 0xFF, 0x3B, 0xFF, 0x70, 0x7F, 0xC0, 0x7F, 0xFF, 0xC0,
0x7F, 0xFF, 0xC0, 0xDB, 0x66, 0xC0, 0x6D, 0xBD, 0x80, 0x6F, 0xF0, 0x7F, 0xEF, 0x3C, 0xF3, 0xC0, 0x7D, 0xF7, 0xDF,
0xF3, 0xC0, 0x6C, 0xDB, 0xB7, 0xE0, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x79, 0xF7, 0xDE, 0xE3,
0x8F, 0xC7, 0x1C, 0x7C, 0x70, 0x03, 0x67, 0x00, 0x3B, 0xB8, 0x01, 0xDF, 0x80, 0x06, 0xD8, 0x00, 0x3F, 0xC0, 0x00,
0x0D, 0xE7, 0xC0, 0xFF, 0xFE, 0x06, 0xCF, 0x30, 0x76, 0x79, 0x83, 0x3F, 0xFC, 0x38, 0xF3, 0xE0, 0x3B, 0x9D, 0xC7,
0x38, 0xE0, 0xE3, 0x1C, 0x77, 0x33, 0x80, 0x03, 0x83, 0x81, 0x81, 0xC0, 0xC0, 0xE0, 0x60, 0x70, 0x30, 0x38, 0x38,
0x18, 0x00, 0x0F, 0x87, 0xE3, 0x80, 0xE0, 0xFF, 0x0C, 0x03, 0x03, 0xFC, 0x38, 0x0E, 0x01, 0xDC, 0x3E, 0xFF, 0x86,
0x03, 0x01, 0xE1, 0xF3, 0xE1, 0xBC, 0x3E, 0x7C, 0x36, 0x03, 0x01, 0x80, 0x08, 0x1F, 0x89, 0xC0, 0x70, 0x3F, 0xFC,
0x38, 0x78, 0xFF, 0xB0, 0x18, 0x0E, 0x33, 0xF8, 0x60, 0xFF, 0x8F, 0x03, 0x9F, 0xE0, 0xE1, 0xE3, 0xE1, 0xC0, 0x70,
0x1C, 0x07, 0x03, 0x80, 0x7E, 0x1B, 0xC0, 0x38, 0x06, 0x01, 0x8F, 0xE7, 0xB9, 0x86, 0xE1, 0xB8, 0x6E, 0x39, 0xDC,
0x3E, 0x00, 0x0E, 0x01, 0xC0, 0x7C, 0x0D, 0x83, 0xB8, 0x63, 0x0C, 0x73, 0x8E, 0x60, 0xDC, 0x1F, 0x83, 0xFF, 0xF0,
0xFF, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xC0, 0xFF, 0xF0,
0x1C, 0x07, 0x03, 0x80, 0xE0, 0x30, 0x38, 0x38, 0x1C, 0x1C, 0x0E, 0x0E, 0x07, 0xFC, 0xFF, 0x80, 0x03, 0x83, 0x81,
0x81, 0xC0, 0xC0, 0xE0, 0x60, 0x70, 0x30, 0x38, 0x38, 0x18, 0x00, 0x77, 0x00, 0xC0, 0x70, 0x18, 0x06, 0x01, 0x80,
0xEF, 0x33, 0xCC, 0x3F, 0x07, 0x81, 0xE0, 0x78, 0x0C, 0x00, 0x7F, 0xBF, 0xFC, 0xCF, 0xFF, 0x7F, 0x80, 0x1E, 0x70,
0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x1C, 0x70, 0x7D, 0xFF, 0xC0, 0x00, 0x07, 0xDF, 0xFC,
0x03, 0x03, 0xBF, 0xE1, 0x81, 0xC7, 0xFC, 0xC0, 0x60, 0x03, 0x87, 0x9F, 0x0E, 0x03, 0xC0, 0x78, 0x0E, 0x00, 0xFF,
0x80, 0x70, 0x3E, 0x03, 0xC0, 0x70, 0xF3, 0xE1, 0xC0, 0x00, 0xFF, 0x80,
}; };
static const EpdGlyph pixelarial14Glyphs[] = { static const EpdGlyph pixelarial14Glyphs[] = {
{0, 0, 0, 0, 0, 0, 0}, //
{0, 0, 0, 0, 0, 0, 0}, // 
{0, 0, 4, 0, 0, 0, 0}, //
{0, 0, 4, 0, 0, 0, 0}, //
{0, 0, 0, 0, 0, 0, 0}, // 
{0, 0, 4, 0, 0, 0, 0}, // {0, 0, 4, 0, 0, 0, 0}, //
{2, 13, 3, 0, 13, 4, 0}, // ! {2, 13, 3, 0, 13, 4, 0}, // !
{4, 6, 5, 0, 13, 3, 4}, // " {4, 6, 5, 0, 13, 3, 4}, // "
@@ -167,18 +548,494 @@ static const EpdGlyph pixelarial14Glyphs[] = {
{2, 13, 3, 0, 13, 4, 1110}, // | {2, 13, 3, 0, 13, 4, 1110}, // |
{4, 17, 5, 0, 13, 9, 1114}, // } {4, 17, 5, 0, 13, 9, 1114}, // }
{11, 4, 12, 0, 9, 6, 1123}, // ~ {11, 4, 12, 0, 9, 6, 1123}, // ~
{3, 6, 4, 0, 13, 3, 1129}, // {0, 0, 4, 0, 0, 0, 1129}, //  
{3, 6, 4, 0, 13, 3, 1132}, // {3, 12, 5, 1, 9, 5, 1129}, // ¡
{6, 6, 6, 0, 13, 5, 1135}, // {8, 13, 10, 1, 11, 13, 1134}, // ¢
{6, 6, 6, 0, 13, 5, 1140}, // {8, 12, 10, 1, 12, 12, 1147}, // £
{9, 9, 10, 0, 11, 11, 1159}, // ¤
{10, 12, 10, 0, 12, 15, 1170}, // ¥
{3, 16, 5, 1, 13, 6, 1185}, // ¦
{8, 14, 8, 0, 13, 14, 1191}, // §
{6, 2, 6, 0, 12, 2, 1205}, // ¨
{12, 12, 14, 1, 12, 18, 1207}, // ©
{6, 6, 7, 0, 12, 5, 1225}, // ª
{8, 7, 8, 0, 8, 7, 1230}, // «
{9, 5, 10, 0, 6, 6, 1237}, // ¬
{5, 1, 5, 0, 5, 1, 1243}, // ­
{12, 12, 14, 1, 12, 18, 1244}, // ®
{6, 1, 6, 0, 12, 1, 1262}, // ¯
{6, 5, 6, 0, 13, 4, 1263}, // °
{9, 10, 10, 0, 10, 12, 1267}, // ±
{6, 7, 6, 0, 12, 6, 1279}, // ²
{6, 7, 6, 0, 12, 6, 1285}, // ³
{4, 3, 6, 2, 13, 2, 1291}, // ´
{8, 12, 10, 1, 9, 12, 1293}, // µ
{10, 15, 11, 0, 12, 19, 1305}, // ¶
{4, 2, 4, 0, 6, 1, 1324}, // ·
{4, 3, 6, 1, 0, 2, 1325}, // ¸
{5, 7, 6, 0, 12, 5, 1327}, // ¹
{7, 6, 8, 0, 12, 6, 1332}, // º
{8, 7, 8, 0, 8, 7, 1338}, // »
{15, 12, 15, 0, 12, 23, 1345}, // ¼
{15, 12, 15, 0, 12, 23, 1368}, // ½
{15, 12, 15, 0, 12, 23, 1391}, // ¾
{7, 12, 7, 0, 9, 11, 1414}, // ¿
{12, 16, 11, 0, 16, 24, 1425}, // À
{12, 16, 11, 0, 16, 24, 1449}, // Á
{12, 16, 11, 0, 16, 24, 1473}, // Â
{12, 16, 11, 0, 16, 24, 1497}, // Ã
{12, 15, 11, 0, 15, 23, 1521}, // Ä
{12, 15, 11, 0, 15, 23, 1544}, // Å
{16, 12, 16, 0, 12, 24, 1567}, // Æ
{11, 16, 11, 0, 13, 22, 1591}, // Ç
{9, 16, 10, 1, 16, 18, 1613}, // È
{9, 16, 10, 1, 16, 18, 1631}, // É
{9, 16, 10, 1, 16, 18, 1649}, // Ê
{9, 15, 10, 1, 15, 17, 1667}, // Ë
{4, 16, 5, 0, 16, 8, 1684}, // Ì
{4, 16, 5, 1, 16, 8, 1692}, // Í
{6, 16, 5, -1, 16, 12, 1700}, // Î
{6, 15, 5, -1, 15, 12, 1712}, // Ï
{12, 12, 12, 0, 12, 18, 1724}, // Ð
{10, 16, 12, 1, 16, 20, 1742}, // Ñ
{13, 16, 13, 0, 16, 26, 1762}, // Ò
{13, 16, 13, 0, 16, 26, 1788}, // Ó
{13, 16, 13, 0, 16, 26, 1814}, // Ô
{13, 16, 13, 0, 16, 26, 1840}, // Õ
{13, 15, 13, 0, 15, 25, 1866}, // Ö
{8, 7, 10, 1, 9, 7, 1891}, // ×
{13, 12, 13, 0, 12, 20, 1898}, // Ø
{10, 16, 12, 1, 16, 20, 1918}, // Ù
{10, 16, 12, 1, 16, 20, 1938}, // Ú
{10, 16, 12, 1, 16, 20, 1958}, // Û
{10, 15, 12, 1, 15, 19, 1978}, // Ü
{11, 16, 10, 0, 16, 22, 1997}, // Ý
{9, 12, 10, 1, 12, 14, 2019}, // Þ
{9, 13, 11, 1, 13, 15, 2033}, // ß
{8, 13, 9, 0, 13, 13, 2048}, // à
{8, 13, 9, 0, 13, 13, 2061}, // á
{8, 13, 9, 0, 13, 13, 2074}, // â
{8, 13, 9, 0, 13, 13, 2087}, // ã
{8, 12, 9, 0, 12, 12, 2100}, // ä
{8, 14, 9, 0, 14, 14, 2112}, // å
{14, 9, 15, 0, 9, 16, 2126}, // æ
{8, 12, 8, 0, 9, 12, 2142}, // ç
{9, 13, 10, 0, 13, 15, 2154}, // è
{9, 13, 10, 0, 13, 15, 2169}, // é
{9, 13, 10, 0, 13, 15, 2184}, // ê
{9, 12, 10, 0, 12, 14, 2199}, // ë
{4, 13, 4, 0, 13, 7, 2213}, // ì
{4, 13, 4, 1, 13, 7, 2220}, // í
{6, 13, 4, -1, 13, 10, 2227}, // î
{6, 12, 4, -1, 12, 9, 2237}, // ï
{10, 13, 10, 0, 13, 17, 2246}, // ð
{8, 13, 10, 1, 13, 13, 2263}, // ñ
{10, 13, 10, 0, 13, 17, 2276}, // ò
{10, 13, 10, 0, 13, 17, 2293}, // ó
{10, 13, 10, 0, 13, 17, 2310}, // ô
{10, 13, 10, 0, 13, 17, 2327}, // õ
{10, 12, 10, 0, 12, 15, 2344}, // ö
{9, 9, 10, 0, 9, 11, 2359}, // ÷
{10, 9, 10, 0, 9, 12, 2370}, // ø
{8, 13, 10, 1, 13, 13, 2382}, // ù
{8, 13, 10, 1, 13, 13, 2395}, // ú
{8, 13, 10, 1, 13, 13, 2408}, // û
{8, 12, 10, 1, 12, 12, 2421}, // ü
{9, 16, 8, 0, 13, 18, 2433}, // ý
{9, 16, 10, 1, 13, 18, 2451}, // þ
{9, 15, 8, 0, 12, 17, 2469}, // ÿ
{12, 15, 11, 0, 15, 23, 2486}, // Ā
{8, 12, 9, 0, 12, 12, 2509}, // ā
{12, 15, 11, 0, 15, 23, 2521}, // Ă
{8, 12, 9, 0, 12, 12, 2544}, // ă
{12, 15, 11, 0, 12, 23, 2556}, // Ą
{8, 12, 9, 0, 9, 12, 2579}, // ą
{11, 16, 11, 0, 16, 22, 2591}, // Ć
{8, 13, 8, 0, 13, 13, 2613}, // ć
{11, 16, 11, 0, 16, 22, 2626}, // Ĉ
{8, 13, 8, 0, 13, 13, 2648}, // ĉ
{11, 15, 11, 0, 15, 21, 2661}, // Ċ
{8, 12, 8, 0, 12, 12, 2682}, // ċ
{11, 16, 11, 0, 16, 22, 2694}, // Č
{8, 13, 8, 0, 13, 13, 2716}, // č
{11, 16, 12, 1, 16, 22, 2729}, // Ď
{12, 13, 11, 0, 13, 20, 2751}, // ď
{12, 12, 12, 0, 12, 18, 2771}, // Đ
{10, 13, 10, 0, 13, 17, 2789}, // đ
{9, 15, 10, 1, 15, 17, 2806}, // Ē
{9, 12, 10, 0, 12, 14, 2823}, // ē
{9, 15, 10, 1, 15, 17, 2837}, // Ĕ
{9, 12, 10, 0, 12, 14, 2854}, // ĕ
{9, 15, 10, 1, 15, 17, 2868}, // Ė
{9, 12, 10, 0, 12, 14, 2885}, // ė
{9, 15, 10, 1, 12, 17, 2899}, // Ę
{9, 12, 10, 0, 9, 14, 2916}, // ę
{9, 16, 10, 1, 16, 18, 2930}, // Ě
{9, 14, 10, 0, 14, 16, 2948}, // ě
{11, 16, 11, 0, 16, 22, 2964}, // Ĝ
{9, 16, 10, 0, 13, 18, 2986}, // ĝ
{11, 15, 11, 0, 15, 21, 3004}, // Ğ
{9, 15, 10, 0, 12, 17, 3025}, // ğ
{11, 15, 11, 0, 15, 21, 3042}, // Ġ
{9, 15, 10, 0, 12, 17, 3063}, // ġ
{11, 15, 11, 0, 12, 21, 3080}, // Ģ
{9, 16, 10, 0, 13, 18, 3101}, // ģ
{10, 16, 12, 1, 16, 20, 3119}, // Ĥ
{9, 16, 10, 0, 16, 18, 3139}, // ĥ
{13, 12, 12, 0, 12, 20, 3157}, // Ħ
{9, 13, 10, 0, 13, 15, 3177}, // ħ
{7, 16, 5, -1, 16, 14, 3192}, // Ĩ
{6, 13, 4, -1, 13, 10, 3206}, // ĩ
{6, 15, 5, -1, 15, 12, 3216}, // Ī
{6, 12, 4, -1, 12, 9, 3228}, // ī
{5, 15, 5, 0, 15, 10, 3237}, // Ĭ
{6, 12, 4, -1, 12, 9, 3247}, // ĭ
{4, 15, 5, 0, 12, 8, 3256}, // Į
{4, 16, 4, 0, 13, 8, 3264}, // į
{3, 15, 5, 1, 15, 6, 3272}, // İ
{2, 9, 4, 1, 9, 3, 3278}, // ı
{11, 12, 13, 1, 12, 17, 3281}, // IJ
{7, 16, 9, 1, 13, 14, 3298}, // ij
{9, 16, 9, 0, 16, 18, 3312}, // Ĵ
{7, 16, 4, -2, 13, 14, 3330}, // ĵ
{10, 15, 11, 1, 12, 19, 3344}, // Ķ
{8, 16, 9, 1, 13, 16, 3363}, // ķ
{8, 9, 9, 1, 9, 9, 3379}, // ĸ
{8, 16, 9, 1, 16, 16, 3388}, // Ĺ
{4, 16, 5, 1, 16, 8, 3404}, // ĺ
{8, 15, 9, 1, 12, 15, 3412}, // Ļ
{5, 16, 5, 0, 13, 10, 3427}, // ļ
{8, 12, 9, 1, 12, 12, 3437}, // Ľ
{5, 13, 5, 1, 13, 9, 3449}, // ľ
{8, 12, 9, 1, 12, 12, 3458}, // Ŀ
{6, 13, 6, 1, 13, 10, 3470}, // ŀ
{10, 12, 9, -1, 12, 15, 3480}, // Ł
{5, 13, 5, 0, 13, 9, 3495}, // ł
{10, 16, 12, 1, 16, 20, 3504}, // Ń
{8, 13, 10, 1, 13, 13, 3524}, // ń
{10, 15, 12, 1, 12, 19, 3537}, // Ņ
{8, 12, 10, 1, 9, 12, 3556}, // ņ
{10, 16, 12, 1, 16, 20, 3568}, // Ň
{8, 13, 10, 1, 13, 13, 3588}, // ň
{9, 14, 10, 0, 14, 16, 3601}, // ʼn
{10, 15, 12, 1, 12, 19, 3617}, // Ŋ
{8, 12, 10, 1, 9, 12, 3636}, // ŋ
{13, 15, 13, 0, 15, 25, 3648}, // Ō
{10, 12, 10, 0, 12, 15, 3673}, // ō
{13, 15, 13, 0, 15, 25, 3688}, // Ŏ
{10, 12, 10, 0, 12, 15, 3713}, // ŏ
{13, 16, 13, 0, 16, 26, 3728}, // Ő
{10, 13, 10, 0, 13, 17, 3754}, // ő
{17, 12, 17, 0, 12, 26, 3771}, // Œ
{16, 9, 16, 0, 9, 18, 3797}, // œ
{10, 16, 11, 1, 16, 20, 3815}, // Ŕ
{6, 13, 7, 1, 13, 10, 3835}, // ŕ
{10, 15, 11, 1, 12, 19, 3845}, // Ŗ
{7, 12, 7, 0, 9, 11, 3864}, // ŗ
{10, 16, 11, 1, 16, 20, 3875}, // Ř
{6, 13, 7, 1, 13, 10, 3895}, // ř
{9, 16, 9, 0, 16, 18, 3905}, // Ś
{7, 13, 8, 0, 13, 12, 3923}, // ś
{9, 16, 9, 0, 16, 18, 3935}, // Ŝ
{7, 13, 8, 0, 13, 12, 3953}, // ŝ
{9, 15, 9, 0, 12, 17, 3965}, // Ş
{7, 12, 8, 0, 9, 11, 3982}, // ş
{9, 16, 9, 0, 16, 18, 3993}, // Š
{7, 13, 8, 0, 13, 12, 4011}, // š
{10, 15, 10, 0, 12, 19, 4023}, // Ţ
{6, 15, 7, 1, 12, 12, 4042}, // ţ
{10, 16, 10, 0, 16, 20, 4054}, // Ť
{6, 13, 7, 1, 13, 10, 4074}, // ť
{10, 12, 10, 0, 12, 15, 4084}, // Ŧ
{6, 12, 7, 1, 12, 9, 4099}, // ŧ
{10, 16, 12, 1, 16, 20, 4108}, // Ũ
{8, 13, 10, 1, 13, 13, 4128}, // ũ
{10, 15, 12, 1, 15, 19, 4141}, // Ū
{8, 12, 10, 1, 12, 12, 4160}, // ū
{10, 15, 12, 1, 15, 19, 4172}, // Ŭ
{8, 12, 10, 1, 12, 12, 4191}, // ŭ
{10, 17, 12, 1, 17, 22, 4203}, // Ů
{8, 14, 10, 1, 14, 14, 4225}, // ů
{10, 16, 12, 1, 16, 20, 4239}, // Ű
{8, 13, 10, 1, 13, 13, 4259}, // ű
{10, 15, 12, 1, 12, 19, 4272}, // Ų
{8, 12, 10, 1, 9, 12, 4291}, // ų
{16, 16, 16, 0, 16, 32, 4303}, // Ŵ
{13, 13, 13, 0, 13, 22, 4335}, // ŵ
{11, 16, 10, 0, 16, 22, 4357}, // Ŷ
{9, 16, 8, 0, 13, 18, 4379}, // ŷ
{11, 15, 10, 0, 15, 21, 4397}, // Ÿ
{10, 16, 10, 0, 16, 20, 4418}, // Ź
{8, 13, 8, 0, 13, 13, 4438}, // ź
{10, 15, 10, 0, 15, 19, 4451}, // Ż
{8, 12, 8, 0, 12, 12, 4470}, // ż
{10, 16, 10, 0, 16, 20, 4482}, // Ž
{8, 13, 8, 0, 13, 13, 4502}, // ž
{6, 14, 5, 1, 14, 11, 4515}, // ſ
{6, 2, 6, 0, 12, 2, 4526}, // ̑
{9, 16, 10, 1, 16, 18, 4528}, // Ѐ
{9, 15, 10, 1, 15, 17, 4546}, // Ё
{13, 12, 13, 0, 12, 20, 4563}, // Ђ
{8, 16, 9, 1, 16, 16, 4583}, // Ѓ
{11, 12, 11, 0, 12, 17, 4599}, // Є
{9, 12, 9, 0, 12, 14, 4616}, // Ѕ
{3, 12, 5, 1, 12, 5, 4630}, // І
{6, 15, 5, -1, 15, 12, 4635}, // Ї
{8, 12, 9, 0, 12, 12, 4647}, // Ј
{18, 13, 18, 0, 12, 30, 4659}, // Љ
{16, 12, 17, 1, 12, 24, 4689}, // Њ
{12, 12, 13, 0, 12, 18, 4713}, // Ћ
{10, 16, 11, 1, 16, 20, 4731}, // Ќ
{10, 16, 12, 1, 16, 20, 4751}, // Ѝ
{10, 15, 10, 0, 15, 19, 4771}, // Ў
{10, 15, 12, 1, 12, 19, 4790}, // Џ
{12, 12, 11, 0, 12, 18, 4809}, // А
{9, 12, 11, 1, 12, 14, 4827}, // Б
{10, 12, 11, 1, 12, 15, 4841}, // В
{8, 12, 9, 1, 12, 12, 4856}, // Г
{12, 15, 12, 0, 12, 23, 4868}, // Д
{9, 12, 10, 1, 12, 14, 4891}, // Е
{15, 12, 15, 0, 12, 23, 4905}, // Ж
{9, 12, 10, 0, 12, 14, 4928}, // З
{10, 12, 12, 1, 12, 15, 4942}, // И
{10, 15, 12, 1, 15, 19, 4957}, // Й
{10, 12, 11, 1, 12, 15, 4976}, // К
{11, 12, 12, 0, 12, 17, 4991}, // Л
{13, 12, 15, 1, 12, 20, 5008}, // М
{10, 12, 12, 1, 12, 15, 5028}, // Н
{13, 12, 13, 0, 12, 20, 5043}, // О
{10, 12, 12, 1, 12, 15, 5063}, // П
{9, 12, 10, 1, 12, 14, 5078}, // Р
{11, 13, 11, 0, 13, 18, 5092}, // С
{10, 12, 10, 0, 12, 15, 5110}, // Т
{10, 12, 10, 0, 12, 15, 5125}, // У
{14, 13, 15, 0, 13, 23, 5140}, // Ф
{11, 12, 11, 0, 12, 17, 5163}, // Х
{11, 15, 12, 1, 12, 21, 5180}, // Ц
{10, 12, 11, 0, 12, 15, 5201}, // Ч
{15, 12, 17, 1, 12, 23, 5216}, // Ш
{16, 15, 17, 1, 12, 30, 5239}, // Щ
{12, 12, 12, 0, 12, 18, 5269}, // Ъ
{13, 12, 15, 1, 12, 20, 5287}, // Ы
{9, 12, 10, 1, 12, 14, 5307}, // Ь
{10, 12, 11, 0, 12, 15, 5321}, // Э
{16, 12, 18, 1, 12, 24, 5336}, // Ю
{10, 12, 11, 0, 12, 15, 5360}, // Я
{8, 9, 9, 0, 9, 9, 5375}, // а
{9, 13, 10, 1, 13, 15, 5384}, // б
{8, 9, 9, 1, 9, 9, 5399}, // в
{6, 9, 7, 1, 9, 7, 5408}, // г
{10, 11, 10, 0, 9, 14, 5415}, // д
{9, 9, 10, 0, 9, 11, 5429}, // е
{13, 9, 13, 0, 9, 15, 5440}, // ж
{8, 9, 8, 0, 9, 9, 5455}, // з
{8, 9, 10, 1, 9, 9, 5464}, // и
{8, 12, 10, 1, 12, 12, 5473}, // й
{8, 9, 9, 1, 9, 9, 5485}, // к
{9, 9, 10, 0, 9, 11, 5494}, // л
{11, 9, 12, 1, 9, 13, 5505}, // м
{8, 9, 10, 1, 9, 9, 5518}, // н
{10, 9, 10, 0, 9, 12, 5527}, // о
{8, 9, 10, 1, 9, 9, 5539}, // п
{9, 12, 10, 1, 9, 14, 5548}, // р
{8, 9, 8, 0, 9, 9, 5562}, // с
{8, 9, 8, 0, 9, 9, 5571}, // т
{9, 12, 8, 0, 9, 14, 5580}, // у
{13, 16, 13, 0, 13, 26, 5594}, // ф
{9, 9, 9, 0, 9, 11, 5620}, // х
{9, 11, 10, 1, 9, 13, 5631}, // ц
{8, 9, 9, 0, 9, 9, 5644}, // ч
{12, 9, 14, 1, 9, 14, 5653}, // ш
{13, 11, 14, 1, 9, 18, 5667}, // щ
{10, 9, 10, 0, 9, 12, 5685}, // ъ
{11, 9, 13, 1, 9, 13, 5697}, // ы
{8, 9, 9, 1, 9, 9, 5710}, // ь
{8, 9, 8, 0, 9, 9, 5719}, // э
{12, 9, 14, 1, 9, 14, 5728}, // ю
{8, 9, 9, 0, 9, 9, 5742}, // я
{9, 13, 10, 0, 13, 15, 5751}, // ѐ
{9, 12, 10, 0, 12, 14, 5766}, // ё
{9, 16, 10, 0, 13, 18, 5780}, // ђ
{6, 13, 7, 1, 13, 10, 5798}, // ѓ
{8, 9, 8, 0, 9, 9, 5808}, // є
{7, 9, 8, 0, 9, 8, 5817}, // ѕ
{3, 13, 4, 1, 13, 5, 5825}, // і
{6, 12, 4, -1, 12, 9, 5830}, // ї
{6, 16, 4, -2, 13, 12, 5839}, // ј
{15, 9, 15, 0, 9, 17, 5851}, // љ
{13, 9, 14, 1, 9, 15, 5868}, // њ
{9, 13, 10, 0, 13, 15, 5883}, // ћ
{8, 13, 9, 1, 13, 13, 5898}, // ќ
{8, 13, 10, 1, 13, 13, 5911}, // ѝ
{9, 15, 8, 0, 12, 17, 5924}, // ў
{8, 11, 10, 1, 9, 11, 5941}, // џ
{12, 13, 12, 0, 13, 20, 5952}, // Ѣ
{10, 13, 10, 0, 13, 17, 5972}, // ѣ
{13, 12, 13, 0, 12, 20, 5989}, // Ѳ
{10, 9, 10, 0, 9, 12, 6009}, // ѳ
{14, 12, 13, 0, 12, 21, 6021}, // Ѵ
{10, 9, 10, 0, 9, 12, 6042}, // ѵ
{12, 18, 13, 1, 15, 27, 6054}, // Ҋ
{10, 15, 10, 1, 12, 19, 6081}, // ҋ
{11, 13, 11, 0, 13, 18, 6100}, // Ҍ
{9, 9, 9, 0, 9, 11, 6118}, // ҍ
{9, 12, 10, 1, 12, 14, 6129}, // Ҏ
{9, 12, 10, 1, 9, 14, 6143}, // ҏ
{8, 14, 9, 1, 14, 14, 6157}, // Ґ
{6, 11, 7, 1, 11, 9, 6171}, // ґ
{9, 12, 9, 0, 12, 14, 6180}, // Ғ
{7, 9, 7, 0, 9, 8, 6194}, // ғ
{9, 15, 11, 1, 12, 17, 6202}, // Ҕ
{8, 12, 9, 1, 9, 12, 6219}, // ҕ
{16, 15, 16, 0, 12, 30, 6231}, // Җ
{14, 11, 13, 0, 9, 20, 6261}, // җ
{9, 15, 10, 0, 12, 17, 6281}, // Ҙ
{8, 12, 8, 0, 9, 12, 6298}, // ҙ
{11, 15, 11, 1, 12, 21, 6310}, // Қ
{9, 12, 9, 1, 9, 14, 6331}, // қ
{11, 12, 12, 1, 12, 17, 6345}, // Ҝ
{10, 9, 11, 1, 9, 12, 6362}, // ҝ
{11, 12, 11, 0, 12, 17, 6374}, // Ҟ
{10, 9, 9, 0, 9, 12, 6391}, // ҟ
{13, 12, 13, 0, 12, 20, 6403}, // Ҡ
{11, 9, 10, 0, 9, 13, 6423}, // ҡ
{11, 15, 12, 1, 12, 21, 6436}, // Ң
{9, 11, 10, 1, 9, 13, 6457}, // ң
{13, 12, 14, 1, 12, 20, 6470}, // Ҥ
{10, 9, 11, 1, 9, 12, 6490}, // ҥ
{16, 15, 18, 1, 12, 30, 6502}, // Ҧ
{14, 12, 15, 1, 9, 21, 6532}, // ҧ
{13, 15, 13, 0, 12, 25, 6553}, // Ҩ
{10, 11, 10, 0, 9, 14, 6578}, // ҩ
{11, 16, 11, 0, 13, 22, 6592}, // Ҫ
{8, 12, 8, 0, 9, 12, 6614}, // ҫ
{10, 15, 10, 0, 12, 19, 6626}, // Ҭ
{8, 11, 8, 0, 9, 11, 6645}, // ҭ
{11, 12, 10, 0, 12, 17, 6656}, // Ү
{9, 12, 9, 0, 9, 14, 6673}, // ү
{11, 12, 10, 0, 12, 17, 6687}, // Ұ
{9, 12, 9, 0, 9, 14, 6704}, // ұ
{11, 15, 11, 0, 12, 21, 6718}, // Ҳ
{9, 11, 9, 0, 9, 13, 6739}, // ҳ
{15, 15, 14, 0, 12, 29, 6752}, // Ҵ
{11, 11, 11, 0, 9, 16, 6781}, // ҵ
{11, 16, 11, 0, 12, 22, 6797}, // Ҷ
{9, 11, 9, 0, 9, 13, 6819}, // ҷ
{10, 12, 11, 0, 12, 15, 6832}, // Ҹ
{8, 9, 9, 0, 9, 9, 6847}, // ҹ
{9, 12, 11, 1, 12, 14, 6856}, // Һ
{8, 13, 10, 1, 13, 13, 6870}, // һ
{14, 12, 14, 0, 12, 21, 6883}, // Ҽ
{11, 9, 11, 0, 9, 13, 6904}, // ҽ
{14, 15, 14, 0, 12, 27, 6917}, // Ҿ
{11, 11, 11, 0, 9, 16, 6944}, // ҿ
{3, 12, 5, 1, 12, 5, 6960}, // Ӏ
{15, 15, 15, 0, 15, 29, 6965}, // Ӂ
{13, 12, 13, 0, 12, 20, 6994}, // ӂ
{9, 15, 11, 1, 12, 17, 7014}, // Ӄ
{8, 12, 9, 1, 9, 12, 7031}, // ӄ
{13, 15, 12, 0, 12, 25, 7043}, // Ӆ
{11, 12, 10, 0, 9, 17, 7068}, // ӆ
{10, 15, 12, 1, 12, 19, 7085}, // Ӈ
{8, 12, 10, 1, 9, 12, 7104}, // ӈ
{12, 15, 12, 1, 12, 23, 7116}, // Ӊ
{10, 12, 10, 1, 9, 15, 7139}, // ӊ
{9, 15, 11, 1, 12, 17, 7154}, // Ӌ
{8, 11, 9, 0, 9, 11, 7171}, // ӌ
{15, 15, 15, 1, 12, 29, 7182}, // Ӎ
{12, 12, 13, 1, 9, 18, 7211}, // ӎ
{3, 12, 5, 1, 12, 5, 7229}, // ӏ
{12, 15, 11, 0, 15, 23, 7234}, // Ӑ
{8, 12, 9, 0, 12, 12, 7257}, // ӑ
{12, 15, 11, 0, 15, 23, 7269}, // Ӓ
{8, 12, 9, 0, 12, 12, 7292}, // ӓ
{16, 12, 16, 0, 12, 24, 7304}, // Ӕ
{14, 9, 15, 0, 9, 16, 7328}, // ӕ
{9, 15, 10, 1, 15, 17, 7344}, // Ӗ
{9, 12, 10, 0, 12, 14, 7361}, // ӗ
{11, 12, 12, 0, 12, 17, 7375}, // Ә
{9, 9, 10, 0, 9, 11, 7392}, // ә
{11, 15, 12, 0, 15, 21, 7403}, // Ӛ
{9, 12, 10, 0, 12, 14, 7424}, // ӛ
{15, 15, 15, 0, 15, 29, 7438}, // Ӝ
{13, 12, 13, 0, 12, 20, 7467}, // ӝ
{9, 15, 10, 0, 15, 17, 7487}, // Ӟ
{8, 12, 8, 0, 12, 12, 7504}, // ӟ
{9, 12, 10, 0, 12, 14, 7516}, // Ӡ
{9, 12, 8, -1, 9, 14, 7530}, // ӡ
{10, 15, 12, 1, 15, 19, 7544}, // Ӣ
{8, 12, 10, 1, 12, 12, 7563}, // ӣ
{10, 15, 12, 1, 15, 19, 7575}, // Ӥ
{8, 12, 10, 1, 12, 12, 7594}, // ӥ
{13, 15, 13, 0, 15, 25, 7606}, // Ӧ
{10, 12, 10, 0, 12, 15, 7631}, // ӧ
{13, 12, 13, 0, 12, 20, 7646}, // Ө
{10, 9, 10, 0, 9, 12, 7666}, // ө
{13, 15, 13, 0, 15, 25, 7678}, // Ӫ
{10, 12, 10, 0, 12, 15, 7703}, // ӫ
{10, 15, 11, 0, 15, 19, 7718}, // Ӭ
{8, 12, 8, 0, 12, 12, 7737}, // ӭ
{10, 15, 10, 0, 15, 19, 7749}, // Ӯ
{9, 15, 8, 0, 12, 17, 7768}, // ӯ
{10, 15, 10, 0, 15, 19, 7785}, // Ӱ
{9, 15, 8, 0, 12, 17, 7804}, // ӱ
{10, 16, 10, 0, 16, 20, 7821}, // Ӳ
{9, 16, 8, 0, 13, 18, 7841}, // ӳ
{10, 15, 11, 0, 15, 19, 7859}, // Ӵ
{8, 12, 9, 0, 12, 12, 7878}, // ӵ
{8, 15, 9, 1, 12, 15, 7890}, // Ӷ
{6, 11, 7, 1, 9, 9, 7905}, // ӷ
{13, 15, 15, 1, 15, 25, 7914}, // Ӹ
{11, 12, 13, 1, 12, 17, 7939}, // ӹ
{10, 1, 8, -1, 5, 2, 7956}, //
{18, 1, 17, -1, 5, 3, 7958}, // —
{18, 1, 17, -1, 5, 3, 7961}, // ―
{3, 6, 4, 0, 13, 3, 7964}, //
{3, 6, 4, 0, 13, 3, 7967}, //
{3, 4, 4, 0, 2, 2, 7970}, //
{6, 6, 6, 0, 13, 5, 7972}, // “
{6, 6, 6, 0, 13, 5, 7977}, // ”
{7, 4, 7, 0, 2, 4, 7982}, // „
{8, 14, 8, 0, 12, 14, 7986}, // †
{8, 14, 8, 0, 12, 14, 8000}, // ‡
{6, 4, 6, 0, 8, 3, 8014}, // •
{15, 2, 17, 1, 2, 4, 8017}, // …
{21, 12, 21, 0, 12, 32, 8021}, // ‰
{5, 7, 5, 0, 8, 5, 8053}, //
{5, 7, 5, 0, 8, 5, 8058}, //
{9, 12, 3, -3, 12, 14, 8063}, //
{10, 12, 10, 0, 12, 15, 8077}, // €
{9, 12, 10, 0, 12, 14, 8092}, // ₮
{9, 14, 10, 0, 13, 16, 8106}, // ₴
{9, 12, 10, 1, 12, 14, 8122}, // ₹
{10, 13, 10, 0, 13, 17, 8136}, // ∂
{11, 12, 11, 0, 12, 17, 8153}, // ∆
{10, 13, 12, 1, 11, 17, 8170}, // ∏
{9, 14, 9, 0, 12, 16, 8187}, // ∑
{9, 1, 10, 0, 5, 2, 8203}, //
{9, 12, 3, -3, 12, 14, 8205}, //
{4, 2, 4, 0, 6, 1, 8219}, // ∙
{10, 13, 10, 0, 13, 17, 8220}, // √
{10, 5, 10, 0, 7, 7, 8237}, // ∞
{7, 16, 6, 0, 13, 14, 8244}, // ∫
{9, 6, 10, 0, 8, 7, 8258}, // ≈
{9, 8, 10, 0, 9, 9, 8265}, // ≠
{9, 9, 10, 0, 9, 11, 8274}, // ≤
{9, 9, 10, 0, 9, 11, 8285}, // ≥
}; };
static const EpdUnicodeInterval pixelarial14Intervals[] = { static const EpdUnicodeInterval pixelarial14Intervals[] = {
{0x20, 0x7E, 0x0}, {0x0, 0x0, 0x0}, {0x8, 0x9, 0x1}, {0xD, 0xD, 0x3}, {0x1D, 0x1D, 0x4},
{0x2018, 0x2019, 0x5F}, {0x20, 0x7E, 0x5}, {0xA0, 0xFF, 0x64}, {0x100, 0x17F, 0xC4}, {0x311, 0x311, 0x144},
{0x201C, 0x201D, 0x61}, {0x400, 0x45F, 0x145}, {0x462, 0x463, 0x1A5}, {0x472, 0x475, 0x1A7}, {0x48A, 0x4F9, 0x1AB},
{0x2013, 0x2015, 0x21B}, {0x2018, 0x201A, 0x21E}, {0x201C, 0x201E, 0x221}, {0x2020, 0x2022, 0x224},
{0x2026, 0x2026, 0x227}, {0x2030, 0x2030, 0x228}, {0x2039, 0x203A, 0x229}, {0x2044, 0x2044, 0x22B},
{0x20AC, 0x20AC, 0x22C}, {0x20AE, 0x20AE, 0x22D}, {0x20B4, 0x20B4, 0x22E}, {0x20B9, 0x20B9, 0x22F},
{0x2202, 0x2202, 0x230}, {0x2206, 0x2206, 0x231}, {0x220F, 0x220F, 0x232}, {0x2211, 0x2212, 0x233},
{0x2215, 0x2215, 0x235}, {0x2219, 0x221A, 0x236}, {0x221E, 0x221E, 0x238}, {0x222B, 0x222B, 0x239},
{0x2248, 0x2248, 0x23A}, {0x2260, 0x2260, 0x23B}, {0x2264, 0x2265, 0x23C},
}; };
static const EpdFontData pixelarial14 = { static const EpdFontData pixelarial14 = {
pixelarial14Bitmaps, pixelarial14Glyphs, pixelarial14Intervals, 3, 17, 13, -4, false, pixelarial14Bitmaps, pixelarial14Glyphs, pixelarial14Intervals, 35, 17, 13, -4, false,
}; };
+558 -70
View File
@@ -7,7 +7,7 @@
#pragma once #pragma once
#include "EpdFontData.h" #include "EpdFontData.h"
static const uint8_t ubuntu_10Bitmaps[7175] = { static const uint8_t ubuntu_10Bitmaps[12366] = {
0xEE, 0xEE, 0xEE, 0xE6, 0x66, 0x00, 0xEF, 0xE0, 0xEF, 0xDF, 0xBF, 0x6E, 0xC0, 0x1C, 0x61, 0xCE, 0x1C, 0xE1, 0x8E, 0xEE, 0xEE, 0xEE, 0xE6, 0x66, 0x00, 0xEF, 0xE0, 0xEF, 0xDF, 0xBF, 0x6E, 0xC0, 0x1C, 0x61, 0xCE, 0x1C, 0xE1, 0x8E,
0xFF, 0xFF, 0xFF, 0x39, 0xC3, 0x9C, 0x39, 0xCF, 0xFF, 0xFF, 0xF7, 0x18, 0x73, 0x87, 0x38, 0x63, 0x80, 0x0C, 0x03, 0xFF, 0xFF, 0xFF, 0x39, 0xC3, 0x9C, 0x39, 0xCF, 0xFF, 0xFF, 0xF7, 0x18, 0x73, 0x87, 0x38, 0x63, 0x80, 0x0C, 0x03,
0x03, 0xF9, 0xFE, 0xFB, 0xB8, 0x0E, 0x01, 0xE0, 0x7E, 0x07, 0xE0, 0x78, 0x07, 0x01, 0xF9, 0xFF, 0xFB, 0xFC, 0x0C, 0x03, 0xF9, 0xFE, 0xFB, 0xB8, 0x0E, 0x01, 0xE0, 0x7E, 0x07, 0xE0, 0x78, 0x07, 0x01, 0xF9, 0xFF, 0xFB, 0xFC, 0x0C,
@@ -359,33 +359,306 @@ static const uint8_t ubuntu_10Bitmaps[7175] = {
0x01, 0xC0, 0x3C, 0x07, 0x80, 0x70, 0x0E, 0x01, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0x33, 0x01, 0xC0, 0x3C, 0x07, 0x80, 0x70, 0x0E, 0x01, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0x33,
0x0F, 0xC1, 0xE0, 0x30, 0x00, 0x1F, 0xE7, 0xF8, 0x1E, 0x0F, 0x03, 0x81, 0xC0, 0xF0, 0x78, 0x1C, 0x0F, 0xFF, 0xFF, 0x0F, 0xC1, 0xE0, 0x30, 0x00, 0x1F, 0xE7, 0xF8, 0x1E, 0x0F, 0x03, 0x81, 0xC0, 0xF0, 0x78, 0x1C, 0x0F, 0xFF, 0xFF,
0x3F, 0x7E, 0xF8, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x7B, 0xFF, 0xC0, 0x3F, 0x7E, 0xF8, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x7B, 0xFF, 0xC0,
0x7F, 0xF7, 0xFF, 0x7F, 0xFF, 0xFD, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFD, 0xFF, 0xFF, 0xF0, 0x76, 0xEE, 0xE0, 0x77, 0x1C, 0x03, 0x80, 0x38, 0x03, 0x00, 0x01, 0xFF, 0xBF, 0xF7, 0x00, 0xE0, 0x1C, 0x03, 0x80, 0x7F, 0xCF, 0xF9, 0xC0,
0x76, 0xE0, 0x77, 0x76, 0xE0, 0x76, 0x6E, 0xEE, 0xEE, 0xEE, 0x77, 0x77, 0x77, 0x6E, 0xEE, 0x77, 0x77, 0x77, 0x6E, 0x38, 0x07, 0x00, 0xE0, 0x1C, 0x03, 0xFF, 0xFF, 0xF0, 0x3B, 0x87, 0x70, 0x00, 0x7F, 0xEF, 0xFD, 0xC0, 0x38, 0x07,
0xEE, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x3F, 0xFF, 0xFC, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0x00, 0xE0, 0x1F, 0xF3, 0xFE, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00, 0xFF, 0xFF, 0xFC, 0xFF, 0xF1, 0xFF, 0xE0,
0xC0, 0x30, 0x0C, 0x03, 0x00, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x3F, 0xFF, 0xFC, 0x30, 0x0C, 0x03, 0x0F, 0xFF, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xFF, 0x03, 0xFF, 0x07, 0x9F, 0x0E, 0x0E, 0x1C, 0x1C, 0x38, 0x38, 0x70, 0x70,
0xFF, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xFB, 0xFF, 0xFF, 0xF8, 0xE1, 0xC3, 0xF0, 0xE1, 0xF8, 0x70, 0xE1, 0xE1, 0xCF, 0x83, 0x9F, 0x00, 0x07, 0x03, 0xC0, 0xE0, 0x30, 0x00, 0x3F, 0xFF, 0xFF, 0x80, 0xE0, 0x38, 0x0E,
0xE0, 0x7C, 0x38, 0x00, 0xEE, 0x38, 0x00, 0xC6, 0x70, 0x00, 0xC6, 0x70, 0x00, 0xC6, 0xE0, 0x00, 0xEE, 0xE0, 0x00, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0x1F, 0xF3, 0xFF, 0x7C, 0xE7, 0x00, 0xE0,
0x7D, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, 0xBE, 0x3E, 0x07, 0x7F, 0x7F, 0x07, 0x63, 0x67, 0x0E, 0x63, 0x63, 0x0E, 0x0E, 0x00, 0xFF, 0x8F, 0xF8, 0xE0, 0x0E, 0x00, 0xF0, 0x07, 0x00, 0x7E, 0xF3, 0xFF, 0x1F, 0xF0, 0x3F, 0xCF, 0xF9,
0x63, 0x67, 0x1C, 0x77, 0x77, 0x1C, 0x3E, 0x3E, 0x1C, 0xE3, 0x9C, 0xF1, 0xC3, 0x8E, 0x1C, 0x61, 0xC7, 0x8E, 0x1C, 0xE7, 0x38, 0x07, 0x00, 0xF0, 0x1F, 0x81, 0xFC, 0x0F, 0xC0, 0x3C, 0x03, 0x80, 0x77, 0x3F, 0xFF, 0x9F, 0xE0, 0xFF,
0xE7, 0x9C, 0x60, 0x00, 0xE0, 0x38, 0x07, 0x01, 0xC0, 0x38, 0x0E, 0x01, 0x80, 0x70, 0x0C, 0x03, 0x80, 0xE0, 0x1C, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xEE, 0xEE, 0x00, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
0x07, 0x00, 0xE0, 0x38, 0x00, 0x07, 0xF0, 0xFE, 0x1F, 0x61, 0xC0, 0xFF, 0xCF, 0xFC, 0x38, 0x0F, 0xF8, 0xFF, 0x83, 0x38, 0x38, 0x38, 0x38, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x7E, 0xFF,
0x80, 0x1C, 0x01, 0xF7, 0x0F, 0xF0, 0x7F, 0xFF, 0xEF, 0xFE, 0x06, 0x00, 0x60, 0x07, 0xC0, 0x7C, 0x3F, 0x83, 0xE0, 0xFB, 0xF8, 0x0F, 0xF8, 0x00, 0x3F, 0xE0, 0x00, 0xE1, 0x80, 0x03, 0x86, 0x00, 0x0E, 0x18, 0x00, 0x38, 0x7F, 0x80,
0x3F, 0xC0, 0x7C, 0x3F, 0x83, 0xE0, 0x3E, 0x00, 0x60, 0x06, 0x00, 0x3F, 0x83, 0xFC, 0x3B, 0xC0, 0x0E, 0x00, 0xCF, 0xE1, 0xFF, 0x03, 0x87, 0x7E, 0x0E, 0x18, 0x38, 0x38, 0x60, 0xF1, 0xC1, 0x83, 0xCF, 0x06, 0x0E, 0x78, 0x1C, 0xFB,
0xFE, 0x0F, 0x81, 0xF0, 0xFF, 0xE7, 0x00, 0x70, 0x07, 0x00, 0x3D, 0xC3, 0xFE, 0x1F, 0xE0, 0xFF, 0xFF, 0xFC, 0x3C, 0xE0, 0x7F, 0xCF, 0x01, 0xFE, 0x00, 0x00, 0x00, 0xE0, 0x70, 0x0E, 0x07, 0x00, 0xE0, 0x70, 0x0E, 0x07, 0x00, 0xE0,
0x01, 0xCF, 0xFD, 0xFF, 0x80, 0xE0, 0xF8, 0xFF, 0x1F, 0x83, 0xC0, 0x3C, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x3F, 0x83, 0x70, 0x0F, 0xFF, 0xFC, 0xFF, 0xFF, 0xEE, 0x07, 0x3F, 0xE0, 0x70, 0x7E, 0x07, 0x07, 0xE0, 0x70, 0x7E, 0x07, 0x07,
0xFC, 0x33, 0xE0, 0x0E, 0x00, 0xE1, 0xFE, 0x3F, 0xF7, 0xDF, 0x70, 0x77, 0x07, 0xE0, 0xEE, 0x0E, 0x70, 0xE7, 0xBC, 0xE0, 0x73, 0xFE, 0x07, 0xFE, 0xE0, 0x7F, 0xC0, 0xFF, 0xF1, 0xFF, 0xE0, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xFF,
0x7F, 0xC3, 0xF8, 0x07, 0x00, 0x1E, 0x00, 0xF8, 0x03, 0xF0, 0x1D, 0xC0, 0x73, 0x81, 0x8E, 0x0E, 0x38, 0x38, 0x70, 0x03, 0xFF, 0x07, 0x9E, 0x0E, 0x1E, 0x1C, 0x1C, 0x38, 0x38, 0x70, 0x70, 0xE0, 0xE1, 0xC1, 0xC3, 0x83, 0x80, 0x03,
0xC1, 0xC7, 0x03, 0x1C, 0x0E, 0xE0, 0x3B, 0xFF, 0xEF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x00, 0x3C, 0x03, 0xC0, 0x1C, 0x00, 0x00, 0x70, 0x7B, 0x87, 0x9C, 0x78, 0xE3, 0x87, 0x38, 0x3B, 0x81, 0xF8, 0x0F,
0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x70, 0xFF, 0xC0, 0x7F, 0x03, 0xBC, 0x1C, 0xF0, 0xE3, 0xC7, 0x0F, 0x38, 0x3D, 0xC0, 0xE0, 0x0C, 0x00, 0x70, 0x01, 0xC0, 0x06,
0xFF, 0xFD, 0xC0, 0x3C, 0x03, 0x80, 0x38, 0x07, 0x80, 0x70, 0x07, 0x01, 0xC0, 0x70, 0x1E, 0x03, 0x80, 0xE0, 0x3C, 0x00, 0x00, 0x70, 0x1F, 0x81, 0xFC, 0x1F, 0xE0, 0xFF, 0x0F, 0xF8, 0xFF, 0xC7, 0x7E, 0x73, 0xF7, 0x1F, 0xF8, 0xFF,
0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xF0, 0x00, 0xE0, 0x38, 0x07, 0x01, 0xC0, 0x38, 0x0E, 0x01, 0x80, 0x70, 0x0C, 0x87, 0xF8, 0x3F, 0xC1, 0xFC, 0x0F, 0xC0, 0x70, 0x1D, 0xC0, 0xFE, 0x03, 0xE0, 0x00, 0x0E, 0x07, 0x38, 0x39, 0xC1,
0x03, 0x80, 0xE0, 0x1C, 0x07, 0x00, 0xE0, 0x38, 0x00, 0xFF, 0x80, 0x00, 0x30, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x06, 0xCF, 0x1E, 0x38, 0xE1, 0xE7, 0x07, 0x70, 0x3F, 0x80, 0xFC, 0x07, 0xC0, 0x1E, 0x00, 0xE0, 0x5F, 0x03, 0xF0, 0x1F,
0x00, 0x70, 0x03, 0x80, 0x18, 0xF1, 0xC7, 0xCE, 0x3E, 0x60, 0x3B, 0x01, 0xF8, 0x07, 0xC0, 0x3C, 0x00, 0xE0, 0x07, 0x00, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07,
0x00, 0x7D, 0xEF, 0xFF, 0xE7, 0x3E, 0x73, 0xFF, 0xF7, 0xDE, 0x0F, 0x1F, 0x1E, 0x1C, 0x38, 0x38, 0x38, 0x38, 0x38, 0xE0, 0x7F, 0xFF, 0xFF, 0xF0, 0x70, 0x07, 0x00, 0x70, 0x07, 0x00, 0x07, 0x80, 0x1E, 0x00, 0x78, 0x03, 0xF0, 0x0F,
0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x78, 0xF8, 0xF0, 0x3C, 0x6F, 0xFD, 0xFF, 0xB1, 0xE3, 0xC6, 0xFF, 0xC0, 0x73, 0x81, 0xCE, 0x06, 0x38, 0x38, 0x70, 0xFF, 0xC7, 0xFF, 0x9C, 0x0E, 0x70, 0x3B, 0x80, 0x7E, 0x01, 0xC0,
0xDF, 0xFB, 0x1E, 0x03, 0x80, 0xE0, 0x73, 0xFF, 0xFF, 0xC3, 0x80, 0xC0, 0x70, 0xFF, 0xFF, 0xF3, 0x81, 0xC0, 0x70, 0xFF, 0xCF, 0xFC, 0xE0, 0x0E, 0x00, 0xE0, 0x0F, 0xF8, 0xFF, 0xCE, 0x7E, 0xE0, 0xEE, 0x07, 0xE0, 0x7E, 0x0E, 0xE3,
0x00, 0x01, 0xC3, 0xF7, 0xFB, 0xF0, 0xF0, 0x3F, 0x07, 0xF8, 0x3F, 0x03, 0xC0, 0x0F, 0xFF, 0xFF, 0xE0, 0x3F, 0x07, 0xEF, 0xFC, 0xFF, 0x80, 0xFF, 0x8F, 0xFC, 0xE3, 0xEE, 0x0E, 0xE0, 0xEE, 0x3E, 0xFF, 0xCF, 0xFE, 0xE3, 0xEE, 0x07,
0xF8, 0x3F, 0x03, 0xC7, 0xF7, 0xFB, 0xF0, 0xE0, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x7E, 0x0F, 0xE3, 0xEF, 0xFE, 0xFF, 0xC0, 0xFF, 0xFF, 0xFE, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0,
0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x00, 0x0F, 0xF8, 0x1F, 0xF0, 0x38, 0xE0, 0x71, 0xC0, 0xE3, 0x81, 0xC7,
0x03, 0x8E, 0x07, 0x1C, 0x0E, 0x38, 0x38, 0x70, 0x70, 0xE1, 0xE1, 0xC3, 0x83, 0x9F, 0xFF, 0xFF, 0xFF, 0xF0, 0x07,
0xE0, 0x0F, 0xC0, 0x1F, 0x80, 0x38, 0xFF, 0xDF, 0xFB, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x3F, 0xE7, 0xFC, 0xE0, 0x1C,
0x03, 0x80, 0x70, 0x0E, 0x01, 0xFF, 0xFF, 0xF8, 0x70, 0xE1, 0xCF, 0x1C, 0x78, 0xF3, 0x9E, 0x0E, 0x73, 0x80, 0xEE,
0xE0, 0x1F, 0xFC, 0x01, 0xFF, 0x00, 0x1F, 0xC0, 0x07, 0xFC, 0x01, 0xFF, 0xC0, 0x7B, 0xBC, 0x1E, 0x73, 0xC3, 0x8E,
0x38, 0xE1, 0xC3, 0xBC, 0x38, 0x78, 0x7F, 0x8F, 0xF9, 0xCF, 0x80, 0x70, 0x0E, 0x0F, 0x87, 0xE0, 0xFE, 0x07, 0xE0,
0x1C, 0x03, 0x80, 0x77, 0x3F, 0xFF, 0x9F, 0xE0, 0xE0, 0x3F, 0x03, 0xF8, 0x3F, 0xC1, 0xFE, 0x1F, 0xF1, 0xFF, 0x8E,
0xFC, 0xE7, 0xEE, 0x3F, 0xF1, 0xFF, 0x0F, 0xF0, 0x7F, 0x83, 0xF8, 0x1F, 0x80, 0xE0, 0x1D, 0xC0, 0xFE, 0x03, 0xE0,
0x00, 0x0E, 0x03, 0xF0, 0x3F, 0x83, 0xFC, 0x1F, 0xE1, 0xFF, 0x1F, 0xF8, 0xEF, 0xCE, 0x7E, 0xE3, 0xFF, 0x1F, 0xF0,
0xFF, 0x07, 0xF8, 0x3F, 0x81, 0xF8, 0x0E, 0xE0, 0xF7, 0x0F, 0x38, 0xF1, 0xC7, 0x0E, 0x70, 0x77, 0x03, 0xF0, 0x1F,
0x80, 0xFE, 0x07, 0x78, 0x39, 0xE1, 0xC7, 0x8E, 0x1E, 0x70, 0x7B, 0x81, 0xC0, 0x0F, 0xF8, 0x3F, 0xE0, 0xE1, 0x83,
0x86, 0x0E, 0x18, 0x38, 0x60, 0xE1, 0x83, 0x86, 0x0E, 0x18, 0x78, 0x61, 0xC1, 0x8F, 0x06, 0xF8, 0x1B, 0xE0, 0x6E,
0x01, 0x80, 0x70, 0x0E, 0x78, 0x0E, 0x78, 0x1E, 0x78, 0x1F, 0x6C, 0x3F, 0x6C, 0x37, 0xEE, 0x37, 0xE6, 0x67, 0xE7,
0x67, 0xE3, 0xE7, 0xE3, 0xC7, 0xE3, 0xC7, 0xE1, 0xC7, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x3E, 0x03, 0xE0, 0x3E, 0x03,
0xE0, 0x3E, 0x03, 0xFF, 0xFF, 0xFF, 0xE0, 0x3E, 0x03, 0xE0, 0x3E, 0x03, 0xE0, 0x3E, 0x03, 0xE0, 0x30, 0x1F, 0xE0,
0x7F, 0xE1, 0xFB, 0xE3, 0x81, 0xEF, 0x01, 0xDC, 0x03, 0xB8, 0x07, 0x70, 0x0F, 0xE0, 0x1D, 0xC0, 0x3B, 0xC0, 0x73,
0x81, 0xE7, 0xEF, 0x87, 0xFE, 0x07, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E,
0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x70, 0xFF, 0x8F, 0xFC, 0xE3, 0xEE, 0x0E, 0xE0,
0xEE, 0x0E, 0xE7, 0xEF, 0xFC, 0xFF, 0x8E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x00, 0x0F, 0xE3, 0xFF,
0x7E, 0xE7, 0x00, 0xF0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x07, 0x00, 0x7E, 0xF3, 0xFF, 0x1F,
0xF0, 0xFF, 0xFF, 0xFF, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0,
0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x73, 0x83, 0x9C, 0x1C, 0xF1, 0xE3, 0x8E, 0x1E, 0x70, 0x77, 0x03, 0xF8, 0x0F,
0xC0, 0x7C, 0x01, 0xE0, 0x0E, 0x05, 0xF0, 0x3F, 0x01, 0xF0, 0x00, 0x01, 0xC0, 0x01, 0xC0, 0x1F, 0xF8, 0x3F, 0xFC,
0x7D, 0xFE, 0xF1, 0xCF, 0xE1, 0xC7, 0xE1, 0xC7, 0xE1, 0xC7, 0xE1, 0xC7, 0xF1, 0xCF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F,
0xF8, 0x01, 0xC0, 0x01, 0xC0, 0xF0, 0x7B, 0xC3, 0x8E, 0x38, 0x7B, 0xC1, 0xFC, 0x07, 0xC0, 0x3E, 0x00, 0xE0, 0x0F,
0x80, 0xFE, 0x07, 0x78, 0x71, 0xC7, 0x87, 0x38, 0x3B, 0xC0, 0xE0, 0xE0, 0x73, 0x81, 0xCE, 0x07, 0x38, 0x1C, 0xE0,
0x73, 0x81, 0xCE, 0x07, 0x38, 0x1C, 0xE0, 0x73, 0x81, 0xCE, 0x07, 0x38, 0x1C, 0xE0, 0x73, 0xFF, 0xFF, 0xFF, 0xC0,
0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F, 0xCF, 0x7F,
0xE7, 0xFC, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0xE0, 0xE1, 0xF8, 0x38, 0x7E, 0x0E, 0x1F, 0x83, 0x87, 0xE0,
0xE1, 0xF8, 0x38, 0x7E, 0x0E, 0x1F, 0x83, 0x87, 0xE0, 0xE1, 0xF8, 0x38, 0x7E, 0x0E, 0x1F, 0x83, 0x87, 0xE0, 0xE1,
0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xE0, 0xE1, 0xCE, 0x0E, 0x1C, 0xE0, 0xE1, 0xCE, 0x0E, 0x1C, 0xE0, 0xE1, 0xCE, 0x0E,
0x1C, 0xE0, 0xE1, 0xCE, 0x0E, 0x1C, 0xE0, 0xE1, 0xCE, 0x0E, 0x1C, 0xE0, 0xE1, 0xCE, 0x0E, 0x1C, 0xE0, 0xE1, 0xCF,
0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x07, 0x00, 0x00, 0x70, 0x00, 0x07, 0x00, 0x00, 0x70, 0xFE, 0x01, 0xFC, 0x00,
0x38, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xFE, 0x03, 0xFF, 0x07, 0x3E, 0x0E, 0x1E, 0x1C, 0x1C, 0x38, 0x38, 0x70, 0xF0,
0xE7, 0xC1, 0xFF, 0x83, 0xFC, 0x00, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xFF, 0x87, 0xFF,
0xC7, 0xE7, 0xE7, 0xE0, 0xE7, 0xE0, 0xE7, 0xE0, 0xE7, 0xE0, 0xE7, 0xE3, 0xE7, 0xFF, 0xC7, 0xFF, 0x87, 0xE0, 0x0E,
0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0F, 0xF8, 0xFF, 0xCE, 0x7E, 0xE0, 0xEE, 0x07, 0xE0, 0x7E, 0x0E, 0xE3, 0xEF, 0xFC,
0xFF, 0x80, 0xFF, 0x8F, 0xFC, 0x73, 0xE0, 0x0E, 0x00, 0x70, 0x07, 0x1F, 0xF1, 0xFF, 0x00, 0x70, 0x07, 0x00, 0xF0,
0x0E, 0x77, 0xEF, 0xFC, 0xFF, 0x80, 0xE0, 0x7F, 0x0E, 0x0F, 0xFC, 0xE1, 0xF7, 0xCE, 0x3C, 0x1E, 0xE3, 0x80, 0xEE,
0x38, 0x07, 0xFF, 0x80, 0x7F, 0xF8, 0x07, 0xE3, 0x80, 0x7E, 0x38, 0x07, 0xE3, 0x80, 0xEE, 0x3C, 0x1E, 0xE1, 0xF7,
0xCE, 0x0F, 0xFC, 0xE0, 0x7F, 0x00, 0x1F, 0xF3, 0xFF, 0x7E, 0x77, 0x07, 0x70, 0x77, 0x07, 0x7E, 0x73, 0xFF, 0x1F,
0xF1, 0xC7, 0x1C, 0x73, 0x87, 0x78, 0x77, 0x07, 0xF0, 0x70, 0x3F, 0x0F, 0xE3, 0x3C, 0x07, 0x3F, 0xDF, 0xF7, 0x9F,
0x87, 0x79, 0xDF, 0xF3, 0xFC, 0x0F, 0xC3, 0xF8, 0xFE, 0x3C, 0x06, 0x01, 0xFF, 0x3F, 0xF7, 0xDE, 0xE1, 0xFC, 0x1F,
0x83, 0xF0, 0x7E, 0x1E, 0xF7, 0x9F, 0xF1, 0xFC, 0xFF, 0x3F, 0xEE, 0x3F, 0x8E, 0xFF, 0xBF, 0xFE, 0x3F, 0x87, 0xE3,
0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x1F, 0xE0, 0xFF, 0x07, 0x38,
0x39, 0xC1, 0xCE, 0x0C, 0x70, 0xE3, 0x87, 0x1C, 0x70, 0xE7, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1C, 0x3F,
0x1F, 0xEF, 0xFF, 0x87, 0xFF, 0xFF, 0xFE, 0x03, 0x80, 0xF9, 0x9F, 0xE3, 0xF8, 0x71, 0x8E, 0x79, 0x9E, 0x3D, 0x9C,
0x1D, 0xB8, 0x0F, 0xF0, 0x0F, 0xF0, 0x1F, 0xF8, 0x1D, 0xBC, 0x39, 0x9C, 0x71, 0x8E, 0xE1, 0x87, 0x7F, 0x1F, 0xE7,
0x78, 0x1E, 0x3F, 0x0F, 0xE0, 0x78, 0x07, 0x67, 0xDF, 0xE7, 0xF0, 0xE1, 0xF8, 0xFE, 0x3F, 0x9F, 0xEE, 0xFB, 0x3F,
0xCF, 0xE3, 0xF0, 0xFC, 0x3E, 0x0C, 0x3B, 0x8F, 0xC1, 0xF0, 0x00, 0x00, 0x38, 0x7E, 0x3F, 0x8F, 0xE7, 0xFB, 0xBE,
0xCF, 0xF3, 0xF8, 0xFC, 0x3F, 0x0F, 0x83, 0xE3, 0xF9, 0xEE, 0xF3, 0xF8, 0xFC, 0x3F, 0x0F, 0xE3, 0xBC, 0xE7, 0xB8,
0xEE, 0x1C, 0x1F, 0xE3, 0xFC, 0x73, 0x8E, 0x71, 0xCE, 0x39, 0xC7, 0x39, 0xC7, 0xF8, 0xFE, 0x1F, 0x83, 0x80, 0x70,
0x3B, 0x83, 0xDE, 0x1F, 0xF1, 0xFF, 0xCF, 0xF6, 0xFF, 0xBE, 0xFD, 0xF7, 0xE7, 0x3F, 0x38, 0xF8, 0x06, 0xE1, 0xF8,
0x7E, 0x1F, 0x87, 0xFF, 0xFF, 0xFE, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1C, 0x3F, 0x0F, 0xF3, 0xFF, 0x70, 0xEE, 0x0F,
0xC1, 0xF8, 0x3F, 0x0E, 0xFB, 0xCF, 0xF0, 0xFC, 0x00, 0xFF, 0xFF, 0xFE, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0x87,
0xE1, 0xF8, 0x7E, 0x1C, 0xFF, 0x1F, 0xF3, 0xDF, 0x70, 0xEE, 0x0F, 0xC1, 0xF8, 0x3F, 0x0E, 0xFB, 0xDF, 0xFB, 0xFE,
0x70, 0x0E, 0x01, 0xC0, 0x38, 0x00, 0x3F, 0x3F, 0xBE, 0xDC, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xFB, 0x3F, 0xCF, 0xE0,
0xFF, 0xFF, 0xF1, 0xC0, 0x70, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C, 0x07, 0x01, 0xC0, 0xE1, 0xDC, 0x39, 0xC7, 0x38,
0xE7, 0x38, 0x77, 0x0E, 0xE0, 0xF8, 0x1F, 0x03, 0xE0, 0x38, 0x07, 0x0B, 0xC1, 0xF8, 0x3E, 0x00, 0x03, 0x00, 0x06,
0x00, 0x0C, 0x00, 0x18, 0x00, 0x30, 0x07, 0xFE, 0x1F, 0xFE, 0x7F, 0xFE, 0xE3, 0x1D, 0xC6, 0x3B, 0x8C, 0x37, 0x18,
0xEE, 0x31, 0xDF, 0xFF, 0x9F, 0xFE, 0x1F, 0xF8, 0x03, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x18, 0x00, 0xF1, 0xCE, 0x78,
0xEE, 0x1F, 0x81, 0xE0, 0x1C, 0x07, 0xC1, 0xFC, 0x7B, 0x8E, 0x3B, 0x87, 0x80, 0xE1, 0xDC, 0x3B, 0x87, 0x70, 0xEE,
0x1D, 0xC3, 0xB8, 0x77, 0x0E, 0xE1, 0xDF, 0xFF, 0xFF, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x61, 0xD8, 0x76, 0x1D, 0x87,
0x7B, 0xDF, 0xF3, 0xFC, 0x07, 0x01, 0xC0, 0x70, 0x1C, 0xE3, 0x8F, 0xC7, 0x1F, 0x8E, 0x3F, 0x1C, 0x7E, 0x38, 0xFC,
0x71, 0xF8, 0xE3, 0xF1, 0xC7, 0xE3, 0x8F, 0xFF, 0xFF, 0xFF, 0xF8, 0xE3, 0x8E, 0x71, 0xC7, 0x38, 0xE3, 0x9C, 0x71,
0xCE, 0x38, 0xE7, 0x1C, 0x73, 0x8E, 0x39, 0xC7, 0x1C, 0xE3, 0x8E, 0x7F, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x70, 0x00,
0x38, 0x00, 0x1C, 0xFC, 0x0F, 0xC0, 0x1C, 0x01, 0xFE, 0x1F, 0xF1, 0xCF, 0x1C, 0x71, 0xC7, 0x1C, 0xF1, 0xFF, 0x1F,
0xE0, 0xE0, 0x1F, 0x80, 0x7E, 0x01, 0xF8, 0x07, 0xFF, 0x1F, 0xFE, 0x7E, 0x7D, 0xF8, 0x77, 0xE7, 0xDF, 0xFE, 0x7F,
0xF1, 0xC0, 0xE0, 0x38, 0x0E, 0x03, 0xFC, 0xFF, 0xB9, 0xFE, 0x1F, 0x87, 0xE7, 0xFF, 0xEF, 0xF0, 0x7E, 0x1F, 0xE6,
0x78, 0x07, 0x3F, 0xCF, 0xF0, 0x1C, 0x0F, 0x6F, 0xBF, 0xEF, 0xE0, 0xE1, 0xF9, 0xC7, 0xFB, 0x9F, 0xFF, 0x38, 0x7F,
0xF0, 0xFF, 0xC1, 0xF9, 0xC3, 0xF3, 0x87, 0xE7, 0xFF, 0xC7, 0xFB, 0x87, 0xE0, 0x3F, 0xDF, 0xF7, 0x9D, 0xC7, 0x79,
0xDF, 0xF3, 0xFC, 0xE7, 0x79, 0xDC, 0x7E, 0x1C, 0x38, 0x0F, 0x01, 0xE0, 0x38, 0x00, 0x0F, 0xC7, 0xFB, 0xFF, 0xE1,
0xFF, 0xFF, 0xFF, 0x80, 0xE0, 0x3E, 0x67, 0xF8, 0xFE, 0x7F, 0x9F, 0xE0, 0x00, 0x00, 0x3F, 0x1F, 0xEF, 0xFF, 0x87,
0xFF, 0xFF, 0xFE, 0x03, 0x80, 0xF9, 0x9F, 0xE3, 0xF8, 0x70, 0x1F, 0xE3, 0xFC, 0x38, 0x07, 0x00, 0xFF, 0x1F, 0xF3,
0xDF, 0x70, 0xEE, 0x1D, 0xC3, 0xB8, 0x77, 0x0E, 0xE1, 0xDC, 0x3B, 0x87, 0x00, 0xE0, 0x3C, 0x0F, 0x81, 0xE0, 0x06,
0x0E, 0x1C, 0x18, 0x00, 0xFF, 0xFF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x3F, 0xBF, 0xFE, 0xDC,
0x0F, 0xE7, 0xF3, 0x81, 0xC0, 0xF9, 0xBF, 0xCF, 0xE0, 0x3F, 0x3F, 0x9E, 0xCE, 0x07, 0xC1, 0xF8, 0x3E, 0x07, 0x67,
0xBF, 0xDF, 0xC0, 0xFC, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xDC, 0x00, 0x03, 0x87, 0x0E, 0x1C, 0x38, 0x70, 0xE1,
0xC3, 0x87, 0x0E, 0x00, 0x1C, 0x70, 0x00, 0x00, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0xFF, 0xFE,
0x1F, 0xE0, 0x07, 0xF8, 0x01, 0xCE, 0x00, 0x73, 0x80, 0x1C, 0xFF, 0x87, 0x3F, 0xE1, 0x8F, 0x3C, 0xE3, 0x87, 0xF8,
0xE3, 0xFC, 0x3F, 0xEE, 0x07, 0xF8, 0xE1, 0xC0, 0x70, 0xE0, 0x38, 0x70, 0x1C, 0x38, 0x0F, 0xFF, 0xE7, 0xFF, 0xFB,
0x87, 0x3F, 0xC3, 0x87, 0xE1, 0xCF, 0xF0, 0xFF, 0xB8, 0x7F, 0x80, 0x70, 0x1F, 0xE3, 0xFC, 0x38, 0x07, 0x00, 0xFF,
0x1F, 0xF3, 0xDF, 0x70, 0xEE, 0x1D, 0xC3, 0xB8, 0x77, 0x0E, 0xE1, 0xDC, 0x3B, 0x87, 0x07, 0x03, 0xC1, 0xE0, 0x70,
0x00, 0x38, 0xFE, 0x7B, 0xBC, 0xFE, 0x3F, 0x0F, 0xC3, 0xF8, 0xEF, 0x39, 0xEE, 0x3B, 0x87, 0x18, 0x07, 0x00, 0xE0,
0x18, 0x00, 0x38, 0x7E, 0x3F, 0x8F, 0xE7, 0xFB, 0xBE, 0xCF, 0xF3, 0xF8, 0xFC, 0x3F, 0x0F, 0x83, 0x3B, 0x87, 0xF0,
0x7C, 0x00, 0x00, 0x01, 0xC3, 0xB8, 0x73, 0x8E, 0x71, 0xCE, 0x70, 0xEE, 0x1D, 0xC1, 0xF0, 0x3E, 0x07, 0xC0, 0x70,
0x0E, 0x17, 0x83, 0xF0, 0x7C, 0x00, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xFF, 0xFF,
0xFC, 0x30, 0x0C, 0x03, 0x00, 0x0E, 0x00, 0x1C, 0x03, 0xFF, 0x87, 0xFF, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0xFC, 0x07,
0xFE, 0x0E, 0x7C, 0x1C, 0x3C, 0x38, 0x38, 0x70, 0x70, 0xE1, 0xE1, 0xCF, 0x83, 0xFF, 0x07, 0xF8, 0x1C, 0x01, 0xC0,
0x1C, 0x01, 0xC0, 0x1C, 0x0F, 0xF8, 0xFF, 0x81, 0xC0, 0x1F, 0xE1, 0xFF, 0x1C, 0xF1, 0xC7, 0x1C, 0x71, 0xCF, 0x1F,
0xF1, 0xFE, 0x1F, 0xE0, 0x7F, 0xE1, 0xF3, 0xE3, 0x81, 0xEE, 0x01, 0xDF, 0xE3, 0xBF, 0xFF, 0x7F, 0xFF, 0xE1, 0xFD,
0xC0, 0x3B, 0xC0, 0x73, 0x81, 0xE7, 0xCF, 0x87, 0xFE, 0x07, 0xF8, 0x00, 0x3F, 0x0F, 0xF3, 0xCF, 0x7C, 0xEF, 0xFF,
0xDF, 0xF9, 0xFF, 0x0E, 0xFB, 0xCF, 0xF0, 0xFC, 0x00, 0xE0, 0x1F, 0x70, 0x0F, 0x9C, 0x0F, 0xCE, 0x07, 0x07, 0x07,
0x01, 0xC3, 0x80, 0xE1, 0xC0, 0x79, 0xC0, 0x1C, 0xE0, 0x0E, 0x60, 0x03, 0xF0, 0x01, 0xF8, 0x00, 0xF8, 0x00, 0x3C,
0x00, 0x1E, 0x00, 0xE0, 0xFE, 0x1F, 0x71, 0xD7, 0x1C, 0x73, 0x83, 0xB8, 0x3B, 0x03, 0xF0, 0x1F, 0x01, 0xE0, 0x0E,
0x00, 0x1D, 0xC0, 0x3F, 0x80, 0x3E, 0x00, 0x00, 0x0E, 0x03, 0x9C, 0x0F, 0x38, 0x3E, 0x70, 0x7C, 0xE1, 0xF9, 0xC7,
0xF3, 0x8E, 0xE7, 0x39, 0xCE, 0xE3, 0x9F, 0xC7, 0x3F, 0x0E, 0x7C, 0x1C, 0xF8, 0x39, 0xE0, 0x7F, 0x80, 0xF8, 0x00,
0x60, 0x01, 0xC0, 0x07, 0x80, 0x0E, 0x00, 0x3B, 0x83, 0xF0, 0x1F, 0x00, 0x00, 0x00, 0x0E, 0x1C, 0xE3, 0xCE, 0x3C,
0xE7, 0xCE, 0xEC, 0xEC, 0xCF, 0xCC, 0xF8, 0xCF, 0x0C, 0xF0, 0xCE, 0x0F, 0x00, 0x70, 0x07, 0x00, 0xE0, 0x0E, 0x38,
0x01, 0xC0, 0x3F, 0x81, 0xFC, 0x03, 0x80, 0x1C, 0x00, 0xFF, 0x07, 0xFE, 0x39, 0xF1, 0xC3, 0xCE, 0x0E, 0x70, 0x73,
0x87, 0x9C, 0xF8, 0xFF, 0xC7, 0xF8, 0xFE, 0x1F, 0xC1, 0xC0, 0x38, 0x07, 0xFC, 0xFF, 0x9C, 0x7B, 0x87, 0x71, 0xEF,
0xF9, 0xFE, 0x00, 0xFF, 0x8F, 0xFC, 0xE3, 0xEE, 0x0E, 0xE0, 0xEE, 0xEE, 0xE7, 0xEF, 0xFC, 0xFF, 0x8E, 0x38, 0xE1,
0xCE, 0x0C, 0xE0, 0x0E, 0x00, 0xE0, 0x00, 0xFF, 0x1F, 0xF3, 0xDF, 0x70, 0xEE, 0x0F, 0xC1, 0xFB, 0xBF, 0x3E, 0xFF,
0xDF, 0xFB, 0xFE, 0x70, 0xCE, 0x1D, 0xC0, 0x38, 0x00, 0x01, 0xC0, 0x70, 0x1F, 0xFF, 0xFF, 0xF8, 0x0E, 0x03, 0x80,
0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x00, 0x07, 0x07, 0x07, 0xFF, 0xFF, 0xE0,
0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x3F, 0xE7, 0xFC, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x3F, 0xC7, 0xF8,
0x38, 0x07, 0x00, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x00, 0x7F, 0xBF, 0xDC, 0x0E, 0x07, 0x07, 0xF3, 0xF8, 0xE0,
0x70, 0x38, 0x1C, 0x00, 0xFF, 0xCF, 0xFC, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xFF, 0x8F, 0xFC, 0xFB, 0xEE, 0x0E,
0xE0, 0xFE, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0xF0, 0x0E, 0x03, 0xE0, 0xFC, 0x0F, 0x80, 0xFF, 0xBF, 0xEE, 0x03, 0x80,
0xFF, 0x3F, 0xEF, 0x7F, 0x87, 0xE1, 0xF8, 0x7E, 0x1C, 0x07, 0x07, 0xC3, 0xE0, 0xF0, 0x70, 0xE1, 0xC7, 0x8E, 0x3C,
0x3C, 0xE7, 0x81, 0xCE, 0x70, 0x0E, 0xEE, 0x00, 0xFF, 0xE0, 0x07, 0xFC, 0x00, 0x3F, 0x80, 0x07, 0xFC, 0x00, 0xEF,
0xE0, 0x1E, 0xEF, 0x03, 0xCE, 0x78, 0x38, 0xE3, 0xC7, 0x0E, 0x1F, 0xF0, 0xE1, 0xF0, 0x00, 0x07, 0x00, 0x00, 0x70,
0x00, 0x07, 0x00, 0x00, 0x70, 0x71, 0x8E, 0x3C, 0xCF, 0x0F, 0x67, 0x03, 0xB7, 0x00, 0xFF, 0x00, 0x7F, 0x80, 0x7F,
0xE0, 0x3B, 0xF8, 0x39, 0xBE, 0x38, 0xC7, 0xF8, 0x63, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x7F, 0x8F, 0xF9,
0xCF, 0x80, 0x70, 0x0E, 0x0F, 0x87, 0xE0, 0xFE, 0x07, 0xE0, 0x1C, 0x03, 0x80, 0x77, 0x3F, 0xFF, 0x9F, 0xE0, 0x70,
0x1F, 0x03, 0xC0, 0x7F, 0x1F, 0xE7, 0x78, 0x1E, 0x3F, 0x0F, 0xE0, 0x78, 0x07, 0x67, 0xDF, 0xE7, 0xF0, 0x70, 0x1E,
0x0F, 0x80, 0xE0, 0xF7, 0x0F, 0x38, 0xF1, 0xC7, 0x0E, 0x70, 0x77, 0x03, 0xF8, 0x1F, 0x80, 0xFE, 0x07, 0x78, 0x39,
0xE1, 0xC7, 0x8E, 0x1E, 0x70, 0x7F, 0x81, 0xE0, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0xE3, 0xDC, 0xF3, 0xBC, 0x7F,
0x0F, 0xC1, 0xF0, 0x3F, 0x87, 0x78, 0xE7, 0x9C, 0x7F, 0x87, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x00, 0xE0, 0x3B, 0x81,
0xEE, 0x0F, 0x38, 0x38, 0xED, 0xC3, 0xBE, 0x0E, 0xF8, 0x3F, 0xC0, 0xFF, 0x83, 0xBF, 0x0E, 0xDE, 0x3B, 0x38, 0xE0,
0x73, 0x81, 0xEE, 0x03, 0xC0, 0xE0, 0xEE, 0x1E, 0xE3, 0xCF, 0xF8, 0xFF, 0x0F, 0xF0, 0xFF, 0x8F, 0xF8, 0xE1, 0xCE,
0x0E, 0xE0, 0x70, 0x38, 0x78, 0xE1, 0xCF, 0xEE, 0x3F, 0xF0, 0x3B, 0xC0, 0xFE, 0x03, 0xF0, 0x0F, 0x80, 0x3F, 0x00,
0xFE, 0x03, 0xBC, 0x0E, 0x38, 0x38, 0xF0, 0xE1, 0xE3, 0x83, 0xC0, 0x70, 0xEF, 0xDC, 0x73, 0x87, 0x70, 0x7E, 0x07,
0xE0, 0x7F, 0x07, 0x78, 0x73, 0xC7, 0x1E, 0x70, 0xF0, 0xFE, 0x1E, 0xFE, 0x1C, 0x0E, 0x38, 0x0E, 0x78, 0x0E, 0xF0,
0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0x80, 0x0F, 0xC0, 0x0F, 0xE0, 0x0E, 0x70, 0x0E, 0x38, 0x0E, 0x3C, 0x0E, 0x1E, 0x0E,
0x0F, 0xFC, 0x77, 0xE7, 0x07, 0x70, 0x3F, 0x01, 0xF8, 0x0F, 0x80, 0x7E, 0x03, 0xF8, 0x1C, 0xE0, 0xE7, 0x87, 0x1E,
0xE0, 0x33, 0x80, 0xCE, 0x03, 0x38, 0x0C, 0xE0, 0x33, 0x80, 0xCF, 0xFF, 0x3F, 0xFC, 0xE0, 0x33, 0x80, 0xCE, 0x03,
0x38, 0x0C, 0xE0, 0x33, 0x80, 0xFE, 0x03, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0xE1, 0xCE, 0x1C, 0xE1,
0xCE, 0x1C, 0xFF, 0xCF, 0xFC, 0xE1, 0xCE, 0x1C, 0xE1, 0xCE, 0x1F, 0xE1, 0xF0, 0x07, 0x00, 0x70, 0x07, 0xE0, 0x3F,
0xE0, 0x3F, 0xE0, 0x30, 0xE0, 0x30, 0xE0, 0x30, 0xE0, 0x30, 0xFF, 0xF0, 0xFF, 0xF0, 0xE0, 0x30, 0xE0, 0x30, 0xE0,
0x30, 0xE0, 0x30, 0xE0, 0x30, 0xE0, 0x30, 0xE0, 0x30, 0xE1, 0xFF, 0x0F, 0xF8, 0x71, 0xC3, 0x8F, 0xFC, 0x7F, 0xE3,
0x87, 0x1C, 0x38, 0xE1, 0xC7, 0x0E, 0x38, 0x70, 0xFF, 0xF0, 0x0F, 0xFF, 0x00, 0xE0, 0x70, 0x0E, 0x07, 0x00, 0xE0,
0x70, 0x0E, 0x07, 0x00, 0xE0, 0x7F, 0xCE, 0x07, 0xFE, 0xE0, 0x79, 0xEE, 0x07, 0x0F, 0xE0, 0x70, 0x7E, 0x07, 0x07,
0xE0, 0x70, 0x7E, 0x07, 0x07, 0xE0, 0x70, 0x70, 0x00, 0x0F, 0x00, 0x01, 0xE0, 0x00, 0x7E, 0x00, 0x07, 0x80, 0xFF,
0xC0, 0x7F, 0xE0, 0x38, 0x70, 0x1C, 0x38, 0x0E, 0x1F, 0xE7, 0x0F, 0xFB, 0x87, 0xBD, 0xC3, 0x87, 0xE1, 0xC3, 0xF0,
0xE1, 0xF8, 0x70, 0xE0, 0x00, 0x70, 0x00, 0xF0, 0x00, 0xF8, 0x00, 0x78, 0x0F, 0xE0, 0x7F, 0xC1, 0xFB, 0x83, 0x80,
0x0F, 0x1F, 0x9C, 0x7F, 0xB8, 0xFF, 0x73, 0xC7, 0xE7, 0x0F, 0xCE, 0x1F, 0xDC, 0x7B, 0xB8, 0xE7, 0xFF, 0xC7, 0xFF,
0x03, 0xF8, 0x00, 0xE0, 0x01, 0xF8, 0x01, 0xF8, 0x00, 0xF0, 0x3F, 0x0F, 0xC3, 0xE8, 0x73, 0xEE, 0xFF, 0x9D, 0xFB,
0x1F, 0x67, 0xFF, 0xEF, 0xF8, 0xFE, 0x03, 0xE0, 0x3E, 0x03, 0xC0, 0x0F, 0xE3, 0xFF, 0x7E, 0xE7, 0x00, 0xF0, 0x0E,
0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x07, 0x00, 0x7E, 0xF3, 0xFF, 0x1F, 0xF0, 0x70, 0x0F, 0x80, 0xF0,
0x3F, 0x3F, 0xBE, 0xDC, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xFB, 0x3F, 0xCF, 0xE1, 0x80, 0xE0, 0xF0, 0xF8, 0xFF, 0xFF,
0xFF, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xF8,
0x0F, 0x80, 0x38, 0x03, 0x80, 0x38, 0x03, 0x80, 0xFF, 0xFF, 0xF1, 0xC0, 0x70, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C,
0x07, 0xC1, 0xF0, 0x1C, 0x07, 0x01, 0xC0, 0xE0, 0x7F, 0x83, 0x9C, 0x3C, 0x71, 0xC3, 0x9C, 0x0E, 0xE0, 0x7E, 0x01,
0xF0, 0x0F, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0xFC, 0x39, 0xC7, 0x38, 0xE7,
0x38, 0x77, 0x0E, 0xE1, 0xF8, 0x1F, 0x03, 0xC0, 0x38, 0x07, 0x00, 0xE0, 0x1C, 0x03, 0x80, 0xE0, 0x7F, 0x83, 0x9C,
0x3C, 0xF1, 0xC3, 0x9E, 0x0E, 0xE0, 0x7E, 0x01, 0xF0, 0x0F, 0x01, 0xFF, 0x0F, 0xF8, 0x0E, 0x00, 0x70, 0x03, 0x80,
0x1C, 0x00, 0xE0, 0xDC, 0x39, 0xC7, 0x38, 0xC7, 0x38, 0x77, 0x0E, 0xC0, 0xF8, 0x1E, 0x0F, 0xF9, 0xFF, 0x07, 0x00,
0xE0, 0x1C, 0x03, 0x80, 0xF0, 0x79, 0xE1, 0xC3, 0x8E, 0x0F, 0x78, 0x1F, 0xC0, 0x3E, 0x00, 0xF8, 0x01, 0xE0, 0x0F,
0x80, 0x7F, 0x01, 0xDE, 0x0E, 0x38, 0x78, 0x71, 0xC1, 0xFF, 0x03, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0,
0xF1, 0xCE, 0x78, 0xEE, 0x1F, 0x81, 0xE0, 0x1C, 0x07, 0xC1, 0xFC, 0x7B, 0xCE, 0x3F, 0x87, 0x80, 0x30, 0x06, 0x00,
0xC0, 0xFF, 0xE7, 0x3F, 0xF9, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x38, 0x1C,
0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0xFF, 0xF0, 0xFF, 0xFC, 0x00, 0x07, 0x00,
0x01, 0xC0, 0x00, 0x70, 0x00, 0x1C, 0xFF, 0x33, 0xFC, 0xC1, 0xC3, 0x07, 0x0C, 0x1C, 0x30, 0x70, 0xC1, 0xC3, 0x07,
0x0C, 0x1C, 0x30, 0x7F, 0xF1, 0xFF, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0xE0, 0xE7, 0x07, 0x38, 0x39, 0xC1, 0xCE,
0x0E, 0x70, 0x73, 0x83, 0x9F, 0x3C, 0x7F, 0xE1, 0xFF, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x7C, 0x03, 0xE0, 0x07,
0x00, 0x38, 0x01, 0xC0, 0x0E, 0x61, 0xCC, 0x39, 0x87, 0x30, 0xE7, 0xBC, 0xFF, 0x8F, 0xF0, 0x0E, 0x01, 0xC0, 0x3C,
0x07, 0x80, 0x30, 0x06, 0x00, 0xC0, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xDD, 0xFB, 0xBF, 0xFF, 0x7F, 0xE7,
0xFC, 0x3B, 0x87, 0x70, 0xEE, 0x01, 0xC0, 0x38, 0xE1, 0xF8, 0x7E, 0x1F, 0xB7, 0x7F, 0xDF, 0xF3, 0xFC, 0x37, 0x0D,
0xC0, 0x70, 0x1C, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0F, 0xFC, 0xFF, 0xEF, 0xBE, 0xE0, 0xEE, 0x07, 0xE0,
0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x70, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x3F, 0xCF, 0xFB, 0xDF, 0xE1, 0xF8,
0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0x01, 0xFC, 0x01, 0xFF, 0x01, 0xF7, 0xC1, 0xE0, 0xEC, 0xE0, 0x37,
0xF0, 0x1F, 0xFF, 0xFE, 0xFF, 0xFF, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xE0, 0x00, 0x7C, 0xE0, 0x1F, 0xF8,
0x07, 0xF8, 0x07, 0xE0, 0x7F, 0xB7, 0xDF, 0xF8, 0x7F, 0xFF, 0xBF, 0xFC, 0x70, 0x03, 0x80, 0x0F, 0xB0, 0x7F, 0x81,
0xFE, 0x01, 0xFC, 0x01, 0xFF, 0x01, 0xF7, 0xC1, 0xE0, 0xEC, 0xE0, 0x37, 0xF0, 0x1F, 0xFF, 0xFE, 0xFF, 0xFF, 0x0E,
0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xE0, 0x00, 0x7C, 0xE0, 0x1F, 0xF8, 0x07, 0xF8, 0x00, 0xE0, 0x00, 0x70, 0x00,
0x38, 0x00, 0x1C, 0x00, 0x07, 0xE0, 0x7F, 0xB7, 0xDF, 0xF8, 0x7F, 0xFF, 0xBF, 0xFC, 0x70, 0x03, 0x80, 0x0F, 0xB0,
0x7F, 0x81, 0xFE, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xB8, 0x00, 0x7F, 0x00,
0x07, 0xC0, 0x00, 0x00, 0x07, 0x0E, 0x1C, 0xF1, 0xC7, 0x8F, 0x39, 0xE0, 0xE7, 0x38, 0x0E, 0xEE, 0x01, 0xFF, 0xC0,
0x1F, 0xF0, 0x01, 0xFC, 0x00, 0x7F, 0xC0, 0x1F, 0xFC, 0x07, 0xBB, 0xC1, 0xE7, 0x3C, 0x38, 0xE3, 0x8E, 0x1C, 0x3B,
0xC3, 0x87, 0x80, 0x07, 0xE0, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x71, 0x8E, 0x79, 0x9E, 0x3D, 0x9C,
0x1D, 0xB8, 0x0F, 0xF0, 0x0F, 0xF0, 0x1F, 0xF8, 0x1D, 0xBC, 0x39, 0x9C, 0x71, 0x8E, 0xE1, 0x87, 0xE0, 0xFE, 0x1E,
0xE3, 0xCE, 0x38, 0xE7, 0x0E, 0xE0, 0xFC, 0x0F, 0xF8, 0xFF, 0xCE, 0x7E, 0xE0, 0xEE, 0x07, 0xE0, 0x7E, 0x07, 0xE0,
0x70, 0x0E, 0x03, 0xE0, 0xFC, 0x0F, 0x80, 0xE3, 0xF9, 0xEE, 0xF3, 0xF8, 0xFC, 0x3F, 0xCF, 0xFB, 0xBF, 0xE1, 0xF8,
0x7E, 0x1C, 0x07, 0x07, 0xC3, 0xE0, 0xF0, 0x0F, 0xF8, 0x1F, 0xF0, 0x38, 0x60, 0x70, 0xC0, 0xE1, 0x81, 0xC3, 0x03,
0x86, 0x07, 0x0C, 0x0E, 0x18, 0x3C, 0x30, 0x70, 0x61, 0xE0, 0xCF, 0x81, 0x9F, 0x03, 0xF8, 0x07, 0x80, 0x07, 0x00,
0x0E, 0x00, 0x38, 0x00, 0x60, 0x1F, 0xE0, 0xFF, 0x07, 0x38, 0x39, 0xC1, 0xCE, 0x0E, 0x70, 0x73, 0x87, 0x1C, 0xF8,
0xE7, 0x87, 0x38, 0x3E, 0x00, 0x70, 0x03, 0x80, 0x38, 0x01, 0xC0, 0xE0, 0x3E, 0x03, 0xE0, 0x3E, 0x03, 0xE0, 0x3E,
0x03, 0xFF, 0xFF, 0xFF, 0xE0, 0x3E, 0x03, 0xE0, 0x3E, 0x03, 0xE0, 0x3E, 0x03, 0xE0, 0x30, 0x07, 0x00, 0x70, 0x1F,
0x01, 0xF0, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xFF, 0xFF, 0xFE, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1C, 0x07, 0x01, 0xC1,
0xF0, 0x78, 0xE0, 0x33, 0x80, 0xCE, 0x03, 0x38, 0x0C, 0xE0, 0x33, 0x80, 0xCF, 0xFF, 0x3F, 0xFC, 0xE0, 0x33, 0x80,
0xCE, 0x03, 0x38, 0x0C, 0xE0, 0x33, 0x80, 0xFE, 0x03, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0xE0, 0x03, 0x00, 0xE1, 0xCE,
0x1C, 0xE1, 0xCE, 0x1C, 0xFF, 0xCF, 0xFC, 0xE1, 0xCE, 0x1C, 0xE1, 0xCE, 0x1C, 0xE1, 0xF0, 0x07, 0x00, 0xE0, 0x0E,
0x00, 0xC0, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F, 0xCF, 0x7F, 0xE7, 0xFC, 0x03, 0x80, 0x70,
0x0E, 0x07, 0xC0, 0xF8, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x00, 0x61, 0xD8, 0x76, 0x1D, 0x87, 0x7B, 0xDF, 0xF3, 0xFC,
0x07, 0x01, 0xC0, 0xF0, 0x3C, 0x0C, 0x03, 0x00, 0xC0, 0x70, 0x0E, 0x1E, 0x03, 0x87, 0x81, 0xE1, 0xE0, 0x7C, 0x6C,
0x3F, 0x1B, 0x0D, 0xCE, 0xE3, 0x73, 0x99, 0x9C, 0xE7, 0x67, 0x38, 0xF9, 0xCE, 0x3C, 0x73, 0x8F, 0x1C, 0xE1, 0xC7,
0x38, 0x01, 0xFE, 0x00, 0x7C, 0x00, 0x07, 0x00, 0x03, 0x80, 0x00, 0xE0, 0x00, 0x30, 0x70, 0x38, 0xE0, 0xF1, 0xE1,
0xE7, 0xC7, 0xCF, 0xCF, 0x9D, 0xBF, 0x3B, 0xEE, 0x77, 0xDC, 0xE7, 0x39, 0xCE, 0x33, 0x80, 0x78, 0x00, 0x70, 0x00,
0xE0, 0x03, 0x80, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xC0, 0x3F, 0x00, 0x78, 0x00, 0x00, 0x07,
0x80, 0x1E, 0x00, 0x78, 0x03, 0xF0, 0x0F, 0xC0, 0x73, 0x81, 0xCE, 0x06, 0x38, 0x38, 0x70, 0xFF, 0xC7, 0xFF, 0x9C,
0x0E, 0x70, 0x3B, 0x80, 0x7E, 0x01, 0xC0, 0x3B, 0x8F, 0xE1, 0xF0, 0x00, 0x00, 0x0F, 0xC3, 0xF8, 0xCF, 0x01, 0xCF,
0xF7, 0xFD, 0xE7, 0xE1, 0xDE, 0x77, 0xFC, 0xFF, 0x1D, 0xC0, 0x77, 0x00, 0x00, 0x01, 0xE0, 0x07, 0x80, 0x1E, 0x00,
0xFC, 0x03, 0xF0, 0x1C, 0xE0, 0x73, 0x81, 0x8E, 0x0E, 0x1C, 0x3F, 0xF1, 0xFF, 0xE7, 0x03, 0x9C, 0x0E, 0xE0, 0x1F,
0x80, 0x70, 0x3B, 0x8E, 0xE0, 0x00, 0x00, 0x3F, 0x0F, 0xE3, 0x3C, 0x07, 0x3F, 0xDF, 0xF7, 0x9F, 0x87, 0x79, 0xDF,
0xF3, 0xFC, 0x00, 0xFF, 0xE0, 0x1F, 0xFC, 0x07, 0xC0, 0x01, 0xD8, 0x00, 0x3B, 0x00, 0x0E, 0x60, 0x03, 0x8F, 0xF0,
0x71, 0xFE, 0x1C, 0x30, 0x03, 0xFE, 0x00, 0xFF, 0xC0, 0x1C, 0x18, 0x07, 0x03, 0x01, 0xE0, 0x7F, 0xF8, 0x0F, 0xF8,
0x3F, 0x7E, 0x1F, 0xFF, 0x8C, 0xFD, 0xE0, 0x38, 0x73, 0xFF, 0xFB, 0xFF, 0xFD, 0xE7, 0x00, 0xC3, 0x80, 0x7B, 0xFB,
0x3F, 0xFF, 0x8F, 0xFF, 0xC0, 0x3F, 0x87, 0xE0, 0x7C, 0x00, 0x0F, 0xFD, 0xFF, 0xB8, 0x07, 0x00, 0xE0, 0x1C, 0x03,
0xFE, 0x7F, 0xCE, 0x01, 0xC0, 0x38, 0x07, 0x00, 0xE0, 0x1F, 0xFF, 0xFF, 0x80, 0x7F, 0x0F, 0xC3, 0xE0, 0x00, 0x00,
0x0F, 0xC7, 0xFB, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0x80, 0xE0, 0x3E, 0x67, 0xF8, 0xFE, 0x7F, 0x83, 0xFF, 0x1C, 0xFC,
0x00, 0xE0, 0x07, 0x80, 0x1C, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xF8, 0x0F, 0xE0, 0xE7, 0x9F, 0x3F, 0xF0, 0x7F,
0x00, 0x7F, 0x1F, 0xE6, 0xF8, 0x07, 0x01, 0xFF, 0xFF, 0xFF, 0x87, 0xF7, 0x9F, 0xE3, 0xF0, 0x1D, 0xC0, 0xEE, 0x00,
0x00, 0xFF, 0x07, 0xFE, 0x39, 0xF8, 0x01, 0xC0, 0x0F, 0x00, 0x38, 0x01, 0xFF, 0xFF, 0xFF, 0xFE, 0x03, 0xF0, 0x1F,
0xC1, 0xCF, 0x3E, 0x7F, 0xE0, 0xFE, 0x00, 0x77, 0x1D, 0xC0, 0x00, 0x00, 0x7F, 0x1F, 0xE6, 0xF8, 0x07, 0x01, 0xFF,
0xFF, 0xFF, 0x87, 0xF7, 0x9F, 0xE3, 0xF0, 0x03, 0xB8, 0x00, 0x77, 0x00, 0x00, 0x00, 0x38, 0x70, 0xE7, 0x8E, 0x3C,
0x79, 0xCF, 0x07, 0x39, 0xC0, 0x77, 0x70, 0x0F, 0xFE, 0x00, 0xFF, 0x80, 0x0F, 0xE0, 0x03, 0xFE, 0x00, 0xFF, 0xE0,
0x3D, 0xDE, 0x0F, 0x39, 0xE1, 0xC7, 0x1C, 0x70, 0xE1, 0xDE, 0x1C, 0x3C, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00,
0x00, 0x71, 0x8E, 0x79, 0x9E, 0x3D, 0x9C, 0x1D, 0xB8, 0x0F, 0xF0, 0x0F, 0xF0, 0x1F, 0xF8, 0x1D, 0xBC, 0x39, 0x9C,
0x71, 0x8E, 0xE1, 0x87, 0x3B, 0x87, 0x70, 0x00, 0x3F, 0xC7, 0xFC, 0xE7, 0xC0, 0x38, 0x07, 0x07, 0xC3, 0xF0, 0x7F,
0x03, 0xF0, 0x0E, 0x01, 0xC0, 0x3B, 0x9F, 0xFF, 0xCF, 0xF0, 0x77, 0x1D, 0xC0, 0x00, 0x00, 0x7F, 0x1F, 0xE7, 0x78,
0x1E, 0x3F, 0x0F, 0xE0, 0x78, 0x07, 0x67, 0xDF, 0xE7, 0xF0, 0x7F, 0xEF, 0xFC, 0x07, 0x01, 0xE0, 0x78, 0x0E, 0x03,
0x80, 0xFC, 0x07, 0xC0, 0x1C, 0x03, 0x80, 0x77, 0x3F, 0xFF, 0x9F, 0xE0, 0x7F, 0xCF, 0xF8, 0x0E, 0x01, 0xC0, 0x70,
0x1C, 0x03, 0x80, 0xFC, 0x07, 0xC0, 0x38, 0x03, 0x00, 0xE7, 0x7C, 0xFF, 0x9F, 0xC0, 0x1F, 0xC0, 0xFE, 0x00, 0x01,
0xC0, 0x7E, 0x07, 0xF0, 0x7F, 0x83, 0xFC, 0x3F, 0xE3, 0xFF, 0x1D, 0xF9, 0xCF, 0xDC, 0x7F, 0xE3, 0xFE, 0x1F, 0xE0,
0xFF, 0x07, 0xF0, 0x3F, 0x01, 0xC0, 0x3F, 0x8F, 0xE0, 0x00, 0x00, 0xE1, 0xF8, 0xFE, 0x3F, 0x9F, 0xEE, 0xFB, 0x3F,
0xCF, 0xE3, 0xF0, 0xFC, 0x3E, 0x0C, 0x1D, 0xC0, 0xEE, 0x00, 0x01, 0xC0, 0x7E, 0x07, 0xF0, 0x7F, 0x83, 0xFC, 0x3F,
0xE3, 0xFF, 0x1D, 0xF9, 0xCF, 0xDC, 0x7F, 0xE3, 0xFE, 0x1F, 0xE0, 0xFF, 0x07, 0xF0, 0x3F, 0x01, 0xC0, 0x3B, 0x8E,
0xE0, 0x00, 0x00, 0xE1, 0xF8, 0xFE, 0x3F, 0x9F, 0xEE, 0xFB, 0x3F, 0xCF, 0xE3, 0xF0, 0xFC, 0x3E, 0x0C, 0x0E, 0xE0,
0x1D, 0xC0, 0x00, 0x00, 0xFF, 0x03, 0xFF, 0x0F, 0xDF, 0x1C, 0x0F, 0x78, 0x0E, 0xE0, 0x1D, 0xC0, 0x3B, 0x80, 0x7F,
0x00, 0xEE, 0x01, 0xDE, 0x03, 0x9C, 0x0F, 0x3F, 0x7C, 0x3F, 0xF0, 0x3F, 0xC0, 0x3B, 0x87, 0x70, 0x00, 0x00, 0x03,
0xF0, 0xFF, 0x3F, 0xF7, 0x0E, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0xEF, 0xBC, 0xFF, 0x0F, 0xC0, 0x1F, 0xE0, 0x7F, 0xE1,
0xF3, 0xE3, 0x81, 0xEE, 0x01, 0xDC, 0x03, 0xBF, 0xFF, 0x7F, 0xFF, 0xE0, 0x1D, 0xC0, 0x3B, 0xC0, 0x73, 0x81, 0xE7,
0xCF, 0x87, 0xFE, 0x07, 0xF8, 0x00, 0x3F, 0x0F, 0xF3, 0xEF, 0x70, 0x6F, 0xFF, 0xFF, 0xF8, 0x3F, 0x0E, 0xFB, 0xCF,
0xF0, 0xFC, 0x00, 0x0E, 0xE0, 0x1D, 0xC0, 0x00, 0x00, 0xFF, 0x03, 0xFF, 0x0F, 0x9F, 0x1C, 0x0F, 0x70, 0x0E, 0xE0,
0x1D, 0xFF, 0xFB, 0xFF, 0xFF, 0x00, 0xEE, 0x01, 0xDE, 0x03, 0x9C, 0x0F, 0x3E, 0x7C, 0x3F, 0xF0, 0x3F, 0xC0, 0x3B,
0x87, 0x70, 0x00, 0x00, 0x03, 0xF0, 0xFF, 0x3E, 0xF7, 0x06, 0xFF, 0xFF, 0xFF, 0x83, 0xF0, 0xEF, 0xBC, 0xFF, 0x0F,
0xC0, 0x3B, 0x83, 0xB8, 0x00, 0x0F, 0xF8, 0xFF, 0xC7, 0x3E, 0x00, 0xE0, 0x07, 0x00, 0x71, 0xFF, 0x1F, 0xF0, 0x07,
0x00, 0x70, 0x0F, 0x00, 0xE7, 0x7E, 0xFF, 0xCF, 0xF8, 0x77, 0x1D, 0xC0, 0x00, 0x00, 0x7E, 0x1F, 0xE6, 0x78, 0x07,
0x3F, 0xCF, 0xF0, 0x1C, 0x0F, 0x6F, 0xBF, 0xEF, 0xE0, 0x1F, 0xC0, 0xFE, 0x00, 0x01, 0xC0, 0xE7, 0x07, 0x38, 0x39,
0xE3, 0xC7, 0x1C, 0x3C, 0xE0, 0xEE, 0x07, 0xF0, 0x1F, 0x80, 0xF8, 0x03, 0xC0, 0x1C, 0x0B, 0xE0, 0x7E, 0x03, 0xE0,
0x00, 0x3F, 0x87, 0xF0, 0x00, 0x00, 0x0E, 0x1D, 0xC3, 0x9C, 0x73, 0x8E, 0x73, 0x87, 0x70, 0xEE, 0x0F, 0x81, 0xF0,
0x3E, 0x03, 0x80, 0x70, 0xBC, 0x1F, 0x83, 0xE0, 0x00, 0x1D, 0xC0, 0xEE, 0x00, 0x01, 0xC0, 0xE7, 0x07, 0x38, 0x39,
0xE3, 0xC7, 0x1C, 0x3C, 0xE0, 0xEE, 0x07, 0xF0, 0x1F, 0x80, 0xF8, 0x03, 0xC0, 0x1C, 0x0B, 0xE0, 0x7E, 0x03, 0xE0,
0x00, 0x3B, 0x87, 0x70, 0x00, 0x00, 0x0E, 0x1D, 0xC3, 0x9C, 0x73, 0x8E, 0x73, 0x87, 0x70, 0xEE, 0x0F, 0x81, 0xF0,
0x3E, 0x03, 0x80, 0x70, 0xBC, 0x1F, 0x83, 0xE0, 0x00, 0x06, 0x60, 0x7F, 0x03, 0xF0, 0x1B, 0x0E, 0x07, 0x38, 0x39,
0xC1, 0xCF, 0x1E, 0x38, 0xE1, 0xE7, 0x07, 0x70, 0x3F, 0x80, 0xFC, 0x07, 0xC0, 0x1E, 0x00, 0xE0, 0x5F, 0x03, 0xF0,
0x1F, 0x00, 0x0E, 0xC3, 0xF8, 0x7E, 0x0D, 0x80, 0x01, 0xC3, 0xB8, 0x73, 0x8E, 0x71, 0xCE, 0x70, 0xEE, 0x1D, 0xC1,
0xF0, 0x3E, 0x07, 0xC0, 0x70, 0x0E, 0x17, 0x83, 0xF0, 0x7C, 0x00, 0x3B, 0x87, 0x70, 0x00, 0x70, 0x7E, 0x0F, 0xC1,
0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, 0xE7, 0xBF, 0xF3, 0xFE, 0x01, 0xC0, 0x38, 0x07, 0x00, 0xE0, 0x1C, 0x3B, 0x8E,
0xE0, 0x00, 0x00, 0x61, 0xD8, 0x76, 0x1D, 0x87, 0x7B, 0xDF, 0xF3, 0xFC, 0x07, 0x01, 0xC0, 0x70, 0x1C, 0xFF, 0xFF,
0xFE, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x3E, 0x0F, 0x80, 0xE0, 0x38,
0x0E, 0x03, 0x80, 0xFF, 0xFF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xF8, 0xF8, 0x38, 0x38, 0x38, 0x0F, 0xF0,
0x0F, 0xF0, 0x00, 0x00, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xFF, 0x87, 0xFF, 0xC7, 0xE7,
0xE7, 0xE0, 0xE7, 0xE0, 0xE7, 0xE0, 0xE7, 0xE0, 0xE7, 0xE3, 0xE7, 0xFF, 0xC7, 0xFF, 0x87, 0x1D, 0xC0, 0x77, 0x00,
0x00, 0x00, 0x00, 0xE0, 0x1F, 0x80, 0x7E, 0x01, 0xF8, 0x07, 0xFF, 0x1F, 0xFE, 0x7E, 0x7D, 0xF8, 0x77, 0xE7, 0xDF,
0xFE, 0x7F, 0xF1, 0xC0, 0x7F, 0xF7, 0xFF, 0x7F, 0xFF, 0xFD, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFD, 0xFF, 0xFF, 0xF0,
0x76, 0xEE, 0xE0, 0x77, 0x76, 0xE0, 0x77, 0x76, 0xE0, 0x76, 0x6E, 0xEE, 0xEE, 0xEE, 0x77, 0x77, 0x77, 0x6E, 0xEE,
0x77, 0x77, 0x77, 0x6E, 0xEE, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x3F, 0xFF, 0xFC, 0x30, 0x0C, 0x03, 0x00, 0xC0,
0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x3F, 0xFF, 0xFC, 0x30,
0x0C, 0x03, 0x0F, 0xFF, 0xFF, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xFB, 0xFF, 0xFF, 0xF8, 0xE1, 0xC3,
0xF0, 0xE1, 0xF8, 0x70, 0xE0, 0x7C, 0x38, 0x00, 0xEE, 0x38, 0x00, 0xC6, 0x70, 0x00, 0xC6, 0x70, 0x00, 0xC6, 0xE0,
0x00, 0xEE, 0xE0, 0x00, 0x7D, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, 0xBE, 0x3E, 0x07, 0x7F, 0x7F, 0x07, 0x63, 0x67,
0x0E, 0x63, 0x63, 0x0E, 0x63, 0x67, 0x1C, 0x77, 0x77, 0x1C, 0x3E, 0x3E, 0x1C, 0xE3, 0x9C, 0xF1, 0xC3, 0x8E, 0x1C,
0x61, 0xC7, 0x8E, 0x1C, 0xE7, 0x9C, 0x60, 0x00, 0xE0, 0x38, 0x07, 0x01, 0xC0, 0x38, 0x0E, 0x01, 0x80, 0x70, 0x0C,
0x03, 0x80, 0xE0, 0x1C, 0x07, 0x00, 0xE0, 0x38, 0x00, 0x07, 0xF0, 0xFE, 0x1F, 0x61, 0xC0, 0xFF, 0xCF, 0xFC, 0x38,
0x0F, 0xF8, 0xFF, 0x83, 0x80, 0x1C, 0x01, 0xF7, 0x0F, 0xF0, 0x7F, 0xFF, 0xEF, 0xFE, 0x06, 0x00, 0x60, 0x07, 0xC0,
0x7C, 0x3F, 0x83, 0xE0, 0x3F, 0xC0, 0x7C, 0x3F, 0x83, 0xE0, 0x3E, 0x00, 0x60, 0x06, 0x00, 0x3F, 0x83, 0xFC, 0x3B,
0xC0, 0x0E, 0x00, 0xCF, 0xFE, 0x0F, 0x81, 0xF0, 0xFF, 0xE7, 0x00, 0x70, 0x07, 0x00, 0x3D, 0xC3, 0xFE, 0x1F, 0xE0,
0xFF, 0xFF, 0xFC, 0x3C, 0x01, 0xCF, 0xFD, 0xFF, 0x80, 0xE0, 0xF8, 0xFF, 0x1F, 0x83, 0xC0, 0x3C, 0x01, 0xC0, 0x1C,
0x01, 0xC0, 0x3F, 0x83, 0xFC, 0x33, 0xE0, 0x0E, 0x00, 0xE1, 0xFE, 0x3F, 0xF7, 0xDF, 0x70, 0x77, 0x07, 0xE0, 0xEE,
0x0E, 0x70, 0xE7, 0xBC, 0x7F, 0xC3, 0xF8, 0x07, 0x00, 0x1E, 0x00, 0xF8, 0x03, 0xF0, 0x1D, 0xC0, 0x73, 0x81, 0x8E,
0x0E, 0x38, 0x38, 0x70, 0xC1, 0xC7, 0x03, 0x1C, 0x0E, 0xE0, 0x3B, 0xFF, 0xEF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xE0,
0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E,
0x07, 0xE0, 0x70, 0xFF, 0xFF, 0xFD, 0xC0, 0x3C, 0x03, 0x80, 0x38, 0x07, 0x80, 0x70, 0x07, 0x01, 0xC0, 0x70, 0x1E,
0x03, 0x80, 0xE0, 0x3C, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xF0, 0x00, 0xE0, 0x38, 0x07, 0x01, 0xC0, 0x38, 0x0E,
0x01, 0x80, 0x70, 0x0C, 0x03, 0x80, 0xE0, 0x1C, 0x07, 0x00, 0xE0, 0x38, 0x00, 0xFF, 0x80, 0x00, 0x30, 0x03, 0x80,
0x1C, 0x00, 0xE0, 0x06, 0x00, 0x70, 0x03, 0x80, 0x18, 0xF1, 0xC7, 0xCE, 0x3E, 0x60, 0x3B, 0x01, 0xF8, 0x07, 0xC0,
0x3C, 0x00, 0xE0, 0x07, 0x00, 0x7D, 0xEF, 0xFF, 0xE7, 0x3E, 0x73, 0xFF, 0xF7, 0xDE, 0x0F, 0x1F, 0x1E, 0x1C, 0x38,
0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x78, 0xF8, 0xF0, 0x3C, 0x6F, 0xFD, 0xFF,
0xB1, 0xE3, 0xC6, 0xFF, 0xDF, 0xFB, 0x1E, 0x03, 0x80, 0xE0, 0x73, 0xFF, 0xFF, 0xC3, 0x80, 0xC0, 0x70, 0xFF, 0xFF,
0xF3, 0x81, 0xC0, 0x70, 0x00, 0x01, 0xC3, 0xF7, 0xFB, 0xF0, 0xF0, 0x3F, 0x07, 0xF8, 0x3F, 0x03, 0xC0, 0x0F, 0xFF,
0xFF, 0xE0, 0x3F, 0x07, 0xF8, 0x3F, 0x03, 0xC7, 0xF7, 0xFB, 0xF0, 0xE0, 0x00, 0x0F, 0xFF, 0xFF,
}; };
static const EpdGlyph ubuntu_10Glyphs[] = { static const EpdGlyph ubuntu_10Glyphs[] = {
@@ -714,54 +987,269 @@ static const EpdGlyph ubuntu_10Glyphs[] = {
{10, 16, 10, 0, 16, 20, 6630}, // ž {10, 16, 10, 0, 16, 20, 6630}, // ž
{8, 16, 6, 1, 16, 16, 6650}, // ſ {8, 16, 6, 1, 16, 16, 6650}, // ſ
{6, 3, 8, 1, 16, 3, 6666}, // ̑ {6, 3, 8, 1, 16, 3, 6666}, // ̑
{12, 2, 10, -1, 7, 3, 6669}, // {11, 20, 12, 1, 20, 28, 6669}, // Ѐ
{22, 2, 21, -1, 7, 6, 6672}, // {11, 18, 12, 1, 18, 25, 6697}, // Ё
{22, 2, 21, -1, 7, 6, 6678}, // {15, 15, 16, 0, 15, 29, 6722}, // Ђ
{4, 5, 5, 1, 16, 3, 6684}, // {10, 20, 11, 1, 20, 25, 6751}, // Ѓ
{4, 5, 5, 0, 16, 3, 6687}, // {12, 15, 13, 1, 15, 23, 6776}, // Є
{4, 5, 5, 0, 2, 3, 6690}, // {11, 15, 11, 0, 15, 21, 6799}, // Ѕ
{8, 5, 9, 1, 16, 5, 6693}, // {3, 15, 6, 1, 15, 6, 6820}, // І
{8, 5, 9, 0, 16, 5, 6698}, // {8, 18, 6, -1, 18, 18, 6826}, // Ї
{8, 5, 9, 0, 2, 5, 6703}, // {9, 15, 11, 0, 15, 17, 6844}, // Ј
{10, 18, 10, 0, 15, 23, 6708}, // {22, 16, 22, 0, 15, 44, 6861}, // Љ
{10, 18, 10, 0, 15, 23, 6731}, // {20, 15, 22, 1, 15, 38, 6905}, // Њ
{6, 5, 8, 1, 10, 4, 6754}, // {15, 15, 16, 0, 15, 29, 6943}, // Ћ
{17, 3, 21, 2, 3, 7, 6758}, // {13, 20, 13, 1, 20, 33, 6972}, // Ќ
{24, 15, 26, 1, 15, 45, 6765}, // {13, 20, 15, 1, 20, 33, 7005}, // Ѝ
{6, 9, 6, 0, 10, 7, 6810}, // {13, 19, 12, 0, 19, 31, 7038}, // Ў
{6, 9, 6, 0, 10, 7, 6817}, // {12, 19, 15, 1, 15, 29, 7069}, // Џ
{11, 15, 3, -4, 15, 21, 6824}, // {14, 15, 14, 0, 15, 27, 7098}, // А
{12, 14, 12, 0, 14, 21, 6845}, // {12, 15, 13, 1, 15, 23, 7125}, // Б
{12, 15, 12, 0, 15, 23, 6866}, // {12, 15, 14, 1, 15, 23, 7148}, // В
{12, 15, 12, 0, 15, 23, 6889}, // {10, 15, 11, 1, 15, 19, 7171}, // Г
{11, 15, 12, 1, 15, 21, 6912}, // {15, 19, 15, 0, 15, 36, 7190}, // Д
{12, 16, 12, 0, 16, 24, 6933}, // {11, 15, 12, 1, 15, 21, 7226}, // Е
{14, 15, 14, 0, 15, 27, 6957}, // {19, 15, 19, 0, 15, 36, 7247}, // Ж
{12, 17, 15, 1, 15, 26, 6984}, // {11, 15, 12, 0, 15, 21, 7283}, // З
{11, 17, 11, 0, 15, 24, 7010}, // {13, 15, 15, 1, 15, 25, 7304}, // И
{10, 2, 12, 1, 7, 3, 7034}, // {13, 19, 15, 1, 19, 31, 7329}, // Й
{11, 15, 3, -4, 15, 21, 7037}, // {13, 15, 13, 1, 15, 25, 7360}, // К
{3, 3, 5, 1, 8, 2, 7058}, // {14, 15, 15, 0, 15, 27, 7385}, // Л
{13, 17, 12, 0, 16, 28, 7060}, // {16, 15, 18, 1, 15, 30, 7412}, // М
{12, 6, 12, 0, 9, 9, 7088}, // {12, 15, 15, 1, 15, 23, 7442}, // Н
{8, 20, 8, 0, 16, 20, 7097}, // {15, 15, 16, 1, 15, 29, 7465}, // О
{11, 8, 12, 0, 10, 11, 7117}, // {12, 15, 15, 1, 15, 23, 7494}, // П
{10, 13, 12, 1, 13, 17, 7128}, // {12, 15, 13, 1, 15, 23, 7517}, // Р
{10, 12, 12, 1, 12, 15, 7145}, // {12, 15, 13, 1, 15, 23, 7540}, // С
{10, 12, 12, 1, 12, 15, 7160}, // {12, 15, 12, 0, 15, 23, 7563}, // Т
{13, 15, 12, 0, 15, 25, 7586}, // У
{16, 16, 18, 1, 16, 32, 7611}, // Ф
{13, 15, 13, 0, 15, 25, 7643}, // Х
{14, 19, 15, 1, 15, 34, 7668}, // Ц
{11, 15, 13, 1, 15, 21, 7702}, // Ч
{18, 15, 21, 1, 15, 34, 7723}, // Ш
{20, 19, 21, 1, 15, 48, 7757}, // Щ
{15, 15, 15, 0, 15, 29, 7805}, // Ъ
{16, 15, 18, 1, 15, 30, 7834}, // Ы
{12, 15, 13, 1, 15, 23, 7864}, // Ь
{12, 15, 13, 0, 15, 23, 7887}, // Э
{20, 15, 22, 1, 15, 38, 7910}, // Ю
{12, 15, 13, 0, 15, 23, 7948}, // Я
{10, 11, 11, 0, 11, 14, 7971}, // а
{11, 16, 13, 1, 16, 22, 7985}, // б
{10, 11, 12, 1, 11, 14, 8007}, // в
{8, 11, 9, 1, 11, 11, 8021}, // г
{13, 14, 13, 0, 11, 23, 8032}, // д
{10, 11, 12, 1, 11, 14, 8055}, // е
{16, 11, 16, 0, 11, 22, 8069}, // ж
{10, 11, 10, 0, 11, 14, 8091}, // з
{10, 11, 13, 1, 11, 14, 8105}, // и
{10, 16, 13, 1, 16, 20, 8119}, // й
{10, 11, 11, 1, 11, 14, 8139}, // к
{11, 11, 13, 0, 11, 16, 8153}, // л
{13, 11, 15, 1, 11, 18, 8169}, // м
{10, 11, 12, 1, 11, 14, 8187}, // н
{11, 11, 12, 1, 11, 16, 8201}, // о
{10, 11, 12, 1, 11, 14, 8217}, // п
{11, 15, 12, 1, 11, 21, 8231}, // р
{9, 11, 10, 1, 11, 13, 8252}, // с
{10, 11, 10, 0, 11, 14, 8265}, // т
{11, 15, 10, 0, 11, 21, 8279}, // у
{15, 20, 16, 1, 16, 38, 8300}, // ф
{11, 11, 11, 0, 11, 16, 8338}, // х
{11, 14, 12, 1, 11, 20, 8354}, // ц
{10, 11, 11, 0, 11, 14, 8374}, // ч
{15, 11, 17, 1, 11, 21, 8388}, // ш
{17, 14, 18, 1, 11, 30, 8409}, // щ
{12, 11, 13, 0, 11, 17, 8439}, // ъ
{14, 11, 16, 1, 11, 20, 8456}, // ы
{10, 11, 11, 1, 11, 14, 8476}, // ь
{10, 11, 10, 0, 11, 14, 8490}, // э
{15, 11, 17, 1, 11, 21, 8504}, // ю
{10, 11, 12, 0, 11, 14, 8525}, // я
{10, 16, 12, 1, 16, 20, 8539}, // ѐ
{10, 15, 12, 1, 15, 19, 8559}, // ё
{11, 20, 12, 0, 16, 28, 8578}, // ђ
{8, 16, 9, 1, 16, 16, 8606}, // ѓ
{9, 11, 10, 1, 11, 13, 8622}, // є
{9, 11, 9, 0, 11, 13, 8635}, // ѕ
{3, 16, 5, 1, 16, 6, 8648}, // і
{7, 15, 5, -1, 15, 14, 8654}, // ї
{6, 20, 5, -2, 16, 15, 8668}, // ј
{18, 11, 18, 0, 11, 25, 8683}, // љ
{17, 11, 18, 1, 11, 24, 8708}, // њ
{11, 16, 12, 0, 16, 22, 8732}, // ћ
{10, 16, 11, 1, 16, 20, 8754}, // ќ
{10, 16, 13, 1, 16, 20, 8774}, // ѝ
{11, 20, 10, 0, 16, 28, 8794}, // ў
{10, 14, 12, 1, 11, 18, 8822}, // џ
{15, 16, 15, 0, 16, 30, 8840}, // Ѣ
{12, 16, 13, 0, 16, 24, 8870}, // ѣ
{15, 15, 16, 1, 15, 29, 8894}, // Ѳ
{11, 11, 12, 1, 11, 16, 8923}, // ѳ
{17, 15, 16, 0, 15, 32, 8939}, // Ѵ
{12, 11, 12, 0, 11, 17, 8971}, // ѵ
{15, 23, 16, 1, 19, 44, 8988}, // Ҋ
{12, 20, 13, 1, 16, 30, 9032}, // ҋ
{13, 16, 13, 0, 16, 26, 9062}, // Ҍ
{11, 11, 11, 0, 11, 16, 9088}, // ҍ
{12, 15, 13, 1, 15, 23, 9104}, // Ҏ
{11, 15, 12, 1, 11, 21, 9127}, // ҏ
{10, 18, 11, 1, 18, 23, 9148}, // Ґ
{8, 14, 9, 1, 14, 14, 9171}, // ґ
{11, 15, 11, 0, 15, 21, 9185}, // Ғ
{9, 11, 9, 0, 11, 13, 9206}, // ғ
{12, 19, 13, 1, 15, 29, 9219}, // Ҕ
{10, 15, 11, 1, 11, 19, 9248}, // ҕ
{20, 19, 19, 0, 15, 48, 9267}, // Җ
{17, 14, 16, 0, 11, 30, 9315}, // җ
{11, 18, 12, 0, 15, 25, 9345}, // Ҙ
{10, 14, 10, 0, 11, 18, 9370}, // ҙ
{13, 19, 14, 1, 15, 31, 9388}, // Қ
{11, 15, 11, 1, 11, 21, 9419}, // қ
{14, 15, 15, 1, 15, 27, 9440}, // Ҝ
{12, 11, 13, 1, 11, 17, 9467}, // ҝ
{14, 15, 13, 0, 15, 27, 9484}, // Ҟ
{12, 11, 12, 0, 11, 17, 9511}, // ҟ
{16, 15, 16, 0, 15, 30, 9528}, // Ҡ
{13, 11, 13, 0, 11, 18, 9558}, // ҡ
{14, 19, 15, 1, 15, 34, 9576}, // Ң
{12, 14, 13, 1, 11, 21, 9610}, // ң
{16, 15, 17, 1, 15, 30, 9631}, // Ҥ
{13, 11, 14, 1, 11, 18, 9661}, // ҥ
{20, 19, 22, 1, 15, 48, 9679}, // Ҧ
{17, 15, 18, 1, 11, 32, 9727}, // ҧ
{15, 19, 17, 1, 15, 36, 9759}, // Ҩ
{11, 14, 13, 1, 11, 20, 9795}, // ҩ
{12, 18, 13, 1, 15, 27, 9815}, // Ҫ
{9, 15, 10, 1, 11, 17, 9842}, // ҫ
{12, 19, 12, 0, 15, 29, 9859}, // Ҭ
{10, 14, 10, 0, 11, 18, 9888}, // ҭ
{13, 15, 13, 0, 15, 25, 9906}, // Ү
{11, 15, 11, 0, 11, 21, 9931}, // ү
{13, 15, 13, 0, 15, 25, 9952}, // Ұ
{11, 15, 11, 0, 11, 21, 9977}, // ұ
{14, 19, 14, 0, 15, 34, 9998}, // Ҳ
{11, 14, 11, 0, 11, 20, 10032}, // ҳ
{18, 19, 18, 0, 15, 43, 10052}, // Ҵ
{14, 14, 14, 0, 11, 25, 10095}, // ҵ
{13, 19, 14, 1, 15, 31, 10120}, // Ҷ
{11, 14, 11, 0, 11, 20, 10151}, // ҷ
{11, 15, 13, 1, 15, 21, 10171}, // Ҹ
{10, 11, 11, 0, 11, 14, 10192}, // ҹ
{12, 15, 13, 1, 15, 23, 10206}, // Һ
{10, 16, 12, 1, 16, 20, 10229}, // һ
{17, 15, 18, 0, 15, 32, 10249}, // Ҽ
{13, 11, 14, 0, 11, 18, 10281}, // ҽ
{17, 19, 18, 0, 15, 41, 10299}, // Ҿ
{13, 14, 14, 0, 11, 23, 10340}, // ҿ
{3, 15, 6, 1, 15, 6, 10363}, // Ӏ
{19, 19, 19, 0, 19, 46, 10369}, // Ӂ
{16, 16, 16, 0, 16, 32, 10415}, // ӂ
{12, 19, 13, 1, 15, 29, 10447}, // Ӄ
{10, 15, 11, 1, 11, 19, 10476}, // ӄ
{15, 19, 15, 0, 15, 36, 10495}, // Ӆ
{13, 15, 13, 0, 11, 25, 10531}, // ӆ
{12, 19, 15, 1, 15, 29, 10556}, // Ӈ
{10, 15, 12, 1, 11, 19, 10585}, // ӈ
{14, 19, 15, 1, 15, 34, 10604}, // Ӊ
{12, 15, 13, 1, 11, 23, 10638}, // ӊ
{11, 19, 13, 1, 15, 27, 10661}, // Ӌ
{10, 14, 11, 0, 11, 18, 10688}, // ӌ
{18, 19, 19, 1, 15, 43, 10706}, // Ӎ
{15, 15, 16, 1, 11, 29, 10749}, // ӎ
{3, 15, 6, 1, 15, 6, 10778}, // ӏ
{14, 19, 14, 0, 19, 34, 10784}, // Ӑ
{10, 16, 11, 0, 16, 20, 10818}, // ӑ
{14, 18, 14, 0, 18, 32, 10838}, // Ӓ
{10, 15, 11, 0, 15, 19, 10870}, // ӓ
{19, 15, 20, 0, 15, 36, 10889}, // Ӕ
{17, 11, 18, 0, 11, 24, 10925}, // ӕ
{11, 19, 12, 1, 19, 27, 10949}, // Ӗ
{10, 16, 12, 1, 16, 20, 10976}, // ӗ
{13, 15, 15, 1, 15, 25, 10996}, // Ә
{10, 11, 12, 1, 11, 14, 11021}, // ә
{13, 18, 15, 1, 18, 30, 11035}, // Ӛ
{10, 15, 12, 1, 15, 19, 11065}, // ӛ
{19, 18, 19, 0, 18, 43, 11084}, // Ӝ
{16, 15, 16, 0, 15, 30, 11127}, // ӝ
{11, 18, 12, 0, 18, 25, 11157}, // Ӟ
{10, 15, 10, 0, 15, 19, 11182}, // ӟ
{11, 15, 12, 0, 15, 21, 11201}, // Ӡ
{11, 15, 10, -1, 11, 21, 11222}, // ӡ
{13, 18, 15, 1, 18, 30, 11243}, // Ӣ
{10, 15, 13, 1, 15, 19, 11273}, // ӣ
{13, 18, 15, 1, 18, 30, 11292}, // Ӥ
{10, 15, 13, 1, 15, 19, 11322}, // ӥ
{15, 18, 16, 1, 18, 34, 11341}, // Ӧ
{11, 15, 12, 1, 15, 21, 11375}, // ӧ
{15, 15, 16, 1, 15, 29, 11396}, // Ө
{11, 11, 12, 1, 11, 16, 11425}, // ө
{15, 18, 16, 1, 18, 34, 11441}, // Ӫ
{11, 15, 12, 1, 15, 21, 11475}, // ӫ
{12, 18, 13, 0, 18, 27, 11496}, // Ӭ
{10, 15, 10, 0, 15, 19, 11523}, // ӭ
{13, 18, 12, 0, 18, 30, 11542}, // Ӯ
{11, 19, 10, 0, 15, 27, 11572}, // ӯ
{13, 18, 12, 0, 18, 30, 11599}, // Ӱ
{11, 19, 10, 0, 15, 27, 11629}, // ӱ
{13, 19, 12, 0, 19, 31, 11656}, // Ӳ
{11, 20, 10, 0, 16, 28, 11687}, // ӳ
{11, 18, 13, 1, 18, 25, 11715}, // Ӵ
{10, 15, 11, 0, 15, 19, 11740}, // ӵ
{10, 19, 11, 1, 15, 24, 11759}, // Ӷ
{8, 14, 9, 1, 11, 14, 11783}, // ӷ
{16, 18, 18, 1, 18, 36, 11797}, // Ӹ
{14, 15, 16, 1, 15, 27, 11833}, // ӹ
{12, 2, 10, -1, 7, 3, 11860}, //
{22, 2, 21, -1, 7, 6, 11863}, // —
{22, 2, 21, -1, 7, 6, 11869}, // ―
{4, 5, 5, 1, 16, 3, 11875}, //
{4, 5, 5, 0, 16, 3, 11878}, //
{4, 5, 5, 0, 2, 3, 11881}, //
{8, 5, 9, 1, 16, 5, 11884}, // “
{8, 5, 9, 0, 16, 5, 11889}, // ”
{8, 5, 9, 0, 2, 5, 11894}, // „
{10, 18, 10, 0, 15, 23, 11899}, // †
{10, 18, 10, 0, 15, 23, 11922}, // ‡
{6, 5, 8, 1, 10, 4, 11945}, // •
{17, 3, 21, 2, 3, 7, 11949}, // …
{24, 15, 26, 1, 15, 45, 11956}, // ‰
{6, 9, 6, 0, 10, 7, 12001}, //
{6, 9, 6, 0, 10, 7, 12008}, //
{11, 15, 3, -4, 15, 21, 12015}, //
{12, 14, 12, 0, 14, 21, 12036}, // €
{12, 15, 12, 0, 15, 23, 12057}, // ₮
{12, 15, 12, 0, 15, 23, 12080}, // ₴
{11, 15, 12, 1, 15, 21, 12103}, // ₹
{12, 16, 12, 0, 16, 24, 12124}, // ∂
{14, 15, 14, 0, 15, 27, 12148}, // ∆
{12, 17, 15, 1, 15, 26, 12175}, // ∏
{11, 17, 11, 0, 15, 24, 12201}, // ∑
{10, 2, 12, 1, 7, 3, 12225}, //
{11, 15, 3, -4, 15, 21, 12228}, //
{3, 3, 5, 1, 8, 2, 12249}, // ∙
{13, 17, 12, 0, 16, 28, 12251}, // √
{12, 6, 12, 0, 9, 9, 12279}, // ∞
{8, 20, 8, 0, 16, 20, 12288}, // ∫
{11, 8, 12, 0, 10, 11, 12308}, // ≈
{10, 13, 12, 1, 13, 17, 12319}, // ≠
{10, 12, 12, 1, 12, 15, 12336}, // ≤
{10, 12, 12, 1, 12, 15, 12351}, // ≥
}; };
static const EpdUnicodeInterval ubuntu_10Intervals[] = { static const EpdUnicodeInterval ubuntu_10Intervals[] = {
{0x0, 0x0, 0x0}, {0x8, 0x9, 0x1}, {0xD, 0xD, 0x3}, {0x1D, 0x1D, 0x4}, {0x0, 0x0, 0x0}, {0x8, 0x9, 0x1}, {0xD, 0xD, 0x3}, {0x1D, 0x1D, 0x4},
{0x20, 0x7E, 0x5}, {0xA0, 0xFF, 0x64}, {0x100, 0x17F, 0xC4}, {0x311, 0x311, 0x144}, {0x20, 0x7E, 0x5}, {0xA0, 0xFF, 0x64}, {0x100, 0x17F, 0xC4}, {0x311, 0x311, 0x144},
{0x2013, 0x2015, 0x145}, {0x2018, 0x201A, 0x148}, {0x201C, 0x201E, 0x14B}, {0x2020, 0x2022, 0x14E}, {0x400, 0x45F, 0x145}, {0x462, 0x463, 0x1A5}, {0x472, 0x475, 0x1A7}, {0x48A, 0x4F9, 0x1AB},
{0x2026, 0x2026, 0x151}, {0x2030, 0x2030, 0x152}, {0x2039, 0x203A, 0x153}, {0x2044, 0x2044, 0x155}, {0x2013, 0x2015, 0x21B}, {0x2018, 0x201A, 0x21E}, {0x201C, 0x201E, 0x221}, {0x2020, 0x2022, 0x224},
{0x20AC, 0x20AC, 0x156}, {0x20AE, 0x20AE, 0x157}, {0x20B4, 0x20B4, 0x158}, {0x20B9, 0x20B9, 0x159}, {0x2026, 0x2026, 0x227}, {0x2030, 0x2030, 0x228}, {0x2039, 0x203A, 0x229}, {0x2044, 0x2044, 0x22B},
{0x2202, 0x2202, 0x15A}, {0x2206, 0x2206, 0x15B}, {0x220F, 0x220F, 0x15C}, {0x2211, 0x2212, 0x15D}, {0x20AC, 0x20AC, 0x22C}, {0x20AE, 0x20AE, 0x22D}, {0x20B4, 0x20B4, 0x22E}, {0x20B9, 0x20B9, 0x22F},
{0x2215, 0x2215, 0x15F}, {0x2219, 0x221A, 0x160}, {0x221E, 0x221E, 0x162}, {0x222B, 0x222B, 0x163}, {0x2202, 0x2202, 0x230}, {0x2206, 0x2206, 0x231}, {0x220F, 0x220F, 0x232}, {0x2211, 0x2212, 0x233},
{0x2248, 0x2248, 0x164}, {0x2260, 0x2260, 0x165}, {0x2264, 0x2265, 0x166}, {0x2215, 0x2215, 0x235}, {0x2219, 0x221A, 0x236}, {0x221E, 0x221E, 0x238}, {0x222B, 0x222B, 0x239},
{0x2248, 0x2248, 0x23A}, {0x2260, 0x2260, 0x23B}, {0x2264, 0x2265, 0x23C},
}; };
static const EpdFontData ubuntu_10 = { static const EpdFontData ubuntu_10 = {
ubuntu_10Bitmaps, ubuntu_10Glyphs, ubuntu_10Intervals, 31, 24, 20, -4, false, ubuntu_10Bitmaps, ubuntu_10Glyphs, ubuntu_10Intervals, 35, 24, 20, -4, false,
}; };
+589 -73
View File
@@ -7,7 +7,7 @@
#pragma once #pragma once
#include "EpdFontData.h" #include "EpdFontData.h"
static const uint8_t ubuntu_bold_10Bitmaps[8017] = { static const uint8_t ubuntu_bold_10Bitmaps[13720] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xEF, 0xEF, 0xE7, 0x1E, 0xF0, 0xF7, 0x87, 0x3C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xEF, 0xEF, 0xE7, 0x1E, 0xF0, 0xF7, 0x87, 0x3C,
0x39, 0xCF, 0xFF, 0xFF, 0xFC, 0xF7, 0x87, 0xBC, 0x39, 0xE7, 0xFF, 0xFF, 0xFE, 0xF7, 0x87, 0xBC, 0x39, 0xE1, 0xCE, 0x39, 0xCF, 0xFF, 0xFF, 0xFC, 0xF7, 0x87, 0xBC, 0x39, 0xE7, 0xFF, 0xFF, 0xFE, 0xF7, 0x87, 0xBC, 0x39, 0xE1, 0xCE,
0x00, 0x0F, 0x01, 0xE0, 0xFF, 0xBF, 0xF7, 0xFC, 0xFB, 0x9E, 0x03, 0xF8, 0x3F, 0xC3, 0xFC, 0x1F, 0x80, 0xF7, 0xBE, 0x00, 0x0F, 0x01, 0xE0, 0xFF, 0xBF, 0xF7, 0xFC, 0xFB, 0x9E, 0x03, 0xF8, 0x3F, 0xC3, 0xFC, 0x1F, 0x80, 0xF7, 0xBE,
@@ -400,36 +400,337 @@ static const uint8_t ubuntu_bold_10Bitmaps[8017] = {
0x80, 0xF8, 0x07, 0x80, 0x7C, 0x07, 0xC0, 0x3C, 0x03, 0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x33, 0x0F, 0xE3, 0x80, 0xF8, 0x07, 0x80, 0x7C, 0x07, 0xC0, 0x3C, 0x03, 0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x33, 0x0F, 0xE3,
0xF0, 0x7C, 0x0E, 0x00, 0x07, 0xFD, 0xFF, 0x7F, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1F, 0x0F, 0xFF, 0xFF, 0xFF, 0xC0, 0xF0, 0x7C, 0x0E, 0x00, 0x07, 0xFD, 0xFF, 0x7F, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1F, 0x0F, 0xFF, 0xFF, 0xFF, 0xC0,
0x3F, 0x3F, 0xBF, 0xDF, 0x6F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0x7E, 0x3F, 0x3F, 0xBF, 0xDF, 0x6F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0x7E,
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x0C, 0x03, 0xC0, 0x78, 0x07, 0x80, 0x70, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F,
0xFF, 0xFF, 0xFF, 0xFE, 0x3B, 0xDE, 0xEF, 0x78, 0x7B, 0xDF, 0xEF, 0x70, 0x7B, 0xDF, 0xEF, 0x70, 0x3B, 0xDE, 0xE7, 0xFD, 0xFF, 0xBF, 0xF7, 0x80, 0xF0, 0x1E, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0x7B, 0xCF, 0x79, 0xEF, 0x00, 0x00, 0x01,
0xF9, 0xDE, 0xF7, 0xBD, 0xE0, 0x7F, 0xBF, 0xDD, 0xFE, 0xFF, 0x77, 0x38, 0x7F, 0xBF, 0xDD, 0xFE, 0xFF, 0x77, 0x38, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x1E, 0x03, 0xC0, 0x7F, 0xEF, 0xFD, 0xFF, 0xBC, 0x07, 0x80, 0xF0, 0x1F, 0xFF, 0xFF,
0x1E, 0x07, 0x81, 0xE0, 0x78, 0xFF, 0xFF, 0xFF, 0xFC, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x03, 0x80, 0xE0, 0xFF, 0xF0, 0xFF, 0xF8, 0x7F, 0xFC, 0x3F, 0xFE, 0x01, 0xE0, 0x00, 0xF0, 0x00, 0x7F, 0xE0, 0x3F, 0xF8, 0x1F, 0xFE,
0x38, 0x0E, 0x03, 0x80, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0xFF, 0xFF, 0xFF, 0xFC, 0x78, 0x1E, 0x07, 0x8F, 0xFF, 0xFF, 0x0F, 0x9F, 0x07, 0x87, 0xC3, 0xC1, 0xE1, 0xE3, 0xE0, 0xF7, 0xF0, 0x7B, 0xF8, 0x3D, 0xF8, 0x03, 0x00, 0xF0, 0x3E,
0xFF, 0xC7, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0x7C, 0xFF, 0xFF, 0xF7, 0xEF, 0x80, 0xF0, 0xE1, 0xFF, 0x3E, 0x7F, 0x0F, 0x01, 0xC0, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0,
0xE7, 0xCF, 0xF8, 0x70, 0xF0, 0x3E, 0x1E, 0x00, 0x0F, 0xE3, 0xC0, 0x01, 0xDC, 0xF0, 0x00, 0x7B, 0xDE, 0x00, 0x0F, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x00, 0x1F, 0xF1, 0xFF, 0xDF, 0xFD, 0xFD, 0xEF, 0x80, 0x78, 0x03, 0xFF, 0x1F, 0xF8,
0x7F, 0x80, 0x00, 0xEE, 0xF0, 0x00, 0x1F, 0xFC, 0x00, 0x01, 0xF7, 0xFE, 0x7E, 0x01, 0xFF, 0xCF, 0xE0, 0x3B, 0xFF, 0xFF, 0xC7, 0x80, 0x3E, 0x01, 0xFD, 0xE7, 0xFF, 0x1F, 0xFC, 0x7F, 0xC0, 0x1F, 0xE3, 0xFE, 0x7F, 0xE7, 0xDC, 0x78,
0xFC, 0x0F, 0x73, 0xF3, 0x83, 0xCE, 0x7E, 0x70, 0x79, 0xFF, 0xFE, 0x1E, 0x3F, 0x9F, 0xC3, 0xC3, 0xF3, 0xF0, 0x00, 0x07, 0xE0, 0x7F, 0x83, 0xFE, 0x0F, 0xE0, 0x3F, 0x01, 0xF7, 0xBF, 0x7F, 0xFF, 0xFE, 0x7F, 0xC0, 0xFF, 0xFF, 0xFF,
0x38, 0xF3, 0xE7, 0x9F, 0x1E, 0x3E, 0x3C, 0x38, 0x00, 0x00, 0xE3, 0xE3, 0xE3, 0xC7, 0xCF, 0x3E, 0xF8, 0xE0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF7, 0x7B, 0xFD, 0xC0, 0x03, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83,
0x01, 0xE0, 0x3C, 0x0F, 0x01, 0xE0, 0x78, 0x0F, 0x03, 0xC0, 0x78, 0x1E, 0x03, 0xC0, 0xF0, 0x1E, 0x07, 0x80, 0xF0, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x00, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03,
0x3C, 0x00, 0x07, 0xF0, 0xFF, 0x1F, 0xF1, 0xF6, 0x3C, 0x07, 0xFE, 0x7F, 0xC3, 0xC0, 0x7F, 0xC7, 0xFC, 0x3C, 0x03, 0xC0, 0xF0, 0x3D, 0x9F, 0xFF, 0xFF, 0xEF, 0xF0, 0x07, 0xFE, 0x00, 0x1F, 0xFC, 0x00, 0x3F, 0xF8, 0x00, 0x78, 0xF0,
0xF7, 0x1F, 0xF0, 0xFF, 0x07, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0x0F, 0xC0, 0xFC, 0x1F, 0xC3, 0xF0, 0x3F, 0x00, 0xF1, 0xE0, 0x01, 0xE3, 0xFF, 0x03, 0xC7, 0xFF, 0x07, 0x8F, 0xFF, 0x0F, 0x1E, 0x7E, 0x3E, 0x3C, 0x3C, 0x78,
0xC3, 0xFC, 0x1F, 0xC3, 0xF0, 0x3F, 0x03, 0xF0, 0x0F, 0x00, 0x3F, 0x87, 0xFC, 0x3F, 0xE3, 0xBE, 0xFF, 0xFF, 0xFF, 0x78, 0x7B, 0xF0, 0xF3, 0xFF, 0xE1, 0xFF, 0xFF, 0x83, 0xFF, 0xBC, 0x07, 0xFE, 0x00, 0xF0, 0x78, 0x07, 0x83, 0xC0,
0x1F, 0x83, 0xF0, 0xFF, 0xFF, 0xFF, 0x78, 0x07, 0xDE, 0x7F, 0xE3, 0xFE, 0x1F, 0xE0, 0xFF, 0xFF, 0xFF, 0xC1, 0xF0, 0x3C, 0x1E, 0x01, 0xE0, 0xF0, 0x0F, 0x07, 0x80, 0x7F, 0xFF, 0xF3, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xF0, 0x79, 0xFF,
0x07, 0xCF, 0xFF, 0x7F, 0xF8, 0x0F, 0x01, 0xF8, 0xFF, 0x87, 0xF8, 0x1F, 0x00, 0x7C, 0x01, 0xF0, 0x07, 0xC0, 0x1F, 0x83, 0xC3, 0xFC, 0x1E, 0x1F, 0xE0, 0xF3, 0xFF, 0x07, 0xFF, 0xF8, 0x3F, 0xFB, 0xC1, 0xFF, 0x00, 0xFF, 0xF8, 0xFF,
0x00, 0x3F, 0x83, 0xFC, 0x3F, 0xE3, 0xBF, 0x00, 0xF1, 0xFF, 0x3F, 0xF7, 0xFF, 0x7D, 0xFF, 0x0F, 0xF0, 0xFF, 0xBE, 0xF8, 0xFF, 0xF8, 0x0F, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0x0F, 0xFC, 0x0F, 0xFE, 0x0F, 0xFE, 0x0F, 0x3F, 0x0F, 0x0F,
0x7F, 0xE7, 0xFC, 0x3F, 0x80, 0x07, 0x80, 0x0F, 0x80, 0x3F, 0x00, 0x7F, 0x01, 0xFE, 0x03, 0xDC, 0x07, 0xBC, 0x1E, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x01, 0x80, 0x07, 0x00, 0x3C, 0x01, 0xE0, 0x07, 0x00, 0x00, 0x0F,
0x78, 0x3C, 0x78, 0x78, 0xF1, 0xE1, 0xE3, 0xC1, 0xE7, 0xFF, 0xDF, 0xFF, 0xBF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xBC, 0x7C, 0xF3, 0xE3, 0xDF, 0x0F, 0xF8, 0x3F, 0xC0, 0xFE, 0x03, 0xFC, 0x0F, 0xF8, 0x3D, 0xF0, 0xF7, 0xC3,
0xFF, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xCF, 0x8F, 0x1F, 0x3C, 0x3E, 0xF0, 0xF8, 0x06, 0x00, 0x3C, 0x00, 0xF8, 0x01, 0xE0, 0x01, 0x80, 0x00, 0x0F, 0x07,
0xC1, 0xFE, 0x0F, 0xF0, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0x07, 0xC0, 0x7C, 0x07, 0x80, 0xF8, 0x0F, 0x83, 0xE0, 0xFC, 0x1F, 0xF0, 0xFF, 0xC7, 0xFF, 0x3F, 0xFC, 0xFF, 0xF7, 0xBF, 0xFE, 0xFF, 0xF3, 0xFF, 0x8F, 0xFE, 0x3F, 0xF0,
0x78, 0x1E, 0x07, 0xC0, 0xF0, 0x3F, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFC, 0x01, 0xE0, 0x3C, 0x0F, 0x01, 0xFF, 0x83, 0xFE, 0x0F, 0xF0, 0x3C, 0x0C, 0xE0, 0x7B, 0x80, 0xFE, 0x01, 0xF0, 0x00, 0x03, 0xE1, 0xF7, 0x87, 0x9F,
0xE0, 0x78, 0x0F, 0x03, 0xC0, 0x78, 0x1E, 0x03, 0xC0, 0xF0, 0x1E, 0x07, 0x80, 0xF0, 0x3C, 0x00, 0x77, 0xFE, 0xE0, 0x1E, 0x3C, 0xF8, 0xFB, 0xC1, 0xEF, 0x07, 0xFC, 0x0F, 0xE0, 0x3F, 0x80, 0x7C, 0x01, 0xF0, 0x6F, 0x81, 0xFE, 0x07,
0x00, 0x3C, 0x01, 0xE0, 0x07, 0x80, 0x1E, 0x00, 0x70, 0x03, 0xC0, 0x0F, 0x0F, 0x38, 0xFD, 0xE3, 0xF7, 0x87, 0xFC, 0xF0, 0x1F, 0x80, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83,
0x07, 0xF0, 0x0F, 0xC0, 0x3E, 0x00, 0x78, 0x00, 0x7D, 0xF3, 0xFF, 0xFF, 0xFF, 0xEE, 0x7F, 0xFF, 0xBF, 0xFD, 0xF7, 0xFC, 0x1F, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x07, 0xC0, 0x0F, 0x80,
0xC0, 0x00, 0x07, 0xC7, 0xE7, 0xF3, 0xE1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3F, 0x80, 0x7F, 0x00, 0xFF, 0x03, 0xDE, 0x07, 0xBC, 0x1F, 0x3C, 0x3C, 0x78, 0x7F, 0xF1, 0xFF, 0xF3, 0xFF, 0xE7,
0x7C, 0x7E, 0x3F, 0x1F, 0x00, 0x00, 0x3C, 0x77, 0xFF, 0x7F, 0xEF, 0xFE, 0xE3, 0xC0, 0x00, 0x3C, 0x77, 0xFF, 0x7F, 0x83, 0xFF, 0x07, 0xFC, 0x07, 0x80, 0xFF, 0xEF, 0xFE, 0xFF, 0xEF, 0x00, 0xF0, 0x0F, 0xFC, 0xFF, 0xEF, 0xFF, 0xF3,
0xEF, 0xFE, 0xE3, 0xC0, 0x03, 0x80, 0xE0, 0x7B, 0xFF, 0xFF, 0xFF, 0xF0, 0xE0, 0x70, 0xFF, 0xFF, 0xFF, 0xFD, 0xC0, 0xFF, 0x0F, 0xF0, 0xFF, 0x3F, 0xFF, 0xFF, 0xFE, 0xFF, 0xC0, 0xFF, 0xC7, 0xFF, 0x3F, 0xFD, 0xE3, 0xEF, 0x1F, 0x7F,
0x70, 0x1C, 0x00, 0x07, 0xDF, 0xFF, 0xFF, 0xFE, 0xF8, 0x3F, 0xEF, 0xFD, 0xFF, 0x07, 0xC0, 0x0F, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0x9F, 0xFE, 0xF1, 0xF7, 0x87, 0xFC, 0x3F, 0xE7, 0xEF, 0xFF, 0x7F, 0xF3, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
0xC0, 0xF8, 0x3F, 0xCF, 0xFD, 0xFF, 0x0F, 0xDF, 0xFF, 0xFF, 0xFE, 0xF8, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xF8, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x00, 0x0F,
0xFE, 0x07, 0xFF, 0x03, 0xFF, 0x81, 0xE3, 0xC0, 0xF1, 0xE0, 0x78, 0xF0, 0x3C, 0x78, 0x1E, 0x3C, 0x1F, 0x1E, 0x0F,
0x0F, 0x07, 0x87, 0x87, 0xC3, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0x03, 0xFC,
0x01, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0x01, 0xE0, 0x3F, 0xF7, 0xFE, 0xFF, 0xDE, 0x03, 0xC0, 0x78, 0x0F,
0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0xF0, 0xFB, 0xE7, 0x8F, 0x9F, 0xBC, 0xF8, 0x7D, 0xEF, 0x81, 0xFF, 0x7C, 0x07, 0xFF,
0xC0, 0x1F, 0xFC, 0x00, 0xFF, 0xC0, 0x0F, 0xFF, 0x00, 0xFF, 0xFC, 0x07, 0xFD, 0xF0, 0x7D, 0xE7, 0xC7, 0xCF, 0x3E,
0x3C, 0x78, 0xFB, 0xE3, 0xC3, 0xE0, 0x7F, 0xC7, 0xFE, 0x7F, 0xE7, 0xBF, 0x01, 0xF0, 0x3E, 0x1F, 0xE1, 0xFE, 0x1F,
0xF0, 0x3F, 0x00, 0xF7, 0xBF, 0x7F, 0xFF, 0xFE, 0x7F, 0xC0, 0xF0, 0x7F, 0xC1, 0xFF, 0x0F, 0xFC, 0x7F, 0xF3, 0xFF,
0xCF, 0xFF, 0x7B, 0xFF, 0xEF, 0xFF, 0x3F, 0xF8, 0xFF, 0xE3, 0xFF, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x03, 0xC0, 0x0C,
0xE0, 0x7F, 0x80, 0xFE, 0x03, 0xF0, 0x00, 0x03, 0xC1, 0xFF, 0x07, 0xFC, 0x3F, 0xF1, 0xFF, 0xCF, 0xFF, 0x3F, 0xFD,
0xEF, 0xFF, 0xBF, 0xFC, 0xFF, 0xE3, 0xFF, 0x8F, 0xFC, 0x3F, 0xE0, 0xFF, 0x83, 0xFC, 0x0F, 0xF0, 0xFB, 0xC7, 0xCF,
0x3E, 0x3D, 0xF0, 0xFF, 0x83, 0xFC, 0x0F, 0xE0, 0x3F, 0xC0, 0xFF, 0x83, 0xDF, 0x0F, 0x7C, 0x3C, 0xF8, 0xF1, 0xF3,
0xC3, 0xEF, 0x0F, 0x80, 0x07, 0xFE, 0x1F, 0xFC, 0x3F, 0xF8, 0x78, 0xF0, 0xF1, 0xE1, 0xE3, 0xC3, 0xC7, 0x87, 0x8F,
0x0F, 0x1E, 0x3E, 0x3C, 0x78, 0x7B, 0xF0, 0xFF, 0xE1, 0xFF, 0x83, 0xFC, 0x07, 0x80, 0x78, 0x0F, 0x3E, 0x0F, 0x9F,
0x07, 0xCF, 0xC7, 0xEF, 0xE3, 0xF7, 0xFB, 0xFB, 0xFD, 0xFF, 0xEE, 0xEF, 0xF7, 0xF7, 0xFB, 0xF3, 0xFC, 0xF9, 0xFE,
0x7C, 0xFF, 0x1C, 0x7F, 0x80, 0x3F, 0xC0, 0x1E, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xE0, 0x1F, 0xE0, 0x7F, 0xF1, 0xFF,
0xF3, 0xF7, 0xEF, 0x83, 0xDE, 0x07, 0xFC, 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0xE0, 0x7F, 0xE0, 0xFF, 0xF7, 0xE7, 0xFF,
0xC7, 0xFF, 0x07, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0,
0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xE0, 0xFF, 0xCF, 0xFE, 0xFF, 0xFF, 0x3F, 0xF0, 0xFF,
0x0F, 0xF3, 0xFF, 0xFF, 0xFF, 0xEF, 0xFC, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x00, 0x1F, 0xF1, 0xFF, 0x9F,
0xFC, 0xFD, 0xEF, 0x80, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3E, 0x01, 0xFC, 0xE7, 0xFF, 0x1F, 0xF8,
0x7F, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x1F, 0x00, 0xF8, 0x07, 0xC0, 0x3E, 0x01, 0xF0, 0x0F, 0x80, 0x7C, 0x03,
0xE0, 0x1F, 0x00, 0xF8, 0x07, 0xC0, 0x3E, 0x00, 0xF8, 0x7D, 0xE1, 0xE7, 0xC7, 0x8F, 0x3E, 0x3E, 0xF0, 0x7B, 0xC1,
0xFF, 0x03, 0xF8, 0x0F, 0xE0, 0x1F, 0x00, 0x7C, 0x1B, 0xE0, 0x7F, 0x81, 0xFC, 0x07, 0xE0, 0x00, 0x01, 0xE0, 0x00,
0x78, 0x00, 0xFF, 0xC0, 0x7F, 0xFC, 0x3F, 0xFF, 0x9F, 0xFF, 0xE7, 0x9E, 0x7D, 0xE7, 0x8F, 0x79, 0xE3, 0xDE, 0x79,
0xF7, 0xFF, 0xF8, 0xFF, 0xFE, 0x3F, 0xFF, 0x03, 0xFF, 0x00, 0x1E, 0x00, 0x07, 0x80, 0xF8, 0x7D, 0xF3, 0xE7, 0xEF,
0x8F, 0xFC, 0x1F, 0xE0, 0x7F, 0x80, 0xFC, 0x01, 0xF0, 0x0F, 0xC0, 0x7F, 0x83, 0xFF, 0x0F, 0xFC, 0x7C, 0xF9, 0xE1,
0xFF, 0x87, 0xC0, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78,
0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x00, 0x0F, 0x00,
0x0F, 0x00, 0x0F, 0xF8, 0x7F, 0xC3, 0xFE, 0x1F, 0xF0, 0xFF, 0x87, 0xFC, 0x3D, 0xF3, 0xEF, 0xFF, 0x7F, 0xF8, 0xFF,
0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0xF0, 0xF1, 0xFE, 0x1E, 0x3F, 0xC3, 0xC7, 0xF8, 0x78, 0xFF,
0x0F, 0x1F, 0xE1, 0xE3, 0xFC, 0x3C, 0x7F, 0x87, 0x8F, 0xF0, 0xF1, 0xFE, 0x1E, 0x3F, 0xC3, 0xC7, 0xF8, 0x78, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF0, 0xF1, 0xE3, 0xC3, 0xC7, 0x8F, 0x0F, 0x1E, 0x3C, 0x3C, 0x78, 0xF0,
0xF1, 0xE3, 0xC3, 0xC7, 0x8F, 0x0F, 0x1E, 0x3C, 0x3C, 0x78, 0xF0, 0xF1, 0xE3, 0xC3, 0xC7, 0x8F, 0x0F, 0x1E, 0x3C,
0x3C, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0x00, 0x00, 0x3C, 0x00, 0x00, 0xF0,
0x00, 0x03, 0xC0, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0x0F, 0xF8, 0x0F, 0xFE, 0x0F, 0xFE,
0x0F, 0x7F, 0x0F, 0x1F, 0x0F, 0x1F, 0x0F, 0x7F, 0x0F, 0xFE, 0x0F, 0xFC, 0x0F, 0xF8, 0xF0, 0x07, 0xF8, 0x03, 0xFC,
0x01, 0xFE, 0x00, 0xFF, 0x00, 0x7F, 0xFE, 0x3F, 0xFF, 0x9F, 0xFF, 0xEF, 0xF3, 0xF7, 0xF8, 0x7B, 0xFC, 0x3D, 0xFE,
0x7E, 0xFF, 0xFF, 0x7F, 0xFF, 0x3F, 0xFE, 0x1E, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0xFC, 0xFF, 0xEF,
0xFF, 0xF3, 0xFF, 0x0F, 0xF0, 0xFF, 0x3F, 0xFF, 0xFF, 0xFE, 0xFF, 0xC0, 0x7F, 0xC1, 0xFF, 0x87, 0xFF, 0x1E, 0xFE,
0x00, 0x78, 0x01, 0xE1, 0xFF, 0xC7, 0xFF, 0x1F, 0xFC, 0x01, 0xF0, 0x07, 0x9E, 0xFE, 0x7F, 0xF1, 0xFF, 0x87, 0xFC,
0x00, 0xF0, 0x3F, 0x87, 0x83, 0xFF, 0x3C, 0x3F, 0xFD, 0xE3, 0xF7, 0xEF, 0x1E, 0x0F, 0xF9, 0xF0, 0x7F, 0xFF, 0x01,
0xFF, 0xF8, 0x0F, 0xFF, 0xC0, 0x7F, 0x9F, 0x07, 0xFC, 0xF8, 0x3F, 0xE3, 0xF7, 0xEF, 0x1F, 0xFF, 0x78, 0x7F, 0xF3,
0xC0, 0xFE, 0x00, 0x0F, 0xF8, 0xFF, 0xCF, 0xFE, 0xFC, 0xF7, 0xC7, 0xBE, 0x3D, 0xF9, 0xE7, 0xFF, 0x3F, 0xF8, 0xFF,
0xC7, 0xDE, 0x7C, 0xF3, 0xC7, 0xBE, 0x3D, 0xE1, 0xE0, 0x7F, 0x8F, 0xF8, 0xFF, 0x19, 0xF3, 0xFE, 0xFF, 0xFE, 0x7F,
0xCF, 0xFF, 0xEF, 0xFC, 0xFF, 0x80, 0x03, 0xE0, 0xFE, 0x1F, 0xE3, 0xFE, 0x7C, 0x07, 0xFC, 0x7F, 0xE7, 0xFF, 0x7D,
0xF7, 0x8F, 0x78, 0xF7, 0x8F, 0x7D, 0xF7, 0xFE, 0x3F, 0xE1, 0xFC, 0xFF, 0x9F, 0xFB, 0xFF, 0xF9, 0xEF, 0xFD, 0xFF,
0xBC, 0xFF, 0x9F, 0xFF, 0xFF, 0xFB, 0xFE, 0x00, 0xFF, 0xFF, 0xFF, 0xFE, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78,
0x3C, 0x00, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xBC, 0x1E, 0xF0, 0xF3, 0xC3, 0xCF, 0x0F, 0x3C, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFC, 0x07, 0xF0, 0x1F, 0xC0, 0x70, 0x1F, 0xC3, 0xFE, 0x7F, 0xE7, 0xDF, 0x7F, 0xF7, 0xFF, 0x78, 0x07,
0xEE, 0x7F, 0xE3, 0xFE, 0x1F, 0xE0, 0xF9, 0xE7, 0xDF, 0x7B, 0xE3, 0xFF, 0xF0, 0xFF, 0xF8, 0x1F, 0xFE, 0x03, 0xFF,
0x01, 0xFF, 0xE0, 0xFF, 0xFC, 0x7D, 0xEF, 0x1E, 0x7B, 0xEF, 0x9E, 0x7C, 0x7F, 0x1F, 0xE7, 0xFD, 0xDF, 0x3F, 0x8F,
0xE0, 0x7D, 0xDF, 0x7F, 0xFF, 0xFF, 0xF8, 0xF1, 0xFE, 0x7F, 0xDF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xF9,
0xFF, 0x3F, 0xC7, 0x80, 0x39, 0x87, 0x78, 0xFE, 0x0F, 0x80, 0x00, 0x00, 0x3C, 0x7F, 0x9F, 0xF7, 0xFE, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFB, 0xFE, 0x7F, 0xCF, 0xF1, 0xE0, 0xF3, 0xEF, 0x7C, 0xFF, 0x8F, 0xF0, 0xFE, 0x0F, 0xE0, 0xFF,
0x0F, 0xF8, 0xF7, 0xCF, 0x3E, 0xF1, 0xE0, 0x1F, 0xF1, 0xFF, 0x1F, 0xF1, 0xEF, 0x1E, 0xF1, 0xEF, 0x3E, 0xFF, 0xCF,
0xFC, 0xFF, 0x8F, 0xF0, 0xF0, 0x78, 0x79, 0xE1, 0xEF, 0xCF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF7, 0xBF, 0xDE, 0xFF, 0x03, 0xC0, 0xF3, 0xFC, 0xFF, 0x3F, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xF3, 0xFC, 0xFF,
0x3C, 0x1F, 0xC3, 0xFE, 0x7F, 0xF7, 0xDF, 0x78, 0xF7, 0x8F, 0x78, 0xF7, 0xDF, 0x7F, 0xF3, 0xFE, 0x1F, 0xC0, 0xFF,
0xFF, 0xFF, 0xFF, 0xCF, 0xF3, 0xFC, 0xFF, 0x3F, 0xCF, 0xF3, 0xFC, 0xFF, 0x3C, 0xFF, 0x9F, 0xFB, 0xFF, 0x7B, 0xFF,
0x1F, 0xE3, 0xFC, 0x7F, 0xDF, 0xFF, 0xFF, 0xFB, 0xFE, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x00, 0x1F, 0xCF, 0xF7, 0xFD,
0xF6, 0x78, 0x1E, 0x07, 0x81, 0xF3, 0x7F, 0xCF, 0xF1, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x80, 0xF0, 0x1E, 0x03,
0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x00, 0xF1, 0xFF, 0x1E, 0x79, 0xE7, 0x9E, 0x7B, 0xC3, 0xFC, 0x3F, 0xC3, 0xF8,
0x1F, 0x81, 0xF0, 0x0F, 0x0D, 0xF0, 0xFE, 0x0F, 0xC0, 0xF8, 0x00, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0,
0x03, 0xC0, 0x1F, 0xF8, 0x3F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFF, 0x7B, 0xCF, 0x7B, 0xCF, 0x7B, 0xCF, 0x7F, 0xFF, 0x7F,
0xFE, 0x3F, 0xFE, 0x1F, 0xF8, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0xF9, 0xE7, 0xBE, 0x7F, 0xC3, 0xF8,
0x1F, 0x81, 0xF0, 0x1F, 0x83, 0xFC, 0x7F, 0xC7, 0x9E, 0xF1, 0xF0, 0xF3, 0xCF, 0x3C, 0xF3, 0xCF, 0x3C, 0xF3, 0xCF,
0x3C, 0xF3, 0xCF, 0x3C, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0x00, 0x70, 0x07, 0xF9, 0xFF, 0x3F, 0xE7, 0xBC, 0xF7,
0x9E, 0xFF, 0xDF, 0xF9, 0xFF, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF3, 0xCF, 0xF3, 0xCF, 0xF3, 0xCF, 0xF3, 0xCF, 0xF3,
0xCF, 0xF3, 0xCF, 0xF3, 0xCF, 0xF3, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0xCF, 0x3C, 0xF3, 0xCF, 0x3C,
0xF3, 0xCF, 0x3C, 0xF3, 0xCF, 0x3C, 0xF3, 0xCF, 0x3C, 0xF3, 0xCF, 0x3C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0xFE, 0x07, 0xF0, 0x3F, 0x80, 0x3C, 0x01, 0xFF, 0x0F, 0xFC, 0x7F, 0xE3,
0xDF, 0x1F, 0xF8, 0xFF, 0xC7, 0xFC, 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7F, 0x80, 0xFF, 0xF9, 0xFF, 0xFB, 0xFF, 0xF7,
0xF9, 0xFF, 0xFF, 0xDF, 0xFF, 0xBF, 0xFE, 0x78, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0xF9, 0xFF, 0xBF, 0xF7, 0x9F,
0xFF, 0xDF, 0xFB, 0xFE, 0x00, 0x7F, 0x0F, 0xF1, 0xFF, 0x3B, 0xE3, 0xFE, 0x7F, 0xC0, 0xFB, 0xBE, 0x7F, 0xDF, 0xF3,
0xFC, 0x00, 0xF0, 0xFC, 0x78, 0xFF, 0x3C, 0xFF, 0xDE, 0x7F, 0xEF, 0xFC, 0x7F, 0xFC, 0x3F, 0xFF, 0x1F, 0xE7, 0xFE,
0xF3, 0xFF, 0x78, 0xFF, 0x3C, 0x3F, 0x00, 0x1F, 0xEF, 0xFD, 0xFF, 0xBE, 0xF7, 0xDE, 0xFF, 0xDF, 0xF9, 0xFF, 0x3D,
0xEF, 0x3F, 0xE7, 0x80, 0x0C, 0x01, 0xE0, 0x1F, 0x00, 0x78, 0x03, 0x80, 0x00, 0x1F, 0xC3, 0xFE, 0x7F, 0xE7, 0xDF,
0x7F, 0xF7, 0xFF, 0x78, 0x07, 0xEE, 0x7F, 0xE3, 0xFE, 0x1F, 0xE0, 0x3D, 0xC3, 0xDE, 0x3D, 0xC0, 0x00, 0x00, 0x01,
0xFC, 0x3F, 0xE7, 0xFE, 0x7D, 0xF7, 0xFF, 0x7F, 0xF7, 0x80, 0x7E, 0xE7, 0xFE, 0x3F, 0xE1, 0xFE, 0x78, 0x07, 0x80,
0xFF, 0x0F, 0xF0, 0x78, 0x07, 0xFC, 0x7F, 0xE7, 0xFE, 0x7D, 0xE7, 0x8F, 0x78, 0xF7, 0x8F, 0x78, 0xF7, 0x8F, 0x78,
0xF7, 0x8F, 0x01, 0xF0, 0x7E, 0x07, 0xE0, 0x7C, 0x0C, 0x0F, 0x07, 0x87, 0x83, 0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xF8,
0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x00, 0x1F, 0xC7, 0xF9, 0xFF, 0x3E, 0xEF, 0xF9, 0xFF, 0x3E, 0x03,
0xEE, 0x7F, 0xC7, 0xFC, 0x7F, 0x80, 0x3F, 0x9F, 0xE7, 0xF9, 0xEE, 0x7F, 0x9F, 0xE3, 0xFD, 0xDF, 0x7F, 0xDF, 0xE7,
0xF0, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0xBF, 0xDC, 0xE0, 0x00, 0x00, 0xF0, 0x78, 0x3C, 0x1E,
0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x3C, 0x78, 0xF0, 0x03, 0xC7, 0x8F, 0x1E, 0x3C, 0x78, 0xF1,
0xE3, 0xC7, 0x8F, 0x3F, 0xFF, 0xF7, 0xE0, 0x1F, 0xF0, 0x03, 0xFE, 0x00, 0x7F, 0xC0, 0x0F, 0x78, 0x01, 0xEF, 0xF8,
0x3D, 0xFF, 0x8F, 0xBF, 0xFF, 0xE7, 0x9F, 0xFC, 0xFF, 0xDF, 0x1F, 0xFB, 0xC3, 0xFE, 0x00, 0xF3, 0xC0, 0x79, 0xE0,
0x3C, 0xF0, 0x1E, 0x78, 0x0F, 0xFF, 0xE7, 0xFF, 0xFB, 0xFF, 0xFF, 0xE7, 0x9F, 0xF3, 0xFF, 0xF9, 0xFF, 0xBC, 0x7F,
0x80, 0x78, 0x07, 0x80, 0xFF, 0x0F, 0xF0, 0x78, 0x07, 0xFC, 0x7F, 0xE7, 0xFE, 0x7D, 0xE7, 0x8F, 0x78, 0xF7, 0x8F,
0x78, 0xF7, 0x8F, 0x78, 0xF7, 0x8F, 0x03, 0x00, 0x78, 0x0F, 0x81, 0xE0, 0x1C, 0x00, 0x00, 0xF3, 0xEF, 0x7C, 0xFF,
0x8F, 0xF0, 0xFE, 0x0F, 0xE0, 0xFF, 0x0F, 0xF8, 0xF7, 0xCF, 0x3E, 0xF1, 0xE0, 0x18, 0x07, 0x80, 0xF0, 0x0F, 0x00,
0xE0, 0x00, 0x3C, 0x7F, 0x9F, 0xF7, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFE, 0x7F, 0xCF, 0xF1, 0xE0, 0x39,
0x83, 0xFC, 0x3F, 0x81, 0xF0, 0x00, 0x00, 0x00, 0xF1, 0xFF, 0x1E, 0x79, 0xE7, 0x9E, 0x7B, 0xC3, 0xFC, 0x3F, 0xC3,
0xF8, 0x1F, 0x81, 0xF0, 0x0F, 0x0D, 0xF0, 0xFE, 0x0F, 0xC0, 0xF8, 0x00, 0xF3, 0xFC, 0xFF, 0x3F, 0xCF, 0xF3, 0xFC,
0xFF, 0x3F, 0xCF, 0xFF, 0xFF, 0xFF, 0xFC, 0x78, 0x1E, 0x07, 0x80, 0x1E, 0x00, 0x3C, 0x03, 0xFF, 0x87, 0xFF, 0x0F,
0xFE, 0x03, 0xC0, 0x07, 0xFE, 0x0F, 0xFE, 0x1F, 0xFE, 0x3C, 0xFC, 0x78, 0x78, 0xF0, 0xF1, 0xE7, 0xE3, 0xFF, 0xC7,
0xFF, 0x0F, 0xF8, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x7F, 0xE3, 0xFF, 0x1F, 0xF8, 0x3C, 0x01, 0xE0,
0x0F, 0xF8, 0x7F, 0xE3, 0xCF, 0x9F, 0xFC, 0xFF, 0xC7, 0xFE, 0x1F, 0xE0, 0x7F, 0xF1, 0xFF, 0xF3, 0xF7, 0xEF, 0x83,
0xDF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xE0, 0x7F, 0xE0, 0xFF, 0xF7, 0xE7, 0xFF, 0xC7, 0xFF, 0x07, 0xF8,
0x00, 0x1F, 0xC3, 0xFE, 0x7F, 0xF7, 0xDF, 0x7F, 0xF7, 0xFF, 0x7F, 0xF7, 0xDF, 0x7F, 0xF3, 0xFE, 0x1F, 0xC0, 0xF0,
0x1F, 0xBE, 0x07, 0xE7, 0x83, 0xF9, 0xE0, 0xF4, 0x7C, 0x7C, 0x0F, 0x1E, 0x03, 0xC7, 0x80, 0xFB, 0xC0, 0x1E, 0xF0,
0x07, 0xFC, 0x00, 0xFE, 0x00, 0x3F, 0x80, 0x0F, 0xE0, 0x01, 0xF0, 0x00, 0x7C, 0x00, 0xF0, 0xFF, 0x8F, 0xDE, 0x7E,
0xF3, 0x87, 0xBC, 0x1F, 0xE0, 0xFE, 0x07, 0xF0, 0x1F, 0x00, 0xF8, 0x03, 0xC0, 0x1F, 0xE0, 0x1F, 0xE0, 0x0F, 0xC0,
0x00, 0x00, 0xF0, 0x7C, 0xF0, 0x7C, 0xF0, 0xFC, 0xF1, 0xFC, 0xF3, 0xFC, 0xF3, 0xFC, 0xF7, 0xBC, 0xFF, 0xBC, 0xFF,
0x3C, 0xFE, 0x3C, 0xFE, 0x3C, 0xFC, 0x3C, 0xF8, 0x3F, 0xF8, 0x3F, 0xF0, 0x3F, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x3C,
0x00, 0x1C, 0x7F, 0x83, 0xFC, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x79, 0xF3, 0xCF, 0x9E, 0xFC, 0xFF, 0xE7, 0xFF, 0x3F,
0xF9, 0xFB, 0xCF, 0xDE, 0x7C, 0xFB, 0xC7, 0xDE, 0x3E, 0x00, 0xF0, 0x0F, 0x00, 0x30, 0x78, 0x03, 0xC0, 0x3F, 0xC1,
0xFE, 0x07, 0x80, 0x3F, 0xF1, 0xFF, 0xCF, 0xFF, 0x79, 0xFB, 0xC3, 0xDE, 0x1E, 0xF3, 0xF7, 0xFF, 0xBF, 0xF8, 0xFF,
0x80, 0x78, 0x0F, 0xF0, 0xFF, 0x07, 0x80, 0x7F, 0xC7, 0xFE, 0x79, 0xE7, 0x9F, 0x7F, 0xE7, 0xFE, 0x7F, 0xC0, 0xFF,
0xCF, 0xFE, 0xFF, 0xFF, 0x3F, 0xF2, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xEF, 0xFC, 0xF1, 0xEF, 0x1E, 0xF0, 0x8F,
0x00, 0xF0, 0x00, 0xFF, 0x9F, 0xFB, 0xFF, 0xF9, 0xFF, 0x1F, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0x79,
0xEF, 0x1D, 0xE1, 0x3C, 0x00, 0x01, 0xE0, 0x3C, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x07, 0x80, 0xF0, 0x1E, 0x03,
0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x00, 0x07, 0x83, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1,
0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x80, 0x3F, 0xF3, 0xFF, 0x3F, 0xF3, 0xC0, 0x3C, 0x03, 0xC0, 0xFF, 0x8F,
0xF8, 0xFF, 0x83, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x00, 0x7F, 0xDF, 0xF7, 0xFD, 0xE0, 0x78, 0x3F,
0xCF, 0xF1, 0xE0, 0x78, 0x1E, 0x07, 0x80, 0xFF, 0xE7, 0xFF, 0x3F, 0xF9, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xFF, 0x1F,
0xFC, 0xFF, 0xF7, 0x9F, 0xBC, 0x3D, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC3, 0xC0, 0x7E, 0x07, 0xF0, 0x7F, 0x03, 0xF0,
0xFF, 0x9F, 0xF3, 0xFE, 0x78, 0x0F, 0x01, 0xFF, 0x3F, 0xF7, 0xFE, 0xF7, 0xDE, 0x3F, 0xC7, 0x81, 0xF0, 0xFC, 0x1F,
0x83, 0xE0, 0xF8, 0xF0, 0xF9, 0xF3, 0xC7, 0xC7, 0xEF, 0x3E, 0x0F, 0xBD, 0xF0, 0x1F, 0xF7, 0xC0, 0x3F, 0xFE, 0x00,
0x7F, 0xF0, 0x01, 0xFF, 0x80, 0x0F, 0xFF, 0x00, 0x7F, 0xFE, 0x01, 0xFF, 0xFC, 0x0F, 0xBD, 0xF8, 0x7C, 0xF3, 0xF9,
0xE3, 0xC7, 0xEF, 0x8F, 0x0F, 0x80, 0x00, 0x1E, 0x00, 0x00, 0x78, 0x00, 0x01, 0xE0, 0x00, 0x07, 0x80, 0xF9, 0xE7,
0xDF, 0x7B, 0xE3, 0xFF, 0xF0, 0xFF, 0xF8, 0x1F, 0xFE, 0x03, 0xFF, 0x01, 0xFF, 0xE0, 0xFF, 0xFC, 0x7D, 0xFF, 0xDE,
0x7B, 0xFF, 0x9E, 0x7C, 0x00, 0x07, 0x00, 0x01, 0xC0, 0x00, 0x70, 0x7F, 0xC7, 0xFE, 0x7F, 0xE7, 0xBF, 0x01, 0xF0,
0x3E, 0x1F, 0xE1, 0xFE, 0x1F, 0xF0, 0x3F, 0x00, 0xF7, 0xBF, 0x7F, 0xFF, 0xFE, 0x7F, 0xC0, 0xF0, 0x0F, 0x00, 0xF8,
0x1F, 0x01, 0xF0, 0x7F, 0x1F, 0xE7, 0xFD, 0xDF, 0x3F, 0x8F, 0xE0, 0x7D, 0xDF, 0x7F, 0xFF, 0xFF, 0xF8, 0x78, 0x1E,
0x07, 0xC3, 0xE0, 0xF8, 0xF0, 0xF9, 0xE3, 0xE3, 0xCF, 0x87, 0xBE, 0x0F, 0xF8, 0x1F, 0xE0, 0x3F, 0x80, 0x7F, 0x80,
0xFF, 0x81, 0xFF, 0x83, 0xDF, 0x87, 0x9F, 0x0F, 0x1F, 0xFE, 0x1F, 0xFC, 0x3F, 0x80, 0x1F, 0x00, 0x3E, 0x00, 0x7C,
0x00, 0xF8, 0xF3, 0xEF, 0x7C, 0xF7, 0x8F, 0xF8, 0xFF, 0x0F, 0xE0, 0xFF, 0x0F, 0xF8, 0xF7, 0xFF, 0x3F, 0xF1, 0xF0,
0x0F, 0x00, 0xF0, 0x0F, 0xF0, 0x3E, 0xF0, 0x3E, 0xF6, 0x7C, 0xF6, 0xF8, 0xF7, 0xF0, 0xFF, 0xE0, 0xFF, 0xE0, 0xFF,
0xF0, 0xF7, 0xF0, 0xF6, 0xF8, 0xF6, 0xF8, 0xF0, 0x7C, 0xF0, 0x3E, 0xF0, 0x3E, 0xF0, 0x1F, 0xF0, 0xFB, 0xFF, 0xCF,
0xFE, 0x3F, 0xF0, 0xFF, 0x83, 0xFF, 0x0F, 0xFE, 0x3F, 0xF8, 0xF1, 0xF3, 0xC3, 0xEF, 0x07, 0x80, 0x7C, 0x00, 0xF8,
0x7F, 0xF9, 0xF7, 0xF7, 0xC7, 0xDF, 0x0F, 0xFE, 0x1F, 0xF8, 0x3F, 0xE0, 0x7F, 0x80, 0xFF, 0x81, 0xFF, 0x83, 0xFF,
0x87, 0xDF, 0x0F, 0x9F, 0x1F, 0x1F, 0x3E, 0x1F, 0x78, 0x07, 0xF7, 0xFF, 0xFD, 0xFF, 0xC7, 0xFC, 0x3F, 0xC1, 0xFC,
0x0F, 0xF0, 0x7F, 0xC3, 0xDF, 0x1E, 0x7C, 0xF1, 0xE0, 0xFF, 0x1F, 0x7F, 0x9F, 0x3F, 0xDF, 0x81, 0xFF, 0x80, 0xFF,
0x80, 0x7F, 0x80, 0x3F, 0x80, 0x1F, 0xE0, 0x0F, 0xF8, 0x07, 0xFC, 0x03, 0xDF, 0x01, 0xE7, 0xC0, 0xF1, 0xF0, 0x78,
0xF8, 0x3C, 0x3E, 0xFE, 0x7F, 0xFB, 0xEF, 0xFF, 0x07, 0xF8, 0x1F, 0xC0, 0x7F, 0x01, 0xFE, 0x07, 0xFC, 0x1E, 0xF8,
0x79, 0xE1, 0xE7, 0xC0, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xFF, 0xF8, 0xFF,
0xF8, 0xFF, 0xF8, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x7F, 0xF0, 0x7F, 0xF0, 0x7F, 0x00, 0x0F, 0x00, 0x0F,
0x00, 0x0F, 0x00, 0x0F, 0xF3, 0xCF, 0x3C, 0xF3, 0xCF, 0x3C, 0xFF, 0xCF, 0xFC, 0xFF, 0xCF, 0x3C, 0xF3, 0xFF, 0x3F,
0xF3, 0xF0, 0x07, 0x00, 0x70, 0x07, 0xF0, 0x7F, 0xF8, 0x3F, 0xFC, 0x1F, 0xFE, 0x0F, 0x0F, 0x07, 0x87, 0x83, 0xC3,
0xFF, 0xE1, 0xFF, 0xF0, 0xFF, 0xF8, 0x78, 0x3C, 0x3C, 0x1E, 0x1E, 0x0F, 0x0F, 0x07, 0x87, 0x83, 0xC3, 0xC1, 0xE0,
0xF3, 0xFF, 0x9F, 0xFC, 0xFF, 0xE7, 0x8F, 0xFC, 0x7F, 0xE3, 0xFF, 0x1E, 0x78, 0xF3, 0xC7, 0x9E, 0x3C, 0xF0, 0xFF,
0xF8, 0x03, 0xFF, 0xE0, 0x0F, 0xFF, 0x80, 0x3C, 0x1E, 0x00, 0xF0, 0x78, 0x03, 0xC1, 0xE0, 0x0F, 0x07, 0xFE, 0x3C,
0x1F, 0xFC, 0xF0, 0x7F, 0xFB, 0xC1, 0xE7, 0xEF, 0x07, 0x87, 0xFC, 0x1E, 0x0F, 0xF0, 0x78, 0x3F, 0xC1, 0xE0, 0xFF,
0x07, 0x87, 0xC0, 0x00, 0x3E, 0x00, 0x03, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0x3E, 0x00, 0xFF, 0xC0, 0x7F, 0xE0, 0x3F,
0xF0, 0x1E, 0x78, 0x0F, 0x3F, 0xE7, 0x9F, 0xFB, 0xCF, 0xFD, 0xE7, 0x9F, 0xF3, 0xC7, 0xF9, 0xE3, 0xFC, 0xF1, 0xE0,
0x01, 0xF0, 0x03, 0xF8, 0x01, 0xF8, 0x00, 0xF8, 0x0F, 0xE0, 0x3F, 0xE0, 0x7F, 0xE0, 0x7E, 0x60, 0xF8, 0x00, 0xF1,
0xFC, 0xF3, 0xFE, 0xF3, 0xFE, 0xF7, 0xDE, 0xF7, 0x9E, 0xFF, 0x9E, 0xFF, 0xFE, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF0,
0x01, 0xFC, 0x01, 0xFE, 0x00, 0x7E, 0x00, 0x3E, 0x1F, 0xC1, 0xFE, 0x1F, 0xE0, 0xFF, 0xE7, 0x3F, 0xBB, 0xFD, 0xDC,
0xEF, 0xEF, 0x7F, 0xF9, 0xFF, 0x87, 0xF8, 0x07, 0xE0, 0x1F, 0x80, 0x7C, 0x1F, 0xF1, 0xFF, 0x9F, 0xFC, 0xFD, 0xEF,
0x80, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3E, 0x01, 0xFC, 0xE7, 0xFF, 0x1F, 0xF8, 0x7F, 0xC0, 0xF0,
0x07, 0x80, 0x5C, 0x03, 0xE0, 0x1F, 0x00, 0x1F, 0xCF, 0xF7, 0xFD, 0xF6, 0x78, 0x1E, 0x07, 0x81, 0xF3, 0x7F, 0xCF,
0xF0, 0xFC, 0x3C, 0x0F, 0x07, 0xC1, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x1F, 0x00, 0xF8, 0x07, 0xC0, 0x3E, 0x01,
0xF0, 0x0F, 0x80, 0x7C, 0x03, 0xE0, 0x1F, 0x00, 0xFE, 0x07, 0xF0, 0x3F, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78,
0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1F, 0x83, 0xF0, 0x7E, 0x01, 0xC0, 0x38, 0x07,
0x00, 0xF8, 0x7F, 0xE1, 0xE7, 0xCF, 0x9F, 0x3C, 0x3F, 0xF0, 0x7F, 0x81, 0xFE, 0x03, 0xF0, 0x0F, 0xC0, 0x1E, 0x00,
0x78, 0x01, 0xE0, 0x07, 0x80, 0x1E, 0x00, 0x78, 0x00, 0xF1, 0xFF, 0x1E, 0x79, 0xE7, 0xBE, 0x7B, 0xC3, 0xFC, 0x3F,
0x81, 0xF8, 0x1F, 0x81, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF8, 0x7F, 0xE1, 0xF7, 0xCF, 0x9F,
0x3C, 0x3F, 0xF0, 0xFF, 0x81, 0xFE, 0x03, 0xF0, 0x0F, 0xC0, 0xFF, 0xC3, 0xFF, 0x01, 0xE0, 0x07, 0x80, 0x1E, 0x00,
0x78, 0x00, 0xF1, 0xFF, 0x1E, 0x79, 0xE7, 0xBE, 0x7B, 0xC3, 0xFC, 0x3F, 0x81, 0xF8, 0x1F, 0x87, 0xFC, 0x7F, 0xC0,
0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF8, 0x7C, 0xF9, 0xF1, 0xFB, 0xE1, 0xFF, 0x81, 0xFE, 0x03, 0xFC, 0x03, 0xF0,
0x03, 0xE0, 0x0F, 0xE0, 0x3F, 0xC0, 0xFF, 0xC1, 0xFF, 0xC7, 0xCF, 0xEF, 0x0F, 0xFE, 0x1F, 0x80, 0x0F, 0x00, 0x1E,
0x00, 0x3C, 0x00, 0x78, 0xF9, 0xE7, 0xBE, 0x7F, 0xC3, 0xF8, 0x1F, 0x81, 0xF0, 0x1F, 0x83, 0xFC, 0x7F, 0xF7, 0x9F,
0xF1, 0xF0, 0x07, 0x00, 0x70, 0x07, 0xFF, 0xF7, 0x8F, 0xFF, 0x78, 0xFF, 0xF7, 0x80, 0xF0, 0x78, 0x0F, 0x07, 0x80,
0xF0, 0x78, 0x0F, 0x07, 0x80, 0xF0, 0x78, 0x0F, 0x07, 0x80, 0xF0, 0x78, 0x0F, 0x07, 0x80, 0xF0, 0x78, 0x0F, 0xFF,
0xF0, 0xFF, 0xFF, 0x0F, 0xFF, 0xF0, 0x00, 0x1F, 0x00, 0x01, 0xF0, 0x00, 0x1F, 0x00, 0x01, 0xF0, 0xFF, 0x79, 0xFE,
0xF3, 0xFD, 0xE1, 0xE3, 0xC3, 0xC7, 0x87, 0x8F, 0x0F, 0x1E, 0x1E, 0x3C, 0x3F, 0xFE, 0x7F, 0xFC, 0xFF, 0xF8, 0x00,
0xF0, 0x01, 0xE0, 0x03, 0xC0, 0xF0, 0xF3, 0xC3, 0xCF, 0x0F, 0x3C, 0x3C, 0xF0, 0xF3, 0xC3, 0xCF, 0xCF, 0x3F, 0xFC,
0x7F, 0xF0, 0xFF, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x03,
0xC0, 0xF1, 0xE7, 0x8F, 0x3C, 0x79, 0xE3, 0xCF, 0x9E, 0x7F, 0xF1, 0xFF, 0x87, 0xFC, 0x01, 0xF8, 0x0F, 0xC0, 0x7E,
0x00, 0xF0, 0x07, 0x80, 0x3C, 0xF0, 0xFF, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0xFF, 0x6F, 0xFE, 0xFF, 0xFF, 0x7F, 0xF3,
0xFF, 0x06, 0xF0, 0x6F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0xF1, 0xFE, 0x3F, 0xC7, 0xFB, 0xFF, 0xFF, 0xFF, 0xDF, 0xF9,
0xFF, 0x07, 0xE0, 0xFC, 0x07, 0x80, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x7F, 0xF3, 0xFF, 0xDF, 0xFE,
0xF9, 0xFF, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xE0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3F,
0xEF, 0xFF, 0xFF, 0xF7, 0xFC, 0xFF, 0x3F, 0xCF, 0xF3, 0xFC, 0xFF, 0x3F, 0xCF, 0x01, 0xFE, 0x00, 0xFF, 0xCE, 0x7F,
0xFB, 0xBF, 0x3E, 0xFF, 0x07, 0xFF, 0xFF, 0xF7, 0xFF, 0xFC, 0xFF, 0xFF, 0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF8, 0x00,
0x1F, 0x9C, 0x07, 0xFF, 0x80, 0xFF, 0xE0, 0x0F, 0xF0, 0xC7, 0xF3, 0xBF, 0xEE, 0xFF, 0xFF, 0xDF, 0xFF, 0xFD, 0xFF,
0xF1, 0xE0, 0x07, 0xEE, 0x0F, 0xF8, 0x1F, 0xF0, 0x3F, 0xC0, 0x01, 0xFE, 0x00, 0xFF, 0xC0, 0x7F, 0xFB, 0x9F, 0xFE,
0xEF, 0x87, 0xBF, 0xC1, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0x3F, 0xFF, 0xC3, 0xC0, 0x00, 0xF8, 0x00, 0x3F, 0x9C, 0x07,
0xFF, 0x80, 0xFF, 0xE0, 0x1F, 0xF0, 0x01, 0xE0, 0x00, 0x78, 0x00, 0x1E, 0x00, 0x07, 0x80, 0x03, 0xF3, 0x1F, 0xEE,
0xFF, 0xFB, 0xFF, 0xFE, 0x3F, 0xFF, 0xF7, 0xFF, 0xC7, 0xEE, 0x0F, 0xF8, 0x3F, 0xF0, 0x7F, 0xC0, 0x78, 0x01, 0xE0,
0x07, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x01, 0x9C, 0x00, 0x1E, 0xE0, 0x00, 0x7F, 0x00, 0x01,
0xF0, 0x00, 0x00, 0x00, 0x7C, 0x78, 0x7D, 0xF3, 0xC7, 0xCF, 0xDE, 0x7C, 0x3E, 0xF7, 0xC0, 0xFF, 0xBE, 0x03, 0xFF,
0xE0, 0x0F, 0xFE, 0x00, 0x7F, 0xE0, 0x07, 0xFF, 0x80, 0x7F, 0xFE, 0x03, 0xFE, 0xF8, 0x3E, 0xF3, 0xE3, 0xE7, 0x9F,
0x1E, 0x3C, 0x7D, 0xF1, 0xE1, 0xF0, 0x07, 0x30, 0x01, 0xFE, 0x00, 0x7F, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00,
0x0F, 0x9E, 0x7D, 0xF7, 0xBE, 0x3F, 0xFF, 0x0F, 0xFF, 0x81, 0xFF, 0xE0, 0x3F, 0xF0, 0x1F, 0xFE, 0x0F, 0xFF, 0xC7,
0xDE, 0xF1, 0xE7, 0xBE, 0xF9, 0xE7, 0xC0, 0xF0, 0xFF, 0x8F, 0xBC, 0xF9, 0xEF, 0x8F, 0x78, 0x7F, 0xC3, 0xFF, 0x1F,
0xFC, 0xFF, 0xF7, 0x9F, 0xBC, 0x3F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC3, 0xE0, 0x3E, 0x07, 0xF0, 0x3F, 0x01, 0xF0,
0xF3, 0xFE, 0xFB, 0xDE, 0x7F, 0x8F, 0xF1, 0xFF, 0x3F, 0xF7, 0xBE, 0xF1, 0xFE, 0x3F, 0xC7, 0x80, 0xF0, 0x3C, 0x1F,
0x83, 0xE0, 0x0F, 0xFE, 0x03, 0xFF, 0x80, 0xFF, 0xE0, 0x3C, 0x78, 0x0F, 0x1E, 0x03, 0xC7, 0x80, 0xF1, 0xE0, 0x3C,
0x78, 0x0F, 0x1E, 0x07, 0xC7, 0x81, 0xE1, 0xE3, 0xF8, 0x78, 0xFC, 0x1F, 0xBF, 0x07, 0xEF, 0x01, 0xF8, 0x00, 0x1E,
0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00, 0x60, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xBC, 0x1E, 0xF0, 0x7B, 0xC3, 0xEF,
0x3F, 0x3C, 0xFC, 0xFF, 0xE3, 0xFF, 0x0F, 0xC0, 0x0E, 0x00, 0x78, 0x01, 0xC0, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0,
0xFF, 0x07, 0xF8, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xE0,
0x0F, 0x01, 0xF8, 0x0F, 0xC0, 0xFC, 0xF1, 0xFE, 0x3F, 0xC7, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xF1, 0xFE,
0x3F, 0xC7, 0x81, 0xF0, 0xFC, 0x1F, 0x83, 0xE0, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xF0,
0x78, 0xFF, 0xF8, 0xFF, 0xF8, 0xFF, 0xF8, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x7E, 0xF0, 0x7E, 0xF0, 0x7E,
0x00, 0x1E, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x18, 0xF3, 0xCF, 0x3C, 0xF3, 0xCF, 0x3C, 0xFF, 0xCF, 0xFC, 0xFF, 0xCF,
0x3C, 0xF3, 0xFF, 0x3F, 0xF3, 0xF0, 0x0E, 0x01, 0xE0, 0x1C, 0xF8, 0x7F, 0xC3, 0xFE, 0x1F, 0xF0, 0xFF, 0x87, 0xFC,
0x3D, 0xF3, 0xEF, 0xFF, 0x7F, 0xF8, 0xFF, 0xC0, 0x1E, 0x00, 0xF0, 0x3F, 0x81, 0xFC, 0x0F, 0xE0, 0x78, 0x03, 0xC0,
0x1E, 0x00, 0xF0, 0xF9, 0xFF, 0x3F, 0xE7, 0xBC, 0xF7, 0xFE, 0xFF, 0xCF, 0xF8, 0x0F, 0x01, 0xE0, 0xFC, 0x1F, 0x83,
0x80, 0x70, 0x0E, 0x00, 0x78, 0x0F, 0x0F, 0x83, 0xE1, 0xF0, 0x7C, 0x3F, 0x1F, 0x8F, 0xE3, 0xF1, 0xFE, 0xFE, 0x3F,
0xDF, 0xE7, 0xBB, 0xBC, 0xF7, 0xF7, 0x9E, 0xFC, 0xF3, 0xCF, 0x9E, 0x79, 0xF3, 0xCF, 0x1C, 0x7F, 0xE0, 0x0F, 0xFC,
0x01, 0xF8, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00, 0x78, 0x00, 0x0E, 0x00, 0xF0, 0x78, 0xF8, 0x78, 0xF8, 0xF8, 0xFC,
0xF8, 0xFD, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xBC, 0xF7, 0xBF, 0xF7, 0xBF, 0xF0, 0x3E, 0x00, 0x1E, 0x00, 0x1E,
0x00, 0x1C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0C, 0xE0, 0x3D, 0xC0, 0x3F, 0x80, 0x3E, 0x00, 0x00,
0x00, 0xF8, 0x01, 0xF0, 0x07, 0xF0, 0x0F, 0xE0, 0x1F, 0xE0, 0x7B, 0xC0, 0xF7, 0x83, 0xE7, 0x87, 0x8F, 0x0F, 0xFE,
0x3F, 0xFE, 0x7F, 0xFC, 0xF0, 0x7F, 0xE0, 0xFF, 0x80, 0xF0, 0x39, 0x87, 0xF8, 0xFE, 0x0F, 0xC0, 0x00, 0x00, 0x1F,
0xE3, 0xFE, 0x3F, 0xC6, 0x7C, 0xFF, 0xBF, 0xFF, 0x9F, 0xF3, 0xFF, 0xFB, 0xFF, 0x3F, 0xE0, 0x1E, 0xF0, 0x3D, 0xE0,
0x7B, 0xC0, 0x00, 0x00, 0x7C, 0x00, 0xF8, 0x03, 0xF8, 0x07, 0xF0, 0x0F, 0xF0, 0x3D, 0xE0, 0x7B, 0xC1, 0xF3, 0xC3,
0xC7, 0x87, 0xFF, 0x1F, 0xFF, 0x3F, 0xFE, 0x78, 0x3F, 0xF0, 0x7F, 0xC0, 0x78, 0x7B, 0xCF, 0x79, 0xEF, 0x00, 0x00,
0x00, 0xFF, 0x1F, 0xF1, 0xFE, 0x33, 0xE7, 0xFD, 0xFF, 0xFC, 0xFF, 0x9F, 0xFF, 0xDF, 0xF9, 0xFF, 0x00, 0xFF, 0xF0,
0x07, 0xFF, 0x80, 0x7F, 0xFC, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x03, 0xDE, 0x00, 0x1E, 0xFF, 0x81, 0xE7, 0xFC, 0x1F,
0x3F, 0xE0, 0xFF, 0xE0, 0x0F, 0xFF, 0x00, 0x7F, 0xF8, 0x07, 0xC3, 0xFF, 0xBC, 0x1F, 0xFF, 0xE0, 0xFF, 0xE0, 0x7F,
0xFF, 0x1F, 0xFF, 0xE3, 0xFF, 0xF8, 0xCF, 0xDF, 0x3F, 0xFF, 0xDF, 0xFF, 0xFF, 0x9E, 0x03, 0xE7, 0xEE, 0xFF, 0xFF,
0x9F, 0xFF, 0xE3, 0xFF, 0xF8, 0x39, 0x87, 0x78, 0xFE, 0x0F, 0x80, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x1E, 0x03,
0xC0, 0x7F, 0xEF, 0xFD, 0xFF, 0xBC, 0x07, 0x80, 0xF0, 0x1F, 0xFF, 0xFF, 0xFF, 0xF0, 0x19, 0xC3, 0xDC, 0x1F, 0xC0,
0xF8, 0x00, 0x00, 0x00, 0x1F, 0xC3, 0xFE, 0x7F, 0xE7, 0xDF, 0x7F, 0xF7, 0xFF, 0x78, 0x07, 0xEE, 0x7F, 0xE3, 0xFE,
0x1F, 0xE0, 0x7F, 0xC1, 0xFF, 0x87, 0xFF, 0x1E, 0x7E, 0x00, 0x78, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1,
0xFF, 0x07, 0xBF, 0x7E, 0x7F, 0xF0, 0xFF, 0xC1, 0xFC, 0x00, 0x7F, 0x87, 0xFC, 0x7F, 0xE3, 0x3E, 0x01, 0xF7, 0xFF,
0x7F, 0xF7, 0x9E, 0x7F, 0xE7, 0xFC, 0x1F, 0x80, 0x3D, 0xC0, 0xF7, 0x83, 0xDC, 0x00, 0x00, 0x7F, 0xC1, 0xFF, 0x87,
0xFF, 0x1E, 0x7E, 0x00, 0x78, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, 0x07, 0xBF, 0x7E, 0x7F, 0xF0,
0xFF, 0xC1, 0xFC, 0x00, 0x39, 0xC3, 0xFC, 0x39, 0xC0, 0x00, 0x00, 0x07, 0xF8, 0x7F, 0xC7, 0xFE, 0x33, 0xE0, 0x1F,
0x7F, 0xF7, 0xFF, 0x79, 0xE7, 0xFE, 0x7F, 0xC1, 0xF8, 0x03, 0xDC, 0x00, 0x1E, 0xF0, 0x00, 0xF7, 0x00, 0x00, 0x00,
0x0F, 0x8F, 0x0F, 0xBE, 0x78, 0xF9, 0xFB, 0xCF, 0x87, 0xDE, 0xF8, 0x1F, 0xF7, 0xC0, 0x7F, 0xFC, 0x01, 0xFF, 0xC0,
0x0F, 0xFC, 0x00, 0xFF, 0xF0, 0x0F, 0xFF, 0xC0, 0x7F, 0xDF, 0x07, 0xDE, 0x7C, 0x7C, 0xF3, 0xE3, 0xC7, 0x8F, 0xBE,
0x3C, 0x3E, 0x07, 0x78, 0x01, 0xFE, 0x00, 0x77, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x79, 0xF7, 0xDE, 0xF8, 0xFF,
0xFC, 0x3F, 0xFE, 0x07, 0xFF, 0x80, 0xFF, 0xC0, 0x7F, 0xF8, 0x3F, 0xFF, 0x1F, 0x7B, 0xC7, 0x9E, 0xFB, 0xE7, 0x9F,
0x3B, 0xC3, 0xFC, 0x3B, 0xC0, 0x00, 0x00, 0x07, 0xFC, 0x7F, 0xE7, 0xFE, 0x7B, 0xF0, 0x1F, 0x03, 0xE1, 0xFE, 0x1F,
0xE1, 0xFF, 0x03, 0xF0, 0x0F, 0x7B, 0xF7, 0xFF, 0xFF, 0xE7, 0xFC, 0x77, 0xBD, 0xE7, 0x78, 0x00, 0x00, 0x1F, 0xC7,
0xF9, 0xFF, 0x77, 0xCF, 0xE3, 0xF8, 0x1F, 0x77, 0xDF, 0xFF, 0xFF, 0xFE, 0x7F, 0xF7, 0xFF, 0x7F, 0xF0, 0x3E, 0x07,
0xC0, 0xF8, 0x1F, 0xC1, 0xFE, 0x03, 0xF0, 0x0F, 0x00, 0xF7, 0xBF, 0xFF, 0xFF, 0xFE, 0x7F, 0xC0, 0xFF, 0xFF, 0xFF,
0xFC, 0x1E, 0x0F, 0x07, 0x83, 0xF0, 0xFE, 0x0F, 0xC0, 0xF0, 0x3F, 0x9F, 0xFF, 0xFF, 0xEF, 0xF0, 0x1F, 0xE0, 0x7F,
0x80, 0x00, 0x3C, 0x1F, 0xF0, 0x7F, 0xC3, 0xFF, 0x1F, 0xFC, 0xFF, 0xF3, 0xFF, 0xDE, 0xFF, 0xFB, 0xFF, 0xCF, 0xFE,
0x3F, 0xF8, 0xFF, 0xC3, 0xFE, 0x0F, 0xF8, 0x3F, 0xC0, 0xF0, 0x3F, 0x87, 0xF0, 0x00, 0x00, 0x0F, 0x1F, 0xE7, 0xFD,
0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x9F, 0xF3, 0xFC, 0x78, 0x1E, 0xE0, 0x7B, 0xC1, 0xEE, 0x00, 0x00,
0xF0, 0x7F, 0xC1, 0xFF, 0x0F, 0xFC, 0x7F, 0xF3, 0xFF, 0xCF, 0xFF, 0x7B, 0xFF, 0xEF, 0xFF, 0x3F, 0xF8, 0xFF, 0xE3,
0xFF, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x03, 0xC0, 0x3B, 0xCF, 0x78, 0xEF, 0x00, 0x00, 0x01, 0xE3, 0xFC, 0xFF, 0xBF,
0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xF3, 0xFE, 0x7F, 0x8F, 0x1E, 0xE0, 0x3D, 0xE0, 0x7B, 0x80, 0x00, 0x01,
0xFE, 0x07, 0xFF, 0x1F, 0xFF, 0x3F, 0x7E, 0xF8, 0x3D, 0xE0, 0x7F, 0xC0, 0x7F, 0x80, 0xFF, 0x01, 0xFE, 0x07, 0xFE,
0x0F, 0xFF, 0x7E, 0x7F, 0xFC, 0x7F, 0xF0, 0x7F, 0x80, 0x3D, 0xE3, 0xDE, 0x3D, 0xE0, 0x00, 0x00, 0x01, 0xFC, 0x3F,
0xE7, 0xFF, 0x7D, 0xF7, 0x8F, 0x78, 0xF7, 0x8F, 0x7D, 0xF7, 0xFF, 0x3F, 0xE1, 0xFC, 0x1F, 0xE0, 0x7F, 0xF1, 0xFF,
0xF3, 0xF7, 0xEF, 0x83, 0xDE, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x3F, 0xE0, 0x7F, 0xE0, 0xFF, 0xF7, 0xE7, 0xFF,
0xC7, 0xFF, 0x07, 0xF8, 0x00, 0x1F, 0xC3, 0xFE, 0x7F, 0xF7, 0xDF, 0x7F, 0xF7, 0xFF, 0x78, 0xF7, 0xDF, 0x7F, 0xF3,
0xFE, 0x1F, 0xC0, 0x1E, 0xE0, 0x3D, 0xE0, 0x7B, 0x80, 0x00, 0x01, 0xFE, 0x07, 0xFF, 0x1F, 0xFF, 0x3F, 0x7E, 0xF8,
0x3D, 0xE0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFE, 0x07, 0xFE, 0x0F, 0xFF, 0x7E, 0x7F, 0xFC, 0x7F, 0xF0, 0x7F,
0x80, 0x3D, 0xC3, 0xDE, 0x3D, 0xC0, 0x00, 0x00, 0x01, 0xFC, 0x3F, 0xE7, 0xFF, 0x7D, 0xF7, 0xFF, 0x7F, 0xF7, 0x8F,
0x7D, 0xF7, 0xFF, 0x3F, 0xE1, 0xFC, 0x3D, 0xE0, 0xF7, 0x83, 0xDE, 0x00, 0x00, 0x7F, 0xC1, 0xFF, 0x87, 0xFF, 0x1E,
0xFE, 0x00, 0x78, 0x01, 0xE1, 0xFF, 0xC7, 0xFF, 0x1F, 0xFC, 0x01, 0xF0, 0x07, 0x9E, 0xFE, 0x7F, 0xF1, 0xFF, 0x87,
0xFC, 0x00, 0x7B, 0x8F, 0x79, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x1F, 0xE3, 0xFE, 0x77, 0xC7, 0xFC, 0xFF, 0x81, 0xF7,
0x7C, 0xFF, 0xBF, 0xE7, 0xF8, 0x1F, 0xE0, 0x7F, 0x80, 0x00, 0x3E, 0x1F, 0x78, 0x79, 0xF1, 0xE3, 0xCF, 0x8F, 0xBC,
0x1E, 0xF0, 0x7F, 0xC0, 0xFE, 0x03, 0xF8, 0x07, 0xC0, 0x1F, 0x06, 0xF8, 0x1F, 0xE0, 0x7F, 0x01, 0xF8, 0x00, 0x3F,
0xC3, 0xFC, 0x00, 0x00, 0x00, 0xF1, 0xFF, 0x1E, 0x79, 0xE7, 0x9E, 0x7B, 0xC3, 0xFC, 0x3F, 0xC3, 0xF8, 0x1F, 0x81,
0xF0, 0x0F, 0x0D, 0xF0, 0xFE, 0x0F, 0xC0, 0xF8, 0x00, 0x1E, 0xE0, 0x7B, 0xC1, 0xEE, 0x00, 0x00, 0xF8, 0x7D, 0xE1,
0xE7, 0xC7, 0x8F, 0x3E, 0x3E, 0xF0, 0x7B, 0xC1, 0xFF, 0x03, 0xF8, 0x0F, 0xE0, 0x1F, 0x00, 0x7C, 0x1B, 0xE0, 0x7F,
0x81, 0xFC, 0x07, 0xE0, 0x00, 0x3B, 0xC7, 0xBC, 0x3B, 0xC0, 0x00, 0x00, 0x0F, 0x1F, 0xF1, 0xE7, 0x9E, 0x79, 0xE7,
0xBC, 0x3F, 0xC3, 0xFC, 0x3F, 0x81, 0xF8, 0x1F, 0x00, 0xF0, 0xDF, 0x0F, 0xE0, 0xFC, 0x0F, 0x80, 0x07, 0x70, 0x3D,
0xC0, 0xEF, 0x07, 0xF8, 0x1C, 0xC0, 0x00, 0x0F, 0x87, 0xDE, 0x1E, 0x7C, 0x78, 0xF3, 0xE3, 0xEF, 0x07, 0xBC, 0x1F,
0xF0, 0x3F, 0x80, 0xFE, 0x01, 0xF0, 0x07, 0xC1, 0xBE, 0x07, 0xF8, 0x1F, 0xC0, 0x7E, 0x00, 0x0C, 0xE1, 0xFE, 0x3D,
0xC3, 0xB8, 0x33, 0x80, 0x00, 0xF1, 0xFF, 0x1E, 0x79, 0xE7, 0x9E, 0x7B, 0xC3, 0xFC, 0x3F, 0xC3, 0xF8, 0x1F, 0x81,
0xF0, 0x0F, 0x0D, 0xF0, 0xFE, 0x0F, 0xC0, 0xF8, 0x00, 0x1D, 0xE1, 0xEF, 0x07, 0x78, 0x00, 0x0F, 0x87, 0xFC, 0x3F,
0xE1, 0xFF, 0x0F, 0xF8, 0x7F, 0xC3, 0xDF, 0x3E, 0xFF, 0xF7, 0xFF, 0x8F, 0xFC, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03,
0xC0, 0x1E, 0x3B, 0xCF, 0x78, 0xEF, 0x00, 0x00, 0x01, 0xF3, 0xFE, 0x7F, 0xCF, 0x79, 0xEF, 0x3D, 0xFF, 0xBF, 0xF3,
0xFE, 0x03, 0xC0, 0x78, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03,
0xC0, 0x78, 0x0F, 0xE1, 0xFC, 0x3F, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x00, 0xFF, 0xFF, 0xFF, 0xFE, 0x0F, 0x07,
0x83, 0xC1, 0xE0, 0xFC, 0x7E, 0x3F, 0x03, 0x81, 0xC0, 0xE0, 0x07, 0x78, 0x03, 0xFC, 0x01, 0xDE, 0x00, 0x00, 0x0F,
0x00, 0x7F, 0x80, 0x3F, 0xC0, 0x1F, 0xE0, 0x0F, 0xF0, 0x07, 0xFF, 0xE3, 0xFF, 0xF9, 0xFF, 0xFE, 0xFF, 0x3F, 0x7F,
0x87, 0xBF, 0xC3, 0xDF, 0xE7, 0xEF, 0xFF, 0xF7, 0xFF, 0xF3, 0xFF, 0xE1, 0xE0, 0x0E, 0xF0, 0x3D, 0xE0, 0x3B, 0xC0,
0x00, 0x00, 0x00, 0x1E, 0x03, 0xFC, 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0xFF, 0x3F, 0xFF, 0x7F, 0xFE, 0xFF, 0x3F, 0xFF,
0xFB, 0xFF, 0xF7, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x3B, 0xDE, 0xEF, 0x78, 0x7B, 0xDF, 0xEF, 0x70, 0x7B, 0xDF, 0xEF, 0x70,
0x3B, 0xDE, 0xE7, 0xF9, 0xDE, 0xF7, 0xBD, 0xE0, 0x7F, 0xBF, 0xDD, 0xFE, 0xFF, 0x77, 0x38, 0x7F, 0xBF, 0xDD, 0xFE,
0xFF, 0x77, 0x38, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0xFF, 0xFF, 0xFF, 0xFC, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1E,
0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0xFF, 0xFF, 0xFF, 0xFC, 0x78, 0x1E, 0x07,
0x8F, 0xFF, 0xFF, 0xFF, 0xC7, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0x7C, 0xFF, 0xFF, 0xF7, 0xEF, 0x80, 0xF0, 0xE1,
0xFF, 0x3E, 0x7F, 0xE7, 0xCF, 0xF8, 0x70, 0xF0, 0x3E, 0x1E, 0x00, 0x0F, 0xE3, 0xC0, 0x01, 0xDC, 0xF0, 0x00, 0x7B,
0xDE, 0x00, 0x0F, 0x7F, 0x80, 0x00, 0xEE, 0xF0, 0x00, 0x1F, 0xFC, 0x00, 0x01, 0xF7, 0xFE, 0x7E, 0x01, 0xFF, 0xCF,
0xE0, 0x3B, 0xFF, 0xFC, 0x0F, 0x73, 0xF3, 0x83, 0xCE, 0x7E, 0x70, 0x79, 0xFF, 0xFE, 0x1E, 0x3F, 0x9F, 0xC3, 0xC3,
0xF3, 0xF0, 0x00, 0x38, 0xF3, 0xE7, 0x9F, 0x1E, 0x3E, 0x3C, 0x38, 0x00, 0x00, 0xE3, 0xE3, 0xE3, 0xC7, 0xCF, 0x3E,
0xF8, 0xE0, 0x00, 0x01, 0xE0, 0x3C, 0x0F, 0x01, 0xE0, 0x78, 0x0F, 0x03, 0xC0, 0x78, 0x1E, 0x03, 0xC0, 0xF0, 0x1E,
0x07, 0x80, 0xF0, 0x3C, 0x00, 0x07, 0xF0, 0xFF, 0x1F, 0xF1, 0xF6, 0x3C, 0x07, 0xFE, 0x7F, 0xC3, 0xC0, 0x7F, 0xC7,
0xFC, 0x3C, 0x03, 0xF7, 0x1F, 0xF0, 0xFF, 0x07, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0x0F, 0xC0, 0xFC, 0x1F,
0xC3, 0xF0, 0x3F, 0xC3, 0xFC, 0x1F, 0xC3, 0xF0, 0x3F, 0x03, 0xF0, 0x0F, 0x00, 0x3F, 0x87, 0xFC, 0x3F, 0xE3, 0xBE,
0xFF, 0xFF, 0xFF, 0x1F, 0x83, 0xF0, 0xFF, 0xFF, 0xFF, 0x78, 0x07, 0xDE, 0x7F, 0xE3, 0xFE, 0x1F, 0xE0, 0xFF, 0xFF,
0xFF, 0xC1, 0xF0, 0x07, 0xCF, 0xFF, 0x7F, 0xF8, 0x0F, 0x01, 0xF8, 0xFF, 0x87, 0xF8, 0x1F, 0x00, 0x7C, 0x01, 0xF0,
0x07, 0xC0, 0x1F, 0x00, 0x3F, 0x83, 0xFC, 0x3F, 0xE3, 0xBF, 0x00, 0xF1, 0xFF, 0x3F, 0xF7, 0xFF, 0x7D, 0xFF, 0x0F,
0xF0, 0xFF, 0xBE, 0x7F, 0xE7, 0xFC, 0x3F, 0x80, 0x07, 0x80, 0x0F, 0x80, 0x3F, 0x00, 0x7F, 0x01, 0xFE, 0x03, 0xDC,
0x07, 0xBC, 0x1E, 0x78, 0x3C, 0x78, 0x78, 0xF1, 0xE1, 0xE3, 0xC1, 0xE7, 0xFF, 0xDF, 0xFF, 0xBF, 0xFF, 0x80, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF,
0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0x07, 0xC0, 0x7C, 0x07, 0x80, 0xF8,
0x0F, 0x83, 0xE0, 0x78, 0x1E, 0x07, 0xC0, 0xF0, 0x3F, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFC, 0x01, 0xE0,
0x3C, 0x0F, 0x01, 0xE0, 0x78, 0x0F, 0x03, 0xC0, 0x78, 0x1E, 0x03, 0xC0, 0xF0, 0x1E, 0x07, 0x80, 0xF0, 0x3C, 0x00,
0x77, 0xFE, 0xE0, 0x00, 0x3C, 0x01, 0xE0, 0x07, 0x80, 0x1E, 0x00, 0x70, 0x03, 0xC0, 0x0F, 0x0F, 0x38, 0xFD, 0xE3,
0xF7, 0x87, 0xFC, 0x07, 0xF0, 0x0F, 0xC0, 0x3E, 0x00, 0x78, 0x00, 0x7D, 0xF3, 0xFF, 0xFF, 0xFF, 0xEE, 0x7F, 0xFF,
0xBF, 0xFD, 0xF7, 0xC0, 0x00, 0x07, 0xC7, 0xE7, 0xF3, 0xE1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1,
0xE0, 0xF0, 0x78, 0x7C, 0x7E, 0x3F, 0x1F, 0x00, 0x00, 0x3C, 0x77, 0xFF, 0x7F, 0xEF, 0xFE, 0xE3, 0xC0, 0x00, 0x3C,
0x77, 0xFF, 0x7F, 0xEF, 0xFE, 0xE3, 0xC0, 0x03, 0x80, 0xE0, 0x7B, 0xFF, 0xFF, 0xFF, 0xF0, 0xE0, 0x70, 0xFF, 0xFF,
0xFF, 0xFD, 0xC0, 0x70, 0x1C, 0x00, 0x07, 0xDF, 0xFF, 0xFF, 0xFE, 0xF8, 0x3F, 0xEF, 0xFD, 0xFF, 0x07, 0xC0, 0x0F,
0xFF, 0xFF, 0xFF, 0xC0, 0xF8, 0x3F, 0xCF, 0xFD, 0xFF, 0x0F, 0xDF, 0xFF, 0xFF, 0xFE, 0xF8, 0x00, 0x0F, 0xFF, 0xFF,
0xFF, 0xC0,
}; };
static const EpdGlyph ubuntu_bold_10Glyphs[] = { static const EpdGlyph ubuntu_bold_10Glyphs[] = {
@@ -758,54 +1059,269 @@ static const EpdGlyph ubuntu_bold_10Glyphs[] = {
{10, 17, 11, 0, 17, 22, 7407}, // ž {10, 17, 11, 0, 17, 22, 7407}, // ž
{9, 16, 7, 1, 16, 18, 7429}, // ſ {9, 16, 7, 1, 16, 18, 7429}, // ſ
{8, 3, 8, 0, 15, 3, 7447}, // ̑ {8, 3, 8, 0, 15, 3, 7447}, // ̑
{11, 3, 11, 0, 8, 5, 7450}, // {11, 21, 13, 1, 21, 29, 7450}, // Ѐ
{21, 3, 21, 0, 8, 8, 7455}, // {11, 20, 13, 1, 20, 28, 7479}, // Ё
{21, 3, 21, 0, 8, 8, 7463}, // {17, 15, 17, 0, 15, 32, 7507}, // Ђ
{5, 6, 5, 0, 16, 4, 7471}, // {11, 21, 12, 1, 21, 29, 7539}, // Ѓ
{5, 6, 5, 0, 16, 4, 7475}, // {13, 15, 14, 1, 15, 25, 7568}, // Є
{5, 6, 5, 0, 3, 4, 7479}, // {12, 15, 12, 0, 15, 23, 7593}, // Ѕ
{10, 6, 10, 0, 16, 8, 7483}, // {4, 15, 7, 1, 15, 8, 7616}, // І
{9, 6, 10, 0, 16, 7, 7491}, // {9, 19, 7, -1, 19, 22, 7624}, // Ї
{9, 6, 10, 0, 3, 7, 7498}, // {10, 15, 11, 0, 15, 19, 7646}, // Ј
{10, 18, 10, 0, 15, 23, 7505}, // {23, 15, 24, 0, 15, 44, 7665}, // Љ
{10, 18, 10, 0, 15, 23, 7528}, // {21, 15, 23, 1, 15, 40, 7709}, // Њ
{7, 6, 8, 0, 10, 6, 7551}, // {16, 15, 16, 0, 15, 30, 7749}, // Ћ
{19, 4, 21, 1, 4, 10, 7557}, // {14, 21, 14, 1, 21, 37, 7779}, // Ќ
{27, 15, 28, 0, 15, 51, 7567}, // {14, 21, 16, 1, 21, 37, 7816}, // Ѝ
{7, 11, 7, 0, 11, 10, 7618}, // {14, 20, 14, 0, 20, 35, 7853}, // Ў
{7, 11, 7, 0, 11, 10, 7628}, // {13, 19, 15, 1, 15, 31, 7888}, // Џ
{11, 15, 3, -4, 15, 21, 7638}, // {15, 15, 15, 0, 15, 29, 7919}, // А
{12, 15, 12, 0, 15, 23, 7659}, // {12, 15, 14, 1, 15, 23, 7948}, // Б
{12, 15, 12, 0, 15, 23, 7682}, // {13, 15, 14, 1, 15, 25, 7971}, // В
{12, 15, 12, 0, 15, 23, 7705}, // {11, 15, 12, 1, 15, 21, 7996}, // Г
{13, 15, 12, 0, 15, 25, 7728}, // {17, 19, 17, 0, 15, 41, 8017}, // Д
{12, 15, 13, 0, 15, 23, 7753}, // {11, 15, 13, 1, 15, 21, 8058}, // Е
{15, 15, 15, 0, 15, 29, 7776}, // {21, 15, 21, 0, 15, 40, 8079}, // Ж
{13, 17, 15, 1, 15, 28, 7805}, // {12, 15, 13, 0, 15, 23, 8119}, // З
{11, 17, 11, 0, 15, 24, 7833}, // {14, 15, 16, 1, 15, 27, 8142}, // И
{10, 3, 12, 1, 8, 4, 7857}, // {14, 20, 16, 1, 20, 35, 8169}, // Й
{11, 15, 3, -4, 15, 21, 7861}, // {14, 15, 14, 1, 15, 27, 8204}, // К
{5, 4, 5, 0, 9, 3, 7882}, // {15, 15, 17, 0, 15, 29, 8231}, // Л
{14, 15, 13, 0, 15, 27, 7885}, // {17, 15, 19, 1, 15, 32, 8260}, // М
{13, 7, 13, 0, 10, 12, 7912}, // {13, 15, 15, 1, 15, 25, 8292}, // Н
{9, 21, 8, 0, 16, 24, 7924}, // {15, 15, 17, 1, 15, 29, 8317}, // О
{12, 11, 12, 0, 12, 17, 7948}, // {13, 15, 15, 1, 15, 25, 8346}, // П
{10, 14, 12, 1, 14, 18, 7965}, // {12, 15, 14, 1, 15, 23, 8371}, // Р
{10, 13, 12, 1, 13, 17, 7983}, // {13, 15, 14, 1, 15, 25, 8394}, // С
{10, 13, 12, 1, 13, 17, 8000}, // {13, 15, 13, 0, 15, 25, 8419}, // Т
{14, 15, 14, 0, 15, 27, 8444}, // У
{18, 16, 18, 0, 16, 36, 8471}, // Ф
{14, 15, 14, 0, 15, 27, 8507}, // Х
{16, 19, 17, 1, 15, 38, 8534}, // Ц
{13, 15, 14, 0, 15, 25, 8572}, // Ч
{19, 15, 21, 1, 15, 36, 8597}, // Ш
{22, 19, 23, 1, 15, 53, 8633}, // Щ
{16, 15, 16, 0, 15, 30, 8686}, // Ъ
{17, 15, 19, 1, 15, 32, 8716}, // Ы
{12, 15, 14, 1, 15, 23, 8748}, // Ь
{14, 15, 14, 0, 15, 27, 8771}, // Э
{21, 15, 23, 1, 15, 40, 8798}, // Ю
{13, 15, 14, 0, 15, 25, 8838}, // Я
{11, 11, 12, 0, 11, 16, 8863}, // а
{12, 16, 13, 0, 16, 24, 8879}, // б
{11, 11, 13, 1, 11, 16, 8903}, // в
{9, 11, 10, 1, 11, 13, 8919}, // г
{14, 14, 14, 0, 11, 25, 8932}, // д
{12, 11, 12, 0, 11, 17, 8957}, // е
{18, 11, 18, 0, 11, 25, 8974}, // ж
{10, 11, 10, 0, 11, 14, 8999}, // з
{11, 11, 13, 1, 11, 16, 9013}, // и
{11, 17, 13, 1, 17, 24, 9029}, // й
{12, 11, 12, 1, 11, 17, 9053}, // к
{12, 11, 13, 0, 11, 17, 9070}, // л
{14, 11, 16, 1, 11, 20, 9087}, // м
{10, 11, 12, 1, 11, 14, 9107}, // н
{12, 11, 13, 0, 11, 17, 9121}, // о
{10, 11, 12, 1, 11, 14, 9138}, // п
{11, 15, 13, 1, 11, 21, 9152}, // р
{10, 11, 11, 0, 11, 14, 9173}, // с
{11, 11, 11, 0, 11, 16, 9187}, // т
{12, 15, 11, 0, 11, 23, 9203}, // у
{16, 20, 17, 0, 16, 40, 9226}, // ф
{12, 11, 12, 0, 11, 17, 9266}, // х
{12, 14, 13, 1, 11, 21, 9283}, // ц
{11, 11, 12, 0, 11, 16, 9304}, // ч
{16, 11, 18, 1, 11, 22, 9320}, // ш
{18, 14, 19, 1, 11, 32, 9342}, // щ
{13, 11, 13, 0, 11, 18, 9374}, // ъ
{15, 11, 17, 1, 11, 21, 9392}, // ы
{11, 11, 12, 1, 11, 16, 9413}, // ь
{11, 11, 11, 0, 11, 16, 9429}, // э
{17, 11, 18, 1, 11, 24, 9445}, // ю
{11, 11, 12, 0, 11, 16, 9469}, // я
{12, 17, 12, 0, 17, 26, 9485}, // ѐ
{12, 16, 12, 0, 16, 24, 9511}, // ё
{12, 20, 13, 0, 16, 30, 9535}, // ђ
{9, 17, 10, 1, 17, 20, 9565}, // ѓ
{11, 11, 11, 0, 11, 16, 9585}, // є
{10, 11, 10, 0, 11, 14, 9601}, // ѕ
{4, 16, 6, 1, 16, 8, 9615}, // і
{9, 16, 6, -2, 16, 18, 9623}, // ї
{7, 20, 6, -2, 16, 18, 9641}, // ј
{19, 11, 19, 0, 11, 27, 9659}, // љ
{17, 11, 18, 1, 11, 24, 9686}, // њ
{12, 16, 13, 0, 16, 24, 9710}, // ћ
{12, 17, 12, 1, 17, 26, 9734}, // ќ
{11, 17, 13, 1, 17, 24, 9760}, // ѝ
{12, 21, 11, 0, 17, 32, 9784}, // ў
{10, 14, 12, 1, 11, 18, 9816}, // џ
{15, 16, 16, 0, 16, 30, 9834}, // Ѣ
{13, 16, 13, 0, 16, 26, 9864}, // ѣ
{15, 15, 17, 1, 15, 29, 9890}, // Ѳ
{12, 11, 13, 0, 11, 17, 9919}, // ѳ
{18, 15, 17, 0, 15, 34, 9936}, // Ѵ
{13, 11, 13, 0, 11, 18, 9970}, // ѵ
{16, 23, 17, 1, 19, 46, 9988}, // Ҋ
{13, 19, 13, 1, 16, 31, 10034}, // ҋ
{13, 15, 14, 0, 15, 25, 10065}, // Ҍ
{12, 11, 12, 0, 11, 17, 10090}, // ҍ
{12, 15, 14, 1, 15, 23, 10107}, // Ҏ
{11, 15, 13, 1, 11, 21, 10130}, // ҏ
{11, 18, 12, 1, 18, 25, 10151}, // Ґ
{9, 14, 10, 1, 14, 16, 10176}, // ґ
{12, 15, 13, 1, 15, 23, 10192}, // Ғ
{10, 11, 11, 1, 11, 14, 10215}, // ғ
{13, 19, 14, 1, 15, 31, 10229}, // Ҕ
{11, 15, 12, 1, 11, 21, 10260}, // ҕ
{22, 19, 21, 0, 15, 53, 10281}, // Җ
{18, 14, 18, 0, 11, 32, 10334}, // җ
{12, 20, 13, 0, 15, 30, 10366}, // Ҙ
{10, 16, 10, 0, 11, 20, 10396}, // ҙ
{15, 19, 15, 1, 15, 36, 10416}, // Қ
{12, 14, 13, 1, 11, 21, 10452}, // қ
{16, 15, 16, 1, 15, 30, 10473}, // Ҝ
{14, 11, 14, 1, 11, 20, 10503}, // ҝ
{15, 16, 15, 0, 16, 30, 10523}, // Ҟ
{13, 12, 13, 0, 12, 20, 10553}, // ҟ
{17, 15, 17, 0, 15, 32, 10573}, // Ҡ
{14, 11, 14, 0, 11, 20, 10605}, // ҡ
{16, 19, 17, 1, 15, 38, 10625}, // Ң
{12, 14, 13, 1, 11, 21, 10663}, // ң
{17, 15, 18, 1, 15, 32, 10684}, // Ҥ
{13, 11, 14, 1, 11, 18, 10716}, // ҥ
{22, 19, 23, 1, 15, 53, 10734}, // Ҧ
{17, 15, 18, 1, 11, 32, 10787}, // ҧ
{16, 19, 17, 1, 15, 38, 10819}, // Ҩ
{13, 14, 13, 0, 11, 23, 10857}, // ҩ
{13, 20, 14, 1, 15, 33, 10880}, // Ҫ
{10, 15, 11, 0, 11, 19, 10913}, // ҫ
{13, 19, 13, 0, 15, 31, 10932}, // Ҭ
{11, 14, 11, 0, 11, 20, 10963}, // ҭ
{14, 15, 14, 0, 15, 27, 10983}, // Ү
{12, 15, 12, 0, 11, 23, 11010}, // ү
{14, 15, 14, 0, 15, 27, 11033}, // Ұ
{12, 15, 12, 0, 11, 23, 11060}, // ұ
{15, 19, 15, 0, 15, 36, 11083}, // Ҳ
{12, 14, 12, 0, 11, 21, 11119}, // ҳ
{20, 19, 20, 0, 15, 48, 11140}, // Ҵ
{15, 14, 15, 0, 11, 27, 11188}, // ҵ
{14, 19, 15, 1, 15, 34, 11215}, // Ҷ
{13, 14, 12, 0, 11, 23, 11249}, // ҷ
{12, 15, 14, 1, 15, 23, 11272}, // Ҹ
{11, 11, 12, 0, 11, 16, 11295}, // ҹ
{13, 15, 15, 1, 15, 25, 11311}, // Һ
{10, 16, 12, 1, 16, 20, 11336}, // һ
{18, 15, 18, 0, 15, 34, 11356}, // Ҽ
{14, 11, 15, 0, 11, 20, 11390}, // ҽ
{18, 19, 18, 0, 15, 43, 11410}, // Ҿ
{14, 14, 15, 0, 11, 25, 11453}, // ҿ
{4, 15, 7, 1, 15, 8, 11478}, // Ӏ
{21, 20, 21, 0, 20, 53, 11486}, // Ӂ
{18, 17, 18, 0, 17, 39, 11539}, // ӂ
{13, 19, 15, 1, 15, 31, 11578}, // Ӄ
{11, 15, 12, 1, 11, 21, 11609}, // ӄ
{18, 19, 17, 0, 15, 43, 11630}, // Ӆ
{14, 14, 14, 0, 11, 25, 11673}, // ӆ
{13, 19, 15, 1, 15, 31, 11698}, // Ӈ
{11, 15, 13, 1, 11, 21, 11729}, // ӈ
{16, 19, 17, 1, 15, 38, 11750}, // Ӊ
{12, 14, 13, 1, 11, 21, 11788}, // ӊ
{13, 19, 14, 0, 15, 31, 11809}, // Ӌ
{11, 14, 12, 0, 11, 20, 11840}, // ӌ
{19, 19, 20, 1, 15, 46, 11860}, // Ӎ
{16, 14, 17, 1, 11, 28, 11906}, // ӎ
{4, 15, 6, 1, 15, 8, 11934}, // ӏ
{15, 20, 15, 0, 20, 38, 11942}, // Ӑ
{11, 17, 12, 0, 17, 24, 11980}, // ӑ
{15, 19, 15, 0, 19, 36, 12004}, // Ӓ
{11, 16, 12, 0, 16, 22, 12040}, // ӓ
{21, 15, 21, 0, 15, 40, 12062}, // Ӕ
{18, 11, 18, 0, 11, 25, 12102}, // ӕ
{11, 20, 13, 1, 20, 28, 12127}, // Ӗ
{12, 17, 12, 0, 17, 26, 12155}, // ӗ
{14, 15, 15, 1, 15, 27, 12181}, // Ә
{12, 11, 12, 0, 11, 17, 12208}, // ә
{14, 19, 15, 1, 19, 34, 12225}, // Ӛ
{12, 16, 12, 0, 16, 24, 12259}, // ӛ
{21, 19, 21, 0, 19, 50, 12283}, // Ӝ
{18, 16, 18, 0, 16, 36, 12333}, // ӝ
{12, 20, 13, 0, 20, 30, 12369}, // Ӟ
{10, 16, 10, 0, 16, 20, 12399}, // ӟ
{12, 15, 13, 0, 15, 23, 12419}, // Ӡ
{10, 15, 11, 0, 11, 19, 12442}, // ӡ
{14, 18, 16, 1, 18, 32, 12461}, // Ӣ
{11, 15, 13, 1, 15, 21, 12493}, // ӣ
{14, 19, 16, 1, 19, 34, 12514}, // Ӥ
{11, 16, 13, 1, 16, 22, 12548}, // ӥ
{15, 19, 17, 1, 19, 36, 12570}, // Ӧ
{12, 16, 13, 0, 16, 24, 12606}, // ӧ
{15, 15, 17, 1, 15, 29, 12630}, // Ө
{12, 11, 13, 0, 11, 17, 12659}, // ө
{15, 19, 17, 1, 19, 36, 12676}, // Ӫ
{12, 16, 13, 0, 16, 24, 12712}, // ӫ
{14, 19, 14, 0, 19, 34, 12736}, // Ӭ
{11, 16, 11, 0, 16, 22, 12770}, // ӭ
{14, 18, 14, 0, 18, 32, 12792}, // Ӯ
{12, 19, 11, 0, 15, 29, 12824}, // ӯ
{14, 19, 14, 0, 19, 34, 12853}, // Ӱ
{12, 20, 11, 0, 16, 30, 12887}, // ӱ
{14, 21, 14, 0, 21, 37, 12917}, // Ӳ
{12, 21, 11, 0, 17, 32, 12954}, // ӳ
{13, 19, 14, 0, 19, 31, 12986}, // Ӵ
{11, 16, 12, 0, 16, 22, 13017}, // ӵ
{11, 19, 12, 1, 15, 27, 13039}, // Ӷ
{9, 14, 10, 1, 11, 16, 13066}, // ӷ
{17, 19, 19, 1, 19, 41, 13082}, // Ӹ
{15, 16, 17, 1, 16, 30, 13123}, // ӹ
{11, 3, 11, 0, 8, 5, 13153}, //
{21, 3, 21, 0, 8, 8, 13158}, // —
{21, 3, 21, 0, 8, 8, 13166}, // ―
{5, 6, 5, 0, 16, 4, 13174}, //
{5, 6, 5, 0, 16, 4, 13178}, //
{5, 6, 5, 0, 3, 4, 13182}, //
{10, 6, 10, 0, 16, 8, 13186}, // “
{9, 6, 10, 0, 16, 7, 13194}, // ”
{9, 6, 10, 0, 3, 7, 13201}, // „
{10, 18, 10, 0, 15, 23, 13208}, // †
{10, 18, 10, 0, 15, 23, 13231}, // ‡
{7, 6, 8, 0, 10, 6, 13254}, // •
{19, 4, 21, 1, 4, 10, 13260}, // …
{27, 15, 28, 0, 15, 51, 13270}, // ‰
{7, 11, 7, 0, 11, 10, 13321}, //
{7, 11, 7, 0, 11, 10, 13331}, //
{11, 15, 3, -4, 15, 21, 13341}, //
{12, 15, 12, 0, 15, 23, 13362}, // €
{12, 15, 12, 0, 15, 23, 13385}, // ₮
{12, 15, 12, 0, 15, 23, 13408}, // ₴
{13, 15, 12, 0, 15, 25, 13431}, // ₹
{12, 15, 13, 0, 15, 23, 13456}, // ∂
{15, 15, 15, 0, 15, 29, 13479}, // ∆
{13, 17, 15, 1, 15, 28, 13508}, // ∏
{11, 17, 11, 0, 15, 24, 13536}, // ∑
{10, 3, 12, 1, 8, 4, 13560}, //
{11, 15, 3, -4, 15, 21, 13564}, //
{5, 4, 5, 0, 9, 3, 13585}, // ∙
{14, 15, 13, 0, 15, 27, 13588}, // √
{13, 7, 13, 0, 10, 12, 13615}, // ∞
{9, 21, 8, 0, 16, 24, 13627}, // ∫
{12, 11, 12, 0, 12, 17, 13651}, // ≈
{10, 14, 12, 1, 14, 18, 13668}, // ≠
{10, 13, 12, 1, 13, 17, 13686}, // ≤
{10, 13, 12, 1, 13, 17, 13703}, // ≥
}; };
static const EpdUnicodeInterval ubuntu_bold_10Intervals[] = { static const EpdUnicodeInterval ubuntu_bold_10Intervals[] = {
{0x0, 0x0, 0x0}, {0x8, 0x9, 0x1}, {0xD, 0xD, 0x3}, {0x1D, 0x1D, 0x4}, {0x0, 0x0, 0x0}, {0x8, 0x9, 0x1}, {0xD, 0xD, 0x3}, {0x1D, 0x1D, 0x4},
{0x20, 0x7E, 0x5}, {0xA0, 0xFF, 0x64}, {0x100, 0x17F, 0xC4}, {0x311, 0x311, 0x144}, {0x20, 0x7E, 0x5}, {0xA0, 0xFF, 0x64}, {0x100, 0x17F, 0xC4}, {0x311, 0x311, 0x144},
{0x2013, 0x2015, 0x145}, {0x2018, 0x201A, 0x148}, {0x201C, 0x201E, 0x14B}, {0x2020, 0x2022, 0x14E}, {0x400, 0x45F, 0x145}, {0x462, 0x463, 0x1A5}, {0x472, 0x475, 0x1A7}, {0x48A, 0x4F9, 0x1AB},
{0x2026, 0x2026, 0x151}, {0x2030, 0x2030, 0x152}, {0x2039, 0x203A, 0x153}, {0x2044, 0x2044, 0x155}, {0x2013, 0x2015, 0x21B}, {0x2018, 0x201A, 0x21E}, {0x201C, 0x201E, 0x221}, {0x2020, 0x2022, 0x224},
{0x20AC, 0x20AC, 0x156}, {0x20AE, 0x20AE, 0x157}, {0x20B4, 0x20B4, 0x158}, {0x20B9, 0x20B9, 0x159}, {0x2026, 0x2026, 0x227}, {0x2030, 0x2030, 0x228}, {0x2039, 0x203A, 0x229}, {0x2044, 0x2044, 0x22B},
{0x2202, 0x2202, 0x15A}, {0x2206, 0x2206, 0x15B}, {0x220F, 0x220F, 0x15C}, {0x2211, 0x2212, 0x15D}, {0x20AC, 0x20AC, 0x22C}, {0x20AE, 0x20AE, 0x22D}, {0x20B4, 0x20B4, 0x22E}, {0x20B9, 0x20B9, 0x22F},
{0x2215, 0x2215, 0x15F}, {0x2219, 0x221A, 0x160}, {0x221E, 0x221E, 0x162}, {0x222B, 0x222B, 0x163}, {0x2202, 0x2202, 0x230}, {0x2206, 0x2206, 0x231}, {0x220F, 0x220F, 0x232}, {0x2211, 0x2212, 0x233},
{0x2248, 0x2248, 0x164}, {0x2260, 0x2260, 0x165}, {0x2264, 0x2265, 0x166}, {0x2215, 0x2215, 0x235}, {0x2219, 0x221A, 0x236}, {0x221E, 0x221E, 0x238}, {0x222B, 0x222B, 0x239},
{0x2248, 0x2248, 0x23A}, {0x2260, 0x2260, 0x23B}, {0x2264, 0x2265, 0x23C},
}; };
static const EpdFontData ubuntu_bold_10 = { static const EpdFontData ubuntu_bold_10 = {
ubuntu_bold_10Bitmaps, ubuntu_bold_10Glyphs, ubuntu_bold_10Intervals, 31, 24, 20, -4, false, ubuntu_bold_10Bitmaps, ubuntu_bold_10Glyphs, ubuntu_bold_10Intervals, 35, 24, 20, -4, false,
}; };
+1 -1
View File
@@ -54,7 +54,7 @@ intervals = [
# (0x0370, 0x03FF), # (0x0370, 0x03FF),
### Cyrillic ### ### Cyrillic ###
# Russian, Ukrainian, Bulgarian, etc. # Russian, Ukrainian, Bulgarian, etc.
# (0x0400, 0x04FF), (0x0400, 0x04FF),
### Math Symbols (common subset) ### ### Math Symbols (common subset) ###
# General math operators # General math operators
(0x2200, 0x22FF), (0x2200, 0x22FF),
+101 -191
View File
@@ -7,247 +7,151 @@
#include <map> #include <map>
#include "Epub/FsHelpers.h" #include "Epub/FsHelpers.h"
#include "Epub/parsers/ContainerParser.h"
#include "Epub/parsers/ContentOpfParser.h"
#include "Epub/parsers/TocNcxParser.h"
bool Epub::findContentOpfFile(const ZipFile& zip, std::string& contentOpfFile) { bool Epub::findContentOpfFile(std::string* contentOpfFile) const {
// open up the meta data to find where the content.opf file lives const auto containerPath = "META-INF/container.xml";
size_t s; size_t containerSize;
const auto metaInfo = reinterpret_cast<char*>(zip.readFileToMemory("META-INF/container.xml", &s, true));
if (!metaInfo) { // Get file size without loading it all into heap
Serial.printf("[%lu] [EBP] Could not find META-INF/container.xml\n", millis()); if (!getItemSize(containerPath, &containerSize)) {
Serial.printf("[%lu] [EBP] Could not find or size META-INF/container.xml\n", millis());
return false; return false;
} }
// parse the meta data ContainerParser containerParser(containerSize);
tinyxml2::XMLDocument metaDataDoc;
const auto result = metaDataDoc.Parse(metaInfo);
free(metaInfo);
if (result != tinyxml2::XML_SUCCESS) { if (!containerParser.setup()) {
Serial.printf("[%lu] [EBP] Could not parse META-INF/container.xml. Error: %d\n", millis(), result);
return false; return false;
} }
const auto container = metaDataDoc.FirstChildElement("container"); // Stream read (reusing your existing stream logic)
if (!container) { if (!readItemContentsToStream(containerPath, containerParser, 512)) {
Serial.printf("[%lu] [EBP] Could not find container element in META-INF/container.xml\n", millis()); Serial.printf("[%lu] [EBP] Could not read META-INF/container.xml\n", millis());
containerParser.teardown();
return false; return false;
} }
const auto rootfiles = container->FirstChildElement("rootfiles"); // Extract the result
if (!rootfiles) { if (containerParser.fullPath.empty()) {
Serial.printf("[%lu] [EBP] Could not find rootfiles element in META-INF/container.xml\n", millis()); Serial.printf("[%lu] [EBP] Could not find valid rootfile in container.xml\n", millis());
containerParser.teardown();
return false; return false;
} }
// find the root file that has the media-type="application/oebps-package+xml" *contentOpfFile = std::move(containerParser.fullPath);
auto rootfile = rootfiles->FirstChildElement("rootfile");
while (rootfile) {
const char* mediaType = rootfile->Attribute("media-type");
if (mediaType && strcmp(mediaType, "application/oebps-package+xml") == 0) {
const char* full_path = rootfile->Attribute("full-path");
if (full_path) {
contentOpfFile = full_path;
return true;
}
}
rootfile = rootfile->NextSiblingElement("rootfile");
}
Serial.printf("[%lu] [EBP] Could not get path to content.opf file\n", millis()); containerParser.teardown();
return false;
}
bool Epub::parseContentOpf(ZipFile& zip, std::string& content_opf_file) {
// read in the content.opf file and parse it
auto contents = reinterpret_cast<char*>(zip.readFileToMemory(content_opf_file.c_str(), nullptr, true));
// parse the contents
tinyxml2::XMLDocument doc;
auto result = doc.Parse(contents);
free(contents);
if (result != tinyxml2::XML_SUCCESS) {
Serial.printf("[%lu] [EBP] Error parsing content.opf - %s\n", millis(),
tinyxml2::XMLDocument::ErrorIDToName(result));
return false;
}
auto package = doc.FirstChildElement("package");
if (!package) package = doc.FirstChildElement("opf:package");
if (!package) {
Serial.printf("[%lu] [EBP] Could not find package element in content.opf\n", millis());
return false;
}
// get the metadata - title and cover image
auto metadata = package->FirstChildElement("metadata");
if (!metadata) metadata = package->FirstChildElement("opf:metadata");
if (!metadata) {
Serial.printf("[%lu] [EBP] Missing metadata\n", millis());
return false;
}
auto titleEl = metadata->FirstChildElement("dc:title");
if (!titleEl) {
Serial.printf("[%lu] [EBP] Missing title\n", millis());
return false;
}
this->title = titleEl->GetText();
auto cover = metadata->FirstChildElement("meta");
if (!cover) cover = metadata->FirstChildElement("opf:meta");
while (cover && cover->Attribute("name") && strcmp(cover->Attribute("name"), "cover") != 0) {
cover = cover->NextSiblingElement("meta");
}
if (!cover) {
Serial.printf("[%lu] [EBP] Missing cover\n", millis());
}
auto coverItem = cover ? cover->Attribute("content") : nullptr;
// read the manifest and spine
// the manifest gives us the names of the files
// the spine gives us the order of the files
// we can then read the files in the order they are in the spine
auto manifest = package->FirstChildElement("manifest");
if (!manifest) manifest = package->FirstChildElement("opf:manifest");
if (!manifest) {
Serial.printf("[%lu] [EBP] Missing manifest\n", millis());
return false;
}
// create a mapping from id to file name
auto item = manifest->FirstChildElement("item");
if (!item) item = manifest->FirstChildElement("opf:item");
std::map<std::string, std::string> items;
while (item) {
std::string itemId = item->Attribute("id");
std::string href = contentBasePath + item->Attribute("href");
// grab the cover image
if (coverItem && itemId == coverItem) {
coverImageItem = href;
}
// grab the ncx file
if (itemId == "ncx" || itemId == "ncxtoc") {
tocNcxItem = href;
}
items[itemId] = href;
auto nextItem = item->NextSiblingElement("item");
if (!nextItem) nextItem = item->NextSiblingElement("opf:item");
item = nextItem;
}
// find the spine
auto spineEl = package->FirstChildElement("spine");
if (!spineEl) spineEl = package->FirstChildElement("opf:spine");
if (!spineEl) {
Serial.printf("[%lu] [EBP] Missing spine\n", millis());
return false;
}
// read the spine
auto itemref = spineEl->FirstChildElement("itemref");
if (!itemref) itemref = spineEl->FirstChildElement("opf:itemref");
while (itemref) {
auto id = itemref->Attribute("idref");
if (items.find(id) != items.end()) {
spine.emplace_back(id, items[id]);
}
auto nextItemRef = itemref->NextSiblingElement("itemref");
if (!nextItemRef) nextItemRef = itemref->NextSiblingElement("opf:itemref");
itemref = nextItemRef;
}
return true; return true;
} }
bool Epub::parseTocNcxFile(const ZipFile& zip) { bool Epub::parseContentOpf(const std::string& contentOpfFilePath) {
size_t contentOpfSize;
if (!getItemSize(contentOpfFilePath, &contentOpfSize)) {
Serial.printf("[%lu] [EBP] Could not get size of content.opf\n", millis());
return false;
}
ContentOpfParser opfParser(getBasePath(), contentOpfSize);
if (!opfParser.setup()) {
Serial.printf("[%lu] [EBP] Could not setup content.opf parser\n", millis());
return false;
}
if (!readItemContentsToStream(contentOpfFilePath, opfParser, 1024)) {
Serial.printf("[%lu] [EBP] Could not read content.opf\n", millis());
opfParser.teardown();
return false;
}
// Grab data from opfParser into epub
title = opfParser.title;
if (!opfParser.coverItemId.empty() && opfParser.items.count(opfParser.coverItemId) > 0) {
coverImageItem = opfParser.items.at(opfParser.coverItemId);
}
if (opfParser.items.count("ncx")) {
tocNcxItem = opfParser.items.at("ncx");
} else if (opfParser.items.count("ncxtoc")) {
tocNcxItem = opfParser.items.at("ncxtoc");
}
for (auto& spineRef : opfParser.spineRefs) {
if (opfParser.items.count(spineRef)) {
spine.emplace_back(spineRef, opfParser.items.at(spineRef));
}
}
Serial.printf("[%lu] [EBP] Successfully parsed content.opf\n", millis());
opfParser.teardown();
return true;
}
bool Epub::parseTocNcxFile() {
// the ncx file should have been specified in the content.opf file // the ncx file should have been specified in the content.opf file
if (tocNcxItem.empty()) { if (tocNcxItem.empty()) {
Serial.printf("[%lu] [EBP] No ncx file specified\n", millis()); Serial.printf("[%lu] [EBP] No ncx file specified\n", millis());
return false; return false;
} }
const auto ncxData = reinterpret_cast<char*>(zip.readFileToMemory(tocNcxItem.c_str(), nullptr, true)); size_t tocSize;
if (!ncxData) { if (!getItemSize(tocNcxItem, &tocSize)) {
Serial.printf("[%lu] [EBP] Could not find %s\n", millis(), tocNcxItem.c_str()); Serial.printf("[%lu] [EBP] Could not get size of toc ncx\n", millis());
return false; return false;
} }
// Parse the Toc contents TocNcxParser ncxParser(contentBasePath, tocSize);
tinyxml2::XMLDocument doc;
const auto result = doc.Parse(ncxData);
free(ncxData);
if (result != tinyxml2::XML_SUCCESS) { if (!ncxParser.setup()) {
Serial.printf("[%lu] [EBP] Error parsing toc %s\n", millis(), tinyxml2::XMLDocument::ErrorIDToName(result)); Serial.printf("[%lu] [EBP] Could not setup toc ncx parser\n", millis());
return false; return false;
} }
const auto ncx = doc.FirstChildElement("ncx"); if (!readItemContentsToStream(tocNcxItem, ncxParser, 1024)) {
if (!ncx) { Serial.printf("[%lu] [EBP] Could not read toc ncx stream\n", millis());
Serial.printf("[%lu] [EBP] Could not find first child ncx in toc\n", millis()); ncxParser.teardown();
return false; return false;
} }
const auto navMap = ncx->FirstChildElement("navMap"); this->toc = std::move(ncxParser.toc);
if (!navMap) {
Serial.printf("[%lu] [EBP] Could not find navMap child in ncx\n", millis());
return false;
}
recursivelyParseNavMap(navMap->FirstChildElement("navPoint")); Serial.printf("[%lu] [EBP] Parsed %d TOC items\n", millis(), this->toc.size());
ncxParser.teardown();
return true; return true;
} }
void Epub::recursivelyParseNavMap(tinyxml2::XMLElement* element) {
// Fills toc map
while (element) {
std::string navTitle = element->FirstChildElement("navLabel")->FirstChildElement("text")->FirstChild()->Value();
const auto content = element->FirstChildElement("content");
std::string href = contentBasePath + content->Attribute("src");
// split the href on the # to get the href and the anchor
const size_t pos = href.find('#');
std::string anchor;
if (pos != std::string::npos) {
anchor = href.substr(pos + 1);
href = href.substr(0, pos);
}
toc.emplace_back(navTitle, href, anchor, 0);
tinyxml2::XMLElement* nestedNavPoint = element->FirstChildElement("navPoint");
if (nestedNavPoint) {
recursivelyParseNavMap(nestedNavPoint);
}
element = element->NextSiblingElement("navPoint");
}
}
// load in the meta data for the epub file // load in the meta data for the epub file
bool Epub::load() { bool Epub::load() {
Serial.printf("[%lu] [EBP] Loading ePub: %s\n", millis(), filepath.c_str());
ZipFile zip("/sd" + filepath); ZipFile zip("/sd" + filepath);
std::string contentOpfFile; std::string contentOpfFilePath;
if (!findContentOpfFile(zip, contentOpfFile)) { if (!findContentOpfFile(&contentOpfFilePath)) {
Serial.printf("[%lu] [EBP] Could not open ePub\n", millis()); Serial.printf("[%lu] [EBP] Could not find content.opf in zip\n", millis());
return false; return false;
} }
contentBasePath = contentOpfFile.substr(0, contentOpfFile.find_last_of('/') + 1); Serial.printf("[%lu] [EBP] Found content.opf at: %s\n", millis(), contentOpfFilePath.c_str());
if (!parseContentOpf(zip, contentOpfFile)) { contentBasePath = contentOpfFilePath.substr(0, contentOpfFilePath.find_last_of('/') + 1);
if (!parseContentOpf(contentOpfFilePath)) {
Serial.printf("[%lu] [EBP] Could not parse content.opf\n", millis());
return false; return false;
} }
if (!parseTocNcxFile(zip)) { if (!parseTocNcxFile()) {
Serial.printf("[%lu] [EBP] Could not parse toc\n", millis());
return false; return false;
} }
Serial.printf("[%lu] [EBP] Loaded ePub: %s\n", millis(), filepath.c_str());
return true; return true;
} }
@@ -344,6 +248,13 @@ bool Epub::readItemContentsToStream(const std::string& itemHref, Print& out, con
return zip.readFileToStream(path.c_str(), out, chunkSize); return zip.readFileToStream(path.c_str(), out, chunkSize);
} }
bool Epub::getItemSize(const std::string& itemHref, size_t* size) const {
const ZipFile zip("/sd" + filepath);
const std::string path = normalisePath(itemHref);
return zip.getInflatedFileSize(path.c_str(), size);
}
int Epub::getSpineItemsCount() const { return spine.size(); } int Epub::getSpineItemsCount() const { return spine.size(); }
std::string& Epub::getSpineItem(const int spineIndex) { std::string& Epub::getSpineItem(const int spineIndex) {
@@ -391,6 +302,5 @@ int Epub::getTocIndexForSpineIndex(const int spineIndex) const {
} }
Serial.printf("[%lu] [EBP] TOC item not found\n", millis()); Serial.printf("[%lu] [EBP] TOC item not found\n", millis());
// not found - default to first item return -1;
return 0;
} }
+6 -16
View File
@@ -1,22 +1,13 @@
#pragma once #pragma once
#include <Print.h> #include <Print.h>
#include <tinyxml2.h>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
class ZipFile; #include "Epub/EpubTocEntry.h"
class EpubTocEntry { class ZipFile;
public:
std::string title;
std::string href;
std::string anchor;
int level;
EpubTocEntry(std::string title, std::string href, std::string anchor, const int level)
: title(std::move(title)), href(std::move(href)), anchor(std::move(anchor)), level(level) {}
};
class Epub { class Epub {
// the title read from the EPUB meta data // the title read from the EPUB meta data
@@ -36,11 +27,9 @@ class Epub {
// Uniq cache key based on filepath // Uniq cache key based on filepath
std::string cachePath; std::string cachePath;
// find the path for the content.opf file bool findContentOpfFile(std::string* contentOpfFile) const;
static bool findContentOpfFile(const ZipFile& zip, std::string& contentOpfFile); bool parseContentOpf(const std::string& contentOpfFilePath);
bool parseContentOpf(ZipFile& zip, std::string& content_opf_file); bool parseTocNcxFile();
bool parseTocNcxFile(const ZipFile& zip);
void recursivelyParseNavMap(tinyxml2::XMLElement* element);
public: public:
explicit Epub(std::string filepath, const std::string& cacheDir) : filepath(std::move(filepath)) { explicit Epub(std::string filepath, const std::string& cacheDir) : filepath(std::move(filepath)) {
@@ -59,6 +48,7 @@ class Epub {
uint8_t* readItemContentsToBytes(const std::string& itemHref, size_t* size = nullptr, uint8_t* readItemContentsToBytes(const std::string& itemHref, size_t* size = nullptr,
bool trailingNullByte = false) const; bool trailingNullByte = false) const;
bool readItemContentsToStream(const std::string& itemHref, Print& out, size_t chunkSize) const; bool readItemContentsToStream(const std::string& itemHref, Print& out, size_t chunkSize) const;
bool getItemSize(const std::string& itemHref, size_t* size) const;
std::string& getSpineItem(int spineIndex); std::string& getSpineItem(int spineIndex);
int getSpineItemsCount() const; int getSpineItemsCount() const;
EpubTocEntry& getTocItem(int tocTndex); EpubTocEntry& getTocItem(int tocTndex);
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <string>
class EpubTocEntry {
public:
std::string title;
std::string href;
std::string anchor;
int level;
EpubTocEntry(std::string title, std::string href, std::string anchor, const int level)
: title(std::move(title)), href(std::move(href)), anchor(std::move(anchor)), level(level) {}
};
+15 -11
View File
@@ -4,6 +4,7 @@
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <functional>
#include <limits> #include <limits>
#include <vector> #include <vector>
@@ -17,15 +18,17 @@ void ParsedText::addWord(std::string word, const EpdFontStyle fontStyle) {
} }
// Consumes data to minimize memory usage // Consumes data to minimize memory usage
std::list<std::shared_ptr<TextBlock>> ParsedText::layoutAndExtractLines(const GfxRenderer& renderer, const int fontId, void ParsedText::layoutAndExtractLines(const GfxRenderer& renderer, const int fontId, const int horizontalMargin,
const int horizontalMargin) { const std::function<void(std::shared_ptr<TextBlock>)>& processLine) {
if (words.empty()) { if (words.empty()) {
return {}; return;
} }
const size_t totalWordCount = words.size(); const size_t totalWordCount = words.size();
const int pageWidth = renderer.getScreenWidth() - horizontalMargin; const int pageWidth = renderer.getScreenWidth() - horizontalMargin;
const int spaceWidth = renderer.getSpaceWidth(fontId); 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;
std::vector<uint16_t> wordWidths; std::vector<uint16_t> wordWidths;
wordWidths.reserve(totalWordCount); wordWidths.reserve(totalWordCount);
@@ -50,7 +53,7 @@ std::list<std::shared_ptr<TextBlock>> ParsedText::layoutAndExtractLines(const Gf
ans[totalWordCount - 1] = totalWordCount - 1; ans[totalWordCount - 1] = totalWordCount - 1;
for (int i = totalWordCount - 2; i >= 0; --i) { for (int i = totalWordCount - 2; i >= 0; --i) {
int currlen = -spaceWidth; int currlen = -spaceWidth + indentWidth;
dp[i] = MAX_COST; dp[i] = MAX_COST;
for (size_t j = i; j < totalWordCount; ++j) { for (size_t j = i; j < totalWordCount; ++j) {
@@ -99,8 +102,6 @@ std::list<std::shared_ptr<TextBlock>> ParsedText::layoutAndExtractLines(const Gf
currentWordIndex = nextBreakIndex; currentWordIndex = nextBreakIndex;
} }
std::list<std::shared_ptr<TextBlock>> lines;
// Initialize iterators for consumption // Initialize iterators for consumption
auto wordStartIt = words.begin(); auto wordStartIt = words.begin();
auto wordStyleStartIt = wordStyles.begin(); auto wordStyleStartIt = wordStyles.begin();
@@ -123,7 +124,11 @@ std::list<std::shared_ptr<TextBlock>> ParsedText::layoutAndExtractLines(const Gf
} }
// Calculate spacing // Calculate spacing
const int spareSpace = pageWidth - lineWordWidthSum; int spareSpace = pageWidth - lineWordWidthSum;
if (wordWidthIndex == 0) {
spareSpace -= indentWidth;
}
int spacing = spaceWidth; int spacing = spaceWidth;
const bool isLastLine = lineBreak == totalWordCount; const bool isLastLine = lineBreak == totalWordCount;
@@ -132,7 +137,8 @@ std::list<std::shared_ptr<TextBlock>> ParsedText::layoutAndExtractLines(const Gf
} }
// Calculate initial x position // Calculate initial x position
uint16_t xpos = 0; uint16_t xpos = (wordWidthIndex == 0) ? indentWidth : 0;
if (style == TextBlock::RIGHT_ALIGN) { if (style == TextBlock::RIGHT_ALIGN) {
xpos = spareSpace - (lineWordCount - 1) * spaceWidth; xpos = spareSpace - (lineWordCount - 1) * spaceWidth;
} else if (style == TextBlock::CENTER_ALIGN) { } else if (style == TextBlock::CENTER_ALIGN) {
@@ -153,7 +159,7 @@ std::list<std::shared_ptr<TextBlock>> ParsedText::layoutAndExtractLines(const Gf
std::list<EpdFontStyle> lineWordStyles; std::list<EpdFontStyle> lineWordStyles;
lineWordStyles.splice(lineWordStyles.begin(), wordStyles, wordStyleStartIt, wordStyleEndIt); lineWordStyles.splice(lineWordStyles.begin(), wordStyles, wordStyleStartIt, wordStyleEndIt);
lines.push_back( processLine(
std::make_shared<TextBlock>(std::move(lineWords), std::move(lineXPos), std::move(lineWordStyles), style)); std::make_shared<TextBlock>(std::move(lineWords), std::move(lineXPos), std::move(lineWordStyles), style));
// Update pointers/indices for the next line // Update pointers/indices for the next line
@@ -162,6 +168,4 @@ std::list<std::shared_ptr<TextBlock>> ParsedText::layoutAndExtractLines(const Gf
wordWidthIndex += lineWordCount; wordWidthIndex += lineWordCount;
lastBreakAt = lineBreak; lastBreakAt = lineBreak;
} }
return lines;
} }
+6 -3
View File
@@ -3,6 +3,7 @@
#include <EpdFontFamily.h> #include <EpdFontFamily.h>
#include <cstdint> #include <cstdint>
#include <functional>
#include <list> #include <list>
#include <memory> #include <memory>
#include <string> #include <string>
@@ -15,15 +16,17 @@ class ParsedText {
std::list<std::string> words; std::list<std::string> words;
std::list<EpdFontStyle> wordStyles; std::list<EpdFontStyle> wordStyles;
TextBlock::BLOCK_STYLE style; TextBlock::BLOCK_STYLE style;
bool extraParagraphSpacing;
public: public:
explicit ParsedText(const TextBlock::BLOCK_STYLE style) : style(style) {} explicit ParsedText(const TextBlock::BLOCK_STYLE style, const bool extraParagraphSpacing)
: style(style), extraParagraphSpacing(extraParagraphSpacing) {}
~ParsedText() = default; ~ParsedText() = default;
void addWord(std::string word, EpdFontStyle fontStyle); void addWord(std::string word, EpdFontStyle fontStyle);
void setStyle(const TextBlock::BLOCK_STYLE style) { this->style = style; } void setStyle(const TextBlock::BLOCK_STYLE style) { this->style = style; }
TextBlock::BLOCK_STYLE getStyle() const { return style; } TextBlock::BLOCK_STYLE getStyle() const { return style; }
bool isEmpty() const { return words.empty(); } bool isEmpty() const { return words.empty(); }
std::list<std::shared_ptr<TextBlock>> layoutAndExtractLines(const GfxRenderer& renderer, int fontId, void layoutAndExtractLines(const GfxRenderer& renderer, int fontId, int horizontalMargin,
int horizontalMargin); const std::function<void(std::shared_ptr<TextBlock>)>& processLine);
}; };
+16 -9
View File
@@ -5,11 +5,11 @@
#include <fstream> #include <fstream>
#include "EpubHtmlParserSlim.h"
#include "FsHelpers.h" #include "FsHelpers.h"
#include "Page.h" #include "Page.h"
#include "parsers/ChapterHtmlSlimParser.h"
constexpr uint8_t SECTION_FILE_VERSION = 4; constexpr uint8_t SECTION_FILE_VERSION = 5;
void Section::onPageComplete(std::unique_ptr<Page> page) { void Section::onPageComplete(std::unique_ptr<Page> page) {
const auto filePath = cachePath + "/page_" + std::to_string(pageCount) + ".bin"; const auto filePath = cachePath + "/page_" + std::to_string(pageCount) + ".bin";
@@ -24,7 +24,8 @@ void Section::onPageComplete(std::unique_ptr<Page> page) {
} }
void Section::writeCacheMetadata(const int fontId, const float lineCompression, const int marginTop, void Section::writeCacheMetadata(const int fontId, const float lineCompression, const int marginTop,
const int marginRight, const int marginBottom, const int marginLeft) const { const int marginRight, const int marginBottom, const int marginLeft,
const bool extraParagraphSpacing) const {
std::ofstream outputFile(("/sd" + cachePath + "/section.bin").c_str()); std::ofstream outputFile(("/sd" + cachePath + "/section.bin").c_str());
serialization::writePod(outputFile, SECTION_FILE_VERSION); serialization::writePod(outputFile, SECTION_FILE_VERSION);
serialization::writePod(outputFile, fontId); serialization::writePod(outputFile, fontId);
@@ -33,12 +34,14 @@ void Section::writeCacheMetadata(const int fontId, const float lineCompression,
serialization::writePod(outputFile, marginRight); serialization::writePod(outputFile, marginRight);
serialization::writePod(outputFile, marginBottom); serialization::writePod(outputFile, marginBottom);
serialization::writePod(outputFile, marginLeft); serialization::writePod(outputFile, marginLeft);
serialization::writePod(outputFile, extraParagraphSpacing);
serialization::writePod(outputFile, pageCount); serialization::writePod(outputFile, pageCount);
outputFile.close(); outputFile.close();
} }
bool Section::loadCacheMetadata(const int fontId, const float lineCompression, const int marginTop, bool Section::loadCacheMetadata(const int fontId, const float lineCompression, const int marginTop,
const int marginRight, const int marginBottom, const int marginLeft) { const int marginRight, const int marginBottom, const int marginLeft,
const bool extraParagraphSpacing) {
if (!SD.exists(cachePath.c_str())) { if (!SD.exists(cachePath.c_str())) {
return false; return false;
} }
@@ -63,15 +66,18 @@ bool Section::loadCacheMetadata(const int fontId, const float lineCompression, c
int fileFontId, fileMarginTop, fileMarginRight, fileMarginBottom, fileMarginLeft; int fileFontId, fileMarginTop, fileMarginRight, fileMarginBottom, fileMarginLeft;
float fileLineCompression; float fileLineCompression;
bool fileExtraParagraphSpacing;
serialization::readPod(inputFile, fileFontId); serialization::readPod(inputFile, fileFontId);
serialization::readPod(inputFile, fileLineCompression); serialization::readPod(inputFile, fileLineCompression);
serialization::readPod(inputFile, fileMarginTop); serialization::readPod(inputFile, fileMarginTop);
serialization::readPod(inputFile, fileMarginRight); serialization::readPod(inputFile, fileMarginRight);
serialization::readPod(inputFile, fileMarginBottom); serialization::readPod(inputFile, fileMarginBottom);
serialization::readPod(inputFile, fileMarginLeft); serialization::readPod(inputFile, fileMarginLeft);
serialization::readPod(inputFile, fileExtraParagraphSpacing);
if (fontId != fileFontId || lineCompression != fileLineCompression || marginTop != fileMarginTop || if (fontId != fileFontId || lineCompression != fileLineCompression || marginTop != fileMarginTop ||
marginRight != fileMarginRight || marginBottom != fileMarginBottom || marginLeft != fileMarginLeft) { marginRight != fileMarginRight || marginBottom != fileMarginBottom || marginLeft != fileMarginLeft ||
extraParagraphSpacing != fileExtraParagraphSpacing) {
inputFile.close(); inputFile.close();
Serial.printf("[%lu] [SCT] Deserialization failed: Parameters do not match\n", millis()); Serial.printf("[%lu] [SCT] Deserialization failed: Parameters do not match\n", millis());
clearCache(); clearCache();
@@ -107,7 +113,8 @@ bool Section::clearCache() const {
} }
bool Section::persistPageDataToSD(const int fontId, const float lineCompression, const int marginTop, bool Section::persistPageDataToSD(const int fontId, const float lineCompression, const int marginTop,
const int marginRight, const int marginBottom, const int marginLeft) { const int marginRight, const int marginBottom, const int marginLeft,
const bool extraParagraphSpacing) {
const auto localPath = epub->getSpineItem(spineIndex); const auto localPath = epub->getSpineItem(spineIndex);
// TODO: Should we get rid of this file all together? // TODO: Should we get rid of this file all together?
@@ -127,8 +134,8 @@ bool Section::persistPageDataToSD(const int fontId, const float lineCompression,
const auto sdTmpHtmlPath = "/sd" + tmpHtmlPath; const auto sdTmpHtmlPath = "/sd" + tmpHtmlPath;
EpubHtmlParserSlim visitor(sdTmpHtmlPath.c_str(), renderer, fontId, lineCompression, marginTop, marginRight, ChapterHtmlSlimParser visitor(sdTmpHtmlPath.c_str(), renderer, fontId, lineCompression, marginTop, marginRight,
marginBottom, marginLeft, marginBottom, marginLeft, extraParagraphSpacing,
[this](std::unique_ptr<Page> page) { this->onPageComplete(std::move(page)); }); [this](std::unique_ptr<Page> page) { this->onPageComplete(std::move(page)); });
success = visitor.parseAndBuildPages(); success = visitor.parseAndBuildPages();
@@ -138,7 +145,7 @@ bool Section::persistPageDataToSD(const int fontId, const float lineCompression,
return false; return false;
} }
writeCacheMetadata(fontId, lineCompression, marginTop, marginRight, marginBottom, marginLeft); writeCacheMetadata(fontId, lineCompression, marginTop, marginRight, marginBottom, marginLeft, extraParagraphSpacing);
return true; return true;
} }
+3 -3
View File
@@ -13,7 +13,7 @@ class Section {
std::string cachePath; std::string cachePath;
void writeCacheMetadata(int fontId, float lineCompression, int marginTop, int marginRight, int marginBottom, void writeCacheMetadata(int fontId, float lineCompression, int marginTop, int marginRight, int marginBottom,
int marginLeft) const; int marginLeft, bool extraParagraphSpacing) const;
void onPageComplete(std::unique_ptr<Page> page); void onPageComplete(std::unique_ptr<Page> page);
public: public:
@@ -26,10 +26,10 @@ class Section {
} }
~Section() = default; ~Section() = default;
bool loadCacheMetadata(int fontId, float lineCompression, int marginTop, int marginRight, int marginBottom, bool loadCacheMetadata(int fontId, float lineCompression, int marginTop, int marginRight, int marginBottom,
int marginLeft); int marginLeft, bool extraParagraphSpacing);
void setupCacheDir() const; void setupCacheDir() const;
bool clearCache() const; bool clearCache() const;
bool persistPageDataToSD(int fontId, float lineCompression, int marginTop, int marginRight, int marginBottom, bool persistPageDataToSD(int fontId, float lineCompression, int marginTop, int marginRight, int marginBottom,
int marginLeft); int marginLeft, bool extraParagraphSpacing);
std::unique_ptr<Page> loadPageFromSD() const; std::unique_ptr<Page> loadPageFromSD() const;
}; };
@@ -1,11 +1,11 @@
#include "EpubHtmlParserSlim.h" #include "ChapterHtmlSlimParser.h"
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include <HardwareSerial.h> #include <HardwareSerial.h>
#include <expat.h> #include <expat.h>
#include "Page.h" #include "../Page.h"
#include "htmlEntities.h" #include "../htmlEntities.h"
const char* HEADER_TAGS[] = {"h1", "h2", "h3", "h4", "h5", "h6"}; const char* HEADER_TAGS[] = {"h1", "h2", "h3", "h4", "h5", "h6"};
constexpr int NUM_HEADER_TAGS = sizeof(HEADER_TAGS) / sizeof(HEADER_TAGS[0]); constexpr int NUM_HEADER_TAGS = sizeof(HEADER_TAGS) / sizeof(HEADER_TAGS[0]);
@@ -25,7 +25,7 @@ constexpr int NUM_IMAGE_TAGS = sizeof(IMAGE_TAGS) / sizeof(IMAGE_TAGS[0]);
const char* SKIP_TAGS[] = {"head", "table"}; const char* SKIP_TAGS[] = {"head", "table"};
constexpr int NUM_SKIP_TAGS = sizeof(SKIP_TAGS) / sizeof(SKIP_TAGS[0]); constexpr int NUM_SKIP_TAGS = sizeof(SKIP_TAGS) / sizeof(SKIP_TAGS[0]);
bool isWhitespace(const char c) { return c == ' ' || c == '\r' || c == '\n'; } bool isWhitespace(const char c) { return c == ' ' || c == '\r' || c == '\n' || c == '\t'; }
// given the start and end of a tag, check to see if it matches a known tag // given the start and end of a tag, check to see if it matches a known tag
bool matches(const char* tag_name, const char* possible_tags[], const int possible_tag_count) { bool matches(const char* tag_name, const char* possible_tags[], const int possible_tag_count) {
@@ -38,7 +38,7 @@ bool matches(const char* tag_name, const char* possible_tags[], const int possib
} }
// start a new text block if needed // start a new text block if needed
void EpubHtmlParserSlim::startNewTextBlock(const TextBlock::BLOCK_STYLE style) { void ChapterHtmlSlimParser::startNewTextBlock(const TextBlock::BLOCK_STYLE style) {
if (currentTextBlock) { if (currentTextBlock) {
// already have a text block running and it is empty - just reuse it // already have a text block running and it is empty - just reuse it
if (currentTextBlock->isEmpty()) { if (currentTextBlock->isEmpty()) {
@@ -48,11 +48,11 @@ void EpubHtmlParserSlim::startNewTextBlock(const TextBlock::BLOCK_STYLE style) {
makePages(); makePages();
} }
currentTextBlock.reset(new ParsedText(style)); currentTextBlock.reset(new ParsedText(style, extraParagraphSpacing));
} }
void XMLCALL EpubHtmlParserSlim::startElement(void* userData, const XML_Char* name, const XML_Char** atts) { void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* name, const XML_Char** atts) {
auto* self = static_cast<EpubHtmlParserSlim*>(userData); auto* self = static_cast<ChapterHtmlSlimParser*>(userData);
(void)atts; (void)atts;
// Middle of skip // Middle of skip
@@ -62,23 +62,7 @@ void XMLCALL EpubHtmlParserSlim::startElement(void* userData, const XML_Char* na
} }
if (matches(name, IMAGE_TAGS, NUM_IMAGE_TAGS)) { if (matches(name, IMAGE_TAGS, NUM_IMAGE_TAGS)) {
// const char* src = element.Attribute("src"); // TODO: Start processing image tags
// if (src) {
// // don't leave an empty text block in the list
// // const BLOCK_STYLE style = currentTextBlock->get_style();
// if (currentTextBlock->isEmpty()) {
// delete currentTextBlock;
// currentTextBlock = nullptr;
// }
// // TODO: Fix this
// // blocks.push_back(new ImageBlock(m_base_path + src));
// // start a new text block - with the same style as before
// // startNewTextBlock(style);
// } else {
// // ESP_LOGE(TAG, "Could not find src attribute");
// }
// start skip
self->skipUntilDepth = self->depth; self->skipUntilDepth = self->depth;
self->depth += 1; self->depth += 1;
return; return;
@@ -109,8 +93,8 @@ void XMLCALL EpubHtmlParserSlim::startElement(void* userData, const XML_Char* na
self->depth += 1; self->depth += 1;
} }
void XMLCALL EpubHtmlParserSlim::characterData(void* userData, const XML_Char* s, const int len) { void XMLCALL ChapterHtmlSlimParser::characterData(void* userData, const XML_Char* s, const int len) {
auto* self = static_cast<EpubHtmlParserSlim*>(userData); auto* self = static_cast<ChapterHtmlSlimParser*>(userData);
// Middle of skip // Middle of skip
if (self->skipUntilDepth < self->depth) { if (self->skipUntilDepth < self->depth) {
@@ -149,8 +133,8 @@ void XMLCALL EpubHtmlParserSlim::characterData(void* userData, const XML_Char* s
} }
} }
void XMLCALL EpubHtmlParserSlim::endElement(void* userData, const XML_Char* name) { void XMLCALL ChapterHtmlSlimParser::endElement(void* userData, const XML_Char* name) {
auto* self = static_cast<EpubHtmlParserSlim*>(userData); auto* self = static_cast<ChapterHtmlSlimParser*>(userData);
(void)name; (void)name;
if (self->partWordBufferIndex > 0) { if (self->partWordBufferIndex > 0) {
@@ -196,7 +180,7 @@ void XMLCALL EpubHtmlParserSlim::endElement(void* userData, const XML_Char* name
} }
} }
bool EpubHtmlParserSlim::parseAndBuildPages() { bool ChapterHtmlSlimParser::parseAndBuildPages() {
startNewTextBlock(TextBlock::JUSTIFIED); startNewTextBlock(TextBlock::JUSTIFIED);
const XML_Parser parser = XML_ParserCreate(nullptr); const XML_Parser parser = XML_ParserCreate(nullptr);
@@ -261,7 +245,21 @@ bool EpubHtmlParserSlim::parseAndBuildPages() {
return true; return true;
} }
void EpubHtmlParserSlim::makePages() { void ChapterHtmlSlimParser::addLineToPage(std::shared_ptr<TextBlock> line) {
const int lineHeight = renderer.getLineHeight(fontId) * lineCompression;
const int pageHeight = GfxRenderer::getScreenHeight() - marginTop - marginBottom;
if (currentPageNextY + lineHeight > pageHeight) {
completePageFn(std::move(currentPage));
currentPage.reset(new Page());
currentPageNextY = marginTop;
}
currentPage->elements.push_back(std::make_shared<PageLine>(line, marginLeft, currentPageNextY));
currentPageNextY += lineHeight;
}
void ChapterHtmlSlimParser::makePages() {
if (!currentTextBlock) { if (!currentTextBlock) {
Serial.printf("[%lu] [EHP] !! No text block to make pages for !!\n", millis()); Serial.printf("[%lu] [EHP] !! No text block to make pages for !!\n", millis());
return; return;
@@ -273,23 +271,11 @@ void EpubHtmlParserSlim::makePages() {
} }
const int lineHeight = renderer.getLineHeight(fontId) * lineCompression; const int lineHeight = renderer.getLineHeight(fontId) * lineCompression;
const int pageHeight = GfxRenderer::getScreenHeight() - marginTop - marginBottom; currentTextBlock->layoutAndExtractLines(
renderer, fontId, marginLeft + marginRight,
// Long running task, make sure to let other things happen [this](const std::shared_ptr<TextBlock>& textBlock) { addLineToPage(textBlock); });
vTaskDelay(1); // Extra paragraph spacing if enabled
if (extraParagraphSpacing) {
const auto lines = currentTextBlock->layoutAndExtractLines(renderer, fontId, marginLeft + marginRight);
for (auto&& line : lines) {
if (currentPageNextY + lineHeight > pageHeight) {
completePageFn(std::move(currentPage));
currentPage.reset(new Page());
currentPageNextY = marginTop;
}
currentPage->elements.push_back(std::make_shared<PageLine>(line, marginLeft, currentPageNextY));
currentPageNextY += lineHeight;
}
// add some extra line between blocks
currentPageNextY += lineHeight / 2; currentPageNextY += lineHeight / 2;
} }
}
@@ -6,15 +6,15 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include "ParsedText.h" #include "../ParsedText.h"
#include "blocks/TextBlock.h" #include "../blocks/TextBlock.h"
class Page; class Page;
class GfxRenderer; class GfxRenderer;
#define MAX_WORD_SIZE 200 #define MAX_WORD_SIZE 200
class EpubHtmlParserSlim { class ChapterHtmlSlimParser {
const char* filepath; const char* filepath;
GfxRenderer& renderer; GfxRenderer& renderer;
std::function<void(std::unique_ptr<Page>)> completePageFn; std::function<void(std::unique_ptr<Page>)> completePageFn;
@@ -35,6 +35,7 @@ class EpubHtmlParserSlim {
int marginRight; int marginRight;
int marginBottom; int marginBottom;
int marginLeft; int marginLeft;
bool extraParagraphSpacing;
void startNewTextBlock(TextBlock::BLOCK_STYLE style); void startNewTextBlock(TextBlock::BLOCK_STYLE style);
void makePages(); void makePages();
@@ -44,9 +45,9 @@ class EpubHtmlParserSlim {
static void XMLCALL endElement(void* userData, const XML_Char* name); static void XMLCALL endElement(void* userData, const XML_Char* name);
public: public:
explicit EpubHtmlParserSlim(const char* filepath, GfxRenderer& renderer, const int fontId, explicit ChapterHtmlSlimParser(const char* filepath, GfxRenderer& renderer, const int fontId,
const float lineCompression, const int marginTop, const int marginRight, const float lineCompression, const int marginTop, const int marginRight,
const int marginBottom, const int marginLeft, const int marginBottom, const int marginLeft, const bool extraParagraphSpacing,
const std::function<void(std::unique_ptr<Page>)>& completePageFn) const std::function<void(std::unique_ptr<Page>)>& completePageFn)
: filepath(filepath), : filepath(filepath),
renderer(renderer), renderer(renderer),
@@ -56,7 +57,9 @@ class EpubHtmlParserSlim {
marginRight(marginRight), marginRight(marginRight),
marginBottom(marginBottom), marginBottom(marginBottom),
marginLeft(marginLeft), marginLeft(marginLeft),
extraParagraphSpacing(extraParagraphSpacing),
completePageFn(completePageFn) {} completePageFn(completePageFn) {}
~EpubHtmlParserSlim() = default; ~ChapterHtmlSlimParser() = default;
bool parseAndBuildPages(); bool parseAndBuildPages();
void addLineToPage(std::shared_ptr<TextBlock> line);
}; };
+96
View File
@@ -0,0 +1,96 @@
#include "ContainerParser.h"
#include <HardwareSerial.h>
bool ContainerParser::setup() {
parser = XML_ParserCreate(nullptr);
if (!parser) {
Serial.printf("[%lu] [CTR] Couldn't allocate memory for parser\n", millis());
return false;
}
XML_SetUserData(parser, this);
XML_SetElementHandler(parser, startElement, endElement);
return true;
}
bool ContainerParser::teardown() {
if (parser) {
XML_ParserFree(parser);
parser = nullptr;
}
return true;
}
size_t ContainerParser::write(const uint8_t data) { return write(&data, 1); }
size_t ContainerParser::write(const uint8_t* buffer, const size_t size) {
if (!parser) return 0;
const uint8_t* currentBufferPos = buffer;
auto remainingInBuffer = size;
while (remainingInBuffer > 0) {
void* const buf = XML_GetBuffer(parser, 1024);
if (!buf) {
Serial.printf("[%lu] [CTR] Couldn't allocate buffer\n", millis());
return 0;
}
const auto toRead = remainingInBuffer < 1024 ? remainingInBuffer : 1024;
memcpy(buf, currentBufferPos, toRead);
if (XML_ParseBuffer(parser, static_cast<int>(toRead), remainingSize == toRead) == XML_STATUS_ERROR) {
Serial.printf("[%lu] [CTR] Parse error: %s\n", millis(), XML_ErrorString(XML_GetErrorCode(parser)));
return 0;
}
currentBufferPos += toRead;
remainingInBuffer -= toRead;
remainingSize -= toRead;
}
return size;
}
void XMLCALL ContainerParser::startElement(void* userData, const XML_Char* name, const XML_Char** atts) {
auto* self = static_cast<ContainerParser*>(userData);
// Simple state tracking to ensure we are looking at the valid schema structure
if (self->state == START && strcmp(name, "container") == 0) {
self->state = IN_CONTAINER;
return;
}
if (self->state == IN_CONTAINER && strcmp(name, "rootfiles") == 0) {
self->state = IN_ROOTFILES;
return;
}
if (self->state == IN_ROOTFILES && strcmp(name, "rootfile") == 0) {
const char* mediaType = nullptr;
const char* path = nullptr;
for (int i = 0; atts[i]; i += 2) {
if (strcmp(atts[i], "media-type") == 0) {
mediaType = atts[i + 1];
} else if (strcmp(atts[i], "full-path") == 0) {
path = atts[i + 1];
}
}
// Check if this is the standard OEBPS package
if (mediaType && path && strcmp(mediaType, "application/oebps-package+xml") == 0) {
self->fullPath = path;
}
}
}
void XMLCALL ContainerParser::endElement(void* userData, const XML_Char* name) {
auto* self = static_cast<ContainerParser*>(userData);
if (self->state == IN_ROOTFILES && strcmp(name, "rootfiles") == 0) {
self->state = IN_CONTAINER;
} else if (self->state == IN_CONTAINER && strcmp(name, "container") == 0) {
self->state = START;
}
}
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include <Print.h>
#include <string>
#include "expat.h"
class ContainerParser final : public Print {
enum ParserState {
START,
IN_CONTAINER,
IN_ROOTFILES,
};
size_t remainingSize;
XML_Parser parser = nullptr;
ParserState state = START;
static void startElement(void* userData, const XML_Char* name, const XML_Char** atts);
static void endElement(void* userData, const XML_Char* name);
public:
std::string fullPath;
explicit ContainerParser(const size_t xmlSize) : remainingSize(xmlSize) {}
bool setup();
bool teardown();
size_t write(uint8_t) override;
size_t write(const uint8_t* buffer, size_t size) override;
};
+175
View File
@@ -0,0 +1,175 @@
#include "ContentOpfParser.h"
#include <HardwareSerial.h>
#include <ZipFile.h>
bool ContentOpfParser::setup() {
parser = XML_ParserCreate(nullptr);
if (!parser) {
Serial.printf("[%lu] [COF] Couldn't allocate memory for parser\n", millis());
return false;
}
XML_SetUserData(parser, this);
XML_SetElementHandler(parser, startElement, endElement);
XML_SetCharacterDataHandler(parser, characterData);
return true;
}
bool ContentOpfParser::teardown() {
if (parser) {
XML_ParserFree(parser);
parser = nullptr;
}
return true;
}
size_t ContentOpfParser::write(const uint8_t data) { return write(&data, 1); }
size_t ContentOpfParser::write(const uint8_t* buffer, const size_t size) {
if (!parser) return 0;
const uint8_t* currentBufferPos = buffer;
auto remainingInBuffer = size;
while (remainingInBuffer > 0) {
void* const buf = XML_GetBuffer(parser, 1024);
if (!buf) {
Serial.printf("[%lu] [COF] Couldn't allocate memory for buffer\n", millis());
XML_ParserFree(parser);
parser = nullptr;
return 0;
}
const auto toRead = remainingInBuffer < 1024 ? remainingInBuffer : 1024;
memcpy(buf, currentBufferPos, toRead);
if (XML_ParseBuffer(parser, static_cast<int>(toRead), remainingSize == toRead) == XML_STATUS_ERROR) {
Serial.printf("[%lu] [COF] Parse error at line %lu: %s\n", millis(), XML_GetCurrentLineNumber(parser),
XML_ErrorString(XML_GetErrorCode(parser)));
XML_ParserFree(parser);
parser = nullptr;
return 0;
}
currentBufferPos += toRead;
remainingInBuffer -= toRead;
remainingSize -= toRead;
}
return size;
}
void XMLCALL ContentOpfParser::startElement(void* userData, const XML_Char* name, const XML_Char** atts) {
auto* self = static_cast<ContentOpfParser*>(userData);
(void)atts;
if (self->state == START && (strcmp(name, "package") == 0 || strcmp(name, "opf:package") == 0)) {
self->state = IN_PACKAGE;
return;
}
if (self->state == IN_PACKAGE && (strcmp(name, "metadata") == 0 || strcmp(name, "opf:metadata") == 0)) {
self->state = IN_METADATA;
return;
}
if (self->state == IN_METADATA && strcmp(name, "dc:title") == 0) {
self->state = IN_BOOK_TITLE;
return;
}
if (self->state == IN_PACKAGE && (strcmp(name, "manifest") == 0 || strcmp(name, "opf:manifest") == 0)) {
self->state = IN_MANIFEST;
return;
}
if (self->state == IN_PACKAGE && (strcmp(name, "spine") == 0 || strcmp(name, "opf:spine") == 0)) {
self->state = IN_SPINE;
return;
}
if (self->state == IN_METADATA && (strcmp(name, "meta") == 0 || strcmp(name, "opf:meta") == 0)) {
bool isCover = false;
std::string coverItemId;
for (int i = 0; atts[i]; i += 2) {
if (strcmp(atts[i], "name") == 0 && strcmp(atts[i + 1], "cover") == 0) {
isCover = true;
} else if (strcmp(atts[i], "content") == 0) {
coverItemId = atts[i + 1];
}
}
if (isCover) {
self->coverItemId = coverItemId;
}
return;
}
if (self->state == IN_MANIFEST && (strcmp(name, "item") == 0 || strcmp(name, "opf:item") == 0)) {
std::string itemId;
std::string href;
for (int i = 0; atts[i]; i += 2) {
if (strcmp(atts[i], "id") == 0) {
itemId = atts[i + 1];
} else if (strcmp(atts[i], "href") == 0) {
href = self->baseContentPath + atts[i + 1];
}
}
self->items[itemId] = href;
return;
}
if (self->state == IN_SPINE && (strcmp(name, "itemref") == 0 || strcmp(name, "opf:itemref") == 0)) {
for (int i = 0; atts[i]; i += 2) {
if (strcmp(atts[i], "idref") == 0) {
self->spineRefs.emplace_back(atts[i + 1]);
break;
}
}
return;
}
}
void XMLCALL ContentOpfParser::characterData(void* userData, const XML_Char* s, const int len) {
auto* self = static_cast<ContentOpfParser*>(userData);
if (self->state == IN_BOOK_TITLE) {
self->title.append(s, len);
return;
}
}
void XMLCALL ContentOpfParser::endElement(void* userData, const XML_Char* name) {
auto* self = static_cast<ContentOpfParser*>(userData);
(void)name;
if (self->state == IN_SPINE && (strcmp(name, "spine") == 0 || strcmp(name, "opf:spine") == 0)) {
self->state = IN_PACKAGE;
return;
}
if (self->state == IN_MANIFEST && (strcmp(name, "manifest") == 0 || strcmp(name, "opf:manifest") == 0)) {
self->state = IN_PACKAGE;
return;
}
if (self->state == IN_BOOK_TITLE && strcmp(name, "dc:title") == 0) {
self->state = IN_METADATA;
return;
}
if (self->state == IN_METADATA && (strcmp(name, "metadata") == 0 || strcmp(name, "opf:metadata") == 0)) {
self->state = IN_PACKAGE;
return;
}
if (self->state == IN_PACKAGE && (strcmp(name, "package") == 0 || strcmp(name, "opf:package") == 0)) {
self->state = START;
return;
}
}
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include <Print.h>
#include <map>
#include "Epub.h"
#include "expat.h"
class ContentOpfParser final : public Print {
enum ParserState {
START,
IN_PACKAGE,
IN_METADATA,
IN_BOOK_TITLE,
IN_MANIFEST,
IN_SPINE,
};
const std::string& baseContentPath;
size_t remainingSize;
XML_Parser parser = nullptr;
ParserState state = START;
static void startElement(void* userData, const XML_Char* name, const XML_Char** atts);
static void characterData(void* userData, const XML_Char* s, int len);
static void endElement(void* userData, const XML_Char* name);
public:
std::string title;
std::string tocNcxPath;
std::string coverItemId;
std::map<std::string, std::string> items;
std::vector<std::string> spineRefs;
explicit ContentOpfParser(const std::string& baseContentPath, const size_t xmlSize)
: baseContentPath(baseContentPath), remainingSize(xmlSize) {}
bool setup();
bool teardown();
size_t write(uint8_t) override;
size_t write(const uint8_t* buffer, size_t size) override;
};
+165
View File
@@ -0,0 +1,165 @@
#include "TocNcxParser.h"
#include <HardwareSerial.h>
bool TocNcxParser::setup() {
parser = XML_ParserCreate(nullptr);
if (!parser) {
Serial.printf("[%lu] [TOC] Couldn't allocate memory for parser\n", millis());
return false;
}
XML_SetUserData(parser, this);
XML_SetElementHandler(parser, startElement, endElement);
XML_SetCharacterDataHandler(parser, characterData);
return true;
}
bool TocNcxParser::teardown() {
if (parser) {
XML_ParserFree(parser);
parser = nullptr;
}
return true;
}
size_t TocNcxParser::write(const uint8_t data) { return write(&data, 1); }
size_t TocNcxParser::write(const uint8_t* buffer, const size_t size) {
if (!parser) return 0;
const uint8_t* currentBufferPos = buffer;
auto remainingInBuffer = size;
while (remainingInBuffer > 0) {
void* const buf = XML_GetBuffer(parser, 1024);
if (!buf) {
Serial.printf("[%lu] [TOC] Couldn't allocate memory for buffer\n", millis());
return 0;
}
const auto toRead = remainingInBuffer < 1024 ? remainingInBuffer : 1024;
memcpy(buf, currentBufferPos, toRead);
if (XML_ParseBuffer(parser, static_cast<int>(toRead), remainingSize == toRead) == XML_STATUS_ERROR) {
Serial.printf("[%lu] [TOC] Parse error at line %lu: %s\n", millis(), XML_GetCurrentLineNumber(parser),
XML_ErrorString(XML_GetErrorCode(parser)));
return 0;
}
currentBufferPos += toRead;
remainingInBuffer -= toRead;
remainingSize -= toRead;
}
return size;
}
void XMLCALL TocNcxParser::startElement(void* userData, const XML_Char* name, const XML_Char** atts) {
// NOTE: We rely on navPoint label and content coming before any nested navPoints, this will be fine:
// <navPoint>
// <navLabel><text>Chapter 1</text></navLabel>
// <content src="ch1.html"/>
// <navPoint> ...nested... </navPoint>
// </navPoint>
//
// This will NOT:
// <navPoint>
// <navPoint> ...nested... </navPoint>
// <navLabel><text>Chapter 1</text></navLabel>
// <content src="ch1.html"/>
// </navPoint>
auto* self = static_cast<TocNcxParser*>(userData);
if (self->state == START && strcmp(name, "ncx") == 0) {
self->state = IN_NCX;
return;
}
if (self->state == IN_NCX && strcmp(name, "navMap") == 0) {
self->state = IN_NAV_MAP;
return;
}
// Handles both top-level and nested navPoints
if ((self->state == IN_NAV_MAP || self->state == IN_NAV_POINT) && strcmp(name, "navPoint") == 0) {
self->state = IN_NAV_POINT;
self->currentDepth++;
self->currentLabel.clear();
self->currentSrc.clear();
return;
}
if (self->state == IN_NAV_POINT && strcmp(name, "navLabel") == 0) {
self->state = IN_NAV_LABEL;
return;
}
if (self->state == IN_NAV_LABEL && strcmp(name, "text") == 0) {
self->state = IN_NAV_LABEL_TEXT;
return;
}
if (self->state == IN_NAV_POINT && strcmp(name, "content") == 0) {
for (int i = 0; atts[i]; i += 2) {
if (strcmp(atts[i], "src") == 0) {
self->currentSrc = atts[i + 1];
break;
}
}
return;
}
}
void XMLCALL TocNcxParser::characterData(void* userData, const XML_Char* s, const int len) {
auto* self = static_cast<TocNcxParser*>(userData);
if (self->state == IN_NAV_LABEL_TEXT) {
self->currentLabel.append(s, len);
}
}
void XMLCALL TocNcxParser::endElement(void* userData, const XML_Char* name) {
auto* self = static_cast<TocNcxParser*>(userData);
if (self->state == IN_NAV_LABEL_TEXT && strcmp(name, "text") == 0) {
self->state = IN_NAV_LABEL;
return;
}
if (self->state == IN_NAV_LABEL && strcmp(name, "navLabel") == 0) {
self->state = IN_NAV_POINT;
return;
}
if (self->state == IN_NAV_POINT && strcmp(name, "navPoint") == 0) {
self->currentDepth--;
if (self->currentDepth == 0) {
self->state = IN_NAV_MAP;
}
return;
}
if (self->state == IN_NAV_POINT && strcmp(name, "content") == 0) {
// At this point (end of content tag), we likely have both Label (from previous tags) and Src.
// This is the safest place to push the data, assuming <navLabel> always comes before <content>.
// NCX spec says navLabel comes before content.
if (!self->currentLabel.empty() && !self->currentSrc.empty()) {
std::string href = self->baseContentPath + self->currentSrc;
std::string anchor;
const size_t pos = href.find('#');
if (pos != std::string::npos) {
anchor = href.substr(pos + 1);
href = href.substr(0, pos);
}
// Push to vector
self->toc.emplace_back(self->currentLabel, href, anchor, self->currentDepth);
// Clear them so we don't re-add them if there are weird XML structures
self->currentLabel.clear();
self->currentSrc.clear();
}
}
}
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include <Print.h>
#include <string>
#include <vector>
#include "Epub/EpubTocEntry.h"
#include "expat.h"
class TocNcxParser final : public Print {
enum ParserState { START, IN_NCX, IN_NAV_MAP, IN_NAV_POINT, IN_NAV_LABEL, IN_NAV_LABEL_TEXT, IN_CONTENT };
const std::string& baseContentPath;
size_t remainingSize;
XML_Parser parser = nullptr;
ParserState state = START;
std::string currentLabel;
std::string currentSrc;
size_t currentDepth = 0;
static void startElement(void* userData, const XML_Char* name, const XML_Char** atts);
static void characterData(void* userData, const XML_Char* s, int len);
static void endElement(void* userData, const XML_Char* name);
public:
std::vector<EpubTocEntry> toc;
explicit TocNcxParser(const std::string& baseContentPath, const size_t xmlSize)
: baseContentPath(baseContentPath), remainingSize(xmlSize) {}
bool setup();
bool teardown();
size_t write(uint8_t) override;
size_t write(const uint8_t* buffer, size_t size) override;
};
+12 -8
View File
@@ -162,9 +162,7 @@ int GfxRenderer::getLineHeight(const int fontId) const {
return fontMap.at(fontId).getData(REGULAR)->advanceY; return fontMap.at(fontId).getData(REGULAR)->advanceY;
} }
uint8_t *GfxRenderer::getFrameBuffer() const { uint8_t* GfxRenderer::getFrameBuffer() const { return einkDisplay.getFrameBuffer(); }
return einkDisplay.getFrameBuffer();
}
void GfxRenderer::swapBuffers() const { einkDisplay.swapBuffers(); } void GfxRenderer::swapBuffers() const { einkDisplay.swapBuffers(); }
@@ -209,14 +207,20 @@ void GfxRenderer::renderChar(const EpdFontFamily& fontFamily, const uint32_t cp,
if (is2Bit) { if (is2Bit) {
const uint8_t byte = bitmap[pixelPosition / 4]; const uint8_t byte = bitmap[pixelPosition / 4];
const uint8_t bit_index = (3 - pixelPosition % 4) * 2; const uint8_t bit_index = (3 - pixelPosition % 4) * 2;
// the direct bit from the font is 0 -> white, 1 -> light gray, 2 -> dark gray, 3 -> black
// we swap this to better match the way images and screen think about colors:
// 0 -> black, 1 -> dark grey, 2 -> light grey, 3 -> white
const uint8_t bmpVal = 3 - (byte >> bit_index) & 0x3;
const uint8_t val = (byte >> bit_index) & 0x3; if (renderMode == BW && bmpVal < 3) {
if (fontRenderMode == BW && val > 0) { // Black (also paints over the grays in BW mode)
drawPixel(screenX, screenY, pixelState); drawPixel(screenX, screenY, pixelState);
} else if (fontRenderMode == GRAYSCALE_MSB && val == 1) { } else if (renderMode == GRAYSCALE_MSB && (bmpVal == 1 || bmpVal == 2)) {
// TODO: Not sure how this anti-aliasing goes on black backgrounds // Light gray (also mark the MSB if it's going to be a dark gray too)
// We have to flag pixels in reverse for the gray buffers, as 0 leave alone, 1 update
drawPixel(screenX, screenY, false); drawPixel(screenX, screenY, false);
} else if (fontRenderMode == GRAYSCALE_LSB && val == 2) { } else if (renderMode == GRAYSCALE_LSB && bmpVal == 1) {
// Dark gray
drawPixel(screenX, screenY, false); drawPixel(screenX, screenY, false);
} }
} else { } else {
+9 -7
View File
@@ -7,17 +7,17 @@
class GfxRenderer { class GfxRenderer {
public: public:
enum FontRenderMode { BW, GRAYSCALE_LSB, GRAYSCALE_MSB }; enum RenderMode { BW, GRAYSCALE_LSB, GRAYSCALE_MSB };
private: private:
EInkDisplay& einkDisplay; EInkDisplay& einkDisplay;
FontRenderMode fontRenderMode; RenderMode renderMode;
std::map<int, EpdFontFamily> fontMap; std::map<int, EpdFontFamily> fontMap;
void renderChar(const EpdFontFamily& fontFamily, uint32_t cp, int* x, const int* y, bool pixelState, void renderChar(const EpdFontFamily& fontFamily, uint32_t cp, int* x, const int* y, bool pixelState,
EpdFontStyle style) const; EpdFontStyle style) const;
public: public:
explicit GfxRenderer(EInkDisplay& einkDisplay) : einkDisplay(einkDisplay), fontRenderMode(BW) {} explicit GfxRenderer(EInkDisplay& einkDisplay) : einkDisplay(einkDisplay), renderMode(BW) {}
~GfxRenderer() = default; ~GfxRenderer() = default;
// Setup // Setup
@@ -41,15 +41,17 @@ class GfxRenderer {
int getTextWidth(int fontId, const char* text, EpdFontStyle style = REGULAR) const; int getTextWidth(int fontId, const char* text, EpdFontStyle style = REGULAR) const;
void drawCenteredText(int fontId, int y, const char* text, bool black = true, EpdFontStyle style = REGULAR) const; void drawCenteredText(int fontId, int y, const char* text, bool black = true, EpdFontStyle style = REGULAR) const;
void drawText(int fontId, int x, int y, const char* text, bool black = true, EpdFontStyle style = REGULAR) const; void drawText(int fontId, int x, int y, const char* text, bool black = true, EpdFontStyle style = REGULAR) const;
void setFontRenderMode(const FontRenderMode mode) { this->fontRenderMode = mode; }
int getSpaceWidth(int fontId) const; int getSpaceWidth(int fontId) const;
int getLineHeight(int fontId) const; int getLineHeight(int fontId) const;
// Grayscale functions
void setRenderMode(const RenderMode mode) { this->renderMode = mode; }
void copyGrayscaleLsbBuffers() const;
void copyGrayscaleMsbBuffers() const;
void displayGrayBuffer() const;
// Low level functions // Low level functions
uint8_t* getFrameBuffer() const; uint8_t* getFrameBuffer() const;
void swapBuffers() const; void swapBuffers() const;
void grayscaleRevert() const; void grayscaleRevert() const;
void copyGrayscaleLsbBuffers() const;
void copyGrayscaleMsbBuffers() const;
void displayGrayBuffer() const;
}; };
+19 -2
View File
@@ -40,7 +40,7 @@ bool ZipFile::loadFileStat(const char* filename, mz_zip_archive_file_stat* fileS
// find the file // find the file
mz_uint32 fileIndex = 0; mz_uint32 fileIndex = 0;
if (!mz_zip_reader_locate_file_v2(&zipArchive, filename, nullptr, 0, &fileIndex)) { if (!mz_zip_reader_locate_file_v2(&zipArchive, filename, nullptr, 0, &fileIndex)) {
Serial.printf("[%lu] [ZIP] Could not find file %s\n", millis, filename); Serial.printf("[%lu] [ZIP] Could not find file %s\n", millis(), filename);
mz_zip_reader_end(&zipArchive); mz_zip_reader_end(&zipArchive);
return false; return false;
} }
@@ -82,6 +82,16 @@ long ZipFile::getDataOffset(const mz_zip_archive_file_stat& fileStat) const {
return fileOffset + localHeaderSize + filenameLength + extraOffset; return fileOffset + localHeaderSize + filenameLength + extraOffset;
} }
bool ZipFile::getInflatedFileSize(const char* filename, size_t* size) const {
mz_zip_archive_file_stat fileStat;
if (!loadFileStat(filename, &fileStat)) {
return false;
}
*size = static_cast<size_t>(fileStat.m_uncomp_size);
return true;
}
uint8_t* ZipFile::readFileToMemory(const char* filename, size_t* size, const bool trailingNullByte) const { uint8_t* ZipFile::readFileToMemory(const char* filename, size_t* size, const bool trailingNullByte) const {
mz_zip_archive_file_stat fileStat; mz_zip_archive_file_stat fileStat;
if (!loadFileStat(filename, &fileStat)) { if (!loadFileStat(filename, &fileStat)) {
@@ -268,7 +278,14 @@ bool ZipFile::readFileToStream(const char* filename, Print& out, const size_t ch
// Write output chunk // Write output chunk
if (outBytes > 0) { if (outBytes > 0) {
processedOutputBytes += outBytes; processedOutputBytes += outBytes;
out.write(outputBuffer + outputCursor, outBytes); if (out.write(outputBuffer + outputCursor, outBytes) != outBytes) {
Serial.printf("[%lu] [ZIP] Failed to write all output bytes to stream\n", millis());
fclose(file);
free(outputBuffer);
free(fileReadBuffer);
free(inflator);
return false;
}
// Update output position in buffer (with wraparound) // Update output position in buffer (with wraparound)
outputCursor = (outputCursor + outBytes) & (TINFL_LZ_DICT_SIZE - 1); outputCursor = (outputCursor + outBytes) & (TINFL_LZ_DICT_SIZE - 1);
} }
+1
View File
@@ -14,6 +14,7 @@ class ZipFile {
public: public:
explicit ZipFile(std::string filePath) : filePath(std::move(filePath)) {} explicit ZipFile(std::string filePath) : filePath(std::move(filePath)) {}
~ZipFile() = default; ~ZipFile() = default;
bool getInflatedFileSize(const char* filename, size_t* size) const;
uint8_t* readFileToMemory(const char* filename, size_t* size = nullptr, bool trailingNullByte = false) const; uint8_t* readFileToMemory(const char* filename, size_t* size = nullptr, bool trailingNullByte = false) const;
bool readFileToStream(const char* filename, Print& out, size_t chunkSize) const; bool readFileToStream(const char* filename, Print& out, size_t chunkSize) const;
}; };
+4 -2
View File
@@ -1,5 +1,5 @@
[platformio] [platformio]
crosspoint_version = 0.4.0 crosspoint_version = 0.6.0
default_envs = default default_envs = default
[base] [base]
@@ -8,6 +8,9 @@ board = esp32-c3-devkitm-1
framework = arduino framework = arduino
monitor_speed = 115200 monitor_speed = 115200
upload_speed = 921600 upload_speed = 921600
check_tool = cppcheck
check_skip_packages = yes
check_severity = medium, high
board_upload.flash_size = 16MB board_upload.flash_size = 16MB
board_upload.maximum_size = 16777216 board_upload.maximum_size = 16777216
@@ -29,7 +32,6 @@ board_build.partitions = partitions.csv
; Libraries ; Libraries
lib_deps = lib_deps =
https://github.com/leethomason/tinyxml2.git#11.0.0
BatteryMonitor=symlink://open-x4-sdk/libs/hardware/BatteryMonitor BatteryMonitor=symlink://open-x4-sdk/libs/hardware/BatteryMonitor
InputManager=symlink://open-x4-sdk/libs/hardware/InputManager InputManager=symlink://open-x4-sdk/libs/hardware/InputManager
EInkDisplay=symlink://open-x4-sdk/libs/display/EInkDisplay EInkDisplay=symlink://open-x4-sdk/libs/display/EInkDisplay
+65
View File
@@ -0,0 +1,65 @@
#include "CrossPointSettings.h"
#include <HardwareSerial.h>
#include <SD.h>
#include <Serialization.h>
#include <cstdint>
#include <fstream>
// Initialize the static instance
CrossPointSettings CrossPointSettings::instance;
constexpr uint8_t SETTINGS_FILE_VERSION = 1;
constexpr uint8_t SETTINGS_COUNT = 2;
constexpr char SETTINGS_FILE[] = "/sd/.crosspoint/settings.bin";
bool CrossPointSettings::saveToFile() const {
// Make sure the directory exists
SD.mkdir("/.crosspoint");
std::ofstream outputFile(SETTINGS_FILE);
serialization::writePod(outputFile, SETTINGS_FILE_VERSION);
serialization::writePod(outputFile, SETTINGS_COUNT);
serialization::writePod(outputFile, whiteSleepScreen);
serialization::writePod(outputFile, extraParagraphSpacing);
outputFile.close();
Serial.printf("[%lu] [CPS] Settings saved to file\n", millis());
return true;
}
bool CrossPointSettings::loadFromFile() {
if (!SD.exists(SETTINGS_FILE + 3)) { // +3 to skip "/sd" prefix
Serial.printf("[%lu] [CPS] Settings file does not exist, using defaults\n", millis());
return false;
}
std::ifstream inputFile(SETTINGS_FILE);
uint8_t version;
serialization::readPod(inputFile, version);
if (version != SETTINGS_FILE_VERSION) {
Serial.printf("[%lu] [CPS] Deserialization failed: Unknown version %u\n", millis(), version);
inputFile.close();
return false;
}
uint8_t fileSettingsCount = 0;
serialization::readPod(inputFile, fileSettingsCount);
// load settings that exist
switch (fileSettingsCount) {
case 1:
serialization::readPod(inputFile, whiteSleepScreen);
break;
case 2:
serialization::readPod(inputFile, whiteSleepScreen);
serialization::readPod(inputFile, extraParagraphSpacing);
break;
}
inputFile.close();
Serial.printf("[%lu] [CPS] Settings loaded from file\n", millis());
return true;
}
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <cstdint>
#include <iosfwd>
class CrossPointSettings {
private:
// Private constructor for singleton
CrossPointSettings() = default;
// Static instance
static CrossPointSettings instance;
public:
// Delete copy constructor and assignment
CrossPointSettings(const CrossPointSettings&) = delete;
CrossPointSettings& operator=(const CrossPointSettings&) = delete;
// Sleep screen settings
uint8_t whiteSleepScreen = 0;
// Text rendering settings
uint8_t extraParagraphSpacing = 1;
~CrossPointSettings() = default;
// Get singleton instance
static CrossPointSettings& getInstance() { return instance; }
bool saveToFile() const;
bool loadFromFile();
};
// Helper macro to access settings
#define SETTINGS CrossPointSettings::getInstance()
+3 -3
View File
@@ -9,7 +9,7 @@
* "./lib/EpdFont/builtinFonts/bookerly_italic_2b.h", * "./lib/EpdFont/builtinFonts/bookerly_italic_2b.h",
* ].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)' * ].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
*/ */
#define READER_FONT_ID 1747632454 #define READER_FONT_ID 828106571
/** /**
* Generated with: * Generated with:
@@ -18,7 +18,7 @@
* "./lib/EpdFont/builtinFonts/ubuntu_bold_10.h", * "./lib/EpdFont/builtinFonts/ubuntu_bold_10.h",
* ].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)' * ].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
*/ */
#define UI_FONT_ID 225955604 #define UI_FONT_ID -56235187
/** /**
* Generated with: * Generated with:
@@ -26,4 +26,4 @@
* "./lib/EpdFont/builtinFonts/pixelarial14.h", * "./lib/EpdFont/builtinFonts/pixelarial14.h",
* ].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)' * ].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
*/ */
#define SMALL_FONT_ID 2037928017 #define SMALL_FONT_ID -1952330053
+28 -4
View File
@@ -14,12 +14,14 @@
#include <builtinFonts/ubuntu_bold_10.h> #include <builtinFonts/ubuntu_bold_10.h>
#include "Battery.h" #include "Battery.h"
#include "CrossPointSettings.h"
#include "CrossPointState.h" #include "CrossPointState.h"
#include "config.h" #include "config.h"
#include "screens/BootLogoScreen.h" #include "screens/BootLogoScreen.h"
#include "screens/EpubReaderScreen.h" #include "screens/EpubReaderScreen.h"
#include "screens/FileSelectionScreen.h" #include "screens/FileSelectionScreen.h"
#include "screens/FullScreenMessageScreen.h" #include "screens/FullScreenMessageScreen.h"
#include "screens/SettingsScreen.h"
#include "screens/SleepScreen.h" #include "screens/SleepScreen.h"
#define SPI_FQ 40000000 #define SPI_FQ 40000000
@@ -58,9 +60,11 @@ EpdFontFamily ubuntuFontFamily(&ubuntu10Font, &ubuntuBold10Font);
// Power button timing // Power button timing
// Time required to confirm boot from sleep // Time required to confirm boot from sleep
constexpr unsigned long POWER_BUTTON_WAKEUP_MS = 1000; constexpr unsigned long POWER_BUTTON_WAKEUP_MS = 500;
// Time required to enter sleep mode // Time required to enter sleep mode
constexpr unsigned long POWER_BUTTON_SLEEP_MS = 1000; constexpr unsigned long POWER_BUTTON_SLEEP_MS = 500;
// Auto-sleep timeout (10 minutes of inactivity)
constexpr unsigned long AUTO_SLEEP_TIMEOUT_MS = 10 * 60 * 1000;
std::unique_ptr<Epub> loadEpub(const std::string& path) { std::unique_ptr<Epub> loadEpub(const std::string& path) {
if (!SD.exists(path.c_str())) { if (!SD.exists(path.c_str())) {
@@ -165,9 +169,14 @@ void onSelectEpubFile(const std::string& path) {
} }
} }
void onGoToSettings() {
exitScreen();
enterNewScreen(new SettingsScreen(renderer, inputManager, onGoHome));
}
void onGoHome() { void onGoHome() {
exitScreen(); exitScreen();
enterNewScreen(new FileSelectionScreen(renderer, inputManager, onSelectEpubFile)); enterNewScreen(new FileSelectionScreen(renderer, inputManager, onSelectEpubFile, onGoToSettings));
} }
void setup() { void setup() {
@@ -199,6 +208,7 @@ void setup() {
// SD Card Initialization // SD Card Initialization
SD.begin(SD_SPI_CS, SPI, SPI_FQ); SD.begin(SD_SPI_CS, SPI, SPI_FQ);
SETTINGS.loadFromFile();
appState.loadFromFile(); appState.loadFromFile();
if (!appState.openEpubPath.empty()) { if (!appState.openEpubPath.empty()) {
auto epub = loadEpub(appState.openEpubPath); auto epub = loadEpub(appState.openEpubPath);
@@ -212,7 +222,7 @@ void setup() {
} }
exitScreen(); exitScreen();
enterNewScreen(new FileSelectionScreen(renderer, inputManager, onSelectEpubFile)); enterNewScreen(new FileSelectionScreen(renderer, inputManager, onSelectEpubFile, onGoToSettings));
// Ensure we're not still holding the power button before leaving setup // Ensure we're not still holding the power button before leaving setup
waitForPowerRelease(); waitForPowerRelease();
@@ -229,6 +239,20 @@ void loop() {
} }
inputManager.update(); inputManager.update();
// Check for any user activity (button press or release)
static unsigned long lastActivityTime = millis();
if (inputManager.wasAnyPressed() || inputManager.wasAnyReleased()) {
lastActivityTime = millis(); // Reset inactivity timer
}
if (millis() - lastActivityTime >= AUTO_SLEEP_TIMEOUT_MS) {
Serial.printf("[%lu] [SLP] Auto-sleep triggered after %lu ms of inactivity\n", millis(), AUTO_SLEEP_TIMEOUT_MS);
enterDeepSleep();
// This should never be hit as `enterDeepSleep` calls esp_deep_sleep_start
return;
}
if (inputManager.wasReleased(InputManager::BTN_POWER) && inputManager.getHeldTime() > POWER_BUTTON_WAKEUP_MS) { if (inputManager.wasReleased(InputManager::BTN_POWER) && inputManager.getHeldTime() > POWER_BUTTON_WAKEUP_MS) {
enterDeepSleep(); enterDeepSleep();
// This should never be hit as `enterDeepSleep` calls esp_deep_sleep_start // This should never be hit as `enterDeepSleep` calls esp_deep_sleep_start
@@ -0,0 +1,107 @@
#include "EpubReaderChapterSelectionScreen.h"
#include <GfxRenderer.h>
#include <SD.h>
#include "config.h"
constexpr int PAGE_ITEMS = 24;
constexpr int SKIP_PAGE_MS = 700;
void EpubReaderChapterSelectionScreen::taskTrampoline(void* param) {
auto* self = static_cast<EpubReaderChapterSelectionScreen*>(param);
self->displayTaskLoop();
}
void EpubReaderChapterSelectionScreen::onEnter() {
if (!epub) {
return;
}
renderingMutex = xSemaphoreCreateMutex();
selectorIndex = currentSpineIndex;
// Trigger first update
updateRequired = true;
xTaskCreate(&EpubReaderChapterSelectionScreen::taskTrampoline, "EpubReaderChapterSelectionScreenTask",
2048, // Stack size
this, // Parameters
1, // Priority
&displayTaskHandle // Task handle
);
}
void EpubReaderChapterSelectionScreen::onExit() {
// Wait until not rendering to delete task to avoid killing mid-instruction to EPD
xSemaphoreTake(renderingMutex, portMAX_DELAY);
if (displayTaskHandle) {
vTaskDelete(displayTaskHandle);
displayTaskHandle = nullptr;
}
vSemaphoreDelete(renderingMutex);
renderingMutex = nullptr;
}
void EpubReaderChapterSelectionScreen::handleInput() {
const bool prevReleased =
inputManager.wasReleased(InputManager::BTN_UP) || inputManager.wasReleased(InputManager::BTN_LEFT);
const bool nextReleased =
inputManager.wasReleased(InputManager::BTN_DOWN) || inputManager.wasReleased(InputManager::BTN_RIGHT);
const bool skipPage = inputManager.getHeldTime() > SKIP_PAGE_MS;
if (inputManager.wasPressed(InputManager::BTN_CONFIRM)) {
onSelectSpineIndex(selectorIndex);
} else if (inputManager.wasPressed(InputManager::BTN_BACK)) {
onGoBack();
} else if (prevReleased) {
if (skipPage) {
selectorIndex =
((selectorIndex / PAGE_ITEMS - 1) * PAGE_ITEMS + epub->getSpineItemsCount()) % epub->getSpineItemsCount();
} else {
selectorIndex = (selectorIndex + epub->getSpineItemsCount() - 1) % epub->getSpineItemsCount();
}
updateRequired = true;
} else if (nextReleased) {
if (skipPage) {
selectorIndex = ((selectorIndex / PAGE_ITEMS + 1) * PAGE_ITEMS) % epub->getSpineItemsCount();
} else {
selectorIndex = (selectorIndex + 1) % epub->getSpineItemsCount();
}
updateRequired = true;
}
}
void EpubReaderChapterSelectionScreen::displayTaskLoop() {
while (true) {
if (updateRequired) {
updateRequired = false;
xSemaphoreTake(renderingMutex, portMAX_DELAY);
renderScreen();
xSemaphoreGive(renderingMutex);
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
}
void EpubReaderChapterSelectionScreen::renderScreen() {
renderer.clearScreen();
const auto pageWidth = renderer.getScreenWidth();
renderer.drawCenteredText(READER_FONT_ID, 10, "Select Chapter", true, BOLD);
const auto pageStartIndex = selectorIndex / PAGE_ITEMS * PAGE_ITEMS;
renderer.fillRect(0, 60 + (selectorIndex % PAGE_ITEMS) * 30 + 2, pageWidth - 1, 30);
for (int i = pageStartIndex; i < epub->getSpineItemsCount() && i < pageStartIndex + PAGE_ITEMS; i++) {
const int tocIndex = epub->getTocIndexForSpineIndex(i);
if (tocIndex == -1) {
renderer.drawText(UI_FONT_ID, 20, 60 + (i % PAGE_ITEMS) * 30, "Unnamed", i != selectorIndex);
} else {
auto item = epub->getTocItem(tocIndex);
renderer.drawText(UI_FONT_ID, 20 + (item.level - 1) * 15, 60 + (i % PAGE_ITEMS) * 30, item.title.c_str(),
i != selectorIndex);
}
}
renderer.displayBuffer();
}
@@ -0,0 +1,38 @@
#pragma once
#include <Epub.h>
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
#include <freertos/task.h>
#include <memory>
#include "Screen.h"
class EpubReaderChapterSelectionScreen final : public Screen {
std::shared_ptr<Epub> epub;
TaskHandle_t displayTaskHandle = nullptr;
SemaphoreHandle_t renderingMutex = nullptr;
int currentSpineIndex = 0;
int selectorIndex = 0;
bool updateRequired = false;
const std::function<void()> onGoBack;
const std::function<void(int newSpineIndex)> onSelectSpineIndex;
static void taskTrampoline(void* param);
[[noreturn]] void displayTaskLoop();
void renderScreen();
public:
explicit EpubReaderChapterSelectionScreen(GfxRenderer& renderer, InputManager& inputManager,
const std::shared_ptr<Epub>& epub, const int currentSpineIndex,
const std::function<void()>& onGoBack,
const std::function<void(int newSpineIndex)>& onSelectSpineIndex)
: Screen(renderer, inputManager),
epub(epub),
currentSpineIndex(currentSpineIndex),
onGoBack(onGoBack),
onSelectSpineIndex(onSelectSpineIndex) {}
void onEnter() override;
void onExit() override;
void handleInput() override;
};
+73 -10
View File
@@ -5,6 +5,8 @@
#include <SD.h> #include <SD.h>
#include "Battery.h" #include "Battery.h"
#include "CrossPointSettings.h"
#include "EpubReaderChapterSelectionScreen.h"
#include "config.h" #include "config.h"
constexpr int PAGES_PER_REFRESH = 15; constexpr int PAGES_PER_REFRESH = 15;
@@ -65,6 +67,37 @@ void EpubReaderScreen::onExit() {
} }
void EpubReaderScreen::handleInput() { void EpubReaderScreen::handleInput() {
// Pass input responsibility to sub screen if exists
if (subScreen) {
subScreen->handleInput();
return;
}
// Enter chapter selection screen
if (inputManager.wasPressed(InputManager::BTN_CONFIRM)) {
// Don't start screen transition while rendering
xSemaphoreTake(renderingMutex, portMAX_DELAY);
subScreen.reset(new EpubReaderChapterSelectionScreen(
this->renderer, this->inputManager, epub, currentSpineIndex,
[this] {
subScreen->onExit();
subScreen.reset();
updateRequired = true;
},
[this](const int newSpineIndex) {
if (currentSpineIndex != newSpineIndex) {
currentSpineIndex = newSpineIndex;
nextPageNumber = 0;
section.reset();
}
subScreen->onExit();
subScreen.reset();
updateRequired = true;
}));
subScreen->onEnter();
xSemaphoreGive(renderingMutex);
}
if (inputManager.wasPressed(InputManager::BTN_BACK)) { if (inputManager.wasPressed(InputManager::BTN_BACK)) {
onGoHome(); onGoHome();
return; return;
@@ -79,6 +112,14 @@ void EpubReaderScreen::handleInput() {
return; return;
} }
// any botton press when at end of the book goes back to the last page
if (currentSpineIndex > 0 && currentSpineIndex >= epub->getSpineItemsCount()) {
currentSpineIndex = epub->getSpineItemsCount() - 1;
nextPageNumber = UINT16_MAX;
updateRequired = true;
return;
}
const bool skipChapter = inputManager.getHeldTime() > SKIP_CHAPTER_MS; const bool skipChapter = inputManager.getHeldTime() > SKIP_CHAPTER_MS;
if (skipChapter) { if (skipChapter) {
@@ -143,16 +184,29 @@ void EpubReaderScreen::renderScreen() {
return; return;
} }
if (currentSpineIndex >= epub->getSpineItemsCount() || currentSpineIndex < 0) { // edge case handling for sub-zero spine index
if (currentSpineIndex < 0) {
currentSpineIndex = 0; currentSpineIndex = 0;
} }
// based bounds of book, show end of book screen
if (currentSpineIndex > epub->getSpineItemsCount()) {
currentSpineIndex = epub->getSpineItemsCount();
}
// Show end of book screen
if (currentSpineIndex == epub->getSpineItemsCount()) {
renderer.clearScreen();
renderer.drawCenteredText(READER_FONT_ID, 300, "End of book", true, BOLD);
renderer.displayBuffer();
return;
}
if (!section) { if (!section) {
const auto filepath = epub->getSpineItem(currentSpineIndex); const auto filepath = epub->getSpineItem(currentSpineIndex);
Serial.printf("[%lu] [ERS] Loading file: %s, index: %d\n", millis(), filepath.c_str(), currentSpineIndex); Serial.printf("[%lu] [ERS] Loading file: %s, index: %d\n", millis(), filepath.c_str(), currentSpineIndex);
section = std::unique_ptr<Section>(new Section(epub, currentSpineIndex, renderer)); section = std::unique_ptr<Section>(new Section(epub, currentSpineIndex, renderer));
if (!section->loadCacheMetadata(READER_FONT_ID, lineCompression, marginTop, marginRight, marginBottom, if (!section->loadCacheMetadata(READER_FONT_ID, lineCompression, marginTop, marginRight, marginBottom, marginLeft,
marginLeft)) { SETTINGS.extraParagraphSpacing)) {
Serial.printf("[%lu] [ERS] Cache not found, building...\n", millis()); Serial.printf("[%lu] [ERS] Cache not found, building...\n", millis());
{ {
@@ -175,7 +229,7 @@ void EpubReaderScreen::renderScreen() {
section->setupCacheDir(); section->setupCacheDir();
if (!section->persistPageDataToSD(READER_FONT_ID, lineCompression, marginTop, marginRight, marginBottom, if (!section->persistPageDataToSD(READER_FONT_ID, lineCompression, marginTop, marginRight, marginBottom,
marginLeft)) { marginLeft, SETTINGS.extraParagraphSpacing)) {
Serial.printf("[%lu] [ERS] Failed to persist page data to SD\n", millis()); Serial.printf("[%lu] [ERS] Failed to persist page data to SD\n", millis());
section.reset(); section.reset();
return; return;
@@ -247,19 +301,19 @@ void EpubReaderScreen::renderContents(std::unique_ptr<Page> page) {
// TODO: Only do this if font supports it // TODO: Only do this if font supports it
{ {
renderer.clearScreen(0x00); renderer.clearScreen(0x00);
renderer.setFontRenderMode(GfxRenderer::GRAYSCALE_LSB); renderer.setRenderMode(GfxRenderer::GRAYSCALE_LSB);
page->render(renderer, READER_FONT_ID); page->render(renderer, READER_FONT_ID);
renderer.copyGrayscaleLsbBuffers(); renderer.copyGrayscaleLsbBuffers();
// Render and copy to MSB buffer // Render and copy to MSB buffer
renderer.clearScreen(0x00); renderer.clearScreen(0x00);
renderer.setFontRenderMode(GfxRenderer::GRAYSCALE_MSB); renderer.setRenderMode(GfxRenderer::GRAYSCALE_MSB);
page->render(renderer, READER_FONT_ID); page->render(renderer, READER_FONT_ID);
renderer.copyGrayscaleMsbBuffers(); renderer.copyGrayscaleMsbBuffers();
// display grayscale part // display grayscale part
renderer.displayGrayBuffer(); renderer.displayGrayBuffer();
renderer.setFontRenderMode(GfxRenderer::BW); renderer.setRenderMode(GfxRenderer::BW);
} }
} }
@@ -307,13 +361,22 @@ void EpubReaderScreen::renderStatusBar() const {
const int titleMarginLeft = 20 + percentageTextWidth + 30 + marginLeft; const int titleMarginLeft = 20 + percentageTextWidth + 30 + marginLeft;
const int titleMarginRight = progressTextWidth + 30 + marginRight; const int titleMarginRight = progressTextWidth + 30 + marginRight;
const int availableTextWidth = GfxRenderer::getScreenWidth() - titleMarginLeft - titleMarginRight; const int availableTextWidth = GfxRenderer::getScreenWidth() - titleMarginLeft - titleMarginRight;
const auto tocItem = epub->getTocItem(epub->getTocIndexForSpineIndex(currentSpineIndex)); const int tocIndex = epub->getTocIndexForSpineIndex(currentSpineIndex);
auto title = tocItem.title;
int titleWidth = renderer.getTextWidth(SMALL_FONT_ID, title.c_str()); std::string title;
int titleWidth;
if (tocIndex == -1) {
title = "Unnamed";
titleWidth = renderer.getTextWidth(SMALL_FONT_ID, "Unnamed");
} else {
const auto tocItem = epub->getTocItem(tocIndex);
title = tocItem.title;
titleWidth = renderer.getTextWidth(SMALL_FONT_ID, title.c_str());
while (titleWidth > availableTextWidth) { while (titleWidth > availableTextWidth) {
title = title.substr(0, title.length() - 8) + "..."; title = title.substr(0, title.length() - 8) + "...";
titleWidth = renderer.getTextWidth(SMALL_FONT_ID, title.c_str()); titleWidth = renderer.getTextWidth(SMALL_FONT_ID, title.c_str());
} }
}
renderer.drawText(SMALL_FONT_ID, titleMarginLeft + (availableTextWidth - titleWidth) / 2, textY, title.c_str()); renderer.drawText(SMALL_FONT_ID, titleMarginLeft + (availableTextWidth - titleWidth) / 2, textY, title.c_str());
} }
+1
View File
@@ -12,6 +12,7 @@ class EpubReaderScreen final : public Screen {
std::unique_ptr<Section> section = nullptr; std::unique_ptr<Section> section = nullptr;
TaskHandle_t displayTaskHandle = nullptr; TaskHandle_t displayTaskHandle = nullptr;
SemaphoreHandle_t renderingMutex = nullptr; SemaphoreHandle_t renderingMutex = nullptr;
std::unique_ptr<Screen> subScreen = nullptr;
int currentSpineIndex = 0; int currentSpineIndex = 0;
int nextPageNumber = 0; int nextPageNumber = 0;
int pagesUntilFullRefresh = 0; int pagesUntilFullRefresh = 0;
+9 -1
View File
@@ -91,11 +91,16 @@ void FileSelectionScreen::handleInput() {
} else { } else {
onSelect(basepath + files[selectorIndex]); onSelect(basepath + files[selectorIndex]);
} }
} else if (inputManager.wasPressed(InputManager::BTN_BACK) && basepath != "/") { } else if (inputManager.wasPressed(InputManager::BTN_BACK)) {
if (basepath != "/") {
basepath = basepath.substr(0, basepath.rfind('/')); basepath = basepath.substr(0, basepath.rfind('/'));
if (basepath.empty()) basepath = "/"; if (basepath.empty()) basepath = "/";
loadFiles(); loadFiles();
updateRequired = true; updateRequired = true;
} else {
// At root level, go to settings
onSettingsOpen();
}
} else if (prevPressed) { } else if (prevPressed) {
selectorIndex = (selectorIndex + files.size() - 1) % files.size(); selectorIndex = (selectorIndex + files.size() - 1) % files.size();
updateRequired = true; updateRequired = true;
@@ -123,6 +128,9 @@ void FileSelectionScreen::render() const {
const auto pageWidth = GfxRenderer::getScreenWidth(); const auto pageWidth = GfxRenderer::getScreenWidth();
renderer.drawCenteredText(READER_FONT_ID, 10, "CrossPoint Reader", true, BOLD); renderer.drawCenteredText(READER_FONT_ID, 10, "CrossPoint Reader", true, BOLD);
// Help text
renderer.drawText(SMALL_FONT_ID, 20, GfxRenderer::getScreenHeight() - 30, "Press BACK for Settings");
if (files.empty()) { if (files.empty()) {
renderer.drawText(UI_FONT_ID, 20, 60, "No EPUBs found"); renderer.drawText(UI_FONT_ID, 20, 60, "No EPUBs found");
} else { } else {
+4 -2
View File
@@ -17,6 +17,7 @@ class FileSelectionScreen final : public Screen {
int selectorIndex = 0; int selectorIndex = 0;
bool updateRequired = false; bool updateRequired = false;
const std::function<void(const std::string&)> onSelect; const std::function<void(const std::string&)> onSelect;
const std::function<void()> onSettingsOpen;
static void taskTrampoline(void* param); static void taskTrampoline(void* param);
[[noreturn]] void displayTaskLoop(); [[noreturn]] void displayTaskLoop();
@@ -25,8 +26,9 @@ class FileSelectionScreen final : public Screen {
public: public:
explicit FileSelectionScreen(GfxRenderer& renderer, InputManager& inputManager, explicit FileSelectionScreen(GfxRenderer& renderer, InputManager& inputManager,
const std::function<void(const std::string&)>& onSelect) const std::function<void(const std::string&)>& onSelect,
: Screen(renderer, inputManager), onSelect(onSelect) {} const std::function<void()>& onSettingsOpen)
: Screen(renderer, inputManager), onSelect(onSelect), onSettingsOpen(onSettingsOpen) {}
void onEnter() override; void onEnter() override;
void onExit() override; void onExit() override;
void handleInput() override; void handleInput() override;
+130
View File
@@ -0,0 +1,130 @@
#include "SettingsScreen.h"
#include <GfxRenderer.h>
#include "CrossPointSettings.h"
#include "config.h"
// Define the static settings list
const SettingInfo SettingsScreen::settingsList[SettingsScreen::settingsCount] = {
{"White Sleep Screen", &CrossPointSettings::whiteSleepScreen},
{"Extra Paragraph Spacing", &CrossPointSettings::extraParagraphSpacing}};
void SettingsScreen::taskTrampoline(void* param) {
auto* self = static_cast<SettingsScreen*>(param);
self->displayTaskLoop();
}
void SettingsScreen::onEnter() {
renderingMutex = xSemaphoreCreateMutex();
// Reset selection to first item
selectedSettingIndex = 0;
// Trigger first update
updateRequired = true;
xTaskCreate(&SettingsScreen::taskTrampoline, "SettingsScreenTask",
2048, // Stack size
this, // Parameters
1, // Priority
&displayTaskHandle // Task handle
);
}
void SettingsScreen::onExit() {
// Wait until not rendering to delete task to avoid killing mid-instruction to EPD
xSemaphoreTake(renderingMutex, portMAX_DELAY);
if (displayTaskHandle) {
vTaskDelete(displayTaskHandle);
displayTaskHandle = nullptr;
}
vSemaphoreDelete(renderingMutex);
renderingMutex = nullptr;
}
void SettingsScreen::handleInput() {
// Handle actions with early return
if (inputManager.wasPressed(InputManager::BTN_CONFIRM)) {
toggleCurrentSetting();
updateRequired = true;
return;
}
if (inputManager.wasPressed(InputManager::BTN_BACK)) {
SETTINGS.saveToFile();
onGoHome();
return;
}
// Handle navigation
if (inputManager.wasPressed(InputManager::BTN_UP) || inputManager.wasPressed(InputManager::BTN_LEFT)) {
// Move selection up (with wrap-around)
selectedSettingIndex = (selectedSettingIndex > 0) ? (selectedSettingIndex - 1) : (settingsCount - 1);
updateRequired = true;
} else if (inputManager.wasPressed(InputManager::BTN_DOWN) || inputManager.wasPressed(InputManager::BTN_RIGHT)) {
// Move selection down (with wrap-around)
selectedSettingIndex = (selectedSettingIndex < settingsCount - 1) ? (selectedSettingIndex + 1) : 0;
updateRequired = true;
}
}
void SettingsScreen::toggleCurrentSetting() {
// Validate index
if (selectedSettingIndex < 0 || selectedSettingIndex >= settingsCount) {
return;
}
// Toggle the boolean value using the member pointer
bool currentValue = SETTINGS.*(settingsList[selectedSettingIndex].valuePtr);
SETTINGS.*(settingsList[selectedSettingIndex].valuePtr) = !currentValue;
// Save settings when they change
SETTINGS.saveToFile();
}
void SettingsScreen::displayTaskLoop() {
while (true) {
if (updateRequired) {
updateRequired = false;
xSemaphoreTake(renderingMutex, portMAX_DELAY);
render();
xSemaphoreGive(renderingMutex);
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
}
void SettingsScreen::render() const {
renderer.clearScreen();
const auto pageWidth = GfxRenderer::getScreenWidth();
const auto pageHeight = GfxRenderer::getScreenHeight();
// Draw header
renderer.drawCenteredText(READER_FONT_ID, 10, "Settings", true, BOLD);
// We always have at least one setting
// Draw all settings
for (int i = 0; i < settingsCount; i++) {
const int settingY = 60 + i * 30; // 30 pixels between settings
// Draw selection indicator for the selected setting
if (i == selectedSettingIndex) {
renderer.drawText(UI_FONT_ID, 5, settingY, ">");
}
// Draw setting name and value
renderer.drawText(UI_FONT_ID, 20, settingY, settingsList[i].name);
bool value = SETTINGS.*(settingsList[i].valuePtr);
renderer.drawText(UI_FONT_ID, pageWidth - 80, settingY, value ? "ON" : "OFF");
}
// Draw help text
renderer.drawText(SMALL_FONT_ID, 20, pageHeight - 30, "Press OK to toggle, BACK to save & exit");
// Always use standard refresh for settings screen
renderer.displayBuffer();
}
+42
View File
@@ -0,0 +1,42 @@
#pragma once
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
#include <freertos/task.h>
#include <cstdint>
#include <string>
#include <vector>
#include "Screen.h"
class CrossPointSettings;
// Structure to hold setting information
struct SettingInfo {
const char* name; // Display name of the setting
uint8_t CrossPointSettings::* valuePtr; // Pointer to member in CrossPointSettings
};
class SettingsScreen final : public Screen {
TaskHandle_t displayTaskHandle = nullptr;
SemaphoreHandle_t renderingMutex = nullptr;
bool updateRequired = false;
int selectedSettingIndex = 0; // Currently selected setting
const std::function<void()> onGoHome;
// Static settings list
static constexpr int settingsCount = 2; // Number of settings
static const SettingInfo settingsList[settingsCount];
static void taskTrampoline(void* param);
[[noreturn]] void displayTaskLoop();
void render() const;
void toggleCurrentSetting();
public:
explicit SettingsScreen(GfxRenderer& renderer, InputManager& inputManager, const std::function<void()>& onGoHome)
: Screen(renderer, inputManager), onGoHome(onGoHome) {}
void onEnter() override;
void onExit() override;
void handleInput() override;
};
+6
View File
@@ -2,6 +2,7 @@
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include "CrossPointSettings.h"
#include "config.h" #include "config.h"
#include "images/CrossLarge.h" #include "images/CrossLarge.h"
@@ -13,6 +14,11 @@ void SleepScreen::onEnter() {
renderer.drawImage(CrossLarge, (pageWidth - 128) / 2, (pageHeight - 128) / 2, 128, 128); renderer.drawImage(CrossLarge, (pageWidth - 128) / 2, (pageHeight - 128) / 2, 128, 128);
renderer.drawCenteredText(UI_FONT_ID, pageHeight / 2 + 70, "CrossPoint", true, BOLD); renderer.drawCenteredText(UI_FONT_ID, pageHeight / 2 + 70, "CrossPoint", true, BOLD);
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight / 2 + 95, "SLEEPING"); renderer.drawCenteredText(SMALL_FONT_ID, pageHeight / 2 + 95, "SLEEPING");
// Apply white screen if enabled in settings
if (!SETTINGS.whiteSleepScreen) {
renderer.invertScreen(); renderer.invertScreen();
}
renderer.displayBuffer(EInkDisplay::HALF_REFRESH); renderer.displayBuffer(EInkDisplay::HALF_REFRESH);
} }