[OpenJDK 2D-Dev] [9] Review request for 8167102: [macosx] PrintRequestAttributeSet breaks page size set using PageFormat

Anton Litvinov anton.litvinov at oracle.com
Tue Mar 28 12:55:57 UTC 2017

Hello Prasanta,

The correct "PageFormat" for each separate page is retrieved in the 
native function "PrinterView.m::rectForPage:(NSInteger)" by invoking the 
Java method "CPrinterJob.getPageformatPrintablePeekgraphics(int)" with 
the first expression specified below and getting the value of 
"PageFormat" from the returned array with the second expression 
specified below.

"jobjectArray objectArray = JNFCallObjectMethod(env, fPrinterJob, 
jm_getPageformatPrintablePeekgraphics, jPageNumber); // AWT_THREADING 
Safe (AWTRunLoopMode)"
"jobject pageFormat = (*env)->GetObjectArrayElement(env, objectArray, 0);"

But in that native method "PrinterView.m::rectForPage" only the page 
orientation field "mOrientation" of the retrieved "PageFormat" for each 
page is analyzed and is set to "NSPrintInfo" object through 
"NSPrintOperation". Thus for some reason at that method analysis of the 
paper size is ignored.

So obviously not taking into account individual paper size of the pages 
for the case, which you described, when the user's code specifies 
different "PageFormat" instances for different pages of the document, 
should take place in JDK, though I did not verify this practically. But 
this issue existed before my fix and is not a result of the fix.

I do not see anything bad in the hard coded "0" page number used in my 
fix, because we need to initialize "NSPrintInfo" with a valid page size 
and the page size of the first page of the document is the only correct 
or appropriate value for this moment, and because this approach already 
exists in "RasterPrinterJob.java" as the next expression.

"PageFormat pf = (PageFormat)pageable.getPageFormat(0).clone();"

 From my point of view, the issue about disrespect of different paper 
sizes for different pages of the document is the issue which is 
different from the issue described in this bug (JDK-8167102) and should 
be fixed separately from my bug, because:
- In my bug "java.awt.print.Printable" interface is involved, while in 
this new issue "java.awt.print.Pageable" interface is the explicit 
- In my bug calling "PrinterJob.print(PrintRequestAttributeSet)" with a 
non-empty "PrintRequestAttributeSet" is the obligatory and the key 
requirement, while in the new issue this condition is irrelevant.
- For my bug one regression test is necessary, while for the new issue 
the different regression test is necessary.

Therefore I suggest to file a separate bug for the discovered issue and 
to address it separately from this bug (JDK-8167102). Would you agree 
with this suggestion? Would you approve the second version of the fix 
for the bug JDK-8167102?

Thank you,

On 3/28/2017 12:46 PM, Prasanta Sadhukhan wrote:
> Hi Anton,
> On 3/27/2017 10:05 PM, Anton Litvinov wrote:
>> Hello Prasanta,
>> Indeed it is Mac specific, as it was written in my previous e-mail, I 
>> verified this fact on Windows OS and Linux OS by your request.
>> Yes, I am fully sure that, when the bug occurs, the paper size of the 
>> printed page is wrong, as it is stated in the bug, and I am fully 
>> sure that with the applied any of 2 versions of the created fix, the 
>> paper size of the printed page becomes correct and as expected. 
>> Otherwise, I would not send the fix for review. The instruction, by 
>> following which the bug can be reproduced, is written in "STEPS TO 
>> FOLLOW TO REPRODUCE THE PROBLEM :" section of the description of the 
>> bug in JBS. This bug is raised by the user, who owns a support 
>> contract and requests for resolution of this bug, this can be seen in 
>> proper comments of the bug record.
>> The automated regression test is not possible for this bug, since it 
>> is necessary to verify visually that the document is physically 
>> printed on the paper of the expected size. Otherwise, I would send 
>> the 1st version of the fix with the automated test already, it is not 
>> the first bug in JDK on which I have been working. By your request 
>> the regression test, even though it is manual, was created and added 
>> to the 2nd version of the fix.
>> Yes, it is correct, the implemented by the test, and the test case 
>> method "Printable.print(Graphics, PageFormat, int)" receives the 
>> correct instance of "PageFormat" in runtime in scenario described in 
>> this bug, because, as you already described, it is extracted using 
>> the expression "pageable.getPageFormat(pageIndex)" in the Java method 
>> "sun.lwawt.macosx.CPrinterJob.getPageformatPrintablePeekgraphics(int)" 
>> called from "PrinterView.m::rectForPage:(NSInteger)" and further 
>> transferred in this method to the Java method 
>> "sun.lwawt.macosx.CPrinterJob.printAndGetPageFormatArea".
>> The wrong paper size which is returned from the method 
>> "RasterPrinterJob.getPageFormatFromAttributes()" and which is set to 
>> certain fields of the Objective-C  object "NSPrintInfo" in the 
>> function "CPrinterJob.m::javaPaperToNSPrintInfo" through the next 
>> call sequence
>> CPrinterJob.m::printLoop() --> 
>> CPrinterJob.m::javaPrinterJobToNSPrintInfo() --> 
>> CPrinterJob.m::javaPageFormatToNSPrintInfo() --> 
>> CPrinterJob.m::javaPaperToNSPrintInfo()
>> further influences physical size of all pages printed by 1 printer job.
>> Thus, I consider that firstly "PageFormat" returned from 
>> "RasterPrinterJob.getPageFormatFromAttributes()" is wrong, and 
>> secondly setting paper size from this wrong "PageFormat" to proper 
>> fields of "NSPrintInfo" object is also incorrect and is a root cause 
>> of this bug.
> OK. So, pageformat values set to native NSPrintInfo is different 
> (wrong) compared to what is being passed to user.
>> Implementation of Java Print Server API surely contains many issues, 
>> and only working on this bug I already encountered 2 additional 
>> different issues, which are described in one of my comments in this 
>> bug record in JBS. However, I prefer to resolve issues separately and 
>> to resolve this particular bug also separately from other issues 
>> which we can indefinitely find while looking at the code and 
>> debugging it, also because it is necessary to deliver the fix for 
>> this bug to "jdk8u-dev" repository finally, while JDK 9 is currently 
>> in RDP 2 phase at which large fixes affecting more platforms or large 
>> code scope would hardly be accepted by Group and Area leads or the 
>> release team.
>> I would like to bring also your attention again to the fact, which 
>> was mentioned in my previous e-mail, that I already ran all manual 
>> and automatic "jtreg" regression tests related to printing from open 
>> and closed parts of JDK on JDK 9 without the fix and with the fix, 
>> what is 198 tests.
>> Do you find anything incorrect in the 2nd version of the fix? Will 
>> you approve the 2nd version of the fix?
> I think there might be a (probable) issue with this fix. PageFormat of 
> 1st page only is used to get the information.
> jobject page = JNFCallObjectMethod(env, srcPrinterJob, 
> jm_getPageFormat, (jint)0);
> What if user has set different pageformat to different page like this 
> below? Will it not lose the 2nd page pageformat? I guess in 
> windows/linux, we obtain pageformat for each pageindex
> PrinterJob job = PrinterJob.getPrinterJob();
> // Create a landscape pageformat
> PageFormat pfl = job.defaultPage();
> pfl.setOrientation(PageFormat.LANDSCAPE);
> //Setup a book
> Book bk = new Book();
> bk.append(new xPrintable(), pfl); // 1st page landscape , can be diff. 
> pagesize too
> bk.append(new xxPrintable(), job.defaultPage()); //2nd page portrait
> job.setPageable(bk);
> Regards
> Prasanta
>> Thank you,
>> Anton
>> On 3/27/2017 9:52 AM, Prasanta Sadhukhan wrote:
>>> Hi Anton,
>>> Ok. So, it seems it mac specific. But, are you sure wrong page size 
>>> is used in mac as is claimed in the bug?
>>> I thought we could use automated regression test instead of manual 
>>> by checking pageformat value in print() as compared to what user 
>>> passes in setPrintable().
>>> Then, I see in print() method in testcase, the "PageFormat" argument 
>>> passed has same values as it is passed in setPrintable() in main() 
>>> even without your fix.
>>> If I reverse trace from print() method present in testcase, I see it 
>>> is called from CPrinterJob.java#printAndGetPageFormatArea()
>>> which is called from PrinterView.m#rectForPage. And before calling 
>>> printAndGetPageFormatArea() it calls 
>>> getPageformatPrintablePeekgraphics() which calls 
>>> pageable.getPageFormat(pageIndex), so it should behave same as 
>>> windows. Am I missing something?
>>> Regards
>>> Prasanta
>>> On 3/27/2017 3:32 AM, Anton Litvinov wrote:
>>>> Hello Prasanta,
>>>> I verified that the bug is not reproducible using JDK 9 compiled 
>>>> from the latest version of "jdk9/client" forest neither on Windows, 
>>>> nor on Linux platform, therefore, yes, this bug is only Mac 
>>>> specific. Debugging showed that on Windows platform the behavior is 
>>>> exactly like you described, on Windows 
>>>> "RasterPrinterJob.print(PrintRequestAttributeSet)" method is 
>>>> responsible for printing the documents and in this method 
>>>> "RasterPrinterJob.printPage(Pageable, int)" is called for each page 
>>>> separately, and in this "printPage" method "PageFormat" instance 
>>>> used for printing of the page is extracted from the the transferred 
>>>> as the method argument instance of "Pageable" by the expression 
>>>> "origPage = document.getPageFormat(pageIndex);".
>>>> The new version of the fix was created. Could you please review the 
>>>> second version of the fix.
>>>> Webrev (the 2nd version): 
>>>> http://cr.openjdk.java.net/~alitvinov/8167102/jdk9/webrev.01
>>>> In the second version of the fix:
>>>> 1. Calling for "RasterPrinterJob.getPageFormatFromAttributes()" was 
>>>> substituted for "sun.lwawt.macosx.CPrinterJob.getPageFormat(int)" 
>>>> in the native method "CPrinterJob.m#javaPrinterJobToNSPrintInfo".
>>>> 2. The method "RasterPrinterJob.getPageFormatFromAttributes()" was 
>>>> removed, since it is not called from any other code in "jdk" 
>>>> repository.
>>>> 3. The manual regression test was created.
>>>> Also on OS X I executed all manual and automatic "jtreg" regression 
>>>> tests related to printing from the listed below directories and the 
>>>> corresponding directories in the closed repositories using both JDK 
>>>> 9 compiled without and with the fix, and I verified that no new 
>>>> test failed on JDK 9 with the fix.
>>>> The directories with the regression tests from open repositories:
>>>> - "jdk/test/java/awt/print"
>>>> - "jdk/test/javax/print"
>>>> Thank you,
>>>> Anton
>>>> On 3/22/2017 7:42 AM, Prasanta Sadhukhan wrote:
>>>>> Hi Anton,
>>>>> I thought about your point and have a question: does this issue 
>>>>> not reproduce in non-mac platform?
>>>>> I thought it probably would so suggested modifying setAttributes() 
>>>>> . But, if it is only reproduced in mac, we need to find out why 
>>>>> despite this setAttributes() flaw, how this is working in non-mac 
>>>>> platform?
>>>>> It probably might work in windows/linux because in 
>>>>> RasterPrinterJob.print(attr) method, after it calls 
>>>>> setAttributes(), it calls printPage() where it gets the original 
>>>>> PageFormat
>>>>> by calling getPageFormat(pageIndex) and gets the orientation, 
>>>>> imageablearea
>>>>> and not by constructing pageFormat from attributes as it is done 
>>>>> in mac.
>>>>> So, probably, in mac also, we need to do away with 
>>>>> getPageFormatFromAttributes() call  and call 
>>>>> getPageFormat(pageIndex) from 
>>>>> CPrinterJob.m#javaPrinterJobToNSPrintInfo().
>>>>> Regards
>>>>> Prasanta
>>>>> On 3/21/2017 8:15 PM, Anton Litvinov wrote:
>>>>>> Hello Prasanta,
>>>>>> Thank you for review of this fix. I have tried to apply the 
>>>>>> approach which you suggested and it allowed to resolve the issue. 
>>>>>> In this case I agree that it would be more correct to resolve the 
>>>>>> issue in 
>>>>>> "RasterPrinterJob.setAttributes(PrintRequestAttributeSet)" 
>>>>>> method. In the first version of the fix I decided to change the 
>>>>>> method "RasterPrinterJob.getPageFormatFromAttributes()", because 
>>>>>> it is invoked only from 1 place in JDK code and this place is 
>>>>>> located in OS X specific code 
>>>>>> "jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m", 
>>>>>> so that would automatically minimize the affected by the fix 
>>>>>> platforms to OS X only.
>>>>>> Starting to work on implementation of the second version of the 
>>>>>> fix including the regression test.
>>>>>> Thank you,
>>>>>> Anton
>>>>>> On 3/21/2017 12:52 PM, Prasanta Sadhukhan wrote:
>>>>>>> I think the real problem is not in 
>>>>>>> RasterPrinterJob.getPageFormatFromAttributes().
>>>>>>> One can see that, when we call RasterPrinterJob.setPrintable(), 
>>>>>>> we call updatePageAttributes() which in turn calls 
>>>>>>> updateAttributesWithPageFormat() where orientation, media and 
>>>>>>> mediaprintablearea "attributes" get populated/cached from the 
>>>>>>> "pageformat" supplied by the user.
>>>>>>> But, when PrinterJob.print(PrintRequestAttributeSet) is called, 
>>>>>>> it calls setAttributes(attributes) where "attributes" is what is 
>>>>>>> populated by the user. It does not contain orientation,media and 
>>>>>>> mediaprintablearea attributes for this bug, so setAttributes 
>>>>>>> sets cached attribute with this user-set attribute instance
>>>>>>> />>else {//
>>>>>>> //>>            // for AWT where pageable is not an instance of 
>>>>>>> OpenBook,//
>>>>>>> //>>            // we need to save paper info//
>>>>>>> // >>           this.attributes = attributes;//
>>>>>>> // >>       }//
>>>>>>> /
>>>>>>> //thereby losing the attributes it has cached earlier from user 
>>>>>>> pageformat. I think we should check if this.attributes is not 
>>>>>>> null, then retain those attributes unless explicitly set by the 
>>>>>>> user in user-defined attributes.
>>>>>>> But, this code is used by windows,linux,mac so it needs to be 
>>>>>>> tested against all those platforms to ensure we are not 
>>>>>>> regressing anything.
>>>>>>> Also, I think user should call validatePage(PageFormat) in 
>>>>>>> application to check if the settings passed is compatible with 
>>>>>>> the printer or not, get compatible/adjusted pageformat and call 
>>>>>>> setPrintable() with that "adjusted" pageformat. If user pass 
>>>>>>> 0,0,fullpaperwidth,fullpaperheight as imageablearea, then he 
>>>>>>> should not expect this setting to be used since printer will 
>>>>>>> have its own hardware limitation (and use some offset printing)
>>>>>>> BTW, a regression testcase (even if it is manual) should be 
>>>>>>> created with the fix.
>>>>>>> Regards
>>>>>>> Prasanta
>>>>>>> On 3/17/2017 10:59 PM, Anton Litvinov wrote:
>>>>>>>> Hello,
>>>>>>>> Could you please review the following fix for the bug.
>>>>>>>> Bug: https://bugs.openjdk.java.net/browse/JDK-8167102
>>>>>>>> Webrev: 
>>>>>>>> http://cr.openjdk.java.net/~alitvinov/8167102/jdk9/webrev.00
>>>>>>>> The bug consists in the fact that, if the user's application 
>>>>>>>> specifies the required page size (media size) through 
>>>>>>>> "java.awt.print.PrinterJob" API particularly via 
>>>>>>>> "java.awt.print.PageFormat" instance supplied to the method 
>>>>>>>> "PrinterJob.setPrintable(Printable, PageFormat)" and calls 
>>>>>>>> "PrinterJob.print(PrintRequestAttributeSet)" with 
>>>>>>>> "javax.print.attribute.PrintRequestAttributeSet" containing at 
>>>>>>>> least 1 any "PrintRequestAttribute", then the page or pages 
>>>>>>>> will be printed with "PageFormat" describing the default page 
>>>>>>>> size of the printer which is different from the expected and 
>>>>>>>> originally set by the user's application "PageFormat".
>>>>>>>> Debugging showed that the new "PageFormat" with unexpected 
>>>>>>>> media size is created in the method 
>>>>>>>> "sun.print.RasterPrinterJob.getPageFormatFromAttributes()" 
>>>>>>>> which is invoked from the native function 
>>>>>>>> "jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m::javaPrinterJobToNSPrintInfo". 
>>>>>>>> The method "RasterPrinterJob.getPageFormatFromAttributes()" 
>>>>>>>> returns a new "PageFormat" always, if the provided by the user 
>>>>>>>> "PrintRequestAttributeSet" is not empty, and the default values 
>>>>>>>> are set to particular instance variables of this "PageFormat", 
>>>>>>>> if "PrintRequestAttributeSet" does not contain the searched 
>>>>>>>> "OrientationRequested", "MediaSizeName", "MediaPrintableArea" 
>>>>>>>> attributes.
>>>>>>>> THE SOLUTION:
>>>>>>>> Although it is clearly stated in Java Platform SE 8 API 
>>>>>>>> Specification (documentation of the method 
>>>>>>>> "PrinterJob.print(PrintRequestAttributeSet)")
>>>>>>>> Specification URL: 
>>>>>>>> http://docs.oracle.com/javase/8/docs/api/java/awt/print/PrinterJob.html#print-javax.print.attribute.PrintRequestAttributeSet-
>>>>>>>> that media size, orientation and imageable area attributes 
>>>>>>>> specified in "PrintRequestAttributeSet" supplied to the method 
>>>>>>>> "PrinterJob.print" will be used for construction of a new 
>>>>>>>> "PageFormat", which will be passed to "Printable" object, 
>>>>>>>> instead of the original "PageFormat" instance set through 
>>>>>>>> "PrinterJob.setPrintable" method, the observed in this issue 
>>>>>>>> behavior is a bug, because in the bug test case neither media 
>>>>>>>> size, nor orientation, nor imageable area attributes are 
>>>>>>>> specified in "PrintRequestAttributeSet".
>>>>>>>> The fix alters the method 
>>>>>>>> "sun.print.RasterPrinterJob.getPageFormatFromAttributes()" to 
>>>>>>>> use corresponding values from "PageFormat" instance originally 
>>>>>>>> set through "PrinterJob" API during construction of the new 
>>>>>>>> "PageFormat", when it is found out that "OrientationRequested", 
>>>>>>>> or "MediaSizeName", or "MediaPrintableArea" attribute is not 
>>>>>>>> specified in "PrintRequestAttributeSet" supplied to 
>>>>>>>> "PrinterJob.print" method.
>>>>>>>> Thank you,
>>>>>>>> Anton

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/2d-dev/attachments/20170328/ed356441/attachment.html>

More information about the 2d-dev mailing list