mirror of
https://github.com/NaitLee/Cat-Printer.git
synced 2025-05-20 01:00:08 -07:00
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:
parent
ab2e83e160
commit
467857e542
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
|
||||||
|
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:
|
||||||
@ -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)
|
||||||
|
|
||||||
|
@ -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