From krueger at lesspain.de Sun Jun 1 08:18:39 2014 From: krueger at lesspain.de (=?UTF-8?Q?Robert_Kr=C3=BCger?=) Date: Sun, 1 Jun 2014 10:18:39 +0200 Subject: Ugly flashing when opening a css-styled stage Message-ID: Hi, I'm in the process of evaluating Java FX 8 for our currently Swing-based product (also Java 8) on OSX. My first attempt to style a stage's background resulted in an ugly flashing effect which I would classify as a show-stopper for delivering a commercial product. This looks like it is caused by the stage being drawn at least once before the style has been applied, and I am wondering what the mistake is since my code is more or less a straight-forward hello world: package jfxtest; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class JXTest extends Application { @Override public void start(Stage primaryStage) throws Exception { final StackPane pane = new StackPane(); final Button closeButton = new Button("Close"); closeButton.setOnAction(event -> primaryStage.close()); pane.getChildren().add(closeButton); final Scene scene = new Scene(pane, 800, 600); scene.getStylesheets().add("dark.css"); scene.getStylesheets(); primaryStage.setScene(scene); primaryStage.setTitle(getClass().getSimpleName()); primaryStage.show(); } public static void main(String[] args) { launch(args); } } with dark.css being: .root { -fx-background: rgb(54, 54, 54); } Is this a Mac-specific problem? Is there a workaround? Which of the two mailing lists is the more appropriate one to post these things (JFX problems which look like they might be platform-specific) to? Thanks, Robert From krueger at lesspain.de Mon Jun 2 07:51:55 2014 From: krueger at lesspain.de (=?UTF-8?Q?Robert_Kr=C3=BCger?=) Date: Mon, 2 Jun 2014 09:51:55 +0200 Subject: Ugly flashing when opening a css-styled stage In-Reply-To: <30C846C5-1189-47C2-BCEE-35876A33F386@reportmill.com> References: <30C846C5-1189-47C2-BCEE-35876A33F386@reportmill.com> Message-ID: Thanks but it does not seem to improve the situation. btw, I am using 1.8.0_05-b13 on Mac OS 10.9.3 on a retina MBP. On Sun, Jun 1, 2014 at 9:59 PM, Jeff Martin wrote: > I haven't seen this, but here's a hack you can try: > > // Show stage transparent once to get proper drawing > _stage.setOpacity(0); _stage.show(); _stage.hide(); _stage.setOpacity(1); > > I've done this before to trigger Stage to set it's width/height property (which I needed to position the stage property). > > jeff > > > On Jun 1, 2014, at 3:18 AM, Robert Kr?ger wrote: > >> Hi, >> >> I'm in the process of evaluating Java FX 8 for our currently >> Swing-based product (also Java 8) on OSX. >> >> My first attempt to style a stage's background resulted in an ugly >> flashing effect which I would classify as a show-stopper for >> delivering a commercial product. This looks like it is caused by the >> stage being drawn at least once before the style has been applied, and >> I am wondering what the mistake is since my code is more or less a >> straight-forward hello world: >> >> package jfxtest; >> >> import javafx.application.Application; >> import javafx.scene.Scene; >> import javafx.scene.control.Button; >> import javafx.scene.layout.StackPane; >> import javafx.stage.Stage; >> >> public class JXTest extends Application { >> >> @Override >> public void start(Stage primaryStage) throws Exception { >> final StackPane pane = new StackPane(); >> final Button closeButton = new Button("Close"); >> closeButton.setOnAction(event -> primaryStage.close()); >> pane.getChildren().add(closeButton); >> final Scene scene = new Scene(pane, 800, 600); >> scene.getStylesheets().add("dark.css"); >> scene.getStylesheets(); >> primaryStage.setScene(scene); >> primaryStage.setTitle(getClass().getSimpleName()); >> primaryStage.show(); >> } >> >> public static void main(String[] args) { >> launch(args); >> } >> } >> >> with dark.css being: >> >> .root { >> -fx-background: rgb(54, 54, 54); >> } >> >> Is this a Mac-specific problem? Is there a workaround? Which of the >> two mailing lists is the more appropriate one to post these things >> (JFX problems which look like they might be platform-specific) to? >> >> Thanks, >> >> Robert > From krueger at lesspain.de Mon Jun 2 09:11:28 2014 From: krueger at lesspain.de (=?UTF-8?Q?Robert_Kr=C3=BCger?=) Date: Mon, 2 Jun 2014 11:11:28 +0200 Subject: Ugly flashing when opening a css-styled stage In-Reply-To: <538C3018.2070803@bestsolution.at> References: <30C846C5-1189-47C2-BCEE-35876A33F386@reportmill.com> <538C3018.2070803@bestsolution.at> Message-ID: No, it does not. So it is not the CSS. On Mon, Jun 2, 2014 at 10:04 AM, Tom Schindl wrote: > To rule out CSS is the reason you could directly set the background: > > pane.setBackground(new Background(new BackgroundFill(Color.rgb(54, 54, > 54), CornerRadii.EMPTY, Insets.EMPTY))); > > Does that improve the situation? > > Tom > > > On 02.06.14 09:51, Robert Kr?ger wrote: >> Thanks but it does not seem to improve the situation. >> >> btw, I am using 1.8.0_05-b13 on Mac OS 10.9.3 on a retina MBP. >> >> On Sun, Jun 1, 2014 at 9:59 PM, Jeff Martin wrote: >>> I haven't seen this, but here's a hack you can try: >>> >>> // Show stage transparent once to get proper drawing >>> _stage.setOpacity(0); _stage.show(); _stage.hide(); _stage.setOpacity(1); >>> >>> I've done this before to trigger Stage to set it's width/height property (which I needed to position the stage property). >>> >>> jeff >>> >>> >>> On Jun 1, 2014, at 3:18 AM, Robert Kr?ger wrote: >>> >>>> Hi, >>>> >>>> I'm in the process of evaluating Java FX 8 for our currently >>>> Swing-based product (also Java 8) on OSX. >>>> >>>> My first attempt to style a stage's background resulted in an ugly >>>> flashing effect which I would classify as a show-stopper for >>>> delivering a commercial product. This looks like it is caused by the >>>> stage being drawn at least once before the style has been applied, and >>>> I am wondering what the mistake is since my code is more or less a >>>> straight-forward hello world: >>>> >>>> package jfxtest; >>>> >>>> import javafx.application.Application; >>>> import javafx.scene.Scene; >>>> import javafx.scene.control.Button; >>>> import javafx.scene.layout.StackPane; >>>> import javafx.stage.Stage; >>>> >>>> public class JXTest extends Application { >>>> >>>> @Override >>>> public void start(Stage primaryStage) throws Exception { >>>> final StackPane pane = new StackPane(); >>>> final Button closeButton = new Button("Close"); >>>> closeButton.setOnAction(event -> primaryStage.close()); >>>> pane.getChildren().add(closeButton); >>>> final Scene scene = new Scene(pane, 800, 600); >>>> scene.getStylesheets().add("dark.css"); >>>> scene.getStylesheets(); >>>> primaryStage.setScene(scene); >>>> primaryStage.setTitle(getClass().getSimpleName()); >>>> primaryStage.show(); >>>> } >>>> >>>> public static void main(String[] args) { >>>> launch(args); >>>> } >>>> } >>>> >>>> with dark.css being: >>>> >>>> .root { >>>> -fx-background: rgb(54, 54, 54); >>>> } >>>> >>>> Is this a Mac-specific problem? Is there a workaround? Which of the >>>> two mailing lists is the more appropriate one to post these things >>>> (JFX problems which look like they might be platform-specific) to? >>>> >>>> Thanks, >>>> >>>> Robert >>> > From anthony.petrov at oracle.com Mon Jun 2 13:01:56 2014 From: anthony.petrov at oracle.com (Anthony Petrov) Date: Mon, 02 Jun 2014 17:01:56 +0400 Subject: Ugly flashing when opening a css-styled stage In-Reply-To: References: Message-ID: <538C75C4.9070500@oracle.com> Hi Robert, > Which of the > two mailing lists is the more appropriate one to post these things > (JFX problems which look like they might be platform-specific) to? FYI: the JDK Mac OS X Port Project has been completed long time ago, so currently the macosx-port-dev@ mailing list isn't appropriate for almost anything. Please report JavaFX bugs at: https://javafx-jira.kenai.com/ AWT/Swing/JDK bugs can be reported at: http://bugreport.java.com/bugreport/ (or http://bugs.sun.com/ ) If you wish to participate in the development of the technologies (e.g. you want to contribute a patch for JavaFX or JDK platform), then you're welcome to post your suggestions on the appropriate development mailing lists (openjfx-dev@, awt-dev@, swing-dev@, etc.) -- best regards, Anthony On 6/1/2014 12:18 PM, Robert Kr?ger wrote: > Hi, > > I'm in the process of evaluating Java FX 8 for our currently > Swing-based product (also Java 8) on OSX. > > My first attempt to style a stage's background resulted in an ugly > flashing effect which I would classify as a show-stopper for > delivering a commercial product. This looks like it is caused by the > stage being drawn at least once before the style has been applied, and > I am wondering what the mistake is since my code is more or less a > straight-forward hello world: > > package jfxtest; > > import javafx.application.Application; > import javafx.scene.Scene; > import javafx.scene.control.Button; > import javafx.scene.layout.StackPane; > import javafx.stage.Stage; > > public class JXTest extends Application { > > @Override > public void start(Stage primaryStage) throws Exception { > final StackPane pane = new StackPane(); > final Button closeButton = new Button("Close"); > closeButton.setOnAction(event -> primaryStage.close()); > pane.getChildren().add(closeButton); > final Scene scene = new Scene(pane, 800, 600); > scene.getStylesheets().add("dark.css"); > scene.getStylesheets(); > primaryStage.setScene(scene); > primaryStage.setTitle(getClass().getSimpleName()); > primaryStage.show(); > } > > public static void main(String[] args) { > launch(args); > } > } > > with dark.css being: > > .root { > -fx-background: rgb(54, 54, 54); > } > > Is this a Mac-specific problem? Is there a workaround? Which of the > two mailing lists is the more appropriate one to post these things > (JFX problems which look like they might be platform-specific) to? > > Thanks, > > Robert > From krueger at lesspain.de Mon Jun 2 15:38:56 2014 From: krueger at lesspain.de (=?UTF-8?Q?Robert_Kr=C3=BCger?=) Date: Mon, 2 Jun 2014 17:38:56 +0200 Subject: Ugly flashing when opening a css-styled stage In-Reply-To: <538C75C4.9070500@oracle.com> References: <538C75C4.9070500@oracle.com> Message-ID: Hi Anthony On Mon, Jun 2, 2014 at 3:01 PM, Anthony Petrov wrote: > Hi Robert, > > >> Which of the >> two mailing lists is the more appropriate one to post these things >> (JFX problems which look like they might be platform-specific) to? > > > FYI: the JDK Mac OS X Port Project has been completed long time ago, so > currently the macosx-port-dev@ mailing list isn't appropriate for almost > anything. Oh, that's a surprise. I thought it was more or less the successor of apple-java-dev, i.e. where one discusses issues/problems/questions specific to the Mac port of the JDK/JRE and Java development on the Mac in general. > > Please report JavaFX bugs at: https://javafx-jira.kenai.com/ Submitted as RT-37372 > > AWT/Swing/JDK bugs can be reported at: http://bugreport.java.com/bugreport/ > (or http://bugs.sun.com/ ) > > If you wish to participate in the development of the technologies (e.g. you > want to contribute a patch for JavaFX or JDK platform), then you're welcome > to post your suggestions on the appropriate development mailing lists > (openjfx-dev@, awt-dev@, swing-dev@, etc.) > I've been subscribed to the two lists for a while now and my impression is, it is also a place where people running into problems with the platform's limitations exchange their experience which has been very valuable especially when dealing with a rather new platform but I guess I need to move to the OTN community for this. Thanks and best regards, Robert From alexandr.scherbatiy at oracle.com Wed Jun 4 14:29:42 2014 From: alexandr.scherbatiy at oracle.com (Alexander Scherbatiy) Date: Wed, 04 Jun 2014 18:29:42 +0400 Subject: [OpenJDK 2D-Dev] [9] Review request for 8029339 Custom MultiResolution image support on HiDPI displays In-Reply-To: <5379E117.6010202@oracle.com> References: <52D51764.8020103@oracle.com> <52DF2F98.3030503@oracle.com> <52F4BCEB.9040702@oracle.com> <52F5782A.9060300@oracle.com> <52FB7E3E.6050000@oracle.com> <52FC14EC.9080503@oracle.com> <53037D3D.80709@oracle.com> <5307E71E.50607@oracle.com> <530F3592.40600@oracle.com> <532B00AD.1000704@oracle.com> <532B7EC5.9000206@oracle.com> <532C4DD7.1080804@oracle.com> <532CD202.5070508@oracle.com> <53302A8E.6090107@oracle.com> <53343914.6090004@oracle.com> <533C8DDB.5000406@oracle.com> <533E9D42.10409@oracle.com> <53598D86.5020607@oracle.com> <535A7509.6050802@oracle.com> <5370DC41.5080608@oracle.com> <537639D5.9000206@oracle.com> <53764700.2060309@oracle.com> <5379E117.6010202@oracle.com> Message-ID: <538F2D56.80609@oracle.com> Hi Phil, Could you review the fix where only new MultiResolutionImage interface and AbstractMultiResolutionImage class are added: http://cr.openjdk.java.net/~alexsch/8029339/webrev.05/ Thanks, Alexandr. On 5/19/2014 2:46 PM, Alexander Scherbatiy wrote: > > Hi Phil, > > On 5/16/2014 9:12 PM, Phil Race wrote: >> 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 ? > It was decided to split the original issue on two parts: > - this fix adds only MultiResolutionImage interface and > AbstractMultiResolutionImage class. > Here is the webrev for it: > http://cr.openjdk.java.net/~alexsch/8029339/webrev.05/ > - the Toolkit related API is moved to the separate issue > > Could you review the current fix: > http://cr.openjdk.java.net/~alexsch/8029339/webrev.05/ > >> 2. What kinds of classes are expected to implement MultiResolutionImage >> Application ones or platform ones ? > Both. > - Application: A developer can provide a set of images with > different resolutions to create a multi-resolution image. An image > with best-fitting resolution > will be drawn on HiDPI display. > - Platform: we used it to support Aqua L&F on HiDPI displays. > >> 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. > > Could we postpone it to the CCC request? > >> >> 4. public List 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 ? > > Here are some usages from the JDK code: > - AquaImagefactory.getAppIconCompositedOn(final Image background) > The original multi-resolution image is used to create another > multi-resolution image with the background > - AquaUtils.generateLightenedImage(Image image, ImageFilter filter) > The original multi-resolution image is used to create lightening > multi-resolution image > - CImage.createFromImage(final Image image) > Resolution variants from a multi-resolution image are used to > create an NSImage > - CCustomCursor: it is possible set a custom cursor which > contains resolution variants to the native system > > Usually the getResolutionVariants() method is used to create one > multi-resolution image based on the another multi-resolution image. > >> 5. Why is the rendering hint needed ? > Someone can manually switch off the multi-resolution image > drawing from graphics so only the base image will be drawn. > It is useful for the performance reason. There is a choice to > draw the high-resolution image slowly or the low-resolution image faster. > > Thanks, > Alexandr. >> -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 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 Image createMRImage(final RVChooser rvChooser, >>>>>>>>> final Type baseImageSeed, final Function>>>>>>>> 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 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 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 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 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 >>>>>>>>>>>>>>> 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 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 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 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 >>>>>>>>>>>>>>>>>>>>>>> getResolutionVariants() { >>>>>>>>>>>>>>>>>>>>>>> return Arrays.asList(this, >>>>>>>>>>>>>>>>>>>>>>> highResolutionImage); >>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>> --------------------- >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> The current fix adds the MultiResolutionImage >>>>>>>>>>>>>>>>>>>>>>> interface >>>>>>>>>>>>>>>>>>>>>>> and >>>>>>>>>>>>>>>>>>>>>>> public >>>>>>>>>>>>>>>>>>>>>>> resolution variant rendering hints. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>> Alexandr. >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>> >>>>>>>>> >>>>>>> >>>>> >>>> >>> >> > From harshman+javadev at gmail.com Sun Jun 8 06:56:50 2014 From: harshman+javadev at gmail.com (Chris Harshman) Date: Sat, 7 Jun 2014 23:56:50 -0700 Subject: 10.10 installation fails Message-ID: Not sure where to send this? Fired up Yosemite DP. Opened Terminal. Typed 'java' and was sent (via "More Info") to the OpenJDK download page. Downloaded JDK 8 Update 05. Mounted the image. Double-clicked the installer: *Java from Oracle requires Mac OS X 10.7.3 or later.* Your system has Mac OS X Version 10.10. This product can be installed on Version 10.7.3 or later. Visit java.com/help for more information. From dalibor.topic at oracle.com Sun Jun 8 09:22:01 2014 From: dalibor.topic at oracle.com (Dalibor Topic) Date: Sun, 08 Jun 2014 11:22:01 +0200 Subject: 10.10 installation fails In-Reply-To: References: Message-ID: <53942B39.7010203@oracle.com> On 6/8/14 8:56 AM, Chris Harshman wrote: > Not sure where to send this? Fired up Yosemite DP. Opened Terminal. Typed > 'java' and was sent (via "More Info") to the OpenJDK download page. > Downloaded JDK 8 Update 05. Mounted the image. Double-clicked the installer: > > *Java from Oracle requires Mac OS X 10.7.3 or later.* > > Your system has Mac OS X Version 10.10. This product can be installed on > Version 10.7.3 or later. Visit java.com/help for more information. > That issue is being tracked at https://bugs.openjdk.java.net/browse/JDK-8027686 cheers, dalibor topic -- Oracle Dalibor Topic | Principal Product Manager Phone: +494089091214 | Mobile: +491737185961 Oracle Java Platform Group ORACLE Deutschland B.V. & Co. KG | K?hneh?fe 5 | 22761 Hamburg ORACLE Deutschland B.V. & Co. KG Hauptverwaltung: Riesstr. 25, D-80992 M?nchen Registergericht: Amtsgericht M?nchen, HRA 95603 Gesch?ftsf?hrer: J?rgen Kunz Komplement?rin: ORACLE Deutschland Verwaltung B.V. Hertogswetering 163/167, 3543 AS Utrecht, Niederlande Handelsregister der Handelskammer Midden-Niederlande, Nr. 30143697 Gesch?ftsf?hrer: Alexander van der Ven, Astrid Kepper, Val Maher Green Oracle Oracle is committed to developing practices and products that help protect the environment From philip.race at oracle.com Mon Jun 9 21:07:26 2014 From: philip.race at oracle.com (Phil Race) Date: Mon, 09 Jun 2014 14:07:26 -0700 Subject: [OpenJDK 2D-Dev] [9] Review request for 8029339 Custom MultiResolution image support on HiDPI displays In-Reply-To: <538F2D56.80609@oracle.com> References: <52D51764.8020103@oracle.com> <52DF2F98.3030503@oracle.com> <52F4BCEB.9040702@oracle.com> <52F5782A.9060300@oracle.com> <52FB7E3E.6050000@oracle.com> <52FC14EC.9080503@oracle.com> <53037D3D.80709@oracle.com> <5307E71E.50607@oracle.com> <530F3592.40600@oracle.com> <532B00AD.1000704@oracle.com> <532B7EC5.9000206@oracle.com> <532C4DD7.1080804@oracle.com> <532CD202.5070508@oracle.com> <53302A8E.6090107@oracle.com> <53343914.6090004@oracle.com> <533C8DDB.5000406@oracle.com> <533E9D42.10409@oracle.com> <53598D86.5020607@oracle.com> <535A7509.6050802@oracle.com> <5370DC41.5080608@oracle.com> <537639D5.9000206@oracle.com> <53764700.2060309@oracle.com> <5379E117.6010202@oracle.com> <538F2D56.80609@oracle.com> Message-ID: <5396220E.9030708@oracle.com> Why the split ? If you look only at the first part. If you can do that then why is the 2nd part needed ? The name "MultiResolutionImage" implies to me that this is a sub-class of Image. But its not, its a way to get images. AbstractMultiResolutionImage, however is a subclass and it implements the former. I am supposing (since you don't explain) that you want an Image sub-class here so that the app can specify it where ever an Image is currently accepted by API and the API that is "aware" can accept it. I worry about the memory cost of all of this. Can the the implementation be "lazy"? ie even if I call getResolutionVariants() do those images all have to be fully initialised before they are used? It looks like the app probably has to do so .. Also it precludes being able to return "on demand" an image that is rendered to be exactly the size requested. That could be created, drawn using graphics primitives and created precisely and only if needed. Instead we have an API that requires you to apparentlty eagerly create even the highest res image when you are on a device that has no need for it. Who will actually call getResolutionVariants() ? Is it us (the implementation) because we don't trust the app to make the right selection based on the parameterised call getResolutionVariant() ? Which approach do we use to pick the image ? If its the former, the app controls it, if its the latter its us. But which ? I am still stuck on the parameters to getResolutionVariant * @param baseImageWidth the width of the base image. Isn't the base image always the smallest ? Why are we, the caller, supposed to say what that size to the class that has that image. So I'd really like to see the example of that method in CustomMultiResolutionImage filled out so we can see what is imagined here .. Based solely on the usage I see here, its not clear why MultiResolutionImage needs to separately exist. what would implement MultiResolutionImage except for a class that extends AbstractMultiResolutionImage ? Where would you use a straight implementation of MultiResolutionImage ? Actually I am not sure you answered Jim's question as to who is requesting these APIs. "The AWT team" doesn't need them as they won't be writing the apps. If the 99% use case will be to provide a way for apps to provide images at custom sizes then we seem to be making them write new code. SFAIK FX found a way to do something similar to what OS X and Windows do which is to load based on file name convention. If we can do that, we load just the one we need. Is the point of use so far removed from the loading logic that we can't do this ? And none of this seems to help anyone who calls new BufferedImage(w, h, type) .. BTW I am not sold on the need for the RenderingHint. Where did the idea come from ? It would affect all rendering using that graphics instance, not just a specific image and if someone doesn't want a MultiRes image used, then maybe they just don't provide one .. In any case, without a solid demonstrated need I would not add the API. -phil. On 6/4/2014 7:29 AM, Alexander Scherbatiy wrote: > > Hi Phil, > > Could you review the fix where only new MultiResolutionImage > interface and AbstractMultiResolutionImage class are added: > http://cr.openjdk.java.net/~alexsch/8029339/webrev.05/ > > Thanks, > Alexandr. > > > On 5/19/2014 2:46 PM, Alexander Scherbatiy wrote: >> >> Hi Phil, >> >> On 5/16/2014 9:12 PM, Phil Race wrote: >>> 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 ? >> It was decided to split the original issue on two parts: >> - this fix adds only MultiResolutionImage interface and >> AbstractMultiResolutionImage class. >> Here is the webrev for it: >> http://cr.openjdk.java.net/~alexsch/8029339/webrev.05/ >> - the Toolkit related API is moved to the separate issue >> >> Could you review the current fix: >> http://cr.openjdk.java.net/~alexsch/8029339/webrev.05/ >> >>> 2. What kinds of classes are expected to implement MultiResolutionImage >>> Application ones or platform ones ? >> Both. >> - Application: A developer can provide a set of images with >> different resolutions to create a multi-resolution image. An image >> with best-fitting resolution >> will be drawn on HiDPI display. >> - Platform: we used it to support Aqua L&F on HiDPI displays. >> >>> 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. >> >> Could we postpone it to the CCC request? >> >>> >>> 4. public List 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 ? >> >> Here are some usages from the JDK code: >> - AquaImagefactory.getAppIconCompositedOn(final Image background) >> The original multi-resolution image is used to create another >> multi-resolution image with the background >> - AquaUtils.generateLightenedImage(Image image, ImageFilter filter) >> The original multi-resolution image is used to create >> lightening multi-resolution image >> - CImage.createFromImage(final Image image) >> Resolution variants from a multi-resolution image are used to >> create an NSImage >> - CCustomCursor: it is possible set a custom cursor which >> contains resolution variants to the native system >> >> Usually the getResolutionVariants() method is used to create one >> multi-resolution image based on the another multi-resolution image. >> >>> 5. Why is the rendering hint needed ? >> Someone can manually switch off the multi-resolution image >> drawing from graphics so only the base image will be drawn. >> It is useful for the performance reason. There is a choice to >> draw the high-resolution image slowly or the low-resolution image >> faster. >> >> Thanks, >> Alexandr. >>> -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 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 Image createMRImage(final RVChooser >>>>>>>>>> rvChooser, >>>>>>>>>> final Type baseImageSeed, final Function>>>>>>>>> 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 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 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 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 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 >>>>>>>>>>>>>>>> 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 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 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 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 >>>>>>>>>>>>>>>>>>>>>>>> getResolutionVariants() { >>>>>>>>>>>>>>>>>>>>>>>> return Arrays.asList(this, >>>>>>>>>>>>>>>>>>>>>>>> highResolutionImage); >>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>> --------------------- >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> The current fix adds the MultiResolutionImage >>>>>>>>>>>>>>>>>>>>>>>> interface >>>>>>>>>>>>>>>>>>>>>>>> and >>>>>>>>>>>>>>>>>>>>>>>> public >>>>>>>>>>>>>>>>>>>>>>>> resolution variant rendering hints. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>> Alexandr. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>> >>>>>>>> >>>>>> >>>>> >>>> >>> >> > From alexandr.scherbatiy at oracle.com Tue Jun 10 14:37:00 2014 From: alexandr.scherbatiy at oracle.com (Alexander Scherbatiy) Date: Tue, 10 Jun 2014 18:37:00 +0400 Subject: [OpenJDK 2D-Dev] [9] Review request for 8029339 Custom MultiResolution image support on HiDPI displays In-Reply-To: <5396220E.9030708@oracle.com> References: <52D51764.8020103@oracle.com> <52DF2F98.3030503@oracle.com> <52F4BCEB.9040702@oracle.com> <52F5782A.9060300@oracle.com> <52FB7E3E.6050000@oracle.com> <52FC14EC.9080503@oracle.com> <53037D3D.80709@oracle.com> <5307E71E.50607@oracle.com> <530F3592.40600@oracle.com> <532B00AD.1000704@oracle.com> <532B7EC5.9000206@oracle.com> <532C4DD7.1080804@oracle.com> <532CD202.5070508@oracle.com> <53302A8E.6090107@oracle.com> <53343914.6090004@oracle.com> <533C8DDB.5000406@oracle.com> <533E9D42.10409@oracle.com> <53598D86.5020607@oracle.com> <535A7509.6050802@oracle.com> <5370DC41.5080608@oracle.com> <537639D5.9000206@oracle.com> <53764700.2060309@oracle.com> <5379E117.6010202@oracle.com> <538F2D56.80609@oracle.com> <5396220E.9030708@oracle.com> Message-ID: <5397180C.5040105@oracle.com> On 6/10/2014 1:07 AM, Phil Race wrote: > Why the split ? > If you look only at the first part. If you can do that then why is the > 2nd part needed ? The second part introduces algorithms that can be used to retrieve a resolution variant from a set of images. It can be DPI based, transform based, OS based and so on. The first part can be implemented without the second part. > The name "MultiResolutionImage" implies to me that this is a sub-class > of Image. > But its not, its a way to get images. AbstractMultiResolutionImage, > however is > a subclass and it implements the former. Could you suggest the better name? It really needs to have an interface if existed image implementation is supposed to have resolution variants. The example which is used in JDK is ToolkitImage. Toolkit.getImage(filename) method returns ToolkitImage which is loaded by demand. LWCToolkit should return an image with resolution variants on Mac OS X if both image and image at 2x are provided. What we need here is the ToolkitImage that contains resolution variants. It can be done if the MultiResolutionImage is an interface and it is not possible to do if MultiResolutionImage is a class. Here is the MultiResolutionToolkitImage implementation: http://hg.openjdk.java.net/jdk9/client/jdk/file/b7ef5e2d252c/src/share/classes/sun/awt/image/MultiResolutionToolkitImage.java > I am supposing (since you don't explain) that you want an Image > sub-class here > so that the app can specify it where ever an Image is currently > accepted by API > and the API that is "aware" can accept it. If an image implements the MultiResolutionImage interface, SunGraphics2D can use it to draw an image with necessary resolution on HiDPI display. > I worry about the memory cost of all of this. Can the the > implementation be "lazy"? Yes. See the MultiResolutionCachedImage implementation: http://hg.openjdk.java.net/jdk9/client/jdk/file/b7ef5e2d252c/src/share/classes/sun/awt/image/MultiResolutionCachedImage.java > ie even if I call getResolutionVariants() do those images all have to > be fully initialised before > they are used? It looks like the app probably has to do so .. If it needs to pass resolution variants to the native system like setting a custom cursor on Mac OS X it really needs to initialize all resolution variants. If it needs to create one multi-resolution image based on another multi-resolution image like generating a lightening image using a filter, it possible to do this lazy. See the map(Function mapper) method in the MultiResolutionCachedImage. SunGraphics2D class uses only getResolutionVariant( ...) method to retrieve necessary resolution variant. It does not call getResolutionVariants() methods so all resolution variants are not created during image drawing. > > Also it precludes being able to return "on demand" an image that is > rendered to > be exactly the size requested. That could be created, drawn using > graphics primitives > and created precisely and only if needed. > > Instead we have an API that requires you to apparentlty eagerly create > even the > highest res image when you are on a device that has no need for it. > > Who will actually call getResolutionVariants() ? Both. > Is it us (the implementation) because we We use it to create an NSImage from a custom cursor. See Toolkit.createCustomCursor() and CImage.createFromImage(final Image image) methods. Developers can use it to show all resolution variants in some image tool. > don't trust the app to make the right selection based on the > parameterised call > getResolutionVariant() ? As it shown, the getResolutionVariant(...) and getResolutionVariants() methods are used for different purposes. getResolutionVariant(...) method is used by SunGraphics2D class to pickup an image with necessary resolution variant. getResolutionVariants() method is used when an application needs to use all resolution variants. > > Which approach do we use to pick the image ? If its the former, the > app controls it, It is the former. We also use it MR-ToolkitImage to get a resolution variant according to the current system (for example, transforms are included to get resolution variant size on Mac OS X). > if its the latter its us. But which ? > > I am still stuck on the parameters to getResolutionVariant > > * @param baseImageWidth the width of the base image. > > > Isn't the base image always the smallest ? No for general case. May be it would be possible to print a multi-resolution image on a printer that can have low DPI. > Why are we, the caller, supposed > to say what that size to the class that has that image. This question has already had long discussion. The answer is that we do it because it is free for us. SunGraphics2D already gets the base image size because it uses it for resolution image size calculation. If you have objections against this, let's remove the base image size parameters. Developer always can obtain this information calling getWidth()/Height() methods. > So I'd really like to see the example of that method in > CustomMultiResolutionImage > filled out so we can see what is imagined here .. Below are two samples. The first one loads a multi-resolution image from disk, and writes text "Hello World!" on it. Only getResolutionVariant(...) method is used by system in SunGraphics2D. The getResolutionVariants() method is not used. The second one creates a lightened custom cursor. The getResolutionVariants() method is called by system to create NSImage with necessary image representations. Note that Toolkit.getImage(filename) method is already able to load both image and image at 2x images on Mac OS X. Sample 1. Draw an image with "Hello World!" text: disk: duke.png, duke at 2x.png ------------------------------- public static void main(String[] args) { Image image = Toolkit.getDefaultToolkit().getImage("duke.png"); // duke.png and duke at 2x.png images are loaded by MR-ToolkitImage Image imagewithText = image instanceof MultiResolutionImage ? new TextMultiresolutionImage(image) : drawText(image); Graphics2D g2d = // get graphics 2D g2d.drawImage(imagewithText, x, y, null); } static Image drawText(Image image) { // return an image with "Hello World!" text } static class TextMultiresolutionImage extends AbstractMultiResolutionImage { private final Image baseImage; public TextMultiresolutionImage(Image baseImage) { this.baseImage = baseImage; } @Override public Image getResolutionVariant(float destImageWidth, float destImageHeight) { Image rvImage = ((MultiResolutionImage) baseImage). getResolutionVariant(destImageWidth, destImageHeight); return drawText(rvImage); } // this method is not used by SunGraphics2D to draw the image @Override public List getResolutionVariants() { List resolutionvariants = new LinkedList<>(); for (Image image : ((MultiResolutionImage) baseImage). getResolutionVariants()) { resolutionvariants.add(drawText(image)); } return resolutionvariants; } @Override protected Image getBaseImage() { return drawText(baseImage); } } ------------------------------- Sample 2. Using filters to create a lightened custom cursor. ------------------------------- public static void main(String[] args) { Image image = Toolkit.getDefaultToolkit().getImage("cursor.png"); // cursor.png and cursor at 2x.png files are provided Image lightenedImage = image instanceof MultiResolutionImage ? new LigtenedMultiresolutionImage(image) : applyFilter(image); Cursor lightenedCursor = Toolkit.getDefaultToolkit(). createCustomCursor(lightenedImage, new Point(0, 0), "Lightened Cursor"); JFrame frame = new JFrame("Frame with lightened cursor"); frame.setCursor(lightenedCursor); } static Image applyFilter(Image image) { // apply a filter to create ligtened image } static class LigtenedMultiresolutionImage extends AbstractMultiResolutionImage { private final Image baseImage; public LigtenedMultiresolutionImage(Image baseImage) { this.baseImage = baseImage; } @Override public Image getResolutionVariant(float destImageWidth, float destImageHeight) { Image rvImage = ((MultiResolutionImage) baseImage). getResolutionVariant(destImageWidth, destImageHeight); return applyFilter(rvImage); } // all resolution variants are created to pass them to NSImage @Override public List getResolutionVariants() { List resolutionvariants = new LinkedList<>(); for (Image image : ((MultiResolutionImage) baseImage). getResolutionVariants()) { resolutionvariants.add(applyFilter(image)); } return resolutionvariants; } @Override protected Image getBaseImage() { return applyFilter(baseImage); } } ------------------------------- > > Based solely on the usage I see here, its not clear why > MultiResolutionImage needs > to separately exist. what would implement MultiResolutionImage except for > a class that extends AbstractMultiResolutionImage ? Where would you use > a straight implementation of MultiResolutionImage ? See sun.awt.image.MultiResolutionToolkitImage in JDK 9. Both ToolkitImage and MultiResolutionImage should be used in this case. > > Actually I am not sure you answered Jim's question as to who is > requesting these APIs. > "The AWT team" doesn't need them as they won't be writing the apps. 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 > > If the 99% use case will be to provide a way for apps to provide > images at custom sizes > then we seem to be making them write new code. SFAIK FX found a way to > do something > similar to what OS X and Windows do which is to load based on file > name convention. JDK 8 have already loaded images with @2x name convention on Mac OS X. See the fix for the issue JDK-8011059 [macosx] Support automatic @2x images loading on Mac OS X https://bugs.openjdk.java.net/browse/JDK-8011059 > If we can do that, we load just the one we need. Is the point > of use so far removed from the loading logic that we can't do this ? Mac OS X has both ways to create images: using @2x name convention for files and NSImage with methods addRepresentation/removeRepresentation/representations. The current API is proposed to dial with images that can have source that is different from files. It is also used to process already loaded images. See the provided two samples with lightened custom cursor and text on image. Is it possible to write the same samples on JavaFX? > And none of this seems to help anyone who calls new BufferedImage(w, > h, type) .. Yes. It needs to create a BufferedImage for each screen resolution and put them to a multi-resolution image. > > BTW I am not sold on the need for the RenderingHint. Where did the > idea come from ? > It would affect all rendering using that graphics instance, not just a > specific image and > if someone doesn't want a MultiRes image used, then maybe they just > don't provide one .. KEY_RESOLUTION_VARIANT is used to switch on/off resolution variants usage. VALUE_RESOLUTION_VARIANT_ON - SunGraphics2D queries resolution variants from multi-resolution image on HiDPI displays. VALUE_RESOLUTION_VARIANT_OFF - SunGraphics2D does not use resolution variants. Only base image is used. > In any case, without a solid demonstrated need I would not add the API. > See provided 2 samples. Thanks, Alexandr. > > -phil. > > On 6/4/2014 7:29 AM, Alexander Scherbatiy wrote: >> >> Hi Phil, >> >> Could you review the fix where only new MultiResolutionImage >> interface and AbstractMultiResolutionImage class are added: >> http://cr.openjdk.java.net/~alexsch/8029339/webrev.05/ >> >> Thanks, >> Alexandr. >> >> >> On 5/19/2014 2:46 PM, Alexander Scherbatiy wrote: >>> >>> Hi Phil, >>> >>> On 5/16/2014 9:12 PM, Phil Race wrote: >>>> 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 ? >>> It was decided to split the original issue on two parts: >>> - this fix adds only MultiResolutionImage interface and >>> AbstractMultiResolutionImage class. >>> Here is the webrev for it: >>> http://cr.openjdk.java.net/~alexsch/8029339/webrev.05/ >>> - the Toolkit related API is moved to the separate issue >>> >>> Could you review the current fix: >>> http://cr.openjdk.java.net/~alexsch/8029339/webrev.05/ >>> >>>> 2. What kinds of classes are expected to implement >>>> MultiResolutionImage >>>> Application ones or platform ones ? >>> Both. >>> - Application: A developer can provide a set of images with >>> different resolutions to create a multi-resolution image. An image >>> with best-fitting resolution >>> will be drawn on HiDPI display. >>> - Platform: we used it to support Aqua L&F on HiDPI displays. >>> >>>> 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. >>> >>> Could we postpone it to the CCC request? >>> >>>> >>>> 4. public List 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 ? >>> >>> Here are some usages from the JDK code: >>> - AquaImagefactory.getAppIconCompositedOn(final Image background) >>> The original multi-resolution image is used to create another >>> multi-resolution image with the background >>> - AquaUtils.generateLightenedImage(Image image, ImageFilter filter) >>> The original multi-resolution image is used to create >>> lightening multi-resolution image >>> - CImage.createFromImage(final Image image) >>> Resolution variants from a multi-resolution image are used >>> to create an NSImage >>> - CCustomCursor: it is possible set a custom cursor which >>> contains resolution variants to the native system >>> >>> Usually the getResolutionVariants() method is used to create one >>> multi-resolution image based on the another multi-resolution image. >>> >>>> 5. Why is the rendering hint needed ? >>> Someone can manually switch off the multi-resolution image >>> drawing from graphics so only the base image will be drawn. >>> It is useful for the performance reason. There is a choice to >>> draw the high-resolution image slowly or the low-resolution image >>> faster. >>> >>> Thanks, >>> Alexandr. >>>> -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 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 Image createMRImage(final RVChooser >>>>>>>>>>> rvChooser, >>>>>>>>>>> final Type baseImageSeed, final Function>>>>>>>>>> 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 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 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 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 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 >>>>>>>>>>>>>>>>> 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 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 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 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 >>>>>>>>>>>>>>>>>>>>>>>>> getResolutionVariants() { >>>>>>>>>>>>>>>>>>>>>>>>> return Arrays.asList(this, >>>>>>>>>>>>>>>>>>>>>>>>> highResolutionImage); >>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>> --------------------- >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> The current fix adds the >>>>>>>>>>>>>>>>>>>>>>>>> MultiResolutionImage interface >>>>>>>>>>>>>>>>>>>>>>>>> and >>>>>>>>>>>>>>>>>>>>>>>>> public >>>>>>>>>>>>>>>>>>>>>>>>> resolution variant rendering hints. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>> Alexandr. >>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>> >>>>>>> >>>>>> >>>>> >>>> >>> >> > From alexandr.scherbatiy at oracle.com Wed Jun 11 15:18:57 2014 From: alexandr.scherbatiy at oracle.com (Alexander Scherbatiy) Date: Wed, 11 Jun 2014 19:18:57 +0400 Subject: [OpenJDK 2D-Dev] [9] Review request for 8029339 Custom MultiResolution image support on HiDPI displays In-Reply-To: <5397180C.5040105@oracle.com> References: <52D51764.8020103@oracle.com> <52DF2F98.3030503@oracle.com> <52F4BCEB.9040702@oracle.com> <52F5782A.9060300@oracle.com> <52FB7E3E.6050000@oracle.com> <52FC14EC.9080503@oracle.com> <53037D3D.80709@oracle.com> <5307E71E.50607@oracle.com> <530F3592.40600@oracle.com> <532B00AD.1000704@oracle.com> <532B7EC5.9000206@oracle.com> <532C4DD7.1080804@oracle.com> <532CD202.5070508@oracle.com> <53302A8E.6090107@oracle.com> <53343914.6090004@oracle.com> <533C8DDB.5000406@oracle.com> <533E9D42.10409@oracle.com> <53598D86.5020607@oracle.com> <535A7509.6050802@oracle.com> <5370DC41.5080608@oracle.com> <537639D5.9000206@oracle.com> <53764700.2060309@oracle.com> <5379E117.6010202@oracle.com> <538F2D56.80609@oracle.com> <5396220E.9030708@oracle.com> <5397180C.5040105@oracle.com> Message-ID: <53987361.5040903@oracle.com> Hi Phil , I just prepared a simple FAQ about the Custom MultiResolution image API. Hope it will be helpful. 1. Scale naming convention for high-resolution images. Different OSes use different "scale" naming convention for high-resolution images: Mac OS X: image.ext, image at 2x.ext Windows: image.scale-100.ext, image.scale-140.ext, image.scale-180.ext Q: Does "scale" naming convention supported in JDK? A: Mac OS X "scale" naming convention are supported in JDK 8u20 (see JDK-8011059) It is planned to support the Windows "scale" naming convention as well. Q. How does it work in JDK? A. Bundle image.ext and image at 2x.ext images with your app on Mac OS X and call Toolkit.getImage(...) method: Image image = Toolkit.getDefaultToolkit().getImage("image.ext"); Graphics2D g2d = // get graphics g2d.drawImage(image, 0, 0, null) SunGraphics2D automatically queries and draws the provided high-resolution image. Q: There are different "scale" naming conventions on Mac OS X and Windows. May be it is better to have unified "scale" naming conventions for all OSes in Java like image[java-scale-Nx].ext? A: It seems reasonable and can be filled as a new JDK enhancement. Q: Does using "scale" naming conventions solves all problems. A: There are tasks like image processing/programmatically generated images/loading images from non-standard sources that can't be solved with predefined set of images. Q: Are there any tools that support these tasks? A: Cocoa API contains NSImage that allows to work with image representations: addRepresentation/removeRepresentation/representations JDK uses these methods to get/set multi-resolution images for the Native system (see sun.lwawt.macosx.CImage class). 2. Graphics2D Q: How SunGraphics2D deals with multi-resolution images? A: SunGraphics2D queries a resolution variant using DPI scale factors and transformed base image sizes // logicalDPIX, logicalDPIY - DPI scale factors // destImageWidth, destImageHeight - transformed base image sizes including DPI scale factors multiResolutionImage.getResolutionVariant(logicalDPIX, logicalDPIY, destImageWidth, destImageHeight); Q: Which algorithm multi-resolution image is used in getResolutionVariant(...) method? A: ToolkitImage returned by toolkit.loadImage() method should behave like the native system. It means that it should use transformed image sizes on Mac OS X and only DPI scale factors on Windows. it looks like: ----------------- // logicalDPIX, logicalDPIY - DPI scale factors // destImageWidth, destImageHeight - transformed base image sizes including DPI scale factors public Image getResolutionVariant(float logicalDPIX, float logicalDPIY, float destImageWidth, float destImageHeight) { if (Mac OS X) { return resolution variant best fitted to the destImageWidth and destImageHeight } else if (Windows){ return resolution variant best fitted to the logicalDPIX and logicalDPIY scale factors } } ----------------- 3. Custom multi-resolution image. Q: The custom multi-resolution image should be able to return an image according to the requested transformed image size and DPI scale factors. Is it enough? A: There are task like setting custom cursor that require to get all resolution variants. So the custom multi-resolution image should also contain the getResolutionVariants(): Q: Should the custom multi-resolution image be class or interface? A: There is ToolkitImage that should also have resolution variants. It is not possible to extend it from MultiResolutionImage class. The current proposal introduces the MultiResolutionImage as an interface. Q: MultiResolutionImage interface sounds strange for me. A: The better name can be suggested. Q: What does the Custom MultiResolution image API suggest? A: The current proposal provides MultiResolutionImage interface with the following methods: --------------------------- Image getResolutionVariant(float logicalDPIX, float logicalDPIY, float destImageWidth, float destImageHeight); List getResolutionVariants(); --------------------------- and AbstractMultiResolutionImage class. See samples below. 4. Memory cost Q: Can the the implementation be "lazy"? A: SunGraphics2D does not require full list of resolution variants. It queries only the image with necessary resolution. It means that resolution variants can be loaded by demand. Setting a custom cursor requires all resolution variants. 5. Rendering hints. Q: Why rendering hints are added. A: Provided rendering hints affects only multi-resolution images and allows to disable resolution variants usage in app. It can be useful for performance reasons. 6. Samples. Q: It is interesting to look at samples. A: Below are 3 samples: 1. Draw an image with "Hello World!" text 2. Set a lightened custom cursor 3. Draw a multi-resolution image created from the program Sample 1. Draw a image with "Hello World!" text. The text is drawn both on the base image and on high-resolution image. disk: duke.png, duke at 2x.png ------------------------------- public static void main(String[] args) { Image image = Toolkit.getDefaultToolkit().getImage("duke.png"); // duke.png and duke at 2x.png images are loaded by MR-ToolkitImage Image imagewithText = image instanceof MultiResolutionImage ? new TextMultiresolutionImage(image) : drawText(image); Graphics2D g2d = // get graphics 2D g2d.drawImage(imagewithText, x, y, null); } static Image drawText(Image image) { // return an image with "Hello World!" text } static class TextMultiresolutionImage extends AbstractMultiResolutionImage { private final Image baseImage; public TextMultiresolutionImage(Image baseImage) { this.baseImage = baseImage; } @Override public Image getResolutionVariant(float logicalDPIX, float logicalDPIY, float destImageWidth, float destImageHeight) { Image rvImage = ((MultiResolutionImage) baseImage). getResolutionVariant(logicalDPIX, logicalDPIY, destImageWidth, destImageHeight); return drawText(rvImage); } @Override public List getResolutionVariants() { // this method is not used by SunGraphics2D to draw the image. // we just skip it in this example } @Override protected Image getBaseImage() { return drawText(baseImage); } } ------------------------------- Sample 2. Using filters to create a lightened custom cursor. The filter is applied to both the base and high-resolution image. ------------------------------- public static void main(String[] args) { Image image = Toolkit.getDefaultToolkit().getImage("cursor.png"); // cursor.png and cursor at 2x.png files are provided Image lightenedImage = image instanceof MultiResolutionImage ? new LigtenedMultiresolutionImage(image) : applyFilter(image); Cursor lightenedCursor = Toolkit.getDefaultToolkit(). createCustomCursor(lightenedImage, new Point(0, 0), "Lightened Cursor"); JFrame frame = new JFrame("Frame with lightened cursor"); frame.setCursor(lightenedCursor); } static Image applyFilter(Image image) { GrayFilter filter = new GrayFilter(true, 50); final ImageProducer prod = new FilteredImageSource(image.getSource(), filter); return Toolkit.getDefaultToolkit().createImage(prod); } static class LigtenedMultiresolutionImage extends AbstractMultiResolutionImage { private final Image baseImage; public LigtenedMultiresolutionImage(Image baseImage) { this.baseImage = baseImage; } @Override public Image getResolutionVariant(float logicalDPIX, float logicalDPIY, float destImageWidth, float destImageHeight) { // this method is not necessary for the custom cursor creation // we just skip it } // all resolution variants are created to pass them to NSImage for the custom cursor on Mac OS X. @Override public List getResolutionVariants() { List resolutionVariants = new LinkedList<>(); for (Image rvImage : ((MultiResolutionImage) baseImage). getResolutionVariants()) { resolutionVariants.add(applyFilter(rvImage)); } return resolutionVariants; } @Override protected Image getBaseImage() { return applyFilter(baseImage); } } ------------------------------- Sample 3. Draw a multi-resolution image created from the program: ------------------------------- public static void main(String[] args) { Image image = generateImage(1); Image image2x = generateImage(2); Image mrImage = new CustomMultiresolutionImage(image, image2x); Graphics2D g2d = // get graphics2D g2d.drawImage(mrImage, 0, 0, null); } static Image generateImage(float scaleFactor) { // generate image according to the scale factor } static class CustomMultiresolutionImage extends AbstractMultiResolutionImage { private final Image image; private final Image highResolutionImage; public CustomMultiresolutionImage(Image baseImage, Image highResolutionImage) { this.image = baseImage; this.highResolutionImage = highResolutionImage; } @Override public Image getResolutionVariant(float logicalDPIX, float logicalDPIY, float destImageWidth, float destImageHeight) { // destImageWidth and destImageHeight includes both transforms // DPI scale factors from Graphics if (destImageWidth <= image.getWidth(null) && destImageHeight <= image.getHeight(null)) { return image; } return highResolutionImage; } @Override public List getResolutionVariants() { return Arrays.asList(image, highResolutionImage); } @Override protected Image getBaseImage() { return image; } } ------------------------------- Thanks, Alexandr. On 6/10/2014 6:37 PM, Alexander Scherbatiy wrote: > On 6/10/2014 1:07 AM, Phil Race wrote: >> Why the split ? >> If you look only at the first part. If you can do that then why is >> the 2nd part needed ? > The second part introduces algorithms that can be used to retrieve > a resolution variant > from a set of images. It can be DPI based, transform based, OS > based and so on. > The first part can be implemented without the second part. > >> The name "MultiResolutionImage" implies to me that this is a >> sub-class of Image. >> But its not, its a way to get images. AbstractMultiResolutionImage, >> however is >> a subclass and it implements the former. > > Could you suggest the better name? It really needs to have an > interface if existed image implementation > is supposed to have resolution variants. The example which is used > in JDK is ToolkitImage. > Toolkit.getImage(filename) method returns ToolkitImage which is > loaded by demand. > LWCToolkit should return an image with resolution variants on Mac > OS X if both image and image at 2x > are provided. What we need here is the ToolkitImage that contains > resolution variants. > It can be done if the MultiResolutionImage is an interface and it > is not possible to do if MultiResolutionImage is a class. > Here is the MultiResolutionToolkitImage implementation: > http://hg.openjdk.java.net/jdk9/client/jdk/file/b7ef5e2d252c/src/share/classes/sun/awt/image/MultiResolutionToolkitImage.java > > >> I am supposing (since you don't explain) that you want an Image >> sub-class here >> so that the app can specify it where ever an Image is currently >> accepted by API >> and the API that is "aware" can accept it. > If an image implements the MultiResolutionImage interface, > SunGraphics2D can use it > to draw an image with necessary resolution on HiDPI display. > >> I worry about the memory cost of all of this. Can the the >> implementation be "lazy"? > Yes. See the MultiResolutionCachedImage implementation: > http://hg.openjdk.java.net/jdk9/client/jdk/file/b7ef5e2d252c/src/share/classes/sun/awt/image/MultiResolutionCachedImage.java > >> ie even if I call getResolutionVariants() do those images all have to >> be fully initialised before >> they are used? It looks like the app probably has to do so .. > If it needs to pass resolution variants to the native system like > setting a custom cursor on Mac OS X > it really needs to initialize all resolution variants. > > If it needs to create one multi-resolution image based on another > multi-resolution image like > generating a lightening image using a filter, it possible to do > this lazy. > See the map(Function mapper) method in the > MultiResolutionCachedImage. > > SunGraphics2D class uses only getResolutionVariant( ...) method to > retrieve necessary resolution variant. > It does not call getResolutionVariants() methods so all resolution > variants are not created during image drawing. > >> >> Also it precludes being able to return "on demand" an image that is >> rendered to >> be exactly the size requested. That could be created, drawn using >> graphics primitives >> and created precisely and only if needed. >> >> Instead we have an API that requires you to apparentlty eagerly >> create even the >> highest res image when you are on a device that has no need for it. >> >> Who will actually call getResolutionVariants() ? > Both. >> Is it us (the implementation) because we > We use it to create an NSImage from a custom cursor. See > Toolkit.createCustomCursor() > and CImage.createFromImage(final Image image) methods. > > Developers can use it to show all resolution variants in some image > tool. > >> don't trust the app to make the right selection based on the >> parameterised call >> getResolutionVariant() ? > As it shown, the getResolutionVariant(...) and > getResolutionVariants() methods are used > for different purposes. > getResolutionVariant(...) method is used by SunGraphics2D class to > pickup an image > with necessary resolution variant. > getResolutionVariants() method is used when an application needs to > use all resolution variants. > >> >> Which approach do we use to pick the image ? If its the former, the >> app controls it, > It is the former. > We also use it MR-ToolkitImage to get a resolution variant > according to the current system (for example, transforms > are included to get resolution variant size on Mac OS X). > >> if its the latter its us. But which ? >> >> I am still stuck on the parameters to getResolutionVariant >> >> * @param baseImageWidth the width of the base image. >> >> >> Isn't the base image always the smallest ? > No for general case. May be it would be possible to print a > multi-resolution image > on a printer that can have low DPI. > >> Why are we, the caller, supposed >> to say what that size to the class that has that image. > > This question has already had long discussion. The answer is that > we do it because it is free for us. > SunGraphics2D already gets the base image size because it uses it > for resolution image size calculation. > If you have objections against this, let's remove the base image > size parameters. > Developer always can obtain this information calling > getWidth()/Height() methods. > >> So I'd really like to see the example of that method in >> CustomMultiResolutionImage >> filled out so we can see what is imagined here .. > > Below are two samples. > The first one loads a multi-resolution image from disk, and writes > text "Hello World!" on it. Only getResolutionVariant(...) method is used > by system in SunGraphics2D. The getResolutionVariants() method is > not used. > > The second one creates a lightened custom cursor. The > getResolutionVariants() method is called by system to create NSImage > with necessary image representations. > > Note that Toolkit.getImage(filename) method is already able to load > both image and image at 2x images on Mac OS X. > > Sample 1. Draw an image with "Hello World!" text: > disk: duke.png, duke at 2x.png > ------------------------------- > public static void main(String[] args) { > > Image image = > Toolkit.getDefaultToolkit().getImage("duke.png"); // duke.png and > duke at 2x.png images are loaded by MR-ToolkitImage > > Image imagewithText = image instanceof MultiResolutionImage > ? new TextMultiresolutionImage(image) : drawText(image); > > Graphics2D g2d = // get graphics 2D > g2d.drawImage(imagewithText, x, y, null); > } > > static Image drawText(Image image) { > // return an image with "Hello World!" text > } > > static class TextMultiresolutionImage extends > AbstractMultiResolutionImage { > > private final Image baseImage; > > public TextMultiresolutionImage(Image baseImage) { > this.baseImage = baseImage; > } > > @Override > public Image getResolutionVariant(float destImageWidth, float > destImageHeight) { > Image rvImage = ((MultiResolutionImage) baseImage). > getResolutionVariant(destImageWidth, > destImageHeight); > return drawText(rvImage); > } > > // this method is not used by SunGraphics2D to draw the image > @Override > public List getResolutionVariants() { > List resolutionvariants = new LinkedList<>(); > for (Image image : ((MultiResolutionImage) baseImage). > getResolutionVariants()) { > resolutionvariants.add(drawText(image)); > } > return resolutionvariants; > } > > @Override > protected Image getBaseImage() { > return drawText(baseImage); > } > } > ------------------------------- > > Sample 2. Using filters to create a lightened custom cursor. > ------------------------------- > public static void main(String[] args) { > > Image image = > Toolkit.getDefaultToolkit().getImage("cursor.png"); // cursor.png and > cursor at 2x.png files are provided > Image lightenedImage = image instanceof MultiResolutionImage > ? new LigtenedMultiresolutionImage(image) : > applyFilter(image); > > Cursor lightenedCursor = Toolkit.getDefaultToolkit(). > createCustomCursor(lightenedImage, new Point(0, 0), > "Lightened Cursor"); > JFrame frame = new JFrame("Frame with lightened cursor"); > frame.setCursor(lightenedCursor); > } > > static Image applyFilter(Image image) { > // apply a filter to create ligtened image > } > > static class LigtenedMultiresolutionImage extends > AbstractMultiResolutionImage { > > private final Image baseImage; > > public LigtenedMultiresolutionImage(Image baseImage) { > this.baseImage = baseImage; > } > > @Override > public Image getResolutionVariant(float destImageWidth, float > destImageHeight) { > Image rvImage = ((MultiResolutionImage) baseImage). > getResolutionVariant(destImageWidth, > destImageHeight); > return applyFilter(rvImage); > } > > // all resolution variants are created to pass them to NSImage > @Override > public List getResolutionVariants() { > List resolutionvariants = new LinkedList<>(); > for (Image image : ((MultiResolutionImage) baseImage). > getResolutionVariants()) { > resolutionvariants.add(applyFilter(image)); > } > return resolutionvariants; > } > > @Override > protected Image getBaseImage() { > return applyFilter(baseImage); > } > } > ------------------------------- >> >> Based solely on the usage I see here, its not clear why >> MultiResolutionImage needs >> to separately exist. what would implement MultiResolutionImage except >> for >> a class that extends AbstractMultiResolutionImage ? Where would you use >> a straight implementation of MultiResolutionImage ? > See sun.awt.image.MultiResolutionToolkitImage in JDK 9. Both > ToolkitImage and MultiResolutionImage should be used in this case. > >> >> Actually I am not sure you answered Jim's question as to who is >> requesting these APIs. >> "The AWT team" doesn't need them as they won't be writing the apps. > > 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 > >> >> If the 99% use case will be to provide a way for apps to provide >> images at custom sizes >> then we seem to be making them write new code. SFAIK FX found a way >> to do something >> similar to what OS X and Windows do which is to load based on file >> name convention. > JDK 8 have already loaded images with @2x name convention on Mac > OS X. > See the fix for the issue JDK-8011059 [macosx] Support automatic > @2x images loading on Mac OS X > https://bugs.openjdk.java.net/browse/JDK-8011059 >> If we can do that, we load just the one we need. Is the point >> of use so far removed from the loading logic that we can't do this ? > > Mac OS X has both ways to create images: using @2x name convention > for files > and NSImage with methods > addRepresentation/removeRepresentation/representations. > > The current API is proposed to dial with images that can have > source that is different from files. > It is also used to process already loaded images. > See the provided two samples with lightened custom cursor and text > on image. > Is it possible to write the same samples on JavaFX? > >> And none of this seems to help anyone who calls new BufferedImage(w, >> h, type) .. > > Yes. It needs to create a BufferedImage for each screen resolution > and put them to a multi-resolution image. > >> >> BTW I am not sold on the need for the RenderingHint. Where did the >> idea come from ? >> It would affect all rendering using that graphics instance, not just >> a specific image and >> if someone doesn't want a MultiRes image used, then maybe they just >> don't provide one .. > > KEY_RESOLUTION_VARIANT is used to switch on/off resolution > variants usage. > VALUE_RESOLUTION_VARIANT_ON - SunGraphics2D queries resolution > variants from multi-resolution image on HiDPI displays. > VALUE_RESOLUTION_VARIANT_OFF - SunGraphics2D does not use > resolution variants. Only base image is used. > >> In any case, without a solid demonstrated need I would not add the API. >> > See provided 2 samples. > > Thanks, > Alexandr. >> >> -phil. >> >> On 6/4/2014 7:29 AM, Alexander Scherbatiy wrote: >>> >>> Hi Phil, >>> >>> Could you review the fix where only new MultiResolutionImage >>> interface and AbstractMultiResolutionImage class are added: >>> http://cr.openjdk.java.net/~alexsch/8029339/webrev.05/ >>> >>> Thanks, >>> Alexandr. >>> >>> >>> On 5/19/2014 2:46 PM, Alexander Scherbatiy wrote: >>>> >>>> Hi Phil, >>>> >>>> On 5/16/2014 9:12 PM, Phil Race wrote: >>>>> 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 ? >>>> It was decided to split the original issue on two parts: >>>> - this fix adds only MultiResolutionImage interface and >>>> AbstractMultiResolutionImage class. >>>> Here is the webrev for it: >>>> http://cr.openjdk.java.net/~alexsch/8029339/webrev.05/ >>>> - the Toolkit related API is moved to the separate issue >>>> >>>> Could you review the current fix: >>>> http://cr.openjdk.java.net/~alexsch/8029339/webrev.05/ >>>> >>>>> 2. What kinds of classes are expected to implement >>>>> MultiResolutionImage >>>>> Application ones or platform ones ? >>>> Both. >>>> - Application: A developer can provide a set of images with >>>> different resolutions to create a multi-resolution image. An image >>>> with best-fitting resolution >>>> will be drawn on HiDPI display. >>>> - Platform: we used it to support Aqua L&F on HiDPI displays. >>>> >>>>> 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. >>>> >>>> Could we postpone it to the CCC request? >>>> >>>>> >>>>> 4. public List 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 ? >>>> >>>> Here are some usages from the JDK code: >>>> - AquaImagefactory.getAppIconCompositedOn(final Image background) >>>> The original multi-resolution image is used to create >>>> another multi-resolution image with the background >>>> - AquaUtils.generateLightenedImage(Image image, ImageFilter >>>> filter) >>>> The original multi-resolution image is used to create >>>> lightening multi-resolution image >>>> - CImage.createFromImage(final Image image) >>>> Resolution variants from a multi-resolution image are used >>>> to create an NSImage >>>> - CCustomCursor: it is possible set a custom cursor which >>>> contains resolution variants to the native system >>>> >>>> Usually the getResolutionVariants() method is used to create >>>> one multi-resolution image based on the another multi-resolution >>>> image. >>>> >>>>> 5. Why is the rendering hint needed ? >>>> Someone can manually switch off the multi-resolution image >>>> drawing from graphics so only the base image will be drawn. >>>> It is useful for the performance reason. There is a choice to >>>> draw the high-resolution image slowly or the low-resolution image >>>> faster. >>>> >>>> Thanks, >>>> Alexandr. >>>>> -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 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 Image createMRImage(final RVChooser >>>>>>>>>>>> rvChooser, >>>>>>>>>>>> final Type baseImageSeed, final Function>>>>>>>>>>> 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 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 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 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 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 >>>>>>>>>>>>>>>>>> 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 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 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 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 >>>>>>>>>>>>>>>>>>>>>>>>>> getResolutionVariants() { >>>>>>>>>>>>>>>>>>>>>>>>>> return Arrays.asList(this, >>>>>>>>>>>>>>>>>>>>>>>>>> highResolutionImage); >>>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>>>>>>>>> --------------------- >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> The current fix adds the >>>>>>>>>>>>>>>>>>>>>>>>>> MultiResolutionImage interface >>>>>>>>>>>>>>>>>>>>>>>>>> and >>>>>>>>>>>>>>>>>>>>>>>>>> public >>>>>>>>>>>>>>>>>>>>>>>>>> resolution variant rendering hints. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>>>>>>>>>>>> Alexandr. >>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>> >>>>>>>> >>>>>>> >>>>>> >>>>> >>>> >>> >> > From dkocher at sudo.ch Fri Jun 13 08:31:36 2014 From: dkocher at sudo.ch (David Kocher) Date: Fri, 13 Jun 2014 10:31:36 +0200 Subject: Bug in apple.security.KeychainStore provider Message-ID: <285E9EC3-45B5-48E2-8FEF-A135E4F403AC@sudo.ch> (I haven?t found a way to register on bugs.openjdk.java.net and file a bug, therefore posting it here). There is a bug in the native KeystoreImpl that it only searches for identities that have a key usage of ?Any? using CSSM_KEYUSE_ANY instead of passing `0` to the SecIdentitySearchCreate keychain function. Refer to line 282 in [1]. This will exclude all identities that have a specific key usage set such as ?Encrypt, Verify, Wrap, Derive?. [1] http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/macosx/native/apple/security/KeystoreImpl.m I have also found issues with instances of KeyEntry that have an empty array for the ?chain? property causing index out of bounds exceptions. See attached patch. -------------- next part -------------- - David From weijun.wang at oracle.com Fri Jun 13 08:50:39 2014 From: weijun.wang at oracle.com (Wang Weijun) Date: Fri, 13 Jun 2014 16:50:39 +0800 Subject: Bug in apple.security.KeychainStore provider In-Reply-To: <285E9EC3-45B5-48E2-8FEF-A135E4F403AC@sudo.ch> References: <285E9EC3-45B5-48E2-8FEF-A135E4F403AC@sudo.ch> Message-ID: Hi David I don't understand what it is but I've created a bug for you: https://bugs.openjdk.java.net/browse/JDK-8046777 BTW, I see no patch. I'm also not sure if this "also found issues" is related to the main bug. Thanks Max On Jun 13, 2014, at 16:31, David Kocher wrote: > (I haven?t found a way to register on bugs.openjdk.java.net and file a bug, therefore posting it here). > > > There is a bug in the native KeystoreImpl that it only searches for identities that have a key usage of ?Any? using CSSM_KEYUSE_ANY instead of passing `0` to the SecIdentitySearchCreate keychain function. Refer to line 282 in [1]. This will exclude all identities that have a specific key usage set such as ?Encrypt, Verify, Wrap, Derive?. > > > [1] http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/macosx/native/apple/security/KeystoreImpl.m > > I have also found issues with instances of KeyEntry that have an empty array for the ?chain? property causing index out of bounds exceptions. See attached patch. > > > > - > David From mik3hall at gmail.com Fri Jun 13 08:52:57 2014 From: mik3hall at gmail.com (Michael Hall) Date: Fri, 13 Jun 2014 03:52:57 -0500 Subject: Bug in apple.security.KeychainStore provider In-Reply-To: <285E9EC3-45B5-48E2-8FEF-A135E4F403AC@sudo.ch> References: <285E9EC3-45B5-48E2-8FEF-A135E4F403AC@sudo.ch> Message-ID: On Jun 13, 2014, at 3:31 AM, David Kocher wrote: > I have also found issues with instances of KeyEntry that have an empty array for the ?chain? property causing index out of bounds exceptions. See attached patch. It might just be me but I'm not seeing an attachment. Michael Hall trz nio.2 for OS X http://www195.pair.com/mik3hall/index.html#trz HalfPipe Java 6/7 shell app http://www195.pair.com/mik3hall/index.html#halfpipe AppConverter convert Apple jvm to openjdk apps http://www195.pair.com/mik3hall/index.html#appconverter From Alan.Bateman at oracle.com Sat Jun 21 09:30:45 2014 From: Alan.Bateman at oracle.com (Alan Bateman) Date: Sat, 21 Jun 2014 10:30:45 +0100 Subject: Can jdk/src/macosx/native/jobjc be deleted? Message-ID: <53A550C5.6020400@oracle.com> JObjC was dropped from the build in JDK 8, it was dropped in a JDK 7 update too. The remnants of it were removed from the build via JDK-8033111 in jdk9-b03 but the dead code in the jdk/src/macosx/native/jobjc was not removed. Is there any reason to keep it around in the JDK 9 forest? -Alan. From zsoakes at gmail.com Tue Jun 24 15:40:57 2014 From: zsoakes at gmail.com (Zach Oakes) Date: Tue, 24 Jun 2014 11:40:57 -0400 Subject: Spawning a new process from a sandboxed app Message-ID: I've successfully shipped Java apps on the MAS using an embedded JRE, but with the stricter signing requirements now in place, I'm having a problem. My script now signs all the binaries, including the JRE's jspawnhelper executable, which my app relies on to spawn new processes via Runtime.exec. The sandboxed app launches correctly, but when it tries launching a new process, I get a dialog saying "OS X needs to repair your Library to run applications". It then fails to spawn the process, and the console says "Sandbox creation failed: Container object initialization failed: failed to get bundleid for app "/Contents/PlugIns/jdk1.7.0_60.jdk/Contents/Home/jre/lib/jspawnhelper". I can't figure out why it is failing to get the bundleid for jspawnhelper. It is definitely being signed with codesign, and I've tried explicitly setting an --identifier to no avail. I would appreciate advice on how to resolve this. From danno.ferrin at oracle.com Tue Jun 24 15:44:01 2014 From: danno.ferrin at oracle.com (Danno Ferrin) Date: Tue, 24 Jun 2014 09:44:01 -0600 Subject: Spawning a new process from a sandboxed app In-Reply-To: References: Message-ID: <523CFA2B-1CE7-4127-9852-D732CBAEF272@oracle.com> What entitlements did you sign spawnhelper with? The same as the main app or the inherit permission? On Jun 24, 2014, at 9:40 AM, Zach Oakes wrote: > I've successfully shipped Java apps on the MAS using an embedded JRE, but > with the stricter signing requirements now in place, I'm having a problem. > My script now signs all the binaries, including the JRE's jspawnhelper > executable, which my app relies on to spawn new processes via Runtime.exec. > > The sandboxed app launches correctly, but when it tries launching a new > process, I get a dialog saying "OS X needs to repair your Library to run > applications". It then fails to spawn the process, and the console says > "Sandbox creation failed: Container object initialization failed: failed to > get bundleid for app > "/Contents/PlugIns/jdk1.7.0_60.jdk/Contents/Home/jre/lib/jspawnhelper". > > I can't figure out why it is failing to get the bundleid for jspawnhelper. > It is definitely being signed with codesign, and I've tried explicitly > setting an --identifier to no avail. I would appreciate advice on how to > resolve this. From zsoakes at gmail.com Tue Jun 24 15:52:33 2014 From: zsoakes at gmail.com (Zach Oakes) Date: Tue, 24 Jun 2014 11:52:33 -0400 Subject: Spawning a new process from a sandboxed app In-Reply-To: <523CFA2B-1CE7-4127-9852-D732CBAEF272@oracle.com> References: <523CFA2B-1CE7-4127-9852-D732CBAEF272@oracle.com> Message-ID: I signed with the same entitlements as the main app. Apple auto-rejects my submission if jspawnhelper doesn't at least have the app-sandbox entitlement. I haven't tried signing it with nothing but the inherit permission, though, so I'll try that right now. On Tue, Jun 24, 2014 at 11:44 AM, Danno Ferrin wrote: > What entitlements did you sign spawnhelper with? The same as the main app > or the inherit permission? > > On Jun 24, 2014, at 9:40 AM, Zach Oakes wrote: > > > I've successfully shipped Java apps on the MAS using an embedded JRE, but > > with the stricter signing requirements now in place, I'm having a > problem. > > My script now signs all the binaries, including the JRE's jspawnhelper > > executable, which my app relies on to spawn new processes via > Runtime.exec. > > > > The sandboxed app launches correctly, but when it tries launching a new > > process, I get a dialog saying "OS X needs to repair your Library to run > > applications". It then fails to spawn the process, and the console says > > "Sandbox creation failed: Container object initialization failed: failed > to > > get bundleid for app > > > "/Contents/PlugIns/jdk1.7.0_60.jdk/Contents/Home/jre/lib/jspawnhelper". > > > > I can't figure out why it is failing to get the bundleid for > jspawnhelper. > > It is definitely being signed with codesign, and I've tried explicitly > > setting an --identifier to no avail. I would appreciate advice on how to > > resolve this. > > From zsoakes at gmail.com Tue Jun 24 16:50:26 2014 From: zsoakes at gmail.com (Zach Oakes) Date: Tue, 24 Jun 2014 12:50:26 -0400 Subject: Spawning a new process from a sandboxed app In-Reply-To: <523CFA2B-1CE7-4127-9852-D732CBAEF272@oracle.com> References: <523CFA2B-1CE7-4127-9852-D732CBAEF272@oracle.com> Message-ID: It looks like that worked, thanks! I ended up creating a separate entitlements file for jspawnhelper which looks like this: com.apple.security.app-sandbox com.apple.security.inherit On Tue, Jun 24, 2014 at 11:44 AM, Danno Ferrin wrote: > What entitlements did you sign spawnhelper with? The same as the main app > or the inherit permission? > > On Jun 24, 2014, at 9:40 AM, Zach Oakes wrote: > > > I've successfully shipped Java apps on the MAS using an embedded JRE, but > > with the stricter signing requirements now in place, I'm having a > problem. > > My script now signs all the binaries, including the JRE's jspawnhelper > > executable, which my app relies on to spawn new processes via > Runtime.exec. > > > > The sandboxed app launches correctly, but when it tries launching a new > > process, I get a dialog saying "OS X needs to repair your Library to run > > applications". It then fails to spawn the process, and the console says > > "Sandbox creation failed: Container object initialization failed: failed > to > > get bundleid for app > > > "/Contents/PlugIns/jdk1.7.0_60.jdk/Contents/Home/jre/lib/jspawnhelper". > > > > I can't figure out why it is failing to get the bundleid for > jspawnhelper. > > It is definitely being signed with codesign, and I've tried explicitly > > setting an --identifier to no avail. I would appreciate advice on how to > > resolve this. > > From danno.ferrin at oracle.com Tue Jun 24 16:52:44 2014 From: danno.ferrin at oracle.com (Danno Ferrin) Date: Tue, 24 Jun 2014 10:52:44 -0600 Subject: Spawning a new process from a sandboxed app In-Reply-To: References: <523CFA2B-1CE7-4127-9852-D732CBAEF272@oracle.com> Message-ID: Lucky guess. This validates my choice to use the inherit permission for all but the main .app in the java packager Mac App Store Ready bundler. What you describe is already being automatically be done in 8u20. Now I know it makes a difference. Thanks for the update. ?Danno On Jun 24, 2014, at 10:50 AM, Zach Oakes wrote: > It looks like that worked, thanks! I ended up creating a separate entitlements file for jspawnhelper which looks like this: > > > > > > com.apple.security.app-sandbox > > com.apple.security.inherit > > > > > > On Tue, Jun 24, 2014 at 11:44 AM, Danno Ferrin wrote: > What entitlements did you sign spawnhelper with? The same as the main app or the inherit permission? > > On Jun 24, 2014, at 9:40 AM, Zach Oakes wrote: > > > I've successfully shipped Java apps on the MAS using an embedded JRE, but > > with the stricter signing requirements now in place, I'm having a problem. > > My script now signs all the binaries, including the JRE's jspawnhelper > > executable, which my app relies on to spawn new processes via Runtime.exec. > > > > The sandboxed app launches correctly, but when it tries launching a new > > process, I get a dialog saying "OS X needs to repair your Library to run > > applications". It then fails to spawn the process, and the console says > > "Sandbox creation failed: Container object initialization failed: failed to > > get bundleid for app > > "/Contents/PlugIns/jdk1.7.0_60.jdk/Contents/Home/jre/lib/jspawnhelper". > > > > I can't figure out why it is failing to get the bundleid for jspawnhelper. > > It is definitely being signed with codesign, and I've tried explicitly > > setting an --identifier to no avail. I would appreciate advice on how to > > resolve this. > > From ajgregory at gmail.com Wed Jun 25 22:08:27 2014 From: ajgregory at gmail.com (AJ Gregory) Date: Wed, 25 Jun 2014 15:08:27 -0700 Subject: Toolkit.sync() Message-ID: Hello.... I'm looking for a way to make sure window updates have made it on screen. Does this do anything in the Mac implementation? Toolkit.getDefaultToolkit().sync(); If not is there some way (in java or jni code) to make sure any window paints have happened on screen and aren't still queued? Thanks! -Aj From anthony.petrov at oracle.com Thu Jun 26 10:05:15 2014 From: anthony.petrov at oracle.com (Anthony Petrov) Date: Thu, 26 Jun 2014 14:05:15 +0400 Subject: Toolkit.sync() In-Reply-To: References: Message-ID: <53ABF05B.9010307@oracle.com> There's no way to detect this with 100% certainty. On any platform. Toolkit.sync() is harmless and probably worth calling after your final Window.setVisible(true) call. However, this method doesn't do much. There's several workarounds though. You may want to Thread.sleep() for a while (like a second or two) after calling Window.setVisible(true). Note that sleep()'ing should be done on a secondary thread, not EDT! Another approach is to override Window.paint() and/or update() methods and assume that after they've been invoked, your window is on the screen already. Again, neither of these methods ensure this. Personally, I feel that sleep() is the most reliable way to go. Note that GUI regression tests in JDK do use the sleep() approach, although they also call some non-public APIs to help it (I'm talking about the SunToolkit.realSync() method). However, even this private API does NOT guarantee anything. Note that I don't suggest you to use this private API because it is not supported and may be removed at any time. Also, you won't be able to use it in applets or web-start applications that are executed in a sandbox. -- best regards, Anthony On 6/26/2014 2:08 AM, AJ Gregory wrote: > Hello.... > > I'm looking for a way to make sure window updates have made it on screen. > > Does this do anything in the Mac implementation? > Toolkit.getDefaultToolkit().sync(); > > If not is there some way (in java or jni code) to make sure any window > paints have happened on screen and aren't still queued? > > Thanks! > -Aj > From david.dehaven at oracle.com Fri Jun 27 14:10:58 2014 From: david.dehaven at oracle.com (David DeHaven) Date: Fri, 27 Jun 2014 07:10:58 -0700 Subject: JavaAppLauncher Message-ID: <4C17A649-C279-4007-AD6A-53650E30361B@oracle.com> Is anyone using JavaAppLauncher in jdk/src/macosx/bundle/JavaAppLauncher? I'm going to be posting a review to remove it and the associated Java source as it's completely unused in the JDK (and hence does not belong there). If you want to continue to use it, then you'll need to fork it and maintain it yourself, or switch to Java packager which is a better option these days anyways. -DrD- From mik3hall at gmail.com Fri Jun 27 22:11:44 2014 From: mik3hall at gmail.com (Michael Hall) Date: Fri, 27 Jun 2014 17:11:44 -0500 Subject: JavaAppLauncher In-Reply-To: <4C17A649-C279-4007-AD6A-53650E30361B@oracle.com> References: <4C17A649-C279-4007-AD6A-53650E30361B@oracle.com> Message-ID: <98B8F706-8A91-4E8F-B6B0-BA70F1DAE26C@gmail.com> I might keep in mind there is still? https://bitbucket.org/infinitekind/appbundler I would assume any JavaAppLauncher executables would continue to work for now as they have up to now and will until? sometime later when someone finally does something to break them. I'd be interested in looking at Java packager when I get chance. Michael Hall trz nio.2 for OS X http://www195.pair.com/mik3hall/index.html#trz HalfPipe Java 6/7 shell app http://www195.pair.com/mik3hall/index.html#halfpipe AppConverter convert Apple jvm to openjdk apps http://www195.pair.com/mik3hall/index.html#appconverter From david.dehaven at oracle.com Sat Jun 28 00:39:28 2014 From: david.dehaven at oracle.com (David DeHaven) Date: Fri, 27 Jun 2014 17:39:28 -0700 Subject: JavaAppLauncher In-Reply-To: <98B8F706-8A91-4E8F-B6B0-BA70F1DAE26C@gmail.com> References: <4C17A649-C279-4007-AD6A-53650E30361B@oracle.com> <98B8F706-8A91-4E8F-B6B0-BA70F1DAE26C@gmail.com> Message-ID: > I might keep in mind there is still? > https://bitbucket.org/infinitekind/appbundler If it's truly a fork of AppBundler then it doesn't use it. AppBundler has it's own launcher code, the executable it produces is also called JavaAppLauncher (and may have been based on this). The Java class uses a different package, so it doesn't rely on JavaAppLauncher in rt.jar. I've yet to find any actual uses of JavaAppLauncher... it was part of the initial port but the native portion is not built (except for the native methods in apple.launcher.JavaAppLauncher which is in osxlib.dylib). None of it has been touched since then except to change copyright dates. -DrD- From mik3hall at gmail.com Sat Jun 28 01:23:25 2014 From: mik3hall at gmail.com (Michael Hall) Date: Fri, 27 Jun 2014 20:23:25 -0500 Subject: JavaAppLauncher In-Reply-To: References: <4C17A649-C279-4007-AD6A-53650E30361B@oracle.com> <98B8F706-8A91-4E8F-B6B0-BA70F1DAE26C@gmail.com> Message-ID: On Jun 27, 2014, at 7:39 PM, David DeHaven wrote: > >> I might keep in mind there is still? >> https://bitbucket.org/infinitekind/appbundler > > If it's truly a fork of AppBundler then it doesn't use it. AppBundler has it's own launcher code, the executable it produces is also called JavaAppLauncher (and may have been based on this). The Java class uses a different package, so it doesn't rely on JavaAppLauncher in rt.jar. > > I've yet to find any actual uses of JavaAppLauncher... it was part of the initial port but the native portion is not built (except for the native methods in apple.launcher.JavaAppLauncher which is in osxlib.dylib). None of it has been touched since then except to change copyright dates. As I remember there was an early port version of JavaAppLauncher that was supported by Mike Swingler. I may have a copy pulled of that somewhere. Then there was the Scott Kovatch and Greg Brown AppBundler project which came out with an Oracle sponsored version of JavaAppLauncher. The infinitekind project was forked off of that. If you are referring to the first pass Mike Swingler supported code I would say there is probably no use of that by anyone at this point, except maybe the copy I pulled which I'm not even using. Mike Swingler could probably tell you more. Michael Hall trz nio.2 for OS X http://www195.pair.com/mik3hall/index.html#trz HalfPipe Java 6/7 shell app http://www195.pair.com/mik3hall/index.html#halfpipe AppConverter convert Apple jvm to openjdk apps http://www195.pair.com/mik3hall/index.html#appconverter