On Fri, 4 Sep 2026 22:17:44 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: > > Remove whitespace modules/javafx.graphics/src/main/java/javafx/scene/image/WritableImage.java line 177: > 175: if (drawingContext == null) { > 176: // note: there is only one implementation of PlatformImage > (by QuantumToolkit) so the hard cast here is safe > 177: drawingContext = new SWDrawingContext((com.sun.prism.Image) > getWritablePlatformImage(), rect -> bufferDirty(rect)); Multiple `WritableImage` instance can be backed by the same `PixelBuffer`, and `PixelBuffer.updateBuffer()` accounts for that fact by notifying all associated writable images. However, in this method, you're only invalidating the `WritableImage` from which the `DrawingContext` was obtained. This leaves all other writable images in a stale state. Maybe this could be solved by using the existing `PixelBuffer.updateBuffer()` logic if the image is backed by a `PixelBuffer`. modules/javafx.graphics/src/main/native-prism-sw/JJavaSurface.c line 163: > 161: > 162: surface->super.data = (void *)((jint *)surface->super.data + > 163: (*env)->GetIntField(env, surfaceHandle, > fieldIds[SURFACE_DATA_OFFSET])); This might violate the contract of [GetPrimitiveArrayCritical](https://docs.oracle.com/en/java/javase/26/docs/specs/jni/functions.html#getprimitivearraycritical-releaseprimitivearraycritical) in two ways: 1. "Inside a critical region, native code must not call other JNI functions", but you're calling `GetIntField`. 2. The pointer passed to `ReleasePrimitiveArrayCritical` must be the exact pointer as returned by `GetPrimitiveArrayCritical`, you can't do pointer arithmetic with it. A solution could be to read the data offset before entering the critical region, retain the original base pointer separately, use base + offset only as the renderer pointer, and then pass the base pointer to `ReleasePrimitiveArrayCritical`. ------------- PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r3939347932 PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r3939333162
