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