On Tue, 29 Nov 2022 10:36:32 GMT, Alexander Scherbatiy <[email protected]> 
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)
>
> Alexander Scherbatiy has updated the pull request incrementally with one 
> additional commit since the last revision:
> 
>   Fix typos in FlipPageFormat class comments

Could you review the updated fix?

I updated the sample which prints 4 rectangles: 
[PrintArrowPaperA5](https://bugs.openjdk.org/secure/attachment/101839/PrintArrowPaperA5.java).
The main difference with the previous sample 
[CutOffImage](https://bugs.openjdk.org/secure/attachment/101145/CutOffImage.java)
 is that the image generation is based on the provided PageFormat class passed 
to the `Printable.print(Graphics graphics, PageFormat pageFormat, int index)` 
method:
``` 
    private static void paintImage(Graphics2D g, PageFormat page, int 
pageIndex) {
        BufferedImage img = createImage((int) page.getWidth(), (int) 
page.getHeight(), page.getOrientation(), pageIndex);
        g.drawImage(img, 0, 0, null);
    }

    private static class TestPrintable implements Printable {

        @Override
        public int print(Graphics graphics, PageFormat pageFormat, int index) {
            paintImage((Graphics2D) graphics, pageFormat, index);
            return PAGE_EXISTS;
        }
    }
``` 
PrintArrowPaperA5 sample uses A5 paper size which allows to test it with real 
printer where A5 paper could be palced horizontally or vertically in the paper 
tray.

PrintArrowPaperA5 sample prints  four rectangles
1. size 5.8 × 8.3 inches (width < height), portrait orientation
2. size 5.8 × 8.3 inches (width < height), landscape orientation
3. size 8.3 × 5.8 inches (width > height), portrait orientation
4. size 8.3 × 5.8 inches (width > height), landscape orientation

jdk 19 only correctly prints rectangles 1 and 2 (width < height) on macOS: 
[print-arrow-paper-a5-macos-jdk19.pdf](https://bugs.openjdk.org/secure/attachment/101840/print-arrow-paper-a5-macos-jdk19.pdf)
Rectangles 3 and 4 (width > height) are truncated.

MacOS NSPrintInfo class has one to one correspondence between a paper size and 
its orientation:
a. (w < h) <-> portrait
b. (w > h) <-> landscape

The proposed fix adds FlipPageFormat class which is intermediate between 
PageFormat and NSPrintInfo and is created only if PageFormat contains a paper 
with width greater than height.

FlipPageFormat establish the following relations:

3. PageFormat: (width > height), portrait orientation
-> FlipPageFormat: (width < height), landscape orientation
-> NSPrintInfo: (width > height) (landscape orientation)

4. PageFormat: (width > height), landscape orientation
-> FlipPageFormat: (width < height), portrait orientation
-> NSPrintInfo: (width < height) (portrait orientation)

FlipPageFormat preserves the original PageFormat class to pass it to a user 
defined `Printable.print(Graphics, PageFormat, int)` method.

`PageFormat pageFormat = pageable.getPageFormat(pageIndex);` line is changed to 
`PageFormat pageFormat = getPageFormat(pageIndex);` 
in the method `getPageformatPrintablePeekgraphics(final int pageIndex)`
to uniformly get FlipPageFormat class from `private PageFormat 
getPageFormat(int pageIndex)` method.

With the fix PrintArrowPaperA5 sample prints pages with paper width greater 
than height without truncation on macOS: 
[print-arrow-paper-a5-macos-jdk-fix.pdf](https://bugs.openjdk.org/secure/attachment/101841/print-arrow-paper-a5-macos-jdk-fix.pdf).

-------------

PR: https://git.openjdk.org/jdk/pull/10808

Reply via email to