Files
ICCery-CPU/Sources/Printing/PrintEngine.swift
T
Local Admin 43bff18101
Build macOS Packages / Build macOS (Intel) (push) Failing after 10s
Build macOS Packages / Build macOS (Apple Silicon) (push) Failing after 10s
Build macOS Packages / Build macOS (Universal) (push) Skipped
removed cruft and restructured.
2026-09-07 05:21:44 -07:00

132 lines
5.0 KiB
Swift

import AppKit
import Foundation
/// SPEC §2 / §7 — `NSPrintOperation` + `NSPrintInfo` + CorePrinting dictionary
/// injection + UI policy (lock Color Matching pane).
final class PrintEngine {
var jobTitle: String
var printerName: String
var mediaSize: String
var mediaType: String?
var paperSource: String?
var resolution: String?
var scaling: Double
var centered: Bool
var landscape: Bool
var colorMode: ColorMatchingMode
var lockColorManagement: Bool
var allowBasicDriverChanges: Bool
init(job: TargetJob) {
jobTitle = job.jobTitle
printerName = job.printSettings.printerName
mediaSize = job.printSettings.mediaSize
mediaType = job.printSettings.mediaType
paperSource = job.printSettings.paperSource
resolution = job.printSettings.resolution
scaling = job.printSettings.scaling
centered = job.printSettings.centered
landscape = false
colorMode = ColorMatchingMode.from(forceUnmanagedColor: job.printSettings.forceUnmanagedColor)
lockColorManagement = job.uiPolicy.lockColorManagement
allowBasicDriverChanges = job.uiPolicy.allowBasicDriverChanges
}
init() {
jobTitle = "Untitled"
printerName = ""
mediaSize = "A4"
mediaType = nil
paperSource = nil
resolution = nil
scaling = 1.0
centered = true
landscape = false
colorMode = .unmanaged
lockColorManagement = true
allowBasicDriverChanges = true
}
func makePrintInfo() throws -> NSPrintInfo {
let info = NSPrintInfo.shared.copy() as! NSPrintInfo
info.jobDisposition = .spool
info.isHorizontallyCentered = false
info.isVerticallyCentered = false
info.leftMargin = 0
info.rightMargin = 0
info.topMargin = 0
info.bottomMargin = 0
info.horizontalPagination = .clip
info.verticalPagination = .clip
info.orientation = landscape ? .landscape : .portrait
info.scalingFactor = 1.0 // geometric scaling is applied in the view, not here
if !printerName.isEmpty {
info.printer = NSPrinter(name: printerName) ?? info.printer
}
let paper = Geometry.paper(named: mediaSize).oriented(landscape: landscape)
info.paperSize = paper.size
info.paperName = NSPrinter.PaperName(rawValue: mediaSize)
ColorMatching.apply(colorMode, to: info)
do {
if let queue = try CUPSManager.namedQueue(printerName) ?? try CUPSManager.listQueues().first(where: { $0.name == printerName }) {
let bypass = CUPSManager.vendorColorBypass(make: queue.make, model: queue.model, ppdText: queue.ppdText)
CUPSManager.applyVendorBypass(bypass, to: info)
}
} catch {
TPLog.error("CUPS lookup failed: \(error)")
throw AppError.printer(String(describing: error))
}
applyOptionalPPDKeys(to: info)
return info
}
private func applyOptionalPPDKeys(to info: NSPrintInfo) {
var extras: [String: String] = [:]
if let mediaType = mediaType { extras["MediaType"] = mediaType }
if let paperSource = paperSource { extras["InputSlot"] = paperSource }
if let resolution = resolution { extras["Resolution"] = resolution }
if extras.isEmpty { return }
CUPSManager.applyVendorBypass(extras, to: info)
}
/// Presents `NSPrintPanel` as a sheet on `window` (SPEC §4.5).
func run(view: TargetCanvasView, window: NSWindow, presentPanel: Bool) {
do {
let info = try makePrintInfo()
view.printInfo = info
view.centered = centered
view.scaling = CGFloat(scaling)
let op = NSPrintOperation(view: view, printInfo: info)
op.jobTitle = jobTitle
op.showsPrintPanel = presentPanel
op.showsProgressPanel = true
op.canSpawnSeparateThread = false
ColorMatching.configurePanel(
op.printPanel,
lockColorManagement: lockColorManagement,
allowBasicDriverChanges: allowBasicDriverChanges
)
// Strip again just before the panel runs — system accessories may
// be installed lazily when the panel is created.
ColorMatching.stripColorMatchingAccessories(from: op.printPanel)
TPLog.info("NSPrintOperation begin — printer=\(printerName) media=\(mediaSize) mode=\(colorMode.pmValue)")
op.runModal(for: window, delegate: self, didRun: #selector(printOpDidRun(_:success:contextInfo:)), contextInfo: nil)
} catch {
PreviewWindowController.presentError(error, on: window)
}
}
@objc private func printOpDidRun(_ op: NSPrintOperation, success: Bool, contextInfo: UnsafeMutableRawPointer?) {
TPLog.info("NSPrintOperation finished success=\(success)")
// SPEC §4: exit 0 for cancel or completed print.
AppDelegate.shared?.pendingExitCode = .success
}
}