From 368208b1f6a713c5296d5b0bcc8a651c3b83a9ce Mon Sep 17 00:00:00 2001 From: DemchaAV Date: Sun, 14 Jun 2026 14:23:00 +0100 Subject: [PATCH] docs(api): correct stale Javadoc on the 1.8 surface - LegendPosition: drop the stale "reserved and rejected by validation" wording; RIGHT/TOP are laid out for every chart kind. - DocumentPaint: document why the Linear/Radial (angle/corner) and LinearAxis/RadialCircle (exact endpoint/radius) forms coexist. - ShapeContainerBuilder: the missing-outline error and class Javadoc now name the full set of outline setters, including path(...). - PathBuilder.dashed(double...): document the IllegalArgumentException it throws eagerly. - SvgIcon: document that a gradient href inherits stops only, not geometry. - CHANGELOG: sealed-permit binary-compat note on ShapeOutline.Path plus a Documentation entry. No behaviour change. --- CHANGELOG.md | 15 ++++++++++++++- .../compose/document/chart/LegendPosition.java | 12 ++++++------ .../demcha/compose/document/dsl/PathBuilder.java | 7 ++++++- .../document/dsl/ShapeContainerBuilder.java | 16 +++++++++------- .../compose/document/style/DocumentPaint.java | 16 ++++++++++++---- .../com/demcha/compose/document/svg/SvgIcon.java | 10 +++++++--- 6 files changed, 54 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 495e2602e..6efbb6ad9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -90,7 +90,10 @@ Entries land here as they merge. mask under `ClipPolicy.CLIP_PATH`. The outline rides the existing vector-path fragment pipeline (one source of truth for native curves) and the clip handler emits the same `addPathSegments` geometry, so fill, clip, - and `addPath(...)` all agree. + and `addPath(...)` all agree. The new `Path` permit is additive and keeps + the artifact binary-compatible (the `japicmp` gate stays green); only + consumer code that exhaustively `switch`es over `ShapeOutline` would need a + new branch, and the canonical authoring surface exposes no such switch. - **SVG path import** (`@since 1.8.0`, **beta** — annotated `@Beta` while the surface hardens against real-world exporter output). `SvgPath.parse(d)` / `parse(d, viewBox...)` in the new `document.svg` package lowers the full @@ -271,6 +274,16 @@ Entries land here as they merge. ### Documentation +- **Contract-drift Javadoc fixes on the new 1.8 surface.** `LegendPosition` + no longer claims `RIGHT`/`TOP` are "reserved and rejected by validation" — + all four placements are laid out for every chart kind, as the resolver and + its tests already prove. `DocumentPaint` documents why the `Linear`/`Radial` + (angle/corner-reaching) and `LinearAxis`/`RadialCircle` (exact endpoint/radius) + forms coexist. `ShapeContainerBuilder`'s missing-outline error and class + Javadoc now name the full set of outline setters (including `path`). + `PathBuilder.dashed(double...)` documents the `IllegalArgumentException` it + throws eagerly, and `SvgIcon` documents that a gradient `href` inherits stops + only, not geometry attributes. - **Browsable feature-catalog PDF.** New flagship `FeatureCatalogExample` renders every shipped capability as a self-documenting block: the heading lands in the PDF outline (the bookmarks panel works as a clickable index), diff --git a/src/main/java/com/demcha/compose/document/chart/LegendPosition.java b/src/main/java/com/demcha/compose/document/chart/LegendPosition.java index f1d1e6f8f..dae0e0807 100644 --- a/src/main/java/com/demcha/compose/document/chart/LegendPosition.java +++ b/src/main/java/com/demcha/compose/document/chart/LegendPosition.java @@ -3,10 +3,10 @@ /** * Placement of the series legend relative to the plot area. * - *

v1 of the geometry resolver supports {@link #NONE} and {@link #BOTTOM}; the - * remaining placements are reserved and rejected by validation until the - * corresponding layout lands. Adding resolver support for a reserved constant is - * an additive, non-breaking change.

+ *

All four placements are laid out by the geometry resolver for every chart + * kind, including pie: {@link #NONE}, {@link #BOTTOM} (a row below the plot), + * {@link #TOP} (a row above), and {@link #RIGHT} (a column beside it). The + * resolver reserves the corresponding gutter and packs the entries to fit.

* * @author Artem Demchyshyn * @since 1.8.0 @@ -21,11 +21,11 @@ public enum LegendPosition { */ BOTTOM, /** - * Reserved — legend column to the right of the plot area. + * Legend column to the right of the plot area. */ RIGHT, /** - * Reserved — single legend row above the plot area. + * Single legend row above the plot area. */ TOP } diff --git a/src/main/java/com/demcha/compose/document/dsl/PathBuilder.java b/src/main/java/com/demcha/compose/document/dsl/PathBuilder.java index 1183e85d7..5140620b7 100644 --- a/src/main/java/com/demcha/compose/document/dsl/PathBuilder.java +++ b/src/main/java/com/demcha/compose/document/dsl/PathBuilder.java @@ -241,10 +241,15 @@ public PathBuilder strokePaint(DocumentPaint strokePaint) { /** * Makes the stroke dashed using alternating on/off lengths in points * (the same contract as {@code LineBuilder.dashed}). Affects only the - * stroke; fills are unaffected. + * stroke; fills are unaffected. Validates eagerly: an empty or + * non-finite/non-positive pattern is rejected at this call, not at + * {@link #build()}. * * @param pattern alternating on/off lengths in points * @return this builder + * @throws IllegalArgumentException if no segments are supplied or any + * segment is not finite and strictly + * positive */ public PathBuilder dashed(double... pattern) { this.dashPattern = DocumentDashPattern.of(pattern); diff --git a/src/main/java/com/demcha/compose/document/dsl/ShapeContainerBuilder.java b/src/main/java/com/demcha/compose/document/dsl/ShapeContainerBuilder.java index 3d4b25b05..f071b551c 100644 --- a/src/main/java/com/demcha/compose/document/dsl/ShapeContainerBuilder.java +++ b/src/main/java/com/demcha/compose/document/dsl/ShapeContainerBuilder.java @@ -15,11 +15,13 @@ * Builder for {@link ShapeContainerNode}. * *

Reads as: "container is a [shape], inside it I'm composing layers". - * The outline is mandatory — call {@link #rectangle(double, double)}, - * {@link #roundedRect(double, double, double)}, {@link #ellipse(double, double)}, - * or {@link #circle(double)} before {@link #build()}. Layers are appended in - * source order (first behind, last in front) and each layer carries one of the - * nine {@link LayerAlign} anchors plus optional on-screen offset.

+ * The outline is mandatory — call one of the outline setters + * ({@link #rectangle(double, double)}, {@link #roundedRect(double, double, double)}, + * {@link #ellipse(double, double)}, {@link #circle(double)}, a polygon factory, + * or {@link #path(double, double, java.util.List)}) before {@link #build()}. + * Layers are appended in source order (first behind, last in front) and each + * layer carries one of the nine {@link LayerAlign} anchors plus optional + * on-screen offset.

* * @author Artem Demchyshyn * @since 1.0.0 @@ -541,8 +543,8 @@ public ShapeContainerBuilder bottomRight(DocumentNode node) { public ShapeContainerNode build() { if (outline == null) { throw new IllegalStateException( - "ShapeContainerBuilder '" + name + "' requires an outline; " - + "call rectangle/roundedRect/ellipse/circle before build()."); + "ShapeContainerBuilder '" + name + "' requires an outline; call an outline " + + "setter (rectangle/roundedRect/ellipse/circle/polygon/path/...) before build()."); } return new ShapeContainerNode(name, outline, layers, clipPolicy, fillColor, stroke, padding, margin, transform); } diff --git a/src/main/java/com/demcha/compose/document/style/DocumentPaint.java b/src/main/java/com/demcha/compose/document/style/DocumentPaint.java index 23a57a86d..1810f2eb0 100644 --- a/src/main/java/com/demcha/compose/document/style/DocumentPaint.java +++ b/src/main/java/com/demcha/compose/document/style/DocumentPaint.java @@ -9,10 +9,18 @@ * single paint vocabulary every fillable surface shares — chart palettes * today, shape and panel fills as they adopt the {@code fillPaint} component. * - *

Backend contract: the PDF backend renders {@link Linear} and - * {@link Radial} as native axial / radial shadings; a backend (or surface) - * that cannot paint a gradient degrades to {@link #primaryColor()} — the - * first stop — so authoring code never branches per backend.

+ *

Backend contract: the PDF backend renders all gradient forms as native + * axial / radial shadings; a backend (or surface) that cannot paint a gradient + * degrades to {@link #primaryColor()} — the first stop — so authoring code + * never branches per backend.

+ * + *

Two ways to spell each gradient coexist by design, not by redundancy. + * {@link Linear} / {@link Radial} take an ergonomic angle / corner-reaching + * geometry and are the chart- and shape-authoring forms; {@link LinearAxis} / + * {@link RadialCircle} take exact endpoints / a radius in the unit box and are + * the forms the SVG reader emits to reproduce a source gradient verbatim. All + * four render through the same shading machinery and degrade to the same + * {@link #primaryColor()}.

* * @author Artem Demchyshyn * @since 1.8.0 diff --git a/src/main/java/com/demcha/compose/document/svg/SvgIcon.java b/src/main/java/com/demcha/compose/document/svg/SvgIcon.java index a124707e7..31c36d6cd 100644 --- a/src/main/java/com/demcha/compose/document/svg/SvgIcon.java +++ b/src/main/java/com/demcha/compose/document/svg/SvgIcon.java @@ -42,9 +42,13 @@ * {@code } references, nested {@code } viewBoxes (inner frames * recurse but their coordinates stay in the outer space), animations, and * the gradient corners that have no PDF analogue (focal points, - * {@code spreadMethod} other than pad, stop opacity). The XML reader - * refuses DOCTYPEs, so external-entity tricks cannot reach the file - * system.

+ * {@code spreadMethod} other than pad, stop opacity). A gradient's + * {@code href} / {@code xlink:href} indirection inherits only the referenced + * {@code } list — not its geometry attributes ({@code x1}/{@code y1}/ + * {@code x2}/{@code y2}, {@code cx}/{@code cy}/{@code r}, {@code gradientUnits}, + * {@code gradientTransform}); keep the coordinates on the referencing gradient. + * The XML reader refuses DOCTYPEs, so external-entity tricks cannot reach the + * file system.

* *
{@code
  * SvgIcon logo = SvgIcon.read(Path.of("assets/logo.svg"));