[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 8 15:02:27 UTC 2014



   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