Merge branch 'NaitLee:main' into imagemagik-usability

This commit is contained in:
Keldon 2023-04-13 10:26:05 +10:00 committed by GitHub
commit dbe18dd89e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 155 additions and 80 deletions

5
.gitignore vendored
View File

@ -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
View File

@ -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
View 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

View File

@ -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 $@

View File

@ -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 $@

View File

@ -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..."

View File

@ -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 dont 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 wont 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 wont affect the host. 5. Some say Docker isnt intended to be “stateful”. But nothing is better in my mere knowledge.
(Some say Docker isnt 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 youre in China Mainland (you guessed it!), or prefer manual setup: If Google isnt available there, or you prefer manual setup:
- Pick a working mirror. Currently theres [Tencent Cloud](https://mirrors.cloud.tencent.com/AndroidSDK/). - Pick a working mirror. Currently theres [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. Its 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. Its currently r25b, but lets 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 doesnt understand it. Lets 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
# lets create the container by first pulling the image # lets 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.

View File

@ -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

View File

@ -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)

View File

@ -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)

View 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

View File

@ -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

View File

@ -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/),雖然有些麻煩的地方

View File

@ -10,7 +10,7 @@
已知支援:`GB0X, GT01, YT01` `X` 表示任意數字) 已知支援:`GB0X, GT01, YT01` `X` 表示任意數字)
可在 Web 介面測試未列出的型號。在 `設定 -> 測試未知裝置` 可在 Web 介面測試未列出的型號。在 `設定 -> 測試未知裝置`
率成功! 率成功!
## 特性 ## 特性

View File

@ -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}'"
} }

View File

@ -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}'"
} }

View File

@ -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}"
} }

View File

@ -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}'"
} }

View File

@ -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}'"
} }

View File

@ -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}'"
} }

View File

@ -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}'"
} }

View File

@ -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')