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