Corbell
Corbell

Reputation: 1393

Cocoa printing with Swift: "Any" printer setup has irregular margins/page size, any workaround?

I'm working on a graphics app for Mac OS in Swift and want to have a professional WYSIWYG layout features for printing.

I've isolated a weird behavior of the Cocoa printing system and just wondered if anyone knows of a setup step I'm missing or a workaround. The issue is that the "Any" printer has irregular, non-centered margins even when horizontal+vertical centering is requested. In particular, the left margin of my landscape letter-size docuemnt is 18pt and the right margin is 40pt - bigger than 1/2", which I feel is an unacceptable contraint, not to mention the annoyance of not being able to rely on the requested centering.

My app is NSDocument-based and I set printInfo margins to 0, centered fields to true, and orientation to .landscape.

self.printInfo.topMargin = 0.0
self.printInfo.rightMargin = 0.0
self.printInfo.leftMargin = 0.0
self.printInfo.bottomMargin = 0.0
self.printInfo.isHorizontallyCentered = true
self.printInfo.isVerticallyCentered = true
self.printInfo.orientation = .landscape

let newPrintOp = NSPrintOperation(view: self.printView!, printInfo: self.printInfo)
newPrintOp.showsPrintPanel = true        
return newPrintOp

I am using Page Setup in this test. I have an EPSON printer that gives me the choice of regular or borderless printing, and with either option, selecting US Letter landscape, I get reasonable imageablePageBounds reported to draw into.

With the borderless page setup, I get

... imageablePageBounds: (0.0, 0.0, 792.0, 612.0)

and with 'regular' letter/landscape I get

... imageablePageBounds: (8.4000244140625, 8.399999618530273, 775.199951171875, 595.1999759674072)

The latter is setting to some driver minimum, but if you double the 8.4 point offsets and add to height and width you still get 792x612 == 11in x 8.5in

If instead I select "Any" printer in Page Setup and select US Letter, landscape, imageablePageBounds is reported (and enforced, even when printing to PDF) as: ... imageablePageBounds: (18.0, 18.0, 734.0, 576.0)

This gives 1/4" (18-pt) margins left, bottom, and top, but forces a 40-pt margin to the right (since width is only 734 - it should be 756 for a 10.5" drawing area). And indeed, if I try to draw an 10-inch image centered with 36pt margins, the right edge very annoyingly gets clipped unless I scale or shift it. It even gets clipped off with PDF output with this setup. Here's an image in the print panel that shows this clipping - the outer black line is the imageable view bounds given by the printing system, the blue line (right edge cut off) is a centered 10 x 7.5 image.

Screenshot of printing panel with issue

Does anyone know if there's a fix for this weird behavior? The ideal fix would be to get a reasonable 1/4" border as a default for anything I'm trying to print, but even if I can't get the max default width above 734pt I still want it to be centered so that I can at least work within 1/2" margins without any clipping.

Upvotes: 1

Views: 801

Answers (3)

Chris Walken
Chris Walken

Reputation: 408

We have worked on this problem for days and weeks with no good answer. We finally filed a DTS report with Apple and sent a simple app that clearly demonstrates the problem with margins. After a week of back and forth Apple's official response was "Sorry, that's just the way it is" and something about how they needed to get back to making emojis and don't have time for any of this printer stuff. Making matters more convoluted, this margin problem only happens on some sizes of paper. To get around this we added instructions to the apps documentation:

Press the (App Name) dropdown button on the print panel and then select "Page Attributes". This will pop up a listing of paper size choices with your paper choice selected with a checkmark. Hold the mouse down on the selected printer size and in a second or so a new menu will pop up and let you select borderless.

Upvotes: 1

Willeke
Willeke

Reputation: 15589

Here's my test app, it prints the view on one page without margins, maybe it helps:

Document.swift

override func windowControllerDidLoadNib(_ windowController: NSWindowController) {
    let newPrintInfo = NSPrintInfo()
    newPrintInfo.leftMargin = 0.0
    newPrintInfo.bottomMargin = 0.0
    newPrintInfo.rightMargin = 0.0
    newPrintInfo.topMargin = 0.0
    newPrintInfo.horizontalPagination = .clip
    newPrintInfo.verticalPagination = .clip
    self.printInfo = newPrintInfo
}

override var printInfo: NSPrintInfo {
    didSet {
        view.printInfoChanged(printInfo)
    }
}

override func printOperation(withSettings printSettings: [NSPrintInfo.AttributeKey : Any]) throws -> NSPrintOperation {
    return NSPrintOperation(view: view, printInfo: printInfo)
}

MyView.swift

func printInfoChanged(_ newPrintInfo: NSPrintInfo) {
    setFrameSize(newPrintInfo.paperSize)
}

override func locationOfPrintRect(_ rect: NSRect) -> NSPoint {
    return NSZeroPoint
}

override func knowsPageRange(_ range: NSRangePointer) -> Bool {
    range.pointee.location = 1
    range.pointee.length = 1
    return true
}

override func rectForPage(_ page: Int) -> NSRect {
    return bounds
}

override func draw(_ dirtyRect: NSRect) {
    super.draw(dirtyRect)
    NSColor.green.set()
    NSBezierPath(rect:bounds).stroke()
    NSColor.red.set()
    NSBezierPath(ovalIn:bounds).stroke()
}

Upvotes: 0

Corbell
Corbell

Reputation: 1393

While the original behavior does seem like a bug, it appears that setting printInfo.paperSize field may provide a partial workaround, as long as the Mac has an installed printer available.

In addition to my other setup, if I add the line

self.printInfo.paperSize = CGSize(width: 792.0, height: 612.0)

for my US-Letter landscape document, and still use Page Setup to set printer "Any" and letter/landscape, when the print job actually runs it now shows up having selected the driver from the EPSON driver rather than leaving the buggy "Any" driver's margins - the result is nicely centered with minimal margins as desired.

enter image description here

I tested on a MacBook Pro with no printer set up, and this workaround did not correct the issue - it still shows up with off-center margin and clips the drawing. So the workaround requires some actual printer to be installed.

I've filed a bug via Apple's feedback assistant, will post an update if anything more is discovered or resolved.

Upvotes: 0

Related Questions