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

Alexander Scherbatiy alexandr.scherbatiy at oracle.com
Mon May 12 14:35:45 UTC 2014


   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