[OpenJDK 2D-Dev] <AWT Dev> [9] Review request for 8029339 Custom MultiResolution image support on HiDPI displays

Alexander Scherbatiy alexandr.scherbatiy at oracle.com
Tue Jul 29 14:44:43 UTC 2014


  Just friendly remainder.

  Thanks,
  Alexandr.


On 7/8/2014 7:02 PM, Alexander Scherbatiy wrote:
>
>
>   Hi Phil,
>
>   Could you review the fix?
>
>   Thanks,
>   Alexandr.
>
>
> On 6/11/2014 7:18 PM, Alexander Scherbatiy wrote:
>>
>>  Hi Phil ,
>>
>>  I just prepared a simple FAQ about the Custom MultiResolution image 
>> API. Hope it will be helpful.
>>
>> 1. Scale naming convention for high-resolution images.
>>
>>  Different OSes use different "scale" naming convention for 
>> high-resolution images:
>>  Mac OS X: image.ext, image at 2x.ext
>>  Windows: image.scale-100.ext, image.scale-140.ext, image.scale-180.ext
>>
>>  Q: Does "scale" naming convention supported in JDK?
>>  A: Mac OS X "scale" naming convention are supported in JDK 8u20 (see 
>> JDK-8011059)
>>       It is planned to support the Windows "scale" naming convention 
>> as well.
>>
>>  Q. How does it work in JDK?
>>  A. Bundle image.ext and image at 2x.ext images with your app on Mac OS 
>> X and call Toolkit.getImage(...) method:
>>         Image image = Toolkit.getDefaultToolkit().getImage("image.ext");
>>         Graphics2D g2d = // get graphics
>>         g2d.drawImage(image, 0, 0, null)
>>   SunGraphics2D automatically queries and draws the provided 
>> high-resolution image.
>>
>>   Q: There are different "scale" naming conventions on Mac OS X and 
>> Windows.
>>        May be it is better to have unified "scale" naming conventions 
>> for all OSes in Java like image[java-scale-Nx].ext?
>>   A: It seems reasonable and can be filled as a new JDK enhancement.
>>
>>   Q: Does using "scale" naming conventions solves all problems.
>>   A: There are tasks like image processing/programmatically generated 
>> images/loading images from non-standard sources
>>        that can't be solved with predefined set of images.
>>   Q: Are there any tools that support these tasks?
>>   A: Cocoa API contains NSImage that allows to work with image 
>> representations: addRepresentation/removeRepresentation/representations
>>       JDK uses these methods to get/set multi-resolution images for 
>> the Native system (see sun.lwawt.macosx.CImage class).
>>
>> 2. Graphics2D
>> Q: How SunGraphics2D deals with multi-resolution images?
>> A: SunGraphics2D queries a resolution variant using DPI scale factors 
>> and transformed base image sizes
>>        //   logicalDPIX, logicalDPIY - DPI scale factors
>>        //   destImageWidth, destImageHeight - transformed base image 
>> sizes including DPI scale factors
>>         multiResolutionImage.getResolutionVariant(logicalDPIX, 
>> logicalDPIY, destImageWidth, destImageHeight);
>>
>> Q: Which algorithm multi-resolution image is used in 
>> getResolutionVariant(...) method?
>> A:  ToolkitImage returned by toolkit.loadImage() method should behave 
>> like the native system.
>>      It means that it should use transformed image sizes on Mac OS X 
>> and only DPI scale factors on Windows.
>>      it looks like:
>>         -----------------
>>        //   logicalDPIX, logicalDPIY - DPI scale factors
>>        //   destImageWidth, destImageHeight - transformed base image 
>> sizes including DPI scale factors
>>         public Image getResolutionVariant(float logicalDPIX, float 
>> logicalDPIY,
>>                 float destImageWidth, float destImageHeight) {
>>                   if (Mac OS X) {
>>                        return resolution variant best fitted to the 
>> destImageWidth and destImageHeight
>>                   } else if (Windows){
>>                        return resolution variant best fitted to the 
>> logicalDPIX and logicalDPIY scale factors
>>                   }
>>         }
>>         -----------------
>>
>>  3. Custom multi-resolution image.
>>  Q: The custom multi-resolution image should be able to return an 
>> image according to the requested
>>       transformed image size and DPI scale factors. Is it enough?
>>   A: There are task like setting custom cursor that require to get 
>> all resolution variants.
>>       So the custom multi-resolution image should also contain the 
>> getResolutionVariants():
>>
>>  Q: Should the custom multi-resolution image be class or interface?
>>  A: There is ToolkitImage that should also have resolution variants.
>>    It is not possible to extend it from MultiResolutionImage class.
>>    The current proposal introduces the MultiResolutionImage as an 
>> interface.
>>
>>  Q: MultiResolutionImage interface sounds strange for me.
>>  A: The better name can be suggested.
>>
>>   Q: What does the Custom MultiResolution image API suggest?
>>   A:  The current proposal provides MultiResolutionImage interface 
>> with the following methods:
>>     ---------------------------
>>     Image getResolutionVariant(float logicalDPIX, float logicalDPIY,
>>             float destImageWidth, float destImageHeight);
>>
>>     List<Image> getResolutionVariants();
>>     ---------------------------
>>   and AbstractMultiResolutionImage class. See samples below.
>>
>>
>>  4. Memory cost
>>  Q: Can the the implementation be "lazy"?
>>  A: SunGraphics2D does not require full list of resolution variants. 
>> It queries only the image with necessary resolution.
>>      It means that resolution variants can be loaded by demand.
>>    Setting a custom cursor requires all resolution variants.
>>
>>  5. Rendering hints.
>>  Q: Why rendering hints are added.
>>  A: Provided rendering hints affects only multi-resolution images and 
>> allows to disable
>>      resolution variants usage in app. It can be useful for 
>> performance reasons.
>>
>>  6. Samples.
>>  Q: It is interesting to look at samples.
>>  A: Below are 3 samples:
>>      1. Draw an image with "Hello World!" text
>>      2. Set a lightened custom cursor
>>      3. Draw a multi-resolution image created from the program
>>
>>    Sample 1. Draw a image with "Hello World!" text. The text is drawn 
>> both on the base image and on high-resolution image.
>>        disk: duke.png, duke at 2x.png
>>    -------------------------------
>>     public static void main(String[] args) {
>>
>>         Image image = 
>> Toolkit.getDefaultToolkit().getImage("duke.png"); // duke.png and 
>> duke at 2x.png images are loaded by MR-ToolkitImage
>>
>>         Image imagewithText = image instanceof MultiResolutionImage
>>                 ? new TextMultiresolutionImage(image) : drawText(image);
>>
>>         Graphics2D g2d = // get graphics 2D
>>         g2d.drawImage(imagewithText, x, y, null);
>>     }
>>
>>     static Image drawText(Image image) {
>>         // return an image with "Hello World!" text
>>     }
>>
>>     static class TextMultiresolutionImage extends 
>> AbstractMultiResolutionImage {
>>
>>         private final Image baseImage;
>>
>>         public TextMultiresolutionImage(Image baseImage) {
>>             this.baseImage = baseImage;
>>         }
>>
>>         @Override
>>         public Image getResolutionVariant(float logicalDPIX, float 
>> logicalDPIY,
>>                 float destImageWidth, float destImageHeight) {
>>             Image rvImage = ((MultiResolutionImage) baseImage).
>>                     getResolutionVariant(logicalDPIX, logicalDPIY,
>>                             destImageWidth, destImageHeight);
>>             return drawText(rvImage);
>>         }
>>
>>         @Override
>>         public List<Image> getResolutionVariants() {
>>                // this method is not used by SunGraphics2D to draw 
>> the image.
>>               // we just skip it in this example
>>         }
>>
>>         @Override
>>         protected Image getBaseImage() {
>>             return drawText(baseImage);
>>         }
>>     }
>>    -------------------------------
>>
>>   Sample 2. Using filters to create a lightened  custom cursor.
>>   The filter is applied to both the base and high-resolution image.
>>    -------------------------------
>>     public static void main(String[] args) {
>>
>>         Image image = 
>> Toolkit.getDefaultToolkit().getImage("cursor.png"); // cursor.png and 
>> cursor at 2x.png files are provided
>>         Image lightenedImage = image instanceof MultiResolutionImage
>>                 ? new LigtenedMultiresolutionImage(image) : 
>> applyFilter(image);
>>
>>         Cursor lightenedCursor = Toolkit.getDefaultToolkit().
>>                 createCustomCursor(lightenedImage, new Point(0, 0), 
>> "Lightened Cursor");
>>         JFrame frame = new JFrame("Frame with lightened cursor");
>>         frame.setCursor(lightenedCursor);
>>     }
>>
>>     static Image applyFilter(Image image) {
>>         GrayFilter filter = new GrayFilter(true, 50);
>>         final ImageProducer prod = new 
>> FilteredImageSource(image.getSource(), filter);
>>         return Toolkit.getDefaultToolkit().createImage(prod);
>>     }
>>
>>     static class LigtenedMultiresolutionImage extends 
>> AbstractMultiResolutionImage {
>>
>>         private final Image baseImage;
>>
>>         public LigtenedMultiresolutionImage(Image baseImage) {
>>             this.baseImage = baseImage;
>>         }
>>
>>         @Override
>>         public Image getResolutionVariant(float logicalDPIX, float 
>> logicalDPIY,
>>                 float destImageWidth, float destImageHeight) {
>>               // this method is not necessary for the custom cursor 
>> creation
>>              // we just skip it
>>         }
>>
>>         // all resolution variants are created to pass them to 
>> NSImage for the custom cursor on Mac OS X.
>>         @Override
>>         public List<Image> getResolutionVariants() {
>>             List<Image> resolutionVariants = new LinkedList<>();
>>             for (Image rvImage : ((MultiResolutionImage) baseImage).
>>                     getResolutionVariants()) {
>>                 resolutionVariants.add(applyFilter(rvImage));
>>             }
>>             return resolutionVariants;
>>         }
>>
>>         @Override
>>         protected Image getBaseImage() {
>>             return applyFilter(baseImage);
>>         }
>>     }
>>    -------------------------------
>>
>>    Sample 3. Draw a multi-resolution image created from the program:
>>    -------------------------------
>>     public static void main(String[] args) {
>>
>>         Image image = generateImage(1);
>>         Image image2x = generateImage(2);
>>         Image mrImage = new CustomMultiresolutionImage(image, image2x);
>>
>>         Graphics2D g2d = // get graphics2D
>>         g2d.drawImage(mrImage, 0, 0, null);
>>     }
>>
>>     static Image generateImage(float scaleFactor) {
>>         // generate image according to the scale factor
>>     }
>>
>>     static class CustomMultiresolutionImage extends 
>> AbstractMultiResolutionImage {
>>
>>         private final Image image;
>>         private final Image highResolutionImage;
>>
>>         public CustomMultiresolutionImage(Image baseImage, Image 
>> highResolutionImage) {
>>             this.image = baseImage;
>>             this.highResolutionImage = highResolutionImage;
>>         }
>>
>>         @Override
>>         public Image getResolutionVariant(float logicalDPIX, float 
>> logicalDPIY,
>>                 float destImageWidth, float destImageHeight) {
>>             // destImageWidth and destImageHeight includes both 
>> transforms
>>             // DPI scale factors from Graphics
>>             if (destImageWidth <= image.getWidth(null)
>>                     && destImageHeight <= image.getHeight(null)) {
>>                 return image;
>>             }
>>             return highResolutionImage;
>>         }
>>
>>         @Override
>>         public List<Image> getResolutionVariants() {
>>             return Arrays.<Image>asList(image, highResolutionImage);
>>         }
>>
>>         @Override
>>         protected Image getBaseImage() {
>>             return image;
>>         }
>>     }
>> -------------------------------
>> Thanks,
>> Alexandr.
>>
>>
>> On 6/10/2014 6:37 PM, Alexander Scherbatiy wrote:
>>> On 6/10/2014 1:07 AM, Phil Race wrote:
>>>> Why the split ?
>>>> If you look only at the first part. If you can do that then why is 
>>>> the 2nd part needed ?
>>>    The second part introduces algorithms that can be used to 
>>> retrieve a resolution variant
>>>    from a set of images. It can be DPI based, transform based, OS 
>>> based and so on.
>>>    The first part can be implemented without the second part.
>>>
>>>> The name "MultiResolutionImage" implies to me that this is a 
>>>> sub-class of Image.
>>>> But its not, its a way to get images. AbstractMultiResolutionImage, 
>>>> however is
>>>> a subclass and it implements the former.
>>>
>>>    Could you suggest the better name? It really needs to have an 
>>> interface if existed image implementation
>>>    is supposed to have resolution variants. The example which is 
>>> used in JDK is ToolkitImage.
>>>    Toolkit.getImage(filename) method returns ToolkitImage which is 
>>> loaded by demand.
>>>    LWCToolkit should return an image with resolution variants on Mac 
>>> OS X if both image and  image at 2x
>>>    are provided. What we need here is the  ToolkitImage that 
>>> contains resolution  variants.
>>>    It can be done if the MultiResolutionImage is an interface and it 
>>> is not possible to do if MultiResolutionImage is a class.
>>>    Here is the MultiResolutionToolkitImage implementation:
>>> http://hg.openjdk.java.net/jdk9/client/jdk/file/b7ef5e2d252c/src/share/classes/sun/awt/image/MultiResolutionToolkitImage.java 
>>>
>>>
>>>> I am supposing (since you don't explain) that you want an Image 
>>>> sub-class here
>>>> so that the app can specify it where ever an Image is currently 
>>>> accepted by API
>>>> and the API that is "aware" can accept it.
>>>     If an image implements the MultiResolutionImage interface, 
>>> SunGraphics2D can use it
>>>     to draw an image with necessary resolution on HiDPI display.
>>>
>>>> I worry about the memory cost of all of this. Can the the 
>>>> implementation be "lazy"?
>>>     Yes. See the MultiResolutionCachedImage implementation:
>>> http://hg.openjdk.java.net/jdk9/client/jdk/file/b7ef5e2d252c/src/share/classes/sun/awt/image/MultiResolutionCachedImage.java 
>>>
>>>> ie even if I call getResolutionVariants() do those images all have 
>>>> to be fully initialised before
>>>> they are used? It looks like the app probably has to do so ..
>>>     If it needs to pass resolution variants to the native system 
>>> like setting a custom cursor on Mac OS X
>>>     it really needs to initialize all resolution variants.
>>>
>>>      If it needs to create one multi-resolution image based on 
>>> another multi-resolution image like
>>>      generating a lightening image using a filter, it possible to do 
>>> this lazy.
>>>      See the map(Function<Image, Image> mapper) method in the 
>>> MultiResolutionCachedImage.
>>>
>>>    SunGraphics2D class uses only getResolutionVariant( ...) method 
>>> to retrieve necessary resolution variant.
>>>    It does not call getResolutionVariants() methods so all 
>>> resolution variants are not created during image drawing.
>>>
>>>>
>>>> Also it precludes being able to return "on demand" an image that is 
>>>> rendered to
>>>> be exactly the size requested. That could be created, drawn using 
>>>> graphics primitives
>>>> and created precisely and only if needed.
>>>>
>>>> Instead we have an API that requires you to apparentlty eagerly 
>>>> create even the
>>>> highest res image when you are on a device that has no need for it.
>>>>
>>>> Who will actually call getResolutionVariants() ? 
>>>     Both.
>>>> Is it us (the implementation) because we
>>>     We use it to create an NSImage from a custom cursor. See 
>>> Toolkit.createCustomCursor()
>>>    and CImage.createFromImage(final Image image) methods.
>>>
>>>    Developers can use it to show all resolution variants in some 
>>> image tool.
>>>
>>>> don't trust the app to make the right selection based on the 
>>>> parameterised call
>>>> getResolutionVariant() ?
>>>    As it shown, the getResolutionVariant(...) and 
>>> getResolutionVariants() methods are used
>>>    for different purposes.
>>>    getResolutionVariant(...) method is used by SunGraphics2D class 
>>> to pickup an image
>>>    with necessary resolution variant.
>>>    getResolutionVariants() method is used when an application needs 
>>> to use all resolution variants.
>>>
>>>>
>>>> Which approach do we use to pick the image ? If its the former, the 
>>>> app controls it,
>>>     It is the former.
>>>     We also use it MR-ToolkitImage to get a resolution variant 
>>> according to the current system (for example, transforms
>>>      are included to get resolution variant size on Mac OS X).
>>>
>>>> if its the latter its us. But which ?
>>>>
>>>> I am still stuck on the parameters to getResolutionVariant
>>>>
>>>>  * @param baseImageWidth the width of the base image.
>>>>
>>>>
>>>> Isn't the base image always the smallest ? 
>>>     No for general case. May be it would be possible to print a 
>>> multi-resolution image
>>>     on a printer that can have low DPI.
>>>
>>>> Why are we, the caller, supposed
>>>> to say what that size to the class that has that image.
>>>
>>>    This question has already had long discussion. The answer is that 
>>> we do it because it is free for us.
>>>    SunGraphics2D already gets the base image size because it uses it 
>>> for resolution image size calculation.
>>>    If you have objections against this, let's remove the base image 
>>> size parameters.
>>>    Developer always can obtain this information calling 
>>> getWidth()/Height() methods.
>>>
>>>> So I'd really like to see the example of that method in 
>>>> CustomMultiResolutionImage
>>>> filled out so we can see what is imagined here ..
>>>
>>>    Below are two samples.
>>>    The first one loads a multi-resolution image from disk, and 
>>> writes text "Hello World!" on it. Only getResolutionVariant(...) 
>>> method is used
>>>    by system in SunGraphics2D. The getResolutionVariants() method is 
>>> not used.
>>>
>>>    The second one creates a lightened custom cursor. The 
>>> getResolutionVariants() method is called by system to create NSImage 
>>> with necessary image representations.
>>>
>>>    Note that Toolkit.getImage(filename) method is already able to 
>>> load both image and image at 2x  images on Mac OS X.
>>>
>>>    Sample 1. Draw an image with "Hello World!" text:
>>>        disk: duke.png, duke at 2x.png
>>>    -------------------------------
>>>     public static void main(String[] args) {
>>>
>>>         Image image = 
>>> Toolkit.getDefaultToolkit().getImage("duke.png"); // duke.png and 
>>> duke at 2x.png images are loaded by MR-ToolkitImage
>>>
>>>         Image imagewithText = image instanceof MultiResolutionImage
>>>                 ? new TextMultiresolutionImage(image) : 
>>> drawText(image);
>>>
>>>         Graphics2D g2d = // get graphics 2D
>>>         g2d.drawImage(imagewithText, x, y, null);
>>>     }
>>>
>>>     static Image drawText(Image image) {
>>>         // return an image with "Hello World!" text
>>>     }
>>>
>>>     static class TextMultiresolutionImage extends 
>>> AbstractMultiResolutionImage {
>>>
>>>         private final Image baseImage;
>>>
>>>         public TextMultiresolutionImage(Image baseImage) {
>>>             this.baseImage = baseImage;
>>>         }
>>>
>>>         @Override
>>>         public Image getResolutionVariant(float destImageWidth, 
>>> float destImageHeight) {
>>>             Image rvImage = ((MultiResolutionImage) baseImage).
>>>                     getResolutionVariant(destImageWidth, 
>>> destImageHeight);
>>>             return drawText(rvImage);
>>>         }
>>>
>>>         // this method is not used by SunGraphics2D to draw the image
>>>         @Override
>>>         public List<Image> getResolutionVariants() {
>>>             List<Image> resolutionvariants = new LinkedList<>();
>>>             for (Image image : ((MultiResolutionImage) baseImage).
>>>                     getResolutionVariants()) {
>>>                 resolutionvariants.add(drawText(image));
>>>             }
>>>             return resolutionvariants;
>>>         }
>>>
>>>         @Override
>>>         protected Image getBaseImage() {
>>>             return drawText(baseImage);
>>>         }
>>>     }
>>>    -------------------------------
>>>
>>>   Sample 2. Using filters to create a lightened  custom cursor.
>>>    -------------------------------
>>>     public static void main(String[] args) {
>>>
>>>         Image image = 
>>> Toolkit.getDefaultToolkit().getImage("cursor.png"); // cursor.png 
>>> and cursor at 2x.png files are provided
>>>         Image lightenedImage = image instanceof MultiResolutionImage
>>>                 ? new LigtenedMultiresolutionImage(image) : 
>>> applyFilter(image);
>>>
>>>         Cursor lightenedCursor = Toolkit.getDefaultToolkit().
>>>                 createCustomCursor(lightenedImage, new Point(0, 0), 
>>> "Lightened Cursor");
>>>         JFrame frame = new JFrame("Frame with lightened cursor");
>>>         frame.setCursor(lightenedCursor);
>>>     }
>>>
>>>     static Image applyFilter(Image image) {
>>>         // apply a filter to create ligtened image
>>>     }
>>>
>>>     static class LigtenedMultiresolutionImage extends 
>>> AbstractMultiResolutionImage {
>>>
>>>         private final Image baseImage;
>>>
>>>         public LigtenedMultiresolutionImage(Image baseImage) {
>>>             this.baseImage = baseImage;
>>>         }
>>>
>>>         @Override
>>>         public Image getResolutionVariant(float destImageWidth, 
>>> float destImageHeight) {
>>>             Image rvImage = ((MultiResolutionImage) baseImage).
>>>                     getResolutionVariant(destImageWidth, 
>>> destImageHeight);
>>>             return applyFilter(rvImage);
>>>         }
>>>
>>>         // all resolution variants are created to pass them to NSImage
>>>         @Override
>>>         public List<Image> getResolutionVariants() {
>>>             List<Image> resolutionvariants = new LinkedList<>();
>>>             for (Image image : ((MultiResolutionImage) baseImage).
>>>                     getResolutionVariants()) {
>>>                 resolutionvariants.add(applyFilter(image));
>>>             }
>>>             return resolutionvariants;
>>>         }
>>>
>>>         @Override
>>>         protected Image getBaseImage() {
>>>             return applyFilter(baseImage);
>>>         }
>>>     }
>>>    -------------------------------
>>>>
>>>> Based solely on the usage I see here, its not clear why 
>>>> MultiResolutionImage needs
>>>> to separately exist. what would implement MultiResolutionImage 
>>>> except for
>>>> a class that extends AbstractMultiResolutionImage  ? Where would 
>>>> you use
>>>> a straight implementation of MultiResolutionImage ?
>>>     See sun.awt.image.MultiResolutionToolkitImage in JDK 9. Both 
>>> ToolkitImage and MultiResolutionImage should be used in this case.
>>>
>>>>
>>>> Actually I am not sure you answered Jim's question as to who is 
>>>> requesting these APIs.
>>>> "The AWT team" doesn't need them as they won't be writing the apps.
>>>
>>>   There was a long thread about the image with sub-pixel resolution 
>>> drawing  on Mac OS X:
>>> http://mail.openjdk.java.net/pipermail/macosx-port-dev/2013-April/005559.html 
>>>
>>>
>>>  It was pointed out that Icon images that can be programmatically 
>>> generated also need to have HiDPI support:
>>> http://mail.openjdk.java.net/pipermail/macosx-port-dev/2013-April/005566.html 
>>>
>>> http://mail.openjdk.java.net/pipermail/macosx-port-dev/2013-April/005569.html 
>>>
>>>
>>>  All requests about Mac OS X HiDPI support were included to the 
>>> umbrella issue:
>>>    7124410 [macosx] Lion HiDPI support
>>> https://bugs.openjdk.java.net/browse/JDK-7124410
>>>
>>>>
>>>> If the 99% use case will be to provide a way for apps to provide 
>>>> images at custom sizes
>>>> then we seem to be making them write new code. SFAIK FX found a way 
>>>> to do something
>>>> similar to what OS X and Windows do which is to load based on file
>>>> name convention. 
>>>       JDK 8 have already loaded images with @2x name convention on 
>>> Mac OS X.
>>>       See the fix for the issue JDK-8011059 [macosx] Support 
>>> automatic @2x images loading on Mac OS X
>>>        https://bugs.openjdk.java.net/browse/JDK-8011059
>>>> If we can do that, we load just the one we need. Is the point
>>>> of use so far removed from the loading logic that we can't do this ?
>>>
>>>     Mac OS X has both ways to create images: using @2x name 
>>> convention for files
>>>     and NSImage with methods 
>>> addRepresentation/removeRepresentation/representations.
>>>
>>>     The current API is proposed to dial with images that can have 
>>> source that is different  from files.
>>>     It is also used to process already loaded images.
>>>     See the provided two samples with lightened custom cursor and 
>>> text on image.
>>>     Is it possible to write the same samples on JavaFX?
>>>
>>>> And none of this seems to help anyone who calls new 
>>>> BufferedImage(w, h, type) ..
>>>
>>>    Yes. It needs to create a BufferedImage for each screen 
>>> resolution and put them to a multi-resolution image.
>>>
>>>>
>>>> BTW I am not sold on the need for the RenderingHint.  Where did the 
>>>> idea come from ?
>>>> It would affect all rendering using that graphics instance, not 
>>>> just a specific image and
>>>> if someone doesn't want a MultiRes image used, then maybe they just 
>>>> don't provide one ..
>>>
>>>     KEY_RESOLUTION_VARIANT is used to switch on/off resolution 
>>> variants usage.
>>>     VALUE_RESOLUTION_VARIANT_ON - SunGraphics2D queries resolution 
>>> variants from multi-resolution image on HiDPI displays.
>>>     VALUE_RESOLUTION_VARIANT_OFF - SunGraphics2D does not use 
>>> resolution variants. Only base image is used.
>>>
>>>> In any case, without a solid demonstrated need I would not add the 
>>>> API.
>>>>
>>>     See provided 2 samples.
>>>
>>>   Thanks,
>>>   Alexandr.
>>>>
>>>> -phil.
>>>>
>>>> On 6/4/2014 7:29 AM, Alexander Scherbatiy wrote:
>>>>>
>>>>>   Hi Phil,
>>>>>
>>>>>   Could you review the fix where only new MultiResolutionImage 
>>>>> interface and AbstractMultiResolutionImage class are added:
>>>>> http://cr.openjdk.java.net/~alexsch/8029339/webrev.05/
>>>>>
>>>>>   Thanks,
>>>>>   Alexandr.
>>>>>
>>>>>
>>>>> On 5/19/2014 2:46 PM, Alexander Scherbatiy wrote:
>>>>>>
>>>>>>   Hi Phil,
>>>>>>
>>>>>> On 5/16/2014 9:12 PM, Phil Race wrote:
>>>>>>> I think Jim was looking at this. I am not sure if you yet 
>>>>>>> answered all his questions/concerns.
>>>>>>>
>>>>>>> There's a lot of API here and it will take more time than I have 
>>>>>>> right now just to get
>>>>>>> my head around it so do not expect a quick answer.
>>>>>>>
>>>>>>> 1. Why is there no javadoc on the new API on Toolkit ?
>>>>>>   It was decided to split the original issue on two parts:
>>>>>>        - this fix adds only MultiResolutionImage interface and 
>>>>>> AbstractMultiResolutionImage class.
>>>>>>            Here is the webrev for it: 
>>>>>> http://cr.openjdk.java.net/~alexsch/8029339/webrev.05/
>>>>>>       - the Toolkit related API is moved to the separate issue
>>>>>>
>>>>>>   Could you review the current fix:
>>>>>> http://cr.openjdk.java.net/~alexsch/8029339/webrev.05/
>>>>>>
>>>>>>> 2. What kinds of classes are expected to implement 
>>>>>>> MultiResolutionImage
>>>>>>> Application ones or platform ones ?
>>>>>>     Both.
>>>>>>     - Application: A developer can provide a set of images with 
>>>>>> different resolutions to create a multi-resolution image. An 
>>>>>> image with best-fitting resolution
>>>>>>         will be drawn on HiDPI display.
>>>>>>     - Platform: we used it to support Aqua L&F on HiDPI displays.
>>>>>>
>>>>>>> 3. can you better explain all these parameters :
>>>>>>>
>>>>>>>   49      * @param logicalDPIX the logical horizontal DPI of the 
>>>>>>> desktop.
>>>>>>>   50      * @param logicalDPIY the logical vertical DPI of the 
>>>>>>> desktop.
>>>>>>>   51      * @param baseImageWidth the width of the base image.
>>>>>>>   52      * @param baseImageHeight the height of the base image.
>>>>>>>   53      * @param destImageWidth the width of the destination 
>>>>>>> image.
>>>>>>>   54      * @param destImageHeight the height of the destination 
>>>>>>> image.
>>>>>>>   55      * @return image resolution variant.
>>>>>>
>>>>>>     Could we postpone it to the CCC request?
>>>>>>
>>>>>>>
>>>>>>> 4.    public List<Image> getResolutionVariants();
>>>>>>>
>>>>>>> So this implies a fixed, known ahead of time set of images ?
>>>>>>> Why is it required to have this API ? How will anyone be able to
>>>>>>> tell which is which and use the list ?
>>>>>>
>>>>>>    Here are some usages from the JDK code:
>>>>>>     - AquaImagefactory.getAppIconCompositedOn(final Image 
>>>>>> background)
>>>>>>        The original multi-resolution image is used to create 
>>>>>> another multi-resolution image with the background
>>>>>>     - AquaUtils.generateLightenedImage(Image image, ImageFilter 
>>>>>> filter)
>>>>>>       The original multi-resolution image is used to create 
>>>>>> lightening multi-resolution image
>>>>>>     - CImage.createFromImage(final Image image)
>>>>>>         Resolution variants from a multi-resolution image are 
>>>>>> used to create an NSImage
>>>>>>     - CCustomCursor:  it is possible set a custom cursor which 
>>>>>> contains resolution variants to the native system
>>>>>>
>>>>>>     Usually the getResolutionVariants() method is used to create 
>>>>>> one multi-resolution image based on the another multi-resolution 
>>>>>> image.
>>>>>>
>>>>>>> 5. Why is the rendering hint needed ?
>>>>>>       Someone can manually switch off the multi-resolution image 
>>>>>> drawing from graphics so only the base image will be drawn.
>>>>>>       It is useful for the performance reason. There is a choice 
>>>>>> to draw the high-resolution image slowly or the low-resolution 
>>>>>> image faster.
>>>>>>
>>>>>>    Thanks,
>>>>>>    Alexandr.
>>>>>>> -phil.
>>>>>>>
>>>>>>>
>>>>>>> On 5/16/2014 9:16 AM, Alexander Scherbatiy wrote:
>>>>>>>>
>>>>>>>>   Hi Phil,
>>>>>>>>
>>>>>>>>   I need a reviewer from the 2d group for the fix. Could you 
>>>>>>>> take a look at the fix and review it?
>>>>>>>>
>>>>>>>>   Thanks,
>>>>>>>>   Alexandr.
>>>>>>>>
>>>>>>>>
>>>>>>>> On 5/12/2014 6:35 PM, Alexander Scherbatiy wrote:
>>>>>>>>>
>>>>>>>>>   There was a long thread about the image with sub-pixel 
>>>>>>>>> resolution drawing  on Mac OS X:
>>>>>>>>> http://mail.openjdk.java.net/pipermail/macosx-port-dev/2013-April/005559.html 
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>  It was pointed out that Icon images that can be 
>>>>>>>>> programmatically generated also need to have HiDPI support:
>>>>>>>>> http://mail.openjdk.java.net/pipermail/macosx-port-dev/2013-April/005566.html 
>>>>>>>>>
>>>>>>>>> http://mail.openjdk.java.net/pipermail/macosx-port-dev/2013-April/005569.html 
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>  All requests about Mac OS X HiDPI support were included to 
>>>>>>>>> the umbrella issue:
>>>>>>>>>    7124410 [macosx] Lion HiDPI support
>>>>>>>>> https://bugs.openjdk.java.net/browse/JDK-7124410
>>>>>>>>>
>>>>>>>>>  Thanks,
>>>>>>>>>  Alexandr.
>>>>>>>>>
>>>>>>>>> On 4/25/2014 6:45 PM, Alexander Scherbatiy wrote:
>>>>>>>>>> On 4/25/2014 2:17 AM, Jim Graham wrote:
>>>>>>>>>>> Hi Alexandr,
>>>>>>>>>>>
>>>>>>>>>>> I asked for who was requesting these facilities and you 
>>>>>>>>>>> responded with the solution you are planning to provide.
>>>>>>>>>>>
>>>>>>>>>>> I don't care what the solution looks like if we have nobody 
>>>>>>>>>>> asking for the feature - I am asking who is asking for these 
>>>>>>>>>>> capabilities?
>>>>>>>>>>
>>>>>>>>>>    This is the request from the AWT team for the HiDPI support.
>>>>>>>>>>
>>>>>>>>>>    Thanks,
>>>>>>>>>>    Alexandr.
>>>>>>>>>>>
>>>>>>>>>>>             ...jim
>>>>>>>>>>>
>>>>>>>>>>> On 4/4/14 4:53 AM, Alexander Scherbatiy wrote:
>>>>>>>>>>>> On 4/3/2014 2:23 AM, Jim Graham wrote:
>>>>>>>>>>>>> Hi Alexandr,
>>>>>>>>>>>>>
>>>>>>>>>>>>> The back and forth is getting confusing here, so I thought 
>>>>>>>>>>>>> I'd try to
>>>>>>>>>>>>> summarize and start fresh(ish):
>>>>>>>>>>>>>
>>>>>>>>>>>>> 1. We need to support @2x internally for MacOS 
>>>>>>>>>>>>> compatibility (done).
>>>>>>>>>>>>>
>>>>>>>>>>>>> 2. We will need to support _DPI images for Win-DPI 
>>>>>>>>>>>>> compatibility (TBD).
>>>>>>>>>>>>>
>>>>>>>>>>>>> 3. Customers may have their own collection of images to 
>>>>>>>>>>>>> bundle
>>>>>>>>>>>>> together into an MR image (working on that here). What is 
>>>>>>>>>>>>> the push
>>>>>>>>>>>>> for this?  Is this simply parity with Mac interfaces?
>>>>>>>>>>>>
>>>>>>>>>>>>          ----------
>>>>>>>>>>>>          Image[] resolutionVariants = // get sorted by 
>>>>>>>>>>>> sizes array of
>>>>>>>>>>>> resolution variants;
>>>>>>>>>>>>          Image mrImage =
>>>>>>>>>>>> Toolkit.getDefaultToolkit().createMRImage(baseImageIndex,
>>>>>>>>>>>> resolutionVariants);
>>>>>>>>>>>>          ----------
>>>>>>>>>>>>
>>>>>>>>>>>>       Here is the proposed patch:
>>>>>>>>>>>> http://cr.openjdk.java.net/~alexsch/8029339/webrev.04/
>>>>>>>>>>>>
>>>>>>>>>>>>> 4. Customers may want to synthetically generate images at 
>>>>>>>>>>>>> arbitrary
>>>>>>>>>>>>> resolutions (a variation that is impacting this solution). 
>>>>>>>>>>>>> What is
>>>>>>>>>>>>> the push for this?
>>>>>>>>>>>>          ----------
>>>>>>>>>>>>          Image mrImage =
>>>>>>>>>>>> Toolkit.getDefaultToolkit().createMRImage(baseImageWidth, 
>>>>>>>>>>>> baseImageHeight,
>>>>>>>>>>>>                  new float[][]{{100, 100}, {150, 150}, 
>>>>>>>>>>>> {200, 200}}, //
>>>>>>>>>>>> resolution variants sizes
>>>>>>>>>>>>                  (rvWidth, rvHeight) -> { /* generate a 
>>>>>>>>>>>> resolution
>>>>>>>>>>>> variant */  });
>>>>>>>>>>>>         ----------
>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> 5. I'm guessing that customers might want to override the 
>>>>>>>>>>>>> logic to
>>>>>>>>>>>>> choose from among multiple resolutions. That came from me 
>>>>>>>>>>>>> based on
>>>>>>>>>>>>> seeing Mac and Win using different selection logic and our 
>>>>>>>>>>>>> history of
>>>>>>>>>>>>> developers split between those wanting cross-platform 
>>>>>>>>>>>>> consistency and
>>>>>>>>>>>>> those wanting consistency with native apps on each 
>>>>>>>>>>>>> platform. Also,
>>>>>>>>>>>>> the needs of an animator may differ from the needs of a
>>>>>>>>>>>>> resolution-settable-document editor as to how dynamically 
>>>>>>>>>>>>> the images
>>>>>>>>>>>>> shift between resolution variants.
>>>>>>>>>>>>         ----------
>>>>>>>>>>>>          Image[] resolutionVariants = // get sorted by 
>>>>>>>>>>>> sizes array of
>>>>>>>>>>>> resolution variants;
>>>>>>>>>>>>          Image mrImage = ImageResolutionHelper.createMRImage(
>>>>>>>>>>>>                  (rvWidth, rvHeight, resolutionVariants) -> 
>>>>>>>>>>>> { /*use a
>>>>>>>>>>>> custom logic to choose a resolution variant from an array 
>>>>>>>>>>>> of images*/},
>>>>>>>>>>>>                  (logicalDPI, baseImageSize, destImageSize) ->
>>>>>>>>>>>> destImageSize, // calculate the custom aware resolution 
>>>>>>>>>>>> variant size
>>>>>>>>>>>>                  baseImageIndex, resolutionVariants);
>>>>>>>>>>>>         ----------
>>>>>>>>>>>>
>>>>>>>>>>>>     or just extend the CustomMultiResolutionImage which has 
>>>>>>>>>>>> Image as the
>>>>>>>>>>>> parent class:
>>>>>>>>>>>>
>>>>>>>>>>>> --------------------
>>>>>>>>>>>>   public class CustomMultiResolutionImage extends
>>>>>>>>>>>> AbstractMultiResolutionImage {
>>>>>>>>>>>>
>>>>>>>>>>>>      @Override
>>>>>>>>>>>>      public Image getResolutionVariant(float logicalDPIX, 
>>>>>>>>>>>> float
>>>>>>>>>>>> logicalDPIY,
>>>>>>>>>>>>              float baseImageWidth, float baseImageHeight,
>>>>>>>>>>>>              float destImageWidth, float destImageHeight) {
>>>>>>>>>>>>          // return a resolution variant based on the given 
>>>>>>>>>>>> logical DPI,
>>>>>>>>>>>>          // base image size, or destination image size
>>>>>>>>>>>>      }
>>>>>>>>>>>>
>>>>>>>>>>>>      @Override
>>>>>>>>>>>>      public List<Image> getResolutionVariants() {
>>>>>>>>>>>>          // return a list of resolution variants
>>>>>>>>>>>>      }
>>>>>>>>>>>>
>>>>>>>>>>>>      @Override
>>>>>>>>>>>>      protected Image getBaseImage() {
>>>>>>>>>>>>          // return the base image
>>>>>>>>>>>>      }
>>>>>>>>>>>> }
>>>>>>>>>>>> --------------------
>>>>>>>>>>>>>
>>>>>>>>>>>>> Is that a fair summary of all of the considerations so 
>>>>>>>>>>>>> far, or did I
>>>>>>>>>>>>> miss something?
>>>>>>>>>>>>     I think it should cover the main needs.
>>>>>>>>>>>>
>>>>>>>>>>>>      Thanks,
>>>>>>>>>>>>      Alexandr.
>>>>>>>>>>>>>
>>>>>>>>>>>>>             ...jim
>>>>>>>>>>>>>
>>>>>>>>>>>>> On 3/27/14 7:43 AM, Alexander Scherbatiy wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>   Below are some thoughts about TK.createMRImage(...) method
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> On 3/24/2014 4:52 PM, Alexander Scherbatiy wrote:
>>>>>>>>>>>>>>> Hello,
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>   Could you review the updated fix:
>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~alexsch/8029339/webrev.03/
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>   - baseImageWidth/Height arguments are added to the
>>>>>>>>>>>>>>> getResolutionVariant(...) method
>>>>>>>>>>>>>>>   - dest image sizes are reverted to included DPI scale
>>>>>>>>>>>>>>>   - AbstractMultiResolutionImage is added. It needs only 
>>>>>>>>>>>>>>> to implement
>>>>>>>>>>>>>>> only 3 methods from the AbstractMultiResolutionImage class
>>>>>>>>>>>>>>>     to create a custom multi-resolution image. For example:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> On 3/22/2014 3:57 AM, Jim Graham wrote:
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Your code example below can be expressed as an 
>>>>>>>>>>>>>>>> implementation of the
>>>>>>>>>>>>>>>> single-method, lambda-compatible interface that 
>>>>>>>>>>>>>>>> expresses just the
>>>>>>>>>>>>>>>> getRV() method. They could easily do:
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> final Image baseImage = ...;
>>>>>>>>>>>>>>>> TK.createMRImage(new RVInterface() {
>>>>>>>>>>>>>>>>     public Image getRV(...) {
>>>>>>>>>>>>>>>>         // calculate rvWidth and rvHeight
>>>>>>>>>>>>>>>>         // look up rvWidth/rvHeight in a database of 
>>>>>>>>>>>>>>>> images
>>>>>>>>>>>>>>>>         // possibly contruct a new image
>>>>>>>>>>>>>>>>         return rvImage;
>>>>>>>>>>>>>>>>     }
>>>>>>>>>>>>>>>> }, baseImage);
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>       The RVInterface mixes the logic that construct an 
>>>>>>>>>>>>>> image and
>>>>>>>>>>>>>> chooses the necessary resolution variant.
>>>>>>>>>>>>>>       It is ok if a developer always implements this 
>>>>>>>>>>>>>> interface. If it
>>>>>>>>>>>>>> needs to have DPI/Transform/Platform aware RVInterface 
>>>>>>>>>>>>>> the image
>>>>>>>>>>>>>> construction logic should be separated.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      Does  TK.createMRImage() method implies that 
>>>>>>>>>>>>>> Platform aware logic
>>>>>>>>>>>>>> should be used for a resolution-variant choosing?
>>>>>>>>>>>>>>      If so, may be general createMRImage() can be placed 
>>>>>>>>>>>>>> in the
>>>>>>>>>>>>>> ImageResolutionHelper.
>>>>>>>>>>>>>>>> The main issue I see is if you might want the newly 
>>>>>>>>>>>>>>>> constructed
>>>>>>>>>>>>>>>> variants to appear in the List returned from the 
>>>>>>>>>>>>>>>> getVariants()
>>>>>>>>>>>>>>>> method.  I'm not sure what value that would have beyond 
>>>>>>>>>>>>>>>> simply
>>>>>>>>>>>>>>>> returning the base media that the object uses from 
>>>>>>>>>>>>>>>> which to construct
>>>>>>>>>>>>>>>> its variants...?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>    It can be solved by using something like array of 
>>>>>>>>>>>>>> image sizes or
>>>>>>>>>>>>>> other seeds and a mapper that can create an image from 
>>>>>>>>>>>>>> the given seed.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>   It can look like:
>>>>>>>>>>>>>> -------------------------
>>>>>>>>>>>>>> public class ImageResolutionHelper {
>>>>>>>>>>>>>>      public interface RVChooser {
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>          public Image getRV(
>>>>>>>>>>>>>>                  float logicalDPIX, float logicalDPIY,
>>>>>>>>>>>>>>                  float baseImageWidth, float 
>>>>>>>>>>>>>> baseImageHeight,
>>>>>>>>>>>>>>                  float destImageWidth, float 
>>>>>>>>>>>>>> destImageHeight,
>>>>>>>>>>>>>>                  final Image... resolutionVariants);
>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      public static final RVChooser DPI_AWARE = ...;
>>>>>>>>>>>>>>      public static final RVChooser TRANSFORM_AWARE = ...;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      // resolutionVariants is an array of sorted by 
>>>>>>>>>>>>>> width/height images
>>>>>>>>>>>>>>      static Image createMRImage(final RVChooser rvChooser,
>>>>>>>>>>>>>>              final int baseImageIndex, final Image...
>>>>>>>>>>>>>> resolutionVariants) { ... }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      // sorted by width/height images should be generated 
>>>>>>>>>>>>>> from seeds
>>>>>>>>>>>>>>      static <Type> Image createMRImage(final RVChooser 
>>>>>>>>>>>>>> rvChooser,
>>>>>>>>>>>>>>              final Type baseImageSeed, final 
>>>>>>>>>>>>>> Function<Type, Image>
>>>>>>>>>>>>>> mapper, final Type... rvSeeds) {...}
>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> public abstract class Toolkit {
>>>>>>>>>>>>>>      public abstract Image createMRImage(int 
>>>>>>>>>>>>>> baseImageIndex, Image...
>>>>>>>>>>>>>> resolutionVariants); // Platform aware rv chooser is used
>>>>>>>>>>>>>>      public abstract RVChooser getPlatformRVChooser() ;
>>>>>>>>>>>>>> }
>>>>>>>>>>>>>> --------------------------
>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>      I think it is better to provide both the 
>>>>>>>>>>>>>>>>> MultiResolutionImage
>>>>>>>>>>>>>>>>> and
>>>>>>>>>>>>>>>>> its implementation based on the given resolution 
>>>>>>>>>>>>>>>>> variants array.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> It occurs to me that even if we don't go with a 
>>>>>>>>>>>>>>>> lambda-factory-based
>>>>>>>>>>>>>>>> approach like what I'm describing, it might make sense 
>>>>>>>>>>>>>>>> to provide a
>>>>>>>>>>>>>>>> baseMR implementation that they can subclass to keep 
>>>>>>>>>>>>>>>> them from trying
>>>>>>>>>>>>>>>> to subclass off of BufferedImage instead. I really 
>>>>>>>>>>>>>>>> would like to
>>>>>>>>>>>>>>>> avoid "custom MR images are subclasses of BufImg" if we 
>>>>>>>>>>>>>>>> can as I
>>>>>>>>>>>>>>>> think the mix of concepts is a little jarring...
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>             ...jim
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>     The implementation could look like:
>>>>>>>>>>>>>>>>> ---------------------------------
>>>>>>>>>>>>>>>>> public class CustomMultiResolutionImage extends Image 
>>>>>>>>>>>>>>>>> implements
>>>>>>>>>>>>>>>>> MultiResolutionImage {
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>      int baseImageIndex;
>>>>>>>>>>>>>>>>>      Image[] resolutionVariants;
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>      public CustomMultiResolutionImage(int 
>>>>>>>>>>>>>>>>> baseImageIndex,
>>>>>>>>>>>>>>>>>              Image... resolutionVariants) {
>>>>>>>>>>>>>>>>>          this.baseImageIndex = baseImageIndex;
>>>>>>>>>>>>>>>>>          this.resolutionVariants = resolutionVariants;
>>>>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>      @Override
>>>>>>>>>>>>>>>>>      public int getWidth(ImageObserver observer) {
>>>>>>>>>>>>>>>>>          return getBaseImage().getWidth(null);
>>>>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>      @Override
>>>>>>>>>>>>>>>>>      public int getHeight(ImageObserver observer) {
>>>>>>>>>>>>>>>>>          return getBaseImage().getHeight(null);
>>>>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>      @Override
>>>>>>>>>>>>>>>>>      public ImageProducer getSource() {
>>>>>>>>>>>>>>>>>          return getBaseImage().getSource();
>>>>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>      @Override
>>>>>>>>>>>>>>>>>      public Graphics getGraphics() {
>>>>>>>>>>>>>>>>>          return getBaseImage().getGraphics();
>>>>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>      @Override
>>>>>>>>>>>>>>>>>      public Object getProperty(String name, 
>>>>>>>>>>>>>>>>> ImageObserver observer) {
>>>>>>>>>>>>>>>>>          return getBaseImage().getProperty(name, 
>>>>>>>>>>>>>>>>> observer);
>>>>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>      @Override
>>>>>>>>>>>>>>>>>      public Image getResolutionVariant(float 
>>>>>>>>>>>>>>>>> logicalDPIX, float
>>>>>>>>>>>>>>>>> logicalDPIY,
>>>>>>>>>>>>>>>>>              float destinationImageWidth, float
>>>>>>>>>>>>>>>>> destinationImageHeight) {
>>>>>>>>>>>>>>>>>              // calculate resolution variant width/height
>>>>>>>>>>>>>>>>>          return getResolutionVariant(rvWidth, rvHeight);
>>>>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>      @Override
>>>>>>>>>>>>>>>>>      public List<Image> getResolutionVariants() {
>>>>>>>>>>>>>>>>>          return Arrays.asList(resolutionVariants);
>>>>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>      private Image getResolutionVariant(float rvWidth, 
>>>>>>>>>>>>>>>>> float
>>>>>>>>>>>>>>>>> rvHeight) {
>>>>>>>>>>>>>>>>>          // return a resolution variant based on the 
>>>>>>>>>>>>>>>>> given width and
>>>>>>>>>>>>>>>>> height
>>>>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>      private Image getBaseImage() {
>>>>>>>>>>>>>>>>>          return resolutionVariants[baseImageIndex];
>>>>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>> ---------------------------------
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>    Thanks,
>>>>>>>>>>>>>>>>>    Alexandr.
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Then we provide one of these from 
>>>>>>>>>>>>>>>>>> TK.get/createImage() when the
>>>>>>>>>>>>>>>>>> platform detects @2x, or Win8-style variants.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> For custom images we provide TK.createMRImage(lambda 
>>>>>>>>>>>>>>>>>> getRV, Image
>>>>>>>>>>>>>>>>>> variants...) and TK.createMRImage(Image variants...);
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Since the get<List> method is just bookkeeping, I 
>>>>>>>>>>>>>>>>>> don't see them
>>>>>>>>>>>>>>>>>> needing to override it, so the getRV() method is 
>>>>>>>>>>>>>>>>>> really the only
>>>>>>>>>>>>>>>>>> thing
>>>>>>>>>>>>>>>>>> they might want to override, and we can tie into the 
>>>>>>>>>>>>>>>>>> new Lambda
>>>>>>>>>>>>>>>>>> capabilities by making a single-method interface for 
>>>>>>>>>>>>>>>>>> it that they
>>>>>>>>>>>>>>>>>> supply in a factory method.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> I realize that the interface you created is more 
>>>>>>>>>>>>>>>>>> fundamentally
>>>>>>>>>>>>>>>>>> OO, but
>>>>>>>>>>>>>>>>>> the Image class has always been special in this 
>>>>>>>>>>>>>>>>>> regard in the AWT
>>>>>>>>>>>>>>>>>> ecosystem (in so far as we do not support someone 
>>>>>>>>>>>>>>>>>> implementing their
>>>>>>>>>>>>>>>>>> own Image subclass even though it is technically 
>>>>>>>>>>>>>>>>>> possible).
>>>>>>>>>>>>>>>>>> Because of
>>>>>>>>>>>>>>>>>> this special nature of Image, we end up with the 
>>>>>>>>>>>>>>>>>> situation that if
>>>>>>>>>>>>>>>>>> someone were given a need to create a subclass of 
>>>>>>>>>>>>>>>>>> Image, then they
>>>>>>>>>>>>>>>>>> would turn to BufImg as their superclass even though 
>>>>>>>>>>>>>>>>>> BufImg is
>>>>>>>>>>>>>>>>>> essentially an implementation-specific leaf node on 
>>>>>>>>>>>>>>>>>> the Image class
>>>>>>>>>>>>>>>>>> hierarchy.  This approach with a factory method to 
>>>>>>>>>>>>>>>>>> create an
>>>>>>>>>>>>>>>>>> internal
>>>>>>>>>>>>>>>>>> subclass of the new MRI class mirrors the existing 
>>>>>>>>>>>>>>>>>> cases of Image
>>>>>>>>>>>>>>>>>> objects that come from factories as well.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Thoughts?
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>             ...jim
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> On 3/20/14 7:52 AM, Alexander Scherbatiy wrote:
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>    Hello,
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>    Could you review the updated version of the fix:
>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~alexsch/8029339/webrev.01/
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>   - The "getResolutionVariant(int width, int 
>>>>>>>>>>>>>>>>>>> height)" method from
>>>>>>>>>>>>>>>>>>> MultiResolutionImage class is changed to
>>>>>>>>>>>>>>>>>>>     Image getResolutionVariant(float logicalDPIX, float
>>>>>>>>>>>>>>>>>>> logicalDPIY,
>>>>>>>>>>>>>>>>>>> float width, float height, AffineTransform transform);
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>   - sun.awt.image.ImageResolutionHelper class is 
>>>>>>>>>>>>>>>>>>> added. The
>>>>>>>>>>>>>>>>>>> sun.awt.image.MultiResolutionToolkitImage and
>>>>>>>>>>>>>>>>>>> sun.awt.image.MultiResolutionBufferedImage classes 
>>>>>>>>>>>>>>>>>>> are used
>>>>>>>>>>>>>>>>>>> PLATFORM ImageResolutionHelper.
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>   The  MultiResolutionImage interface implementation 
>>>>>>>>>>>>>>>>>>> could look
>>>>>>>>>>>>>>>>>>> like:
>>>>>>>>>>>>>>>>>>> ------------------------------
>>>>>>>>>>>>>>>>>>> public class CustomMultiResolutionImage extends 
>>>>>>>>>>>>>>>>>>> BufferedImage
>>>>>>>>>>>>>>>>>>> implements
>>>>>>>>>>>>>>>>>>> MultiResolutionImage {
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>      private final Image[] resolutionVariants;
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>      public CustomMultiResolutionImage(int 
>>>>>>>>>>>>>>>>>>> baseIndex, Image...
>>>>>>>>>>>>>>>>>>> images) {
>>>>>>>>>>>>>>>>>>> super(images[baseIndex].getWidth(null),
>>>>>>>>>>>>>>>>>>> images[baseIndex].getHeight(null),
>>>>>>>>>>>>>>>>>>> BufferedImage.TYPE_INT_RGB);
>>>>>>>>>>>>>>>>>>> this.resolutionVariants = images;
>>>>>>>>>>>>>>>>>>>          Graphics g = getGraphics();
>>>>>>>>>>>>>>>>>>> g.drawImage(images[baseIndex], 0, 0, null);
>>>>>>>>>>>>>>>>>>>          g.dispose();
>>>>>>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>      @Override
>>>>>>>>>>>>>>>>>>>      public Image getResolutionVariant(float 
>>>>>>>>>>>>>>>>>>> logicalDPIX, float
>>>>>>>>>>>>>>>>>>> logicalDPIY,
>>>>>>>>>>>>>>>>>>>              float width, float height, AffineTransform
>>>>>>>>>>>>>>>>>>> transform) {
>>>>>>>>>>>>>>>>>>>          return getResolutionVariant(logicalDPIX * 
>>>>>>>>>>>>>>>>>>> width,
>>>>>>>>>>>>>>>>>>> logicalDPIY *
>>>>>>>>>>>>>>>>>>> height);
>>>>>>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>      @Override
>>>>>>>>>>>>>>>>>>>      public List<Image> getResolutionVariants() {
>>>>>>>>>>>>>>>>>>>          return Arrays.asList(resolutionVariants);
>>>>>>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>      public Image getResolutionVariant(double width, 
>>>>>>>>>>>>>>>>>>> double
>>>>>>>>>>>>>>>>>>> height) {
>>>>>>>>>>>>>>>>>>>          for (Image image : resolutionVariants) {
>>>>>>>>>>>>>>>>>>>              if (width <= image.getWidth(null) && 
>>>>>>>>>>>>>>>>>>> height <=
>>>>>>>>>>>>>>>>>>> image.getHeight(null)) {
>>>>>>>>>>>>>>>>>>>                  return image;
>>>>>>>>>>>>>>>>>>>              }
>>>>>>>>>>>>>>>>>>>          }
>>>>>>>>>>>>>>>>>>>          return this;
>>>>>>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>>>> ------------------------------
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>    Thanks,
>>>>>>>>>>>>>>>>>>>    Alexandr.
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> On 2/27/2014 4:54 PM, Alexander Scherbatiy wrote:
>>>>>>>>>>>>>>>>>>>> On 2/22/2014 3:54 AM, Jim Graham wrote:
>>>>>>>>>>>>>>>>>>>>> Hi Alexandr,
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> On 2/18/14 7:33 AM, Alexander Scherbatiy wrote:
>>>>>>>>>>>>>>>>>>>>>> Hi Jim,
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>   Let's divide the discussion into two part.
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>   1. Where it is better to hold resolution variants?
>>>>>>>>>>>>>>>>>>>>>>      Putting resolution variants in Image class 
>>>>>>>>>>>>>>>>>>>>>> brings some
>>>>>>>>>>>>>>>>>>>>>> questions like:
>>>>>>>>>>>>>>>>>>>>>>    - Some type of images do not need to have 
>>>>>>>>>>>>>>>>>>>>>> resolution variants
>>>>>>>>>>>>>>>>>>>>>>    - Should resolution variants have the same 
>>>>>>>>>>>>>>>>>>>>>> type as the base
>>>>>>>>>>>>>>>>>>>>>> image?
>>>>>>>>>>>>>>>>>>>>>>    - getResolutionVariants() method can return 
>>>>>>>>>>>>>>>>>>>>>> copy of the
>>>>>>>>>>>>>>>>>>>>>> original
>>>>>>>>>>>>>>>>>>>>>> list
>>>>>>>>>>>>>>>>>>>>>> so add/removeRV methods should be also added.
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>    There are pros and cons for placing resolution 
>>>>>>>>>>>>>>>>>>>>>> variants to
>>>>>>>>>>>>>>>>>>>>>> Image
>>>>>>>>>>>>>>>>>>>>>> class or to a separate intreface.
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> I agree that this could be a separate interface. 
>>>>>>>>>>>>>>>>>>>>> In my examples
>>>>>>>>>>>>>>>>>>>>> below I was just sticking them inside an "Image{}" 
>>>>>>>>>>>>>>>>>>>>> to show where
>>>>>>>>>>>>>>>>>>>>> they
>>>>>>>>>>>>>>>>>>>>> lived in the set of involved objects, not a specific
>>>>>>>>>>>>>>>>>>>>> recommendation
>>>>>>>>>>>>>>>>>>>>> that they actually be new methods on the base 
>>>>>>>>>>>>>>>>>>>>> class itself. I
>>>>>>>>>>>>>>>>>>>>> probably should have put a comment there about that.
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> With respect to add/remove - that is assuming a 
>>>>>>>>>>>>>>>>>>>>> need for manual
>>>>>>>>>>>>>>>>>>>>> construction of an image set, right? Forgive me if 
>>>>>>>>>>>>>>>>>>>>> I'm
>>>>>>>>>>>>>>>>>>>>> forgetting
>>>>>>>>>>>>>>>>>>>>> something, but I seem to recall that manual 
>>>>>>>>>>>>>>>>>>>>> Multi-Res images was
>>>>>>>>>>>>>>>>>>>>> proposed as a way for developers to introduce @2x 
>>>>>>>>>>>>>>>>>>>>> support
>>>>>>>>>>>>>>>>>>>>> themselves,
>>>>>>>>>>>>>>>>>>>>> but if we are internally managing @2x and -DPI 
>>>>>>>>>>>>>>>>>>>>> variants for them,
>>>>>>>>>>>>>>>>>>>>> then I'm not sure if there is actual developer 
>>>>>>>>>>>>>>>>>>>>> need to manually
>>>>>>>>>>>>>>>>>>>>> construct their own.  Am I forgetting something?
>>>>>>>>>>>>>>>>>>>>    The NSImage has 
>>>>>>>>>>>>>>>>>>>> addRepresentation/removeRepresentation
>>>>>>>>>>>>>>>>>>>> methods to
>>>>>>>>>>>>>>>>>>>> work with image representations on Mac OS X.
>>>>>>>>>>>>>>>>>>>>    The java.awt.Image class should provide similar
>>>>>>>>>>>>>>>>>>>> functionality to
>>>>>>>>>>>>>>>>>>>> have the possibilities as Cocoa on HiDPI displays.
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> 2. Using scale factor/image sizes/scaled image 
>>>>>>>>>>>>>>>>>>>>>> sizes to
>>>>>>>>>>>>>>>>>>>>>> retreive a
>>>>>>>>>>>>>>>>>>>>>> resolution variant.
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>    May be it is better to have a structure that 
>>>>>>>>>>>>>>>>>>>>>> provide all
>>>>>>>>>>>>>>>>>>>>>> necessary
>>>>>>>>>>>>>>>>>>>>>> information  to query the resolution variant: 
>>>>>>>>>>>>>>>>>>>>>> scale factor,
>>>>>>>>>>>>>>>>>>>>>> draw area
>>>>>>>>>>>>>>>>>>>>>> width/height, transformed area width/height?
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>    For example:
>>>>>>>>>>>>>>>>>>>>>>    ---------------------
>>>>>>>>>>>>>>>>>>>>>>      public interface MultiResolutionImage {
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>          interface DrawAreaInfo {
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>              float getScaleFactor();
>>>>>>>>>>>>>>>>>>>>>>              float getAreaWidth();
>>>>>>>>>>>>>>>>>>>>>>              float getAreaHeight();
>>>>>>>>>>>>>>>>>>>>>>              float getTransformedAreaWidth();
>>>>>>>>>>>>>>>>>>>>>>              float getTransformedAreaHeight();
>>>>>>>>>>>>>>>>>>>>>>          }
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>          public Image 
>>>>>>>>>>>>>>>>>>>>>> getResolutionVariant(DrawAreaInfo
>>>>>>>>>>>>>>>>>>>>>> drawAreaInfo) ;
>>>>>>>>>>>>>>>>>>>>>>          public List<Image> getResolutionVariants();
>>>>>>>>>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>>>>>>>>>    ---------------------
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> The problem with a constructor is that this is 
>>>>>>>>>>>>>>>>>>>>> something that is
>>>>>>>>>>>>>>>>>>>>> (potentially) done on every drawImage() call, 
>>>>>>>>>>>>>>>>>>>>> which means we are
>>>>>>>>>>>>>>>>>>>>> inviting GC into the equation. If we can come up 
>>>>>>>>>>>>>>>>>>>>> with a simple
>>>>>>>>>>>>>>>>>>>>> "just
>>>>>>>>>>>>>>>>>>>>> a couple/3/4 numbers" way to embed that data into 
>>>>>>>>>>>>>>>>>>>>> a method call
>>>>>>>>>>>>>>>>>>>>> argument list then we can make this lighter weight.
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> What about simply having floating point (double) 
>>>>>>>>>>>>>>>>>>>>> dimensions on
>>>>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>>>>> rendered size
>>>>>>>>>>>>>>>>>>>>       There should be a way to choose a resolution 
>>>>>>>>>>>>>>>>>>>> variant
>>>>>>>>>>>>>>>>>>>> based on
>>>>>>>>>>>>>>>>>>>> requested drawing size or transformed drawing size.
>>>>>>>>>>>>>>>>>>>>       At least a current transformation should be 
>>>>>>>>>>>>>>>>>>>> included too.
>>>>>>>>>>>>>>>>>>>>> plus a single floating point "logical DPI" for the 
>>>>>>>>>>>>>>>>>>>>> screen?
>>>>>>>>>>>>>>>>>>>>      There is the ID2D1Factory::GetDesktopDpi 
>>>>>>>>>>>>>>>>>>>> method which returns
>>>>>>>>>>>>>>>>>>>> dpiX and dpiY.
>>>>>>>>>>>>>>>>>>>> http://msdn.microsoft.com/en-us/library/windows/apps/dd371316 
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>     That means that logicalDPIX/Y can have 
>>>>>>>>>>>>>>>>>>>> different values.
>>>>>>>>>>>>>>>>>>>>      At least it is described in the
>>>>>>>>>>>>>>>>>>>> http://msdn.microsoft.com/en-us/library/windows/apps/ff684173 
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>      "To get the DPI setting, call the 
>>>>>>>>>>>>>>>>>>>> ID2D1Factory::GetDesktopDpi
>>>>>>>>>>>>>>>>>>>> method. The DPI is returned as two floating-point 
>>>>>>>>>>>>>>>>>>>> values, one for
>>>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>>>> x-axis and one for the y-axis. In theory, these 
>>>>>>>>>>>>>>>>>>>> values can differ.
>>>>>>>>>>>>>>>>>>>> Calculate a separate scaling factor for each axis."
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>   The getResolutionVariant method could look like:
>>>>>>>>>>>>>>>>>>>> --------------------------------------
>>>>>>>>>>>>>>>>>>>>     public Image getResolutionVariant(float 
>>>>>>>>>>>>>>>>>>>> logicalDPIX, float
>>>>>>>>>>>>>>>>>>>> logicalDPIY,
>>>>>>>>>>>>>>>>>>>>             float widthX, float widthY, 
>>>>>>>>>>>>>>>>>>>> AffineTransform
>>>>>>>>>>>>>>>>>>>> transform);
>>>>>>>>>>>>>>>>>>>> --------------------------------------
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>  If the image is known (either passed as an 
>>>>>>>>>>>>>>>>>>>>> argument or the
>>>>>>>>>>>>>>>>>>>>> method is
>>>>>>>>>>>>>>>>>>>>> called on the image), then it can provide the 
>>>>>>>>>>>>>>>>>>>>> original WH.
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> The MultiResolutionImage default implementation 
>>>>>>>>>>>>>>>>>>>>>> could allow
>>>>>>>>>>>>>>>>>>>>>> to use
>>>>>>>>>>>>>>>>>>>>>> different strategies like scale 
>>>>>>>>>>>>>>>>>>>>>> factor/transfom/OS based
>>>>>>>>>>>>>>>>>>>>>>    to query a resolution variant. The OS based 
>>>>>>>>>>>>>>>>>>>>>> strategy can be
>>>>>>>>>>>>>>>>>>>>>> used by
>>>>>>>>>>>>>>>>>>>>>> default.
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> For Mac policy, all we need is the transformed 
>>>>>>>>>>>>>>>>>>>>> dimensions, which
>>>>>>>>>>>>>>>>>>>>> can
>>>>>>>>>>>>>>>>>>>>> be passed in as FP for generality. For Windows 
>>>>>>>>>>>>>>>>>>>>> policy, all we
>>>>>>>>>>>>>>>>>>>>> need
>>>>>>>>>>>>>>>>>>>>> is logical DPI for the screen. What other 
>>>>>>>>>>>>>>>>>>>>> information would we
>>>>>>>>>>>>>>>>>>>>> need, or would an algorithm like to use, that 
>>>>>>>>>>>>>>>>>>>>> can't be computed
>>>>>>>>>>>>>>>>>>>>> from
>>>>>>>>>>>>>>>>>>>>> those 2 pieces?
>>>>>>>>>>>>>>>>>>>>      The aim is to provide a base class that can be 
>>>>>>>>>>>>>>>>>>>> used to
>>>>>>>>>>>>>>>>>>>> create a
>>>>>>>>>>>>>>>>>>>> MultiResolutionImage like:
>>>>>>>>>>>>>>>>>>>> http://hg.openjdk.java.net/jdk9/client/jdk/diff/ae53ebce5fa3/src/share/classes/sun/awt/image/MultiResolutionBufferedImage.java 
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>      A developer should be able to implement a 
>>>>>>>>>>>>>>>>>>>> custom algorithm to
>>>>>>>>>>>>>>>>>>>> query a resolution variant.
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>     It can be done by overriding the 
>>>>>>>>>>>>>>>>>>>> getResolutionVariant image:
>>>>>>>>>>>>>>>>>>>>    -----------------------
>>>>>>>>>>>>>>>>>>>>         Image mrImage = new 
>>>>>>>>>>>>>>>>>>>> MultiResolutionBufferedImage(){
>>>>>>>>>>>>>>>>>>>>             @Override
>>>>>>>>>>>>>>>>>>>>             public Image getResolutionVariant(...) {
>>>>>>>>>>>>>>>>>>>>                 // Custom logic here
>>>>>>>>>>>>>>>>>>>>             }
>>>>>>>>>>>>>>>>>>>>         };
>>>>>>>>>>>>>>>>>>>>    -----------------------
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>    Or it can be done by using resolution variant 
>>>>>>>>>>>>>>>>>>>> choosers so a
>>>>>>>>>>>>>>>>>>>> developer can implement custom resolution variant 
>>>>>>>>>>>>>>>>>>>> query:
>>>>>>>>>>>>>>>>>>>>    -----------------------
>>>>>>>>>>>>>>>>>>>> public class MultiResolutionBufferedImage implements
>>>>>>>>>>>>>>>>>>>> MultiResolutionImage{
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>     interface ResolutionVariantChooser{
>>>>>>>>>>>>>>>>>>>>         Image getResolutionVariant(dpi, size,..., 
>>>>>>>>>>>>>>>>>>>> List<Image>
>>>>>>>>>>>>>>>>>>>> resolutionVariants);
>>>>>>>>>>>>>>>>>>>>     }
>>>>>>>>>>>>>>>>>>>>     ResolutionVariantChooser TRANSFORM_BASED = null;
>>>>>>>>>>>>>>>>>>>>     ResolutionVariantChooser DPI_BASED = null;
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>     ResolutionVariantChooser rvChooser;
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>     @Override
>>>>>>>>>>>>>>>>>>>>     public Image getResolutionVariant(dpi, 
>>>>>>>>>>>>>>>>>>>> size,...,) {
>>>>>>>>>>>>>>>>>>>>         return rvChooser.getResolutionVariant(dpi, 
>>>>>>>>>>>>>>>>>>>> size,...,
>>>>>>>>>>>>>>>>>>>> getResolutionVariants());
>>>>>>>>>>>>>>>>>>>>     }
>>>>>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>>>>>    -----------------------
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>   Thanks,
>>>>>>>>>>>>>>>>>>>>   Alexandr.
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>             ...jim
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> On 2/13/2014 4:42 AM, Jim Graham wrote:
>>>>>>>>>>>>>>>>>>>>>>> On 2/12/14 5:59 AM, Alexander Scherbatiy wrote:
>>>>>>>>>>>>>>>>>>>>>>>> On 2/8/2014 4:19 AM, Jim Graham wrote:
>>>>>>>>>>>>>>>>>>>>>>>>> The primary thing that I was concerned about 
>>>>>>>>>>>>>>>>>>>>>>>>> was the
>>>>>>>>>>>>>>>>>>>>>>>>> presence of
>>>>>>>>>>>>>>>>>>>>>>>>> integers in the API when Windows uses 
>>>>>>>>>>>>>>>>>>>>>>>>> non-integer multiples
>>>>>>>>>>>>>>>>>>>>>>>>       It would make sense to pass real numbers 
>>>>>>>>>>>>>>>>>>>>>>>> to the
>>>>>>>>>>>>>>>>>>>>>>>> getResolutionVariant() method if the difference 
>>>>>>>>>>>>>>>>>>>>>>>> between
>>>>>>>>>>>>>>>>>>>>>>>> resolution
>>>>>>>>>>>>>>>>>>>>>>>> variants sizes is 1.
>>>>>>>>>>>>>>>>>>>>>>>>       It seems that it is not a common case.
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> I was thinking of other API that is related to 
>>>>>>>>>>>>>>>>>>>>>>> this, such as
>>>>>>>>>>>>>>>>>>>>>>> the API
>>>>>>>>>>>>>>>>>>>>>>> that queries the scaling factor from a 
>>>>>>>>>>>>>>>>>>>>>>> SurfaceManager. I
>>>>>>>>>>>>>>>>>>>>>>> seem to
>>>>>>>>>>>>>>>>>>>>>>> remember some integer return values in that, but 
>>>>>>>>>>>>>>>>>>>>>>> Windows might
>>>>>>>>>>>>>>>>>>>>>>> have
>>>>>>>>>>>>>>>>>>>>>>> the answer 1.4 or 1.8, depending on the screen 
>>>>>>>>>>>>>>>>>>>>>>> scaling factor
>>>>>>>>>>>>>>>>>>>>>>> that was
>>>>>>>>>>>>>>>>>>>>>>> determined from the UI.
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> In terms of the getResolutionVariant() method 
>>>>>>>>>>>>>>>>>>>>>>> here, those
>>>>>>>>>>>>>>>>>>>>>>> non-integer
>>>>>>>>>>>>>>>>>>>>>>> screen scaling factors don't directly impact 
>>>>>>>>>>>>>>>>>>>>>>> this API. But, we
>>>>>>>>>>>>>>>>>>>>>>> have
>>>>>>>>>>>>>>>>>>>>>>> some issues with the use of integers there from 
>>>>>>>>>>>>>>>>>>>>>>> other sources:
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> - That API assumes that the caller will 
>>>>>>>>>>>>>>>>>>>>>>> determine the pixel
>>>>>>>>>>>>>>>>>>>>>>> size
>>>>>>>>>>>>>>>>>>>>>>> needed, but the actual media choice is 
>>>>>>>>>>>>>>>>>>>>>>> determined with
>>>>>>>>>>>>>>>>>>>>>>> different
>>>>>>>>>>>>>>>>>>>>>>> techniques on Mac and Windows so this means that 
>>>>>>>>>>>>>>>>>>>>>>> the caller
>>>>>>>>>>>>>>>>>>>>>>> will
>>>>>>>>>>>>>>>>>>>>>>> have
>>>>>>>>>>>>>>>>>>>>>>> to worry about platform conventions. Is that the 
>>>>>>>>>>>>>>>>>>>>>>> right
>>>>>>>>>>>>>>>>>>>>>>> tradeoff?
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> - The technique recommended for Mac involves 
>>>>>>>>>>>>>>>>>>>>>>> computing the
>>>>>>>>>>>>>>>>>>>>>>> precise
>>>>>>>>>>>>>>>>>>>>>>> size desired using the current transform, which 
>>>>>>>>>>>>>>>>>>>>>>> may be a
>>>>>>>>>>>>>>>>>>>>>>> floating
>>>>>>>>>>>>>>>>>>>>>>> point value, so the integer values used in this 
>>>>>>>>>>>>>>>>>>>>>>> API are already
>>>>>>>>>>>>>>>>>>>>>>> approximations and there is no documentation on 
>>>>>>>>>>>>>>>>>>>>>>> how to
>>>>>>>>>>>>>>>>>>>>>>> generate the
>>>>>>>>>>>>>>>>>>>>>>> proper integer.  In particular, the current code 
>>>>>>>>>>>>>>>>>>>>>>> in SG2D
>>>>>>>>>>>>>>>>>>>>>>> naively
>>>>>>>>>>>>>>>>>>>>>>> uses
>>>>>>>>>>>>>>>>>>>>>>> a cast to integer to determine the values to 
>>>>>>>>>>>>>>>>>>>>>>> supply which
>>>>>>>>>>>>>>>>>>>>>>> means a
>>>>>>>>>>>>>>>>>>>>>>> transformed size of W+0.5 will be truncated to W 
>>>>>>>>>>>>>>>>>>>>>>> and the lower
>>>>>>>>>>>>>>>>>>>>>>> resolution image will be used. Does that conform 
>>>>>>>>>>>>>>>>>>>>>>> to Mac
>>>>>>>>>>>>>>>>>>>>>>> guidelines? Do
>>>>>>>>>>>>>>>>>>>>>>> they require the truncated size to reach W+1 
>>>>>>>>>>>>>>>>>>>>>>> before the next
>>>>>>>>>>>>>>>>>>>>>>> size is
>>>>>>>>>>>>>>>>>>>>>>> used?  Passing in float or double values would 
>>>>>>>>>>>>>>>>>>>>>>> sidestep all of
>>>>>>>>>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>>>>>>>>>> since then the comparisons would be done with 
>>>>>>>>>>>>>>>>>>>>>>> full precision,
>>>>>>>>>>>>>>>>>>>>>>> but as
>>>>>>>>>>>>>>>>>>>>>>> long as we can determine a "best practices 
>>>>>>>>>>>>>>>>>>>>>>> compatible with all
>>>>>>>>>>>>>>>>>>>>>>> platforms" rule on how to round to integers, 
>>>>>>>>>>>>>>>>>>>>>>> then integers
>>>>>>>>>>>>>>>>>>>>>>> are OK
>>>>>>>>>>>>>>>>>>>>>>> there.
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> - The Windows document you cite below suggests 
>>>>>>>>>>>>>>>>>>>>>>> that the
>>>>>>>>>>>>>>>>>>>>>>> determination
>>>>>>>>>>>>>>>>>>>>>>> should be made by looking at the Screen DPI and 
>>>>>>>>>>>>>>>>>>>>>>> choosing the
>>>>>>>>>>>>>>>>>>>>>>> next
>>>>>>>>>>>>>>>>>>>>>>> higher media variant based on that screen DPI. 
>>>>>>>>>>>>>>>>>>>>>>> They do not
>>>>>>>>>>>>>>>>>>>>>>> specify
>>>>>>>>>>>>>>>>>>>>>>> choosing media based on the current transform as 
>>>>>>>>>>>>>>>>>>>>>>> is done for
>>>>>>>>>>>>>>>>>>>>>>> Mac.  If
>>>>>>>>>>>>>>>>>>>>>>> we stick with supplying values that are used to 
>>>>>>>>>>>>>>>>>>>>>>> determine which
>>>>>>>>>>>>>>>>>>>>>>> media
>>>>>>>>>>>>>>>>>>>>>>> to use, then on Windows we should not take the 
>>>>>>>>>>>>>>>>>>>>>>> transform into
>>>>>>>>>>>>>>>>>>>>>>> account,
>>>>>>>>>>>>>>>>>>>>>>> but instead query the SurfaceManager for the 
>>>>>>>>>>>>>>>>>>>>>>> scale factor and
>>>>>>>>>>>>>>>>>>>>>>> only
>>>>>>>>>>>>>>>>>>>>>>> transform by those values (even if the current 
>>>>>>>>>>>>>>>>>>>>>>> transform was
>>>>>>>>>>>>>>>>>>>>>>> manually
>>>>>>>>>>>>>>>>>>>>>>> overridden to identity).
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> There are pros and cons to both approaches.
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> Mac ensures that you are always using the best 
>>>>>>>>>>>>>>>>>>>>>>> media for any
>>>>>>>>>>>>>>>>>>>>>>> given
>>>>>>>>>>>>>>>>>>>>>>> render operation.
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> But, Windows ensure more consistency in the face 
>>>>>>>>>>>>>>>>>>>>>>> of other
>>>>>>>>>>>>>>>>>>>>>>> scaling.
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> The thing to consider is that if you have a 
>>>>>>>>>>>>>>>>>>>>>>> 500x500 image
>>>>>>>>>>>>>>>>>>>>>>> with a
>>>>>>>>>>>>>>>>>>>>>>> 1000x1000 variant and you rendering it at 
>>>>>>>>>>>>>>>>>>>>>>> 500x500 and then
>>>>>>>>>>>>>>>>>>>>>>> 501x501,
>>>>>>>>>>>>>>>>>>>>>>> that first jump will be fairly jarring as the 
>>>>>>>>>>>>>>>>>>>>>>> scaled version
>>>>>>>>>>>>>>>>>>>>>>> of the
>>>>>>>>>>>>>>>>>>>>>>> 1000x1000 will not look precisely like the 
>>>>>>>>>>>>>>>>>>>>>>> original 500x500
>>>>>>>>>>>>>>>>>>>>>>> did.
>>>>>>>>>>>>>>>>>>>>>>> With
>>>>>>>>>>>>>>>>>>>>>>> @2x images only, this effect is minimized so the 
>>>>>>>>>>>>>>>>>>>>>>> advantage of
>>>>>>>>>>>>>>>>>>>>>>> always
>>>>>>>>>>>>>>>>>>>>>>> using "the best media for a given render 
>>>>>>>>>>>>>>>>>>>>>>> operation" may
>>>>>>>>>>>>>>>>>>>>>>> outweigh the
>>>>>>>>>>>>>>>>>>>>>>> inconsistency issue. But, on Windows where the 
>>>>>>>>>>>>>>>>>>>>>>> media are
>>>>>>>>>>>>>>>>>>>>>>> 1.4x or
>>>>>>>>>>>>>>>>>>>>>>> 1.8x
>>>>>>>>>>>>>>>>>>>>>>> in size, a downscaled image will start to show more
>>>>>>>>>>>>>>>>>>>>>>> interpolation
>>>>>>>>>>>>>>>>>>>>>>> noise and so the balance of the two choices may 
>>>>>>>>>>>>>>>>>>>>>>> shift more
>>>>>>>>>>>>>>>>>>>>>>> towards not
>>>>>>>>>>>>>>>>>>>>>>> wanting a jarring shift.
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> We might want one or more of the following:
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> - Developer chooses policy (TX_AWARE, DPI_AWARE,
>>>>>>>>>>>>>>>>>>>>>>> ALWAYS_LARGEST,
>>>>>>>>>>>>>>>>>>>>>>> NONE,
>>>>>>>>>>>>>>>>>>>>>>> PLATFORM) where the last policy would use 
>>>>>>>>>>>>>>>>>>>>>>> TX_AWARE on Mac and
>>>>>>>>>>>>>>>>>>>>>>> DPI_AWARE on Windows
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> - We create our own policy and always use it 
>>>>>>>>>>>>>>>>>>>>>>> (TX_AWARE? or
>>>>>>>>>>>>>>>>>>>>>>> DPI_AWARE?)
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> - We create our own policy that dynamically 
>>>>>>>>>>>>>>>>>>>>>>> chooses one of the
>>>>>>>>>>>>>>>>>>>>>>> above
>>>>>>>>>>>>>>>>>>>>>>> strategies depending on platform or available 
>>>>>>>>>>>>>>>>>>>>>>> media or ???
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> - We could create an optional interface for them 
>>>>>>>>>>>>>>>>>>>>>>> to install
>>>>>>>>>>>>>>>>>>>>>>> their
>>>>>>>>>>>>>>>>>>>>>>> own
>>>>>>>>>>>>>>>>>>>>>>> algorithm as well.  I think it would work best 
>>>>>>>>>>>>>>>>>>>>>>> as a delegate
>>>>>>>>>>>>>>>>>>>>>>> interface
>>>>>>>>>>>>>>>>>>>>>>> that one installs into Image so that it can be 
>>>>>>>>>>>>>>>>>>>>>>> used with any
>>>>>>>>>>>>>>>>>>>>>>> image
>>>>>>>>>>>>>>>>>>>>>>> without having to subclass (it wouldn't really 
>>>>>>>>>>>>>>>>>>>>>>> have much to do
>>>>>>>>>>>>>>>>>>>>>>> for
>>>>>>>>>>>>>>>>>>>>>>> BufferedImages or VolatileImages, though):
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> class Image {
>>>>>>>>>>>>>>>>>>>>>>>     void 
>>>>>>>>>>>>>>>>>>>>>>> setResolutionHelper(ImageResolutionHelper foo);
>>>>>>>>>>>>>>>>>>>>>>>     List<Image> getResolutionVariants();
>>>>>>>>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> or:
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> class Graphics {
>>>>>>>>>>>>>>>>>>>>>>>      void 
>>>>>>>>>>>>>>>>>>>>>>> setResolutionHelper(ImageResolutionHelper foo);
>>>>>>>>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> or - anywhere else it could be installed more 
>>>>>>>>>>>>>>>>>>>>>>> centrally (per
>>>>>>>>>>>>>>>>>>>>>>> App
>>>>>>>>>>>>>>>>>>>>>>> context)?
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> and the interface would be something like one of 
>>>>>>>>>>>>>>>>>>>>>>> these
>>>>>>>>>>>>>>>>>>>>>>> variants:
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> interface ImageResolutionHelper {
>>>>>>>>>>>>>>>>>>>>>>>     // This version would prevent substituting a 
>>>>>>>>>>>>>>>>>>>>>>> random image:
>>>>>>>>>>>>>>>>>>>>>>>     // They have to return an index into the 
>>>>>>>>>>>>>>>>>>>>>>> List<Image> for
>>>>>>>>>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>>>>>>>>>> image...
>>>>>>>>>>>>>>>>>>>>>>>     public int chooseVariant(Image img, double 
>>>>>>>>>>>>>>>>>>>>>>> dpi, number w,
>>>>>>>>>>>>>>>>>>>>>>> number h);
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> or:
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>     // This version would allow substituting an 
>>>>>>>>>>>>>>>>>>>>>>> arbitrary
>>>>>>>>>>>>>>>>>>>>>>> image:
>>>>>>>>>>>>>>>>>>>>>>>     public Image getVariant(Image img, double 
>>>>>>>>>>>>>>>>>>>>>>> dpi, number w,
>>>>>>>>>>>>>>>>>>>>>>> number
>>>>>>>>>>>>>>>>>>>>>>> h);
>>>>>>>>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> Since they would be in full control of the 
>>>>>>>>>>>>>>>>>>>>>>> policy, though, we
>>>>>>>>>>>>>>>>>>>>>>> would
>>>>>>>>>>>>>>>>>>>>>>> unfortunately always have to call this, there 
>>>>>>>>>>>>>>>>>>>>>>> would be no more
>>>>>>>>>>>>>>>>>>>>>>> testing
>>>>>>>>>>>>>>>>>>>>>>> in SG2D to see "if" we need to deal with DPI, 
>>>>>>>>>>>>>>>>>>>>>>> though perhaps we
>>>>>>>>>>>>>>>>>>>>>>> could
>>>>>>>>>>>>>>>>>>>>>>> document some internal conditions in which we do 
>>>>>>>>>>>>>>>>>>>>>>> not call it
>>>>>>>>>>>>>>>>>>>>>>> for
>>>>>>>>>>>>>>>>>>>>>>> common cases (but that would have to be well 
>>>>>>>>>>>>>>>>>>>>>>> agreed not to
>>>>>>>>>>>>>>>>>>>>>>> get in
>>>>>>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>>>>>>> way of reasonable uses of the API and well 
>>>>>>>>>>>>>>>>>>>>>>> documented)?
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> Note that we would have to do a security audit 
>>>>>>>>>>>>>>>>>>>>>>> to make sure
>>>>>>>>>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>>>>>>>>>> random image substitution couldn't allow any 
>>>>>>>>>>>>>>>>>>>>>>> sort of "screen
>>>>>>>>>>>>>>>>>>>>>>> phishing"
>>>>>>>>>>>>>>>>>>>>>>> exploit.
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>             ...jim
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> and also what policy they use for choosing 
>>>>>>>>>>>>>>>>>>>>>>>>> scaled images.
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> I don't see a mention of taking the current 
>>>>>>>>>>>>>>>>>>>>>>>>> transform into
>>>>>>>>>>>>>>>>>>>>>>>>> account,
>>>>>>>>>>>>>>>>>>>>>>>>> just physical issues like screen DPI and form 
>>>>>>>>>>>>>>>>>>>>>>>>> factor. They
>>>>>>>>>>>>>>>>>>>>>>>>> talk
>>>>>>>>>>>>>>>>>>>>>>>>> about
>>>>>>>>>>>>>>>>>>>>>>>>> resolution plateaus and in their 
>>>>>>>>>>>>>>>>>>>>>>>>> recommendations section they
>>>>>>>>>>>>>>>>>>>>>>>>> tell the
>>>>>>>>>>>>>>>>>>>>>>>>> developer to use a particular property that 
>>>>>>>>>>>>>>>>>>>>>>>>> tells them the
>>>>>>>>>>>>>>>>>>>>>>>>> screen
>>>>>>>>>>>>>>>>>>>>>>>>> resolution to figure out which image to load 
>>>>>>>>>>>>>>>>>>>>>>>>> if they are
>>>>>>>>>>>>>>>>>>>>>>>>> loading
>>>>>>>>>>>>>>>>>>>>>>>>> manually.  There is no discussion about 
>>>>>>>>>>>>>>>>>>>>>>>>> dynamically loading
>>>>>>>>>>>>>>>>>>>>>>>>> multiple
>>>>>>>>>>>>>>>>>>>>>>>>> versions of the image based on a dynamic 
>>>>>>>>>>>>>>>>>>>>>>>>> program-applied
>>>>>>>>>>>>>>>>>>>>>>>>> transform
>>>>>>>>>>>>>>>>>>>>>>>>> factor as is done on MacOS.
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> Also, they tell developers to draw images to a 
>>>>>>>>>>>>>>>>>>>>>>>>> specific size
>>>>>>>>>>>>>>>>>>>>>>>>> rather
>>>>>>>>>>>>>>>>>>>>>>>>> than using auto-sizing. That begs the question 
>>>>>>>>>>>>>>>>>>>>>>>>> as to how
>>>>>>>>>>>>>>>>>>>>>>>>> they
>>>>>>>>>>>>>>>>>>>>>>>>> interpret a call to draw an image just using a 
>>>>>>>>>>>>>>>>>>>>>>>>> location in
>>>>>>>>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>>>>>>>>> presence of various DPI factors.
>>>>>>>>>>>>>>>>>>>>>>>>       There is an interesting doc that 
>>>>>>>>>>>>>>>>>>>>>>>> describes how to write
>>>>>>>>>>>>>>>>>>>>>>>> DPI-aware
>>>>>>>>>>>>>>>>>>>>>>>> Win32 applications:
>>>>>>>>>>>>>>>>>>>>>>>> http://msdn.microsoft.com/en-us/library/dd464646%28v=vs.85%29.aspx 
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>       It is suggested to handle WM_DPICHANGED 
>>>>>>>>>>>>>>>>>>>>>>>> message, load
>>>>>>>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>>>>>>>> graphic
>>>>>>>>>>>>>>>>>>>>>>>> that has slightly greater resolution to the 
>>>>>>>>>>>>>>>>>>>>>>>> current DPI and
>>>>>>>>>>>>>>>>>>>>>>>> use
>>>>>>>>>>>>>>>>>>>>>>>> StretchBlt
>>>>>>>>>>>>>>>>>>>>>>>>       to scale down the image.
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>      Thanks,
>>>>>>>>>>>>>>>>>>>>>>>>      Alexandr.
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>             ...jim
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> On 2/7/14 3:00 AM, Alexander Scherbatiy wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>> On 1/22/2014 6:40 AM, Jim Graham wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>> Hi Alexander,
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> Before we get too far down the road on this 
>>>>>>>>>>>>>>>>>>>>>>>>>>> API, I think we
>>>>>>>>>>>>>>>>>>>>>>>>>>> understand
>>>>>>>>>>>>>>>>>>>>>>>>>>> the way in which MacOS processes 
>>>>>>>>>>>>>>>>>>>>>>>>>>> multi-resolution images
>>>>>>>>>>>>>>>>>>>>>>>>>>> for
>>>>>>>>>>>>>>>>>>>>>>>>>>> HiDPI
>>>>>>>>>>>>>>>>>>>>>>>>>>> screens, but have we investigated the 
>>>>>>>>>>>>>>>>>>>>>>>>>>> processes that
>>>>>>>>>>>>>>>>>>>>>>>>>>> Windows
>>>>>>>>>>>>>>>>>>>>>>>>>>> uses
>>>>>>>>>>>>>>>>>>>>>>>>>>> under Windows 8? My impression is that 
>>>>>>>>>>>>>>>>>>>>>>>>>>> Windows 8 has
>>>>>>>>>>>>>>>>>>>>>>>>>>> included a
>>>>>>>>>>>>>>>>>>>>>>>>>>> number of new techniques for dealing with 
>>>>>>>>>>>>>>>>>>>>>>>>>>> the high
>>>>>>>>>>>>>>>>>>>>>>>>>>> resolution
>>>>>>>>>>>>>>>>>>>>>>>>>>> displays
>>>>>>>>>>>>>>>>>>>>>>>>>>> that it will run on in the Windows tablet 
>>>>>>>>>>>>>>>>>>>>>>>>>>> and mobile
>>>>>>>>>>>>>>>>>>>>>>>>>>> industries
>>>>>>>>>>>>>>>>>>>>>>>>>>> and
>>>>>>>>>>>>>>>>>>>>>>>>>>> that these will also come into play as 4K 
>>>>>>>>>>>>>>>>>>>>>>>>>>> displays (already
>>>>>>>>>>>>>>>>>>>>>>>>>>> available)
>>>>>>>>>>>>>>>>>>>>>>>>>>> become more common on the desktop. We should 
>>>>>>>>>>>>>>>>>>>>>>>>>>> make sure
>>>>>>>>>>>>>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>>>>>>>>>>>>>> what we
>>>>>>>>>>>>>>>>>>>>>>>>>>> come up with here can provide native 
>>>>>>>>>>>>>>>>>>>>>>>>>>> compatibility with
>>>>>>>>>>>>>>>>>>>>>>>>>>> either
>>>>>>>>>>>>>>>>>>>>>>>>>>> platform's policies and standard practices.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> If you've investigated the MS policies I'd 
>>>>>>>>>>>>>>>>>>>>>>>>>>> like to see a
>>>>>>>>>>>>>>>>>>>>>>>>>>> summary so
>>>>>>>>>>>>>>>>>>>>>>>>>>> that we can consider them as we review this 
>>>>>>>>>>>>>>>>>>>>>>>>>>> API...
>>>>>>>>>>>>>>>>>>>>>>>>>>     There is the Windows Guidelines for 
>>>>>>>>>>>>>>>>>>>>>>>>>> scaling to pixel
>>>>>>>>>>>>>>>>>>>>>>>>>> density:
>>>>>>>>>>>>>>>>>>>>>>>>>> http://msdn.microsoft.com/en-us/library/windows/apps/hh465362.aspx 
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>     which says that Windows has automatic 
>>>>>>>>>>>>>>>>>>>>>>>>>> resource loading
>>>>>>>>>>>>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>>>>>>>>>>>>> supports
>>>>>>>>>>>>>>>>>>>>>>>>>> three version of images scaling (100%, 140%, 
>>>>>>>>>>>>>>>>>>>>>>>>>> and 180%)
>>>>>>>>>>>>>>>>>>>>>>>>>> --------------------------------
>>>>>>>>>>>>>>>>>>>>>>>>>> Without scaling, as the pixel density of a 
>>>>>>>>>>>>>>>>>>>>>>>>>> display device
>>>>>>>>>>>>>>>>>>>>>>>>>> increases, the
>>>>>>>>>>>>>>>>>>>>>>>>>> physical sizes of objects on screen get smaller.
>>>>>>>>>>>>>>>>>>>>>>>>>> When UI would otherwise be too small to touch 
>>>>>>>>>>>>>>>>>>>>>>>>>> and when text
>>>>>>>>>>>>>>>>>>>>>>>>>> gets
>>>>>>>>>>>>>>>>>>>>>>>>>> too
>>>>>>>>>>>>>>>>>>>>>>>>>> small to read,
>>>>>>>>>>>>>>>>>>>>>>>>>> Windows scales the system and app UI to one 
>>>>>>>>>>>>>>>>>>>>>>>>>> of the following
>>>>>>>>>>>>>>>>>>>>>>>>>> scaling
>>>>>>>>>>>>>>>>>>>>>>>>>> plateaus:
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>      1.0 (100%, no scaling is applied)
>>>>>>>>>>>>>>>>>>>>>>>>>>      1.4 (140% scaling)
>>>>>>>>>>>>>>>>>>>>>>>>>>      1.8 (180% scaling)
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>> Windows determines which scaling plateau to 
>>>>>>>>>>>>>>>>>>>>>>>>>> use based on the
>>>>>>>>>>>>>>>>>>>>>>>>>> physical
>>>>>>>>>>>>>>>>>>>>>>>>>> screen size, the screen resolution, the DPI 
>>>>>>>>>>>>>>>>>>>>>>>>>> of the
>>>>>>>>>>>>>>>>>>>>>>>>>> screen, and
>>>>>>>>>>>>>>>>>>>>>>>>>> form
>>>>>>>>>>>>>>>>>>>>>>>>>> factor.
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>> Use resource loading for bitmap images in the 
>>>>>>>>>>>>>>>>>>>>>>>>>> app package
>>>>>>>>>>>>>>>>>>>>>>>>>> For
>>>>>>>>>>>>>>>>>>>>>>>>>> bitmap
>>>>>>>>>>>>>>>>>>>>>>>>>> images stored
>>>>>>>>>>>>>>>>>>>>>>>>>> in the app package, provide a separate image 
>>>>>>>>>>>>>>>>>>>>>>>>>> for each
>>>>>>>>>>>>>>>>>>>>>>>>>> scaling
>>>>>>>>>>>>>>>>>>>>>>>>>> factor(100%, 140%, and 180%),
>>>>>>>>>>>>>>>>>>>>>>>>>> and name your image files using the "scale" 
>>>>>>>>>>>>>>>>>>>>>>>>>> naming
>>>>>>>>>>>>>>>>>>>>>>>>>> convention
>>>>>>>>>>>>>>>>>>>>>>>>>> described
>>>>>>>>>>>>>>>>>>>>>>>>>> below.
>>>>>>>>>>>>>>>>>>>>>>>>>> Windows loads the right image for the current 
>>>>>>>>>>>>>>>>>>>>>>>>>> scale
>>>>>>>>>>>>>>>>>>>>>>>>>> automatically.
>>>>>>>>>>>>>>>>>>>>>>>>>> --------------------------------
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>   The image name convention for the various 
>>>>>>>>>>>>>>>>>>>>>>>>>> scales is:
>>>>>>>>>>>>>>>>>>>>>>>>>> images/logo.scale-100.png
>>>>>>>>>>>>>>>>>>>>>>>>>> images/logo.scale-140.png
>>>>>>>>>>>>>>>>>>>>>>>>>> images/logo.scale-180.png
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>    The 'ms-appx:///images/logo.png' uri is 
>>>>>>>>>>>>>>>>>>>>>>>>>> used to load the
>>>>>>>>>>>>>>>>>>>>>>>>>> image
>>>>>>>>>>>>>>>>>>>>>>>>>> in an
>>>>>>>>>>>>>>>>>>>>>>>>>> application.
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>    If we want to support this in the same way 
>>>>>>>>>>>>>>>>>>>>>>>>>> as it is done
>>>>>>>>>>>>>>>>>>>>>>>>>> for Mac
>>>>>>>>>>>>>>>>>>>>>>>>>> OS X
>>>>>>>>>>>>>>>>>>>>>>>>>>    the WToolkit should return MultiResolution 
>>>>>>>>>>>>>>>>>>>>>>>>>> image in
>>>>>>>>>>>>>>>>>>>>>>>>>> case if
>>>>>>>>>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>>>>>>>>>> loaded image has .scale-* qualifiers.
>>>>>>>>>>>>>>>>>>>>>>>>>>    The Graphics class can request an image 
>>>>>>>>>>>>>>>>>>>>>>>>>> with necessary
>>>>>>>>>>>>>>>>>>>>>>>>>> resolution
>>>>>>>>>>>>>>>>>>>>>>>>>> from the MultiResolution image.
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>    It seems that nothing should be changed in 
>>>>>>>>>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>>>>>>>>>> MultiResolution
>>>>>>>>>>>>>>>>>>>>>>>>>> interface in this case.
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>     Thanks,
>>>>>>>>>>>>>>>>>>>>>>>>>>     Alexandr.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> ...jim
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> On 1/14/14 2:54 AM, Alexander Scherbatiy wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hello,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Could you review the fix:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>    bug: 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8029339 
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>    webrev:
>>>>>>>>>>>>>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~alexsch/8029339/webrev.00 
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>    This is a proposal to introduce an API 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> that allows to
>>>>>>>>>>>>>>>>>>>>>>>>>>>> create a
>>>>>>>>>>>>>>>>>>>>>>>>>>>> custom
>>>>>>>>>>>>>>>>>>>>>>>>>>>> multi resolution image.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> I. It seems reasonable that the API should 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> provide two
>>>>>>>>>>>>>>>>>>>>>>>>>>>> basic
>>>>>>>>>>>>>>>>>>>>>>>>>>>> operations:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>   1. Get the resolution variant based on 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> the requested
>>>>>>>>>>>>>>>>>>>>>>>>>>>> image
>>>>>>>>>>>>>>>>>>>>>>>>>>>> width and
>>>>>>>>>>>>>>>>>>>>>>>>>>>> height:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>      - Image getResolutionVariant(int 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> width, int height)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>     Usually the system provides the scale 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> factor which
>>>>>>>>>>>>>>>>>>>>>>>>>>>> represents
>>>>>>>>>>>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>>>>>>>>>>>> number of pixels corresponding to each 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> linear unit on the
>>>>>>>>>>>>>>>>>>>>>>>>>>>> display.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>     However, it has sense to combine the 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> scale factor and
>>>>>>>>>>>>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>>>>>>>>>>>>> current
>>>>>>>>>>>>>>>>>>>>>>>>>>>> transformations to get the actual image 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> size to be
>>>>>>>>>>>>>>>>>>>>>>>>>>>> displayed.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>   2. Get all provided resolution variants:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>     - List<Image> getResolutionVariants()
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>    There are several uses cases:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>     - Create a new multi-resolution image 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> based on the
>>>>>>>>>>>>>>>>>>>>>>>>>>>> given
>>>>>>>>>>>>>>>>>>>>>>>>>>>> multi-resolution image.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>     - Pass to the native system the 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> multi-resolution
>>>>>>>>>>>>>>>>>>>>>>>>>>>> image. For
>>>>>>>>>>>>>>>>>>>>>>>>>>>> example,
>>>>>>>>>>>>>>>>>>>>>>>>>>>> a use can set to the system the custom 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> multi-resolution
>>>>>>>>>>>>>>>>>>>>>>>>>>>> cursor.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> II. There are some possible ways where the 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> new API can be
>>>>>>>>>>>>>>>>>>>>>>>>>>>> added
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>   1. java.awt.Image.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>    The 2 new methods can be added to the 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Image class. A
>>>>>>>>>>>>>>>>>>>>>>>>>>>> user
>>>>>>>>>>>>>>>>>>>>>>>>>>>> can
>>>>>>>>>>>>>>>>>>>>>>>>>>>> override
>>>>>>>>>>>>>>>>>>>>>>>>>>>>    the getResolutionVariant() and 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> getResolutionVariants()
>>>>>>>>>>>>>>>>>>>>>>>>>>>> methods to
>>>>>>>>>>>>>>>>>>>>>>>>>>>> provide the resolution variants
>>>>>>>>>>>>>>>>>>>>>>>>>>>>    or there can be default implementations 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> of these
>>>>>>>>>>>>>>>>>>>>>>>>>>>> methods
>>>>>>>>>>>>>>>>>>>>>>>>>>>> if a
>>>>>>>>>>>>>>>>>>>>>>>>>>>> user
>>>>>>>>>>>>>>>>>>>>>>>>>>>> puts resolution variants
>>>>>>>>>>>>>>>>>>>>>>>>>>>>    to the list in the sorted order.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>    To check that the image has resolution 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> variants the
>>>>>>>>>>>>>>>>>>>>>>>>>>>> following
>>>>>>>>>>>>>>>>>>>>>>>>>>>> statement can be used:
>>>>>>>>>>>>>>>>>>>>>>>>>>>> image.getResolutionVariants().size()
>>>>>>>>>>>>>>>>>>>>>>>>>>>> != 1
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>    The disadvantage is that there is an 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> overhead that the
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Image
>>>>>>>>>>>>>>>>>>>>>>>>>>>> class
>>>>>>>>>>>>>>>>>>>>>>>>>>>> should contain the List object and not all
>>>>>>>>>>>>>>>>>>>>>>>>>>>>    images can have resolution variants.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>   2. Introduce new MultiResolutionImage 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> interface.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>    A user should extend Image class and 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> implement the
>>>>>>>>>>>>>>>>>>>>>>>>>>>> MultiResolutionImage interface.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>    For example:
>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---------------------
>>>>>>>>>>>>>>>>>>>>>>>>>>>>      public class 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> CustomMultiResolutionImage extends
>>>>>>>>>>>>>>>>>>>>>>>>>>>> BufferedImage
>>>>>>>>>>>>>>>>>>>>>>>>>>>> implements MultiResolutionImage {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>          Image highResolutionImage;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> public 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> CustomMultiResolutionImage(BufferedImage
>>>>>>>>>>>>>>>>>>>>>>>>>>>> baseImage,
>>>>>>>>>>>>>>>>>>>>>>>>>>>> BufferedImage highResolutionImage) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>> super(baseImage.getWidth(),
>>>>>>>>>>>>>>>>>>>>>>>>>>>> baseImage.getHeight(),
>>>>>>>>>>>>>>>>>>>>>>>>>>>> baseImage.getType());
>>>>>>>>>>>>>>>>>>>>>>>>>>>> this.highResolutionImage = 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> highResolutionImage;
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Graphics g = getGraphics();
>>>>>>>>>>>>>>>>>>>>>>>>>>>> g.drawImage(baseImage, 0, 0, null);
>>>>>>>>>>>>>>>>>>>>>>>>>>>> g.dispose();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>          }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> @Override
>>>>>>>>>>>>>>>>>>>>>>>>>>>> public Image getResolutionVariant(int 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> width, int
>>>>>>>>>>>>>>>>>>>>>>>>>>>> height) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>> return ((width <= getWidth() && height <=
>>>>>>>>>>>>>>>>>>>>>>>>>>>> getHeight()))
>>>>>>>>>>>>>>>>>>>>>>>>>>>> ? this : highResolutionImage;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>          }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> @Override
>>>>>>>>>>>>>>>>>>>>>>>>>>>> public List<Image> getResolutionVariants() {
>>>>>>>>>>>>>>>>>>>>>>>>>>>> return Arrays.asList(this,
>>>>>>>>>>>>>>>>>>>>>>>>>>>> highResolutionImage);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>          }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---------------------
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>   The current fix adds the 
>>>>>>>>>>>>>>>>>>>>>>>>>>>> MultiResolutionImage interface
>>>>>>>>>>>>>>>>>>>>>>>>>>>> and
>>>>>>>>>>>>>>>>>>>>>>>>>>>> public
>>>>>>>>>>>>>>>>>>>>>>>>>>>> resolution variant rendering hints.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Alexandr.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>




More information about the 2d-dev mailing list