mirror of
https://github.com/NaitLee/Cat-Printer.git
synced 2025-05-16 07:10:30 -07:00
Merge branch 'NaitLee:main' into imagemagik-usability
This commit is contained in:
commit
dbe18dd89e
5
.gitignore
vendored
5
.gitignore
vendored
@ -24,13 +24,16 @@ build-common/python-win32*
|
|||||||
build-common/python-w32*
|
build-common/python-w32*
|
||||||
# bleak_winrt is now outside python-w32
|
# bleak_winrt is now outside python-w32
|
||||||
build-common/bleak_winrt
|
build-common/bleak_winrt
|
||||||
|
# local pf2
|
||||||
|
pf2
|
||||||
|
pf2.zip
|
||||||
|
*.pf2
|
||||||
# dev config
|
# dev config
|
||||||
config.json
|
config.json
|
||||||
# dev backup
|
# dev backup
|
||||||
*.bak
|
*.bak
|
||||||
# test files
|
# test files
|
||||||
*.dump
|
*.dump
|
||||||
*.pf2
|
|
||||||
*.pbm
|
*.pbm
|
||||||
test.png
|
test.png
|
||||||
# some other junk
|
# some other junk
|
||||||
|
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -43,7 +43,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "printer.py",
|
"program": "printer.py",
|
||||||
"args": [
|
"args": [
|
||||||
"-m", "-f", "GB02", "-t", "1,font,pf2", "COPYING"
|
"-m", "-f", "GB02", "-t", "1,unifont,pf2", "dev-diary.txt"
|
||||||
],
|
],
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"justMyCode": true
|
"justMyCode": true
|
||||||
|
22
build-android/.p4a
Normal file
22
build-android/.p4a
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
--private ..
|
||||||
|
--dist_name "cat-printer"
|
||||||
|
--package "io.github.naitlee.catprinter"
|
||||||
|
--name "Cat Printer"
|
||||||
|
--icon icon.png
|
||||||
|
--bootstrap webview
|
||||||
|
--window
|
||||||
|
--blacklist-requirements sqlite3,openssl
|
||||||
|
--port 8095
|
||||||
|
--arch arm64-v8a
|
||||||
|
--blacklist "blacklist.txt"
|
||||||
|
--presplash blank.png
|
||||||
|
--presplash-color black
|
||||||
|
--add-source "advancedwebview"
|
||||||
|
--manifest-orientation user
|
||||||
|
--android_api 30
|
||||||
|
--permission BLUETOOTH
|
||||||
|
--permission BLUETOOTH_SCAN
|
||||||
|
--permission BLUETOOTH_CONNECT
|
||||||
|
--permission BLUETOOTH_ADMIN
|
||||||
|
--permission ACCESS_FINE_LOCATION
|
||||||
|
--permission ACCESS_COARSE_LOCATION
|
@ -1,9 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
version=`cat ../version`
|
version=`cat ../version`
|
||||||
|
|
||||||
p4a apk --private .. --dist_name="cat-printer" --package="io.github.naitlee.catprinter" --name="Cat Printer" \
|
p4a apk --requirements "`cat build-deps.txt`" --version "$version" $@
|
||||||
--icon=icon.png --version=$version --bootstrap=webview --window --requirements="`cat build-deps.txt`" \
|
|
||||||
--blacklist-requirements=sqlite3,openssl --port=8095 --arch=arm64-v8a --blacklist="blacklist.txt" \
|
|
||||||
--presplash=blank.png --presplash-color=black --add-source="advancedwebview" --manifest-orientation=user \
|
|
||||||
--permission=BLUETOOTH --permission=BLUETOOTH_SCAN --permission=BLUETOOTH_CONNECT \
|
|
||||||
--permission=BLUETOOTH_ADMIN --permission=ACCESS_FINE_LOCATION --permission=ACCESS_COARSE_LOCATION $@
|
|
||||||
|
@ -4,9 +4,4 @@ version=`cat ../version`
|
|||||||
rm -rf "dist"
|
rm -rf "dist"
|
||||||
unzip -q "../cat-printer-bare-$version.zip"
|
unzip -q "../cat-printer-bare-$version.zip"
|
||||||
mv "cat-printer" "dist"
|
mv "cat-printer" "dist"
|
||||||
p4a apk --private "dist" --dist_name="cat-printer" --package="io.github.naitlee.catprinter" --name="Cat Printer" \
|
p4a apk --version="$version" --requirements="`cat build-deps.txt`" --release $@
|
||||||
--icon=icon.png --version="$version" --bootstrap=webview --window --requirements="`cat build-deps.txt`" \
|
|
||||||
--blacklist-requirements=sqlite3,openssl --port=8095 --arch=arm64-v8a --release \
|
|
||||||
--presplash=blank.png --presplash-color=black --add-source="advancedwebview" --orientation=user \
|
|
||||||
--permission=BLUETOOTH --permission=BLUETOOTH_SCAN --permission=BLUETOOTH_CONNECT \
|
|
||||||
--permission=BLUETOOTH_ADMIN --permission=ACCESS_FINE_LOCATION --permission=ACCESS_COARSE_LOCATION $@
|
|
||||||
|
@ -4,7 +4,7 @@ unsigned_apk=cat-printer-release-unsigned-$version.apk
|
|||||||
signed_apk=cat-printer-android-$version.apk
|
signed_apk=cat-printer-android-$version.apk
|
||||||
|
|
||||||
if {
|
if {
|
||||||
$ANDROIDSDK/build-tools/*/zipalign 4 $unsigned_apk $signed_apk;
|
$ANDROIDSDK/build-tools/*/zipalign 4 $unsigned_apk $signed_apk &&
|
||||||
$ANDROIDSDK/build-tools/*/apksigner sign --ks $1 $signed_apk;
|
$ANDROIDSDK/build-tools/*/apksigner sign --ks $1 $signed_apk;
|
||||||
}; then
|
}; then
|
||||||
echo "Complete! Moving APK..."
|
echo "Complete! Moving APK..."
|
||||||
|
@ -5,34 +5,26 @@ Expecting to cost about half a day.
|
|||||||
|
|
||||||
Worthy to work on! This gives possibility to everything about Android in your mind!
|
Worthy to work on! This gives possibility to everything about Android in your mind!
|
||||||
|
|
||||||
|
See [#Troubleshooting](#troubleshooting) for some problems you may meet.
|
||||||
|
|
||||||
Note: not being confirmed to 100% work yet. Be the first bird to try! Or bookmark this, arrange your time & come back later.
|
Note: not being confirmed to 100% work yet. Be the first bird to try! Or bookmark this, arrange your time & come back later.
|
||||||
|
|
||||||
## Prepare
|
## Prepare
|
||||||
|
|
||||||
First, think about what will be your build environment. I choose to use a Ubuntu Docker container.
|
First, think about what will be your build environment. I choose to use a Docker container with a newer GNU/Linux distribution.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
<summary>Expand Comparison</summary>
|
<summary>Expand Notes</summary>
|
||||||
|
|
||||||
| | Minimal Ubuntu | Ubuntu | [Artix](https://artixlinux.org/) |
|
Notes:
|
||||||
| :-------------------------- | :------------: | :----: | :------: |
|
|
||||||
| Base system<sup>1</sup> | | ✓ | ✓ |
|
|
||||||
| Pkg diversity | ✓ | ✓ | ✓ |
|
|
||||||
| Fresh pkg<sup>2</sup> | | | ✓ |
|
|
||||||
| Less hassle<sup>3</sup> | ✓ | | ✓ |
|
|
||||||
| Maintainability<sup>4</sup> | ✓ | | |
|
|
||||||
|
|
||||||
Note: “Minimal Ubuntu” can mean a Ubuntu [Docker](https://docs.docker.com/get-started/overview/) image, a Ubuntu chroot environment, etc.
|
1. In theory you can just use your existing system, if you don’t afraid of messing it up.
|
||||||
|
|
||||||
1. In theory you can just have Ubuntu as base system, but see 2, 3, and 4.
|
|
||||||
2. Rolling distribution have newer packages offered.
|
2. Rolling distribution have newer packages offered.
|
||||||
It may give great experience in daily use, but will heavily bloat the update if many development packages are installed alltogether.
|
It may give great experience in daily use, but will heavily bloat the update if many development packages are installed alltogether.
|
||||||
That said, Artix alone *worked* in those days. If you want, go ahead.
|
3. By operating in an isolated environment, a mess taking place inside won’t affect the host.
|
||||||
3. Mis-designs will stress you down. systemd will ruin your mood.
|
4. Good candidates are: Arch, Artix, OpenSUSE Leap, and their neighbors.
|
||||||
4. By operating in an isolated environment, a mess taking place inside won’t affect the host.
|
5. Some say Docker isn’t intended to be “stateful”. But nothing is better in my mere knowledge.
|
||||||
|
|
||||||
(Some say Docker isn’t intended to be “stateful”. But nothing is better in my mere knowledge.)
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@ -66,7 +58,11 @@ cd $DIR_GIT
|
|||||||
# Cat-Printer
|
# Cat-Printer
|
||||||
git clone https://github.com/NaitLee/Cat-Printer.git
|
git clone https://github.com/NaitLee/Cat-Printer.git
|
||||||
# Bleak, we need some Java code from its source
|
# Bleak, we need some Java code from its source
|
||||||
git clone https://github.com/hbldh/bleak.git
|
# git clone https://github.com/hbldh/bleak.git
|
||||||
|
# Use an older version for being compatible with p4a recipes (setup.py)
|
||||||
|
wget https://files.pythonhosted.org/packages/e6/b4/e63829826a157d180831a1c5d3720e75d613c1290cb239510d148b906836/bleak-0.19.5.tar.gz
|
||||||
|
tar -xzf bleak-0.19.5.tar.gz && rm bleak-0.19.5.tar.gz
|
||||||
|
mv bleak-0.19.5 bleak
|
||||||
# AdvancedWebView, in order to give Android WebView capability to use <input type="file" />
|
# AdvancedWebView, in order to give Android WebView capability to use <input type="file" />
|
||||||
git clone https://github.com/delight-im/Android-AdvancedWebView.git
|
git clone https://github.com/delight-im/Android-AdvancedWebView.git
|
||||||
|
|
||||||
@ -83,17 +79,17 @@ After that, continue to [Fix the NDK](#fix-the-ndk).
|
|||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
If you’re in China Mainland (you guessed it!), or prefer manual setup:
|
If Google isn’t available there, or you prefer manual setup:
|
||||||
|
|
||||||
- Pick a working mirror. Currently there’s [Tencent Cloud](https://mirrors.cloud.tencent.com/AndroidSDK/).
|
- Pick a working mirror. Currently there’s [Tencent Cloud](https://mirrors.cloud.tencent.com/AndroidSDK/).
|
||||||
|
|
||||||
- Pay attention to [required version of Android NDK](https://python-for-android.readthedocs.io/en/latest/quickstart/#basic-sdk-install), this will increase by time. It’s currently r25b.
|
- Pay attention to [required version of Android NDK](https://python-for-android.readthedocs.io/en/latest/quickstart/#basic-sdk-install), this will increase by time. It’s currently r25b, but let’s use r25c.
|
||||||
|
|
||||||
- Fetch & extract some archives, as shown in this table:
|
- Fetch & extract some archives, as shown in this table:
|
||||||
|
|
||||||
| Archive file | Top-level dir inside | Target directory |
|
| Archive file | Top-level dir inside | Target directory |
|
||||||
| ----------------------------------- | ----------------------- | ----------------------------------- |
|
| ----------------------------------- | ----------------------- | ----------------------------------- |
|
||||||
| `android-ndk-r25b-linux.zip` | `android-ndk-r25b` | `android/android-ndk-r25b` |
|
| `android-ndk-r25c-linux.zip` | `android-ndk-r25c` | `android/android-ndk-r25c` |
|
||||||
| `build-tools_r33-linux.zip` | `android-13` | `android/build-tools/33.0.0` |
|
| `build-tools_r33-linux.zip` | `android-13` | `android/build-tools/33.0.0` |
|
||||||
| `commandlinetools-linux-8512546_latest.zip` | `cmdline-tools` | `android/cmdline-tools/latest` |
|
| `commandlinetools-linux-8512546_latest.zip` | `cmdline-tools` | `android/cmdline-tools/latest` |
|
||||||
| `platform-30_r03.zip` | `android-11` | `android/platforms/android-30` |
|
| `platform-30_r03.zip` | `android-11` | `android/platforms/android-30` |
|
||||||
@ -106,7 +102,7 @@ So after that you will get:
|
|||||||
|
|
||||||
```
|
```
|
||||||
android
|
android
|
||||||
├── android-ndk-r25b
|
├── android-ndk-r25c
|
||||||
├── build-tools
|
├── build-tools
|
||||||
│ └── 33.0.0
|
│ └── 33.0.0
|
||||||
├── cmdline-tools
|
├── cmdline-tools
|
||||||
@ -125,7 +121,7 @@ System doesn’t understand it. Let’s replace them as symlinks:
|
|||||||
```bash
|
```bash
|
||||||
# you may already have these from p4a guide
|
# you may already have these from p4a guide
|
||||||
ANDROIDSDK="$DIR_BUILD/android"
|
ANDROIDSDK="$DIR_BUILD/android"
|
||||||
ANDROIDNDK="$DIR_BUILD/android/android-ndk-r25b"
|
ANDROIDNDK="$DIR_BUILD/android/android-ndk-r25c"
|
||||||
# feel free to check this script
|
# feel free to check this script
|
||||||
python3 $DIR_GIT/Cat-Printer/build-android/fix-ndk-execs.py $ANDROIDNDK
|
python3 $DIR_GIT/Cat-Printer/build-android/fix-ndk-execs.py $ANDROIDNDK
|
||||||
```
|
```
|
||||||
@ -147,10 +143,10 @@ after that, restart docker service, or reboot.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# let’s create the container by first pulling the image
|
# let’s create the container by first pulling the image
|
||||||
docker pull ubuntu:latest
|
docker pull archlinux:latest
|
||||||
# please, pass previously mentioned directories (or their parent) via -v parameter, we will access them here
|
# please, pass previously mentioned directories (or their parent) via -v parameter, we will access them here
|
||||||
# example: `-v /source1/android:/target1/android -v /source2/git-repo:/target2/git-repo`
|
# example: `-v /source1/android:/target1/android -v /source2/git-repo:/target2/git-repo`
|
||||||
docker create --name catbuild -v /mnt/data:/mnt/data --tty -i ubuntu
|
docker create --name catbuild -v /mnt/data:/mnt/data --tty -i archlinux
|
||||||
|
|
||||||
# From now on, start the container like this
|
# From now on, start the container like this
|
||||||
docker start -i catbuild
|
docker start -i catbuild
|
||||||
@ -161,17 +157,13 @@ docker start -i catbuild
|
|||||||
OK, we are now inside the container shell. Set it up:
|
OK, we are now inside the container shell. Set it up:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# (Optional) use a Ubuntu repository mirror
|
# (Optional) use a repository mirror:
|
||||||
# sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
|
# cd /etc/pacman.d; mv mirrorlist mirrorlist.bak; echo 'Server = https://mirrors.ustc.edu.cn/archlinux/$repo/os/$arch' >mirrorlist
|
||||||
dpkg --add-architecture i386
|
pacman -Syuu jdk-openjdk python3 python-pip git cython zip nano vim tar wget unzip base-devel clang lld libffi
|
||||||
apt update
|
|
||||||
apt upgrade
|
|
||||||
# find python-for-android dependencies here:
|
# find python-for-android dependencies here:
|
||||||
# https://python-for-android.readthedocs.io/en/latest/quickstart/#installing-dependencies
|
# https://python-for-android.readthedocs.io/en/latest/quickstart/#installing-dependencies
|
||||||
# there should be a command for Ubuntu that you can directly run
|
# there should be command for Arch/Ubuntu that you can directly run
|
||||||
# ... though we need more
|
# (Optional) use a pypi mirror:
|
||||||
apt install -y python3-pip lld libffi-dev zip nano
|
|
||||||
# (Optional) use a pypi mirror
|
|
||||||
# pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
|
# pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
|
||||||
pip install python-for-android cython bleak
|
pip install python-for-android cython bleak
|
||||||
```
|
```
|
||||||
@ -187,7 +179,7 @@ We should glue them up by hand.
|
|||||||
echo '
|
echo '
|
||||||
export DIR_BUILD="/mnt/data/@"
|
export DIR_BUILD="/mnt/data/@"
|
||||||
export ANDROIDSDK="$DIR_BUILD/android"
|
export ANDROIDSDK="$DIR_BUILD/android"
|
||||||
export ANDROIDNDK="$DIR_BUILD/android/android-ndk-r25b"
|
export ANDROIDNDK="$DIR_BUILD/android/android-ndk-r25c"
|
||||||
export ANDROIDAPI="30"
|
export ANDROIDAPI="30"
|
||||||
export NDKAPI="21"' >> .bashrc
|
export NDKAPI="21"' >> .bashrc
|
||||||
|
|
||||||
@ -200,6 +192,7 @@ source ~/.bashrc
|
|||||||
```bash
|
```bash
|
||||||
# define shortcut(s). use your target paths!
|
# define shortcut(s). use your target paths!
|
||||||
DIR_GIT="$DIR_BUILD/git-repo/"
|
DIR_GIT="$DIR_BUILD/git-repo/"
|
||||||
|
# note this involves python version, change as needed
|
||||||
DIR_P4A="/usr/local/lib/python3.10/dist-packages/pythonforandroid/"
|
DIR_P4A="/usr/local/lib/python3.10/dist-packages/pythonforandroid/"
|
||||||
|
|
||||||
# p4a will generate some intermediate data. “expose” this to the host for convenient manipulation.
|
# p4a will generate some intermediate data. “expose” this to the host for convenient manipulation.
|
||||||
@ -343,7 +336,7 @@ Try the ultimate helper `1-build.sh`, if you also have everything in [developmen
|
|||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
Common issues and fixes:
|
### Common
|
||||||
|
|
||||||
| Error message | Fix |
|
| Error message | Fix |
|
||||||
|-|-|
|
|-|-|
|
||||||
@ -354,6 +347,33 @@ Common issues and fixes:
|
|||||||
| No such file or directory `build-android/dist` | Create a bare bundle before creating an APK |
|
| No such file or directory `build-android/dist` | Create a bare bundle before creating an APK |
|
||||||
| JAVA_HOME is not set and no 'java' command could be found in your PATH. | Install a JDK (e.g. `openjdk-19-jdk`) |
|
| JAVA_HOME is not set and no 'java' command could be found in your PATH. | Install a JDK (e.g. `openjdk-19-jdk`) |
|
||||||
|
|
||||||
|
### Special
|
||||||
|
|
||||||
|
Something like these:
|
||||||
|
(pardon me for not memorizing the log well)
|
||||||
|
|
||||||
|
```
|
||||||
|
… platform is . …
|
||||||
|
is unsupported, assuming android-19 …
|
||||||
|
……
|
||||||
|
……
|
||||||
|
……
|
||||||
|
crtbegin… … not found
|
||||||
|
…
|
||||||
|
crtend… … not found
|
||||||
|
```
|
||||||
|
|
||||||
|
Change `$ANDROIDNDK/build/gmsl/__gmsl` line 512:
|
||||||
|
```
|
||||||
|
int_encode = $(__gmsl_tr1)$(wordlist 1,$1,$(__gmsl_input_int))
|
||||||
|
```
|
||||||
|
to this:
|
||||||
|
```
|
||||||
|
int_encode = $(__gmsl_tr1)$(wordlist 1,$(if $1, $1,0),$(__gmsl_input_int))
|
||||||
|
```
|
||||||
|
|
||||||
|
(Thanks to a comment around [here](https://stackoverflow.com/questions/10285242/openssl-using-androids-ndk-problems#answer-14369078))
|
||||||
|
|
||||||
## The End
|
## The End
|
||||||
|
|
||||||
You made it! You now have ability to contribute much more, outside of Cat-Printer. Try to bring an app in your mind to reality, with just Python, Web, and this build environment.
|
You made it! You now have ability to contribute much more, outside of Cat-Printer. Try to bring an app in your mind to reality, with just Python, Web, and this build environment.
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
export version=`cat ../version`
|
export version=`cat ../version`
|
||||||
for i in $(find | grep -E '.*\.pyc'); do rm $i; done
|
for i in $(find | grep -E '.*\.pyc'); do rm $i; done
|
||||||
for i in $(find | grep -E '__pycache__'); do rm -d $i; done
|
for i in $(find | grep -E '__pycache__'); do rm -d $i; done
|
||||||
python3 bundle.py $version
|
# python3 bundle.py $version
|
||||||
python3 bundle.py -w $version
|
# python3 bundle.py -w $version
|
||||||
python3 bundle.py -b $version
|
python3 bundle.py -b $version
|
||||||
|
35
printer.py
35
printer.py
@ -1,7 +1,7 @@
|
|||||||
'''
|
'''
|
||||||
Cat-Printer Core
|
Cat-Printer Core
|
||||||
|
|
||||||
Copyright © 2021-2022 NaitLee Soft. All rights reserved.
|
Copyright © 2021-2023 NaitLee Soft. All rights reserved.
|
||||||
|
|
||||||
License GPL-3.0-or-later: https://www.gnu.org/licenses/gpl-3.0.html
|
License GPL-3.0-or-later: https://www.gnu.org/licenses/gpl-3.0.html
|
||||||
'''
|
'''
|
||||||
@ -13,6 +13,7 @@ import argparse
|
|||||||
import subprocess
|
import subprocess
|
||||||
import asyncio
|
import asyncio
|
||||||
import platform
|
import platform
|
||||||
|
import zipfile
|
||||||
|
|
||||||
class ExitCodes():
|
class ExitCodes():
|
||||||
'Exit codes'
|
'Exit codes'
|
||||||
@ -311,7 +312,7 @@ class PrinterDriver(Commander):
|
|||||||
_pending_data: io.BytesIO = None
|
_pending_data: io.BytesIO = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._loop = asyncio.get_event_loop_policy().get_event_loop()
|
self._loop = asyncio.get_event_loop_policy().new_event_loop()
|
||||||
|
|
||||||
def loop(self, *futures):
|
def loop(self, *futures):
|
||||||
''' Run coroutines in order in current event loop until complete,
|
''' Run coroutines in order in current event loop until complete,
|
||||||
@ -484,13 +485,37 @@ class PrinterDriver(Commander):
|
|||||||
dump_pbm.write(next(data.to_pbm(merge_pages=True)))
|
dump_pbm.write(next(data.to_pbm(merge_pages=True)))
|
||||||
self._finish()
|
self._finish()
|
||||||
|
|
||||||
|
def _get_pf2(self, path: str):
|
||||||
|
''' Get file io of a PF2 font in several ways
|
||||||
|
'''
|
||||||
|
path += '.pf2'
|
||||||
|
file = None
|
||||||
|
parents = ('', 'pf2/')
|
||||||
|
if not path:
|
||||||
|
path = 'unifont'
|
||||||
|
for parent in parents:
|
||||||
|
if os.path.exists(full_path := os.path.join(parent, path)):
|
||||||
|
file = open(full_path, 'rb')
|
||||||
|
break
|
||||||
|
else: # if didn't break
|
||||||
|
if os.path.exists('pf2.zip'):
|
||||||
|
with zipfile.ZipFile('pf2.zip') as pf2zip:
|
||||||
|
for name in pf2zip.namelist():
|
||||||
|
if name == path:
|
||||||
|
with pf2zip.open(name) as f:
|
||||||
|
file = io.BytesIO(f.read())
|
||||||
|
break
|
||||||
|
return file
|
||||||
|
|
||||||
def _print_text(self, file: io.BufferedIOBase):
|
def _print_text(self, file: io.BufferedIOBase):
|
||||||
paper_width = self.model.paper_width
|
paper_width = self.model.paper_width
|
||||||
text_io = io.TextIOWrapper(file, encoding='utf-8')
|
text_io = io.TextIOWrapper(file, encoding='utf-8')
|
||||||
if self.text_canvas is None:
|
if self.text_canvas is None:
|
||||||
self.text_canvas = TextCanvas(paper_width, wrap=self.wrap,
|
self.text_canvas = TextCanvas(paper_width, wrap=self.wrap,
|
||||||
rtl=self.rtl, font_path=self.font_family + '.pf2',
|
rtl=self.rtl, font_path=self.font_family + '.pf2',
|
||||||
scale=self.font_scale)
|
font_data_io=self._get_pf2(self.font_family), scale=self.font_scale)
|
||||||
|
if self.text_canvas.broken:
|
||||||
|
error(i18n('pf2-font-not-found-or-broken-0', self.font_family), exception=PrinterError)
|
||||||
# with stdin you maybe trying out a typewriter
|
# with stdin you maybe trying out a typewriter
|
||||||
# so print a "ruler", indicating max characters in one line
|
# so print a "ruler", indicating max characters in one line
|
||||||
if file is sys.stdin.buffer:
|
if file is sys.stdin.buffer:
|
||||||
@ -669,9 +694,9 @@ def _main():
|
|||||||
if args.energy is not None:
|
if args.energy is not None:
|
||||||
printer.energy = int(args.energy * 0xffff)
|
printer.energy = int(args.energy * 0xffff)
|
||||||
elif args.convert == 'text' or args.text:
|
elif args.convert == 'text' or args.text:
|
||||||
printer.energy = 96
|
printer.energy = 0x6000
|
||||||
else:
|
else:
|
||||||
printer.energy = 64
|
printer.energy = 0x4000
|
||||||
if args.quality is not None:
|
if args.quality is not None:
|
||||||
printer.speed = 4 * (args.quality + 5)
|
printer.speed = 4 * (args.quality + 5)
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ class I18nLib():
|
|||||||
|
|
||||||
def __init__(self, search_path='lang', lang=None, fallback=None):
|
def __init__(self, search_path='lang', lang=None, fallback=None):
|
||||||
self.fallback = fallback or 'en-US'
|
self.fallback = fallback or 'en-US'
|
||||||
self.lang = lang or (locale.getdefaultlocale()[0] or fallback).replace('_', '-')
|
self.lang = lang or (locale.getdefaultlocale()[0] or self.fallback).replace('_', '-')
|
||||||
with open(os.path.join(search_path, self.fallback + '.json'),
|
with open(os.path.join(search_path, self.fallback + '.json'),
|
||||||
'r', encoding='utf-8') as file:
|
'r', encoding='utf-8') as file:
|
||||||
self.data = json.load(file)
|
self.data = json.load(file)
|
||||||
|
@ -53,8 +53,8 @@ class Character():
|
|||||||
class PF2():
|
class PF2():
|
||||||
'The PF2 class, for serializing a PF2 font file'
|
'The PF2 class, for serializing a PF2 font file'
|
||||||
|
|
||||||
is_pf2: bool
|
broken: bool = False
|
||||||
'Sets to false if the read file is not PF2 font file'
|
'Sets to True if the font file is bad'
|
||||||
|
|
||||||
missing_character_code: int
|
missing_character_code: int
|
||||||
in_memory: bool
|
in_memory: bool
|
||||||
@ -70,12 +70,11 @@ class PF2():
|
|||||||
descent: int
|
descent: int
|
||||||
character_index: Dict[int, Tuple[int, int]]
|
character_index: Dict[int, Tuple[int, int]]
|
||||||
data_offset: int
|
data_offset: int
|
||||||
data_io: io.BufferedIOBase
|
data_io: io.BufferedIOBase = None
|
||||||
|
|
||||||
def __init__(self, path='font.pf2', *, read_to_mem=True, missing_character: str='?'):
|
def __init__(self, file: io.BufferedIOBase, *, read_to_mem=True, missing_character: str='?'):
|
||||||
self.missing_character_code = ord(missing_character)
|
self.missing_character_code = ord(missing_character)
|
||||||
self.in_memory = read_to_mem
|
self.in_memory = read_to_mem
|
||||||
file = open(path, 'rb')
|
|
||||||
if read_to_mem:
|
if read_to_mem:
|
||||||
self.data_io = io.BytesIO(file.read())
|
self.data_io = io.BytesIO(file.read())
|
||||||
file.close()
|
file.close()
|
||||||
@ -142,7 +141,8 @@ class PF2():
|
|||||||
__getitem__ = get_char
|
__getitem__ = get_char
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.data_io.close()
|
if self.data_io is not None:
|
||||||
|
self.data_io.close()
|
||||||
|
|
||||||
|
|
||||||
class CharacterS(Character):
|
class CharacterS(Character):
|
||||||
@ -168,6 +168,8 @@ class PF2S(PF2):
|
|||||||
|
|
||||||
def __init__(self, *args, scale: int=1, **kwargs):
|
def __init__(self, *args, scale: int=1, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
if self.broken:
|
||||||
|
return
|
||||||
self.scale = scale
|
self.scale = scale
|
||||||
self.point_size *= scale
|
self.point_size *= scale
|
||||||
self.max_width *= scale
|
self.max_width *= scale
|
||||||
|
@ -4,6 +4,7 @@ from .pf2 import PF2S
|
|||||||
|
|
||||||
class TextCanvas():
|
class TextCanvas():
|
||||||
'Canvas for text printing, requires PF2 lib'
|
'Canvas for text printing, requires PF2 lib'
|
||||||
|
broken: bool = False
|
||||||
width: int
|
width: int
|
||||||
height: int
|
height: int
|
||||||
canvas: bytearray = None
|
canvas: bytearray = None
|
||||||
@ -12,8 +13,13 @@ class TextCanvas():
|
|||||||
scale: int
|
scale: int
|
||||||
pf2 = None
|
pf2 = None
|
||||||
def __init__(self, width, *, wrap=False, rtl=False,
|
def __init__(self, width, *, wrap=False, rtl=False,
|
||||||
font_path='font.pf2', scale=1):
|
font_path='font.pf2', font_data_io=None, scale=1):
|
||||||
self.pf2 = PF2S(font_path, scale=scale)
|
if font_data_io is None:
|
||||||
|
font_data_io = open(font_path, 'rb')
|
||||||
|
self.pf2 = PF2S(font_data_io, scale=scale)
|
||||||
|
if self.pf2.broken:
|
||||||
|
self.broken = True
|
||||||
|
return
|
||||||
self.width = width
|
self.width = width
|
||||||
self.wrap = wrap
|
self.wrap = wrap
|
||||||
self.rtl = rtl
|
self.rtl = rtl
|
||||||
|
@ -147,7 +147,7 @@ Copyright © 2021-2022 NaitLee Soft. 保留一些權利。
|
|||||||
|
|
||||||
- 當然不能沒有 Python 和 Web 技術!
|
- 當然不能沒有 Python 和 Web 技術!
|
||||||
- [Bleak](https://bleak.readthedocs.io/en/latest/) 跨平台藍牙低功耗庫,牛!
|
- [Bleak](https://bleak.readthedocs.io/en/latest/) 跨平台藍牙低功耗庫,牛!
|
||||||
- [roddeh-i18n](https://github.com/roddeh/i18njs),當前內置的國際化功能受此啓發
|
- [roddeh-i18n](https://github.com/roddeh/i18njs),當前內置的國際化功能受此啟發
|
||||||
- [PF2 font](http://grub.gibibit.com/New_font_format),很好的簡易像素字體格式
|
- [PF2 font](http://grub.gibibit.com/New_font_format),很好的簡易像素字體格式
|
||||||
- ImageMagick 和 Ghostscript,有用的東西已經在系統裏,就當然不用考慮別的了
|
- ImageMagick 和 Ghostscript,有用的東西已經在系統裏,就當然不用考慮別的了
|
||||||
- [python-for-android](https://python-for-android.readthedocs.io/en/latest/),雖然有些麻煩的地方
|
- [python-for-android](https://python-for-android.readthedocs.io/en/latest/),雖然有些麻煩的地方
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
已知支援:`GB0X, GT01, YT01` (`X` 表示任意數字)
|
已知支援:`GB0X, GT01, YT01` (`X` 表示任意數字)
|
||||||
|
|
||||||
可在 Web 介面測試未列出的型號。在 `設定 -> 測試未知裝置`
|
可在 Web 介面測試未列出的型號。在 `設定 -> 測試未知裝置`
|
||||||
有機率成功!
|
有概率成功!
|
||||||
|
|
||||||
## 特性
|
## 特性
|
||||||
|
|
||||||
|
@ -140,5 +140,7 @@
|
|||||||
"monospace": "Monospace",
|
"monospace": "Monospace",
|
||||||
"rotate-image": "Bild drehen",
|
"rotate-image": "Bild drehen",
|
||||||
"test-unknown-device": "Unbekanntes Gerät testen",
|
"test-unknown-device": "Unbekanntes Gerät testen",
|
||||||
"now-will-scan-for-all-bluetooth-devices-nearby": "Der Scan sucht jetzt nach allen Bluetooth-Geräten in der Nähe"
|
"now-will-scan-for-all-bluetooth-devices-nearby": "Der Scan sucht jetzt nach allen Bluetooth-Geräten in der Nähe",
|
||||||
|
|
||||||
|
"pf2-font-not-found-or-broken-0": "PF2 font not found or broken: '{0}'"
|
||||||
}
|
}
|
@ -158,5 +158,6 @@
|
|||||||
"rotate-image": "Rotate Image",
|
"rotate-image": "Rotate Image",
|
||||||
"test-unknown-device": "Test Unknown Device",
|
"test-unknown-device": "Test Unknown Device",
|
||||||
"scan": "Scan",
|
"scan": "Scan",
|
||||||
"now-will-scan-for-all-bluetooth-devices-nearby": "Scan set to search for all bluetooth devides nearby."
|
"now-will-scan-for-all-bluetooth-devices-nearby": "Scan set to search for all bluetooth devides nearby.",
|
||||||
|
"pf2-font-not-found-or-broken-0": "PF2 font not found or broken: '{0}'"
|
||||||
}
|
}
|
@ -136,5 +136,6 @@
|
|||||||
"rotate-image": "ROLL PIC",
|
"rotate-image": "ROLL PIC",
|
||||||
"test-unknown-device": "I HAV STRENGE KITTE",
|
"test-unknown-device": "I HAV STRENGE KITTE",
|
||||||
"now-will-scan-for-all-bluetooth-devices-nearby": "WIL FIND ALL THINY KITTE OR NOT",
|
"now-will-scan-for-all-bluetooth-devices-nearby": "WIL FIND ALL THINY KITTE OR NOT",
|
||||||
"scan": "FIND"
|
"scan": "FIND",
|
||||||
|
"pf2-font-not-found-or-broken-0": "KITTE FONT LOST OR DEAD> {0}"
|
||||||
}
|
}
|
||||||
|
@ -148,5 +148,6 @@
|
|||||||
"javascript-accessibilityjs-description": "一些无障碍功能",
|
"javascript-accessibilityjs-description": "一些无障碍功能",
|
||||||
"javascript-catprinter-description": "猫咪打印机 (Cat-Printer) 主脚本",
|
"javascript-catprinter-description": "猫咪打印机 (Cat-Printer) 主脚本",
|
||||||
"free-software": "自由软件",
|
"free-software": "自由软件",
|
||||||
"free-software-description": "尊重您计算自由的软件。"
|
"free-software-description": "尊重您计算自由的软件。",
|
||||||
|
"pf2-font-not-found-or-broken-0": "PF2 字体丢失或损坏:'{0}'"
|
||||||
}
|
}
|
@ -36,7 +36,7 @@
|
|||||||
"dry-run": "乾運行",
|
"dry-run": "乾運行",
|
||||||
"dry-run-test-print-process-only": "乾運行:僅測試打印流程",
|
"dry-run-test-print-process-only": "乾運行:僅測試打印流程",
|
||||||
"you-can-close-this-page-manually": "您可手動關閉此頁面",
|
"you-can-close-this-page-manually": "您可手動關閉此頁面",
|
||||||
"please-enable-bluetooth": "請啓用藍牙",
|
"please-enable-bluetooth": "請啟用藍牙",
|
||||||
"error-happened-please-check-error-message": "發生錯誤,請檢查錯誤消息",
|
"error-happened-please-check-error-message": "發生錯誤,請檢查錯誤消息",
|
||||||
"you-can-seek-for-help-with-detailed-info-below": "您可以使用以下詳細信息尋求幫助",
|
"you-can-seek-for-help-with-detailed-info-below": "您可以使用以下詳細信息尋求幫助",
|
||||||
"or-try-to-scan-longer": "或者嘗試延長掃描時間",
|
"or-try-to-scan-longer": "或者嘗試延長掃描時間",
|
||||||
@ -106,7 +106,7 @@
|
|||||||
"show-this-help-message": "顯示此幫助信息",
|
"show-this-help-message": "顯示此幫助信息",
|
||||||
"do-nothing": "什麼也不做",
|
"do-nothing": "什麼也不做",
|
||||||
"scan-for-a-printer": "掃描打印機",
|
"scan-for-a-printer": "掃描打印機",
|
||||||
"text-printing-mode-with-options": "啓用文字打印並指定選項",
|
"text-printing-mode-with-options": "啟用文字打印並指定選項",
|
||||||
"image-printing-options": "圖片打印選項",
|
"image-printing-options": "圖片打印選項",
|
||||||
"convert-input-image-with-imagemagick": "使用 ImageMagick 轉換輸入圖片",
|
"convert-input-image-with-imagemagick": "使用 ImageMagick 轉換輸入圖片",
|
||||||
"reset-configuration-": "要重置配置嗎?",
|
"reset-configuration-": "要重置配置嗎?",
|
||||||
@ -148,5 +148,6 @@
|
|||||||
"javascript-accessibilityjs-description": "一些無障礙功能",
|
"javascript-accessibilityjs-description": "一些無障礙功能",
|
||||||
"javascript-catprinter-description": "貓咪打印機 (Cat-Printer) 主腳本",
|
"javascript-catprinter-description": "貓咪打印機 (Cat-Printer) 主腳本",
|
||||||
"free-software": "自由軟件",
|
"free-software": "自由軟件",
|
||||||
"free-software-description": "尊重您計算自由的軟件。"
|
"free-software-description": "尊重您計算自由的軟件。",
|
||||||
|
"pf2-font-not-found-or-broken-0": "PF2 字體丟失或損壞:'{0}'"
|
||||||
}
|
}
|
@ -148,5 +148,6 @@
|
|||||||
"javascript-accessibilityjs-description": "一些無障礙功能",
|
"javascript-accessibilityjs-description": "一些無障礙功能",
|
||||||
"javascript-catprinter-description": "貓咪打印機 (Cat-Printer) 主腳本",
|
"javascript-catprinter-description": "貓咪打印機 (Cat-Printer) 主腳本",
|
||||||
"free-software": "自由軟件",
|
"free-software": "自由軟件",
|
||||||
"free-software-description": "尊重您計算自由的軟件。"
|
"free-software-description": "尊重您計算自由的軟件。",
|
||||||
|
"pf2-font-not-found-or-broken-0": "PF2 字體丟失或損壞:'{0}'"
|
||||||
}
|
}
|
@ -148,5 +148,6 @@
|
|||||||
"javascript-accessibilityjs-description": "一些無障礙功能",
|
"javascript-accessibilityjs-description": "一些無障礙功能",
|
||||||
"javascript-catprinter-description": "貓咪印表機 (Cat-Printer) 主指令碼",
|
"javascript-catprinter-description": "貓咪印表機 (Cat-Printer) 主指令碼",
|
||||||
"free-software": "自由軟體",
|
"free-software": "自由軟體",
|
||||||
"free-software-description": "尊重您計算自由的軟體。"
|
"free-software-description": "尊重您計算自由的軟體。",
|
||||||
|
"pf2-font-not-found-or-broken-0": "PF2 字型丟失或損壞:'{0}'"
|
||||||
}
|
}
|
@ -3,7 +3,7 @@
|
|||||||
Cat-Printer: Web Frontend
|
Cat-Printer: Web Frontend
|
||||||
Use together with 'index.html'
|
Use together with 'index.html'
|
||||||
|
|
||||||
Copyright © 2021-2022 NaitLee Soft. All rights reserved.
|
Copyright © 2021-2023 NaitLee Soft. All rights reserved.
|
||||||
|
|
||||||
License GPL-3.0-or-later: https://www.gnu.org/licenses/gpl-3.0.html
|
License GPL-3.0-or-later: https://www.gnu.org/licenses/gpl-3.0.html
|
||||||
`;
|
`;
|
||||||
@ -922,7 +922,6 @@ class Main {
|
|||||||
if (
|
if (
|
||||||
error_details.name === 'org.bluez.Error.NotReady' ||
|
error_details.name === 'org.bluez.Error.NotReady' ||
|
||||||
error_details.name === 'org.freedesktop.DBus.Error.UnknownObject' ||
|
error_details.name === 'org.freedesktop.DBus.Error.UnknownObject' ||
|
||||||
error_details.name === 'org.bluez.Error.NotReady' ||
|
|
||||||
error_details.details.includes('not turned on') ||
|
error_details.details.includes('not turned on') ||
|
||||||
error_details.details.includes('No powered Bluetooth adapter') ||
|
error_details.details.includes('No powered Bluetooth adapter') ||
|
||||||
error_details.details.includes('WinError -2147020577')
|
error_details.details.includes('WinError -2147020577')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user