Aleo, Noto Sans, Open Dyslexic fonts (#163)

## Summary

* Swap out Bookerly font due to licensing issues, replace default font
with Aleo
* I did a bunch of searching around for a nice replacement font, and
this trumped several other like Literata, Merriwether, Vollkorn, etc
* Add Noto Sans, and Open Dyslexic as font options
  * They can be selected in the settings screen
* Add font size options (Small, Medium, Large, Extra Large)
  * Adjustable in settings
* Swap out uses of reader font in headings and replaced with slightly
larger Ubuntu font
* Replaced PixelArial14 font as it was difficult to track down, replace
with Space Grotesk
* Remove auto formatting on generated font files
* Massively speeds up formatting step now that there is a lot more CPP
font source
* Include fonts with their licenses in the repo

## Additional Context

Line compression setting will follow

| Font | Small | Medium | Large | X Large |
| --- | --- | --- | --- | --- |
| Aleo |
![IMG_5704](https://github.com/user-attachments/assets/7acb054f-ddef-4080-b3c8-590cfaf13115)
|
![IMG_5705](https://github.com/user-attachments/assets/d4819036-5c89-486e-92c3-86094fa4d89a)
|
![IMG_5706](https://github.com/user-attachments/assets/35caf622-d126-4396-9c3e-f927eba1e1f4)
|
![IMG_5707](https://github.com/user-attachments/assets/af32370a-6244-400f-bea9-5c27db040b5b)
|
| Noto Sans |
![IMG_5708](https://github.com/user-attachments/assets/1f9264a5-c069-4e22-9099-a082bfcaabc5)
|
![IMG_5709](https://github.com/user-attachments/assets/ef6b07fe-8d87-403a-b152-05f50b69b78e)
|
![IMG_5710](https://github.com/user-attachments/assets/112a5d20-262c-4dc0-b67d-980b237e4607)
|
![IMG_5711](https://github.com/user-attachments/assets/d25e0e1d-2ace-450d-96dd-618e4efd4805)
|
| Open Dyslexic |
![IMG_5712](https://github.com/user-attachments/assets/ead64690-f261-4fae-a4a2-0becd1162e2d)
|
![IMG_5713](https://github.com/user-attachments/assets/59d60f7d-5142-4591-96b0-c04e0a4c6436)
|
![IMG_5714](https://github.com/user-attachments/assets/bb6652cd-1790-46a3-93ea-2b8f70d0d36d)
|
![IMG_5715](https://github.com/user-attachments/assets/496e7eb4-c81a-4232-83e9-9ba9148fdea4)
|
This commit is contained in:
Dave Allie 2025-12-30 18:21:47 +10:00 committed by GitHub
parent 9f31f80c80
commit bf7bffd506
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
104 changed files with 211365 additions and 20841 deletions

View File

@ -1,26 +1,19 @@
#!/bin/bash #!/bin/bash
# Configuration: Standard arguments for clang-format GIT_LS_FILES_FLAGS=""
STYLE_ARGS="-style=file -i" if [[ "$1" == "-g" ]]; then
GIT_LS_FILES_FLAGS="--modified"
fi
# --- Main Logic --- # --- Main Logic ---
if [[ "$1" == "-g" ]]; then # Format all files (or only modified files if -g is passed)
# Mode: Format all modified files (staged and unstaged)
# Use 'git ls-files' to get a list of all files with pending changes: # Use 'git ls-files' to get a list of all files tracked by git:
# --modified: files tracked by git that have been modified (staged or unstaged) # --modified: files tracked by git that have been modified (staged or unstaged)
# --exclude-standard: ignores files in .gitignore # --exclude-standard: ignores files in .gitignore
git ls-files --modified --exclude-standard \ # Additionally exclude files in 'lib/EpdFont/builtinFonts/' as they are script-generated.
git ls-files --exclude-standard ${GIT_LS_FILES_FLAGS} \
| grep -E '\.(c|cpp|h|hpp)$' \ | grep -E '\.(c|cpp|h|hpp)$' \
| xargs -r clang-format $STYLE_ARGS | grep -v -E '^lib/EpdFont/builtinFonts/' \
| xargs -r clang-format -style=file -i
# NOTE: We skip the 'git add' step from before.
# When running on unstaged files, 'clang-format -i' modifies them
# in the working directory, where they remain unstaged (M).
else
# Executes original working command directly.
find src lib \( -name "*.c" -o -name "*.cpp" -o -name "*.h" -o -name "*.hpp" \) -exec clang-format $STYLE_ARGS {} +
fi

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
#pragma once
#include <builtinFonts/aleo_12_bold.h>
#include <builtinFonts/aleo_12_bolditalic.h>
#include <builtinFonts/aleo_12_italic.h>
#include <builtinFonts/aleo_12_regular.h>
#include <builtinFonts/aleo_14_bold.h>
#include <builtinFonts/aleo_14_bolditalic.h>
#include <builtinFonts/aleo_14_italic.h>
#include <builtinFonts/aleo_14_regular.h>
#include <builtinFonts/aleo_16_bold.h>
#include <builtinFonts/aleo_16_bolditalic.h>
#include <builtinFonts/aleo_16_italic.h>
#include <builtinFonts/aleo_16_regular.h>
#include <builtinFonts/aleo_18_bold.h>
#include <builtinFonts/aleo_18_bolditalic.h>
#include <builtinFonts/aleo_18_italic.h>
#include <builtinFonts/aleo_18_regular.h>
#include <builtinFonts/notosans_12_bold.h>
#include <builtinFonts/notosans_12_bolditalic.h>
#include <builtinFonts/notosans_12_italic.h>
#include <builtinFonts/notosans_12_regular.h>
#include <builtinFonts/notosans_14_bold.h>
#include <builtinFonts/notosans_14_bolditalic.h>
#include <builtinFonts/notosans_14_italic.h>
#include <builtinFonts/notosans_14_regular.h>
#include <builtinFonts/notosans_16_bold.h>
#include <builtinFonts/notosans_16_bolditalic.h>
#include <builtinFonts/notosans_16_italic.h>
#include <builtinFonts/notosans_16_regular.h>
#include <builtinFonts/notosans_18_bold.h>
#include <builtinFonts/notosans_18_bolditalic.h>
#include <builtinFonts/notosans_18_italic.h>
#include <builtinFonts/notosans_18_regular.h>
#include <builtinFonts/opendyslexic_10_bold.h>
#include <builtinFonts/opendyslexic_10_bolditalic.h>
#include <builtinFonts/opendyslexic_10_italic.h>
#include <builtinFonts/opendyslexic_10_regular.h>
#include <builtinFonts/opendyslexic_12_bold.h>
#include <builtinFonts/opendyslexic_12_bolditalic.h>
#include <builtinFonts/opendyslexic_12_italic.h>
#include <builtinFonts/opendyslexic_12_regular.h>
#include <builtinFonts/opendyslexic_14_bold.h>
#include <builtinFonts/opendyslexic_14_bolditalic.h>
#include <builtinFonts/opendyslexic_14_italic.h>
#include <builtinFonts/opendyslexic_14_regular.h>
#include <builtinFonts/opendyslexic_8_bold.h>
#include <builtinFonts/opendyslexic_8_bolditalic.h>
#include <builtinFonts/opendyslexic_8_italic.h>
#include <builtinFonts/opendyslexic_8_regular.h>
#include <builtinFonts/spacegrotesk.h>
#include <builtinFonts/ubuntu_10_bold.h>
#include <builtinFonts/ubuntu_10_regular.h>
#include <builtinFonts/ubuntu_12_bold.h>
#include <builtinFonts/ubuntu_12_regular.h>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,93 @@
Copyright 2018 The Aleo Project Authors (https://github.com/AlessioLaiso/aleo)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View File

@ -0,0 +1,93 @@
Copyright 2022 The Noto Project Authors (https://github.com/notofonts/latin-greek-cyrillic)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View File

@ -0,0 +1,94 @@
Copyright (c) 2019-07-29, Abbie Gonzalez (https://abbiecod.es|support@abbiecod.es),
with Reserved Font Name OpenDyslexic.
Copyright (c) 12/2012 - 2019
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View File

@ -0,0 +1,93 @@
Copyright 2020 The Space Grotesk Project Authors (https://github.com/floriankarsten/space-grotesk)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View File

@ -0,0 +1,96 @@
-------------------------------
UBUNTU FONT LICENCE Version 1.0
-------------------------------
PREAMBLE
This licence allows the licensed fonts to be used, studied, modified and
redistributed freely. The fonts, including any derivative works, can be
bundled, embedded, and redistributed provided the terms of this licence
are met. The fonts and derivatives, however, cannot be released under
any other licence. The requirement for fonts to remain under this
licence does not require any document created using the fonts or their
derivatives to be published under this licence, as long as the primary
purpose of the document is not to be a vehicle for the distribution of
the fonts.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this licence and clearly marked as such. This may
include source files, build scripts and documentation.
"Original Version" refers to the collection of Font Software components
as received under this licence.
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to
a new environment.
"Copyright Holder(s)" refers to all individuals and companies who have a
copyright ownership of the Font Software.
"Substantially Changed" refers to Modified Versions which can be easily
identified as dissimilar to the Font Software by users of the Font
Software comparing the Original Version with the Modified Version.
To "Propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification and with or without charging
a redistribution fee), making available to the public, and in some
countries other activities as well.
PERMISSION & CONDITIONS
This licence does not grant any rights under trademark law and all such
rights are reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of the Font Software, to propagate the Font Software, subject to
the below conditions:
1) Each copy of the Font Software must contain the above copyright
notice and this licence. These can be included either as stand-alone
text files, human-readable headers or in the appropriate machine-
readable metadata fields within text or binary files as long as those
fields can be easily viewed by the user.
2) The font name complies with the following:
(a) The Original Version must retain its name, unmodified.
(b) Modified Versions which are Substantially Changed must be renamed to
avoid use of the name of the Original Version or similar names entirely.
(c) Modified Versions which are not Substantially Changed must be
renamed to both (i) retain the name of the Original Version and (ii) add
additional naming elements to distinguish the Modified Version from the
Original Version. The name of such Modified Versions must be the name of
the Original Version, with "derivative X" where X represents the name of
the new work, appended to that name.
3) The name(s) of the Copyright Holder(s) and any contributor to the
Font Software shall not be used to promote, endorse or advertise any
Modified Version, except (i) as required by this licence, (ii) to
acknowledge the contribution(s) of the Copyright Holder(s) or (iii) with
their explicit written permission.
4) The Font Software, modified or unmodified, in part or in whole, must
be distributed entirely under this licence, and must not be distributed
under any other licence. The requirement for fonts to remain under this
licence does not affect any document created using the Font Software,
except any version of the Font Software extracted from a document
created using the Font Software may only be distributed under this
licence.
TERMINATION
This licence becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

View File

@ -0,0 +1,826 @@
/**
* generated by fontconvert.py
* name: spacegrotesk
* size: 8
* mode: 1-bit
*/
#pragma once
#include "EpdFontData.h"
static const uint8_t spacegroteskBitmaps[5331] = {
0x66, 0x66, 0x66, 0x66, 0x60, 0x67, 0x20, 0x00, 0xF9, 0xF1, 0xA6, 0xC0, 0x00, 0x33, 0x0C, 0xC3,
0x31, 0xFF, 0xFF, 0xCC, 0xC3, 0x33, 0xFF, 0xFF, 0xCC, 0xC3, 0x30, 0xCC, 0x0C, 0x03, 0x03, 0xF1,
0xFE, 0x6D, 0x9B, 0x77, 0xC8, 0xF8, 0x1F, 0x93, 0x7E, 0xCD, 0xB3, 0x7F, 0x8F, 0xE0, 0xC0, 0x30,
0x78, 0x37, 0xE3, 0x33, 0x39, 0x9B, 0x87, 0xD8, 0x1D, 0x80, 0x19, 0x01, 0xFE, 0x1D, 0xB8, 0xCC,
0xCC, 0x66, 0xC3, 0xE0, 0x04, 0x00, 0x3E, 0x1F, 0x86, 0x03, 0x84, 0x63, 0x1F, 0xF7, 0xFD, 0x8C,
0xC3, 0x38, 0xC7, 0xF0, 0xFC, 0x06, 0x73, 0x60, 0x19, 0xEE, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C,
0x30, 0xC3, 0x0E, 0x1E, 0x3C, 0xC3, 0xC3, 0x86, 0x1C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x61,
0xBC, 0xE0, 0x08, 0x6A, 0x3E, 0xFF, 0x7F, 0x3E, 0x6A, 0x08, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0x18,
0x18, 0x18, 0x06, 0x73, 0x60, 0xFF, 0xE0, 0x06, 0x72, 0x0C, 0x18, 0x30, 0xE1, 0x83, 0x06, 0x18,
0x30, 0x61, 0x83, 0x06, 0x18, 0x30, 0x40, 0x3E, 0x3F, 0xB0, 0xF8, 0x3C, 0x1E, 0x0F, 0x07, 0x83,
0xC1, 0xE0, 0xF9, 0xCF, 0xE1, 0x80, 0x1C, 0xF7, 0xDB, 0xEF, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x3F,
0x1F, 0xE6, 0x19, 0x87, 0x41, 0xC0, 0x60, 0xF8, 0xF8, 0x70, 0x18, 0x07, 0xF9, 0xFF, 0x7F, 0x9F,
0xF0, 0x38, 0x3C, 0x1C, 0x07, 0xC1, 0xF8, 0x06, 0xC1, 0xD8, 0x67, 0x38, 0xFC, 0x0C, 0x00, 0x07,
0x03, 0xC0, 0xF0, 0x6C, 0x3B, 0x0C, 0xC6, 0x33, 0x8C, 0xFF, 0xFF, 0xF0, 0x30, 0x0C, 0x7F, 0x9F,
0xE6, 0x01, 0x80, 0x7F, 0x1F, 0xE7, 0x18, 0x07, 0x61, 0xD8, 0x67, 0x38, 0xFC, 0x0C, 0x00, 0x7E,
0x7F, 0xB0, 0xD8, 0x3F, 0xE7, 0xFB, 0x0D, 0x83, 0xC1, 0xE1, 0xF9, 0xCF, 0xC1, 0x80, 0xFF, 0xFF,
0xC0, 0x60, 0x60, 0x30, 0x30, 0x38, 0x18, 0x1C, 0x0C, 0x0E, 0x06, 0x00, 0x3F, 0x1F, 0xE6, 0x1D,
0x83, 0x61, 0xCF, 0xE7, 0xF9, 0x87, 0xE0, 0xF8, 0x37, 0x3C, 0xFE, 0x0C, 0x00, 0x3F, 0x1F, 0xE6,
0x19, 0x87, 0xE1, 0xD8, 0x77, 0xFC, 0xFF, 0x41, 0xD8, 0x67, 0x38, 0xFC, 0x0C, 0x00, 0x06, 0x72,
0x00, 0x06, 0x72, 0x06, 0x72, 0x00, 0x06, 0x73, 0x60, 0x01, 0x0F, 0x3E, 0xF0, 0xF0, 0x7C, 0x1F,
0x03, 0xFF, 0xFF, 0x7F, 0xFF, 0x00, 0xC0, 0xF0, 0x7E, 0x0F, 0x07, 0x3E, 0xF8, 0xC0, 0x3F, 0x3F,
0xD8, 0x78, 0x34, 0x18, 0x3C, 0x3C, 0x18, 0x0C, 0x00, 0x07, 0x03, 0x80, 0x80, 0x0F, 0xE0, 0x3F,
0xF0, 0xE0, 0x73, 0x18, 0x6E, 0x7F, 0x79, 0xDE, 0xF3, 0x1D, 0xEE, 0x1B, 0xDC, 0x37, 0x98, 0xEF,
0x3B, 0xFB, 0x3F, 0xE7, 0x10, 0x07, 0x80, 0x07, 0xFC, 0x01, 0xF0, 0x0E, 0x03, 0xC0, 0x7C, 0x0D,
0x83, 0xB0, 0x66, 0x0C, 0x63, 0xFC, 0x7F, 0x8C, 0x39, 0x83, 0x60, 0x60, 0xFF, 0x9F, 0xF8, 0xC3,
0x18, 0x63, 0x0C, 0x7F, 0x8F, 0xE1, 0x86, 0x30, 0xC6, 0x19, 0xFF, 0x7F, 0xC0, 0x3E, 0x3F, 0xB8,
0x78, 0x3C, 0x1E, 0x03, 0x01, 0x83, 0xC1, 0xE0, 0xFD, 0xEF, 0xE1, 0xC0, 0xFF, 0x1F, 0xF0, 0xC7,
0x18, 0x63, 0x0E, 0x61, 0xCC, 0x39, 0x87, 0x30, 0xC6, 0x19, 0xFF, 0x7F, 0xC0, 0xFF, 0xFF, 0xC0,
0xC0, 0xC0, 0xFE, 0xFE, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xFE, 0xFE,
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x3E, 0x3F, 0xB8, 0x78, 0x3C, 0x1E, 0x03, 0x3F, 0x9F, 0xC1, 0xE0,
0xFD, 0xEF, 0xF1, 0x80, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1F, 0xFF, 0xFF, 0x83, 0xC1, 0xE0, 0xF0,
0x78, 0x30, 0xFF, 0xFF, 0xFF, 0x0F, 0x83, 0xE0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x33, 0x0C, 0xC3,
0x38, 0xC7, 0x71, 0xF8, 0x18, 0x00, 0xC3, 0xE3, 0xB3, 0x9B, 0x8F, 0x87, 0x83, 0xC1, 0xF0, 0xDC,
0x67, 0x31, 0xD8, 0x70, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF,
0xE0, 0x77, 0x83, 0xBC, 0x3D, 0xE1, 0xEF, 0x8F, 0x6C, 0x7B, 0x66, 0xDB, 0x36, 0xCD, 0xB6, 0x7D,
0xB3, 0xCD, 0x9E, 0x60, 0xE1, 0xF8, 0xFC, 0x7F, 0x3D, 0x9E, 0xCF, 0x37, 0x9B, 0xCF, 0xE3, 0xF1,
0xF8, 0xF0, 0x3E, 0x1F, 0xEE, 0x1B, 0x06, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xB0, 0x6F, 0x79,
0xFC, 0x1C, 0x00, 0xFE, 0x7F, 0xB0, 0xF8, 0x3C, 0x1E, 0x1B, 0xFD, 0xF8, 0xC0, 0x60, 0x30, 0x18,
0x00, 0x3E, 0x1F, 0xEE, 0x1B, 0x06, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xB0, 0x6F, 0x79, 0xFC,
0x1C, 0x03, 0x80, 0xE0, 0xFE, 0x7F, 0xB0, 0x78, 0x3C, 0x1E, 0x1F, 0xFD, 0xFF, 0xC3, 0xE1, 0xF0,
0xF8, 0x70, 0x3F, 0x1F, 0xE6, 0x19, 0x87, 0x70, 0x8F, 0x81, 0xF9, 0x07, 0xE0, 0xD8, 0x37, 0x38,
0xFE, 0x0C, 0x00, 0xFF, 0xFF, 0xF0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00,
0xC0, 0x30, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xFD, 0xEF, 0xE1,
0xC0, 0xC0, 0xF8, 0x36, 0x1D, 0x86, 0x61, 0x8C, 0x63, 0x30, 0xCC, 0x1B, 0x07, 0xC1, 0xE0, 0x78,
0xC3, 0x8F, 0x9E, 0x36, 0x78, 0xD9, 0xB3, 0x66, 0xCD, 0x9B, 0x76, 0xED, 0x9B, 0x36, 0x3C, 0xF8,
0xF1, 0xE3, 0xC7, 0x8F, 0x1E, 0xE0, 0xCC, 0x38, 0xC6, 0x1D, 0x81, 0xF0, 0x3C, 0x03, 0x80, 0xF8,
0x3B, 0x06, 0x31, 0xC7, 0x70, 0x60, 0xC0, 0xF8, 0x76, 0x18, 0xCE, 0x3B, 0x07, 0x81, 0xE0, 0x30,
0x0C, 0x03, 0x00, 0xC0, 0x30, 0x7F, 0xBF, 0xC0, 0xE0, 0x60, 0x60, 0x70, 0x70, 0x70, 0x30, 0x30,
0x3F, 0xFF, 0xF0, 0x77, 0xF1, 0x8C, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x1E, 0xF8, 0x60, 0x60,
0x60, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x0C, 0x0C, 0x0C, 0x06, 0x06, 0x06, 0x02, 0xF7, 0xC6,
0x31, 0x8C, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x7F, 0xF0, 0x1C, 0x1E, 0x1D, 0x8C, 0xEC, 0x30, 0xFF,
0x7F, 0x80, 0x00, 0x67, 0x30, 0x1C, 0x0F, 0xC6, 0x31, 0x8C, 0x3F, 0x1F, 0xCE, 0x31, 0x9E, 0x7F,
0xC6, 0x00, 0xC0, 0x60, 0x30, 0x1B, 0x8F, 0xF7, 0x1F, 0x07, 0x83, 0xC1, 0xE0, 0xFC, 0xFF, 0xE0,
0xC0, 0x0E, 0x0F, 0xC7, 0x39, 0x86, 0x60, 0x18, 0x06, 0x19, 0xCE, 0x3F, 0x03, 0x00, 0x00, 0xC0,
0x30, 0x0C, 0x73, 0x3F, 0xDC, 0x76, 0x1D, 0x83, 0x60, 0xD8, 0x77, 0x3C, 0xFF, 0x0C, 0x00, 0x0E,
0x1F, 0x9C, 0xEC, 0x37, 0xFB, 0xFD, 0x86, 0xE7, 0x3F, 0x06, 0x00, 0x1E, 0x3C, 0x63, 0xFF, 0xE3,
0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x1C, 0x8F, 0xF7, 0x1D, 0x87, 0x60, 0xD8, 0x36, 0x1D, 0xEF,
0x3F, 0xC0, 0x30, 0x0C, 0xFF, 0x3F, 0x80, 0xC0, 0xC0, 0xC0, 0xDC, 0xFE, 0xE3, 0xC3, 0xC3, 0xC3,
0xC3, 0xC3, 0xC3, 0xDB, 0x0D, 0xB6, 0xDB, 0x60, 0x31, 0x8C, 0x03, 0x18, 0xC6, 0x31, 0x8C, 0x63,
0x1B, 0xCC, 0xC0, 0xC0, 0xC0, 0xC2, 0xCE, 0xDC, 0xF8, 0xF0, 0xF0, 0xD8, 0xCE, 0xC7, 0xFF, 0xFF,
0xFF, 0x18, 0xC7, 0xFF, 0xB9, 0xCD, 0x8C, 0x6C, 0x63, 0x63, 0x1B, 0x18, 0xD8, 0xC6, 0xC6, 0x30,
0x1C, 0xFE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x0E, 0x0F, 0xC7, 0x39, 0x87, 0x60, 0xD8,
0x36, 0x19, 0xCE, 0x3F, 0x03, 0x00, 0x1C, 0x7F, 0xB8, 0xF8, 0x3C, 0x1E, 0x0F, 0x07, 0xE7, 0xFF,
0x66, 0x30, 0x18, 0x0C, 0x00, 0x1C, 0x8F, 0xF7, 0x1D, 0x87, 0x60, 0xD8, 0x36, 0x1D, 0xCF, 0x3F,
0xC3, 0x30, 0x0C, 0x03, 0x00, 0x80, 0x1F, 0xF9, 0x8C, 0x63, 0x18, 0xC0, 0x1C, 0x7E, 0x63, 0x62,
0x7E, 0x1F, 0x63, 0x63, 0x3F, 0x0C, 0x00, 0x30, 0x63, 0xFF, 0xE3, 0x06, 0x0C, 0x18, 0x30, 0x70,
0xF0, 0x01, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7F, 0x10, 0x41, 0x71, 0xD8, 0xCC, 0x67,
0x71, 0xB0, 0xD8, 0x38, 0x1C, 0x00, 0x42, 0x13, 0x38, 0xD9, 0xEE, 0xCF, 0x66, 0xDB, 0x36, 0xD8,
0xF3, 0xC7, 0x9E, 0x38, 0xE0, 0x40, 0x98, 0x63, 0x30, 0xF8, 0x1E, 0x07, 0x83, 0xF1, 0xCC, 0x61,
0x80, 0x01, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7F, 0x13, 0x03, 0x7F, 0x7E, 0xFD, 0xFC,
0x38, 0xE3, 0x8E, 0x38, 0x7E, 0xFE, 0x1E, 0x3C, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0xF1, 0xE0, 0x60,
0xC1, 0x83, 0x06, 0x0F, 0x1E, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF1, 0xF0, 0x60, 0xC1, 0x83, 0x06,
0x0C, 0x1E, 0x3C, 0x60, 0xC1, 0x83, 0x06, 0x7C, 0xF0, 0x10, 0x7B, 0xFF, 0x4C, 0x67, 0x60, 0x66,
0x66, 0x66, 0x66, 0x60, 0x08, 0x0C, 0x07, 0x0F, 0xCF, 0xF6, 0xDB, 0x61, 0xB0, 0xDB, 0x7F, 0x9F,
0x83, 0x01, 0x80, 0x1F, 0x0F, 0xE3, 0x1C, 0xC3, 0x30, 0xDF, 0x07, 0xC0, 0xC0, 0x30, 0x0C, 0x07,
0xF9, 0xFF, 0x00, 0x1F, 0xF7, 0xF9, 0x86, 0x60, 0xD8, 0x36, 0x19, 0xCE, 0x7F, 0xD3, 0x20, 0xC0,
0xCC, 0x39, 0xC6, 0x19, 0xC3, 0xB0, 0x3C, 0x1F, 0xE1, 0xFC, 0x7F, 0x87, 0xF0, 0x30, 0x06, 0x00,
0xFF, 0xFF, 0x0F, 0xFF, 0xF0, 0x3E, 0x7E, 0x63, 0x62, 0x7C, 0x7E, 0x7B, 0x3F, 0x47, 0xC3, 0x67,
0x7E, 0x18, 0x6C, 0xD9, 0xB0, 0x3F, 0x1F, 0xEC, 0xDF, 0x7B, 0xF3, 0xFC, 0xBF, 0x0F, 0xCF, 0xFE,
0xF7, 0xB6, 0x39, 0xFC, 0x0C, 0x00, 0x78, 0xD8, 0xF3, 0xEC, 0xCF, 0xCC, 0x00, 0x0C, 0x63, 0xBD,
0xEE, 0x73, 0x87, 0x70, 0x77, 0x87, 0x38, 0x23, 0xFF, 0xFF, 0x03, 0x03, 0xFF, 0xE0, 0x3E, 0x7F,
0x5D, 0x5D, 0x55, 0x77, 0x3E, 0x00, 0x7C, 0xF8, 0x7B, 0xFC, 0xF3, 0x78, 0x40, 0x08, 0x18, 0x18,
0xFF, 0xFF, 0x18, 0x18, 0x18, 0x7F, 0xFF, 0x01, 0xEC, 0xC3, 0x7B, 0x8F, 0xC0, 0xFC, 0x73, 0x8F,
0xCD, 0xF3, 0x00, 0x36, 0x60, 0x00, 0x61, 0xB0, 0xD8, 0x6C, 0x36, 0x1B, 0x0D, 0xCE, 0xFF, 0xE8,
0x30, 0x18, 0x0C, 0x00, 0x3F, 0xBF, 0xF3, 0x79, 0xBC, 0xDB, 0xED, 0xF6, 0x1B, 0x0D, 0x86, 0xC3,
0x61, 0xB0, 0x1F, 0xA0, 0x21, 0x8E, 0xF7, 0x00, 0x77, 0xF3, 0x33, 0x3C, 0xFF, 0x1E, 0x3C, 0x6F,
0x8E, 0x00, 0xCC, 0x3B, 0xC7, 0xB8, 0x67, 0x39, 0xDD, 0xEE, 0xE2, 0x30, 0x70, 0x21, 0xC1, 0x8F,
0x0C, 0x0C, 0x60, 0x33, 0x80, 0xCC, 0x00, 0x67, 0x03, 0x1C, 0x18, 0xD0, 0xE7, 0xE3, 0x1F, 0xD8,
0x04, 0x00, 0x00, 0x70, 0x21, 0xC1, 0x8F, 0x0C, 0x0C, 0x60, 0x33, 0x80, 0xCC, 0x00, 0x6F, 0x83,
0x33, 0x18, 0x18, 0xE1, 0xE3, 0x0C, 0x18, 0x3F, 0x00, 0x00, 0xFC, 0x18, 0x38, 0x60, 0xE1, 0xC1,
0xE3, 0x0C, 0xCC, 0x0F, 0xB0, 0x0C, 0xC7, 0x03, 0x9E, 0x0E, 0x6C, 0x19, 0xFC, 0x63, 0xF9, 0x80,
0x60, 0x00, 0x00, 0x0C, 0x06, 0x03, 0x00, 0x00, 0xC0, 0xE0, 0xE0, 0xE0, 0xE1, 0xF0, 0xD8, 0x6F,
0xE1, 0xE0, 0x1C, 0x01, 0x80, 0x10, 0x07, 0x01, 0xE0, 0x3E, 0x06, 0xC1, 0xD8, 0x33, 0x06, 0x31,
0xFE, 0x3F, 0xC6, 0x1C, 0xC1, 0xB0, 0x30, 0x06, 0x01, 0xC0, 0x30, 0x07, 0x01, 0xE0, 0x3E, 0x06,
0xC1, 0xD8, 0x33, 0x06, 0x31, 0xFE, 0x3F, 0xC6, 0x1C, 0xC1, 0xB0, 0x30, 0x0E, 0x03, 0xE0, 0xCC,
0x07, 0x01, 0xE0, 0x3E, 0x06, 0xC1, 0xD8, 0x33, 0x06, 0x31, 0xFE, 0x3F, 0xC6, 0x1C, 0xC1, 0xB0,
0x30, 0x1D, 0x07, 0xE0, 0x18, 0x07, 0x01, 0xE0, 0x3E, 0x06, 0xC1, 0xD8, 0x33, 0x06, 0x31, 0xFE,
0x3F, 0xC6, 0x1C, 0xC1, 0xB0, 0x30, 0x1B, 0x07, 0x60, 0x4C, 0x07, 0x01, 0xE0, 0x3E, 0x06, 0xC1,
0xD8, 0x33, 0x06, 0x31, 0xFE, 0x3F, 0xC6, 0x1C, 0xC1, 0xB0, 0x30, 0x0E, 0x03, 0xC0, 0x78, 0x06,
0x00, 0xE0, 0x3C, 0x07, 0xC0, 0xD8, 0x3B, 0x06, 0x60, 0xC6, 0x3F, 0xC7, 0xF8, 0xC3, 0x98, 0x36,
0x06, 0x07, 0xF8, 0x3F, 0xE0, 0xF0, 0x07, 0xC0, 0x1B, 0x00, 0x6F, 0xE3, 0x3F, 0x8F, 0xC0, 0x7F,
0x01, 0x8C, 0x06, 0x3F, 0xB0, 0xFE, 0x3E, 0x3F, 0xB8, 0x78, 0x3C, 0x1E, 0x03, 0x01, 0x83, 0xC1,
0xE0, 0xFD, 0xEF, 0xE1, 0xC0, 0x70, 0x78, 0x38, 0x30, 0x18, 0x18, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0,
0xFE, 0xFE, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0x0C, 0x18, 0x18, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xFE,
0xFE, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0x18, 0x3E, 0x66, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xFE, 0xFE,
0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0x66, 0x7E, 0x24, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xFE, 0xFE, 0xC0,
0xC0, 0xC0, 0xFF, 0xFF, 0xCD, 0xB6, 0xDB, 0x6D, 0xB6, 0xD8, 0x7B, 0x6D, 0xB6, 0xDB, 0x6D, 0xB0,
0x39, 0xFC, 0xCC, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x00, 0xCF, 0xF4, 0x8C, 0x30,
0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x00, 0xFF, 0x1F, 0xF0, 0xC7, 0x18, 0x63, 0x0E, 0xF9,
0xFF, 0x39, 0x87, 0x30, 0xC6, 0x19, 0xFF, 0x7F, 0xC0, 0x3A, 0x1F, 0x09, 0x1C, 0x3F, 0x1F, 0x8F,
0xE7, 0xB3, 0xD9, 0xE6, 0xF3, 0x79, 0xFC, 0x7E, 0x3F, 0x1E, 0x18, 0x06, 0x00, 0xC0, 0xF8, 0x7F,
0xB8, 0x6C, 0x1B, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x06, 0xC1, 0xBD, 0xE7, 0xF0, 0x70, 0x0C, 0x03,
0x00, 0x80, 0xF8, 0x7F, 0xB8, 0x6C, 0x1B, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x06, 0xC1, 0xBD, 0xE7,
0xF0, 0x70, 0x1C, 0x0F, 0x83, 0x20, 0xF8, 0x7F, 0xB8, 0x6C, 0x1B, 0x07, 0xC1, 0xF0, 0x7C, 0x1F,
0x06, 0xC1, 0xBD, 0xE7, 0xF0, 0x70, 0x3A, 0x0F, 0x82, 0x40, 0xF8, 0x7F, 0xB8, 0x6C, 0x1B, 0x07,
0xC1, 0xF0, 0x7C, 0x1F, 0x06, 0xC1, 0xBD, 0xE7, 0xF0, 0x70, 0x36, 0x0D, 0xC3, 0x20, 0xF8, 0x7F,
0xB8, 0x6C, 0x1B, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x06, 0xC1, 0xBD, 0xE7, 0xF0, 0x70, 0x00, 0x67,
0x7E, 0x3C, 0x3C, 0x7E, 0x67, 0x42, 0x03, 0x0F, 0xC7, 0xFB, 0x9E, 0xC7, 0xB3, 0x7C, 0xDF, 0x27,
0xD9, 0xF6, 0x6F, 0x1B, 0xDE, 0x7F, 0x1F, 0x06, 0x00, 0x18, 0x0C, 0x02, 0x18, 0x3C, 0x1E, 0x0F,
0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1F, 0xBD, 0xFC, 0x38, 0x0C, 0x06, 0x02, 0x18, 0x3C,
0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1F, 0xBD, 0xFC, 0x38, 0x1C, 0x1F, 0x0C,
0x98, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1F, 0xBD, 0xFC, 0x38, 0x36,
0x1B, 0x8C, 0x98, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1F, 0xBD, 0xFC,
0x38, 0x06, 0x03, 0x80, 0xC3, 0x03, 0xE1, 0xD8, 0x63, 0x38, 0xEC, 0x1E, 0x07, 0x80, 0xC0, 0x30,
0x0C, 0x03, 0x00, 0xC0, 0xC0, 0x60, 0x3F, 0x9F, 0xEC, 0x3E, 0x0F, 0x07, 0x87, 0xFF, 0x7F, 0x30,
0x18, 0x00, 0x3E, 0x3F, 0xB8, 0xD8, 0x6C, 0x66, 0x63, 0x39, 0x9E, 0xC3, 0xF8, 0xFE, 0x7B, 0xF0,
0x60, 0x18, 0x06, 0x00, 0xC0, 0x70, 0x3F, 0x18, 0xC6, 0x30, 0xFC, 0x7F, 0x38, 0xC6, 0x79, 0xFF,
0x18, 0x00, 0x06, 0x03, 0x00, 0xC0, 0x70, 0x3F, 0x18, 0xC6, 0x30, 0xFC, 0x7F, 0x38, 0xC6, 0x79,
0xFF, 0x18, 0x00, 0x1C, 0x0F, 0x83, 0x70, 0x70, 0x3F, 0x18, 0xC6, 0x30, 0xFC, 0x7F, 0x38, 0xC6,
0x79, 0xFF, 0x18, 0x00, 0x10, 0x0F, 0xC2, 0xE0, 0x70, 0x3F, 0x18, 0xC6, 0x30, 0xFC, 0x7F, 0x38,
0xC6, 0x79, 0xFF, 0x18, 0x00, 0x36, 0x0D, 0xC3, 0x60, 0x70, 0x3F, 0x18, 0xC6, 0x30, 0xFC, 0x7F,
0x38, 0xC6, 0x79, 0xFF, 0x18, 0x00, 0x08, 0x07, 0x81, 0x60, 0x70, 0x1C, 0x0F, 0xC6, 0x31, 0x8C,
0x3F, 0x1F, 0xCE, 0x31, 0x9E, 0x7F, 0xC6, 0x00, 0x1C, 0x70, 0x7F, 0xF9, 0x8E, 0x33, 0x1C, 0x33,
0xFF, 0xEF, 0xFF, 0xF8, 0xE1, 0x33, 0xE6, 0x7E, 0xFC, 0x30, 0x60, 0x0E, 0x0F, 0xC7, 0x39, 0x86,
0x60, 0x18, 0x06, 0x19, 0xCE, 0x3F, 0x03, 0x00, 0xE0, 0x78, 0x0C, 0x00, 0x18, 0x0E, 0x03, 0x01,
0xC3, 0xF3, 0x9D, 0x86, 0xFF, 0x7F, 0xB0, 0xDC, 0xE7, 0xE0, 0xC0, 0x06, 0x07, 0x03, 0x01, 0xC3,
0xF3, 0x9D, 0x86, 0xFF, 0x7F, 0xB0, 0xDC, 0xE7, 0xE0, 0xC0, 0x0C, 0x0F, 0x0C, 0xC1, 0xC3, 0xF3,
0x9D, 0x86, 0xFF, 0x7F, 0xB0, 0xDC, 0xE7, 0xE0, 0xC0, 0x12, 0x1F, 0x8C, 0xC1, 0xC3, 0xF3, 0x9D,
0x86, 0xFF, 0x7F, 0xB0, 0xDC, 0xE7, 0xE0, 0xC0, 0xDD, 0x86, 0xDB, 0x6D, 0xB0, 0x6E, 0xC0, 0xCC,
0xCC, 0xCC, 0xCC, 0x31, 0xEC, 0xC0, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x4B, 0xFC, 0xC0, 0x30,
0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x02, 0x07, 0x80, 0xE0, 0x3C, 0x0D, 0x8F, 0xE7, 0x39, 0x87, 0x60,
0xD8, 0x36, 0x19, 0xCE, 0x3F, 0x03, 0x00, 0x10, 0x3E, 0x6C, 0x1C, 0xFE, 0xE3, 0xC3, 0xC3, 0xC3,
0xC3, 0xC3, 0xC3, 0x18, 0x03, 0x00, 0xC0, 0x38, 0x3F, 0x1C, 0xE6, 0x1D, 0x83, 0x60, 0xD8, 0x67,
0x38, 0xFC, 0x0C, 0x00, 0x06, 0x01, 0x80, 0xC0, 0x38, 0x3F, 0x1C, 0xE6, 0x1D, 0x83, 0x60, 0xD8,
0x67, 0x38, 0xFC, 0x0C, 0x00, 0x0C, 0x07, 0x83, 0x30, 0x38, 0x3F, 0x1C, 0xE6, 0x1D, 0x83, 0x60,
0xD8, 0x67, 0x38, 0xFC, 0x0C, 0x00, 0x08, 0x07, 0xC3, 0x70, 0x38, 0x3F, 0x1C, 0xE6, 0x1D, 0x83,
0x60, 0xD8, 0x67, 0x38, 0xFC, 0x0C, 0x00, 0x12, 0x0F, 0xC1, 0xB0, 0x38, 0x3F, 0x1C, 0xE6, 0x1D,
0x83, 0x60, 0xD8, 0x67, 0x38, 0xFC, 0x0C, 0x00, 0x18, 0x1C, 0x18, 0xFF, 0xFF, 0x00, 0x1C, 0x18,
0x00, 0x03, 0xE3, 0xF1, 0xCE, 0x67, 0xDB, 0x36, 0xCD, 0xE6, 0x7B, 0x8F, 0xC2, 0xC0, 0x00, 0x30,
0x38, 0x18, 0x01, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7F, 0x10, 0x0C, 0x1C, 0x18, 0x01,
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7F, 0x10, 0x18, 0x3C, 0x66, 0x01, 0xC3, 0xC3, 0xC3,
0xC3, 0xC3, 0xC3, 0xE7, 0x7F, 0x10, 0x24, 0x7E, 0x66, 0x01, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
0xE7, 0x7F, 0x10, 0x0C, 0x1C, 0x18, 0x01, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7F, 0x13,
0x03, 0x7F, 0x7E, 0xC0, 0x60, 0x30, 0x1B, 0x8F, 0xF7, 0x1F, 0x07, 0x83, 0xC1, 0xE0, 0xFC, 0xDF,
0xEC, 0xC6, 0x03, 0x01, 0x80, 0x24, 0x7E, 0x76, 0x01, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7,
0x7F, 0x13, 0x03, 0x7F, 0x7E, 0x3F, 0x03, 0xC0, 0x38, 0x0F, 0x01, 0xF0, 0x36, 0x0E, 0xC1, 0x98,
0x31, 0x8F, 0xF1, 0xFE, 0x30, 0xE6, 0x0D, 0x81, 0x80, 0x3F, 0x0F, 0x81, 0xC0, 0xFC, 0x63, 0x18,
0xC3, 0xF1, 0xFC, 0xE3, 0x19, 0xE7, 0xFC, 0x60, 0x33, 0x03, 0xE0, 0x38, 0x07, 0x01, 0xE0, 0x3E,
0x06, 0xC1, 0xD8, 0x33, 0x06, 0x31, 0xFE, 0x3F, 0xC6, 0x1C, 0xC1, 0xB0, 0x30, 0x32, 0x0F, 0x81,
0xE0, 0x70, 0x3F, 0x18, 0xC6, 0x30, 0xFC, 0x7F, 0x38, 0xC6, 0x79, 0xFF, 0x18, 0x00, 0x0E, 0x03,
0xC0, 0x7C, 0x0D, 0x83, 0xB0, 0x66, 0x0C, 0x63, 0xFC, 0x7F, 0x8C, 0x39, 0x83, 0x60, 0x60, 0x0C,
0x01, 0xC0, 0x38, 0x1C, 0x0F, 0xC6, 0x31, 0x8C, 0x3F, 0x1F, 0xCE, 0x31, 0x9E, 0x7F, 0xC6, 0x60,
0x18, 0x07, 0x0C, 0x06, 0x02, 0x07, 0xC7, 0xF7, 0x0F, 0x07, 0x83, 0xC0, 0x60, 0x30, 0x78, 0x3C,
0x1F, 0xBD, 0xFC, 0x38, 0x06, 0x01, 0x80, 0xC0, 0x38, 0x3F, 0x1C, 0xE6, 0x19, 0x80, 0x60, 0x18,
0x67, 0x38, 0xFC, 0x0C, 0x00, 0x1C, 0x1F, 0x0C, 0x87, 0xC7, 0xF7, 0x0F, 0x07, 0x83, 0xC0, 0x60,
0x30, 0x78, 0x3C, 0x1F, 0xBD, 0xFC, 0x38, 0x0C, 0x07, 0x83, 0x30, 0x38, 0x3F, 0x1C, 0xE6, 0x19,
0x80, 0x60, 0x18, 0x67, 0x38, 0xFC, 0x0C, 0x00, 0x1C, 0x0E, 0x02, 0x07, 0xC7, 0xF7, 0x0F, 0x07,
0x83, 0xC0, 0x60, 0x30, 0x78, 0x3C, 0x1F, 0xBD, 0xFC, 0x38, 0x0C, 0x03, 0x00, 0xC0, 0x38, 0x3F,
0x1C, 0xE6, 0x19, 0x80, 0x60, 0x18, 0x67, 0x38, 0xFC, 0x0C, 0x00, 0x36, 0x1F, 0x07, 0x07, 0xC7,
0xF7, 0x0F, 0x07, 0x83, 0xC0, 0x60, 0x30, 0x78, 0x3C, 0x1F, 0xBD, 0xFC, 0x38, 0x33, 0x07, 0xC0,
0xE0, 0x38, 0x3F, 0x1C, 0xE6, 0x19, 0x80, 0x60, 0x18, 0x67, 0x38, 0xFC, 0x0C, 0x00, 0x3B, 0x03,
0xC0, 0x30, 0x7F, 0x8F, 0xF8, 0x63, 0x8C, 0x31, 0x87, 0x30, 0xE6, 0x1C, 0xC3, 0x98, 0x63, 0x0C,
0xFF, 0xBF, 0xE0, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x39, 0xE3, 0xFC, 0x38, 0xE1, 0x87, 0x0C, 0x18,
0x60, 0xC3, 0x0E, 0x1C, 0xF0, 0x7F, 0x80, 0xC0, 0x00, 0xFF, 0x1F, 0xF0, 0xC7, 0x18, 0x63, 0x0E,
0xF9, 0xFF, 0x39, 0x87, 0x30, 0xC6, 0x19, 0xFF, 0x7F, 0xC0, 0x00, 0xC0, 0xFC, 0x1F, 0x8E, 0x63,
0xFC, 0xE3, 0x98, 0x73, 0x06, 0x60, 0xCC, 0x39, 0xCF, 0x1F, 0xE0, 0xC0, 0x7E, 0x3C, 0xFF, 0xFF,
0xC0, 0xC0, 0xC0, 0xFE, 0xFE, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0x3F, 0x1F, 0x83, 0x87, 0xE7, 0x3B,
0x0D, 0xFE, 0xFF, 0x61, 0xB9, 0xCF, 0xC1, 0x80, 0x66, 0x7E, 0x1C, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0,
0xFE, 0xFE, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0x33, 0x1F, 0x87, 0x81, 0xC3, 0xF3, 0x9D, 0x86, 0xFF,
0x7F, 0xB0, 0xDC, 0xE7, 0xE0, 0xC0, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xFE, 0xFE,
0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0x0C, 0x06, 0x03, 0x01, 0xC3, 0xF3, 0x9D, 0x86, 0xFF, 0x7F, 0xB0,
0xDC, 0xE7, 0xE0, 0xC0, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xFE, 0xFE, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF,
0x06, 0x07, 0x07, 0x0E, 0x1F, 0x9C, 0xEC, 0x37, 0xFB, 0xFD, 0x86, 0xE7, 0x3F, 0x07, 0x01, 0xC0,
0xE0, 0x66, 0x3C, 0x18, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xFE, 0xFE, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF,
0x33, 0x0F, 0x03, 0x81, 0xC3, 0xF3, 0x9D, 0x86, 0xFF, 0x7F, 0xB0, 0xDC, 0xE7, 0xE0, 0xC0, 0x1C,
0x1F, 0x0C, 0x87, 0xC7, 0xF7, 0x0F, 0x07, 0x83, 0xC0, 0x67, 0xF3, 0xF8, 0x3C, 0x1F, 0xBD, 0xFE,
0x30, 0x0E, 0x07, 0xC1, 0xB0, 0x72, 0x3F, 0xDC, 0x76, 0x1D, 0x83, 0x60, 0xD8, 0x77, 0xBC, 0xFF,
0x00, 0xC0, 0x33, 0xFC, 0xFE, 0x32, 0x1F, 0x07, 0x07, 0xC7, 0xF7, 0x0F, 0x07, 0x83, 0xC0, 0x67,
0xF3, 0xF8, 0x3C, 0x1F, 0xBD, 0xFE, 0x30, 0x19, 0x07, 0xC0, 0xE0, 0x72, 0x3F, 0xDC, 0x76, 0x1D,
0x83, 0x60, 0xD8, 0x77, 0xBC, 0xFF, 0x00, 0xC0, 0x33, 0xFC, 0xFE, 0x0C, 0x0E, 0x02, 0x07, 0xC7,
0xF7, 0x0F, 0x07, 0x83, 0xC0, 0x67, 0xF3, 0xF8, 0x3C, 0x1F, 0xBD, 0xFE, 0x30, 0x04, 0x03, 0x80,
0x40, 0x72, 0x3F, 0xDC, 0x76, 0x1D, 0x83, 0x60, 0xD8, 0x77, 0xBC, 0xFF, 0x00, 0xC0, 0x33, 0xFC,
0xFE, 0x3E, 0x3F, 0xB8, 0x78, 0x3C, 0x1E, 0x03, 0x3F, 0x9F, 0xC1, 0xE0, 0xFD, 0xEF, 0xF1, 0x80,
0xE0, 0x70, 0x18, 0x08, 0x00, 0x06, 0x03, 0x00, 0xE0, 0x38, 0x1C, 0x8F, 0xF7, 0x1D, 0x87, 0x60,
0xD8, 0x36, 0x1D, 0xEF, 0x3F, 0xC0, 0x30, 0x0C, 0xFF, 0x3F, 0x80, 0x1C, 0x1F, 0x0D, 0x98, 0x3C,
0x1E, 0x0F, 0x07, 0x83, 0xFF, 0xFF, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x06, 0x38, 0x1F, 0x0C, 0xC0,
0xC0, 0x30, 0x0C, 0x03, 0x70, 0xFE, 0x38, 0xCC, 0x33, 0x0C, 0xC3, 0x30, 0xCC, 0x33, 0x0C, 0x60,
0xCC, 0x1B, 0xFF, 0xFF, 0xF6, 0x0C, 0xFF, 0x9F, 0xF3, 0x06, 0x60, 0xCC, 0x19, 0x83, 0x30, 0x60,
0x60, 0x7E, 0x3F, 0x0D, 0xC7, 0xF3, 0x8D, 0x86, 0xC3, 0x61, 0xB0, 0xD8, 0x6C, 0x30, 0x6F, 0xF1,
0x8C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x00, 0x23, 0xFD, 0x80, 0x30, 0xC3, 0x0C,
0x30, 0xC3, 0x0C, 0xFD, 0xE3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC0, 0xFF, 0xF0,
0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x00, 0xCF, 0xF3, 0x8C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C,
0x30, 0xC3, 0x00, 0xCF, 0xF7, 0x80, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0xDB, 0x6D, 0xB6, 0xDB,
0x6D, 0xB8, 0xDB, 0x0D, 0xB6, 0xDB, 0x6D, 0xB8, 0xDB, 0x6D, 0xB6, 0xDB, 0x6D, 0xB0, 0x3F, 0xFF,
0xC0, 0xF9, 0xFF, 0x9F, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x20, 0xC0, 0x0C, 0x30, 0xC3, 0x0C,
0x39, 0xC1, 0xF8, 0x06, 0x00, 0xCD, 0x9F, 0x30, 0x2C, 0xD9, 0xB3, 0x66, 0xCD, 0x9B, 0x36, 0x60,
0xC1, 0x87, 0x0C, 0x07, 0x03, 0xE0, 0xCC, 0x3E, 0x0F, 0x80, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xCC,
0x33, 0x0C, 0xE3, 0x1D, 0xC7, 0xE0, 0x60, 0x31, 0xEC, 0xC0, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C,
0x30, 0xCF, 0x18, 0xC3, 0xE3, 0xB3, 0x9B, 0x8F, 0x87, 0x83, 0xC1, 0xF0, 0xDC, 0x67, 0x31, 0xD8,
0x70, 0x00, 0xC0, 0x70, 0x30, 0x18, 0x00, 0xC0, 0xC0, 0xC0, 0xC2, 0xCE, 0xDC, 0xF8, 0xF0, 0xF0,
0xD8, 0xCE, 0xC7, 0x00, 0x38, 0x38, 0x18, 0x10, 0x02, 0xCE, 0xDC, 0xF8, 0xF0, 0xF0, 0xD8, 0xCE,
0xC7, 0x60, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF,
0x7B, 0x6D, 0xB6, 0xDB, 0x6D, 0xB0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
0xFF, 0xFF, 0x00, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0xFF, 0x3F, 0xC0, 0xD8, 0xD8, 0xD0, 0xD0,
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0xDE, 0xF5, 0xAC, 0x63, 0x18, 0xC6, 0x31, 0x80,
0xC0, 0xC0, 0xC0, 0xC0, 0xC4, 0xCE, 0xC4, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0xC3, 0x0C, 0x30, 0xC3,
0x0C, 0xB7, 0xCB, 0x0C, 0x30, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x38, 0x0F, 0x07, 0x03, 0xC0, 0x30,
0x0C, 0x03, 0xFC, 0xFF, 0x30, 0xC3, 0x0C, 0x30, 0xF3, 0xFC, 0xF0, 0xC3, 0x0C, 0x0C, 0x06, 0x02,
0x1C, 0x3F, 0x1F, 0x8F, 0xE7, 0xB3, 0xD9, 0xE6, 0xF3, 0x79, 0xFC, 0x7E, 0x3F, 0x1E, 0x0C, 0x0C,
0x18, 0x1C, 0xFE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE1, 0xF8, 0xFC, 0x7F, 0x3D, 0x9E,
0xCF, 0x37, 0x9B, 0xCF, 0xE3, 0xF1, 0xF8, 0xF0, 0x00, 0xE0, 0x70, 0x18, 0x08, 0x00, 0x1C, 0xFE,
0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x00, 0x18, 0x18, 0x18, 0x18, 0x36, 0x1F, 0x07, 0x1C,
0x3F, 0x1F, 0x8F, 0xE7, 0xB3, 0xD9, 0xE6, 0xF3, 0x79, 0xFC, 0x7E, 0x3F, 0x1E, 0x66, 0x3E, 0x1C,
0x1C, 0xFE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC0, 0xE0, 0x60, 0xC0, 0x1C, 0xFE, 0xE3,
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE1, 0xF8, 0xFC, 0x7F, 0x3D, 0x9E, 0xCF, 0x37, 0x9B, 0xCF,
0xE3, 0xF1, 0xF8, 0xF0, 0x18, 0x0C, 0x1E, 0x0E, 0x1C, 0xFE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
0xC3, 0x03, 0x03, 0x0F, 0x0E, 0x3E, 0x0F, 0x83, 0xE1, 0xFE, 0xE1, 0xB0, 0x6C, 0x1F, 0x07, 0xC1,
0xF0, 0x7C, 0x1B, 0x06, 0xF7, 0x9F, 0xC1, 0xC0, 0x3F, 0x0F, 0xC0, 0xE0, 0xFC, 0x73, 0x98, 0x76,
0x0D, 0x83, 0x61, 0x9C, 0xE3, 0xF0, 0x30, 0x32, 0x0F, 0x81, 0xC0, 0xF8, 0x7F, 0xB8, 0x6C, 0x1B,
0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x06, 0xC1, 0xBD, 0xE7, 0xF0, 0x70, 0x33, 0x07, 0xC1, 0xE0, 0x38,
0x3F, 0x1C, 0xE6, 0x1D, 0x83, 0x60, 0xD8, 0x67, 0x38, 0xFC, 0x0C, 0x00, 0x1F, 0x0F, 0x83, 0x40,
0xF8, 0x7F, 0xB8, 0x6C, 0x1B, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x06, 0xC1, 0xBD, 0xE7, 0xF0, 0x70,
0x0F, 0x06, 0xC1, 0xE0, 0x38, 0x3F, 0x1C, 0xE6, 0x1D, 0x83, 0x60, 0xD8, 0x67, 0x38, 0xFC, 0x0C,
0x00, 0x1F, 0xF3, 0xFF, 0xB9, 0x81, 0x8C, 0x0C, 0x60, 0x63, 0xFB, 0x1F, 0xD8, 0xC0, 0xC6, 0x07,
0x30, 0x1F, 0xFC, 0x7F, 0xF0, 0x0E, 0x1C, 0x1F, 0xBF, 0x1C, 0xF8, 0xCC, 0x38, 0x66, 0x0F, 0xF3,
0x07, 0xF9, 0x87, 0x0C, 0xE7, 0xCE, 0x3F, 0x7E, 0x06, 0x0C, 0x00, 0x0C, 0x0E, 0x06, 0x1F, 0xCF,
0xF6, 0x0F, 0x07, 0x83, 0xC3, 0xFF, 0xBF, 0xF8, 0x7C, 0x3E, 0x1F, 0x0E, 0x19, 0x8C, 0x3F, 0xF3,
0x18, 0xC6, 0x31, 0x80, 0xFE, 0x7F, 0xB0, 0x78, 0x3C, 0x1E, 0x1F, 0xFD, 0xFF, 0xC3, 0xE1, 0xF0,
0xF8, 0x70, 0x00, 0xC0, 0x70, 0x38, 0x18, 0x00, 0x1F, 0xF9, 0x8C, 0x63, 0x18, 0xC0, 0x31, 0x8C,
0x60, 0x66, 0x1E, 0x06, 0x1F, 0xCF, 0xF6, 0x0F, 0x07, 0x83, 0xC3, 0xFF, 0xBF, 0xF8, 0x7C, 0x3E,
0x1F, 0x0E, 0x6C, 0xF8, 0xE0, 0x67, 0xCE, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x00, 0x06, 0x03, 0x80,
0xC0, 0xFC, 0x7F, 0x98, 0x66, 0x1D, 0xC2, 0x3E, 0x07, 0xE4, 0x1F, 0x83, 0x60, 0xDC, 0xE3, 0xF8,
0x30, 0x0C, 0x0C, 0x18, 0x1C, 0x7E, 0x63, 0x62, 0x7E, 0x1F, 0x63, 0x63, 0x3F, 0x0C, 0x0E, 0x07,
0xC3, 0x30, 0xFC, 0x7F, 0x98, 0x66, 0x1D, 0xC2, 0x3E, 0x07, 0xE4, 0x1F, 0x83, 0x60, 0xDC, 0xE3,
0xF8, 0x30, 0x1C, 0x3E, 0x76, 0x1C, 0x7E, 0x63, 0x62, 0x7E, 0x1F, 0x63, 0x63, 0x3F, 0x0C, 0x3F,
0x1F, 0xE6, 0x19, 0x87, 0x70, 0x8F, 0x81, 0xF9, 0x07, 0xE0, 0xD8, 0x37, 0x38, 0xFE, 0x0E, 0x01,
0x81, 0xE0, 0x38, 0x1C, 0x7E, 0x63, 0x62, 0x7E, 0x1F, 0x63, 0x63, 0x3F, 0x0C, 0x0E, 0x1E, 0x1C,
0x33, 0x07, 0x80, 0xC0, 0xFC, 0x7F, 0x98, 0x66, 0x1D, 0xC2, 0x3E, 0x07, 0xE4, 0x1F, 0x83, 0x60,
0xDC, 0xE3, 0xF8, 0x30, 0x66, 0x3E, 0x1C, 0x1C, 0x7E, 0x63, 0x62, 0x7E, 0x1F, 0x63, 0x63, 0x3F,
0x0C, 0xFF, 0xFF, 0xF0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30,
0x0C, 0x03, 0x81, 0xE0, 0x30, 0x00, 0x30, 0x63, 0xFF, 0xE3, 0x06, 0x0C, 0x18, 0x30, 0x70, 0xF1,
0x83, 0x8F, 0x0C, 0x33, 0x07, 0x80, 0xC3, 0xFF, 0xFF, 0xC3, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00,
0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x06, 0x06, 0x1E, 0x1E, 0x7E, 0xFE, 0x18, 0x18, 0x18, 0x18,
0x18, 0x1C, 0x1E, 0xFF, 0xFF, 0xF0, 0xC0, 0x30, 0x0C, 0x0F, 0xC3, 0xF0, 0x30, 0x0C, 0x03, 0x00,
0xC0, 0x30, 0x00, 0x30, 0x63, 0xFF, 0xE3, 0x06, 0x7F, 0xFE, 0x30, 0x70, 0xF0, 0x3A, 0x1F, 0x09,
0x18, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1F, 0xBD, 0xFC, 0x38, 0x10,
0x7E, 0x6C, 0x01, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7F, 0x10, 0x3E, 0x1F, 0x30, 0x78,
0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3F, 0x7B, 0xF8, 0x70, 0x7E, 0x7E, 0x01,
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7F, 0x10, 0x32, 0x1F, 0x07, 0x18, 0x3C, 0x1E, 0x0F,
0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1F, 0xBD, 0xFC, 0x38, 0x66, 0x7E, 0x3C, 0x01, 0xC3,
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7F, 0x10, 0x1C, 0x0F, 0x07, 0x03, 0x8C, 0x1E, 0x0F, 0x07,
0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0xDE, 0xFE, 0x1C, 0x00, 0x08, 0x3C, 0x3C, 0x3C,
0x01, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7F, 0x10, 0x1F, 0x1B, 0x0D, 0x18, 0x3C, 0x1E,
0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1F, 0xBD, 0xFC, 0x38, 0x16, 0x36, 0x3C, 0x01,
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7F, 0x10, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F,
0x07, 0x83, 0xC1, 0xE0, 0xFD, 0xEF, 0xE1, 0xE0, 0x30, 0x18, 0x01, 0x61, 0xB0, 0xD8, 0x6C, 0x36,
0x1B, 0x0D, 0xCE, 0x7F, 0x09, 0x80, 0xE0, 0x70, 0x03, 0x80, 0x1F, 0x00, 0xCC, 0x30, 0xE3, 0xE7,
0x8D, 0x9E, 0x36, 0x6C, 0xD9, 0xB3, 0x66, 0xDD, 0xBB, 0x66, 0xCD, 0x8F, 0x3E, 0x3C, 0x78, 0xF1,
0xE3, 0xC7, 0x80, 0x07, 0x00, 0x7C, 0x03, 0x70, 0x84, 0x26, 0x71, 0xB3, 0xDD, 0x9E, 0xCD, 0xB6,
0x6D, 0xB1, 0xE7, 0x8F, 0x3C, 0x71, 0xC0, 0x0E, 0x07, 0xC3, 0x33, 0x03, 0xE1, 0xD8, 0x63, 0x38,
0xEC, 0x1E, 0x07, 0x80, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x18, 0x3C, 0x66, 0x01, 0xC3, 0xC3,
0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7F, 0x13, 0x03, 0x7F, 0x7E, 0x33, 0x0F, 0xC1, 0x23, 0x03, 0xE1,
0xD8, 0x63, 0x38, 0xEC, 0x1E, 0x07, 0x80, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x0E, 0x06, 0x02,
0x0F, 0xF7, 0xF8, 0x1C, 0x0C, 0x0C, 0x0E, 0x0E, 0x0E, 0x06, 0x06, 0x07, 0xFF, 0xFE, 0x18, 0x30,
0xC7, 0xEF, 0xE1, 0xC7, 0x1C, 0x71, 0xC3, 0xF7, 0xF0, 0x0C, 0x0E, 0x02, 0x0F, 0xF7, 0xF8, 0x1C,
0x0C, 0x0C, 0x0E, 0x0E, 0x0E, 0x06, 0x06, 0x07, 0xFF, 0xFE, 0x30, 0x70, 0xC7, 0xEF, 0xE1, 0xC7,
0x1C, 0x71, 0xC3, 0xF7, 0xF0, 0x37, 0x0F, 0x03, 0x0F, 0xF7, 0xF8, 0x1C, 0x0C, 0x0C, 0x0E, 0x0E,
0x0E, 0x06, 0x06, 0x07, 0xFF, 0xFE, 0xCC, 0xF8, 0xE7, 0xEF, 0xE1, 0xC7, 0x1C, 0x71, 0xC3, 0xF7,
0xF0, 0x3C, 0xF3, 0x1C, 0xF0, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x67, 0x30, 0x36, 0x60, 0x38, 0x79,
0xB8, 0x20, 0xF9, 0x70, 0x7C, 0xF8, 0x4D, 0xF7, 0x80, 0x6D, 0x80, 0x6C, 0xD9, 0xB0, 0x73, 0xCE,
0x60, 0x23, 0x96, 0xE0, 0x6D, 0xB7, 0x80, 0x66, 0xF8, 0xE0, 0x79, 0xB3, 0xC0, 0x39, 0xF4, 0xC0,
0x69, 0xB0, 0x66, 0x60, 0x6D, 0x00, 0x6C, 0xD9, 0x00, 0x6D, 0xA0, 0x21, 0x8E, 0xF7, 0x00, 0x44,
0x66, 0x4D, 0xF3, 0x80, 0x7C, 0xF8, 0x7C, 0xFC, 0x7F, 0xF7, 0xFF, 0x00, 0x03, 0x06, 0x06, 0x0C,
0x18, 0x18, 0x30, 0x30, 0x60, 0x40, 0x00, 0x03, 0x06, 0x06, 0x06, 0x0C, 0x0C, 0x08, 0x18, 0x18,
0x30, 0x30, 0x20, 0x60, 0x60, 0x40, 0xFF, 0xE0, 0xFF, 0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xC0, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0x46, 0x60, 0x06, 0x73, 0x60, 0x06, 0x73, 0x60, 0x00, 0xD9,
0x63, 0xE7, 0xC0, 0x00, 0x00, 0xF9, 0xF1, 0xA6, 0xC0, 0x00, 0x00, 0xF9, 0xF1, 0xA6, 0xC0, 0x00,
0x18, 0x18, 0x18, 0x7E, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFE,
0xFF, 0x18, 0x18, 0xFE, 0xFF, 0x18, 0x18, 0x18, 0x6F, 0xFF, 0xF0, 0x00, 0x0D, 0xDD, 0xFB, 0x92,
0x20, 0x78, 0x30, 0xFC, 0x60, 0xCC, 0xE0, 0xCD, 0xC0, 0x7D, 0x80, 0x3B, 0x00, 0x06, 0x44, 0x0F,
0xFF, 0x1D, 0xBB, 0x19, 0x33, 0x31, 0xBB, 0x61, 0xFF, 0x00, 0x44, 0x6D, 0xA4, 0x6D, 0xE7, 0x96,
0x58, 0x06, 0x3D, 0xE7, 0x07, 0x07, 0x83, 0x83, 0xC3, 0xC7, 0x87, 0x1D, 0xEE, 0x20, 0x00, 0x60,
0x18, 0x07, 0x01, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x38, 0x06, 0x01, 0x80, 0x60, 0x00, 0x00,
0x70, 0x6E, 0x1D, 0xC3, 0x00, 0xC0, 0x30, 0x0E, 0x03, 0x80, 0x60, 0x18, 0x06, 0x19, 0x87, 0xB0,
0xF0, 0x04, 0x0F, 0x05, 0x0F, 0x8F, 0xEF, 0xFE, 0xFF, 0x7F, 0xA8, 0xFC, 0x7E, 0xFF, 0x7F, 0xBF,
0xFB, 0xF9, 0xF0, 0xF0, 0x3F, 0x8F, 0xE3, 0x00, 0xC0, 0x30, 0x0F, 0xE3, 0xF8, 0xC0, 0x7C, 0x3F,
0x83, 0x00, 0xC0, 0x1F, 0x0F, 0xE3, 0x1C, 0xC3, 0x30, 0xDF, 0x03, 0x01, 0xF0, 0x30, 0x0C, 0x07,
0xF9, 0xFF, 0x38, 0x63, 0xC6, 0x3C, 0x63, 0xC6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x33, 0x63,
0x3E, 0x31, 0xE3, 0x1E, 0x3F, 0x83, 0xFC, 0x30, 0xCF, 0xFF, 0xFF, 0xF3, 0x1C, 0x3F, 0xC3, 0xF0,
0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x63, 0xC6, 0x63, 0xC6, 0x63, 0xCE, 0x63, 0xCC, 0xFF, 0xFE,
0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0x36, 0x6C, 0x3C, 0x78, 0x3C, 0x78, 0x1C, 0x38, 0x00, 0xC0,
0xFC, 0x1F, 0x8E, 0x63, 0xFC, 0xE3, 0x98, 0x73, 0x06, 0x60, 0xCC, 0x39, 0xCF, 0x1F, 0xE0, 0xC0,
0xFF, 0x80, 0x1F, 0x87, 0xF8, 0xC3, 0x98, 0x3F, 0xC7, 0xFC, 0x3F, 0x07, 0xF3, 0x70, 0x66, 0x1C,
0xF7, 0x0F, 0xE0, 0x60, 0x30, 0xC6, 0x38, 0xCE, 0x1B, 0x83, 0xE1, 0xFF, 0x3F, 0xE1, 0xF0, 0x37,
0x06, 0x70, 0xC7, 0x18, 0x70, 0x3F, 0x83, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0x3F, 0xC3,
0xF0, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x08, 0x06, 0x0F, 0x8F, 0xEE, 0xDE, 0x6F, 0x37, 0x98,
0xCF, 0xE7, 0xF3, 0x79, 0xBF, 0xFB, 0xFC, 0x70, 0x18, 0x08, 0x06, 0x0F, 0x8F, 0xEE, 0xDE, 0x6F,
0x37, 0x98, 0xCC, 0x66, 0xF3, 0x79, 0xBF, 0xFB, 0xF8, 0x70, 0x18, 0xFF, 0xFF, 0xE0, 0x63, 0xFF,
0xFF, 0x81, 0x8F, 0xE3, 0xF8, 0x06, 0x01, 0x80, 0x60, 0x18, 0x30, 0x18, 0x0F, 0x0F, 0x8F, 0x01,
0xE3, 0xE7, 0x63, 0x31, 0x99, 0x8F, 0xC7, 0xC0, 0x0C, 0x03, 0x03, 0xF1, 0xFE, 0xED, 0xB3, 0x7C,
0xCF, 0x33, 0xCC, 0xF3, 0x3C, 0xCF, 0x33, 0xC0, 0xF0, 0x30, 0x3F, 0x87, 0xF8, 0xC3, 0x18, 0x73,
0x0C, 0xFF, 0xBF, 0xE1, 0x80, 0xFF, 0x06, 0x00, 0xC0, 0x18, 0x00, 0x1E, 0x07, 0x8F, 0xF3, 0xFE,
0x30, 0xCC, 0x33, 0x0C, 0xFE, 0x3F, 0x8C, 0x73, 0x0C, 0xC3, 0xFF, 0xFF, 0xE1, 0xE0, 0x78, 0x08,
0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0F, 0xFF, 0xBF, 0xFC, 0xC0, 0x03, 0x00, 0x0C, 0x00, 0x00, 0x00,
0x0C, 0x07, 0x83, 0xF1, 0xF6, 0x6C, 0xC3, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x00,
0x80, 0x06, 0x00, 0x18, 0x00, 0x6F, 0xFF, 0xBF, 0xFC, 0x01, 0xC0, 0x1C, 0x00, 0xC0, 0x00, 0x00,
0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC1, 0x32, 0x6D, 0xCF, 0xE1, 0xF0, 0x38, 0x00,
0x00, 0x08, 0x80, 0xE6, 0x0E, 0x18, 0xE0, 0x6F, 0xFF, 0xBF, 0xFC, 0xC1, 0xC3, 0x1C, 0x0C, 0xC0,
0x00, 0x00, 0x0C, 0x07, 0x83, 0xF1, 0xF6, 0x6C, 0xC3, 0x00, 0xC1, 0x32, 0x6D, 0xCF, 0xE1, 0xF0,
0x38, 0x00, 0x00, 0x7C, 0x7F, 0x38, 0x1E, 0x0F, 0x86, 0xE3, 0x38, 0x0E, 0x03, 0x80, 0x00, 0x1F,
0x1F, 0xC0, 0xE0, 0xF0, 0xF8, 0xEC, 0xE6, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x70, 0x1C, 0x27, 0x31,
0xD8, 0x7C, 0x1E, 0x3F, 0x3F, 0x80, 0x00, 0x01, 0xE1, 0xD9, 0xCD, 0xC7, 0xC3, 0xC1, 0xF8, 0xFE,
0x00, 0x38, 0x1E, 0x03, 0x87, 0xE7, 0xF7, 0x3B, 0x0F, 0x83, 0xC1, 0xE1, 0xB9, 0xCF, 0xC1, 0x80,
0x01, 0x03, 0xC3, 0xF9, 0xDE, 0x66, 0xDB, 0xB6, 0xCD, 0xB3, 0x7B, 0x8F, 0xC3, 0xC0, 0xC0, 0x0E,
0x07, 0x81, 0xE0, 0x6C, 0x33, 0x0C, 0xC3, 0x39, 0xC6, 0x61, 0x98, 0x67, 0xFF, 0xFF, 0xFF, 0x7F,
0xB0, 0xD8, 0x6C, 0x36, 0x1B, 0x0D, 0x86, 0xC3, 0x61, 0xB0, 0xD8, 0x6C, 0x36, 0x1B, 0x0D, 0x82,
0x7F, 0xDF, 0xF6, 0x00, 0xC0, 0x38, 0x07, 0x00, 0xC0, 0x18, 0x0E, 0x03, 0x01, 0x80, 0xE0, 0x70,
0x18, 0x07, 0xFD, 0xFF, 0xFF, 0xFF, 0x06, 0x0C, 0x30, 0x60, 0xC3, 0x06, 0x0C, 0x30, 0x60, 0xC3,
0x06, 0x0C, 0x30, 0x60, 0xC0, 0x77, 0xBF, 0xE0, 0x00, 0x00, 0xC0, 0x30, 0x0C, 0x06, 0x01, 0x80,
0x60, 0x18, 0x0C, 0x73, 0x3C, 0xC3, 0x30, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x13, 0x1F, 0xE6, 0xCD,
0xB3, 0x7F, 0x8E, 0xE0, 0x1C, 0xF3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xCF, 0x38,
0x3B, 0x7F, 0xCE, 0x3B, 0x7F, 0xCE, 0x00, 0x0C, 0x0C, 0xFF, 0xFF, 0x7F, 0xFF, 0x30, 0x30, 0x01,
0x0F, 0x3E, 0xF0, 0xF0, 0x7C, 0x1F, 0x03, 0x7F, 0xFF, 0xC0, 0xF0, 0x7E, 0x0F, 0x07, 0x3E, 0xF8,
0xC0, 0x7F, 0xFF,
};
static const EpdGlyph spacegroteskGlyphs[] = {
{ 0, 0, 10, 0, 0, 0, 0 }, //
{ 0, 0, 4, 0, 0, 0, 0 }, //
{ 4, 13, 4, 0, 12, 7, 0 }, // !
{ 7, 6, 7, 0, 13, 6, 7 }, // "
{ 10, 12, 10, 0, 12, 15, 13 }, // #
{ 10, 16, 10, 0, 14, 20, 28 }, // $
{ 13, 13, 13, 0, 12, 22, 48 }, // %
{ 10, 12, 10, 0, 12, 15, 70 }, // &
{ 4, 6, 4, 0, 13, 3, 85 }, // '
{ 6, 17, 6, 1, 13, 13, 88 }, // (
{ 6, 17, 6, 0, 13, 13, 101 }, // )
{ 8, 8, 9, 0, 12, 8, 114 }, // *
{ 8, 8, 10, 1, 10, 8, 122 }, // +
{ 4, 6, 4, 0, 3, 3, 130 }, // ,
{ 6, 2, 8, 1, 5, 2, 133 }, // -
{ 4, 4, 4, 0, 3, 2, 135 }, // .
{ 7, 16, 6, 0, 12, 14, 137 }, // /
{ 9, 13, 11, 1, 12, 15, 151 }, // 0
{ 6, 12, 7, 0, 12, 9, 166 }, // 1
{ 10, 12, 10, 0, 12, 15, 175 }, // 2
{ 10, 13, 10, 0, 12, 17, 190 }, // 3
{ 10, 12, 10, 0, 12, 15, 207 }, // 4
{ 10, 13, 10, 0, 12, 17, 222 }, // 5
{ 9, 13, 10, 1, 12, 15, 239 }, // 6
{ 9, 12, 9, 0, 12, 14, 254 }, // 7
{ 10, 13, 10, 0, 12, 17, 268 }, // 8
{ 10, 13, 10, 0, 12, 17, 285 }, // 9
{ 4, 10, 4, 0, 9, 5, 302 }, // :
{ 4, 12, 4, 0, 9, 6, 307 }, // ;
{ 8, 8, 10, 1, 10, 8, 313 }, // <
{ 8, 5, 10, 1, 8, 5, 321 }, // =
{ 8, 8, 10, 1, 10, 8, 326 }, // >
{ 9, 13, 10, 0, 12, 15, 334 }, // ?
{ 15, 16, 17, 1, 12, 30, 349 }, // @
{ 11, 12, 11, 0, 12, 17, 379 }, // A
{ 11, 12, 11, 0, 12, 17, 396 }, // B
{ 9, 13, 11, 1, 12, 15, 413 }, // C
{ 11, 12, 11, 0, 12, 17, 428 }, // D
{ 8, 12, 9, 1, 12, 12, 445 }, // E
{ 8, 12, 9, 1, 12, 12, 457 }, // F
{ 9, 13, 11, 1, 12, 15, 469 }, // G
{ 9, 12, 11, 1, 12, 14, 484 }, // H
{ 2, 12, 4, 1, 12, 3, 498 }, // I
{ 10, 13, 10, 0, 12, 17, 501 }, // J
{ 9, 12, 10, 1, 12, 14, 518 }, // K
{ 8, 12, 9, 1, 12, 12, 532 }, // L
{ 13, 12, 14, 1, 12, 20, 544 }, // M
{ 9, 12, 11, 1, 12, 14, 564 }, // N
{ 10, 13, 11, 1, 12, 17, 578 }, // O
{ 9, 12, 10, 1, 12, 14, 595 }, // P
{ 10, 15, 11, 1, 12, 19, 609 }, // Q
{ 9, 12, 11, 1, 12, 14, 628 }, // R
{ 10, 13, 10, 0, 12, 17, 642 }, // S
{ 10, 12, 10, 0, 12, 15, 659 }, // T
{ 9, 13, 11, 1, 12, 15, 674 }, // U
{ 10, 12, 10, 0, 12, 15, 689 }, // V
{ 14, 12, 15, 0, 12, 21, 704 }, // W
{ 11, 12, 11, 0, 12, 17, 725 }, // X
{ 10, 12, 10, 0, 12, 15, 742 }, // Y
{ 9, 12, 10, 0, 12, 14, 757 }, // Z
{ 5, 17, 6, 1, 13, 11, 771 }, // [
{ 8, 16, 6, -1, 12, 16, 782 }, // <backslash>
{ 5, 17, 6, 0, 13, 11, 798 }, // ]
{ 9, 5, 10, 1, 12, 6, 809 }, // ^
{ 9, 3, 10, 1, 0, 4, 815 }, // _
{ 4, 3, 5, 0, 12, 2, 819 }, // `
{ 10, 10, 10, 0, 9, 13, 821 }, // a
{ 9, 13, 11, 1, 12, 15, 834 }, // b
{ 10, 10, 10, 0, 9, 13, 849 }, // c
{ 10, 13, 11, 0, 12, 17, 862 }, // d
{ 9, 10, 10, 0, 9, 12, 879 }, // e
{ 7, 12, 7, 0, 12, 11, 891 }, // f
{ 10, 13, 11, 0, 9, 17, 902 }, // g
{ 8, 12, 10, 1, 12, 12, 919 }, // h
{ 3, 12, 4, 1, 12, 5, 931 }, // i
{ 5, 16, 4, -1, 12, 10, 936 }, // j
{ 8, 12, 9, 1, 12, 12, 946 }, // k
{ 2, 12, 4, 1, 12, 3, 958 }, // l
{ 13, 9, 14, 1, 9, 15, 961 }, // m
{ 8, 9, 10, 1, 9, 9, 976 }, // n
{ 10, 10, 10, 0, 9, 13, 985 }, // o
{ 9, 13, 11, 1, 9, 15, 998 }, // p
{ 10, 13, 11, 0, 9, 17, 1013 }, // q
{ 5, 9, 6, 1, 9, 6, 1030 }, // r
{ 8, 10, 9, 0, 9, 10, 1036 }, // s
{ 7, 12, 8, 0, 12, 11, 1046 }, // t
{ 8, 10, 10, 1, 9, 10, 1057 }, // u
{ 9, 9, 9, 0, 9, 11, 1067 }, // v
{ 13, 9, 13, 0, 9, 15, 1078 }, // w
{ 10, 9, 10, 0, 9, 12, 1093 }, // x
{ 8, 13, 10, 1, 9, 13, 1105 }, // y
{ 7, 9, 9, 1, 9, 8, 1118 }, // z
{ 7, 17, 7, 0, 13, 15, 1126 }, // {
{ 2, 19, 4, 1, 14, 5, 1141 }, // |
{ 7, 17, 7, 0, 13, 15, 1146 }, // }
{ 8, 4, 10, 1, 8, 4, 1161 }, // ~
{ 0, 0, 4, 0, 0, 0, 1165 }, //  
{ 4, 13, 4, 0, 9, 7, 1165 }, // ¡
{ 9, 13, 10, 1, 11, 15, 1172 }, // ¢
{ 10, 12, 10, 0, 12, 15, 1187 }, // £
{ 10, 10, 10, 0, 11, 13, 1202 }, // ¤
{ 11, 12, 10, 0, 12, 17, 1215 }, // ¥
{ 2, 19, 4, 1, 14, 5, 1232 }, // ¦
{ 8, 13, 8, 0, 12, 13, 1237 }, // §
{ 7, 3, 7, 0, 12, 3, 1250 }, // ¨
{ 10, 13, 12, 1, 12, 17, 1253 }, // ©
{ 7, 7, 7, 0, 12, 7, 1270 }, // ª
{ 11, 8, 11, 0, 8, 11, 1277 }, // «
{ 8, 4, 10, 1, 7, 4, 1288 }, // ¬
{ 6, 2, 8, 1, 5, 2, 1292 }, // ­
{ 8, 8, 9, 0, 12, 8, 1294 }, // ®
{ 7, 2, 7, 0, 11, 2, 1302 }, // ¯
{ 6, 6, 6, 0, 12, 5, 1304 }, // °
{ 8, 10, 10, 1, 10, 10, 1309 }, // ±
{ 6, 7, 6, 0, 13, 6, 1319 }, // ²
{ 6, 7, 6, 0, 12, 6, 1325 }, // ³
{ 4, 3, 5, 0, 12, 2, 1331 }, // ´
{ 9, 13, 10, 1, 9, 15, 1333 }, // µ
{ 9, 12, 10, 0, 12, 14, 1348 }, // ¶
{ 3, 4, 3, 0, 7, 2, 1362 }, // ·
{ 5, 5, 5, 0, 1, 4, 1364 }, // ¸
{ 4, 6, 4, 0, 12, 3, 1368 }, // ¹
{ 7, 7, 7, 0, 12, 7, 1371 }, // º
{ 10, 8, 11, 1, 8, 10, 1378 }, // »
{ 14, 13, 14, 0, 12, 23, 1388 }, // ¼
{ 14, 13, 14, 0, 12, 23, 1411 }, // ½
{ 15, 13, 15, 0, 12, 25, 1434 }, // ¾
{ 9, 13, 10, 0, 9, 15, 1459 }, // ¿
{ 11, 15, 11, 0, 15, 21, 1474 }, // À
{ 11, 15, 11, 0, 15, 21, 1495 }, // Á
{ 11, 15, 11, 0, 15, 21, 1516 }, // Â
{ 11, 15, 11, 0, 15, 21, 1537 }, // Ã
{ 11, 15, 11, 0, 15, 21, 1558 }, // Ä
{ 11, 16, 11, 0, 16, 22, 1579 }, // Å
{ 14, 12, 14, 0, 12, 21, 1601 }, // Æ
{ 9, 16, 11, 1, 12, 18, 1622 }, // Ç
{ 8, 15, 9, 1, 15, 15, 1640 }, // È
{ 8, 15, 9, 1, 15, 15, 1655 }, // É
{ 8, 15, 9, 1, 15, 15, 1670 }, // Ê
{ 8, 15, 9, 1, 15, 15, 1685 }, // Ë
{ 3, 15, 4, 0, 15, 6, 1700 }, // Ì
{ 3, 15, 4, 1, 15, 6, 1706 }, // Í
{ 6, 15, 4, -1, 15, 12, 1712 }, // Î
{ 6, 15, 4, -1, 15, 12, 1724 }, // Ï
{ 11, 12, 11, 0, 12, 17, 1736 }, // Ð
{ 9, 15, 11, 1, 15, 17, 1753 }, // Ñ
{ 10, 16, 11, 1, 15, 20, 1770 }, // Ò
{ 10, 16, 11, 1, 15, 20, 1790 }, // Ó
{ 10, 16, 11, 1, 15, 20, 1810 }, // Ô
{ 10, 16, 11, 1, 15, 20, 1830 }, // Õ
{ 10, 16, 11, 1, 15, 20, 1850 }, // Ö
{ 8, 8, 10, 1, 10, 8, 1870 }, // ×
{ 10, 15, 11, 1, 13, 19, 1878 }, // Ø
{ 9, 16, 11, 1, 15, 18, 1897 }, // Ù
{ 9, 16, 11, 1, 15, 18, 1915 }, // Ú
{ 9, 16, 11, 1, 15, 18, 1933 }, // Û
{ 9, 16, 11, 1, 15, 18, 1951 }, // Ü
{ 10, 15, 10, 0, 15, 19, 1969 }, // Ý
{ 9, 12, 10, 1, 12, 14, 1988 }, // Þ
{ 9, 13, 10, 1, 12, 15, 2002 }, // ß
{ 10, 13, 10, 0, 12, 17, 2017 }, // à
{ 10, 13, 10, 0, 12, 17, 2034 }, // á
{ 10, 13, 10, 0, 12, 17, 2051 }, // â
{ 10, 13, 10, 0, 12, 17, 2068 }, // ã
{ 10, 13, 10, 0, 12, 17, 2085 }, // ä
{ 10, 14, 10, 0, 13, 18, 2102 }, // å
{ 15, 10, 15, 0, 9, 19, 2120 }, // æ
{ 10, 13, 10, 0, 9, 17, 2139 }, // ç
{ 9, 13, 10, 0, 12, 15, 2156 }, // è
{ 9, 13, 10, 0, 12, 15, 2171 }, // é
{ 9, 13, 10, 0, 12, 15, 2186 }, // ê
{ 9, 13, 10, 0, 12, 15, 2201 }, // ë
{ 3, 12, 4, 0, 12, 5, 2216 }, // ì
{ 4, 12, 4, 1, 12, 6, 2221 }, // í
{ 6, 12, 4, -1, 12, 9, 2227 }, // î
{ 6, 12, 4, -1, 12, 9, 2236 }, // ï
{ 10, 14, 10, 0, 13, 18, 2245 }, // ð
{ 8, 12, 10, 1, 12, 12, 2263 }, // ñ
{ 10, 13, 10, 0, 12, 17, 2275 }, // ò
{ 10, 13, 10, 0, 12, 17, 2292 }, // ó
{ 10, 13, 10, 0, 12, 17, 2309 }, // ô
{ 10, 13, 10, 0, 12, 17, 2326 }, // õ
{ 10, 13, 10, 0, 12, 17, 2343 }, // ö
{ 8, 8, 10, 1, 10, 8, 2360 }, // ÷
{ 10, 12, 10, 0, 10, 15, 2368 }, // ø
{ 8, 13, 10, 1, 12, 13, 2383 }, // ù
{ 8, 13, 10, 1, 12, 13, 2396 }, // ú
{ 8, 13, 10, 1, 12, 13, 2409 }, // û
{ 8, 13, 10, 1, 12, 13, 2422 }, // ü
{ 8, 16, 10, 1, 12, 16, 2435 }, // ý
{ 9, 16, 11, 1, 12, 18, 2451 }, // þ
{ 8, 16, 10, 1, 12, 16, 2469 }, // ÿ
{ 11, 14, 11, 0, 14, 20, 2485 }, // Ā
{ 10, 12, 10, 0, 11, 15, 2505 }, // ā
{ 11, 15, 11, 0, 15, 21, 2520 }, // Ă
{ 10, 13, 10, 0, 12, 17, 2541 }, // ă
{ 11, 15, 11, 0, 12, 21, 2558 }, // Ą
{ 10, 12, 10, 0, 9, 15, 2579 }, // ą
{ 9, 16, 11, 1, 15, 18, 2594 }, // Ć
{ 10, 13, 10, 0, 12, 17, 2612 }, // ć
{ 9, 16, 11, 1, 15, 18, 2629 }, // Ĉ
{ 10, 13, 10, 0, 12, 17, 2647 }, // ĉ
{ 9, 16, 11, 1, 15, 18, 2664 }, // Ċ
{ 10, 13, 10, 0, 12, 17, 2682 }, // ċ
{ 9, 16, 11, 1, 15, 18, 2699 }, // Č
{ 10, 13, 10, 0, 12, 17, 2717 }, // č
{ 11, 15, 11, 0, 15, 21, 2734 }, // Ď
{ 13, 13, 12, 0, 12, 22, 2755 }, // ď
{ 11, 12, 11, 0, 12, 17, 2777 }, // Đ
{ 11, 13, 11, 0, 12, 18, 2794 }, // đ
{ 8, 14, 9, 1, 14, 14, 2812 }, // Ē
{ 9, 12, 10, 0, 11, 14, 2826 }, // ē
{ 8, 15, 9, 1, 15, 15, 2840 }, // Ĕ
{ 9, 13, 10, 0, 12, 15, 2855 }, // ĕ
{ 8, 15, 9, 1, 15, 15, 2870 }, // Ė
{ 9, 13, 10, 0, 12, 15, 2885 }, // ė
{ 8, 15, 9, 1, 12, 15, 2900 }, // Ę
{ 9, 12, 10, 0, 9, 14, 2915 }, // ę
{ 8, 15, 9, 1, 15, 15, 2929 }, // Ě
{ 9, 13, 10, 0, 12, 15, 2944 }, // ě
{ 9, 16, 11, 1, 15, 18, 2959 }, // Ĝ
{ 10, 16, 11, 0, 12, 20, 2977 }, // ĝ
{ 9, 16, 11, 1, 15, 18, 2997 }, // Ğ
{ 10, 16, 11, 0, 12, 20, 3015 }, // ğ
{ 9, 16, 11, 1, 15, 18, 3035 }, // Ġ
{ 10, 16, 11, 0, 12, 20, 3053 }, // ġ
{ 9, 17, 11, 1, 12, 20, 3073 }, // Ģ
{ 10, 17, 11, 0, 13, 22, 3093 }, // ģ
{ 9, 15, 11, 1, 15, 17, 3115 }, // Ĥ
{ 10, 15, 10, -1, 15, 19, 3132 }, // ĥ
{ 11, 12, 11, 0, 12, 17, 3151 }, // Ħ
{ 9, 12, 10, 0, 12, 14, 3168 }, // ħ
{ 6, 15, 4, -1, 15, 12, 3182 }, // Ĩ
{ 6, 12, 4, -1, 12, 9, 3194 }, // ĩ
{ 6, 14, 4, -1, 14, 11, 3203 }, // Ī
{ 6, 11, 4, -1, 11, 9, 3214 }, // ī
{ 6, 15, 4, -1, 15, 12, 3223 }, // Ĭ
{ 6, 12, 4, -1, 12, 9, 3235 }, // ĭ
{ 3, 15, 4, 1, 12, 6, 3244 }, // Į
{ 3, 15, 4, 1, 12, 6, 3250 }, // į
{ 3, 15, 4, 1, 15, 6, 3256 }, // İ
{ 2, 9, 4, 1, 9, 3, 3262 }, // ı
{ 12, 13, 12, 0, 12, 20, 3265 }, // IJ
{ 7, 16, 8, 1, 12, 14, 3285 }, // ij
{ 10, 16, 10, 0, 15, 20, 3299 }, // Ĵ
{ 6, 16, 4, -1, 12, 12, 3319 }, // ĵ
{ 9, 17, 10, 1, 12, 20, 3331 }, // Ķ
{ 8, 17, 9, 1, 12, 17, 3351 }, // ķ
{ 8, 9, 9, 1, 9, 9, 3368 }, // ĸ
{ 8, 15, 9, 1, 15, 15, 3377 }, // Ĺ
{ 3, 15, 4, 1, 15, 6, 3392 }, // ĺ
{ 8, 17, 9, 1, 12, 17, 3398 }, // Ļ
{ 2, 17, 4, 1, 12, 5, 3415 }, // ļ
{ 8, 12, 9, 1, 12, 12, 3420 }, // Ľ
{ 5, 12, 5, 1, 12, 8, 3432 }, // ľ
{ 8, 12, 9, 1, 12, 12, 3440 }, // Ŀ
{ 6, 12, 7, 1, 12, 9, 3452 }, // ŀ
{ 10, 12, 10, 0, 12, 15, 3461 }, // Ł
{ 6, 12, 6, 0, 12, 9, 3476 }, // ł
{ 9, 15, 11, 1, 15, 17, 3485 }, // Ń
{ 8, 12, 10, 1, 12, 12, 3502 }, // ń
{ 9, 17, 11, 1, 12, 20, 3514 }, // Ņ
{ 8, 14, 10, 1, 9, 14, 3534 }, // ņ
{ 9, 15, 11, 1, 15, 17, 3548 }, // Ň
{ 8, 12, 10, 1, 12, 12, 3565 }, // ň
{ 8, 13, 10, 1, 13, 13, 3577 }, // ʼn
{ 9, 16, 11, 1, 12, 18, 3590 }, // Ŋ
{ 8, 13, 10, 1, 9, 13, 3608 }, // ŋ
{ 10, 15, 11, 1, 14, 19, 3621 }, // Ō
{ 10, 12, 10, 0, 11, 15, 3640 }, // ō
{ 10, 16, 11, 1, 15, 20, 3655 }, // Ŏ
{ 10, 13, 10, 0, 12, 17, 3675 }, // ŏ
{ 10, 16, 11, 1, 15, 20, 3692 }, // Ő
{ 10, 13, 10, 0, 12, 17, 3712 }, // ő
{ 13, 12, 14, 1, 12, 20, 3729 }, // Œ
{ 17, 10, 17, 0, 9, 22, 3749 }, // œ
{ 9, 15, 11, 1, 15, 17, 3771 }, // Ŕ
{ 5, 12, 6, 1, 12, 8, 3788 }, // ŕ
{ 9, 17, 11, 1, 12, 20, 3796 }, // Ŗ
{ 5, 14, 6, 1, 9, 9, 3816 }, // ŗ
{ 9, 15, 11, 1, 15, 17, 3825 }, // Ř
{ 7, 12, 6, 0, 12, 11, 3842 }, // ř
{ 10, 16, 10, 0, 15, 20, 3853 }, // Ś
{ 8, 13, 9, 0, 12, 13, 3873 }, // ś
{ 10, 16, 10, 0, 15, 20, 3886 }, // Ŝ
{ 8, 13, 9, 0, 12, 13, 3906 }, // ŝ
{ 10, 16, 10, 0, 12, 20, 3919 }, // Ş
{ 8, 13, 9, 0, 9, 13, 3939 }, // ş
{ 10, 16, 10, 0, 15, 20, 3952 }, // Š
{ 8, 13, 9, 0, 12, 13, 3972 }, // š
{ 10, 16, 10, 0, 12, 20, 3985 }, // Ţ
{ 7, 16, 8, 0, 12, 14, 4005 }, // ţ
{ 10, 15, 10, 0, 15, 19, 4019 }, // Ť
{ 8, 13, 8, 0, 13, 13, 4038 }, // ť
{ 10, 12, 10, 0, 12, 15, 4051 }, // Ŧ
{ 7, 12, 8, 0, 12, 11, 4066 }, // ŧ
{ 9, 16, 11, 1, 15, 18, 4077 }, // Ũ
{ 8, 13, 10, 1, 12, 13, 4095 }, // ũ
{ 9, 15, 11, 1, 14, 17, 4108 }, // Ū
{ 8, 12, 10, 1, 11, 12, 4125 }, // ū
{ 9, 16, 11, 1, 15, 18, 4137 }, // Ŭ
{ 8, 13, 10, 1, 12, 13, 4155 }, // ŭ
{ 9, 17, 11, 1, 16, 20, 4168 }, // Ů
{ 8, 14, 10, 1, 13, 14, 4188 }, // ů
{ 9, 16, 11, 1, 15, 18, 4202 }, // Ű
{ 8, 13, 10, 1, 12, 13, 4220 }, // ű
{ 9, 15, 11, 1, 12, 17, 4233 }, // Ų
{ 9, 12, 10, 1, 9, 14, 4250 }, // ų
{ 14, 15, 15, 0, 15, 27, 4264 }, // Ŵ
{ 13, 12, 13, 0, 12, 20, 4291 }, // ŵ
{ 10, 15, 10, 0, 15, 19, 4311 }, // Ŷ
{ 8, 16, 10, 1, 12, 16, 4330 }, // ŷ
{ 10, 15, 10, 0, 15, 19, 4346 }, // Ÿ
{ 9, 15, 10, 0, 15, 17, 4365 }, // Ź
{ 7, 12, 9, 1, 12, 11, 4382 }, // ź
{ 9, 15, 10, 0, 15, 17, 4393 }, // Ż
{ 7, 12, 9, 1, 12, 11, 4410 }, // ż
{ 9, 15, 10, 0, 15, 17, 4421 }, // Ž
{ 7, 12, 9, 1, 12, 11, 4438 }, // ž
{ 6, 12, 6, 0, 12, 9, 4449 }, // ſ
{ 4, 3, 0, 0, 12, 2, 4458 }, // ̀
{ 4, 3, 0, 0, 12, 2, 4460 }, // ́
{ 7, 3, 0, 0, 12, 3, 4462 }, // ̂
{ 7, 3, 0, 0, 12, 3, 4465 }, // ̃
{ 7, 2, 0, 0, 11, 2, 4468 }, // ̄
{ 6, 3, 0, 0, 12, 3, 4470 }, // ̆
{ 3, 3, 0, 0, 12, 2, 4473 }, // ̇
{ 7, 3, 0, 0, 12, 3, 4475 }, // ̈
{ 5, 4, 0, 0, 13, 3, 4478 }, // ̉
{ 5, 4, 0, 0, 13, 3, 4481 }, // ̊
{ 6, 3, 0, 0, 12, 3, 4484 }, // ̋
{ 7, 3, 0, 0, 12, 3, 4487 }, // ̌
{ 6, 3, 0, 0, 12, 3, 4490 }, // ̏
{ 6, 3, 0, 0, 12, 3, 4493 }, // ̑
{ 3, 4, 0, 0, 13, 2, 4496 }, // ̒
{ 4, 3, 0, 0, 10, 2, 4498 }, // ̛
{ 3, 3, 0, 0, -1, 2, 4500 }, // ̣
{ 7, 3, 0, 0, -1, 3, 4502 }, // ̤
{ 3, 4, 0, 0, -1, 2, 4505 }, // ̦
{ 5, 5, 0, 0, 1, 4, 4507 }, // ̧
{ 4, 4, 0, 0, 1, 2, 4511 }, // ̨
{ 6, 3, 0, 0, -1, 3, 4513 }, // ̮
{ 7, 2, 0, 0, -1, 2, 4516 }, // ̱
{ 7, 2, 0, 0, 11, 2, 4518 }, // ̵
{ 12, 2, 0, 0, 10, 3, 4520 }, // ̶
{ 8, 12, 0, 0, 10, 12, 4523 }, // ̷
{ 8, 15, 0, 0, 13, 15, 4535 }, // ̸
{ 0, 0, 10, 0, 0, 0, 4550 }, //
{ 0, 0, 4, 0, 0, 0, 4550 }, //
{ 0, 0, 3, 0, 0, 0, 4550 }, //
{ 0, 0, 1, 0, 0, 0, 4550 }, //
{ 0, 0, 0, 0, 0, 0, 4550 }, //
{ 6, 2, 8, 1, 5, 2, 4550 }, //
{ 9, 2, 10, 1, 5, 3, 4552 }, //
{ 8, 2, 10, 1, 5, 2, 4555 }, //
{ 13, 2, 15, 1, 5, 4, 4557 }, // —
{ 13, 2, 15, 1, 5, 4, 4561 }, // ―
{ 4, 6, 4, 0, 13, 3, 4565 }, //
{ 4, 6, 4, 0, 13, 3, 4568 }, //
{ 4, 6, 4, 0, 3, 3, 4571 }, //
{ 7, 6, 7, 0, 13, 6, 4574 }, // “
{ 7, 6, 7, 0, 13, 6, 4580 }, // ”
{ 7, 6, 7, 0, 3, 6, 4586 }, // „
{ 8, 12, 10, 1, 12, 12, 4592 }, // †
{ 8, 12, 10, 1, 12, 12, 4604 }, // ‡
{ 4, 5, 6, 1, 7, 3, 4616 }, // •
{ 11, 4, 11, 0, 3, 6, 4619 }, // …
{ 16, 13, 16, 0, 12, 26, 4625 }, // ‰
{ 3, 5, 3, 0, 12, 2, 4651 }, //
{ 6, 5, 6, 0, 12, 4, 4653 }, // ″
{ 7, 8, 8, 0, 8, 7, 4657 }, //
{ 6, 8, 8, 1, 8, 6, 4664 }, //
{ 11, 13, 11, 0, 12, 18, 4670 }, //
{ 11, 13, 12, 0, 12, 18, 4688 }, // ⁒
{ 9, 16, 11, 1, 14, 18, 4706 }, // ₡
{ 10, 12, 10, 0, 12, 15, 4724 }, // ₣
{ 10, 12, 10, 0, 12, 15, 4739 }, // ₤
{ 12, 12, 13, 0, 12, 18, 4754 }, // ₦
{ 12, 12, 12, 0, 12, 18, 4772 }, // ₧
{ 16, 12, 16, 0, 12, 24, 4790 }, // ₩
{ 11, 14, 12, 0, 12, 20, 4814 }, // ₫
{ 11, 13, 11, 0, 12, 18, 4834 }, // €
{ 11, 12, 11, 0, 12, 17, 4852 }, // ₭
{ 12, 12, 12, 0, 12, 18, 4869 }, // ₱
{ 9, 16, 11, 1, 14, 18, 4887 }, // ₲
{ 9, 16, 11, 1, 14, 18, 4905 }, // ₵
{ 10, 12, 11, 1, 12, 15, 4923 }, // ₹
{ 9, 12, 9, 0, 12, 14, 4938 }, // ₺
{ 10, 14, 12, 1, 14, 18, 4952 }, // ₼
{ 11, 12, 11, 0, 12, 17, 4970 }, // ₽
{ 10, 16, 12, 1, 14, 20, 4987 }, // ₿
{ 13, 10, 13, 0, 9, 17, 5007 }, // ←
{ 10, 12, 10, 0, 12, 15, 5024 }, // ↑
{ 13, 10, 13, 0, 9, 17, 5039 }, // →
{ 10, 13, 10, 0, 12, 17, 5056 }, // ↓
{ 13, 10, 13, 0, 9, 17, 5073 }, // ↔
{ 10, 13, 10, 0, 12, 17, 5090 }, // ↕
{ 9, 10, 10, 1, 9, 12, 5107 }, // ↖
{ 9, 10, 10, 0, 9, 12, 5119 }, // ↗
{ 9, 9, 10, 0, 9, 11, 5131 }, // ↘
{ 9, 9, 10, 1, 9, 11, 5142 }, // ↙
{ 9, 13, 10, 1, 12, 15, 5153 }, // ∂
{ 10, 12, 11, 0, 10, 15, 5168 }, // ∅
{ 10, 12, 10, 0, 12, 15, 5183 }, // ∆
{ 9, 16, 10, 1, 12, 18, 5198 }, // ∏
{ 10, 16, 10, 0, 12, 20, 5216 }, // ∑
{ 8, 2, 10, 1, 7, 2, 5236 }, //
{ 7, 17, 6, 0, 14, 15, 5238 }, //
{ 5, 5, 10, 3, 8, 4, 5253 }, // ∙
{ 10, 15, 10, 0, 15, 19, 5257 }, // √
{ 10, 6, 10, 0, 9, 8, 5276 }, // ∞
{ 6, 16, 10, 2, 12, 12, 5284 }, // ∫
{ 8, 7, 10, 1, 9, 7, 5296 }, // ≈
{ 8, 8, 10, 1, 10, 8, 5303 }, // ≠
{ 8, 10, 10, 1, 10, 10, 5311 }, // ≤
{ 8, 10, 10, 1, 10, 10, 5321 }, // ≥
};
static const EpdUnicodeInterval spacegroteskIntervals[] = {
{ 0xD, 0xD, 0x0 },
{ 0x20, 0x7E, 0x1 },
{ 0xA0, 0xFF, 0x60 },
{ 0x100, 0x17F, 0xC0 },
{ 0x300, 0x304, 0x140 },
{ 0x306, 0x30C, 0x145 },
{ 0x30F, 0x30F, 0x14C },
{ 0x311, 0x312, 0x14D },
{ 0x31B, 0x31B, 0x14F },
{ 0x323, 0x324, 0x150 },
{ 0x326, 0x328, 0x152 },
{ 0x32E, 0x32E, 0x155 },
{ 0x331, 0x331, 0x156 },
{ 0x335, 0x338, 0x157 },
{ 0x2007, 0x200B, 0x15B },
{ 0x2010, 0x2010, 0x160 },
{ 0x2012, 0x2015, 0x161 },
{ 0x2018, 0x201A, 0x165 },
{ 0x201C, 0x201E, 0x168 },
{ 0x2020, 0x2022, 0x16B },
{ 0x2026, 0x2026, 0x16E },
{ 0x2030, 0x2030, 0x16F },
{ 0x2032, 0x2033, 0x170 },
{ 0x2039, 0x203A, 0x172 },
{ 0x2044, 0x2044, 0x174 },
{ 0x2052, 0x2052, 0x175 },
{ 0x20A1, 0x20A1, 0x176 },
{ 0x20A3, 0x20A4, 0x177 },
{ 0x20A6, 0x20A7, 0x179 },
{ 0x20A9, 0x20A9, 0x17B },
{ 0x20AB, 0x20AD, 0x17C },
{ 0x20B1, 0x20B2, 0x17F },
{ 0x20B5, 0x20B5, 0x181 },
{ 0x20B9, 0x20BA, 0x182 },
{ 0x20BC, 0x20BD, 0x184 },
{ 0x20BF, 0x20BF, 0x186 },
{ 0x2190, 0x2199, 0x187 },
{ 0x2202, 0x2202, 0x191 },
{ 0x2205, 0x2206, 0x192 },
{ 0x220F, 0x220F, 0x194 },
{ 0x2211, 0x2212, 0x195 },
{ 0x2215, 0x2215, 0x197 },
{ 0x2219, 0x221A, 0x198 },
{ 0x221E, 0x221E, 0x19A },
{ 0x222B, 0x222B, 0x19B },
{ 0x2248, 0x2248, 0x19C },
{ 0x2260, 0x2260, 0x19D },
{ 0x2264, 0x2265, 0x19E },
};
static const EpdFontData spacegrotesk = {
spacegroteskBitmaps,
spacegroteskGlyphs,
spacegroteskIntervals,
48,
21,
17,
-5,
false,
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,137 @@
#!/bin/bash
set -e
cd "$(dirname "$0")/../builtinFonts"
echo "// The contents of this file are generated by ./lib/EpdFont/scripts/build-font-ids.sh"
echo "#pragma once"
echo ""
echo "#define ALEO_12_FONT_ID ($(
ruby -rdigest -e 'puts [
"./aleo_12_regular.h",
"./aleo_12_bold.h",
"./aleo_12_bolditalic.h",
"./aleo_12_italic.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"
echo "#define ALEO_14_FONT_ID ($(
ruby -rdigest -e 'puts [
"./aleo_14_regular.h",
"./aleo_14_bold.h",
"./aleo_14_bolditalic.h",
"./aleo_14_italic.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"
echo "#define ALEO_16_FONT_ID ($(
ruby -rdigest -e 'puts [
"./aleo_16_regular.h",
"./aleo_16_bold.h",
"./aleo_16_bolditalic.h",
"./aleo_16_italic.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"
echo "#define ALEO_18_FONT_ID ($(
ruby -rdigest -e 'puts [
"./aleo_18_regular.h",
"./aleo_18_bold.h",
"./aleo_18_bolditalic.h",
"./aleo_18_italic.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"
echo "#define NOTOSANS_12_FONT_ID ($(
ruby -rdigest -e 'puts [
"./notosans_12_regular.h",
"./notosans_12_bold.h",
"./notosans_12_bolditalic.h",
"./notosans_12_italic.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"
echo "#define NOTOSANS_14_FONT_ID ($(
ruby -rdigest -e 'puts [
"./notosans_14_regular.h",
"./notosans_14_bold.h",
"./notosans_14_bolditalic.h",
"./notosans_14_italic.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"
echo "#define NOTOSANS_16_FONT_ID ($(
ruby -rdigest -e 'puts [
"./notosans_16_regular.h",
"./notosans_16_bold.h",
"./notosans_16_bolditalic.h",
"./notosans_16_italic.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"
echo "#define NOTOSANS_18_FONT_ID ($(
ruby -rdigest -e 'puts [
"./notosans_18_regular.h",
"./notosans_18_bold.h",
"./notosans_18_bolditalic.h",
"./notosans_18_italic.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"
echo "#define OPENDYSLEXIC_8_FONT_ID ($(
ruby -rdigest -e 'puts [
"./opendyslexic_8_regular.h",
"./opendyslexic_8_bold.h",
"./opendyslexic_8_bolditalic.h",
"./opendyslexic_8_italic.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"
echo "#define OPENDYSLEXIC_10_FONT_ID ($(
ruby -rdigest -e 'puts [
"./opendyslexic_10_regular.h",
"./opendyslexic_10_bold.h",
"./opendyslexic_10_bolditalic.h",
"./opendyslexic_10_italic.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"
echo "#define OPENDYSLEXIC_12_FONT_ID ($(
ruby -rdigest -e 'puts [
"./opendyslexic_12_regular.h",
"./opendyslexic_12_bold.h",
"./opendyslexic_12_bolditalic.h",
"./opendyslexic_12_italic.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"
echo "#define OPENDYSLEXIC_14_FONT_ID ($(
ruby -rdigest -e 'puts [
"./opendyslexic_14_regular.h",
"./opendyslexic_14_bold.h",
"./opendyslexic_14_bolditalic.h",
"./opendyslexic_14_italic.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"
echo "#define UI_10_FONT_ID ($(
ruby -rdigest -e 'puts [
"./ubuntu_10_regular.h",
"./ubuntu_10_bold.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"
echo "#define UI_12_FONT_ID ($(
ruby -rdigest -e 'puts [
"./ubuntu_12_regular.h",
"./ubuntu_12_bold.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"
echo "#define SMALL_FONT_ID ($(
ruby -rdigest -e 'puts [
"./spacegrotesk.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"

View File

@ -0,0 +1,55 @@
#!/bin/bash
set -e
cd "$(dirname "$0")"
READER_FONT_STYLES=("Regular" "Italic" "Bold" "BoldItalic")
ALEO_FONT_SIZES=(12 14 16 18)
NOTOSANS_FONT_SIZES=(12 14 16 18)
OPENDYSLEXIC_FONT_SIZES=(8 10 12 14)
for size in ${ALEO_FONT_SIZES[@]}; do
for style in ${READER_FONT_STYLES[@]}; do
font_name="aleo_${size}_$(echo $style | tr '[:upper:]' '[:lower:]')"
font_path="../builtinFonts/source/Aleo/Aleo-${style}.ttf"
output_path="../builtinFonts/${font_name}.h"
python fontconvert.py $font_name $size $font_path --2bit > $output_path
echo "Generated $output_path"
done
done
for size in ${NOTOSANS_FONT_SIZES[@]}; do
for style in ${READER_FONT_STYLES[@]}; do
font_name="notosans_${size}_$(echo $style | tr '[:upper:]' '[:lower:]')"
font_path="../builtinFonts/source/NotoSans/NotoSans-${style}.ttf"
output_path="../builtinFonts/${font_name}.h"
python fontconvert.py $font_name $size $font_path --2bit > $output_path
echo "Generated $output_path"
done
done
for size in ${OPENDYSLEXIC_FONT_SIZES[@]}; do
for style in ${READER_FONT_STYLES[@]}; do
font_name="opendyslexic_${size}_$(echo $style | tr '[:upper:]' '[:lower:]')"
font_path="../builtinFonts/source/OpenDyslexic/OpenDyslexic-${style}.otf"
output_path="../builtinFonts/${font_name}.h"
python fontconvert.py $font_name $size $font_path --2bit > $output_path
echo "Generated $output_path"
done
done
UI_FONT_SIZES=(10 12)
UI_FONT_STYLES=("Regular" "Bold")
for size in ${UI_FONT_SIZES[@]}; do
for style in ${UI_FONT_STYLES[@]}; do
font_name="ubuntu_${size}_$(echo $style | tr '[:upper:]' '[:lower:]')"
font_path="../builtinFonts/source/Ubuntu/Ubuntu-${style}.ttf"
output_path="../builtinFonts/${font_name}.h"
python fontconvert.py $font_name $size $font_path > $output_path
echo "Generated $output_path"
done
done
python fontconvert.py spacegrotesk 8 ../builtinFonts/source/SpaceGrotesk/SpaceGrotesk-Regular.ttf > ../builtinFonts/spacegrotesk.h

View File

@ -4,13 +4,15 @@
#include <SDCardManager.h> #include <SDCardManager.h>
#include <Serialization.h> #include <Serialization.h>
#include "fontIds.h"
// Initialize the static instance // Initialize the static instance
CrossPointSettings CrossPointSettings::instance; CrossPointSettings CrossPointSettings::instance;
namespace { namespace {
constexpr uint8_t SETTINGS_FILE_VERSION = 1; constexpr uint8_t SETTINGS_FILE_VERSION = 1;
// Increment this when adding new persisted settings fields // Increment this when adding new persisted settings fields
constexpr uint8_t SETTINGS_COUNT = 7; constexpr uint8_t SETTINGS_COUNT = 9;
constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin"; constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin";
} // namespace } // namespace
@ -32,6 +34,8 @@ bool CrossPointSettings::saveToFile() const {
serialization::writePod(outputFile, orientation); serialization::writePod(outputFile, orientation);
serialization::writePod(outputFile, frontButtonLayout); serialization::writePod(outputFile, frontButtonLayout);
serialization::writePod(outputFile, sideButtonLayout); serialization::writePod(outputFile, sideButtonLayout);
serialization::writePod(outputFile, fontFamily);
serialization::writePod(outputFile, fontSize);
outputFile.close(); outputFile.close();
Serial.printf("[%lu] [CPS] Settings saved to file\n", millis()); Serial.printf("[%lu] [CPS] Settings saved to file\n", millis());
@ -72,9 +76,55 @@ bool CrossPointSettings::loadFromFile() {
if (++settingsRead >= fileSettingsCount) break; if (++settingsRead >= fileSettingsCount) break;
serialization::readPod(inputFile, sideButtonLayout); serialization::readPod(inputFile, sideButtonLayout);
if (++settingsRead >= fileSettingsCount) break; if (++settingsRead >= fileSettingsCount) break;
serialization::readPod(inputFile, fontFamily);
if (++settingsRead >= fileSettingsCount) break;
serialization::readPod(inputFile, fontSize);
if (++settingsRead >= fileSettingsCount) break;
} while (false); } while (false);
inputFile.close(); inputFile.close();
Serial.printf("[%lu] [CPS] Settings loaded from file\n", millis()); Serial.printf("[%lu] [CPS] Settings loaded from file\n", millis());
return true; return true;
} }
int CrossPointSettings::getReaderFontId() const {
switch (fontFamily) {
case ALEO:
default:
switch (fontSize) {
case SMALL:
return ALEO_12_FONT_ID;
case MEDIUM:
default:
return ALEO_14_FONT_ID;
case LARGE:
return ALEO_16_FONT_ID;
case EXTRA_LARGE:
return ALEO_18_FONT_ID;
}
case NOTOSANS:
switch (fontSize) {
case SMALL:
return NOTOSANS_12_FONT_ID;
case MEDIUM:
default:
return NOTOSANS_14_FONT_ID;
case LARGE:
return NOTOSANS_16_FONT_ID;
case EXTRA_LARGE:
return NOTOSANS_18_FONT_ID;
}
case OPENDYSLEXIC:
switch (fontSize) {
case SMALL:
return OPENDYSLEXIC_8_FONT_ID;
case MEDIUM:
default:
return OPENDYSLEXIC_10_FONT_ID;
case LARGE:
return OPENDYSLEXIC_12_FONT_ID;
case EXTRA_LARGE:
return OPENDYSLEXIC_14_FONT_ID;
}
}
}

View File

@ -38,6 +38,11 @@ class CrossPointSettings {
// Swapped: Next, Previous // Swapped: Next, Previous
enum SIDE_BUTTON_LAYOUT { PREV_NEXT = 0, NEXT_PREV = 1 }; enum SIDE_BUTTON_LAYOUT { PREV_NEXT = 0, NEXT_PREV = 1 };
// Font family options
enum FONT_FAMILY { ALEO = 0, NOTOSANS = 1, OPENDYSLEXIC = 2 };
// Font size options
enum FONT_SIZE { SMALL = 0, MEDIUM = 1, LARGE = 2, EXTRA_LARGE = 3 };
// Sleep screen settings // Sleep screen settings
uint8_t sleepScreen = DARK; uint8_t sleepScreen = DARK;
// Status bar settings // Status bar settings
@ -53,6 +58,10 @@ class CrossPointSettings {
uint8_t frontButtonLayout = BACK_CONFIRM_LEFT_RIGHT; uint8_t frontButtonLayout = BACK_CONFIRM_LEFT_RIGHT;
// Side button layout // Side button layout
uint8_t sideButtonLayout = PREV_NEXT; uint8_t sideButtonLayout = PREV_NEXT;
// Font family
uint8_t fontFamily = ALEO;
// Font size
uint8_t fontSize = MEDIUM;
~CrossPointSettings() = default; ~CrossPointSettings() = default;
@ -60,6 +69,7 @@ class CrossPointSettings {
static CrossPointSettings& getInstance() { return instance; } static CrossPointSettings& getInstance() { return instance; }
uint16_t getPowerButtonDuration() const { return shortPwrBtn ? 10 : 400; } uint16_t getPowerButtonDuration() const { return shortPwrBtn ? 10 : 400; }
int getReaderFontId() const;
bool saveToFile() const; bool saveToFile() const;
bool loadFromFile(); bool loadFromFile();

View File

@ -2,7 +2,7 @@
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include "config.h" #include "fontIds.h"
#include "images/CrossLarge.h" #include "images/CrossLarge.h"
void BootActivity::onEnter() { void BootActivity::onEnter() {
@ -13,7 +13,7 @@ void BootActivity::onEnter() {
renderer.clearScreen(); renderer.clearScreen();
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_10_FONT_ID, pageHeight / 2 + 70, "CrossPoint", true, BOLD);
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight / 2 + 95, "BOOTING"); renderer.drawCenteredText(SMALL_FONT_ID, pageHeight / 2 + 95, "BOOTING");
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, CROSSPOINT_VERSION); renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, CROSSPOINT_VERSION);
renderer.displayBuffer(); renderer.displayBuffer();

View File

@ -1,7 +1,6 @@
#include "SleepActivity.h" #include "SleepActivity.h"
#include <Epub.h> #include <Epub.h>
#include <FsHelpers.h>
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include <SDCardManager.h> #include <SDCardManager.h>
#include <Xtc.h> #include <Xtc.h>
@ -10,7 +9,7 @@
#include "CrossPointSettings.h" #include "CrossPointSettings.h"
#include "CrossPointState.h" #include "CrossPointState.h"
#include "config.h" #include "fontIds.h"
#include "images/CrossLarge.h" #include "images/CrossLarge.h"
namespace { namespace {
@ -43,15 +42,15 @@ void SleepActivity::onEnter() {
} }
void SleepActivity::renderPopup(const char* message) const { void SleepActivity::renderPopup(const char* message) const {
const int textWidth = renderer.getTextWidth(READER_FONT_ID, message); const int textWidth = renderer.getTextWidth(UI_12_FONT_ID, message);
constexpr int margin = 20; constexpr int margin = 20;
const int x = (renderer.getScreenWidth() - textWidth - margin * 2) / 2; const int x = (renderer.getScreenWidth() - textWidth - margin * 2) / 2;
constexpr int y = 117; constexpr int y = 117;
const int w = textWidth + margin * 2; const int w = textWidth + margin * 2;
const int h = renderer.getLineHeight(READER_FONT_ID) + margin * 2; const int h = renderer.getLineHeight(UI_12_FONT_ID) + margin * 2;
// renderer.clearScreen(); // renderer.clearScreen();
renderer.fillRect(x + 5, y + 5, w - 10, h - 10, false); renderer.fillRect(x + 5, y + 5, w - 10, h - 10, false);
renderer.drawText(READER_FONT_ID, x + margin, y + margin, message); renderer.drawText(UI_12_FONT_ID, x + margin, y + margin, message);
renderer.drawRect(x + 5, y + 5, w - 10, h - 10); renderer.drawRect(x + 5, y + 5, w - 10, h - 10);
renderer.displayBuffer(); renderer.displayBuffer();
} }
@ -130,7 +129,7 @@ void SleepActivity::renderDefaultSleepScreen() const {
renderer.clearScreen(); renderer.clearScreen();
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_10_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");
// Make sleep screen dark unless light is selected in settings // Make sleep screen dark unless light is selected in settings

View File

@ -5,7 +5,7 @@
#include "CrossPointState.h" #include "CrossPointState.h"
#include "MappedInputManager.h" #include "MappedInputManager.h"
#include "config.h" #include "fontIds.h"
void HomeActivity::taskTrampoline(void* param) { void HomeActivity::taskTrampoline(void* param) {
auto* self = static_cast<HomeActivity*>(param); auto* self = static_cast<HomeActivity*>(param);
@ -103,7 +103,7 @@ void HomeActivity::render() const {
renderer.clearScreen(); renderer.clearScreen();
const auto pageWidth = renderer.getScreenWidth(); const auto pageWidth = renderer.getScreenWidth();
renderer.drawCenteredText(READER_FONT_ID, 10, "CrossPoint Reader", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, 10, "CrossPoint Reader", true, BOLD);
// Draw selection // Draw selection
renderer.fillRect(0, 60 + selectorIndex * 30 - 2, pageWidth - 1, 30); renderer.fillRect(0, 60 + selectorIndex * 30 - 2, pageWidth - 1, 30);
@ -125,30 +125,30 @@ void HomeActivity::render() const {
// Truncate if too long // Truncate if too long
std::string continueLabel = "Continue: " + bookName; std::string continueLabel = "Continue: " + bookName;
int itemWidth = renderer.getTextWidth(UI_FONT_ID, continueLabel.c_str()); int itemWidth = renderer.getTextWidth(UI_10_FONT_ID, continueLabel.c_str());
while (itemWidth > renderer.getScreenWidth() - 40 && continueLabel.length() > 8) { while (itemWidth > renderer.getScreenWidth() - 40 && continueLabel.length() > 8) {
continueLabel.replace(continueLabel.length() - 5, 5, "..."); continueLabel.replace(continueLabel.length() - 5, 5, "...");
itemWidth = renderer.getTextWidth(UI_FONT_ID, continueLabel.c_str()); itemWidth = renderer.getTextWidth(UI_10_FONT_ID, continueLabel.c_str());
Serial.printf("[%lu] [HOM] width: %lu, pageWidth: %lu\n", millis(), itemWidth, pageWidth); Serial.printf("[%lu] [HOM] width: %lu, pageWidth: %lu\n", millis(), itemWidth, pageWidth);
} }
renderer.drawText(UI_FONT_ID, 20, menuY, continueLabel.c_str(), selectorIndex != menuIndex); renderer.drawText(UI_10_FONT_ID, 20, menuY, continueLabel.c_str(), selectorIndex != menuIndex);
menuY += 30; menuY += 30;
menuIndex++; menuIndex++;
} }
renderer.drawText(UI_FONT_ID, 20, menuY, "Browse", selectorIndex != menuIndex); renderer.drawText(UI_10_FONT_ID, 20, menuY, "Browse", selectorIndex != menuIndex);
menuY += 30; menuY += 30;
menuIndex++; menuIndex++;
renderer.drawText(UI_FONT_ID, 20, menuY, "File transfer", selectorIndex != menuIndex); renderer.drawText(UI_10_FONT_ID, 20, menuY, "File transfer", selectorIndex != menuIndex);
menuY += 30; menuY += 30;
menuIndex++; menuIndex++;
renderer.drawText(UI_FONT_ID, 20, menuY, "Settings", selectorIndex != menuIndex); renderer.drawText(UI_10_FONT_ID, 20, menuY, "Settings", selectorIndex != menuIndex);
const auto labels = mappedInput.mapLabels("Back", "Confirm", "Left", "Right"); const auto labels = mappedInput.mapLabels("Back", "Confirm", "Left", "Right");
renderer.drawButtonHints(UI_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4); renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
renderer.displayBuffer(); renderer.displayBuffer();
} }

View File

@ -11,7 +11,7 @@
#include "MappedInputManager.h" #include "MappedInputManager.h"
#include "NetworkModeSelectionActivity.h" #include "NetworkModeSelectionActivity.h"
#include "WifiSelectionActivity.h" #include "WifiSelectionActivity.h"
#include "config.h" #include "fontIds.h"
namespace { namespace {
// AP Mode configuration // AP Mode configuration
@ -334,7 +334,7 @@ void CrossPointWebServerActivity::render() const {
} else if (state == WebServerActivityState::AP_STARTING) { } else if (state == WebServerActivityState::AP_STARTING) {
renderer.clearScreen(); renderer.clearScreen();
const auto pageHeight = renderer.getScreenHeight(); const auto pageHeight = renderer.getScreenHeight();
renderer.drawCenteredText(READER_FONT_ID, pageHeight / 2 - 20, "Starting Hotspot...", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, pageHeight / 2 - 20, "Starting Hotspot...", true, BOLD);
renderer.displayBuffer(); renderer.displayBuffer();
} }
} }
@ -365,22 +365,21 @@ void CrossPointWebServerActivity::renderServerRunning() const {
// Use consistent line spacing // Use consistent line spacing
constexpr int LINE_SPACING = 28; // Space between lines constexpr int LINE_SPACING = 28; // Space between lines
renderer.drawCenteredText(READER_FONT_ID, 15, "File Transfer", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, 15, "File Transfer", true, BOLD);
if (isApMode) { if (isApMode) {
// AP mode display - center the content block // AP mode display - center the content block
int startY = 55; int startY = 55;
renderer.drawCenteredText(UI_FONT_ID, startY, "Hotspot Mode", true, BOLD); renderer.drawCenteredText(UI_10_FONT_ID, startY, "Hotspot Mode", true, BOLD);
std::string ssidInfo = "Network: " + connectedSSID; std::string ssidInfo = "Network: " + connectedSSID;
renderer.drawCenteredText(UI_FONT_ID, startY + LINE_SPACING, ssidInfo.c_str(), true, REGULAR); renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING, ssidInfo.c_str());
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 2, "Connect your device to this WiFi network", renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 2, "Connect your device to this WiFi network");
true, REGULAR);
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 3, renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 3,
"or scan QR code with your phone to connect to Wifi.", true, REGULAR); "or scan QR code with your phone to connect to Wifi.");
// Show QR code for URL // Show QR code for URL
std::string wifiConfig = std::string("WIFI:T:WPA;S:") + connectedSSID + ";P:" + "" + ";;"; std::string wifiConfig = std::string("WIFI:T:WPA;S:") + connectedSSID + ";P:" + "" + ";;";
drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 4, wifiConfig); drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 4, wifiConfig);
@ -388,16 +387,15 @@ void CrossPointWebServerActivity::renderServerRunning() const {
startY += 6 * 29 + 3 * LINE_SPACING; startY += 6 * 29 + 3 * LINE_SPACING;
// Show primary URL (hostname) // Show primary URL (hostname)
std::string hostnameUrl = std::string("http://") + AP_HOSTNAME + ".local/"; std::string hostnameUrl = std::string("http://") + AP_HOSTNAME + ".local/";
renderer.drawCenteredText(UI_FONT_ID, startY + LINE_SPACING * 3, hostnameUrl.c_str(), true, BOLD); renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING * 3, hostnameUrl.c_str(), true, BOLD);
// Show IP address as fallback // Show IP address as fallback
std::string ipUrl = "or http://" + connectedIP + "/"; std::string ipUrl = "or http://" + connectedIP + "/";
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 4, ipUrl.c_str(), true, REGULAR); renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 4, ipUrl.c_str());
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 5, "Open this URL in your browser", true, REGULAR); renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 5, "Open this URL in your browser");
// Show QR code for URL // Show QR code for URL
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 6, "or scan QR code with your phone:", true, renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 6, "or scan QR code with your phone:");
REGULAR);
drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 7, hostnameUrl); drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 7, hostnameUrl);
} else { } else {
// STA mode display (original behavior) // STA mode display (original behavior)
@ -407,27 +405,26 @@ void CrossPointWebServerActivity::renderServerRunning() const {
if (ssidInfo.length() > 28) { if (ssidInfo.length() > 28) {
ssidInfo.replace(25, ssidInfo.length() - 25, "..."); ssidInfo.replace(25, ssidInfo.length() - 25, "...");
} }
renderer.drawCenteredText(UI_FONT_ID, startY, ssidInfo.c_str(), true, REGULAR); renderer.drawCenteredText(UI_10_FONT_ID, startY, ssidInfo.c_str());
std::string ipInfo = "IP Address: " + connectedIP; std::string ipInfo = "IP Address: " + connectedIP;
renderer.drawCenteredText(UI_FONT_ID, startY + LINE_SPACING, ipInfo.c_str(), true, REGULAR); renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING, ipInfo.c_str());
// Show web server URL prominently // Show web server URL prominently
std::string webInfo = "http://" + connectedIP + "/"; std::string webInfo = "http://" + connectedIP + "/";
renderer.drawCenteredText(UI_FONT_ID, startY + LINE_SPACING * 2, webInfo.c_str(), true, BOLD); renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING * 2, webInfo.c_str(), true, BOLD);
// Also show hostname URL // Also show hostname URL
std::string hostnameUrl = std::string("or http://") + AP_HOSTNAME + ".local/"; std::string hostnameUrl = std::string("or http://") + AP_HOSTNAME + ".local/";
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 3, hostnameUrl.c_str(), true, REGULAR); renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 3, hostnameUrl.c_str());
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 4, "Open this URL in your browser", true, REGULAR); renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 4, "Open this URL in your browser");
// Show QR code for URL // Show QR code for URL
drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 6, webInfo); drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 6, webInfo);
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 5, "or scan QR code with your phone:", true, renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 5, "or scan QR code with your phone:");
REGULAR);
} }
const auto labels = mappedInput.mapLabels("« Exit", "", "", ""); const auto labels = mappedInput.mapLabels("« Exit", "", "", "");
renderer.drawButtonHints(UI_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4); renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
} }

View File

@ -3,7 +3,7 @@
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include "MappedInputManager.h" #include "MappedInputManager.h"
#include "config.h" #include "fontIds.h"
namespace { namespace {
constexpr int MENU_ITEM_COUNT = 2; constexpr int MENU_ITEM_COUNT = 2;
@ -97,10 +97,10 @@ void NetworkModeSelectionActivity::render() const {
const auto pageHeight = renderer.getScreenHeight(); const auto pageHeight = renderer.getScreenHeight();
// Draw header // Draw header
renderer.drawCenteredText(READER_FONT_ID, 10, "File Transfer", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, 10, "File Transfer", true, BOLD);
// Draw subtitle // Draw subtitle
renderer.drawCenteredText(UI_FONT_ID, 50, "How would you like to connect?", true, REGULAR); renderer.drawCenteredText(UI_10_FONT_ID, 50, "How would you like to connect?");
// Draw menu items centered on screen // Draw menu items centered on screen
constexpr int itemHeight = 50; // Height for each menu item (including description) constexpr int itemHeight = 50; // Height for each menu item (including description)
@ -117,13 +117,13 @@ void NetworkModeSelectionActivity::render() const {
// Draw text: black=false (white text) when selected (on black background) // Draw text: black=false (white text) when selected (on black background)
// black=true (black text) when not selected (on white background) // black=true (black text) when not selected (on white background)
renderer.drawText(UI_FONT_ID, 30, itemY, MENU_ITEMS[i], /*black=*/!isSelected); renderer.drawText(UI_10_FONT_ID, 30, itemY, MENU_ITEMS[i], /*black=*/!isSelected);
renderer.drawText(SMALL_FONT_ID, 30, itemY + 22, MENU_DESCRIPTIONS[i], /*black=*/!isSelected); renderer.drawText(SMALL_FONT_ID, 30, itemY + 22, MENU_DESCRIPTIONS[i], /*black=*/!isSelected);
} }
// Draw help text at bottom // Draw help text at bottom
const auto labels = mappedInput.mapLabels("« Back", "Select", "", ""); const auto labels = mappedInput.mapLabels("« Back", "Select", "", "");
renderer.drawButtonHints(UI_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4); renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
renderer.displayBuffer(); renderer.displayBuffer();
} }

View File

@ -8,7 +8,7 @@
#include "MappedInputManager.h" #include "MappedInputManager.h"
#include "WifiCredentialStore.h" #include "WifiCredentialStore.h"
#include "activities/util/KeyboardEntryActivity.h" #include "activities/util/KeyboardEntryActivity.h"
#include "config.h" #include "fontIds.h"
void WifiSelectionActivity::taskTrampoline(void* param) { void WifiSelectionActivity::taskTrampoline(void* param) {
auto* self = static_cast<WifiSelectionActivity*>(param); auto* self = static_cast<WifiSelectionActivity*>(param);
@ -496,14 +496,14 @@ void WifiSelectionActivity::renderNetworkList() const {
const auto pageHeight = renderer.getScreenHeight(); const auto pageHeight = renderer.getScreenHeight();
// Draw header // Draw header
renderer.drawCenteredText(READER_FONT_ID, 10, "WiFi Networks", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, 10, "WiFi Networks", true, BOLD);
if (networks.empty()) { if (networks.empty()) {
// No networks found or scan failed // No networks found or scan failed
const auto height = renderer.getLineHeight(UI_FONT_ID); const auto height = renderer.getLineHeight(UI_10_FONT_ID);
const auto top = (pageHeight - height) / 2; const auto top = (pageHeight - height) / 2;
renderer.drawCenteredText(UI_FONT_ID, top, "No networks found", true, REGULAR); renderer.drawCenteredText(UI_10_FONT_ID, top, "No networks found");
renderer.drawCenteredText(SMALL_FONT_ID, top + height + 10, "Press OK to scan again", true, REGULAR); renderer.drawCenteredText(SMALL_FONT_ID, top + height + 10, "Press OK to scan again");
} else { } else {
// Calculate how many networks we can display // Calculate how many networks we can display
constexpr int startY = 60; constexpr int startY = 60;
@ -524,7 +524,7 @@ void WifiSelectionActivity::renderNetworkList() const {
// Draw selection indicator // Draw selection indicator
if (static_cast<int>(i) == selectedNetworkIndex) { if (static_cast<int>(i) == selectedNetworkIndex) {
renderer.drawText(UI_FONT_ID, 5, networkY, ">"); renderer.drawText(UI_10_FONT_ID, 5, networkY, ">");
} }
// Draw network name (truncate if too long) // Draw network name (truncate if too long)
@ -532,20 +532,20 @@ void WifiSelectionActivity::renderNetworkList() const {
if (displayName.length() > 16) { if (displayName.length() > 16) {
displayName.replace(13, displayName.length() - 13, "..."); displayName.replace(13, displayName.length() - 13, "...");
} }
renderer.drawText(UI_FONT_ID, 20, networkY, displayName.c_str()); renderer.drawText(UI_10_FONT_ID, 20, networkY, displayName.c_str());
// Draw signal strength indicator // Draw signal strength indicator
std::string signalStr = getSignalStrengthIndicator(network.rssi); std::string signalStr = getSignalStrengthIndicator(network.rssi);
renderer.drawText(UI_FONT_ID, pageWidth - 90, networkY, signalStr.c_str()); renderer.drawText(UI_10_FONT_ID, pageWidth - 90, networkY, signalStr.c_str());
// Draw saved indicator (checkmark) for networks with saved passwords // Draw saved indicator (checkmark) for networks with saved passwords
if (network.hasSavedPassword) { if (network.hasSavedPassword) {
renderer.drawText(UI_FONT_ID, pageWidth - 50, networkY, "+"); renderer.drawText(UI_10_FONT_ID, pageWidth - 50, networkY, "+");
} }
// Draw lock icon for encrypted networks // Draw lock icon for encrypted networks
if (network.isEncrypted) { if (network.isEncrypted) {
renderer.drawText(UI_FONT_ID, pageWidth - 30, networkY, "*"); renderer.drawText(UI_10_FONT_ID, pageWidth - 30, networkY, "*");
} }
} }
@ -566,61 +566,61 @@ void WifiSelectionActivity::renderNetworkList() const {
// Draw help text // Draw help text
renderer.drawText(SMALL_FONT_ID, 20, pageHeight - 75, "* = Encrypted | + = Saved"); renderer.drawText(SMALL_FONT_ID, 20, pageHeight - 75, "* = Encrypted | + = Saved");
const auto labels = mappedInput.mapLabels("« Back", "Connect", "", ""); const auto labels = mappedInput.mapLabels("« Back", "Connect", "", "");
renderer.drawButtonHints(UI_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4); renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
} }
void WifiSelectionActivity::renderConnecting() const { void WifiSelectionActivity::renderConnecting() const {
const auto pageHeight = renderer.getScreenHeight(); const auto pageHeight = renderer.getScreenHeight();
const auto height = renderer.getLineHeight(UI_FONT_ID); const auto height = renderer.getLineHeight(UI_10_FONT_ID);
const auto top = (pageHeight - height) / 2; const auto top = (pageHeight - height) / 2;
if (state == WifiSelectionState::SCANNING) { if (state == WifiSelectionState::SCANNING) {
renderer.drawCenteredText(UI_FONT_ID, top, "Scanning...", true, REGULAR); renderer.drawCenteredText(UI_10_FONT_ID, top, "Scanning...");
} else { } else {
renderer.drawCenteredText(READER_FONT_ID, top - 40, "Connecting...", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Connecting...", true, BOLD);
std::string ssidInfo = "to " + selectedSSID; std::string ssidInfo = "to " + selectedSSID;
if (ssidInfo.length() > 25) { if (ssidInfo.length() > 25) {
ssidInfo.replace(22, ssidInfo.length() - 22, "..."); ssidInfo.replace(22, ssidInfo.length() - 22, "...");
} }
renderer.drawCenteredText(UI_FONT_ID, top, ssidInfo.c_str(), true, REGULAR); renderer.drawCenteredText(UI_10_FONT_ID, top, ssidInfo.c_str());
} }
} }
void WifiSelectionActivity::renderConnected() const { void WifiSelectionActivity::renderConnected() const {
const auto pageHeight = renderer.getScreenHeight(); const auto pageHeight = renderer.getScreenHeight();
const auto height = renderer.getLineHeight(UI_FONT_ID); const auto height = renderer.getLineHeight(UI_10_FONT_ID);
const auto top = (pageHeight - height * 4) / 2; const auto top = (pageHeight - height * 4) / 2;
renderer.drawCenteredText(READER_FONT_ID, top - 30, "Connected!", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, top - 30, "Connected!", true, BOLD);
std::string ssidInfo = "Network: " + selectedSSID; std::string ssidInfo = "Network: " + selectedSSID;
if (ssidInfo.length() > 28) { if (ssidInfo.length() > 28) {
ssidInfo.replace(25, ssidInfo.length() - 25, "..."); ssidInfo.replace(25, ssidInfo.length() - 25, "...");
} }
renderer.drawCenteredText(UI_FONT_ID, top + 10, ssidInfo.c_str(), true, REGULAR); renderer.drawCenteredText(UI_10_FONT_ID, top + 10, ssidInfo.c_str());
const std::string ipInfo = "IP Address: " + connectedIP; const std::string ipInfo = "IP Address: " + connectedIP;
renderer.drawCenteredText(UI_FONT_ID, top + 40, ipInfo.c_str(), true, REGULAR); renderer.drawCenteredText(UI_10_FONT_ID, top + 40, ipInfo.c_str());
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "Press any button to continue", true, REGULAR); renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "Press any button to continue");
} }
void WifiSelectionActivity::renderSavePrompt() const { void WifiSelectionActivity::renderSavePrompt() const {
const auto pageWidth = renderer.getScreenWidth(); const auto pageWidth = renderer.getScreenWidth();
const auto pageHeight = renderer.getScreenHeight(); const auto pageHeight = renderer.getScreenHeight();
const auto height = renderer.getLineHeight(UI_FONT_ID); const auto height = renderer.getLineHeight(UI_10_FONT_ID);
const auto top = (pageHeight - height * 3) / 2; const auto top = (pageHeight - height * 3) / 2;
renderer.drawCenteredText(READER_FONT_ID, top - 40, "Connected!", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Connected!", true, BOLD);
std::string ssidInfo = "Network: " + selectedSSID; std::string ssidInfo = "Network: " + selectedSSID;
if (ssidInfo.length() > 28) { if (ssidInfo.length() > 28) {
ssidInfo.replace(25, ssidInfo.length() - 25, "..."); ssidInfo.replace(25, ssidInfo.length() - 25, "...");
} }
renderer.drawCenteredText(UI_FONT_ID, top, ssidInfo.c_str(), true, REGULAR); renderer.drawCenteredText(UI_10_FONT_ID, top, ssidInfo.c_str());
renderer.drawCenteredText(UI_FONT_ID, top + 40, "Save password for next time?", true, REGULAR); renderer.drawCenteredText(UI_10_FONT_ID, top + 40, "Save password for next time?");
// Draw Yes/No buttons // Draw Yes/No buttons
const int buttonY = top + 80; const int buttonY = top + 80;
@ -631,46 +631,46 @@ void WifiSelectionActivity::renderSavePrompt() const {
// Draw "Yes" button // Draw "Yes" button
if (savePromptSelection == 0) { if (savePromptSelection == 0) {
renderer.drawText(UI_FONT_ID, startX, buttonY, "[Yes]"); renderer.drawText(UI_10_FONT_ID, startX, buttonY, "[Yes]");
} else { } else {
renderer.drawText(UI_FONT_ID, startX + 4, buttonY, "Yes"); renderer.drawText(UI_10_FONT_ID, startX + 4, buttonY, "Yes");
} }
// Draw "No" button // Draw "No" button
if (savePromptSelection == 1) { if (savePromptSelection == 1) {
renderer.drawText(UI_FONT_ID, startX + buttonWidth + buttonSpacing, buttonY, "[No]"); renderer.drawText(UI_10_FONT_ID, startX + buttonWidth + buttonSpacing, buttonY, "[No]");
} else { } else {
renderer.drawText(UI_FONT_ID, startX + buttonWidth + buttonSpacing + 4, buttonY, "No"); renderer.drawText(UI_10_FONT_ID, startX + buttonWidth + buttonSpacing + 4, buttonY, "No");
} }
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "LEFT/RIGHT: Select | OK: Confirm", true, REGULAR); renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "LEFT/RIGHT: Select | OK: Confirm");
} }
void WifiSelectionActivity::renderConnectionFailed() const { void WifiSelectionActivity::renderConnectionFailed() const {
const auto pageHeight = renderer.getScreenHeight(); const auto pageHeight = renderer.getScreenHeight();
const auto height = renderer.getLineHeight(UI_FONT_ID); const auto height = renderer.getLineHeight(UI_10_FONT_ID);
const auto top = (pageHeight - height * 2) / 2; const auto top = (pageHeight - height * 2) / 2;
renderer.drawCenteredText(READER_FONT_ID, top - 20, "Connection Failed", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, top - 20, "Connection Failed", true, BOLD);
renderer.drawCenteredText(UI_FONT_ID, top + 20, connectionError.c_str(), true, REGULAR); renderer.drawCenteredText(UI_10_FONT_ID, top + 20, connectionError.c_str());
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "Press any button to continue", true, REGULAR); renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "Press any button to continue");
} }
void WifiSelectionActivity::renderForgetPrompt() const { void WifiSelectionActivity::renderForgetPrompt() const {
const auto pageWidth = renderer.getScreenWidth(); const auto pageWidth = renderer.getScreenWidth();
const auto pageHeight = renderer.getScreenHeight(); const auto pageHeight = renderer.getScreenHeight();
const auto height = renderer.getLineHeight(UI_FONT_ID); const auto height = renderer.getLineHeight(UI_10_FONT_ID);
const auto top = (pageHeight - height * 3) / 2; const auto top = (pageHeight - height * 3) / 2;
renderer.drawCenteredText(READER_FONT_ID, top - 40, "Forget Network?", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Forget Network?", true, BOLD);
std::string ssidInfo = "Network: " + selectedSSID; std::string ssidInfo = "Network: " + selectedSSID;
if (ssidInfo.length() > 28) { if (ssidInfo.length() > 28) {
ssidInfo.replace(25, ssidInfo.length() - 25, "..."); ssidInfo.replace(25, ssidInfo.length() - 25, "...");
} }
renderer.drawCenteredText(UI_FONT_ID, top, ssidInfo.c_str(), true, REGULAR); renderer.drawCenteredText(UI_10_FONT_ID, top, ssidInfo.c_str());
renderer.drawCenteredText(UI_FONT_ID, top + 40, "Remove saved password?", true, REGULAR); renderer.drawCenteredText(UI_10_FONT_ID, top + 40, "Remove saved password?");
// Draw Yes/No buttons // Draw Yes/No buttons
const int buttonY = top + 80; const int buttonY = top + 80;
@ -681,17 +681,17 @@ void WifiSelectionActivity::renderForgetPrompt() const {
// Draw "Yes" button // Draw "Yes" button
if (forgetPromptSelection == 0) { if (forgetPromptSelection == 0) {
renderer.drawText(UI_FONT_ID, startX, buttonY, "[Yes]"); renderer.drawText(UI_10_FONT_ID, startX, buttonY, "[Yes]");
} else { } else {
renderer.drawText(UI_FONT_ID, startX + 4, buttonY, "Yes"); renderer.drawText(UI_10_FONT_ID, startX + 4, buttonY, "Yes");
} }
// Draw "No" button // Draw "No" button
if (forgetPromptSelection == 1) { if (forgetPromptSelection == 1) {
renderer.drawText(UI_FONT_ID, startX + buttonWidth + buttonSpacing, buttonY, "[No]"); renderer.drawText(UI_10_FONT_ID, startX + buttonWidth + buttonSpacing, buttonY, "[No]");
} else { } else {
renderer.drawText(UI_FONT_ID, startX + buttonWidth + buttonSpacing + 4, buttonY, "No"); renderer.drawText(UI_10_FONT_ID, startX + buttonWidth + buttonSpacing + 4, buttonY, "No");
} }
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "LEFT/RIGHT: Select | OK: Confirm", true, REGULAR); renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "LEFT/RIGHT: Select | OK: Confirm");
} }

View File

@ -10,13 +10,14 @@
#include "CrossPointState.h" #include "CrossPointState.h"
#include "EpubReaderChapterSelectionActivity.h" #include "EpubReaderChapterSelectionActivity.h"
#include "MappedInputManager.h" #include "MappedInputManager.h"
#include "config.h" #include "fontIds.h"
namespace { namespace {
constexpr int pagesPerRefresh = 15; constexpr int pagesPerRefresh = 15;
constexpr unsigned long skipChapterMs = 700; constexpr unsigned long skipChapterMs = 700;
constexpr unsigned long goHomeMs = 1000; constexpr unsigned long goHomeMs = 1000;
constexpr float lineCompression = 0.95f; constexpr float lineCompression = 0.95f;
constexpr int topPadding = 5;
constexpr int horizontalPadding = 5; constexpr int horizontalPadding = 5;
constexpr int statusBarMargin = 19; constexpr int statusBarMargin = 19;
} // namespace } // namespace
@ -234,7 +235,7 @@ void EpubReaderActivity::renderScreen() {
// Show end of book screen // Show end of book screen
if (currentSpineIndex == epub->getSpineItemsCount()) { if (currentSpineIndex == epub->getSpineItemsCount()) {
renderer.clearScreen(); renderer.clearScreen();
renderer.drawCenteredText(READER_FONT_ID, 300, "End of book", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, 300, "End of book", true, BOLD);
renderer.displayBuffer(); renderer.displayBuffer();
return; return;
} }
@ -243,6 +244,7 @@ void EpubReaderActivity::renderScreen() {
int orientedMarginTop, orientedMarginRight, orientedMarginBottom, orientedMarginLeft; int orientedMarginTop, orientedMarginRight, orientedMarginBottom, orientedMarginLeft;
renderer.getOrientedViewableTRBL(&orientedMarginTop, &orientedMarginRight, &orientedMarginBottom, renderer.getOrientedViewableTRBL(&orientedMarginTop, &orientedMarginRight, &orientedMarginBottom,
&orientedMarginLeft); &orientedMarginLeft);
orientedMarginTop += topPadding;
orientedMarginLeft += horizontalPadding; orientedMarginLeft += horizontalPadding;
orientedMarginRight += horizontalPadding; orientedMarginRight += horizontalPadding;
orientedMarginBottom += statusBarMargin; orientedMarginBottom += statusBarMargin;
@ -255,29 +257,29 @@ void EpubReaderActivity::renderScreen() {
const auto viewportWidth = renderer.getScreenWidth() - orientedMarginLeft - orientedMarginRight; const auto viewportWidth = renderer.getScreenWidth() - orientedMarginLeft - orientedMarginRight;
const auto viewportHeight = renderer.getScreenHeight() - orientedMarginTop - orientedMarginBottom; const auto viewportHeight = renderer.getScreenHeight() - orientedMarginTop - orientedMarginBottom;
if (!section->loadSectionFile(READER_FONT_ID, lineCompression, SETTINGS.extraParagraphSpacing, viewportWidth, if (!section->loadSectionFile(SETTINGS.getReaderFontId(), lineCompression, SETTINGS.extraParagraphSpacing,
viewportHeight)) { viewportWidth, viewportHeight)) {
Serial.printf("[%lu] [ERS] Cache not found, building...\n", millis()); Serial.printf("[%lu] [ERS] Cache not found, building...\n", millis());
// Progress bar dimensions // Progress bar dimensions
constexpr int barWidth = 200; constexpr int barWidth = 200;
constexpr int barHeight = 10; constexpr int barHeight = 10;
constexpr int boxMargin = 20; constexpr int boxMargin = 20;
const int textWidth = renderer.getTextWidth(READER_FONT_ID, "Indexing..."); const int textWidth = renderer.getTextWidth(UI_12_FONT_ID, "Indexing...");
const int boxWidthWithBar = (barWidth > textWidth ? barWidth : textWidth) + boxMargin * 2; const int boxWidthWithBar = (barWidth > textWidth ? barWidth : textWidth) + boxMargin * 2;
const int boxWidthNoBar = textWidth + boxMargin * 2; const int boxWidthNoBar = textWidth + boxMargin * 2;
const int boxHeightWithBar = renderer.getLineHeight(READER_FONT_ID) + barHeight + boxMargin * 3; const int boxHeightWithBar = renderer.getLineHeight(UI_12_FONT_ID) + barHeight + boxMargin * 3;
const int boxHeightNoBar = renderer.getLineHeight(READER_FONT_ID) + boxMargin * 2; const int boxHeightNoBar = renderer.getLineHeight(UI_12_FONT_ID) + boxMargin * 2;
const int boxXWithBar = (renderer.getScreenWidth() - boxWidthWithBar) / 2; const int boxXWithBar = (renderer.getScreenWidth() - boxWidthWithBar) / 2;
const int boxXNoBar = (renderer.getScreenWidth() - boxWidthNoBar) / 2; const int boxXNoBar = (renderer.getScreenWidth() - boxWidthNoBar) / 2;
constexpr int boxY = 50; constexpr int boxY = 50;
const int barX = boxXWithBar + (boxWidthWithBar - barWidth) / 2; const int barX = boxXWithBar + (boxWidthWithBar - barWidth) / 2;
const int barY = boxY + renderer.getLineHeight(READER_FONT_ID) + boxMargin * 2; const int barY = boxY + renderer.getLineHeight(UI_12_FONT_ID) + boxMargin * 2;
// Always show "Indexing..." text first // Always show "Indexing..." text first
{ {
renderer.fillRect(boxXNoBar, boxY, boxWidthNoBar, boxHeightNoBar, false); renderer.fillRect(boxXNoBar, boxY, boxWidthNoBar, boxHeightNoBar, false);
renderer.drawText(READER_FONT_ID, boxXNoBar + boxMargin, boxY + boxMargin, "Indexing..."); renderer.drawText(UI_12_FONT_ID, boxXNoBar + boxMargin, boxY + boxMargin, "Indexing...");
renderer.drawRect(boxXNoBar + 5, boxY + 5, boxWidthNoBar - 10, boxHeightNoBar - 10); renderer.drawRect(boxXNoBar + 5, boxY + 5, boxWidthNoBar - 10, boxHeightNoBar - 10);
renderer.displayBuffer(); renderer.displayBuffer();
pagesUntilFullRefresh = 0; pagesUntilFullRefresh = 0;
@ -286,7 +288,7 @@ void EpubReaderActivity::renderScreen() {
// Setup callback - only called for chapters >= 50KB, redraws with progress bar // Setup callback - only called for chapters >= 50KB, redraws with progress bar
auto progressSetup = [this, boxXWithBar, boxWidthWithBar, boxHeightWithBar, barX, barY] { auto progressSetup = [this, boxXWithBar, boxWidthWithBar, boxHeightWithBar, barX, barY] {
renderer.fillRect(boxXWithBar, boxY, boxWidthWithBar, boxHeightWithBar, false); renderer.fillRect(boxXWithBar, boxY, boxWidthWithBar, boxHeightWithBar, false);
renderer.drawText(READER_FONT_ID, boxXWithBar + boxMargin, boxY + boxMargin, "Indexing..."); renderer.drawText(UI_12_FONT_ID, boxXWithBar + boxMargin, boxY + boxMargin, "Indexing...");
renderer.drawRect(boxXWithBar + 5, boxY + 5, boxWidthWithBar - 10, boxHeightWithBar - 10); renderer.drawRect(boxXWithBar + 5, boxY + 5, boxWidthWithBar - 10, boxHeightWithBar - 10);
renderer.drawRect(barX, barY, barWidth, barHeight); renderer.drawRect(barX, barY, barWidth, barHeight);
renderer.displayBuffer(); renderer.displayBuffer();
@ -299,8 +301,8 @@ void EpubReaderActivity::renderScreen() {
renderer.displayBuffer(EInkDisplay::FAST_REFRESH); renderer.displayBuffer(EInkDisplay::FAST_REFRESH);
}; };
if (!section->createSectionFile(READER_FONT_ID, lineCompression, SETTINGS.extraParagraphSpacing, viewportWidth, if (!section->createSectionFile(SETTINGS.getReaderFontId(), lineCompression, SETTINGS.extraParagraphSpacing,
viewportHeight, progressSetup, progressCallback)) { viewportWidth, viewportHeight, progressSetup, progressCallback)) {
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;
@ -320,7 +322,7 @@ void EpubReaderActivity::renderScreen() {
if (section->pageCount == 0) { if (section->pageCount == 0) {
Serial.printf("[%lu] [ERS] No pages to render\n", millis()); Serial.printf("[%lu] [ERS] No pages to render\n", millis());
renderer.drawCenteredText(READER_FONT_ID, 300, "Empty chapter", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, 300, "Empty chapter", true, BOLD);
renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft); renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft);
renderer.displayBuffer(); renderer.displayBuffer();
return; return;
@ -328,7 +330,7 @@ void EpubReaderActivity::renderScreen() {
if (section->currentPage < 0 || section->currentPage >= section->pageCount) { if (section->currentPage < 0 || section->currentPage >= section->pageCount) {
Serial.printf("[%lu] [ERS] Page out of bounds: %d (max %d)\n", millis(), section->currentPage, section->pageCount); Serial.printf("[%lu] [ERS] Page out of bounds: %d (max %d)\n", millis(), section->currentPage, section->pageCount);
renderer.drawCenteredText(READER_FONT_ID, 300, "Out of bounds", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, 300, "Out of bounds", true, BOLD);
renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft); renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft);
renderer.displayBuffer(); renderer.displayBuffer();
return; return;
@ -362,7 +364,7 @@ void EpubReaderActivity::renderScreen() {
void EpubReaderActivity::renderContents(std::unique_ptr<Page> page, const int orientedMarginTop, void EpubReaderActivity::renderContents(std::unique_ptr<Page> page, const int orientedMarginTop,
const int orientedMarginRight, const int orientedMarginBottom, const int orientedMarginRight, const int orientedMarginBottom,
const int orientedMarginLeft) { const int orientedMarginLeft) {
page->render(renderer, READER_FONT_ID, orientedMarginLeft, orientedMarginTop); page->render(renderer, SETTINGS.getReaderFontId(), orientedMarginLeft, orientedMarginTop);
renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft); renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft);
if (pagesUntilFullRefresh <= 1) { if (pagesUntilFullRefresh <= 1) {
renderer.displayBuffer(EInkDisplay::HALF_REFRESH); renderer.displayBuffer(EInkDisplay::HALF_REFRESH);
@ -380,13 +382,13 @@ void EpubReaderActivity::renderContents(std::unique_ptr<Page> page, const int or
{ {
renderer.clearScreen(0x00); renderer.clearScreen(0x00);
renderer.setRenderMode(GfxRenderer::GRAYSCALE_LSB); renderer.setRenderMode(GfxRenderer::GRAYSCALE_LSB);
page->render(renderer, READER_FONT_ID, orientedMarginLeft, orientedMarginTop); page->render(renderer, SETTINGS.getReaderFontId(), orientedMarginLeft, orientedMarginTop);
renderer.copyGrayscaleLsbBuffers(); renderer.copyGrayscaleLsbBuffers();
// Render and copy to MSB buffer // Render and copy to MSB buffer
renderer.clearScreen(0x00); renderer.clearScreen(0x00);
renderer.setRenderMode(GfxRenderer::GRAYSCALE_MSB); renderer.setRenderMode(GfxRenderer::GRAYSCALE_MSB);
page->render(renderer, READER_FONT_ID, orientedMarginLeft, orientedMarginTop); page->render(renderer, SETTINGS.getReaderFontId(), orientedMarginLeft, orientedMarginTop);
renderer.copyGrayscaleMsbBuffers(); renderer.copyGrayscaleMsbBuffers();
// display grayscale part // display grayscale part
@ -409,7 +411,7 @@ void EpubReaderActivity::renderStatusBar(const int orientedMarginRight, const in
// Position status bar near the bottom of the logical screen, regardless of orientation // Position status bar near the bottom of the logical screen, regardless of orientation
const auto screenHeight = renderer.getScreenHeight(); const auto screenHeight = renderer.getScreenHeight();
const auto textY = screenHeight - orientedMarginBottom + 2; const auto textY = screenHeight - orientedMarginBottom - 2;
int percentageTextWidth = 0; int percentageTextWidth = 0;
int progressTextWidth = 0; int progressTextWidth = 0;

View File

@ -3,7 +3,7 @@
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include "MappedInputManager.h" #include "MappedInputManager.h"
#include "config.h" #include "fontIds.h"
namespace { namespace {
// Time threshold for treating a long press as a page-up/page-down // Time threshold for treating a long press as a page-up/page-down
@ -120,14 +120,14 @@ void EpubReaderChapterSelectionActivity::renderScreen() {
const auto pageWidth = renderer.getScreenWidth(); const auto pageWidth = renderer.getScreenWidth();
const int pageItems = getPageItems(); const int pageItems = getPageItems();
renderer.drawCenteredText(READER_FONT_ID, 10, "Select Chapter", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, 10, "Select Chapter", true, BOLD);
const auto pageStartIndex = selectorIndex / pageItems * pageItems; const auto pageStartIndex = selectorIndex / pageItems * pageItems;
renderer.fillRect(0, 60 + (selectorIndex % pageItems) * 30 - 2, pageWidth - 1, 30); renderer.fillRect(0, 60 + (selectorIndex % pageItems) * 30 - 2, pageWidth - 1, 30);
for (int tocIndex = pageStartIndex; tocIndex < epub->getTocItemsCount() && tocIndex < pageStartIndex + pageItems; for (int tocIndex = pageStartIndex; tocIndex < epub->getTocItemsCount() && tocIndex < pageStartIndex + pageItems;
tocIndex++) { tocIndex++) {
auto item = epub->getTocItem(tocIndex); auto item = epub->getTocItem(tocIndex);
renderer.drawText(UI_FONT_ID, 20 + (item.level - 1) * 15, 60 + (tocIndex % pageItems) * 30, item.title.c_str(), renderer.drawText(UI_10_FONT_ID, 20 + (item.level - 1) * 15, 60 + (tocIndex % pageItems) * 30, item.title.c_str(),
tocIndex != selectorIndex); tocIndex != selectorIndex);
} }

View File

@ -4,7 +4,7 @@
#include <SDCardManager.h> #include <SDCardManager.h>
#include "MappedInputManager.h" #include "MappedInputManager.h"
#include "config.h" #include "fontIds.h"
namespace { namespace {
constexpr int PAGE_ITEMS = 23; constexpr int PAGE_ITEMS = 23;
@ -165,14 +165,14 @@ void FileSelectionActivity::render() const {
renderer.clearScreen(); renderer.clearScreen();
const auto pageWidth = renderer.getScreenWidth(); const auto pageWidth = renderer.getScreenWidth();
renderer.drawCenteredText(READER_FONT_ID, 10, "Books", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, 10, "Books", true, BOLD);
// Help text // Help text
const auto labels = mappedInput.mapLabels("« Home", "Open", "", ""); const auto labels = mappedInput.mapLabels("« Home", "Open", "", "");
renderer.drawButtonHints(UI_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4); renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
if (files.empty()) { if (files.empty()) {
renderer.drawText(UI_FONT_ID, 20, 60, "No books found"); renderer.drawText(UI_10_FONT_ID, 20, 60, "No books found");
renderer.displayBuffer(); renderer.displayBuffer();
return; return;
} }
@ -181,12 +181,12 @@ void FileSelectionActivity::render() const {
renderer.fillRect(0, 60 + (selectorIndex % PAGE_ITEMS) * 30 - 2, pageWidth - 1, 30); renderer.fillRect(0, 60 + (selectorIndex % PAGE_ITEMS) * 30 - 2, pageWidth - 1, 30);
for (int i = pageStartIndex; i < files.size() && i < pageStartIndex + PAGE_ITEMS; i++) { for (int i = pageStartIndex; i < files.size() && i < pageStartIndex + PAGE_ITEMS; i++) {
auto item = files[i]; auto item = files[i];
int itemWidth = renderer.getTextWidth(UI_FONT_ID, item.c_str()); int itemWidth = renderer.getTextWidth(UI_10_FONT_ID, item.c_str());
while (itemWidth > renderer.getScreenWidth() - 40 && item.length() > 8) { while (itemWidth > renderer.getScreenWidth() - 40 && item.length() > 8) {
item.replace(item.length() - 5, 5, "..."); item.replace(item.length() - 5, 5, "...");
itemWidth = renderer.getTextWidth(UI_FONT_ID, item.c_str()); itemWidth = renderer.getTextWidth(UI_10_FONT_ID, item.c_str());
} }
renderer.drawText(UI_FONT_ID, 20, 60 + (i % PAGE_ITEMS) * 30, item.c_str(), i != selectorIndex); renderer.drawText(UI_10_FONT_ID, 20, 60 + (i % PAGE_ITEMS) * 30, item.c_str(), i != selectorIndex);
} }
renderer.displayBuffer(); renderer.displayBuffer();

View File

@ -14,7 +14,7 @@
#include "CrossPointState.h" #include "CrossPointState.h"
#include "MappedInputManager.h" #include "MappedInputManager.h"
#include "XtcReaderChapterSelectionActivity.h" #include "XtcReaderChapterSelectionActivity.h"
#include "config.h" #include "fontIds.h"
namespace { namespace {
constexpr int pagesPerRefresh = 15; constexpr int pagesPerRefresh = 15;
@ -165,7 +165,7 @@ void XtcReaderActivity::renderScreen() {
if (currentPage >= xtc->getPageCount()) { if (currentPage >= xtc->getPageCount()) {
// Show end of book screen // Show end of book screen
renderer.clearScreen(); renderer.clearScreen();
renderer.drawCenteredText(UI_FONT_ID, 300, "End of book", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, 300, "End of book", true, BOLD);
renderer.displayBuffer(); renderer.displayBuffer();
return; return;
} }
@ -194,7 +194,7 @@ void XtcReaderActivity::renderPage() {
if (!pageBuffer) { if (!pageBuffer) {
Serial.printf("[%lu] [XTR] Failed to allocate page buffer (%lu bytes)\n", millis(), pageBufferSize); Serial.printf("[%lu] [XTR] Failed to allocate page buffer (%lu bytes)\n", millis(), pageBufferSize);
renderer.clearScreen(); renderer.clearScreen();
renderer.drawCenteredText(UI_FONT_ID, 300, "Memory error", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, 300, "Memory error", true, BOLD);
renderer.displayBuffer(); renderer.displayBuffer();
return; return;
} }
@ -205,7 +205,7 @@ void XtcReaderActivity::renderPage() {
Serial.printf("[%lu] [XTR] Failed to load page %lu\n", millis(), currentPage); Serial.printf("[%lu] [XTR] Failed to load page %lu\n", millis(), currentPage);
free(pageBuffer); free(pageBuffer);
renderer.clearScreen(); renderer.clearScreen();
renderer.drawCenteredText(UI_FONT_ID, 300, "Page load error", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, 300, "Page load error", true, BOLD);
renderer.displayBuffer(); renderer.displayBuffer();
return; return;
} }

View File

@ -3,7 +3,7 @@
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include "MappedInputManager.h" #include "MappedInputManager.h"
#include "config.h" #include "fontIds.h"
namespace { namespace {
constexpr int SKIP_PAGE_MS = 700; constexpr int SKIP_PAGE_MS = 700;
@ -130,11 +130,11 @@ void XtcReaderChapterSelectionActivity::renderScreen() {
const auto pageWidth = renderer.getScreenWidth(); const auto pageWidth = renderer.getScreenWidth();
const int pageItems = getPageItems(); const int pageItems = getPageItems();
renderer.drawCenteredText(READER_FONT_ID, 10, "Select Chapter", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, 10, "Select Chapter", true, BOLD);
const auto& chapters = xtc->getChapters(); const auto& chapters = xtc->getChapters();
if (chapters.empty()) { if (chapters.empty()) {
renderer.drawCenteredText(UI_FONT_ID, 120, "No chapters", true, REGULAR); renderer.drawCenteredText(UI_10_FONT_ID, 120, "No chapters");
renderer.displayBuffer(); renderer.displayBuffer();
return; return;
} }
@ -144,7 +144,7 @@ void XtcReaderChapterSelectionActivity::renderScreen() {
for (int i = pageStartIndex; i < static_cast<int>(chapters.size()) && i < pageStartIndex + pageItems; i++) { for (int i = pageStartIndex; i < static_cast<int>(chapters.size()) && i < pageStartIndex + pageItems; i++) {
const auto& chapter = chapters[i]; const auto& chapter = chapters[i];
const char* title = chapter.name.empty() ? "Unnamed" : chapter.name.c_str(); const char* title = chapter.name.empty() ? "Unnamed" : chapter.name.c_str();
renderer.drawText(UI_FONT_ID, 20, 60 + (i % pageItems) * 30, title, i != selectorIndex); renderer.drawText(UI_10_FONT_ID, 20, 60 + (i % pageItems) * 30, title, i != selectorIndex);
} }
renderer.displayBuffer(); renderer.displayBuffer();

View File

@ -5,7 +5,7 @@
#include "MappedInputManager.h" #include "MappedInputManager.h"
#include "activities/network/WifiSelectionActivity.h" #include "activities/network/WifiSelectionActivity.h"
#include "config.h" #include "fontIds.h"
#include "network/OtaUpdater.h" #include "network/OtaUpdater.h"
void OtaUpdateActivity::taskTrampoline(void* param) { void OtaUpdateActivity::taskTrampoline(void* param) {
@ -128,56 +128,58 @@ void OtaUpdateActivity::render() {
const auto pageWidth = renderer.getScreenWidth(); const auto pageWidth = renderer.getScreenWidth();
renderer.clearScreen(); renderer.clearScreen();
renderer.drawCenteredText(READER_FONT_ID, 10, "Update", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, 10, "Update", true, BOLD);
if (state == CHECKING_FOR_UPDATE) { if (state == CHECKING_FOR_UPDATE) {
renderer.drawCenteredText(UI_FONT_ID, 300, "Checking for update...", true, BOLD); renderer.drawCenteredText(UI_10_FONT_ID, 300, "Checking for update...", true, BOLD);
renderer.displayBuffer(); renderer.displayBuffer();
return; return;
} }
if (state == WAITING_CONFIRMATION) { if (state == WAITING_CONFIRMATION) {
renderer.drawCenteredText(UI_FONT_ID, 200, "New update available!", true, BOLD); renderer.drawCenteredText(UI_10_FONT_ID, 200, "New update available!", true, BOLD);
renderer.drawText(UI_FONT_ID, 20, 250, "Current Version: " CROSSPOINT_VERSION); renderer.drawText(UI_10_FONT_ID, 20, 250, "Current Version: " CROSSPOINT_VERSION);
renderer.drawText(UI_FONT_ID, 20, 270, ("New Version: " + updater.getLatestVersion()).c_str()); renderer.drawText(UI_10_FONT_ID, 20, 270, ("New Version: " + updater.getLatestVersion()).c_str());
renderer.drawRect(25, pageHeight - 40, 106, 40); renderer.drawRect(25, pageHeight - 40, 106, 40);
renderer.drawText(UI_FONT_ID, 25 + (105 - renderer.getTextWidth(UI_FONT_ID, "Cancel")) / 2, pageHeight - 35, renderer.drawText(UI_10_FONT_ID, 25 + (105 - renderer.getTextWidth(UI_10_FONT_ID, "Cancel")) / 2, pageHeight - 35,
"Cancel"); "Cancel");
renderer.drawRect(130, pageHeight - 40, 106, 40); renderer.drawRect(130, pageHeight - 40, 106, 40);
renderer.drawText(UI_FONT_ID, 130 + (105 - renderer.getTextWidth(UI_FONT_ID, "Update")) / 2, pageHeight - 35, renderer.drawText(UI_10_FONT_ID, 130 + (105 - renderer.getTextWidth(UI_10_FONT_ID, "Update")) / 2, pageHeight - 35,
"Update"); "Update");
renderer.displayBuffer(); renderer.displayBuffer();
return; return;
} }
if (state == UPDATE_IN_PROGRESS) { if (state == UPDATE_IN_PROGRESS) {
renderer.drawCenteredText(UI_FONT_ID, 310, "Updating...", true, BOLD); renderer.drawCenteredText(UI_10_FONT_ID, 310, "Updating...", true, BOLD);
renderer.drawRect(20, 350, pageWidth - 40, 50); renderer.drawRect(20, 350, pageWidth - 40, 50);
renderer.fillRect(24, 354, static_cast<int>(updaterProgress * static_cast<float>(pageWidth - 44)), 42); renderer.fillRect(24, 354, static_cast<int>(updaterProgress * static_cast<float>(pageWidth - 44)), 42);
renderer.drawCenteredText(UI_FONT_ID, 420, (std::to_string(static_cast<int>(updaterProgress * 100)) + "%").c_str()); renderer.drawCenteredText(UI_10_FONT_ID, 420,
(std::to_string(static_cast<int>(updaterProgress * 100)) + "%").c_str());
renderer.drawCenteredText( renderer.drawCenteredText(
UI_FONT_ID, 440, (std::to_string(updater.processedSize) + " / " + std::to_string(updater.totalSize)).c_str()); UI_10_FONT_ID, 440,
(std::to_string(updater.processedSize) + " / " + std::to_string(updater.totalSize)).c_str());
renderer.displayBuffer(); renderer.displayBuffer();
return; return;
} }
if (state == NO_UPDATE) { if (state == NO_UPDATE) {
renderer.drawCenteredText(UI_FONT_ID, 300, "No update available", true, BOLD); renderer.drawCenteredText(UI_10_FONT_ID, 300, "No update available", true, BOLD);
renderer.displayBuffer(); renderer.displayBuffer();
return; return;
} }
if (state == FAILED) { if (state == FAILED) {
renderer.drawCenteredText(UI_FONT_ID, 300, "Update failed", true, BOLD); renderer.drawCenteredText(UI_10_FONT_ID, 300, "Update failed", true, BOLD);
renderer.displayBuffer(); renderer.displayBuffer();
return; return;
} }
if (state == FINISHED) { if (state == FINISHED) {
renderer.drawCenteredText(UI_FONT_ID, 300, "Update complete", true, BOLD); renderer.drawCenteredText(UI_10_FONT_ID, 300, "Update complete", true, BOLD);
renderer.drawCenteredText(UI_FONT_ID, 350, "Press and hold power button to turn back on"); renderer.drawCenteredText(UI_10_FONT_ID, 350, "Press and hold power button to turn back on");
renderer.displayBuffer(); renderer.displayBuffer();
state = SHUTTING_DOWN; state = SHUTTING_DOWN;
return; return;

View File

@ -5,11 +5,11 @@
#include "CrossPointSettings.h" #include "CrossPointSettings.h"
#include "MappedInputManager.h" #include "MappedInputManager.h"
#include "OtaUpdateActivity.h" #include "OtaUpdateActivity.h"
#include "config.h" #include "fontIds.h"
// Define the static settings list // Define the static settings list
namespace { namespace {
constexpr int settingsCount = 8; constexpr int settingsCount = 10;
const SettingInfo settingsList[settingsCount] = { const SettingInfo settingsList[settingsCount] = {
// Should match with SLEEP_SCREEN_MODE // Should match with SLEEP_SCREEN_MODE
{"Sleep Screen", SettingType::ENUM, &CrossPointSettings::sleepScreen, {"Dark", "Light", "Custom", "Cover"}}, {"Sleep Screen", SettingType::ENUM, &CrossPointSettings::sleepScreen, {"Dark", "Light", "Custom", "Cover"}},
@ -28,6 +28,8 @@ const SettingInfo settingsList[settingsCount] = {
SettingType::ENUM, SettingType::ENUM,
&CrossPointSettings::sideButtonLayout, &CrossPointSettings::sideButtonLayout,
{"Prev, Next", "Next, Prev"}}, {"Prev, Next", "Next, Prev"}},
{"Reader Font Family", SettingType::ENUM, &CrossPointSettings::fontFamily, {"Aleo", "Noto Sans", "Open Dyslexic"}},
{"Reader Font Size", SettingType::ENUM, &CrossPointSettings::fontSize, {"Small", "Medium", "Large", "X Large"}},
{"Check for updates", SettingType::ACTION, nullptr, {}}, {"Check for updates", SettingType::ACTION, nullptr, {}},
}; };
} // namespace } // namespace
@ -157,7 +159,7 @@ void SettingsActivity::render() const {
const auto pageHeight = renderer.getScreenHeight(); const auto pageHeight = renderer.getScreenHeight();
// Draw header // Draw header
renderer.drawCenteredText(READER_FONT_ID, 10, "Settings", true, BOLD); renderer.drawCenteredText(UI_12_FONT_ID, 10, "Settings", true, BOLD);
// Draw selection // Draw selection
renderer.fillRect(0, 60 + selectedSettingIndex * 30 - 2, pageWidth - 1, 30); renderer.fillRect(0, 60 + selectedSettingIndex * 30 - 2, pageWidth - 1, 30);
@ -168,11 +170,11 @@ void SettingsActivity::render() const {
// Draw selection indicator for the selected setting // Draw selection indicator for the selected setting
if (i == selectedSettingIndex) { if (i == selectedSettingIndex) {
renderer.drawText(UI_FONT_ID, 5, settingY, ">"); renderer.drawText(UI_10_FONT_ID, 5, settingY, ">");
} }
// Draw setting name // Draw setting name
renderer.drawText(UI_FONT_ID, 20, settingY, settingsList[i].name, i != selectedSettingIndex); renderer.drawText(UI_10_FONT_ID, 20, settingY, settingsList[i].name, i != selectedSettingIndex);
// Draw value based on setting type // Draw value based on setting type
std::string valueText = ""; std::string valueText = "";
@ -183,8 +185,8 @@ void SettingsActivity::render() const {
const uint8_t value = SETTINGS.*(settingsList[i].valuePtr); const uint8_t value = SETTINGS.*(settingsList[i].valuePtr);
valueText = settingsList[i].enumValues[value]; valueText = settingsList[i].enumValues[value];
} }
const auto width = renderer.getTextWidth(UI_FONT_ID, valueText.c_str()); const auto width = renderer.getTextWidth(UI_10_FONT_ID, valueText.c_str());
renderer.drawText(UI_FONT_ID, pageWidth - 20 - width, settingY, valueText.c_str(), i != selectedSettingIndex); renderer.drawText(UI_10_FONT_ID, pageWidth - 20 - width, settingY, valueText.c_str(), i != selectedSettingIndex);
} }
// Draw version text above button hints // Draw version text above button hints
@ -193,7 +195,7 @@ void SettingsActivity::render() const {
// Draw help text // Draw help text
const auto labels = mappedInput.mapLabels("« Save", "Toggle", "", ""); const auto labels = mappedInput.mapLabels("« Save", "Toggle", "", "");
renderer.drawButtonHints(UI_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4); renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
// Always use standard refresh for settings screen // Always use standard refresh for settings screen
renderer.displayBuffer(); renderer.displayBuffer();

View File

@ -2,15 +2,15 @@
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include "config.h" #include "fontIds.h"
void FullScreenMessageActivity::onEnter() { void FullScreenMessageActivity::onEnter() {
Activity::onEnter(); Activity::onEnter();
const auto height = renderer.getLineHeight(UI_FONT_ID); const auto height = renderer.getLineHeight(UI_10_FONT_ID);
const auto top = (renderer.getScreenHeight() - height) / 2; const auto top = (renderer.getScreenHeight() - height) / 2;
renderer.clearScreen(); renderer.clearScreen();
renderer.drawCenteredText(UI_FONT_ID, top, text.c_str(), true, style); renderer.drawCenteredText(UI_10_FONT_ID, top, text.c_str(), true, style);
renderer.displayBuffer(refreshMode); renderer.displayBuffer(refreshMode);
} }

Some files were not shown because too many files have changed in this diff Show More