This commit is contained in:
dzc committed 2026-09-23 18:11:35 +08:00
1 parent eaec48a95b
commit 6a9dbf9080
3 files changed
+48 -7

No files matched your search

+15
View File
@@ -3,6 +3,13 @@ import 'dart:typed_data';
import 'package:image/image.dart';
/// 纵向卡面 → 横向位图的预旋转方向(Windows Pavo 直打校准常量)。
///
/// 实测(2026-09-23 Windows CS-200e):纵向缓冲 + byOrientation=1 会被 SDK 旋转 90°
/// 且锚定错位(内容横向贴左、顺时针转卡才可读)。修复=统一预旋转成 1014×642 横向
/// 位图 + byOrientation=2 打印。此常量定旋转方向:打测试卡若差 90°(顺/逆)就取反。
const bool pavoPortraitRotateClockwise = true;
/// PNG data URL 解析与像素层转换(Windows PavoApi 直打用)。
///
/// 卡面为 CR-80 @300dpi:横向 1014×642 / 纵向 642×1014,按源图纵横比自动选择;
@@ -20,6 +27,14 @@ class CardImage {
/// 宽 ≥ 高 = 横向卡面
bool get isLandscape => width >= height;
/// 纵向卡面预旋转为横向位图(Windows Pavo 直打用,见 [pavoPortraitRotateClockwise])。
/// 已是横向的原样返回。返回新实例,原实例不变(正/背面各自转换)。
CardImage toLandscape() {
if (isLandscape) return this;
final rotated = copyRotate(_canvas, angle: pavoPortraitRotateClockwise ? 90 : -90);
return CardImage._(rotated, rotated.width, rotated.height);
}
/// 解析 data:image/png;base64,…(或其他 data URL 形式),缩放到卡面画布并铺白底。
static CardImage fromDataUrl(String dataUrl) {
if (dataUrl.trim().isEmpty) {
+12 -7
View File
@@ -113,17 +113,22 @@ Future<void> pavoPrintSync({
}
final printer = printers.first.toNativeUtf16();
try {
final frontImg = CardImage.fromDataUrl(frontColor);
// Windows Pavo 直打方向校准(2026-09-23 实测):纵向位图 + byOrientation=1 会被
// SDK 旋转 90° 且锚定错位;统一预旋转成 1014×642 横向位图后按 byOrientation=2 打印。
// 旋转方向常量见 card_image.dart 的 pavoPortraitRotateClockwise(测试卡校准)。
final frontImg = CardImage.fromDataUrl(frontColor).toLandscape();
final frontBgr = frontImg.toBgr24();
final Uint8List? frontKGray =
frontK != null && frontK.isNotEmpty ? CardImage.fromDataUrl(frontK).toGray8() : null;
final Uint8List? frontKGray = frontK != null && frontK.isNotEmpty
? CardImage.fromDataUrl(frontK).toLandscape().toGray8()
: null;
final Uint8List? backBgr;
final Uint8List? backKGray;
if (backColor != null && backColor.isNotEmpty) {
final backImg = CardImage.fromDataUrl(backColor);
final backImg = CardImage.fromDataUrl(backColor).toLandscape();
backBgr = backImg.toBgr24();
backKGray =
backK != null && backK.isNotEmpty ? CardImage.fromDataUrl(backK).toGray8() : null;
backKGray = backK != null && backK.isNotEmpty
? CardImage.fromDataUrl(backK).toLandscape().toGray8()
: null;
} else {
backBgr = null;
backKGray = null;
@@ -136,7 +141,7 @@ Future<void> pavoPrintSync({
frontK: frontKGray,
backBgr: backBgr,
backK: backKGray,
isLandscape: frontImg.isLandscape,
isLandscape: true,
copies: copies,
);
} finally {
+21
View File
@@ -55,3 +55,24 @@ Root: HKCU; Subkey: "Software\Microsoft\Windows\CurrentVersion\Run"; ValueType:
[Run]
Filename: "{app}\{#AppExeName}"; Description: "立即运行 {#AppName}"; Flags: nowait postinstall skipifsilent
; 覆盖安装/卸载前结束正在运行的实例,避免 exe/dll 被占用导致文件替换失败
[Code]
procedure TaskkillApp();
var
ResultCode: Integer;
begin
Exec(ExpandConstant('{cmd}'), '/C taskkill /F /IM "{#AppExeName}"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
end;
function PrepareToInstall(var NeedsRestart: Boolean): String;
begin
TaskkillApp();
Result := '';
end;
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usUninstall then
TaskkillApp();
end;