这是在Cocoa中实现缩放打印的正确方法吗?

时间:2017-09-06 01:12:32

标签: cocoa

我正在尝试在我的新Cocoa应用程序中实现打印。除了缩放之外,一切都工作正常,即缩放,即75%,125%等打印

据我从Apple文档中可以看出,该程序应该根据比例因子调整从rectForPage:方法返回的矩形。我找到了一些似乎以这种方式工作的样本Apple代码,以及cocoabuilder上的旧帖子。

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Printing/osxp_pagination/osxp_pagination.html

http://www.cocoabuilder.com/archive/cocoa/211683-scaled-printing.html

我的rectForPage:代码如下所示:

std::net::IpAddr

然而,我无法让它正常工作。无论此方法返回的是什么尺寸的矩形,输出始终以100%打印。我确实验证了actualPageRect会根据比例设置而变化,并且打印输出会裁剪到指定的矩形,但不会缩放。我有点期待Apple会根据比例因子来扩展视图,但事实并非如此。

经过长时间的调查,我放弃了这个方法,并尝试了另一种方法。现在我有rectForPage:总是返回实际的页面大小,我更改了drawRect:使用仿射变换绘制缩放输出:

NSPrintInfo *pi = [[NSPrintOperation currentOperation] printInfo];
NSSize paperSize = [pi paperSize]; // Calculate the page dimensions in points
// Convert dimensions to the scaled view
CGFloat pageScale = [[[pi dictionary] objectForKey:NSPrintScalingFactor] floatValue];
CGFloat topMargin = [pi topMargin];
CGFloat leftMargin = [pi leftMargin];
CGFloat bottomMargin = [pi bottomMargin];
CGFloat rightMargin = [pi rightMargin];
CGFloat pageHeight = (paperSize.height - topMargin - bottomMargin) / pageScale;
CGFloat pageWidth = (paperSize.width - leftMargin - rightMargin) / pageScale;
NSRect bounds = [self bounds];
NSRect actualPageRect = NSMakeRect(
                                   NSMinX(bounds),
                                   NSMinY(bounds),
                                   pageWidth * pageScale,
                                   pageHeight * pageScale);

return actualPageRect;

我还修改了knowsPageRange:方法以考虑扩展。

结果是 - 这是有效的。该程序现在生成我想要的任何缩放输出,并且它是正确分页的。但我很确定这是错误的解决方案。我认为必须有一些我遗漏的细节,它可以通过缩放从rectForPage:返回的矩形来正确缩放,但我在这一点上很难过。由于它正在工作,我可以离开它,但如果这不是正确的方法,我宁愿修复它。

2 个答案:

答案 0 :(得分:1)

让我们从the documentation开始使用rectForPage:的定义:

  

由子类实现,以确定要为页码page打印的视图部分。

  

一个矩形,用于定义要为pageNumber打印的视图区域。如果NSZeroRect在视图的边界之外,则此方法返回pageNumber

所以这些是裁剪矩形。无论你绘制什么都被裁剪到这个矩形,并且该绘图被视为该页面的内容。 (你可能也会在drawRect:中得到那个矩形,期望你跳过它之外的任何东西。)这些矩形是两个边界单位(即,相同的单位, self.bounds是真实的单位(默认为1/72英寸)。

那么,打印信息的scalingFactor呢?

据我所知,截至10.12.6,它不适用于AppKit - 您必须自己检索并使用scalingFactor。 (我可能会遗漏一些东西。)

drawRect:中缩放绘图是完全合理的方法。您的页面矩形将保持不变;你的绘图将被缩放。如果scalingFactor为2,则您的绘图将加倍,并且您将在页面矩形中有四分之一(每个轴上1/2)。

由于页面矩形是边界单位,因此缩放边界(使用setBoundsSize:scaleUnitSquareToSize:)是另一种方式。然后你的绘图页面rect将同时缩放。问题在于,这适用于屏幕绘图和打印图纸;当您有一个单独的视图或视图层次结构进行打印时,它最有意义。

所以,基于参考文档(以及我在10.12.6上的实验),我认为你做对了。

至于文档中的示例,我认为它是为TextEdit的页面视图编写的,其中边距是视图绘图的一部分(请注意,它会裁剪topMarginbottomMargin,例如)。也就是说,只要您发现示例代码看似错误,不清楚或基于未说明的假设,我建议您file a bug

答案 1 :(得分:0)

我为OSX / Swift 5支付2美分: (不要错过knowsPageRange,否则不会调用rectForPage。)

override func knowsPageRange(_ range: NSRangePointer) -> Bool {
        return true
    }


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

    guard let pi = NSPrintOperation.current?.printInfo else{return CGRect.zero}

    let paperSize = pi.paperSize // Calculate the page dimensions in points
    // Convert dimensions to the scaled view

    let dict = pi.dictionary()
    let pageScale = dict[NSPrintInfo.AttributeKey.scalingFactor] as! CGFloat

    let topMargin = pi.topMargin
    let  leftMargin = pi.leftMargin
    let bottomMargin = pi.bottomMargin
    let rightMargin = pi.rightMargin
    let pageHeight = (paperSize.height - topMargin - bottomMargin) / pageScale
    let pageWidth = (paperSize.width - leftMargin - rightMargin) / pageScale
    let bounds = self.bounds
    let actualPageRect = NSRect(x: NSMinX(bounds), y:  NSMinY(bounds), width: pageWidth * pageScale, height: pageHeight * pageScale)

    return actualPageRect
}

在某些情况下,请确保Rect为零,否则打印将停止:否则,将无限期打印。

就我而言,我只是做了: ..

if page>1{return CGRect.zero}