[OpenJDK 2D-Dev] [10] RFR JDK-8186987:NullPointerException in RasterPrinterJob without PrinterResolution

Prasanta Sadhukhan prasanta.sadhukhan at oracle.com
Wed Sep 20 06:29:57 UTC 2017


Hi Phil,


On 9/19/2017 3:16 AM, Phil Race wrote:
> Hi,
>
>
> On 09/04/2017 03:07 AM, Prasanta Sadhukhan wrote:
>> Hi Prahalad, Phil,
>>
>> JDK uses DocumentProperties function [1] to query the printer 
>> configuration data in windows.
>>
>> For a RIcoh printer which we (in IDC) use by default, 
>> pDevMode->dmFields is initialized to 0x200ff0f, which corresponds to
>> DM_MEDIATYPE  | DM_DUPLEX   | DM_YRESOLUTION   | DM_TTOPTION | 
>> DM_COLLATE  | DM_COPIES  | DM_DEFAULTSOURCE  | DM_PRINTQUALITY |
>> DM_COLOR  | DM_PAPERWIDTH  | DM_PAPERLENGTH | DM_PAPERSIZE  | 
>> DM_ORIENTATION
>>
>> But, for, Brother printer, pDevMode->dmFields is initialized to 
>> 0x1930f which corresponds to
>> DM_FORMNAME  | DM_DUPLEX   | DM_COLLATE | DM_COPIES  | 
>> DM_DEFAULTSOURCE  | DM_PAPERWIDTH  | DM_PAPERLENGTH | DM_PAPERSIZE | 
>> DM_ORIENTATION
>> so there is no DM_YRESOLUTION and DM_PRINTQUALITY in dmFields,
>> so even though YRESOLUTION and PRINTQUALITY is populated by 
>> :DocumentProperties API, the corresponding indices are not set,
>> resulting in having "GETDEFAULT_ERROR" [-50] in the array for those 
>> indices.
>>
>
> Very odd. It sounds like a driver bug and I'm surprised that the 
> Microsoft HWQL tests don't catch it.
> Was the driver directly from Brother ? 
Yes, I took the driver from 
http://support.brother.com/g/b/downloadlist.aspx?c=us_ot&lang=en&prod=hl2240d_all&os=93

> Perhaps someone considered those fields so mandatory
> that you don't even need to check that they are set ?
>
> This case reminds me of the fishy settings for a different bug 
> reviewed here : 
> http://mail.openjdk.java.net/pipermail/2d-dev/2016-June/007011.html so 
> ... I suppose this might be OK but still ..
>
>> I have modified my fix to populate the yresolution and printquality 
>> indices even though dmFields are not set by :DocumeProperties, 
>> provided those fields are not 0.
>
>
> Actually the code says you are doing that only if as they are GREATER 
> than zero .. not just different than zero.
>
> So here
> 919 if (pDevMode->dmFields & DM_PRINTQUALITY || 
> pDevMode->dmPrintQuality > 0) { If quality is used by a driver but it 
> forget to set the mask bit then you will still ignore it. Perhaps you 
> want != 0 ?
Yes, right. I actually overlooked the spec which says

*dmPrintQuality*

    Specifies the printer resolution. There are four predefined
    device-independent values:

    *DMRES_HIGH*
    *DMRES_MEDIUM*
    *DMRES_LOW*
    *DMRES_DRAFT*

    If a positive value is specified, it specifies the number of dots
    per inch (DPI) and is therefore device dependent

and as per wingdi.h, these values are -ve. I have updated the fix to use 
!=0.

>>
>> I have retained defaulting to low 300 dpi resolution as there might 
>> be a case when AwtPrintControl::getDevmode() fails resulting in 
>> returning default values which is -50.
>
> Are you referring to the code in Win32PrintService.java ?
> I'm not sure about doing that. The way I read your code is now if a 
> driver specifies dmQuality as negative
> and leaves yRes at zero (meaning ignore it) .. you now no longer 
> ignore it and return a new PrinterResolution
> for a made up (300,300) resolution.
>
Ok, right. I looked at the spec and saw what you are saying

*dmYResolution*

    Specifies the y-resolution, in dots per inch, of the printer. If the
    printer initializes this member, the *dmPrintQuality* member
    specifies the x-resolution

which means, if dmPrintQuality is initialized +ve for x resolution, the 
y-resolution is specified by dmYResolution.
Or in reverse way, if dmPrintQuality is -ve, then there might not be any 
need of specifying dmYResolution.

I have updated the webrev to cater to both changes

http://cr.openjdk.java.net/~psadhukhan/8186987/webrev.02/

Regards
Prasanta


>> Also, in linux, we do the similar 
>> http://hg.openjdk.java.net/jdk10/client/jdk/file/70359afda5d0/src/java.desktop/unix/classes/sun/print/IPPPrintService.java#l1565
>>
> What we do in Linux (for Postscript) is different as postscript allows 
> you to specify the DPI for your content
> and the interpreter must handle that.
>
> -phil.
>
>> http://cr.openjdk.java.net/~psadhukhan/8186987/webrev.01/
>>
>> Regards
>> Prasanta
>> [1] 
>> [https://msdn.microsoft.com/en-us/library/windows/desktop/dd183576(v=vs.85).aspx] 
>>
>> On 9/4/2017 8:28 AM, Prahalad Kumar Narayanan wrote
>>> Hello Prasanta
>>>
>>> Thanks for the explanation.
>>> Being new to the Printing subsystem, it helped get the context of 
>>> the problem.
>>>
>>> As I understand, the problem is due to getDefaultPrinterSetings() 
>>> returning negative values for defYRes and quality.
>>> And the fix evades such negative values with a hardcoded low 300 DPI 
>>> resolution.
>>>
>>> I 'm suspecting the bug to be in the code that returns values for 
>>> default printer settings
>>> . Since these values are device specific, I believe, the code might 
>>> use few platform APIs to query the resolutions on that printer 
>>> device & return the same.
>>> . It's here that default resolutions are not retrieved properly.
>>> . So my view is to trace this location & fix the population of 
>>> default printer settings than a hardcoded DPI resolution.
>>>      . When a problem has surfaced on one printer, there is 
>>> possibility for the same to occur on many devices as well.
>>>      . Besides printers may not be supporting low 300 DPI resolution 
>>> going forward.
>>>
>>> I may be wrong in my understanding. You could wait for other's 
>>> review & follow up.
>>>
>>> Thank you
>>> Have a good day
>>>
>>> Prahalad N.
>>>
>>> -----Original Message-----
>>> From: Prasanta Sadhukhan
>>> Sent: Thursday, August 31, 2017 3:39 PM
>>> To: Philip Race; 2d-dev
>>> Subject: [OpenJDK 2D-Dev] [10] RFR JDK-8186987:NullPointerException 
>>> in RasterPrinterJob without PrinterResolution
>>>
>>> Hi All,
>>>
>>> Please review a fix for an issue where it a NPE is seen when an 
>>> attempt is made to print to Brother HL-2240D series printer.
>>>
>>> It seems when RasterPrinterJob#setAttributes() is called with no 
>>> PrinterResolution attribute set, it first checks if 
>>> PrinterResolution category is supported.
>>> If it is supported, then it sees if the supplied resolution value is 
>>> supported. Now, since no PrinterResolution attribute is set, so
>>> isSupportedValue() returns false [as "printer resolution attribute"
>>> object is null]
>>> It then goes to get the default resolution attribute via
>>> getDefaultAttributeValue() which calls getDefaultPrinterSettings() 
>>> and use yRes,Quality from this printer to construct a 
>>> "PrinterResolution"
>>> object.
>>>
>>> Now, it seems in Brother HL-2240D series printer, it supports 3 
>>> resolution [300, 600, HQ 1200] but for all these 3 resolutions,
>>> getDefaultPrinterSettings() returns -50 for yRes and Quality.
>>> So, as per this code
>>> http://hg.openjdk.java.net/jdk10/client/jdk/file/dbb5b171a16b/src/java.desktop/windows/classes/sun/print/Win32PrintService.java#l1189 
>>>
>>> res < 0 and no PrinterResolution object is instantiated so when RPJ 
>>> accesses 
>>> printerResAttr.getCrossFeedResolution(ResolutionSyntax.DPI); it 
>>> causes NPE.
>>>
>>> Proposed fix is to create a default lowly 300 dpi PrinterResolution 
>>> if, for some reason, yRes and Quality from printer comes out -ve.
>>> http://cr.openjdk.java.net/~psadhukhan/8186987/webrev.00/
>>>
>>> Regards
>>> Prasanta
>>
>

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


More information about the 2d-dev mailing list