On Sun, 6 Sep 2026 22:27:53 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:
> 
>   Optimized dirty rect handling (benefits more than just SWDraingContext)

Here is the next batch of comments...

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

> 236:         }
> 237: 
> 238:         throw new IllegalStateException("image buffer is neither heap 
> array-backed nor direct");

Will `ByteBuffer.allocate().asIntBuffer()` be rejected?

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

> 978:         }
> 979: 
> 980:         path.setWindingRule(fillRule == FillRule.EVEN_ODD ? 
> Path2D.WIND_EVEN_ODD : Path2D.WIND_NON_ZERO);

this overwrites the current winding rule - it it compatible with the API spec 
in `DrawingContext` ?

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

> 980:         path.setWindingRule(fillRule == FillRule.EVEN_ODD ? 
> Path2D.WIND_EVEN_ODD : Path2D.WIND_NON_ZERO);
> 981: 
> 982:         graphics.setTransform(BaseTransform.IDENTITY_TRANSFORM);

will that work with non-uniform transform scaling or shear?
also, what would happen if an absolute gradient or image patterns are used?

can we add these cases to the test?

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

> 1003:          */
> 1004: 
> 1005:         double scale = Math.sqrt(transform.getMxx() * 
> transform.getMxx() + transform.getMyx() * transform.getMyx());

will it work correctly with a non-uniform scale?

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

> 1095: 
> 1096:     @Override
> 1097:     public void fillText(String text, double x, double y, double 
> maxWidth) {

what's the behavior of `fillText()` when `maxWidth` <= 0?

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

> 1204: 
> 1205:         // Ensure it's a Prism image
> 1206:         if (!(platformImage instanceof com.sun.prism.Image prismImage)) 
> {

`GraphicsContext::drawImage()` silently ignores a `null` image, should this 
method simply return instead of throwing an exception?

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

> 224:  *         <td class="colLast">
> 225:  *             The method used to determine the interior of paths for a 
> path fill or
> 226:  *            clip operation.

minor: bad indent

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

> 173:     public final DrawingContext getDrawingContext() {
> 174:         if (drawingContext == null) {
> 175:             drawingContext = 
> Toolkit.getToolkit().createDrawingContext(getWritablePlatformImage(), 
> this::notifyDrawingContextDirty);

`setPlatformImage()` L1086 can replace the platform image (as a result of 
`snapshot`, for instance).  this will disassociate the cached `drawingContext` 
from the platform image.

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

PR Review: https://git.openjdk.org/jfx/pull/1969#pullrequestreview-5283695099
PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r4076550428
PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r4076697519
PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r4076519801
PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r4076530789
PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r4076648763
PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r4076742281
PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r4076702229
PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r4076428807

Reply via email to