[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 May 16 16:16:21 UTC 2014
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 2d-dev
mailing list