Better PF2 font handling: from wd, pf2 dir, or pf2.zip;

Fix too light strength for command line printing;
Minor changes to code
This commit is contained in:
NaitLee 2023-04-07 18:27:02 +08:00
parent ab2e83e160
commit 467857e542
15 changed files with 71 additions and 28 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

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:
@ -667,9 +692,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

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