On Fri, 21 Aug 2026 22:42:36 GMT, Andy Goryachev <[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. >> >> **New API for `GraphicsContext`** >> >> Because `GraphicsContext` was never designed to support a more generic API >> when it was conceived, it has gained a few new methods that were a better >> fit for the reusable `DrawingContext` interface: >> >> - `clipRect(x, y, w, h)` -- convenience equivalent to `rect(...)` + `clip()` >> - `getEffect()` -- no arg getter for the `Effect` >> - `getTextDirection()` and `setTextDirection(NodeOrientation)` -- takes >> precedence over `Canvas.getNodeOrientation()` when not set to `INHERIT` (the >> default) >> >> **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). > > The size argument is a good one. > > One last question: would it make more sense to update the `Canvas` instead to > remove the size limitation, instead of creating some parallel way of doing > the same thing, possibly introducing subtle and not so subtle differences? > > Another aspect: let's say we decide to go with two parallel APIs - should we > then make sure they mirror each other exactly? If so, would it create > another maintenance burden? @andy-goryachev-oracle I noticed that for Cursors, if the format is INT_ARGB_PRE, we just don't scale them at all. Now, it was already possible before (with your own PixelBuffer) to create a INT_ARGB_PRE image, and use that as cursor -- but platforms limit the size of their cursors, so passing INT based images through unscaled while scaling the BYTE based images seems like a pre-existing bug. Also, the scaling code (for both icons and cursors) is basically the same code repeated twice written in slightly different styles. I could extract that (making it also testable) and have both WindowStage and Cursors use it. That would also fix the missing scaling bug for cursors. That is also getting a bit out of scope for this PR, what do you think? ------------- PR Comment: https://git.openjdk.org/jfx/pull/1969#issuecomment-6374501890
