[OpenJDK 2D-Dev] <AWT Dev> [8] Review request for 8011059 [macosx] Make JDK demos look perfect on retina displays
Alexander Scherbatiy
alexandr.scherbatiy at oracle.com
Thu Nov 21 05:41:59 PST 2013
On 11/20/2013 3:17 PM, Jim Graham wrote:
> In looking through the ToolkitImage code some more it occurs to me
> that it was already designed (moreso in a previous life) to hold onto
> multiple representations of the image anyway. In a prior life in 1.0
> and 1.1 it held separate ImageRepresentation objects for each size it
> was scaled to (via drawImage(w,h)), but that was simplified to a
> single ImageRep when we converted to Java2D and started doing scaling
> on the fly for all drawImage() operations. Still, the concept of an
> alternate resolution version of the image is probably more in line
> with the ImageRepresentation object within the ToolkitImage than in
> having multiple ToolkitImage objects and a wrapper for them.
>
> This would also deal more naturally with the ImageObserver issue since
> there really would be only one Image and SG2D would not deal with the
> sub-representations, it would be dealt with in the DrawImage pipeline
> code when it queries the ToolkitImage for the ImageRepresentation object.
>
> In the end, I think that design would be simpler overall, would it be
> possible to shift those gears for this fix? If not, we should
> consider it for a near-term future cleanup task perhaps...
I think that it would be better to postpone this cleanup to a
near-term future task.
Thanks,
Alexandr.
>
> ...jim
>
> On 11/19/2013 7:58 PM, Jim Graham wrote:
>> Based on the information below, I have the following suggestions...
>>
>> We should probably allow asynchronous loading of the scaled
>> resolution variants. This is a minor variation of what the
>> ImageObserver was originally designed for, but technically might
>> violate some developer's expectations if they have only dealt with a
>> post-Java2D version of Java. Some education might be helpful here.
>>
>> The wording on drawImage(dxy12, sxy12) should probably be reworded to
>> indicate that asynchronous scaling would not happen, but alternate
>> versions of the image may be accessed.
>>
>> In all cases, if the version of the image that we would ideally want
>> to show hasn't been loaded, but the standard version has (or if @2x
>> was loaded, but we want the regular version too?) then we should
>> probably go with the version that was loaded, but still trigger the
>> loading of the alternate version and notify their Observer as it is
>> loaded.
>>
>> I also examined the places in the code where we notify the
>> ImageObserver. A search for the observer method should show all
>> places we call it, but the primary ones look like they are fairly few
>> places. If we tag the resolution variant images with the composite
>> image from which they came, then we can have those few places do
>> something like:
>>
>> Image obsimg = (img instanceof SunToolkitImage) ? (()
>> img).getObservedImage() : img;
>>
>> I think in most cases the img is already known to be our internal
>> SunToolkit image and so we don't even need to check instanceof...
>>
>> ...jim
>>
>> On 11/19/2013 7:01 PM, Jim Graham wrote:
>>> I did some more reading about the various ways in which the
>>> ImageObserver is used and noticed the following points, some of
>>> which may be to our advantage.
>>>
>>> Many of the drawImage() calls mention that they will notify the
>>> observer as the image is "scaled or converted for the output
>>> device". I believe in the world before 2D, we would often have to
>>> load or convert the image asynchronously for various changes in the
>>> output. When we created the 2D interface and added some on-the-fly
>>> image scaling code, we mentioned that scaling was no longer
>>> asynchronous, but technically the API is still designed for
>>> asynchronous operations when the rendering parameters change.
>>>
>>> However, the drawImage() call that takes 8 parameters dxy12, sxy12 -
>>> specifically includes the words:
>>>
>>> * This method always uses the unscaled version of the image
>>> * to render the scaled rectangle and performs the required
>>> * scaling on the fly. It does not use a cached, scaled version
>>> * of the image for this operation. Scaling of the image from
>>> source
>>> * to destination is performed such that the first coordinate
>>> * of the source rectangle is mapped to the first coordinate of
>>> * the destination rectangle, and the second source coordinate is
>>> * mapped to the second destination coordinate. The subimage is
>>> * scaled and flipped as needed to preserve those mappings.
>>> public abstract boolean drawImage(Image img,
>>> int dx1, int dy1, int dx2,
>>> int dy2,
>>> int sx1, int sy1, int sx2,
>>> int sy2,
>>> ImageObserver observer);
>>>
>>> which basically, at the time it was created in 1.1, was an opt "out"
>>> of the asynchronous operations that might happen when you scaled an
>>> image with drawImage(xywh). As worded, this would suggest that this
>>> method does not use the @2x version and always uses the default
>>> resolution version, but those words were not put there for this
>>> particular intent, they were put there to indicate that we weren't
>>> going to do an off-line scaling of the pixels which sometimes
>>> happened in 1.0.x and possibly 1.1 (for the other calls that
>>> predated 1.1 until Java2D).
>>>
>>> I also found the Component.prepareImage() and Component.checkImage()
>>> methods which also take an ImageObserver. Those methods imply that
>>> they will possibly start the process and return information on a
>>> particular version of an image appropriate for the current output
>>> device. There is even a prepareImage(w,h) method that gets an image
>>> ready to render at the indicated size. Given that these methods are
>>> on component, it probably makes sense to have that code look up
>>> which representation would be used for those indicated dimensions on
>>> the indicated output device that the Component is displayed on.
>>>
>>> ...jim
>>>
More information about the macosx-port-dev
mailing list