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

Alexander Scherbatiy alexandr.scherbatiy at oracle.com
Fri Apr 25 14:45:29 UTC 2014


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