On Sun, 4 Oct 2026 09:31:42 GMT, John Hendrikx <[email protected]> wrote:

>> This PR adds a `getDrawingContext` method to `WritableImage`, which works 
>> similar to `Canvas::getGraphicsContext` and shares the same signatures. Key 
>> features include:
>> 
>> - **Shape rendering**: `strokeRect`, `fillRect`, `strokeOval`, `fillOval`, 
>> `strokeArc`, `fillArc`, `strokePolyline`, `fillPolygon`, etc.
>> - **Stroke and fill attributes**: `lineWidth`, `lineCap`, `lineJoin`, 
>> `miterLimit`, `fillRule`, `stroke` and `fill` paints.
>> - **Global graphics settings**: `globalAlpha` and `globalBlendMode`.
>> - **Image drawing**: draw other `Image` instances with scaling and 
>> source/destination rectangles.
>> - **Text rendering**: render text
>> - **Save/Restore**: store current stroke, font, dashes, etc and restore them 
>> later
>> - **Paths**: begin a path, with lines, curves, etc, then stroke or fill it
>> - **Clips**: support rectangular clips in the SW renderer
>> 
>> This feature enables direct software rendering to `WritableImage` without 
>> requiring a `Canvas` + snapshot.
>> 
>> **Additional notes**:
>> 
>> - The implementation leverages the software stack consisting of the Marlin 
>> rasterizer and Pisces compositor/painter.
>> 
>> **Example usage**:
>> 
>> 
>> WritableImage img = new WritableImage(400, 400);
>> DrawingContext ctx = img.getDrawingContext();
>> ctx.setFill(Color.RED);
>> ctx.fillRect(50, 50, 100, 100);
>> 
>> 
>> See the sample program `RandomShapesDemo` to see a `WritableImage` and 
>> `Canvas` side by side performing the same operations:
>> 
>> <img width="1249" height="741" alt="image" 
>> src="https://github.com/user-attachments/assets/4a0b9dcc-8f96-4faa-99cf-83c66d2c851e";
>>  />
>> 
>> Newer version:
>> 
>> <img width="1249" height="741" alt="image" 
>> src="https://github.com/user-attachments/assets/c0502620-3d02-4fbd-8c33-43bd5138b42c";
>>  />
>> 
>> ---------
>> - [x] I confirm that I make this contribution in accordance with the 
>> [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai).
>
> John Hendrikx has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Add implNote about known snapshot issue

Still some issues, see inline. 

I think the buffer endianness issue might warrant a unit test.

modules/javafx.graphics/src/main/java/com/sun/javafx/util/FXCleaner.java line 1:

> 1: package com.sun.javafx.util;

needs copyright header

modules/javafx.graphics/src/main/java/com/sun/javafx/util/FXCleaner.java line 
13:

> 11:  * Usage example:
> 12:  * <pre>
> 13:  *     FXCleaner.register(resource, () -> resource.dispose());

bad example: the lambda creates a strong reference to `resource`, so the 
cleaner action will never run.

modules/javafx.graphics/src/main/java/com/sun/prism/sw/SWDrawingContext.java 
line 1052:

> 1050:             return inversePath;
> 1051:         }
> 1052:         catch (NoninvertibleTransformException e) {

when this happens, the path will be unchanged.  graphics.fill() or .draw() will 
then apply the same non-invertable transform again, which contradicts 
DrawingContext:1414

modules/javafx.graphics/src/main/java/com/sun/prism/sw/SWDrawingContext.java 
line 1241:

> 1239:         // Ensure it's a Prism image
> 1240:         if (!(platformImage instanceof com.sun.prism.Image prismImage)) 
> {
> 1241:             throw new IllegalArgumentException("PlatformImage must be a 
> Prism Image");

a failed image (progress=1.0, platformImage=null) will throw here, but public 
`drawImage()` specifies not such failure.  should we check isError() and ignore?

modules/javafx.graphics/src/main/java/javafx/scene/image/DrawingContext.java 
line 1602:

> 1600:      * @param x position on the x axis.
> 1601:      * @param y position on the y axis.
> 1602:      * @param maxWidth the maximum width of the string; a value of zero 
> or

simply explaining away maxWidth<0 won't help, I think:
SWDrawingContext:1294 honors the rule and draws text, while 
GraphicsContext:1294 returns without drw=awing.

modules/javafx.graphics/src/main/java/javafx/scene/image/WritableImage.java 
line 181:

> 179:      *     format (for example, when created from a {@code 
> BYTE_BGRA_PRE} {@code PixelBuffer})
> 180:      */
> 181:     public final DrawingContext getDrawingContext() {

`@since 28`

modules/javafx.graphics/src/main/native-prism-sw/JDirectBufferSurface.c line 
140:

> 138:     }
> 139: 
> 140:     void* data = (*env)->GetDirectBufferAddress(env, 
> surface->dataHandle);

Will this fail when byte order of the direct buffer differs from the system 
byte order?

-------------

Changes requested by angorya (Reviewer).

PR Review: https://git.openjdk.org/jfx/pull/1969#pullrequestreview-5421134500
PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r4189452768
PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r4189528593
PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r4189336903
PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r4189448801
PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r4189358677
PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r4189458161
PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r4189310424

Reply via email to