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

Alexander Scherbatiy alexandr.scherbatiy at oracle.com
Wed Dec 10 11:29:42 UTC 2014



   Hi Phil,

   Could you look at the two suggested ways of the multi-resolution 
image support API implementation?

   Thanks,
   Alexandr.

On 8/20/2014 8:10 PM, Alexander Scherbatiy wrote:
>
>   Hi Phil,
>
>   I have prepared the fix where resolution variants are added directly 
> to the Image:
>    http://cr.openjdk.java.net/~alexsch/8029339/list/webrev.00
>
>   You could compare this with the previous version where 
> MultiResolutionImage interface is used:
>     http://cr.openjdk.java.net/~alexsch/8029339/webrev.05
>
>   It could help to decide in which way it is better to provide the 
> multi-resolution image support.
>
>   Below are some comments:
>
>   1. High level goal:
>      Introduce an API that allows to create and handle an image with 
> resolution variants.
>
>   2. What is not subject of the provided API
>     - Scale naming convention for high-resolution images
>     - Providing pixel scale factor for the screen/window
>
>   3. Use cases
>
>    3.1 Loading and drawing high-resolution icons in IntelliJ IDEA
>      A high-resolution image is loaded from resources and stored in 
> JBHiDPIScaledImage class  which is a subclass of the buffered image.
>      The high-resolution image is used to create a disabled icon in 
> the IconLoader.getDisabledIcon(icon) method.
> https://github.com/JetBrains/intellij-community/blob/master/platform/util/src/com/intellij/openapi/util/IconLoader.java 
>
>
>    3.2 Loading and drawing high-resolution icons in NetBeans
>      NetBeans does not have support for the high-resolution icons 
> loading.
>      It loads an icon from the file system using 
> Toolkit.getDefaultToolkit().getImage(url) method or from resources
>      by  ImageReader  and store it in ToolTipImage class which is 
> subclass of the buffered image.
>      ImageUtilities.createDisabledIcon(icon) method creates a disabled 
> icon by applying  RGBImageFilter to the icon.
> http://hg.netbeans.org/main/file/97dcf49eb4a7/openide.util/src/org/openide/util/ImageUtilities.java 
>
>
>    3.3 Loading system icons in JDK 1.8
>      JDK requests icons from the native system for system L&Fs and 
> applies filters for them.
>      See for example AquaUtils.generateLightenedImage() method:
> http://hg.openjdk.java.net/jdk9/client/jdk/file/e6f48c4fad38/src/java.desktop/macosx/classes/com/apple/laf/AquaUtils.java 
>
>
>   4. HiDPI support for Images on different OSes
>
>     4.1 Mac OS X
>       Cocoa API contains NSImage that allows to work with image 
> representations: add/remove/get all representations.
>       It picks up an image with necessary resolution based on the 
> screen backing store pixel scale factor and applied transforms.
> https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSImage_Class/Reference/Reference.html 
>
>
>     4.2 Linux
>       GTK+ 3 API has gtkcssimagescaled lib (it seems that it is not 
> public/stable)
>       that parses the -gtk-scaled css property and draws a GtkCssImage 
> according to the given scale factor.
>
>       I have not found information about the HiDPI support in Xlib.
>
>     4.3 Windows
>       I have only found the tutorial that suggests to select and draw 
> a bitmap using the queried DPI
>       and scale the coordinates for drawing a rectangular frame
> http://msdn.microsoft.com/en-us/library/dd464659%28v=vs.85%29.aspx
>
>       Windows also provides the horizontal and vertical DPI of the 
> desktop
> http://msdn.microsoft.com/en-us/library/windows/apps/dd371316
>
>   5. Pseudo API
>      Below are some ways which illustrates how multi-resolution images 
> can be created and used.
>
>     5.1 Resolution variants are stored directly in Image class.
>     To query a resolution variant it needs to compare the resolution 
> variant width/height
>     with the requested high-resolution size.
>     ------------
>     public abstract class Image {
>
>         public void addResolutionVariant(Image image) {...}
>         public List<Image> getResolutionVariants() {...}
>     }
>     ------------
>     // create a disabled image with resolution variants
>
>     Image disabledImage = getDisabledImage(image);
>
>     for (Image rv : image.getResolutionVariants()) {
>         disabledImage.addResolutionVariant(getDisabledImage(rv));
>     }
>     ------------
>     This approach requires that all resolution variants have been 
> created even not of them are really used.
>
>     5.2  Resolution variants are stored in a separate object that 
> allows to create them by demand.
>     To query a resolution variant it needs to compare the resolution 
> variant scale factor
>     with the requested scale (that can include both screen DPI scale 
> and applied transforms).
>     ------------
>     public abstract class Image {
>
>         public static interface ResolutionVariant {
>             Image getImage();
>             float getScaleFactor();
>         }
>
>         public void addResolutionVariant(ResolutionVariant 
> resolutionVariant) {...}
>         public List<ResolutionVariant> getResolutionVariants() {...}
>     }
>     ------------
>     // create a disabled image with resolution variants
>     Image disabledImage = getDisabledImage(image);
>
>     for (Image.ResolutionVariant rv : image.getResolutionVariants()) {
>         disabledImage.addResolutionVariant(new 
> Image.ResolutionVariant() {
>
>             public Image getImage() {
>                 return getDisabledImage(rv.getImage());
>             }
>
>             public float getScaleFactor() {
>                 return rv.getScaleFactor();
>             }
>         });
>     }
>     ------------
>
>     It does not have problem if a predefined set of images is provided 
> (like image.png and image at 2x.png on the file system).
>     This does not cover cases where a resolution variant can be 
> created using the exact requested size (like loading icons from the 
> native system).
>     A resolution variant can be queried based on a scale factor and 
> applied transforms.
>
>     5.3 The provided example allows to create a resolution variant 
> using the requested high-resolution image size.
>     ------------
>     public interface MultiResolutionImage {
>         Image getResolutionVariant(float width, float height);
>     }
>     ------------
>     // create a multi-resolution image
>     Image mrImage = new AbstractMultiResolutionImage() {
>
>             public Image getResolutionVariant(float width, float 
> height) {
>                 // create and return a resolution variant with exact 
> requested width/height size
>             }
>
>             protected Image getBaseImage() {
>                 return baseImage;
>             }
>         };
>     ------------
>     // create a disabled image with resolution variants
>     Image disabledImage = null;
>     if (image instanceof MultiResolutionImage) {
>         final MultiResolutionImage mrImage = (MultiResolutionImage) 
> image;
>         disabledImage = new AbstractMultiResolutionImage(){
>
>             public Image getResolutionVariant(float width, float 
> height) {
>                 return 
> getDisabledImage(mrImage.getResolutionVariant(width, height));
>             }
>
>             protected Image getBaseImage() {
>                 return getDisabledImage(mrImage);
>             }
>         };
>     } else {
>         disabledImage = getDisabledImage(image);
>     }
>     ------------
>
>   Thanks,
>   Alexandr.
>
>
> On 7/29/2014 6:44 PM, Alexander Scherbatiy wrote:
>>> 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 awt-dev mailing list