这是在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:代码看起来像这样:

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;

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

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

- (void)drawRect:(NSRect)dirtyRect
{
    [super drawRect:dirtyRect];
    NSAffineTransform* xform = [NSAffineTransform transform];
    [xform scaleXBy:pageScale yBy:pageScale];
    [xform concat];
    [self layoutReport];
    [xform invert];
    [xform concat];
}

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

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

最佳答案 让我们从rectForPage:的定义开始,从
the documentation开始:

Implemented by subclasses to determine the portion of the view to be printed for the page number page.

A rectangle defining the region of the view to be printed for pageNumber. This method returns NSZeroRect if pageNumber is outside the view’s bounds.

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

那么,打印信息的scalingFactor呢?

据我所知,从10.12.6开始,它不适用于AppKit – 您必须自己检索并使用scalingFactor. (我可能会遗漏一些东西.)

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

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

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

至于文档中的示例,我认为它是为TextEdit的页面视图编写的,其中边距是视图绘图的一部分(请注意,它会从topMargin和bottomMargin中裁剪掉).也就是说,我会建议您在任何时候找到看似错误,不清楚或基于未说明的假设的示例代码.

点赞