RFR: 8295737: macOS: Print content cut off when width > height with portrait orientation
SWinxy
duke at openjdk.org
Fri Oct 21 19:04:55 UTC 2022
On Fri, 21 Oct 2022 08:42:12 GMT, Alexander Scherbatiy <alexsch at openjdk.org> wrote:
> A printed content is truncated on macOS if the content paper size width larger than height with portrait orientation or width is less than height with landscape orientation.
>
> To reproduce the issue run the [CutOffImage](https://bugs.openjdk.org/secure/attachment/101145/CutOffImage.java) sample on MacOS.
>
> Four rectangles are printed:
> 1. size 300x100, portrait orientation
> 2. size 300x100, landscape orientation
> 3. size 100x300, portrait orientation
> 4. size 100x300, landscape orientation
>
> The first and fourth rectangles are truncated: [cut off content](https://bugs.openjdk.org/secure/attachment/101153/before-fix-all.pdf)
>
> The reason is that NSPrintInfo class does not allow to set paper size and orientation independently.
> Setting paper size width large than height changes NSPrintInfo orientation to landscape.
> Setting paper size width less than height changes NSPrintInfo orientation to portrait.
> Updating NSPrintInfo orientation from landscape to portrait or from portrait to landscape swaps NSPrintInfo paper width and height.
>
> The Cocoa code that shows NSPrintInfo behavior:
>
> #import <Cocoa/Cocoa.h>
>
> int main()
> {
> NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
> NSApp = [NSApplication sharedApplication];
>
> #ifdef __MAC_10_9 // code for SDK 10.9 or newer
> #define NS_PORTRAIT NSPaperOrientationPortrait
> #define NS_LANDSCAPE NSPaperOrientationLandscape
> #else // code for SDK 10.8 or older
> #define NS_PORTRAIT NSPortraitOrientation
> #define NS_LANDSCAPE NSLandscapeOrientation
> #endif
>
> printf("NS_PORTRAIT: %d\n", NS_PORTRAIT);
> printf("NS_LANDSCAPE: %d\n", NS_LANDSCAPE);
>
> printf("create default print info\n");
> NSPrintInfo* defaultPrintInfo = [[NSPrintInfo sharedPrintInfo] copy];
> NSSize size = [defaultPrintInfo paperSize];
> printf("orientation: %d, paper size: [%f, %f]\n", [defaultPrintInfo orientation], size.width, size.height);
>
> printf("call setUpPrintOperationDefaultValues\n");
> [defaultPrintInfo setUpPrintOperationDefaultValues];
> size = [defaultPrintInfo paperSize];
> printf("orientation: %d, paper size: [%f, %f]\n", [defaultPrintInfo orientation], size.width, size.height);
>
> double w = 300.0;
> double h = 100.0;
> printf("set size: [%f, %f]\n", w, h);
> [defaultPrintInfo setPaperSize:NSMakeSize(w, h)];
> size = [defaultPrintInfo paperSize];
> printf("orientation: %d, paper size: [%f, %f]\n", [defaultPrintInfo orientation], size.width, size.height);
>
> printf("Set NS_PORTRAIT orientation\n");
> [defaultPrintInfo setOrientation: NS_PORTRAIT];
> size = [defaultPrintInfo paperSize];
> printf("orientation: %d, paper size: [%f, %f]\n", [defaultPrintInfo orientation], size.width, size.height);
>
> [NSApp run];
>
> [NSApp release];
> [pool release];
> return(EXIT_SUCCESS);
> }
>
>
> On macOS Mojave 10.14.5 it prints:
>
>
> NS_PORTRAIT: 0
> NS_LANDSCAPE: 1
> create default print info
> orientation: 0, paper size: [612.000000, 792.000000]
> call setUpPrintOperationDefaultValues
> orientation: 0, paper size: [612.000000, 792.000000]
> set size: [300.000000, 100.000000]
> orientation: 1, paper size: [300.000000, 100.000000] // orientation flip
> Set NS_PORTRAIT orientation
> orientation: 0, paper size: [100.000000, 300.000000] // size flip
> ```
>
> There are four possible cases for printing a rectangle with different size and orientation:
> 1. Input: paper size: (w > h), orientation portrait
> [dstPrintInfo setPaperSize: NSMakeSize(w, h)] // size: (w, h), orientation: landscape
> [dstPrintInfo setOrientation: NS_PORTRAIT] // size: (h, w), orientation: portrait
> Note: width and height are swapped
> 2. Input: paper size: (w > h), orientation landscape
> [dstPrintInfo setPaperSize: NSMakeSize(h, w)] // size: (h, w), orientation: portrait
> [dstPrintInfo setOrientation: NS_LANDSCAPE] // size: (w, h), orientation: landscape
> 3. Input: paper size: (w < h), orientation portrait
> [dstPrintInfo setPaperSize: NSMakeSize(w, h)] // size: (w, h), orientation: portrait
> [dstPrintInfo setOrientation: NS_PORTRAIT] // size: (w, h), orientation: portrait
> 4. Input: paper size: (w < h), orientation landscape
> [dstPrintInfo setPaperSize: NSMakeSize(h, w)] // size: (h, w), orientation: landscape
> [dstPrintInfo setOrientation: NS_LANDSCAPE] // size: (h, w), orientation: landscape
> Note: width and height are swapped
>
> Only for cases 1 and 4 the final width and height are swapped.
> The proposed fix enlarges height for cases 1 and 4 to not cut the printed rectangle.
>
> It is not full fix which draws rectangles for cases 1 and 4 in the requested size.
> Setting requested size leads that subsequent orientation flips width and height.
> The fix only enlarges the truncated area in height direction. The enlarged area in width is preserved as before the fix.
>
> Printed rectangles before and after the fix:
> 1. size 300x100, portrait orientation: [before-fix-1.pdf](https://bugs.openjdk.org/secure/attachment/101157/before-fix-1.pdf), [after-fix-1.pdf](https://bugs.openjdk.org/secure/attachment/101162/after-fix-1.pdf)
> 2. size 300x100, landscape orientation: [before-fix-2.pdf](https://bugs.openjdk.org/secure/attachment/101156/before-fix-2.pdf), [after-fix-2.pdf](https://bugs.openjdk.org/secure/attachment/101161/after-fix-2.pdf)
> 3. size 100x300, portrait orientation: [before-fix-3.pdf](https://bugs.openjdk.org/secure/attachment/101155/before-fix-3.pdf), [after-fix-3.pdf](https://bugs.openjdk.org/secure/attachment/101160/after-fix-3.pdf)
> 4. size 100x300, landscape orientation: [before-fix-4.pdf](https://bugs.openjdk.org/secure/attachment/101154/before-fix-4.pdf), [after-fix-4.pdf](https://bugs.openjdk.org/secure/attachment/101159/after-fix-4.pdf)
>
> All four rectangles: [before-fix-all.pdf](https://bugs.openjdk.org/secure/attachment/101153/before-fix-all.pdf), [after-fix-all.pdf](https://bugs.openjdk.org/secure/attachment/101158/after-fix-all.pdf)
src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m line 340:
> 338: orientation = NS_PORTRAIT;
> 339: break;
> 340: }
Could we replace the switch with an if statement? I don't see a reason why we need to query the orientation if we're just going to override it.
int format = (*env)->CallIntMethod(env,srcPageFormat, jm_getOrientation); // AWT_THREADING Safe (!appKit)
NSPaperOrientation orientation;
if (format == java_awt_print_PageFormat_LANDSCAPE || format == java_awt_print_PageFormat_REVERSE_LANDSCAPE)) {
// AppKit printing doesn't support REVERSE_LANDSCAPE. Radar 2960295.
//+++gdb Are LANDSCAPE and REVERSE_LANDSCAPE still inverted?
orientation = NS_LANDSCAPE; //+++gdb Are LANDSCAPE and REVERSE_LANDSCAPE still inverted?
} else {
orientation = NS_PORTRAIT;
}
src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m line 362:
> 360: // [dstPrintInfo setPaperSize: NSMakeSize(h, w)] // size: (h, w), orientation: landscape
> 361: // [dstPrintInfo setOrientation: NS_LANDSCAPE] // size: (h, w), orientation: landscape
> 362: // Note: width and height are swapped
Comment is too lengthy. Here's my suggestion to condense.
Suggestion:
// It's not possible to set NSPrinterInfo paper size and orientation independently.
// Changing the paper size will change the orientation, and vise versa.
-------------
PR: https://git.openjdk.org/jdk/pull/10808
More information about the client-libs-dev
mailing list