Hello, Jim.
27.03.15 0:48, Jim Graham wrote:
RenderingHints.java:

Where do we process this hint? Don't we need to pass it to the getVariant() method?

I don't understand the hint values other than the one that always uses the base image. Default I guess gives us the ability to use the Mac algorithm of "next larger size" on Mac and "based on Screen DPI" on Windows, but the 3rd value "ON" is so vague as to not have any meaning. Perhaps we should just delete it, but then do we just always do the Mac method? Or do we vaguely have our internal images have a platform-specific method and the Abstract/Base classes just do what they want with no control from the user? In FX we are also still struggling with this issue and we may likely just do what the Mac does in all cases, but perhaps AWT needs to "behave like the platform" more? If we are going to have actual values, then we need to have them do something, which means:

- SG2D needs to track the hint just like we do the other hints that affect our processing
- MRI.getVariant() needs to have the hint as an argument
- BaseMRI should probably do something with that hint
- hint values should include:
    - ..._DEFAULT - implementation gets to decide
    - ..._BASE - always use the base image
    - ..._SIZE_FIT - Mac algorithm of smallest image that is big enough
    - ..._DPI_FIT - choose based on DPI of the screen, ignoring transform
I did not watch this discussion, but I have a question about use of dpi vs scale. Why we cannot make things simpler and provide only width+height to the getResolutionVariant()?
Like this:
Image getResolutionVariant(float destImageWidth, float destImageWidth);
All other things can be calculated internally by this method.

We will pass width and height, based on the hints which were set to the SG2D. By default this hint will be _FULL_SIZE_FIT like on osx and width/height will include full transformation(dev+usr), On windows for Window and VolatileImages this will be _DPI_FIT and width/height will include dev transformation only.
It is unclear what hint should be default in BufferedImage on windows.
List of the hints should looks like:
    - ..._DEFAULT - implementation gets to decide
    - ..._BASE - always use the base image
- ..._FULL_SIZE_FIT - Mac algorithm of smallest image that is big enough - ..._DEFAULT_DPI_FIT - choose based on DPI of the screen, ignoring transform - ..._USR_DPI_FIT - choose based on users transform, ignoring device transform.
Names can be tweaked for sure.
It seems we will cover all possible cases in such solution, no?
line 978 - missing blank line between fields

SG2D.java:

- The interface says that you will be passing in the "logical DPI" of the display, but here you are actually passing in the screen's scale factor.


On 3/13/15 6:34 AM, Alexander Scherbatiy wrote:

   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 im...@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.



--
Best regards, Sergey.

Reply via email to