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

Alexander Scherbatiy alexandr.scherbatiy at oracle.com
Fri Mar 13 13:34:27 UTC 2015


   Hello,

   Could you review the proposed API based on MultiresolutionImage 
interface:
     http://cr.openjdk.java.net/~alexsch/8029339/webrev.06/

  - return unmodifiable list comment is added to the 
getResolutionVariants() method javadoc in MultiresolutionImage interface
  - base image size arguments are removed form the 
getResolutionVariant(...) method in MultiresolutionImage interface
  - BaseMultiResolutionImage class that allows to create a 
multi-resolution image based on resolution variant array is added
  - the test for the BaseMultiResolutionImage is added

  Thanks,
  Alexandr.

On 2/14/2015 3:23 AM, Jim Graham wrote:
> The second solution looks good.  I'd make it standard practice 
> (perhaps even mentioned in the documentation) to return unmodifiable 
> lists from the getVariants() method.  The Collections class provides 
> easy methods to create these lists, and it sends a clear message to 
> the caller that the list was provided for them to read, but not write 
> to.  Otherwise they may add a new image to the list you provided them 
> and wonder why it wasn't showing up.  Also, an unmodifiable list can 
> be cached and reused for subsequent calls without having to create a 
> new list every time.
>
> In getResolutionVariant() was there a reason why the base dimensions 
> were provided as float?  The destination dimensions make sense as 
> float since they could be the result of a scale, but the source 
> dimensions are typically getWidth/getHeight() on the base image.  A 
> related question would be if they are needed at all, since the 
> implementation should probably already be aware of what the base image 
> is and what its dimensions are.  I'm guessing they are provided 
> because the implementation in SG2D already knows them and it makes it 
> easier to forward the implementation on to a shared (static?) method?
>
> With respect to default implementations, I take it that the BaseMRI is 
> along the pattern that we see in Swing for Base classes.  Would it be 
> helpful to provide an implementation (in addition or instead) that 
> allows a developer to take a bunch of images and quickly make an MRI 
> without having to override anything?  The implementations of 
> getBaseImage() and getResolutionVariants() are pretty straightforward 
> and a fairly reasonable default algorithm can be provided for 
> getRV(dimensions).  This question is more of an idle question for my 
> own curiosity than a stumbling block...
>
>             ...jim
>
> On 1/22/2015 6:49 AM, Alexander Scherbatiy wrote:
>>
>>    Hi Phil,
>>
>>    I have prepared two versions of the proposed API:
>>
>>    I) Resolution variants are added directly to the Image:
>>     http://cr.openjdk.java.net/~alexsch/8029339/list/webrev.00
>>
>>    II)  MultiResolutionImage interface is used:
>>      http://cr.openjdk.java.net/~alexsch/8029339/webrev.05
>>
>>    It could help to decide which way should be chosen for the the
>> multi-resolution image support.
>>
>>    Below are some comments:
>>
>>    1. High level goal:
>>       Introduce an API that allows to create and handle an image with
>> resolution variants.
>>
>>    2. What is not subject of the provided API
>>      - Scale naming convention for high-resolution images
>>      - Providing pixel scale factor for the screen/window
>>
>>    3. Use cases
>>     3.1 Loading and drawing high-resolution icons in IntelliJ IDEA
>>       A high-resolution image is loaded from resources and stored in
>> JBHiDPIScaledImage class  which is a subclass of the buffered image.
>>       The high-resolution image is used to create a disabled icon in the
>> IconLoader.getDisabledIcon(icon) method.
>> https://github.com/JetBrains/intellij-community/blob/master/platform/util/src/com/intellij/openapi/util/IconLoader.java 
>>
>>
>>
>>     3.2 Loading and drawing high-resolution icons in NetBeans
>>       NetBeans does not have support for the high-resolution icons 
>> loading.
>>       It loads an icon from the file system using
>> Toolkit.getDefaultToolkit().getImage(url) method or from resources
>>       by  ImageReader  and store it in ToolTipImage class which is
>> subclass of the buffered image.
>>       ImageUtilities.createDisabledIcon(icon) method creates a disabled
>> icon by applying  RGBImageFilter to the icon.
>> http://hg.netbeans.org/main/file/97dcf49eb4a7/openide.util/src/org/openide/util/ImageUtilities.java 
>>
>>
>>
>>     3.3 Loading system icons in JDK 1.8
>>       JDK requests icons from the native system for system L&Fs and
>> applies filters for them.
>>       See for example AquaUtils.generateLightenedImage() method:
>> http://hg.openjdk.java.net/jdk9/client/jdk/file/e6f48c4fad38/src/java.desktop/macosx/classes/com/apple/laf/AquaUtils.java 
>>
>>
>>
>>    4. HiDPI support for Images on different OSes
>>
>>      4.1 Mac OS X
>>        Cocoa API contains NSImage that allows to work with image
>> representations: add/remove/get all representations.
>>        It picks up an image with necessary resolution based on the
>> screen backing store pixel scale factor and applied transforms.
>> https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSImage_Class/Reference/Reference.html 
>>
>>
>>
>>      4.2 Linux
>>        GTK+ 3 API has gtkcssimagescaled lib (it seems that it is not
>> public/stable)
>>        that parses the -gtk-scaled css property and draws a GtkCssImage
>> according to the given scale factor.
>>
>>        I have not found information about the HiDPI support in Xlib.
>>
>>      4.3 Windows
>>        I have only found the tutorial that suggests to select and draw a
>> bitmap using the queried DPI
>>        and scale the coordinates for drawing a rectangular frame
>> http://msdn.microsoft.com/en-us/library/dd464659%28v=vs.85%29.aspx
>>
>>        Windows also provides the horizontal and vertical DPI of the 
>> desktop
>> http://msdn.microsoft.com/en-us/library/windows/apps/dd371316
>>
>>    5. Pseudo API
>>       Below are some ways which illustrates how multi-resolution images
>> can be created and used.
>>
>>      5.1 Resolution variants are stored directly in Image class.
>>      To query a resolution variant it needs to compare the resolution
>> variant width/height
>>      with the requested high-resolution size.
>>      ------------
>>      public abstract class Image {
>>
>>          public void addResolutionVariant(Image image) {...}
>>          public List<Image> getResolutionVariants() {...}
>>      }
>>      ------------
>>      // create a disabled image with resolution variants
>>
>>      Image disabledImage = getDisabledImage(image);
>>
>>      for (Image rv : image.getResolutionVariants()) {
>> disabledImage.addResolutionVariant(getDisabledImage(rv));
>>      }
>>      ------------
>>      This approach requires that all resolution variants have been
>> created even not of them are really used.
>>
>>      5.2  Resolution variants are stored in a separate object that
>> allows to create them by demand.
>>      To query a resolution variant it needs to compare the resolution
>> variant scale factor
>>      with the requested scale (that can include both screen DPI scale
>> and applied transforms).
>>      ------------
>>      public abstract class Image {
>>
>>          public static interface ResolutionVariant {
>>              Image getImage();
>>              float getScaleFactor();
>>          }
>>
>>          public void addResolutionVariant(ResolutionVariant
>> resolutionVariant) {...}
>>          public List<ResolutionVariant> getResolutionVariants() {...}
>>      }
>>      ------------
>>      // create a disabled image with resolution variants
>>      Image disabledImage = getDisabledImage(image);
>>
>>      for (Image.ResolutionVariant rv : image.getResolutionVariants()) {
>>          disabledImage.addResolutionVariant(new 
>> Image.ResolutionVariant() {
>>
>>              public Image getImage() {
>>                  return getDisabledImage(rv.getImage());
>>              }
>>
>>              public float getScaleFactor() {
>>                  return rv.getScaleFactor();
>>              }
>>          });
>>      }
>>      ------------
>>
>>      It does not have problem if a predefined set of images is provided
>> (like image.png and image at 2x.png on the file system).
>>      This does not cover cases where a resolution variant can be created
>> using the exact requested size (like loading icons from the native 
>> system).
>>      A resolution variant can be queried based on a scale factor and
>> applied transforms.
>>
>>      5.3 The provided example allows to create a resolution variant
>> using the requested high-resolution image size.
>>      ------------
>>      public interface MultiResolutionImage {
>>          Image getResolutionVariant(float width, float height);
>>      }
>>      ------------
>>      // create a multi-resolution image
>>      Image mrImage = new AbstractMultiResolutionImage() {
>>
>>              public Image getResolutionVariant(float width, float 
>> height) {
>>                  // create and return a resolution variant with exact
>> requested width/height size
>>              }
>>
>>              protected Image getBaseImage() {
>>                  return baseImage;
>>              }
>>          };
>>      ------------
>>      // create a disabled image with resolution variants
>>      Image disabledImage = null;
>>      if (image instanceof MultiResolutionImage) {
>>          final MultiResolutionImage mrImage = (MultiResolutionImage) 
>> image;
>>          disabledImage = new AbstractMultiResolutionImage(){
>>
>>              public Image getResolutionVariant(float width, float 
>> height) {
>>                  return
>> getDisabledImage(mrImage.getResolutionVariant(width, height));
>>              }
>>
>>              protected Image getBaseImage() {
>>                  return getDisabledImage(mrImage);
>>              }
>>          };
>>      } else {
>>          disabledImage = getDisabledImage(image);
>>      }
>>      ------------
>>
>>    Thanks,
>>    Alexandr.



More information about the awt-dev mailing list