diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a6d07349b..31ce987b2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -147,7 +147,7 @@ jobs:
run: ./mvnw -B -ntp test -pl . -P no-poi
binary-compat:
- name: Binary Compatibility (japicmp vs v1.6.9)
+ name: Binary Compatibility (japicmp vs pom baseline)
if: github.event_name == 'pull_request'
needs: architecture-and-documentation-guards
runs-on: ubuntu-latest
@@ -166,8 +166,9 @@ jobs:
cache: maven
- name: Compare public API against baseline
- # The `japicmp` profile resolves the prior published jar
- # (v1.6.8 from Maven Central) and diffs it against the
+ # The `japicmp` profile resolves the baseline release pinned
+ # by the `japicmp.baseline` property in pom.xml (via the
+ # profile-local JitPack repository) and diffs it against the
# freshly-built artifact. Fails the job on any binary-
# incompatible modification to the public surface. Source-
# incompatible changes are reported only (phased policy).
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5c3bac84b..64784acb1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -95,6 +95,15 @@ Entries land here as they merge.
not fit in the remaining page space relocates whole to the next page instead
of orphaning its heading from the content below. Blocks taller than a page
still flow. Default off — existing layouts are byte-identical.
+- **Removed: `ConfigLoader`** (breaking). The `com.demcha.compose.ConfigLoader`
+ YAML/JSON config-file helper was an application-bootstrap utility with no
+ connection to document rendering — nothing in the library, tests, or
+ examples referenced it. Gone with it: the ``
+ `jackson-dataformat-yaml` dependency (ConfigLoader was its only consumer)
+ and the YAML entry in the `NoClassDefFoundError` troubleshooting section.
+ Consumers who relied on the helper can copy the former ~100-line class into
+ their own codebase or load configs directly with Jackson
+ (`new ObjectMapper(new YAMLFactory()).readValue(...)`).
### Bug fixes
@@ -136,6 +145,15 @@ Entries land here as they merge.
regression testing. Every snippet is verified against the current API;
the folder index (`docs/recipes/README.md`) no longer carries a
"not yet covered" list.
+- **Word-export example.** New `WordExportExample`
+ (`examples/features/docx`) renders the same `DocumentSession` as a
+ fixed-layout PDF *and* an editable Word file via `DocxSemanticBackend`,
+ one section per capability-table row: inline runs, nested lists with
+ custom markers, tables, side-by-side rows, an embedded image, a page
+ break, the chart→data-table fallback, and the geometry that stays
+ PDF-only. Committed previews live under `assets/readme/examples/`
+ (`word-export-companion.pdf` / `.docx`); the examples module adds the
+ optional `poi-ooxml` dependency exactly like a consuming project would.
- **`BusinessReportExample` chart is now a native vector chart.** The flagship
report's five-quarter Revenue/Profit block previously rasterised a bar chart
through Graphics2D into an embedded PNG; it now uses `ChartSpec.bar()` with a
diff --git a/assets/readme/examples/word-export-companion.docx b/assets/readme/examples/word-export-companion.docx
new file mode 100644
index 000000000..43ff0d055
Binary files /dev/null and b/assets/readme/examples/word-export-companion.docx differ
diff --git a/assets/readme/examples/word-export-companion.pdf b/assets/readme/examples/word-export-companion.pdf
new file mode 100644
index 000000000..77ba11cdf
Binary files /dev/null and b/assets/readme/examples/word-export-companion.pdf differ
diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md
index 7a9279178..4b08cdaa1 100644
--- a/docs/troubleshooting.md
+++ b/docs/troubleshooting.md
@@ -39,8 +39,8 @@ Per-feature mapping: [canonical ↔ legacy parity matrix](architecture/canonical
## `NoClassDefFoundError` at runtime
-GraphCompose marks two heavy, rarely-needed dependencies **optional** so
-PDF-only consumers don't pay for them. If you use the feature, add the
+GraphCompose marks one heavy, rarely-needed dependency **optional** so
+PDF-only consumers don't pay for it. If you use DOCX export, add the
dependency to **your** project.
**DOCX export** — `document.export(new DocxSemanticBackend())` needs
@@ -54,20 +54,6 @@ Apache POI on your classpath:
```
-**YAML config** — loading a `*.yaml` / `*.yml` resource through
-`ConfigLoader` needs the Jackson YAML dataformat (the error names
-`YAMLFactory`):
-
-```xml
-
- com.fasterxml.jackson.dataformat
- jackson-dataformat-yaml
-
-
-```
-
-…or load a JSON config instead, which needs no extra dependency.
-
## The bundled examples won't resolve `graph-compose`
**Cause.** `examples/` is a **separate Maven module** that depends on the
diff --git a/examples/README.md b/examples/README.md
index fea013c73..a1c08f539 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -93,6 +93,7 @@ are with the canonical DSL, then jump to its detailed section below.
| [Charts](#charts) | Native vector bar, line, and pie/donut charts — data/spec/style layers, axis & grid toggles, point markers, value labels, legend | [PDF](../assets/readme/examples/chart-showcase.pdf) · [Source](src/main/java/com/demcha/examples/features/charts/ChartShowcaseExample.java) |
| [PDF chrome](#pdf-chrome) | `DocumentMetadata`, `DocumentWatermark`, `DocumentHeaderFooter`, `DocumentBookmarkOptions` | [PDF](../assets/readme/examples/pdf-chrome.pdf) · [Source](src/main/java/com/demcha/examples/features/chrome/PdfChromeExample.java) |
| [HTTP streaming](#http-streaming) | `writePdf(OutputStream)` for Servlet / S3 / GCS — caller's stream is not closed | [PDF](../assets/readme/examples/invoice-http-stream.pdf) · [Source](src/main/java/com/demcha/examples/features/streaming/HttpStreamingExample.java) |
+| [Word export (DOCX)](#word-export-docx) | `DocxSemanticBackend` — the same session renders a fixed-layout PDF and an editable Word file; paragraphs / lists / tables / images map 1:1, charts fall back to their data table | [PDF](../assets/readme/examples/word-export-companion.pdf) · [DOCX](../assets/readme/examples/word-export-companion.docx) · [Source](src/main/java/com/demcha/examples/features/docx/WordExportExample.java) |
| [Layout snapshot regression](#layout-snapshot-regression) | Deterministic `layoutSnapshot()` workflow with baseline + drift report — production regression-testing pattern | [PDF](../assets/readme/examples/invoice-snapshot-regression.pdf) · [Source](src/main/java/com/demcha/examples/features/snapshots/LayoutSnapshotRegressionExample.java) |
| [Business report cover](#business-report-cover) | Single-page Q1 investor brief — hero image, KPI cards, bar chart, metrics table | [PDF](../assets/readme/examples/business-report.pdf) · [Source](src/main/java/com/demcha/examples/flagships/BusinessReportExample.java) |
| [Master showcase](#master-showcase) | Kitchen-sink "Q2 sample report" combining the canonical surface end-to-end | [PDF](../assets/readme/examples/master-showcase.pdf) · [Source](src/main/java/com/demcha/examples/flagships/MasterShowcaseExample.java) |
@@ -576,6 +577,47 @@ public ResponseEntity invoice(@PathVariable Long id) {
[📄 View PDF](../assets/readme/examples/invoice-http-stream.pdf) ·
[📜 Full source](src/main/java/com/demcha/examples/features/streaming/HttpStreamingExample.java)
+### Word export (DOCX)
+
+The semantic backend walks the document graph and writes **editable
+Word content** — no layout pass, no PDF chrome. One session, two
+outputs:
+
+```java
+try (DocumentSession document = GraphCompose.document(pdfFile)
+ .pageSize(595, 842)
+ .margin(DocumentInsets.of(48))
+ .create()) {
+ document.metadata(DocumentMetadata.builder()
+ .title("GraphCompose Word export companion")
+ .author("GraphCompose").build()); // → Word core properties
+
+ document.pageFlow().name("Flow")
+ .addRich(rich -> rich.plain("Inline ").bold("runs").plain(" survive."))
+ .addList(list -> list.markerFor(1, ListMarker.custom("◦"))
+ .addItem("Nested authoring", l1 -> l1
+ .addItem("Two spaces of indent per depth in Word")))
+ .addTable(t -> t.headerRow("Quarter", "Revenue").row("Q1", "42"))
+ .addSection("Chart", s -> s.chart(ChartSpec.bar().data(quarters).build()))
+ .build();
+
+ document.buildPdf(); // fixed-layout PDF
+ document.export(new DocxSemanticBackend(), docxFile); // editable Word file
+}
+```
+
+Paragraphs (inline runs included), lists, tables, side-by-side rows,
+images, spacers, and page breaks map 1:1; session metadata lands in the
+Word core properties. Charts export as their categories-by-series data
+table (one capability warning per export), shape containers flatten to
+inline layers, and pure geometry — dividers, shapes, barcodes — stays
+PDF-only by design. Requires `org.apache.poi:poi-ooxml` on the
+classpath (the dependency is optional in the GraphCompose POM).
+
+[📄 View PDF](../assets/readme/examples/word-export-companion.pdf) ·
+[📝 Word file](../assets/readme/examples/word-export-companion.docx) ·
+[📜 Full source](src/main/java/com/demcha/examples/features/docx/WordExportExample.java)
+
### Layout snapshot regression
The full `compose → layoutSnapshot() → LayoutSnapshotJson.toJson(...)`
diff --git a/examples/pom.xml b/examples/pom.xml
index 92107adfa..0626462a6 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -44,6 +44,15 @@
${graphcompose.version}
+
+
+ org.apache.poi
+ poi-ooxml
+ 5.5.1
+
+
ch.qos.logbacklogback-classic
diff --git a/examples/src/main/java/com/demcha/examples/GenerateAllExamples.java b/examples/src/main/java/com/demcha/examples/GenerateAllExamples.java
index 53a00824f..099e78bf5 100644
--- a/examples/src/main/java/com/demcha/examples/GenerateAllExamples.java
+++ b/examples/src/main/java/com/demcha/examples/GenerateAllExamples.java
@@ -3,6 +3,7 @@
import com.demcha.examples.features.barcodes.BarcodeShowcaseExample;
import com.demcha.examples.features.charts.ChartShowcaseExample;
import com.demcha.examples.features.canvas.CanvasLayerExample;
+import com.demcha.examples.features.docx.WordExportExample;
import com.demcha.examples.features.chrome.PdfChromeExample;
import com.demcha.examples.features.lists.NestedListExample;
import com.demcha.examples.features.shapes.ShapeContainerExample;
@@ -138,6 +139,9 @@ public static void main(String[] args) throws Exception {
System.out.println("Generated: " + CustomBusinessThemeExample.generate());
System.out.println("Generated: " + PdfChromeExample.generate());
+ // DOCX export
+ System.out.println("Generated: " + WordExportExample.generate());
+
// Barcodes
System.out.println("Generated: " + BarcodeShowcaseExample.generate());
diff --git a/examples/src/main/java/com/demcha/examples/features/docx/WordExportExample.java b/examples/src/main/java/com/demcha/examples/features/docx/WordExportExample.java
new file mode 100644
index 000000000..e16da1429
--- /dev/null
+++ b/examples/src/main/java/com/demcha/examples/features/docx/WordExportExample.java
@@ -0,0 +1,212 @@
+package com.demcha.examples.features.docx;
+
+import com.demcha.compose.GraphCompose;
+import com.demcha.compose.document.api.DocumentSession;
+import com.demcha.compose.document.backend.semantic.DocxSemanticBackend;
+import com.demcha.compose.document.chart.ChartData;
+import com.demcha.compose.document.chart.ChartSpec;
+import com.demcha.compose.document.image.DocumentImageData;
+import com.demcha.compose.document.node.ListMarker;
+import com.demcha.compose.document.output.DocumentMetadata;
+import com.demcha.compose.document.style.DocumentColor;
+import com.demcha.compose.document.style.DocumentInsets;
+import com.demcha.compose.document.style.DocumentStroke;
+import com.demcha.compose.document.style.DocumentTextDecoration;
+import com.demcha.compose.document.style.DocumentTextStyle;
+import com.demcha.compose.document.table.DocumentTableColumn;
+import com.demcha.compose.font.FontName;
+import com.demcha.examples.support.ExampleOutputPaths;
+
+import javax.imageio.ImageIO;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.GradientPaint;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.nio.file.Path;
+
+/**
+ * One document, two outputs: the same {@link DocumentSession} renders a
+ * fixed-layout PDF and exports an editable Word file through
+ * {@link DocxSemanticBackend}. Each section demonstrates one row of the
+ * DOCX capability table from {@code docs/recipes/docx-export.md}:
+ * styled paragraphs and inline runs map 1:1, lists keep markers and
+ * per-depth indent, tables and side-by-side rows stay tables, images
+ * embed at their declared size, page breaks survive, charts fall back to
+ * their data table, and pure geometry (dividers, shape containers) stays
+ * PDF-only by design.
+ *
+ *
Requires {@code org.apache.poi:poi-ooxml} on the classpath — the
+ * dependency is optional in the GraphCompose POM, so this module adds it
+ * explicitly, exactly like a consuming project would.
+ *
+ * @author Artem Demchyshyn
+ */
+public final class WordExportExample {
+
+ private static final DocumentColor INK = DocumentColor.rgb(34, 38, 50);
+ private static final DocumentColor MUTED = DocumentColor.rgb(102, 106, 118);
+ private static final DocumentColor NAVY = DocumentColor.rgb(20, 45, 80);
+ private static final DocumentColor GOLD = DocumentColor.rgb(196, 153, 76);
+ private static final DocumentColor TEAL = DocumentColor.rgb(20, 80, 95);
+
+ private WordExportExample() {
+ }
+
+ public static Path generate() throws Exception {
+ Path pdfFile = ExampleOutputPaths.prepare("features/docx", "word-export-companion.pdf");
+ Path docxFile = ExampleOutputPaths.prepare("features/docx", "word-export-companion.docx");
+
+ DocumentTextStyle title = DocumentTextStyle.builder()
+ .fontName(FontName.HELVETICA_BOLD)
+ .size(20)
+ .color(NAVY)
+ .decoration(DocumentTextDecoration.BOLD)
+ .build();
+ DocumentTextStyle heading = DocumentTextStyle.builder()
+ .fontName(FontName.HELVETICA_BOLD)
+ .size(13)
+ .color(INK)
+ .decoration(DocumentTextDecoration.BOLD)
+ .build();
+ DocumentTextStyle body = DocumentTextStyle.builder()
+ .fontName(FontName.HELVETICA)
+ .size(11)
+ .color(INK)
+ .build();
+ DocumentTextStyle caption = DocumentTextStyle.builder()
+ .fontName(FontName.HELVETICA_OBLIQUE)
+ .size(10)
+ .color(MUTED)
+ .build();
+
+ ChartData quarters = ChartData.builder()
+ .categories("Q1", "Q2", "Q3", "Q4")
+ .series("Revenue", 42.0, 55.0, 61.0, 70.0)
+ .series("Profit", 12.0, 17.0, 21.0, 26.0)
+ .build();
+ DocumentImageData photo = demoImage();
+
+ try (DocumentSession document = GraphCompose.document(pdfFile)
+ .pageSize(595, 842)
+ .margin(DocumentInsets.of(48))
+ .create()) {
+
+ // Session metadata lands in the PDF info dictionary AND the
+ // Word core properties (File > Info in Word).
+ document.metadata(DocumentMetadata.builder()
+ .title("GraphCompose Word export companion")
+ .author("GraphCompose")
+ .subject("Every node the semantic DOCX backend maps, falls back on, or skips")
+ .keywords("graphcompose, docx, semantic export")
+ .build());
+
+ document.pageFlow().name("Flow").spacing(14)
+ .addParagraph("GraphCompose → Word, from one document", title)
+ .addRich(rich -> rich
+ .plain("This file exists twice: a fixed-layout ")
+ .bold("PDF")
+ .plain(" and an editable ")
+ .bold("DOCX")
+ .plain(" exported from the same session. Inline runs — ")
+ .italic("italic, ")
+ .color("colored, ", GOLD)
+ .accent("bold accents", TEAL)
+ .plain(" — survive in both."))
+
+ .addParagraph("Lists keep markers and indent", heading)
+ .addList(list -> list
+ .name("FlatList")
+ .textStyle(body)
+ .dash()
+ .items("Flat items use the list marker",
+ "Word gets one paragraph per item"))
+ .addList(list -> list
+ .name("NestedList")
+ .textStyle(body)
+ .itemSpacing(2)
+ .markerFor(1, ListMarker.custom("◦"))
+ .markerFor(2, ListMarker.custom("▪"))
+ .addItem("Nested authoring", l1 -> l1
+ .addItem("Two spaces of indent per depth in Word", l2 -> l2
+ .addItem("Custom markers survive the export"))))
+
+ .addParagraph("Tables stay tables", heading)
+ .addTable(t -> t
+ .columns(DocumentTableColumn.auto(),
+ DocumentTableColumn.auto(),
+ DocumentTableColumn.auto())
+ .headerRow("Quarter", "Revenue", "Profit")
+ .row("Q1", "42", "12")
+ .row("Q2", "55", "17")
+ .row("Q3", "61", "21")
+ .row("Q4", "70", "26"))
+
+ .addParagraph("Side-by-side rows become one-row tables", heading)
+ .addRow(r -> r.spacing(14).weights(1, 1)
+ .addSection("Left", a -> a
+ .addParagraph("Left cell — editors keep the columns.", body))
+ .addSection("Right", b -> b
+ .addParagraph("Right cell — content stays editable.", body)))
+
+ .addParagraph("Images embed at their declared size", heading)
+ .addImage(i -> i.source(photo).size(180, 100))
+
+ .addPageBreak(pb -> pb.name("ToPage2"))
+
+ .addParagraph("Charts fall back to their data", heading)
+ .addParagraph("The PDF renders the vector chart; Word has no layout pass, "
+ + "so the same node exports as a categories-by-series table.", caption)
+ .addSection("Chart", s -> s.chart(ChartSpec.bar().data(quarters).build()))
+
+ .addParagraph("Geometry stays PDF-only by design", heading)
+ .addParagraph("The divider and the badge below render in the PDF; the "
+ + "semantic export skips pure geometry and writes the badge's "
+ + "text inline instead.", caption)
+ .addDivider(d -> d.width(420).thickness(2).color(GOLD))
+ .addCircle(72, TEAL, c -> c
+ .stroke(DocumentStroke.of(GOLD, 1.2))
+ .center(new com.demcha.compose.document.dsl.ParagraphBuilder()
+ .text("GC")
+ .textStyle(DocumentTextStyle.builder()
+ .fontName(FontName.HELVETICA_BOLD).size(20)
+ .color(DocumentColor.WHITE).build())
+ .align(com.demcha.compose.document.node.TextAlign.CENTER)
+ .build()))
+ .build();
+
+ document.buildPdf();
+ document.export(new DocxSemanticBackend(), docxFile);
+ }
+ System.out.println("Generated: " + docxFile);
+ return pdfFile;
+ }
+
+ /**
+ * Small deterministic gradient placeholder (a few KB) — keeps the
+ * committed PDF/DOCX previews light, unlike the 1.8 MB catalog photo.
+ */
+ private static DocumentImageData demoImage() throws Exception {
+ BufferedImage image = new BufferedImage(360, 200, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g = image.createGraphics();
+ try {
+ g.setPaint(new GradientPaint(0, 0, new Color(20, 45, 80),
+ 360, 200, new Color(20, 80, 95)));
+ g.fillRect(0, 0, 360, 200);
+ g.setPaint(new Color(196, 153, 76));
+ g.setStroke(new BasicStroke(6f));
+ g.drawLine(0, 170, 360, 110);
+ } finally {
+ g.dispose();
+ }
+ ByteArrayOutputStream png = new ByteArrayOutputStream();
+ ImageIO.write(image, "png", png);
+ return DocumentImageData.fromBytes(png.toByteArray());
+ }
+
+ public static void main(String[] args) throws Exception {
+ Path output = generate();
+ System.out.println("Generated: " + output);
+ }
+}
diff --git a/examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java b/examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java
index 3aec5fe1b..8243582e3 100644
--- a/examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java
+++ b/examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java
@@ -103,6 +103,7 @@ record Entry(String title, String description, List tags, String codeUrl
feature("chrome", "pdf-chrome", "PDF Chrome", "Headers, footers, watermarks, metadata, document protection / encryption.", "chrome", "metadata", "watermark");
feature("streaming", "invoice-http-stream", "HTTP Streaming", "Stream PDF directly to a Servlet response with no buffering.", "streaming", "http");
feature("snapshots", "invoice-snapshot-regression", "Layout Snapshots", "How LayoutSnapshotAssertions captures the resolved layout graph for regression testing.", "snapshots", "testing");
+ feature("docx", "word-export-companion", "Word Export (DOCX)", "DocxSemanticBackend — the same document as a fixed-layout PDF and an editable Word file; charts fall back to their data table.", "docx", "word", "export");
// ===== Flagships =====
flagship("master-showcase", "Master Showcase", "Kitchen-sink demo combining every primitive into a single document — the full GraphCompose surface.", "showcase");
@@ -206,6 +207,7 @@ private static void feature(String group, String id, String title, String desc,
case "chrome" -> "chrome/PdfChromeExample.java";
case "streaming" -> "streaming/HttpStreamingExample.java";
case "snapshots" -> "snapshots/LayoutSnapshotRegressionExample.java";
+ case "docx" -> "docx/WordExportExample.java";
default -> group + "/" + capitalize(id);
};
ENTRIES.put(id, entry(title, desc, withCategory(group, tags), EX_BASE + "/features/" + file));
diff --git a/pom.xml b/pom.xml
index 0a575f8f1..1f773f121 100644
--- a/pom.xml
+++ b/pom.xml
@@ -203,24 +203,6 @@
jackson-databind
-
-
- com.fasterxml.jackson.dataformat
- jackson-dataformat-yaml
- true
-
-
com.google.zxingcore
@@ -728,6 +710,16 @@
japicmp baseline advances to the release that lands the change.
-->
com.demcha.compose.engine.measurement.TextMeasurementSystem
+
+ com.demcha.compose.ConfigLoader
diff --git a/src/main/java/com/demcha/compose/ConfigLoader.java b/src/main/java/com/demcha/compose/ConfigLoader.java
deleted file mode 100644
index c40475ab2..000000000
--- a/src/main/java/com/demcha/compose/ConfigLoader.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package com.demcha.compose;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
-import lombok.extern.slf4j.Slf4j;
-
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-@Slf4j
-public final class ConfigLoader {
-
-
- private ConfigLoader() {
- }
-
- /**
- * Load YAML or JSON from a classpath resource into the given class.
- * Supports running from IDE and from a fat JAR.
- * Optionally resolves {@code ${ENV}} or {@code ${ENV:default}} placeholders
- * from environment variables.
- *
- *
Optional dependency: the YAML path requires
- * {@code com.fasterxml.jackson.dataformat:jackson-dataformat-yaml} on
- * the classpath. GraphCompose declares it as an optional Maven
- * dependency since {@code v1.6.7}; applications that load YAML
- * configs through this helper must add the artifact to their own
- * build. JSON configs work without it.
- *
- * @throws java.lang.NoClassDefFoundError if {@code fileName} ends with
- * {@code .yaml} / {@code .yml} and
- * {@code jackson-dataformat-yaml} is not on the classpath.
- */
- public static T loadConfigWithEnv(String fileName, Class clazz, boolean resolveEnv) {
- log.info("Initializing variables from '{}'", fileName);
- ObjectMapper mapper;
- if (fileName == null || fileName.isBlank()) throw new RuntimeException("fileName can`t be null or blank");
-
- if (fileName.endsWith("yaml") || fileName.endsWith("yml")) {
- mapper = new ObjectMapper(new YAMLFactory());
- } else {
- mapper = new ObjectMapper();
-
- }
-
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
- if (cl == null) cl = ConfigLoader.class.getClassLoader();
-
- URL resource = cl.getResource(fileName);
- if (resource == null) {
- throw new IllegalArgumentException("Config resource not found on classpath: " + fileName + "Url: " + resource);
- }
- log.info("Reading config from '{}'", resource);
-
- String raw;
- try (InputStream is = resource.openStream();
- BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
-
- StringBuilder sb = new StringBuilder();
- String line;
- while ((line = br.readLine()) != null) sb.append(line).append('\n');
- raw = sb.toString();
- } catch (Exception e) {
- log.error("Failed to read config '{}': {}", fileName, e.toString(), e);
- throw new RuntimeException("Failed to read config: " + fileName, e);
- }
-
- String resolved = resolveEnv ? replaceEnvVariables(raw) : raw;
-
-
- log.info("Creating a config YAML object '{}'", clazz.getSimpleName());
- try {
- log.info("Parsing config '{}'", fileName);
- return mapper.readValue(resolved, clazz);
- } catch (JsonProcessingException e) {
- log.error("Failed to parse config '{}': {}", fileName, e.toString(), e);
- throw new RuntimeException( "Failed to parse config: " + fileName, e);
- }
- }
-
- /**
- * Replace ${ENV} or ${ENV:default} with values from SystemECS.getenv().
- * Unknown vars without default → empty string.
- */
- private static String replaceEnvVariables(String text) {
- // ${VAR} or ${VAR:default value}
- Pattern p = Pattern.compile("\\$\\{([A-Za-z_][A-Za-z0-9_]*) (?:: ([^}]*))?\\}", Pattern.COMMENTS);
- Matcher m = p.matcher(text);
- StringBuffer out = new StringBuffer();
-
- while (m.find()) {
- String var = m.group(1);
- String def = m.group(2); // may be null
- String val = System.getenv(var);
- if (val == null) val = (def != null ? def : "");
- // Escape backslashes and dollars for appendReplacement
- m.appendReplacement(out, Matcher.quoteReplacement(val));
- }
- m.appendTail(out);
- return out.toString();
- }
-}
diff --git a/src/main/java/com/demcha/compose/GraphCompose.java b/src/main/java/com/demcha/compose/GraphCompose.java
index a9841ae97..f20ba3ca7 100644
--- a/src/main/java/com/demcha/compose/GraphCompose.java
+++ b/src/main/java/com/demcha/compose/GraphCompose.java
@@ -15,6 +15,7 @@
/**
* Main entry point for GraphCompose document authoring.
+ *
*
* Application code starts here and should use the canonical semantic document
* session through {@link #document()} to turn author intent into a paginated
@@ -23,18 +24,18 @@
*
*
The typical runtime flow is:
*
- *
create a semantic session with {@link #document(Path)} or {@link #document()}
- *
author content with {@link DocumentSession#pageFlow()}, {@link DocumentSession#compose(java.util.function.Consumer)},
- * or {@link DocumentSession#dsl()}
- *
inspect {@link DocumentSession#layoutGraph()} or {@link DocumentSession#layoutSnapshot()} if needed
- *
call {@link DocumentSession#buildPdf()} or {@link DocumentSession#toPdfBytes()}
+ *
Create a semantic session with {@link #document(Path)} or {@link #document()}.
+ *
Author content with {@link DocumentSession#pageFlow()},
+ * {@link DocumentSession#compose(java.util.function.Consumer)}, or
+ * {@link DocumentSession#dsl()}.
+ *
Inspect {@link DocumentSession#layoutGraph()} or
+ * {@link DocumentSession#layoutSnapshot()} if needed.
+ *
Call {@link DocumentSession#buildPdf()} or {@link DocumentSession#toPdfBytes()}.
The values are deliberately plain geometry. PDFBox-specific page objects
* are created only by the PDF backend when a document is rendered.
*
- * @param width page width in points
+ * @param width page width in points
* @param height page height in points
* @since 1.0.0
*/
@@ -29,7 +29,7 @@ public record DocumentPageSize(double width, double height) {
/**
* Creates a page size from point dimensions.
*
- * @param width page width in points
+ * @param width page width in points
* @param height page height in points
*/
public DocumentPageSize {
@@ -44,7 +44,7 @@ public record DocumentPageSize(double width, double height) {
/**
* Creates a page size from point dimensions.
*
- * @param width page width in points
+ * @param width page width in points
* @param height page height in points
* @return page size value
*/
diff --git a/src/main/java/com/demcha/compose/document/api/DocumentRenderingFacade.java b/src/main/java/com/demcha/compose/document/api/DocumentRenderingFacade.java
index 117f91da4..fc1db5beb 100644
--- a/src/main/java/com/demcha/compose/document/api/DocumentRenderingFacade.java
+++ b/src/main/java/com/demcha/compose/document/api/DocumentRenderingFacade.java
@@ -42,6 +42,10 @@ final class DocumentRenderingFacade {
this.context = Objects.requireNonNull(context, "context");
}
+ private static long elapsedMillis(long startNanos) {
+ return TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos);
+ }
+
R render(FixedLayoutBackend backend, Path outputFile) throws Exception {
context.ensureOpen();
Objects.requireNonNull(backend, "backend");
@@ -170,10 +174,6 @@ void buildPdf(Path outputFile) throws Exception {
}
}
- private static long elapsedMillis(long startNanos) {
- return TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos);
- }
-
/**
* Context callbacks that the rendering facade reads from
* {@link DocumentSession}. The session implements this interface so the
diff --git a/src/main/java/com/demcha/compose/document/api/DocumentSession.java b/src/main/java/com/demcha/compose/document/api/DocumentSession.java
index 869dacb78..548099e85 100644
--- a/src/main/java/com/demcha/compose/document/api/DocumentSession.java
+++ b/src/main/java/com/demcha/compose/document/api/DocumentSession.java
@@ -1,34 +1,30 @@
package com.demcha.compose.document.api;
import com.demcha.compose.GraphCompose;
-import com.demcha.compose.font.FontFamilyDefinition;
import com.demcha.compose.document.backend.fixed.FixedLayoutBackend;
-import com.demcha.compose.document.backend.fixed.pdf.PdfMeasurementResources;
import com.demcha.compose.document.backend.fixed.pdf.PdfFixedLayoutBackend;
+import com.demcha.compose.document.backend.fixed.pdf.PdfMeasurementResources;
import com.demcha.compose.document.backend.fixed.pdf.options.PdfHeaderFooterOptions;
import com.demcha.compose.document.backend.fixed.pdf.options.PdfMetadataOptions;
import com.demcha.compose.document.backend.fixed.pdf.options.PdfProtectionOptions;
import com.demcha.compose.document.backend.fixed.pdf.options.PdfWatermarkOptions;
import com.demcha.compose.document.backend.semantic.SemanticBackend;
-import com.demcha.compose.document.output.DocumentHeaderFooter;
-import com.demcha.compose.document.output.DocumentMetadata;
-import com.demcha.compose.document.output.DocumentOutputOptions;
-import com.demcha.compose.document.output.DocumentProtection;
-import com.demcha.compose.document.output.DocumentWatermark;
import com.demcha.compose.document.debug.snapshot.LayoutGraphSnapshotExtractor;
import com.demcha.compose.document.dsl.DocumentDsl;
import com.demcha.compose.document.dsl.PageFlowBuilder;
import com.demcha.compose.document.exceptions.DocumentRenderingException;
import com.demcha.compose.document.layout.*;
-import com.demcha.compose.document.node.DocumentNode;
import com.demcha.compose.document.node.ContainerNode;
+import com.demcha.compose.document.node.DocumentNode;
+import com.demcha.compose.document.output.*;
import com.demcha.compose.document.snapshot.LayoutSnapshot;
import com.demcha.compose.document.style.DocumentColor;
import com.demcha.compose.document.style.DocumentInsets;
+import com.demcha.compose.font.FontFamilyDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.awt.Color;
+import java.awt.*;
import java.io.OutputStream;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -70,32 +66,28 @@ public final class DocumentSession implements AutoCloseable {
private final LayoutCompiler compiler;
private final List roots = new ArrayList<>();
private final List customFontFamilies = new ArrayList<>();
-
+ private final DocumentChromeOptions chromeOptions = new DocumentChromeOptions();
+ private final DocumentLayoutCache layoutCache = new DocumentLayoutCache();
+ private final DocumentRenderingFacade renderingFacade = new DocumentRenderingFacade(new RenderingContextImpl());
private DocumentPageSize pageSize;
private DocumentInsets margin;
private LayoutCanvas canvas;
private boolean markdown;
private boolean guideLines;
private List pageBackgrounds = List.of();
-
- private final DocumentChromeOptions chromeOptions = new DocumentChromeOptions();
-
private PdfMeasurementResources measurementResources;
-
- private final DocumentLayoutCache layoutCache = new DocumentLayoutCache();
- private final DocumentRenderingFacade renderingFacade = new DocumentRenderingFacade(new RenderingContextImpl());
private boolean closed;
/**
* Creates a canonical document session.
*
- * @param defaultOutputFile optional default PDF output path
- * @param pageSize physical page size
- * @param margin page margin
+ * @param defaultOutputFile optional default PDF output path
+ * @param pageSize physical page size
+ * @param margin page margin
* @param customFontFamilies document-local font families
- * @param markdown whether markdown parsing is enabled
- * @param guideLines whether PDF guide-line overlays are enabled
+ * @param markdown whether markdown parsing is enabled
+ * @param guideLines whether PDF guide-line overlays are enabled
*/
public DocumentSession(Path defaultOutputFile,
DocumentPageSize pageSize,
@@ -124,6 +116,23 @@ public DocumentSession(Path defaultOutputFile,
guideLines);
}
+ /**
+ * Runs a PDF convenience body and unifies the cross-cutting checked-exception
+ * wrapping: any underlying {@link Exception} is rewrapped as
+ * {@link DocumentRenderingException} with the supplied {@code action} fragment.
+ * {@link RuntimeException}s pass through unchanged so existing callers that
+ * already catch them keep their semantics.
+ */
+ private static R wrapPdfRendering(String action, PdfRenderingBody body) throws DocumentRenderingException {
+ try {
+ return body.run();
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new DocumentRenderingException("Failed to " + action + ": " + e.getMessage(), e);
+ }
+ }
+
/**
* Returns the fluent semantic DSL facade bound to this session.
*
@@ -141,8 +150,8 @@ public DocumentDsl dsl() {
* @return a new DSL facade for authoring roots and semantic nodes
* @throws IllegalStateException if this session has already been closed
* @deprecated since 1.6.0; prefer {@link #dsl()}. Carrying two names for
- * the same operation on the session facade adds maintenance
- * cost without clarity. Scheduled for removal in v2.0.
+ * the same operation on the session facade adds maintenance
+ * cost without clarity. Scheduled for removal in v2.0.
*/
@Deprecated(since = "1.6.0", forRemoval = true)
public DocumentDsl builder() {
@@ -256,7 +265,7 @@ public DocumentSession pageSize(DocumentPageSize pageSize) {
/**
* Updates the physical page size from point dimensions.
*
- * @param width page width in points
+ * @param width page width in points
* @param height page height in points
* @return this session
*/
@@ -408,7 +417,7 @@ public DocumentSession metadata(DocumentMetadata metadata) {
* @param options legacy PDF metadata options, or {@code null} to clear
* @return this session
* @deprecated since 1.6.0, removal in v2.0; prefer the canonical
- * {@link #metadata(DocumentMetadata)}.
+ * {@link #metadata(DocumentMetadata)}.
*/
@Deprecated(since = "1.6.0", forRemoval = true)
public DocumentSession metadata(PdfMetadataOptions options) {
@@ -435,7 +444,7 @@ public DocumentSession watermark(DocumentWatermark watermark) {
* @param options legacy PDF watermark options, or {@code null} to clear
* @return this session
* @deprecated since 1.6.0, removal in v2.0; prefer the canonical
- * {@link #watermark(DocumentWatermark)}.
+ * {@link #watermark(DocumentWatermark)}.
*/
@Deprecated(since = "1.6.0", forRemoval = true)
public DocumentSession watermark(PdfWatermarkOptions options) {
@@ -462,7 +471,7 @@ public DocumentSession protect(DocumentProtection protection) {
* @param options legacy PDF protection options, or {@code null} to clear
* @return this session
* @deprecated since 1.6.0, removal in v2.0; prefer the canonical
- * {@link #protect(DocumentProtection)}.
+ * {@link #protect(DocumentProtection)}.
*/
@Deprecated(since = "1.6.0", forRemoval = true)
public DocumentSession protect(PdfProtectionOptions options) {
@@ -488,7 +497,7 @@ public DocumentSession header(DocumentHeaderFooter header) {
* @param options legacy PDF header/footer options
* @return this session
* @deprecated since 1.6.0, removal in v2.0; prefer the canonical
- * {@link #header(DocumentHeaderFooter)}.
+ * {@link #header(DocumentHeaderFooter)}.
*/
@Deprecated(since = "1.6.0", forRemoval = true)
public DocumentSession header(PdfHeaderFooterOptions options) {
@@ -514,7 +523,7 @@ public DocumentSession footer(DocumentHeaderFooter footer) {
* @param options legacy PDF header/footer options
* @return this session
* @deprecated since 1.6.0, removal in v2.0; prefer the canonical
- * {@link #footer(DocumentHeaderFooter)}.
+ * {@link #footer(DocumentHeaderFooter)}.
*/
@Deprecated(since = "1.6.0", forRemoval = true)
public DocumentSession footer(PdfHeaderFooterOptions options) {
@@ -557,7 +566,7 @@ public DocumentSession registerFontFamily(FontFamilyDefinition definition) {
* mutations through {@code invalidate()} since v1.6.7).
*
* @param definition node definition implementation
- * @param semantic node type handled by the definition
+ * @param semantic node type handled by the definition
* @return this session
* @throws IllegalStateException if this session has already been closed
*/
@@ -712,7 +721,7 @@ public LayoutSnapshot layoutSnapshot() {
* Renders the current layout graph with the supplied fixed-layout backend.
*
* @param backend backend implementation that consumes the resolved layout graph
- * @param backend-specific result type
+ * @param backend-specific result type
* @return backend render result
* @throws Exception if rendering fails
*/
@@ -723,9 +732,9 @@ public R render(FixedLayoutBackend backend) throws Exception {
/**
* Renders the current layout graph with an explicit output target override.
*
- * @param backend backend implementation that consumes the resolved layout graph
+ * @param backend backend implementation that consumes the resolved layout graph
* @param outputFile optional output target for backends that persist to disk
- * @param backend-specific result type
+ * @param backend-specific result type
* @return backend render result
* @throws Exception if rendering fails
*/
@@ -737,7 +746,7 @@ public R render(FixedLayoutBackend backend, Path outputFile) throws Excep
* Exports the semantic graph through a semantic backend using the default output file.
*
* @param backend semantic backend implementation
- * @param backend-specific result type
+ * @param backend-specific result type
* @return export result
* @throws Exception if export fails
*/
@@ -748,9 +757,9 @@ public R export(SemanticBackend backend) throws Exception {
/**
* Exports the semantic graph through a semantic backend using an explicit output target.
*
- * @param backend semantic backend implementation
+ * @param backend semantic backend implementation
* @param outputFile optional output file override
- * @param backend-specific result type
+ * @param backend-specific result type
* @return export result
* @throws Exception if export fails
*/
@@ -793,7 +802,7 @@ public void writePdf(OutputStream output) throws DocumentRenderingException {
/**
* Builds the current document into the default output file configured on the builder.
*
- * @throws IllegalStateException if no default output file was configured
+ * @throws IllegalStateException if no default output file was configured
* @throws DocumentRenderingException if PDF rendering fails
*/
public void buildPdf() throws DocumentRenderingException {
@@ -912,23 +921,6 @@ private long elapsedMillis(long startNanos) {
return TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos);
}
- /**
- * Runs a PDF convenience body and unifies the cross-cutting checked-exception
- * wrapping: any underlying {@link Exception} is rewrapped as
- * {@link DocumentRenderingException} with the supplied {@code action} fragment.
- * {@link RuntimeException}s pass through unchanged so existing callers that
- * already catch them keep their semantics.
- */
- private static R wrapPdfRendering(String action, PdfRenderingBody body) throws DocumentRenderingException {
- try {
- return body.run();
- } catch (RuntimeException e) {
- throw e;
- } catch (Exception e) {
- throw new DocumentRenderingException("Failed to " + action + ": " + e.getMessage(), e);
- }
- }
-
@FunctionalInterface
private interface PdfRenderingBody {
R run() throws Exception;
diff --git a/src/main/java/com/demcha/compose/document/api/Internal.java b/src/main/java/com/demcha/compose/document/api/Internal.java
index c9e97884e..8e9608fac 100644
--- a/src/main/java/com/demcha/compose/document/api/Internal.java
+++ b/src/main/java/com/demcha/compose/document/api/Internal.java
@@ -1,10 +1,6 @@
package com.demcha.compose.document.api;
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
+import java.lang.annotation.*;
/**
* Marks an API element as internal to GraphCompose.
diff --git a/src/main/java/com/demcha/compose/document/api/PageBackgroundFill.java b/src/main/java/com/demcha/compose/document/api/PageBackgroundFill.java
index f6991ad48..cb30a61d3 100644
--- a/src/main/java/com/demcha/compose/document/api/PageBackgroundFill.java
+++ b/src/main/java/com/demcha/compose/document/api/PageBackgroundFill.java
@@ -52,7 +52,9 @@ public record PageBackgroundFill(double xRatio,
double heightRatio,
DocumentColor color) {
- /** Validates the ratio bounds and that the fill color is non-null. */
+ /**
+ * Validates the ratio bounds and that the fill color is non-null.
+ */
public PageBackgroundFill {
Objects.requireNonNull(color, "color");
if (xRatio < 0.0 || xRatio > 1.0) {
@@ -87,7 +89,7 @@ public static PageBackgroundFill fullPage(DocumentColor color) {
* Full-height column at the left page edge, with width = ratio of page width.
*
* @param widthRatio width as a fraction of the canvas width (0..1]
- * @param color fill color (required)
+ * @param color fill color (required)
* @return a {@code PageBackgroundFill} spanning the full page height at the left edge
*/
public static PageBackgroundFill leftColumn(double widthRatio,
@@ -99,7 +101,7 @@ public static PageBackgroundFill leftColumn(double widthRatio,
* Full-height column at the right page edge, with width = ratio of page width.
*
* @param widthRatio width as a fraction of the canvas width (0..1]
- * @param color fill color (required)
+ * @param color fill color (required)
* @return a {@code PageBackgroundFill} spanning the full page height at the right edge
*/
public static PageBackgroundFill rightColumn(double widthRatio,
@@ -111,9 +113,9 @@ public static PageBackgroundFill rightColumn(double widthRatio,
/**
* Full-height column at an arbitrary horizontal offset.
*
- * @param xRatio left edge of the column: 0.0 = left edge, 1.0 = right edge
+ * @param xRatio left edge of the column: 0.0 = left edge, 1.0 = right edge
* @param widthRatio width as a fraction of the canvas width (0..1]
- * @param color fill color (required)
+ * @param color fill color (required)
* @return a {@code PageBackgroundFill} spanning the full page height from {@code xRatio}
*/
public static PageBackgroundFill column(double xRatio,
@@ -126,7 +128,7 @@ public static PageBackgroundFill column(double xRatio,
* Full-width band flush with the top of the page (height = ratio of page height).
*
* @param heightRatio height as a fraction of the canvas height (0..1]
- * @param color fill color (required)
+ * @param color fill color (required)
* @return a {@code PageBackgroundFill} spanning the full page width at the top edge
*/
public static PageBackgroundFill topBand(double heightRatio,
@@ -138,7 +140,7 @@ public static PageBackgroundFill topBand(double heightRatio,
* Full-width band flush with the bottom of the page (height = ratio of page height).
*
* @param heightRatio height as a fraction of the canvas height (0..1]
- * @param color fill color (required)
+ * @param color fill color (required)
* @return a {@code PageBackgroundFill} spanning the full page width at the bottom edge
*/
public static PageBackgroundFill bottomBand(double heightRatio,
@@ -151,8 +153,8 @@ public static PageBackgroundFill bottomBand(double heightRatio,
* Full-width band whose top edge sits {@code yRatioFromTop} down the page (0.0 = page top).
*
* @param yRatioFromTop top edge of the band: 0.0 = page top, 1.0 = page bottom
- * @param heightRatio height as a fraction of the canvas height (0..1]
- * @param color fill color (required)
+ * @param heightRatio height as a fraction of the canvas height (0..1]
+ * @param color fill color (required)
* @return a {@code PageBackgroundFill} spanning the full page width from {@code yRatioFromTop}
*/
public static PageBackgroundFill band(double yRatioFromTop,
@@ -166,8 +168,8 @@ public static PageBackgroundFill band(double yRatioFromTop,
* Top-aligned band sized in absolute points, converted against {@code pageHeight}.
*
* @param heightPoints band height in points
- * @param pageHeight reference page height in points used to convert points to a ratio
- * @param color fill color (required)
+ * @param pageHeight reference page height in points used to convert points to a ratio
+ * @param color fill color (required)
* @return a {@code PageBackgroundFill} spanning the full page width at the top edge
*/
public static PageBackgroundFill topBandPoints(double heightPoints,
@@ -180,9 +182,9 @@ public static PageBackgroundFill topBandPoints(double heightPoints,
* Band positioned and sized in absolute points from the page top, converted against {@code pageHeight}.
*
* @param yFromTopPoints offset of the band top edge from the page top in points
- * @param heightPoints band height in points
- * @param pageHeight reference page height in points used to convert points to ratios
- * @param color fill color (required)
+ * @param heightPoints band height in points
+ * @param pageHeight reference page height in points used to convert points to ratios
+ * @param color fill color (required)
* @return a {@code PageBackgroundFill} spanning the full page width from {@code yFromTopPoints}
*/
public static PageBackgroundFill bandPoints(double yFromTopPoints,
diff --git a/src/main/java/com/demcha/compose/document/api/PdfOutputOptionsToCanonical.java b/src/main/java/com/demcha/compose/document/api/PdfOutputOptionsToCanonical.java
index 6b3046cb2..80ba70b97 100644
--- a/src/main/java/com/demcha/compose/document/api/PdfOutputOptionsToCanonical.java
+++ b/src/main/java/com/demcha/compose/document/api/PdfOutputOptionsToCanonical.java
@@ -1,17 +1,7 @@
package com.demcha.compose.document.api;
-import com.demcha.compose.document.backend.fixed.pdf.options.PdfHeaderFooterOptions;
-import com.demcha.compose.document.backend.fixed.pdf.options.PdfHeaderFooterZone;
-import com.demcha.compose.document.backend.fixed.pdf.options.PdfProtectionOptions;
-import com.demcha.compose.document.backend.fixed.pdf.options.PdfWatermarkLayer;
-import com.demcha.compose.document.backend.fixed.pdf.options.PdfWatermarkOptions;
-import com.demcha.compose.document.backend.fixed.pdf.options.PdfWatermarkPosition;
-import com.demcha.compose.document.output.DocumentHeaderFooter;
-import com.demcha.compose.document.output.DocumentHeaderFooterZone;
-import com.demcha.compose.document.output.DocumentProtection;
-import com.demcha.compose.document.output.DocumentWatermark;
-import com.demcha.compose.document.output.DocumentWatermarkLayer;
-import com.demcha.compose.document.output.DocumentWatermarkPosition;
+import com.demcha.compose.document.backend.fixed.pdf.options.*;
+import com.demcha.compose.document.output.*;
import com.demcha.compose.document.style.DocumentColor;
/**
diff --git a/src/main/java/com/demcha/compose/document/api/SessionFontApi.java b/src/main/java/com/demcha/compose/document/api/SessionFontApi.java
index 9fb9c440c..fec73b7c0 100644
--- a/src/main/java/com/demcha/compose/document/api/SessionFontApi.java
+++ b/src/main/java/com/demcha/compose/document/api/SessionFontApi.java
@@ -65,7 +65,7 @@ public SessionFontApi registerFamily(FontFamilyDefinition definition) {
* {@link DocumentSession#registerNodeDefinition(NodeDefinition)}.
*
* @param definition node definition implementation
- * @param semantic node type handled by the definition
+ * @param semantic node type handled by the definition
* @return this facade for chaining
* @throws IllegalStateException if the owning session has already been closed
*/
diff --git a/src/main/java/com/demcha/compose/document/backend/fixed/FixedLayoutBackend.java b/src/main/java/com/demcha/compose/document/backend/fixed/FixedLayoutBackend.java
index d0c1d4895..10025c70b 100644
--- a/src/main/java/com/demcha/compose/document/backend/fixed/FixedLayoutBackend.java
+++ b/src/main/java/com/demcha/compose/document/backend/fixed/FixedLayoutBackend.java
@@ -19,7 +19,7 @@ public interface FixedLayoutBackend {
/**
* Renders one resolved layout graph.
*
- * @param graph resolved graph emitted by the semantic compiler
+ * @param graph resolved graph emitted by the semantic compiler
* @param context render-pass configuration and output target
* @return backend-specific render result
* @throws Exception if rendering fails
diff --git a/src/main/java/com/demcha/compose/document/backend/fixed/FixedLayoutRenderContext.java b/src/main/java/com/demcha/compose/document/backend/fixed/FixedLayoutRenderContext.java
index 3e50fecb9..ff4c3ce38 100644
--- a/src/main/java/com/demcha/compose/document/backend/fixed/FixedLayoutRenderContext.java
+++ b/src/main/java/com/demcha/compose/document/backend/fixed/FixedLayoutRenderContext.java
@@ -14,10 +14,10 @@
*
The context carries only document-wide render configuration. Backends must
* treat it as read-only and derive any mutable render-pass state from it.
*
- * @param canvas physical page canvas used by the resolved layout graph
+ * @param canvas physical page canvas used by the resolved layout graph
* @param customFontFamilies document-local font families available to the backend
- * @param outputFile optional file target for backends that persist artifacts to disk
- * @param outputStream optional caller-owned stream target for streaming render output
+ * @param outputFile optional file target for backends that persist artifacts to disk
+ * @param outputStream optional caller-owned stream target for streaming render output
*/
public record FixedLayoutRenderContext(
LayoutCanvas canvas,
diff --git a/src/main/java/com/demcha/compose/document/backend/fixed/pdf/PdfDocumentPostProcessor.java b/src/main/java/com/demcha/compose/document/backend/fixed/pdf/PdfDocumentPostProcessor.java
index ce03a2c33..53d95700f 100644
--- a/src/main/java/com/demcha/compose/document/backend/fixed/pdf/PdfDocumentPostProcessor.java
+++ b/src/main/java/com/demcha/compose/document/backend/fixed/pdf/PdfDocumentPostProcessor.java
@@ -34,11 +34,11 @@ private PdfDocumentPostProcessor() {
* Applies canonical document-level PDF options to an already rendered
* PDFBox document in place.
*
- * @param document target PDFBox document
- * @param canvas semantic layout canvas used to derive content margins
- * @param metadataOptions canonical metadata options, or {@code null}
- * @param watermarkOptions canonical watermark options, or {@code null}
- * @param protectionOptions canonical protection options, or {@code null}
+ * @param document target PDFBox document
+ * @param canvas semantic layout canvas used to derive content margins
+ * @param metadataOptions canonical metadata options, or {@code null}
+ * @param watermarkOptions canonical watermark options, or {@code null}
+ * @param protectionOptions canonical protection options, or {@code null}
* @param headerFooterOptions repeating header/footer options
* @throws IOException if PDFBox post-processing fails
*/
@@ -94,11 +94,11 @@ public static void apply(PDDocument document,
* Applies canonical document-level PDF options to already rendered PDF bytes
* and returns a new byte array.
*
- * @param pdfBytes rendered PDF bytes
- * @param canvas semantic layout canvas used to derive content margins
- * @param metadataOptions canonical metadata options, or {@code null}
- * @param watermarkOptions canonical watermark options, or {@code null}
- * @param protectionOptions canonical protection options, or {@code null}
+ * @param pdfBytes rendered PDF bytes
+ * @param canvas semantic layout canvas used to derive content margins
+ * @param metadataOptions canonical metadata options, or {@code null}
+ * @param watermarkOptions canonical watermark options, or {@code null}
+ * @param protectionOptions canonical protection options, or {@code null}
* @param headerFooterOptions repeating header/footer options
* @return post-processed PDF bytes
* @throws IOException if the PDF cannot be loaded or post-processed
@@ -121,9 +121,9 @@ public static byte[] apply(byte[] pdfBytes,
/**
* Returns {@code true} when any document-level post-processing option is set.
*
- * @param metadataOptions canonical metadata options, or {@code null}
- * @param watermarkOptions canonical watermark options, or {@code null}
- * @param protectionOptions canonical protection options, or {@code null}
+ * @param metadataOptions canonical metadata options, or {@code null}
+ * @param watermarkOptions canonical watermark options, or {@code null}
+ * @param protectionOptions canonical protection options, or {@code null}
* @param headerFooterOptions repeating header/footer options
* @return {@code true} when post-processing work is required
*/
@@ -132,9 +132,9 @@ public static boolean hasPostProcessing(PdfMetadataOptions metadataOptions,
PdfProtectionOptions protectionOptions,
Collection headerFooterOptions) {
return metadataOptions != null
- || watermarkOptions != null
- || protectionOptions != null
- || (headerFooterOptions != null && !headerFooterOptions.isEmpty());
+ || watermarkOptions != null
+ || protectionOptions != null
+ || (headerFooterOptions != null && !headerFooterOptions.isEmpty());
}
private static void applyProtection(PDDocument document, PdfProtectionOptions options) throws IOException {
diff --git a/src/main/java/com/demcha/compose/document/backend/fixed/pdf/PdfFixedLayoutBackend.java b/src/main/java/com/demcha/compose/document/backend/fixed/pdf/PdfFixedLayoutBackend.java
index 39254ff3e..f5dfdecca 100644
--- a/src/main/java/com/demcha/compose/document/backend/fixed/pdf/PdfFixedLayoutBackend.java
+++ b/src/main/java/com/demcha/compose/document/backend/fixed/pdf/PdfFixedLayoutBackend.java
@@ -2,35 +2,12 @@
import com.demcha.compose.document.backend.fixed.FixedLayoutBackend;
import com.demcha.compose.document.backend.fixed.FixedLayoutRenderContext;
-import com.demcha.compose.document.backend.fixed.pdf.handlers.PdfBarcodeFragmentRenderHandler;
-import com.demcha.compose.document.backend.fixed.pdf.handlers.PdfEllipseFragmentRenderHandler;
-import com.demcha.compose.document.backend.fixed.pdf.handlers.PdfPolygonFragmentRenderHandler;
-import com.demcha.compose.document.backend.fixed.pdf.handlers.PdfImageFragmentRenderHandler;
-import com.demcha.compose.document.backend.fixed.pdf.handlers.PdfLineFragmentRenderHandler;
-import com.demcha.compose.document.backend.fixed.pdf.handlers.PdfParagraphFragmentRenderHandler;
-import com.demcha.compose.document.backend.fixed.pdf.handlers.PdfShapeClipBeginRenderHandler;
-import com.demcha.compose.document.backend.fixed.pdf.handlers.PdfShapeClipEndRenderHandler;
-import com.demcha.compose.document.backend.fixed.pdf.handlers.PdfShapeFragmentRenderHandler;
-import com.demcha.compose.document.backend.fixed.pdf.handlers.PdfTableRowFragmentRenderHandler;
-import com.demcha.compose.document.backend.fixed.pdf.handlers.PdfTransformBeginRenderHandler;
-import com.demcha.compose.document.backend.fixed.pdf.handlers.PdfTransformEndRenderHandler;
-import com.demcha.compose.document.backend.fixed.pdf.options.PdfHeaderFooterOptions;
-import com.demcha.compose.document.backend.fixed.pdf.options.PdfHeaderFooterZone;
-import com.demcha.compose.document.backend.fixed.pdf.options.PdfMetadataOptions;
-import com.demcha.compose.document.backend.fixed.pdf.options.PdfProtectionOptions;
-import com.demcha.compose.document.backend.fixed.pdf.options.PdfWatermarkOptions;
+import com.demcha.compose.document.backend.fixed.pdf.handlers.*;
+import com.demcha.compose.document.backend.fixed.pdf.options.*;
import com.demcha.compose.document.exceptions.UnsupportedNodeCapabilityException;
import com.demcha.compose.document.layout.LayoutGraph;
import com.demcha.compose.document.layout.PlacedFragment;
-import com.demcha.compose.document.layout.payloads.BarcodeFragmentPayload;
-import com.demcha.compose.document.layout.payloads.ImageFragmentPayload;
-import com.demcha.compose.document.layout.payloads.ParagraphFragmentPayload;
-import com.demcha.compose.document.layout.payloads.ParagraphImageSpan;
-import com.demcha.compose.document.layout.payloads.ParagraphLine;
-import com.demcha.compose.document.layout.payloads.ParagraphSpan;
-import com.demcha.compose.document.layout.payloads.PdfSemanticFragmentPayload;
-import com.demcha.compose.document.layout.payloads.ShapeFragmentPayload;
-import com.demcha.compose.document.layout.payloads.TableRowFragmentPayload;
+import com.demcha.compose.document.layout.payloads.*;
import com.demcha.compose.font.FontLibrary;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
@@ -41,12 +18,7 @@
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
import java.util.concurrent.TimeUnit;
/**
@@ -81,6 +53,31 @@ public PdfFixedLayoutBackend() {
this(defaultHandlers(), false, null, null, null, List.of());
}
+ PdfFixedLayoutBackend(Collection extends PdfFragmentRenderHandler>> handlers) {
+ this(handlers, false, null, null, null, List.of());
+ }
+
+ private PdfFixedLayoutBackend(Collection extends PdfFragmentRenderHandler>> handlers,
+ boolean guideLines,
+ PdfMetadataOptions metadataOptions,
+ PdfWatermarkOptions watermarkOptions,
+ PdfProtectionOptions protectionOptions,
+ Collection headerFooterOptions) {
+ Map, PdfFragmentRenderHandler>> registry = new LinkedHashMap<>();
+ for (PdfFragmentRenderHandler> handler : handlers) {
+ PdfFragmentRenderHandler> previous = registry.put(handler.payloadType(), Objects.requireNonNull(handler, "handler"));
+ if (previous != null) {
+ throw new IllegalArgumentException("Duplicate PDF handler for payload type " + handler.payloadType().getName());
+ }
+ }
+ this.handlers = Map.copyOf(registry);
+ this.guideLines = guideLines;
+ this.metadataOptions = metadataOptions;
+ this.watermarkOptions = watermarkOptions;
+ this.protectionOptions = protectionOptions;
+ this.headerFooterOptions = List.copyOf(headerFooterOptions);
+ }
+
/**
* Returns a builder for PDF-specific render options.
*
@@ -106,29 +103,72 @@ private static List> defaultHandlers() {
new PdfTransformEndRenderHandler());
}
- PdfFixedLayoutBackend(Collection extends PdfFragmentRenderHandler>> handlers) {
- this(handlers, false, null, null, null, List.of());
+ private static PdfLinkAnnotationWriter.PlacedPdfRect spanLinkRectangle(ParagraphSpan span,
+ double spanX,
+ double lineTop,
+ double lineHeight,
+ double textAscent,
+ double baselineOffsetFromBottom) {
+ com.demcha.compose.document.node.InlineImageAlignment alignment;
+ double graphicHeight;
+ double baselineOffset;
+ if (span instanceof ParagraphImageSpan imageSpan) {
+ alignment = imageSpan.alignment();
+ graphicHeight = imageSpan.height();
+ baselineOffset = imageSpan.baselineOffset();
+ } else if (span instanceof com.demcha.compose.document.layout.payloads.ParagraphShapeSpan shapeSpan) {
+ alignment = shapeSpan.alignment();
+ graphicHeight = shapeSpan.height();
+ baselineOffset = shapeSpan.baselineOffset();
+ } else {
+ // Text spans cover the full line box.
+ return new PdfLinkAnnotationWriter.PlacedPdfRect(
+ spanX,
+ lineTop - lineHeight,
+ span.width(),
+ lineHeight);
+ }
+ // Inline-graphic baseline placement, kept in lockstep with
+ // PdfParagraphFragmentRenderHandler.resolveInlineGraphicBottom — both
+ // place an inline image or shape on the text baseline identically.
+ double baselineY = lineTop - lineHeight + baselineOffsetFromBottom;
+ double lineBottom = baselineY - baselineOffsetFromBottom;
+ double base = switch (alignment == null
+ ? com.demcha.compose.document.node.InlineImageAlignment.CENTER
+ : alignment) {
+ case BASELINE -> baselineY;
+ case CENTER -> lineBottom + (lineHeight - graphicHeight) / 2.0;
+ case TEXT_TOP -> baselineY + textAscent - graphicHeight;
+ case TEXT_BOTTOM -> lineBottom;
+ };
+ return new PdfLinkAnnotationWriter.PlacedPdfRect(
+ spanX,
+ base + baselineOffset,
+ span.width(),
+ graphicHeight);
}
- private PdfFixedLayoutBackend(Collection extends PdfFragmentRenderHandler>> handlers,
- boolean guideLines,
- PdfMetadataOptions metadataOptions,
- PdfWatermarkOptions watermarkOptions,
- PdfProtectionOptions protectionOptions,
- Collection headerFooterOptions) {
- Map, PdfFragmentRenderHandler>> registry = new LinkedHashMap<>();
- for (PdfFragmentRenderHandler> handler : handlers) {
- PdfFragmentRenderHandler> previous = registry.put(handler.payloadType(), Objects.requireNonNull(handler, "handler"));
+ private static List> mergeHandlers(
+ List> defaults,
+ List> additions) {
+ if (additions.isEmpty()) {
+ return defaults;
+ }
+ Map, PdfFragmentRenderHandler>> byPayloadType = new LinkedHashMap<>();
+ for (PdfFragmentRenderHandler> handler : defaults) {
+ byPayloadType.put(handler.payloadType(), handler);
+ }
+ for (PdfFragmentRenderHandler> handler : additions) {
+ PdfFragmentRenderHandler> previous = byPayloadType.put(handler.payloadType(), handler);
if (previous != null) {
- throw new IllegalArgumentException("Duplicate PDF handler for payload type " + handler.payloadType().getName());
+ RENDER_LOG.debug(
+ "render.pdf.handler.replaced payloadType={} previous={} replacement={}",
+ handler.payloadType().getName(),
+ previous.getClass().getName(),
+ handler.getClass().getName());
}
}
- this.handlers = Map.copyOf(registry);
- this.guideLines = guideLines;
- this.metadataOptions = metadataOptions;
- this.watermarkOptions = watermarkOptions;
- this.protectionOptions = protectionOptions;
- this.headerFooterOptions = List.copyOf(headerFooterOptions);
+ return List.copyOf(byPayloadType.values());
}
@Override
@@ -140,7 +180,7 @@ public String name() {
* Renders the resolved layout graph into PDF bytes and optionally writes the
* result to the configured output file.
*
- * @param graph resolved layout graph produced by the semantic compiler
+ * @param graph resolved layout graph produced by the semantic compiler
* @param context fixed-layout render configuration including page canvas and output target
* @return rendered PDF document bytes
* @throws Exception if PDF creation, rendering, or saving fails
@@ -189,7 +229,7 @@ public byte[] render(LayoutGraph graph, FixedLayoutRenderContext context) throws
* never closes it. The caller remains responsible for HTTP/file/S3 stream
* lifecycle and backpressure.
*
- * @param graph resolved layout graph produced by the semantic compiler
+ * @param graph resolved layout graph produced by the semantic compiler
* @param context fixed-layout render configuration with a non-null output stream
* @throws Exception if PDF creation, rendering, or saving fails
*/
@@ -247,7 +287,7 @@ private int renderToOutput(LayoutGraph graph, FixedLayoutRenderContext context,
for (int index = 0; index < graph.fragments().size(); index++) {
PlacedFragment fragment = graph.fragments().get(index);
if (fragment.payload() instanceof TableRowFragmentPayload
- && tableRowHandler instanceof PdfTableRowFragmentRenderHandler tableHandler) {
+ && tableRowHandler instanceof PdfTableRowFragmentRenderHandler tableHandler) {
index = renderTableRowGroup(graph.fragments(), index, tableHandler, environment, guideLines, ownerBounds);
continue;
}
@@ -278,8 +318,8 @@ private int renderTableRowGroup(List fragments,
String tablePath = fragments.get(startIndex).path();
int endExclusive = startIndex;
while (endExclusive < fragments.size()
- && Objects.equals(fragments.get(endExclusive).path(), tablePath)
- && fragments.get(endExclusive).payload() instanceof TableRowFragmentPayload) {
+ && Objects.equals(fragments.get(endExclusive).path(), tablePath)
+ && fragments.get(endExclusive).payload() instanceof TableRowFragmentPayload) {
endExclusive++;
}
@@ -407,51 +447,6 @@ private void addParagraphLinks(PlacedFragment fragment,
}
}
- private static PdfLinkAnnotationWriter.PlacedPdfRect spanLinkRectangle(ParagraphSpan span,
- double spanX,
- double lineTop,
- double lineHeight,
- double textAscent,
- double baselineOffsetFromBottom) {
- com.demcha.compose.document.node.InlineImageAlignment alignment;
- double graphicHeight;
- double baselineOffset;
- if (span instanceof ParagraphImageSpan imageSpan) {
- alignment = imageSpan.alignment();
- graphicHeight = imageSpan.height();
- baselineOffset = imageSpan.baselineOffset();
- } else if (span instanceof com.demcha.compose.document.layout.payloads.ParagraphShapeSpan shapeSpan) {
- alignment = shapeSpan.alignment();
- graphicHeight = shapeSpan.height();
- baselineOffset = shapeSpan.baselineOffset();
- } else {
- // Text spans cover the full line box.
- return new PdfLinkAnnotationWriter.PlacedPdfRect(
- spanX,
- lineTop - lineHeight,
- span.width(),
- lineHeight);
- }
- // Inline-graphic baseline placement, kept in lockstep with
- // PdfParagraphFragmentRenderHandler.resolveInlineGraphicBottom — both
- // place an inline image or shape on the text baseline identically.
- double baselineY = lineTop - lineHeight + baselineOffsetFromBottom;
- double lineBottom = baselineY - baselineOffsetFromBottom;
- double base = switch (alignment == null
- ? com.demcha.compose.document.node.InlineImageAlignment.CENTER
- : alignment) {
- case BASELINE -> baselineY;
- case CENTER -> lineBottom + (lineHeight - graphicHeight) / 2.0;
- case TEXT_TOP -> baselineY + textAscent - graphicHeight;
- case TEXT_BOTTOM -> lineBottom;
- };
- return new PdfLinkAnnotationWriter.PlacedPdfRect(
- spanX,
- base + baselineOffset,
- span.width(),
- graphicHeight);
- }
-
@SuppressWarnings("unchecked")
private PdfFragmentRenderHandler
*
- * @param fragment placed row fragment to render
- * @param payload table-row payload carrying the resolved cells
+ * @param fragment placed row fragment to render
+ * @param payload table-row payload carrying the resolved cells
* @param environment active PDF render environment
* @throws java.io.IOException if writing to the PDF content stream fails
*/
@@ -74,8 +74,8 @@ public void renderFills(PlacedFragment fragment,
/**
* Paints table cell borders and text for one row fragment.
*
- * @param fragment placed row fragment to render
- * @param payload table-row payload carrying the resolved cells
+ * @param fragment placed row fragment to render
+ * @param payload table-row payload carrying the resolved cells
* @param environment active PDF render environment
* @throws java.io.IOException if writing to the PDF content stream fails
*/
diff --git a/src/main/java/com/demcha/compose/document/backend/fixed/pdf/options/PdfBarcodeOptions.java b/src/main/java/com/demcha/compose/document/backend/fixed/pdf/options/PdfBarcodeOptions.java
index 6254b3ffe..8e71f134e 100644
--- a/src/main/java/com/demcha/compose/document/backend/fixed/pdf/options/PdfBarcodeOptions.java
+++ b/src/main/java/com/demcha/compose/document/backend/fixed/pdf/options/PdfBarcodeOptions.java
@@ -5,7 +5,7 @@
import lombok.Builder;
import lombok.Getter;
-import java.awt.Color;
+import java.awt.*;
/**
* Canonical barcode payload configuration attached to semantic barcode nodes.
diff --git a/src/main/java/com/demcha/compose/document/backend/fixed/pdf/options/PdfHeaderFooterOptions.java b/src/main/java/com/demcha/compose/document/backend/fixed/pdf/options/PdfHeaderFooterOptions.java
index a031e6f9f..7a1625d23 100644
--- a/src/main/java/com/demcha/compose/document/backend/fixed/pdf/options/PdfHeaderFooterOptions.java
+++ b/src/main/java/com/demcha/compose/document/backend/fixed/pdf/options/PdfHeaderFooterOptions.java
@@ -5,7 +5,7 @@
import lombok.Builder;
import lombok.Getter;
-import java.awt.Color;
+import java.awt.*;
/**
* Canonical repeating header/footer configuration for the semantic PDF API.
diff --git a/src/main/java/com/demcha/compose/document/backend/fixed/pdf/options/PdfWatermarkOptions.java b/src/main/java/com/demcha/compose/document/backend/fixed/pdf/options/PdfWatermarkOptions.java
index 24354055a..95ff1a550 100644
--- a/src/main/java/com/demcha/compose/document/backend/fixed/pdf/options/PdfWatermarkOptions.java
+++ b/src/main/java/com/demcha/compose/document/backend/fixed/pdf/options/PdfWatermarkOptions.java
@@ -5,7 +5,7 @@
import lombok.Builder;
import lombok.Getter;
-import java.awt.Color;
+import java.awt.*;
import java.nio.file.Path;
/**
diff --git a/src/main/java/com/demcha/compose/document/chart/AxisSpec.java b/src/main/java/com/demcha/compose/document/chart/AxisSpec.java
index e020ff27c..4bcf358db 100644
--- a/src/main/java/com/demcha/compose/document/chart/AxisSpec.java
+++ b/src/main/java/com/demcha/compose/document/chart/AxisSpec.java
@@ -11,13 +11,12 @@
*
* @param baselineAtZero force the axis to include zero; recommended for bars to
* avoid misleading truncated baselines
- * @param min explicit lower bound, or {@code null} to derive from data
- * @param max explicit upper bound, or {@code null} to derive from data
- * @param format number format applied to axis tick labels
- * @param showGridLines emit a horizontal grid line per major tick
+ * @param min explicit lower bound, or {@code null} to derive from data
+ * @param max explicit upper bound, or {@code null} to derive from data
+ * @param format number format applied to axis tick labels
+ * @param showGridLines emit a horizontal grid line per major tick
* @param showTickLabels emit the numeric tick label for each major tick; when
* {@code false} the value axis reserves no left gutter
- *
* @author Artem Demchyshyn
* @since 1.8.0
*/
@@ -29,7 +28,9 @@ public record AxisSpec(
boolean showGridLines,
boolean showTickLabels
) {
- /** Validates explicit bounds and normalizes the format. */
+ /**
+ * Validates explicit bounds and normalizes the format.
+ */
public AxisSpec {
if (min != null && max != null && min >= max) {
throw new IllegalArgumentException("axis min must be < max: " + min + " >= " + max);
@@ -42,10 +43,10 @@ public record AxisSpec(
* showing tick labels).
*
* @param baselineAtZero include zero
- * @param min explicit lower bound or {@code null}
- * @param max explicit upper bound or {@code null}
- * @param format tick-label number format
- * @param showGridLines draw grid lines
+ * @param min explicit lower bound or {@code null}
+ * @param max explicit upper bound or {@code null}
+ * @param format tick-label number format
+ * @param showGridLines draw grid lines
*/
public AxisSpec(boolean baselineAtZero, Double min, Double max,
NumberFormatSpec format, boolean showGridLines) {
@@ -70,7 +71,9 @@ public static Builder builder() {
return new Builder();
}
- /** Fluent builder for {@link AxisSpec}. */
+ /**
+ * Fluent builder for {@link AxisSpec}.
+ */
public static final class Builder {
private boolean baselineAtZero = true;
private Double min;
diff --git a/src/main/java/com/demcha/compose/document/chart/BarChartLayout.java b/src/main/java/com/demcha/compose/document/chart/BarChartLayout.java
index 228f2c6ff..1014c2a0f 100644
--- a/src/main/java/com/demcha/compose/document/chart/BarChartLayout.java
+++ b/src/main/java/com/demcha/compose/document/chart/BarChartLayout.java
@@ -3,22 +3,12 @@
import com.demcha.compose.document.node.LineNode;
import com.demcha.compose.document.node.ShapeNode;
import com.demcha.compose.document.node.TextAlign;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentCornerRadius;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentPaint;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextStyle;
+import com.demcha.compose.document.style.*;
import java.util.ArrayList;
import java.util.List;
-import static com.demcha.compose.document.chart.ChartLayoutSupport.GAP;
-import static com.demcha.compose.document.chart.ChartLayoutSupport.MIN_BAR_HEIGHT;
-import static com.demcha.compose.document.chart.ChartLayoutSupport.emitChipLabel;
-import static com.demcha.compose.document.chart.ChartLayoutSupport.inkCenter;
-import static com.demcha.compose.document.chart.ChartLayoutSupport.label;
-import static com.demcha.compose.document.chart.ChartLayoutSupport.valueLabelGap;
+import static com.demcha.compose.document.chart.ChartLayoutSupport.*;
/**
* Geometry for vertical and horizontal bar charts, grouped or stacked, with
diff --git a/src/main/java/com/demcha/compose/document/chart/BarGrouping.java b/src/main/java/com/demcha/compose/document/chart/BarGrouping.java
index b66fcf4f4..c7130b103 100644
--- a/src/main/java/com/demcha/compose/document/chart/BarGrouping.java
+++ b/src/main/java/com/demcha/compose/document/chart/BarGrouping.java
@@ -7,8 +7,12 @@
* @since 1.8.0
*/
public enum BarGrouping {
- /** Series render side by side inside the category slot. */
+ /**
+ * Series render side by side inside the category slot.
+ */
GROUPED,
- /** Series stack on top of each other; the axis scales to stacked sums. */
+ /**
+ * Series stack on top of each other; the axis scales to stacked sums.
+ */
STACKED
}
diff --git a/src/main/java/com/demcha/compose/document/chart/ChartData.java b/src/main/java/com/demcha/compose/document/chart/ChartData.java
index ff0655188..6d441b10e 100644
--- a/src/main/java/com/demcha/compose/document/chart/ChartData.java
+++ b/src/main/java/com/demcha/compose/document/chart/ChartData.java
@@ -15,14 +15,15 @@
* authoring time rather than producing a skewed plot.
*
* @param categories ordered category (x-axis) labels; at least one
- * @param series ordered value series; at least one, each aligned to categories
- *
+ * @param series ordered value series; at least one, each aligned to categories
* @author Artem Demchyshyn
* @since 1.8.0
*/
public record ChartData(List categories, List series) {
- /** Defensively copies both lists and enforces the alignment invariant. */
+ /**
+ * Defensively copies both lists and enforces the alignment invariant.
+ */
public ChartData {
Objects.requireNonNull(categories, "categories");
Objects.requireNonNull(series, "series");
@@ -43,6 +44,15 @@ public record ChartData(List categories, List series) {
}
}
+ /**
+ * Starts a mutable builder.
+ *
+ * @return new builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
/**
* Number of value series.
*
@@ -61,24 +71,17 @@ public int categoryCount() {
return categories.size();
}
- /**
- * Starts a mutable builder.
- *
- * @return new builder
- */
- public static Builder builder() {
- return new Builder();
- }
-
/**
* One named value series. {@code null} entries are allowed and mean a
* missing point — a gap in a line, a skipped bar — distinct from {@code 0}.
*
- * @param name legend label for this series
+ * @param name legend label for this series
* @param values value per category, aligned by index; entries may be null
*/
public record Series(String name, List values) {
- /** Normalizes the name and tolerates {@code null} value entries. */
+ /**
+ * Normalizes the name and tolerates {@code null} value entries.
+ */
public Series {
name = name == null ? "" : name;
Objects.requireNonNull(values, "values");
@@ -88,7 +91,7 @@ public record Series(String name, List values) {
/**
* Convenience: build a series from a name and a primitive run.
*
- * @param name series name
+ * @param name series name
* @param values value run
* @return series
*/
@@ -101,7 +104,9 @@ public static Series of(String name, double... values) {
}
}
- /** Mutable builder; produces an immutable {@link ChartData}. */
+ /**
+ * Mutable builder; produces an immutable {@link ChartData}.
+ */
public static final class Builder {
private final List categories = new ArrayList<>();
private final List series = new ArrayList<>();
@@ -142,7 +147,7 @@ public Builder series(Series s) {
/**
* Adds a value series from a name and a primitive run.
*
- * @param name series name
+ * @param name series name
* @param values value run
* @return this builder
*/
diff --git a/src/main/java/com/demcha/compose/document/chart/ChartDefaults.java b/src/main/java/com/demcha/compose/document/chart/ChartDefaults.java
index 34cc1c2b0..0cb781d5e 100644
--- a/src/main/java/com/demcha/compose/document/chart/ChartDefaults.java
+++ b/src/main/java/com/demcha/compose/document/chart/ChartDefaults.java
@@ -23,13 +23,19 @@
*/
public final class ChartDefaults {
- /** Fraction of a category slot a bar group fills when no style overrides it. */
+ /**
+ * Fraction of a category slot a bar group fills when no style overrides it.
+ */
public static final double BAR_WIDTH_RATIO = 0.72;
- /** Default number of axis tick intervals requested from {@link NiceScale}. */
+ /**
+ * Default number of axis tick intervals requested from {@link NiceScale}.
+ */
public static final int TARGET_TICKS = 5;
- /** Default professional series palette (Tableau-10 inspired, deterministic). */
+ /**
+ * Default professional series palette (Tableau-10 inspired, deterministic).
+ */
public static final List DEFAULT_PALETTE = List.of(
DocumentPaint.solid(DocumentColor.rgb(78, 121, 167)),
DocumentPaint.solid(DocumentColor.rgb(242, 142, 43)),
@@ -40,25 +46,33 @@ public final class ChartDefaults {
DocumentPaint.solid(DocumentColor.rgb(176, 122, 161)),
DocumentPaint.solid(DocumentColor.rgb(156, 117, 95)));
- /** Default grid line stroke — a thin light-grey rule. */
+ /**
+ * Default grid line stroke — a thin light-grey rule.
+ */
public static final DocumentStroke DEFAULT_GRID_STROKE =
DocumentStroke.of(DocumentColor.rgb(224, 224, 224), 0.5);
- /** Default tick / category label style. */
+ /**
+ * Default tick / category label style.
+ */
public static final DocumentTextStyle AXIS_TEXT_STYLE = DocumentTextStyle.builder()
.fontName(FontName.HELVETICA)
.size(8)
.color(DocumentColor.rgb(90, 90, 90))
.build();
- /** Default legend label style. */
+ /**
+ * Default legend label style.
+ */
public static final DocumentTextStyle LEGEND_TEXT_STYLE = DocumentTextStyle.builder()
.fontName(FontName.HELVETICA)
.size(9)
.color(DocumentColor.rgb(60, 60, 60))
.build();
- /** Default value-label style. */
+ /**
+ * Default value-label style.
+ */
public static final DocumentTextStyle VALUE_LABEL_TEXT_STYLE = DocumentTextStyle.builder()
.fontName(FontName.HELVETICA)
.size(8)
@@ -74,21 +88,29 @@ public final class ChartDefaults {
public static final DocumentPaint VALUE_LABEL_HALO =
DocumentPaint.solid(DocumentColor.WHITE);
- /** Default pie/donut slice separator — a white 1pt stroke between slices. */
+ /**
+ * Default pie/donut slice separator — a white 1pt stroke between slices.
+ */
public static final DocumentStroke SLICE_STROKE =
DocumentStroke.of(DocumentColor.WHITE, 1.0);
- /** Default donut-centre KPI text style. */
+ /**
+ * Default donut-centre KPI text style.
+ */
public static final DocumentTextStyle DONUT_CENTER_TEXT_STYLE = DocumentTextStyle.builder()
.fontName(FontName.HELVETICA_BOLD)
.size(13)
.color(DocumentColor.rgb(45, 45, 45))
.build();
- /** Arc tessellation step for pie/donut sector polygons, in degrees. */
+ /**
+ * Arc tessellation step for pie/donut sector polygons, in degrees.
+ */
public static final double SECTOR_TESSELLATION_STEP_DEGREES = 3.0;
- /** Built-in default chart theme used when no document theme is supplied. */
+ /**
+ * Built-in default chart theme used when no document theme is supplied.
+ */
public static final ChartTheme DEFAULT_THEME = new ChartTheme(
DEFAULT_PALETTE,
DEFAULT_GRID_STROKE,
diff --git a/src/main/java/com/demcha/compose/document/chart/ChartLayoutResolver.java b/src/main/java/com/demcha/compose/document/chart/ChartLayoutResolver.java
index c50d8c60f..d64ee6977 100644
--- a/src/main/java/com/demcha/compose/document/chart/ChartLayoutResolver.java
+++ b/src/main/java/com/demcha/compose/document/chart/ChartLayoutResolver.java
@@ -30,11 +30,11 @@ private ChartLayoutResolver() {
/**
* Resolves a chart spec into positioned primitive children.
*
- * @param spec what to plot
- * @param style fully-coalesced style (theme already merged in)
- * @param theme active chart theme (supplies the fallback palette)
- * @param width chart inner box width in points
- * @param height chart inner box height in points
+ * @param spec what to plot
+ * @param style fully-coalesced style (theme already merged in)
+ * @param theme active chart theme (supplies the fallback palette)
+ * @param width chart inner box width in points
+ * @param height chart inner box height in points
* @param metrics text measurement seam for label sizing
* @return positioned primitive nodes filling the chart box; never null
*/
diff --git a/src/main/java/com/demcha/compose/document/chart/ChartLayoutSupport.java b/src/main/java/com/demcha/compose/document/chart/ChartLayoutSupport.java
index 35a625445..ef63b4e1d 100644
--- a/src/main/java/com/demcha/compose/document/chart/ChartLayoutSupport.java
+++ b/src/main/java/com/demcha/compose/document/chart/ChartLayoutSupport.java
@@ -4,11 +4,7 @@
import com.demcha.compose.document.node.ParagraphNode;
import com.demcha.compose.document.node.ShapeNode;
import com.demcha.compose.document.node.TextAlign;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentCornerRadius;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextStyle;
+import com.demcha.compose.document.style.*;
import java.util.ArrayList;
import java.util.List;
@@ -33,43 +29,14 @@ final class ChartLayoutSupport {
static final double DEFAULT_VALUE_LABEL_OFFSET = 2.0;
static final double HALO_PAD_X = 2.0;
static final double HALO_PAD_Y = 1.0;
- /** Cap height as a fraction of font size (Helvetica-class fonts ≈ 0.72em). */
+ /**
+ * Cap height as a fraction of font size (Helvetica-class fonts ≈ 0.72em).
+ */
static final double CAP_HEIGHT_RATIO = 0.70;
private ChartLayoutSupport() {
}
- /** One legend entry: a swatch colour plus its label. */
- record LegendEntry(String name, DocumentColor color) {
- }
-
- /** Space reserved for the legend on each side of the plot. */
- record LegendReserve(double bottomH, double topH, double rightW) {
- static final LegendReserve NONE = new LegendReserve(0, 0, 0);
- }
-
- /** Plot rectangle and scale, all in bottom-up inner-box coordinates. */
- record Frame(NiceScale scale, double plotLeftX, double plotRightX,
- double plotBottomY, double plotTopY,
- double leftGutter, double legendH,
- double axisLineH, double legendLineH, double valueLineH) {
- double plotWidth() {
- return plotRightX - plotLeftX;
- }
-
- double plotHeight() {
- return plotTopY - plotBottomY;
- }
-
- double yForValue(double value) {
- return plotBottomY + scale.fractionOf(value) * plotHeight();
- }
-
- double plotCenterY() {
- return (plotBottomY + plotTopY) / 2.0;
- }
- }
-
static List seriesLegendEntries(ChartData data, ChartStyle style,
ChartTheme theme) {
List entries = new ArrayList<>(data.seriesCount());
@@ -81,7 +48,9 @@ static List seriesLegendEntries(ChartData data, ChartStyle style,
return entries;
}
- /** Computes the strip/column space the legend reserves around the plot. */
+ /**
+ * Computes the strip/column space the legend reserves around the plot.
+ */
static LegendReserve legendReserve(LegendPosition position, List entries,
ChartStyle style, ChartTextMetrics metrics) {
if (position == LegendPosition.NONE || entries.isEmpty()) {
@@ -191,7 +160,7 @@ static double[] domain(ChartData data, boolean stacked, boolean includeZero) {
min = Math.min(min, 0.0);
max = Math.max(max, 0.0);
}
- return new double[] {min, max};
+ return new double[]{min, max};
}
static void emitGridAndTicks(List out, Frame f, AxisSpec axis,
@@ -220,7 +189,9 @@ static void emitGridAndTicks(List out, Frame f, AxisSpec axis,
}
}
- /** Emits one vertical category-separator grid line per inner slot boundary. */
+ /**
+ * Emits one vertical category-separator grid line per inner slot boundary.
+ */
static void emitVerticalGrid(List out, Frame f, int categoryCount,
ChartStyle style) {
DocumentStroke stroke = style.grid() == null ? null : style.grid().vertical();
@@ -316,7 +287,9 @@ private static void emitLegendEntry(List out, LegendEntry entry,
x + SWATCH_SIZE + SWATCH_LABEL_GAP, labelBottom, labelW, legendLineH));
}
- /** Emits an optional halo chip followed by a centred label box. */
+ /**
+ * Emits an optional halo chip followed by a centred label box.
+ */
static void emitChipLabel(List out, String name, String text,
DocumentTextStyle textStyle, DocumentColor halo,
double centerX, double yBottom, double labelW, double lineH) {
@@ -370,4 +343,41 @@ static void requireSupportedValueLabels(ValueLabelMode mode) {
"ValueLabelMode.INSIDE is not yet supported; use OUTSIDE or NONE");
}
}
+
+ /**
+ * One legend entry: a swatch colour plus its label.
+ */
+ record LegendEntry(String name, DocumentColor color) {
+ }
+
+ /**
+ * Space reserved for the legend on each side of the plot.
+ */
+ record LegendReserve(double bottomH, double topH, double rightW) {
+ static final LegendReserve NONE = new LegendReserve(0, 0, 0);
+ }
+
+ /**
+ * Plot rectangle and scale, all in bottom-up inner-box coordinates.
+ */
+ record Frame(NiceScale scale, double plotLeftX, double plotRightX,
+ double plotBottomY, double plotTopY,
+ double leftGutter, double legendH,
+ double axisLineH, double legendLineH, double valueLineH) {
+ double plotWidth() {
+ return plotRightX - plotLeftX;
+ }
+
+ double plotHeight() {
+ return plotTopY - plotBottomY;
+ }
+
+ double yForValue(double value) {
+ return plotBottomY + scale.fractionOf(value) * plotHeight();
+ }
+
+ double plotCenterY() {
+ return (plotBottomY + plotTopY) / 2.0;
+ }
+ }
}
diff --git a/src/main/java/com/demcha/compose/document/chart/ChartPrimitive.java b/src/main/java/com/demcha/compose/document/chart/ChartPrimitive.java
index 32de15821..b4b6296c0 100644
--- a/src/main/java/com/demcha/compose/document/chart/ChartPrimitive.java
+++ b/src/main/java/com/demcha/compose/document/chart/ChartPrimitive.java
@@ -16,17 +16,18 @@
* within (matching the node's intrinsic size for shapes and lines, and the
* label box for paragraphs).
*
- * @param node the primitive node (bar, line segment, grid line, label, swatch)
- * @param x left edge of the box, points from the inner box's left edge
- * @param y bottom edge of the box, points from the inner box's bottom edge
- * @param width box width in points (positive)
+ * @param node the primitive node (bar, line segment, grid line, label, swatch)
+ * @param x left edge of the box, points from the inner box's left edge
+ * @param y bottom edge of the box, points from the inner box's bottom edge
+ * @param width box width in points (positive)
* @param height box height in points (positive)
- *
* @author Artem Demchyshyn
* @since 1.8.0
*/
public record ChartPrimitive(DocumentNode node, double x, double y, double width, double height) {
- /** Validates the node reference, finite coordinates, and positive box. */
+ /**
+ * Validates the node reference, finite coordinates, and positive box.
+ */
public ChartPrimitive {
Objects.requireNonNull(node, "node");
requireFinite(x, "x");
diff --git a/src/main/java/com/demcha/compose/document/chart/ChartSize.java b/src/main/java/com/demcha/compose/document/chart/ChartSize.java
index 39d7f235a..a46f21447 100644
--- a/src/main/java/com/demcha/compose/document/chart/ChartSize.java
+++ b/src/main/java/com/demcha/compose/document/chart/ChartSize.java
@@ -10,14 +10,6 @@
*/
public sealed interface ChartSize permits ChartSize.Fixed, ChartSize.AspectRatio {
- /**
- * Resolves the chart height in points.
- *
- * @param availableWidth width handed down by the layout pass
- * @return chart height in points
- */
- double resolveHeight(double availableWidth);
-
/**
* Height fixed in points regardless of width.
*
@@ -39,20 +31,31 @@ static ChartSize aspectRatio(double w, double h) {
return new AspectRatio(w, h);
}
+ /**
+ * Resolves the chart height in points.
+ *
+ * @param availableWidth width handed down by the layout pass
+ * @return chart height in points
+ */
+ double resolveHeight(double availableWidth);
+
/**
* Fixed-height policy.
*
* @param points height in points
*/
record Fixed(double points) implements ChartSize {
- /** Validates the fixed height. */
+ /**
+ * Validates the fixed height.
+ */
public Fixed {
if (points <= 0 || Double.isNaN(points) || Double.isInfinite(points)) {
throw new IllegalArgumentException("fixed height must be finite and positive: " + points);
}
}
- @Override public double resolveHeight(double availableWidth) {
+ @Override
+ public double resolveHeight(double availableWidth) {
return points;
}
}
@@ -64,14 +67,17 @@ record Fixed(double points) implements ChartSize {
* @param h ratio height term
*/
record AspectRatio(double w, double h) implements ChartSize {
- /** Validates the ratio terms. */
+ /**
+ * Validates the ratio terms.
+ */
public AspectRatio {
if (w <= 0 || h <= 0 || Double.isNaN(w) || Double.isNaN(h)) {
throw new IllegalArgumentException("aspect ratio sides must be positive: " + w + ":" + h);
}
}
- @Override public double resolveHeight(double availableWidth) {
+ @Override
+ public double resolveHeight(double availableWidth) {
return availableWidth * (h / w);
}
}
diff --git a/src/main/java/com/demcha/compose/document/chart/ChartSpec.java b/src/main/java/com/demcha/compose/document/chart/ChartSpec.java
index d1a21bad0..6e52aa2c3 100644
--- a/src/main/java/com/demcha/compose/document/chart/ChartSpec.java
+++ b/src/main/java/com/demcha/compose/document/chart/ChartSpec.java
@@ -19,6 +19,33 @@
*/
public sealed interface ChartSpec permits ChartSpec.Bar, ChartSpec.Line, ChartSpec.Pie {
+ /**
+ * Starts a bar-chart builder.
+ *
+ * @return bar builder
+ */
+ static Bar.Builder bar() {
+ return new Bar.Builder();
+ }
+
+ /**
+ * Starts a line-chart builder.
+ *
+ * @return line builder
+ */
+ static Line.Builder line() {
+ return new Line.Builder();
+ }
+
+ /**
+ * Starts a pie/donut-chart builder.
+ *
+ * @return pie builder
+ */
+ static Pie.Builder pie() {
+ return new Pie.Builder();
+ }
+
/**
* Tabular data backing this chart.
*
@@ -49,43 +76,16 @@ public sealed interface ChartSpec permits ChartSpec.Bar, ChartSpec.Line, ChartSp
*/
ChartSize size();
- /**
- * Starts a bar-chart builder.
- *
- * @return bar builder
- */
- static Bar.Builder bar() {
- return new Bar.Builder();
- }
-
- /**
- * Starts a line-chart builder.
- *
- * @return line builder
- */
- static Line.Builder line() {
- return new Line.Builder();
- }
-
- /**
- * Starts a pie/donut-chart builder.
- *
- * @return pie builder
- */
- static Pie.Builder pie() {
- return new Pie.Builder();
- }
-
/**
* Bar chart: vertical or horizontal, grouped or stacked.
*
- * @param data tabular data
- * @param horizontal true = bars run horizontally (categories on y)
- * @param grouping side-by-side vs stacked when multiple series
- * @param valueAxis numeric-axis configuration
- * @param legend legend placement
- * @param valueLabels per-bar value label mode
- * @param size width-responsive sizing policy
+ * @param data tabular data
+ * @param horizontal true = bars run horizontally (categories on y)
+ * @param grouping side-by-side vs stacked when multiple series
+ * @param valueAxis numeric-axis configuration
+ * @param legend legend placement
+ * @param valueLabels per-bar value label mode
+ * @param size width-responsive sizing policy
* @param showCategoryLabels emit the category (x-axis) label under each slot
*/
record Bar(
@@ -98,7 +98,9 @@ record Bar(
ChartSize size,
boolean showCategoryLabels
) implements ChartSpec {
- /** Normalizes structural defaults. */
+ /**
+ * Normalizes structural defaults.
+ */
public Bar {
Objects.requireNonNull(data, "data");
grouping = grouping == null ? BarGrouping.GROUPED : grouping;
@@ -108,29 +110,31 @@ record Bar(
size = size == null ? ChartSize.aspectRatio(16, 9) : size;
}
- @Override
- public NumberFormatSpec valueFormat() {
- return valueAxis.format();
- }
-
/**
* Backward-compatible constructor without the category-label toggle
* (defaults to showing category labels).
*
- * @param data tabular data
- * @param horizontal horizontal orientation
- * @param grouping multi-series grouping
- * @param valueAxis numeric-axis configuration
- * @param legend legend placement
+ * @param data tabular data
+ * @param horizontal horizontal orientation
+ * @param grouping multi-series grouping
+ * @param valueAxis numeric-axis configuration
+ * @param legend legend placement
* @param valueLabels per-bar value label mode
- * @param size sizing policy
+ * @param size sizing policy
*/
public Bar(ChartData data, boolean horizontal, BarGrouping grouping, AxisSpec valueAxis,
LegendPosition legend, ValueLabelMode valueLabels, ChartSize size) {
this(data, horizontal, grouping, valueAxis, legend, valueLabels, size, true);
}
- /** Fluent builder for a {@link Bar} spec. */
+ @Override
+ public NumberFormatSpec valueFormat() {
+ return valueAxis.format();
+ }
+
+ /**
+ * Fluent builder for a {@link Bar} spec.
+ */
public static final class Builder {
private ChartData data;
private boolean horizontal = false;
@@ -245,14 +249,14 @@ public Bar build() {
* Line chart: one polyline per series, optional point markers (markers come
* from {@link ChartStyle#pointMarker()} so the geometry is reused).
*
- * @param data tabular data
- * @param smooth true = curved (Catmull-Rom) segments; false = straight
- * @param area fill the region between each series and the axis baseline
- * (translucent series colour; see {@code ChartStyle.areaOpacity})
- * @param valueAxis numeric-axis configuration
- * @param legend legend placement
- * @param valueLabels per-point value label mode
- * @param size width-responsive sizing policy
+ * @param data tabular data
+ * @param smooth true = curved (Catmull-Rom) segments; false = straight
+ * @param area fill the region between each series and the axis baseline
+ * (translucent series colour; see {@code ChartStyle.areaOpacity})
+ * @param valueAxis numeric-axis configuration
+ * @param legend legend placement
+ * @param valueLabels per-point value label mode
+ * @param size width-responsive sizing policy
* @param showCategoryLabels emit the category (x-axis) label under each slot
*/
record Line(
@@ -265,7 +269,9 @@ record Line(
ChartSize size,
boolean showCategoryLabels
) implements ChartSpec {
- /** Normalizes structural defaults. */
+ /**
+ * Normalizes structural defaults.
+ */
public Line {
Objects.requireNonNull(data, "data");
valueAxis = valueAxis == null ? AxisSpec.defaults() : valueAxis;
@@ -274,28 +280,30 @@ record Line(
size = size == null ? ChartSize.aspectRatio(16, 9) : size;
}
- @Override
- public NumberFormatSpec valueFormat() {
- return valueAxis.format();
- }
-
/**
* Backward-compatible constructor without the area and category-label
* toggles (no area fill; category labels shown).
*
- * @param data tabular data
- * @param smooth curved segments
- * @param valueAxis numeric-axis configuration
- * @param legend legend placement
+ * @param data tabular data
+ * @param smooth curved segments
+ * @param valueAxis numeric-axis configuration
+ * @param legend legend placement
* @param valueLabels per-point value label mode
- * @param size sizing policy
+ * @param size sizing policy
*/
public Line(ChartData data, boolean smooth, AxisSpec valueAxis, LegendPosition legend,
ValueLabelMode valueLabels, ChartSize size) {
this(data, smooth, false, valueAxis, legend, valueLabels, size, true);
}
- /** Fluent builder for a {@link Line} spec. */
+ @Override
+ public NumberFormatSpec valueFormat() {
+ return valueAxis.format();
+ }
+
+ /**
+ * Fluent builder for a {@link Line} spec.
+ */
public static final class Builder {
private ChartData data;
private boolean smooth = false;
@@ -415,19 +423,19 @@ public Line build() {
* unrepresentable here by design — the spec carries its own value/percent
* formats instead.
*
- * @param data tabular data; must contain exactly one series
- * @param donutRatio 0 for a solid pie; (0..0.9] = hole radius as a fraction
- * of the outer radius
+ * @param data tabular data; must contain exactly one series
+ * @param donutRatio 0 for a solid pie; (0..0.9] = hole radius as a fraction
+ * of the outer radius
* @param startAngleDegrees angle of the first slice's leading edge
* (90 = twelve o'clock)
- * @param clockwise slice layout direction
- * @param sliceLabels what each slice's outside label shows
- * @param valueFormat format for {@link SliceLabelMode#VALUE} labels
- * @param percentFormat format for percent labels (suffix included)
- * @param centerText optional KPI text in the donut hole; requires
- * {@code donutRatio > 0}
- * @param legend legend placement; lists category names
- * @param size width-responsive sizing policy (1:1 by default)
+ * @param clockwise slice layout direction
+ * @param sliceLabels what each slice's outside label shows
+ * @param valueFormat format for {@link SliceLabelMode#VALUE} labels
+ * @param percentFormat format for percent labels (suffix included)
+ * @param centerText optional KPI text in the donut hole; requires
+ * {@code donutRatio > 0}
+ * @param legend legend placement; lists category names
+ * @param size width-responsive sizing policy (1:1 by default)
*/
record Pie(
ChartData data,
@@ -441,7 +449,9 @@ record Pie(
LegendPosition legend,
ChartSize size
) implements ChartSpec {
- /** Validates the single-series invariant and the ratio/angle ranges. */
+ /**
+ * Validates the single-series invariant and the ratio/angle ranges.
+ */
public Pie {
Objects.requireNonNull(data, "data");
if (data.seriesCount() != 1) {
@@ -467,7 +477,9 @@ record Pie(
}
}
- /** Fluent builder for a {@link Pie} spec. */
+ /**
+ * Fluent builder for a {@link Pie} spec.
+ */
public static final class Builder {
private ChartData data;
private double donutRatio = 0.0;
diff --git a/src/main/java/com/demcha/compose/document/chart/ChartStyle.java b/src/main/java/com/demcha/compose/document/chart/ChartStyle.java
index 2c2b91534..7f6bc5314 100644
--- a/src/main/java/com/demcha/compose/document/chart/ChartStyle.java
+++ b/src/main/java/com/demcha/compose/document/chart/ChartStyle.java
@@ -31,32 +31,31 @@
* the gradient work), the {@link PointMarker} ellipse marker, and the small
* {@link GridStyle} record below.
*
- * @param palette ordered series paints
+ * @param palette ordered series paints
* @param seriesPaintOverrides explicit per-series paint by zero-based index
- * @param lineWidth stroke width for line series in points, or {@code null} for
- * the default; series colour always comes from the paint cascade
- * @param barCornerRadius per-bar corner radius, or {@code null}
- * @param barWidthRatio fraction (0,1] of the category slot a bar group fills
- * @param grid grid-line configuration
- * @param pointMarker ellipse marker drawn at every line-chart data point, or
- * {@code null} for none; see {@link PointMarker}
- * @param valueLabelOffset gap in points between a bar top / point marker and its
- * value label, or {@code null} for the default
- * @param axisTextStyle tick / category label style
- * @param legendTextStyle legend label style
- * @param valueLabelTextStyle value-label style
- * @param valueLabelHalo halo chip painted behind line-chart value labels so the
- * digits stay legible where line strokes cross them; match
- * it to the chart's surface colour on non-white backgrounds
- * @param areaOpacity opacity of the area fill under {@code ChartSpec.line().area(true)}
- * series, in (0..1], or {@code null} for the default (0.35)
- * @param sliceStroke pie/donut slice separator stroke, or {@code null} for the
- * themed default (white 1pt)
- * @param sliceGapDegrees angular gap between pie/donut slices (pad angle), or
- * {@code null} for none
+ * @param lineWidth stroke width for line series in points, or {@code null} for
+ * the default; series colour always comes from the paint cascade
+ * @param barCornerRadius per-bar corner radius, or {@code null}
+ * @param barWidthRatio fraction (0,1] of the category slot a bar group fills
+ * @param grid grid-line configuration
+ * @param pointMarker ellipse marker drawn at every line-chart data point, or
+ * {@code null} for none; see {@link PointMarker}
+ * @param valueLabelOffset gap in points between a bar top / point marker and its
+ * value label, or {@code null} for the default
+ * @param axisTextStyle tick / category label style
+ * @param legendTextStyle legend label style
+ * @param valueLabelTextStyle value-label style
+ * @param valueLabelHalo halo chip painted behind line-chart value labels so the
+ * digits stay legible where line strokes cross them; match
+ * it to the chart's surface colour on non-white backgrounds
+ * @param areaOpacity opacity of the area fill under {@code ChartSpec.line().area(true)}
+ * series, in (0..1], or {@code null} for the default (0.35)
+ * @param sliceStroke pie/donut slice separator stroke, or {@code null} for the
+ * themed default (white 1pt)
+ * @param sliceGapDegrees angular gap between pie/donut slices (pad angle), or
+ * {@code null} for none
* @param donutCenterTextStyle style for the donut-centre KPI text, or
* {@code null} for the themed default
- *
* @author Artem Demchyshyn
* @since 1.8.0
*/
@@ -78,7 +77,9 @@ public record ChartStyle(
Double sliceGapDegrees,
DocumentTextStyle donutCenterTextStyle
) {
- /** Copy-protects collections and validates ratio bounds. */
+ /**
+ * Copy-protects collections and validates ratio bounds.
+ */
public ChartStyle {
palette = palette == null ? List.of() : List.copyOf(palette);
seriesPaintOverrides = seriesPaintOverrides == null
@@ -90,7 +91,7 @@ public record ChartStyle(
throw new IllegalArgumentException("barWidthRatio must be in (0,1]: " + barWidthRatio);
}
if (valueLabelOffset != null && (valueLabelOffset < 0
- || valueLabelOffset.isNaN() || valueLabelOffset.isInfinite())) {
+ || valueLabelOffset.isNaN() || valueLabelOffset.isInfinite())) {
throw new IllegalArgumentException(
"valueLabelOffset must be finite and non-negative: " + valueLabelOffset);
}
@@ -98,7 +99,7 @@ public record ChartStyle(
throw new IllegalArgumentException("areaOpacity must be in (0,1]: " + areaOpacity);
}
if (sliceGapDegrees != null && (sliceGapDegrees < 0 || sliceGapDegrees > 30
- || sliceGapDegrees.isNaN())) {
+ || sliceGapDegrees.isNaN())) {
throw new IllegalArgumentException(
"sliceGapDegrees must be in [0, 30]: " + sliceGapDegrees);
}
@@ -163,7 +164,7 @@ public ChartStyle mergedUnder(ChartStyle top) {
* the style palette, then the supplied fallback palette, cycling by modulo so
* a chart never runs out of colours.
*
- * @param index zero-based series index
+ * @param index zero-based series index
* @param fallbackPalette palette to use when neither override nor style palette applies
* @return the paint to fill / stroke this series with
*/
@@ -184,7 +185,7 @@ public DocumentPaint paintForSeries(int index, List fallbackPalet
* grid family entirely.
*
* @param horizontal stroke for horizontal grid lines (value gridlines)
- * @param vertical stroke for vertical grid lines (category separators)
+ * @param vertical stroke for vertical grid lines (category separators)
*/
public record GridStyle(DocumentStroke horizontal, DocumentStroke vertical) {
/**
@@ -207,7 +208,9 @@ public static GridStyle none() {
}
}
- /** Fluent builder; all setters optional. */
+ /**
+ * Fluent builder; all setters optional.
+ */
public static final class Builder {
private final List palette = new ArrayList<>();
private final Map overrides = new HashMap<>();
diff --git a/src/main/java/com/demcha/compose/document/chart/ChartTextMetrics.java b/src/main/java/com/demcha/compose/document/chart/ChartTextMetrics.java
index 4230faae6..132290637 100644
--- a/src/main/java/com/demcha/compose/document/chart/ChartTextMetrics.java
+++ b/src/main/java/com/demcha/compose/document/chart/ChartTextMetrics.java
@@ -21,7 +21,7 @@ public interface ChartTextMetrics {
* Measures the rendered width of {@code text} in the supplied style.
*
* @param style text style
- * @param text text to measure
+ * @param text text to measure
* @return width in points
*/
double width(DocumentTextStyle style, String text);
diff --git a/src/main/java/com/demcha/compose/document/chart/ChartTheme.java b/src/main/java/com/demcha/compose/document/chart/ChartTheme.java
index 26ca338ff..61ffbef88 100644
--- a/src/main/java/com/demcha/compose/document/chart/ChartTheme.java
+++ b/src/main/java/com/demcha/compose/document/chart/ChartTheme.java
@@ -15,14 +15,13 @@
* with no {@link ChartStyle} still matches the document's palette and typography
* automatically.
*
- * @param palette ordered series paints; cycled by the resolver
- * @param gridStroke default grid line stroke
- * @param axisTextStyle default tick / category label style
- * @param legendTextStyle default legend label style
+ * @param palette ordered series paints; cycled by the resolver
+ * @param gridStroke default grid line stroke
+ * @param axisTextStyle default tick / category label style
+ * @param legendTextStyle default legend label style
* @param valueLabelTextStyle default value-label style
- * @param valueLabelHalo default halo chip painted behind line-chart value labels
- * so digits stay legible where line strokes cross them
- *
+ * @param valueLabelHalo default halo chip painted behind line-chart value labels
+ * so digits stay legible where line strokes cross them
* @author Artem Demchyshyn
* @since 1.8.0
*/
@@ -34,7 +33,9 @@ public record ChartTheme(
DocumentTextStyle valueLabelTextStyle,
DocumentPaint valueLabelHalo
) {
- /** Copy-protects and validates the palette. */
+ /**
+ * Copy-protects and validates the palette.
+ */
public ChartTheme {
Objects.requireNonNull(palette, "palette");
palette = List.copyOf(palette);
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 07ab5d6d8..f1d1e6f8f 100644
--- a/src/main/java/com/demcha/compose/document/chart/LegendPosition.java
+++ b/src/main/java/com/demcha/compose/document/chart/LegendPosition.java
@@ -12,12 +12,20 @@
* @since 1.8.0
*/
public enum LegendPosition {
- /** No legend is rendered. */
+ /**
+ * No legend is rendered.
+ */
NONE,
- /** Single legend row below the plot area. */
+ /**
+ * Single legend row below the plot area.
+ */
BOTTOM,
- /** Reserved — legend column to the right of the plot area. */
+ /**
+ * Reserved — legend column to the right of the plot area.
+ */
RIGHT,
- /** Reserved — single legend row above the plot area. */
+ /**
+ * Reserved — single legend row above the plot area.
+ */
TOP
}
diff --git a/src/main/java/com/demcha/compose/document/chart/LineChartLayout.java b/src/main/java/com/demcha/compose/document/chart/LineChartLayout.java
index 2d5d7ac89..cc0639721 100644
--- a/src/main/java/com/demcha/compose/document/chart/LineChartLayout.java
+++ b/src/main/java/com/demcha/compose/document/chart/LineChartLayout.java
@@ -2,19 +2,12 @@
import com.demcha.compose.document.node.EllipseNode;
import com.demcha.compose.document.node.PolygonNode;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextStyle;
-import com.demcha.compose.document.style.ShapePoint;
+import com.demcha.compose.document.style.*;
import java.util.ArrayList;
import java.util.List;
-import static com.demcha.compose.document.chart.ChartLayoutSupport.DEFAULT_LINE_WIDTH;
-import static com.demcha.compose.document.chart.ChartLayoutSupport.emitChipLabel;
-import static com.demcha.compose.document.chart.ChartLayoutSupport.segment;
-import static com.demcha.compose.document.chart.ChartLayoutSupport.valueLabelGap;
+import static com.demcha.compose.document.chart.ChartLayoutSupport.*;
/**
* Geometry for line charts: straight or Catmull-Rom-smoothed polylines,
@@ -26,7 +19,9 @@
*/
final class LineChartLayout {
- /** Sub-segments per Catmull-Rom span; fixed so geometry stays deterministic. */
+ /**
+ * Sub-segments per Catmull-Rom span; fixed so geometry stays deterministic.
+ */
private static final int SMOOTH_SUBDIVISIONS = 8;
private static final double DEFAULT_AREA_OPACITY = 0.35;
@@ -137,7 +132,9 @@ static List resolve(ChartSpec.Line line, ChartStyle style,
return out;
}
- /** Splits a series into contiguous non-null runs of (x, y) samples. */
+ /**
+ * Splits a series into contiguous non-null runs of (x, y) samples.
+ */
private static List> sampleSeries(ChartData.Series series,
ChartLayoutSupport.Frame f,
double slotW, boolean smooth) {
@@ -152,7 +149,7 @@ private static List> sampleSeries(ChartData.Series series,
}
continue;
}
- current.add(new double[] {
+ current.add(new double[]{
f.plotLeftX() + (c + 0.5) * slotW, f.yForValue(v)});
}
if (!current.isEmpty()) {
@@ -179,7 +176,7 @@ private static List smoothRun(List points) {
double[] p3 = points.get(Math.min(points.size() - 1, i + 2));
for (int t = 1; t <= SMOOTH_SUBDIVISIONS; t++) {
double u = (double) t / SMOOTH_SUBDIVISIONS;
- samples.add(new double[] {
+ samples.add(new double[]{
catmullRom(p0[0], p1[0], p2[0], p3[0], u),
catmullRom(p0[1], p1[1], p2[1], p3[1], u)});
}
@@ -191,12 +188,14 @@ private static double catmullRom(double p0, double p1, double p2, double p3, dou
double t2 = t * t;
double t3 = t2 * t;
return 0.5 * ((2 * p1)
- + (-p0 + p2) * t
- + (2 * p0 - 5 * p1 + 4 * p2 - p3) * t2
- + (-p0 + 3 * p1 - 3 * p2 + p3) * t3);
+ + (-p0 + p2) * t
+ + (2 * p0 - 5 * p1 + 4 * p2 - p3) * t2
+ + (-p0 + 3 * p1 - 3 * p2 + p3) * t3);
}
- /** Closes a sampled run down to the plot baseline and emits it as a polygon. */
+ /**
+ * Closes a sampled run down to the plot baseline and emits it as a polygon.
+ */
private static void emitAreaPolygon(List out, String name,
List run, double baselineY,
DocumentColor fill) {
@@ -248,7 +247,7 @@ private static void emitValueLabels(List out, ChartLayoutSupport
List order = new ArrayList<>();
for (int s = 0; s < data.seriesCount(); s++) {
if (data.series().get(s).values().get(c) != null) {
- order.add(new int[] {s});
+ order.add(new int[]{s});
}
}
int catIndex = c;
@@ -272,7 +271,7 @@ private static void emitValueLabels(List out, ChartLayoutSupport
// Flip below the point; close series read better split around it.
yBottom = py - markerHalfH - labelGap - f.valueLineH();
}
- placedBoxes.add(new double[] {yBottom, yBottom + f.valueLineH()});
+ placedBoxes.add(new double[]{yBottom, yBottom + f.valueLineH()});
emitChipLabel(out, "value_s" + s + "_c" + c, text, valueStyle, halo,
px, yBottom, labelW, f.valueLineH());
}
diff --git a/src/main/java/com/demcha/compose/document/chart/NiceScale.java b/src/main/java/com/demcha/compose/document/chart/NiceScale.java
index 2d9bc0b38..e7dcfff31 100644
--- a/src/main/java/com/demcha/compose/document/chart/NiceScale.java
+++ b/src/main/java/com/demcha/compose/document/chart/NiceScale.java
@@ -7,11 +7,10 @@
* machine or locale — this is the keystone of chart determinism, and it is
* unit-tested in isolation with golden tables before any rendering is involved.
*
- * @param niceMin rounded lower bound
- * @param niceMax rounded upper bound
- * @param tickStep distance between successive ticks
+ * @param niceMin rounded lower bound
+ * @param niceMax rounded upper bound
+ * @param tickStep distance between successive ticks
* @param tickCount number of tick marks ({@code niceMin .. niceMax} inclusive)
- *
* @author Artem Demchyshyn
* @since 1.8.0
*/
@@ -20,8 +19,8 @@ public record NiceScale(double niceMin, double niceMax, double tickStep, int tic
/**
* Computes a nice scale.
*
- * @param dataMin smallest value to cover
- * @param dataMax largest value to cover
+ * @param dataMin smallest value to cover
+ * @param dataMax largest value to cover
* @param includeZero pull the range to include zero (bars)
* @param targetTicks desired number of intervals (e.g. 5); a hint, not exact
* @return rounded bounds and step
diff --git a/src/main/java/com/demcha/compose/document/chart/NumberFormatSpec.java b/src/main/java/com/demcha/compose/document/chart/NumberFormatSpec.java
index 9fa9d3360..fd85f8fbf 100644
--- a/src/main/java/com/demcha/compose/document/chart/NumberFormatSpec.java
+++ b/src/main/java/com/demcha/compose/document/chart/NumberFormatSpec.java
@@ -12,12 +12,11 @@
* "k / M" abbreviation without an escape hatch. Java-only callers that truly
* need arbitrary formatting can still pre-format their {@link ChartData} labels.
*
- * @param pattern {@link java.text.DecimalFormat} pattern, e.g. {@code "#,##0.0"}
- * @param locale grouping/decimal-separator locale; defaults to {@link Locale#ROOT}
- * @param prefix text prepended to every formatted value (e.g. {@code "$"})
- * @param suffix text appended to every formatted value (e.g. {@code " k"})
+ * @param pattern {@link java.text.DecimalFormat} pattern, e.g. {@code "#,##0.0"}
+ * @param locale grouping/decimal-separator locale; defaults to {@link Locale#ROOT}
+ * @param prefix text prepended to every formatted value (e.g. {@code "$"})
+ * @param suffix text appended to every formatted value (e.g. {@code " k"})
* @param scaleDivisor value is divided by this before formatting; must be finite and non-zero
- *
* @author Artem Demchyshyn
* @since 1.8.0
*/
@@ -28,7 +27,9 @@ public record NumberFormatSpec(
String suffix,
double scaleDivisor
) {
- /** Normalizes nullable fields and rejects a zero / non-finite divisor. */
+ /**
+ * Normalizes nullable fields and rejects a zero / non-finite divisor.
+ */
public NumberFormatSpec {
pattern = (pattern == null || pattern.isBlank()) ? "#,##0.##" : pattern;
locale = locale == null ? Locale.ROOT : locale;
diff --git a/src/main/java/com/demcha/compose/document/chart/PieChartLayout.java b/src/main/java/com/demcha/compose/document/chart/PieChartLayout.java
index 8a7cc72cb..0e1b7b965 100644
--- a/src/main/java/com/demcha/compose/document/chart/PieChartLayout.java
+++ b/src/main/java/com/demcha/compose/document/chart/PieChartLayout.java
@@ -2,20 +2,12 @@
import com.demcha.compose.document.node.PolygonNode;
import com.demcha.compose.document.node.TextAlign;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextStyle;
-import com.demcha.compose.document.style.ShapePoint;
+import com.demcha.compose.document.style.*;
import java.util.ArrayList;
import java.util.List;
-import static com.demcha.compose.document.chart.ChartLayoutSupport.GAP;
-import static com.demcha.compose.document.chart.ChartLayoutSupport.HALO_PAD_Y;
-import static com.demcha.compose.document.chart.ChartLayoutSupport.emitChipLabel;
-import static com.demcha.compose.document.chart.ChartLayoutSupport.label;
-import static com.demcha.compose.document.chart.ChartLayoutSupport.valueLabelGap;
+import static com.demcha.compose.document.chart.ChartLayoutSupport.*;
/**
* Geometry for pie/donut charts: arc-tessellated sector polygons, mid-angle
diff --git a/src/main/java/com/demcha/compose/document/chart/PointMarker.java b/src/main/java/com/demcha/compose/document/chart/PointMarker.java
index 20584502d..309fdfbaf 100644
--- a/src/main/java/com/demcha/compose/document/chart/PointMarker.java
+++ b/src/main/java/com/demcha/compose/document/chart/PointMarker.java
@@ -14,17 +14,18 @@
* ring (a white ring over a coloured line is the classic way to keep
* overlapping joints readable).
*
- * @param width marker width (horizontal axis) in points
+ * @param width marker width (horizontal axis) in points
* @param height marker height (vertical axis) in points
- * @param fill explicit marker fill, or {@code null} to use the series paint
+ * @param fill explicit marker fill, or {@code null} to use the series paint
* @param stroke outline ring, or {@code null} for none
- *
* @author Artem Demchyshyn
* @since 1.8.0
*/
public record PointMarker(double width, double height, DocumentPaint fill, DocumentStroke stroke) {
- /** Validates marker axes. */
+ /**
+ * Validates marker axes.
+ */
public PointMarker {
requirePositiveFinite(width, "width");
requirePositiveFinite(height, "height");
@@ -43,7 +44,7 @@ public static PointMarker circle(double diameter) {
/**
* Elliptical marker filled with the series paint.
*
- * @param width horizontal axis in points
+ * @param width horizontal axis in points
* @param height vertical axis in points
* @return marker
*/
@@ -51,6 +52,12 @@ public static PointMarker ellipse(double width, double height) {
return new PointMarker(width, height, null, null);
}
+ private static void requirePositiveFinite(double v, String name) {
+ if (v <= 0 || Double.isNaN(v) || Double.isInfinite(v)) {
+ throw new IllegalArgumentException(name + " must be finite and positive: " + v);
+ }
+ }
+
/**
* Returns a copy with an explicit fill (overrides the series paint).
*
@@ -70,10 +77,4 @@ public PointMarker withFill(DocumentPaint fill) {
public PointMarker withStroke(DocumentStroke stroke) {
return new PointMarker(width, height, fill, stroke);
}
-
- private static void requirePositiveFinite(double v, String name) {
- if (v <= 0 || Double.isNaN(v) || Double.isInfinite(v)) {
- throw new IllegalArgumentException(name + " must be finite and positive: " + v);
- }
- }
}
diff --git a/src/main/java/com/demcha/compose/document/chart/SliceLabelMode.java b/src/main/java/com/demcha/compose/document/chart/SliceLabelMode.java
index d964adfbe..4535e215e 100644
--- a/src/main/java/com/demcha/compose/document/chart/SliceLabelMode.java
+++ b/src/main/java/com/demcha/compose/document/chart/SliceLabelMode.java
@@ -8,14 +8,24 @@
* @since 1.8.0
*/
public enum SliceLabelMode {
- /** No slice labels. */
+ /**
+ * No slice labels.
+ */
NONE,
- /** The raw value, formatted with the spec's value format. */
+ /**
+ * The raw value, formatted with the spec's value format.
+ */
VALUE,
- /** The slice's share of the total, formatted with the spec's percent format. */
+ /**
+ * The slice's share of the total, formatted with the spec's percent format.
+ */
PERCENT,
- /** The category name. */
+ /**
+ * The category name.
+ */
CATEGORY,
- /** Category name followed by the percent share. */
+ /**
+ * Category name followed by the percent share.
+ */
CATEGORY_PERCENT
}
diff --git a/src/main/java/com/demcha/compose/document/chart/ValueLabelMode.java b/src/main/java/com/demcha/compose/document/chart/ValueLabelMode.java
index a04a625c6..bdc68bdc1 100644
--- a/src/main/java/com/demcha/compose/document/chart/ValueLabelMode.java
+++ b/src/main/java/com/demcha/compose/document/chart/ValueLabelMode.java
@@ -7,10 +7,16 @@
* @since 1.8.0
*/
public enum ValueLabelMode {
- /** No value labels. */
+ /**
+ * No value labels.
+ */
NONE,
- /** Above a vertical bar / above a line point. */
+ /**
+ * Above a vertical bar / above a line point.
+ */
OUTSIDE,
- /** Reserved — inside the bar body near its end. */
+ /**
+ * Reserved — inside the bar body near its end.
+ */
INSIDE
}
diff --git a/src/main/java/com/demcha/compose/document/debug/snapshot/LayoutGraphSnapshotExtractor.java b/src/main/java/com/demcha/compose/document/debug/snapshot/LayoutGraphSnapshotExtractor.java
index 8879ecd87..54d163beb 100644
--- a/src/main/java/com/demcha/compose/document/debug/snapshot/LayoutGraphSnapshotExtractor.java
+++ b/src/main/java/com/demcha/compose/document/debug/snapshot/LayoutGraphSnapshotExtractor.java
@@ -11,7 +11,6 @@
import java.math.BigDecimal;
import java.math.RoundingMode;
-import java.util.List;
import java.util.Objects;
/**
diff --git a/src/main/java/com/demcha/compose/document/dsl/AbstractFlowBuilder.java b/src/main/java/com/demcha/compose/document/dsl/AbstractFlowBuilder.java
index 3c548938a..bf4fdb414 100644
--- a/src/main/java/com/demcha/compose/document/dsl/AbstractFlowBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/AbstractFlowBuilder.java
@@ -5,17 +5,11 @@
import com.demcha.compose.document.dsl.internal.BuilderSupport;
import com.demcha.compose.document.image.DocumentImageData;
import com.demcha.compose.document.node.ChartNode;
-import com.demcha.compose.document.node.DocumentBookmarkOptions;
import com.demcha.compose.document.node.DocumentLinkOptions;
import com.demcha.compose.document.node.DocumentNode;
-import com.demcha.compose.document.style.DocumentBorders;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentCornerRadius;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextStyle;
-
-import java.awt.Color;
+import com.demcha.compose.document.style.*;
+
+import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -29,8 +23,8 @@
* @since 1.0.0
*/
public abstract class AbstractFlowBuilder, N extends DocumentNode> {
- private String name = "";
private final List children = new ArrayList<>();
+ private String name = "";
private double spacing = 0.0;
private DocumentInsets padding = DocumentInsets.zero();
private DocumentInsets margin = DocumentInsets.zero();
@@ -85,10 +79,10 @@ public T padding(DocumentInsets padding) {
/**
* Sets flow padding from explicit side values.
*
- * @param top top padding
- * @param right right padding
+ * @param top top padding
+ * @param right right padding
* @param bottom bottom padding
- * @param left left padding
+ * @param left left padding
* @return this builder
*/
public T padding(float top, float right, float bottom, float left) {
@@ -109,10 +103,10 @@ public T margin(DocumentInsets margin) {
/**
* Sets flow margin from explicit side values.
*
- * @param top top margin
- * @param right right margin
+ * @param top top margin
+ * @param right right margin
* @param bottom bottom margin
- * @param left left margin
+ * @param left left margin
* @return this builder
*/
public T margin(float top, float right, float bottom, float left) {
@@ -210,8 +204,8 @@ public T band(DocumentColor color) {
* padding. Pass {@code 0.0} for {@code radius} or {@code padding} to skip
* either step.
*
- * @param color panel fill color
- * @param radius corner radius in points
+ * @param color panel fill color
+ * @param radius corner radius in points
* @param padding inner padding in points (applied uniformly on all sides)
* @return this builder
*/
@@ -232,12 +226,12 @@ public T softPanel(DocumentColor color, double radius, double padding) {
* side — e.g. a hero block that sits flush against a left accent
* strip and only rounds its right corners.
*
- * @param color panel fill color
+ * @param color panel fill color
* @param cornerRadius per-corner radii (use the
* {@link DocumentCornerRadius#right(double)} /
* {@code .left} / {@code .top} / {@code .bottom}
* factories for asymmetric layouts)
- * @param padding inner padding in points (applied uniformly on all sides)
+ * @param padding inner padding in points (applied uniformly on all sides)
* @return this builder
*/
public T softPanel(DocumentColor color, DocumentCornerRadius cornerRadius, double padding) {
@@ -268,10 +262,10 @@ public T softPanel(DocumentColor color) {
* {@code softPanel(color, radius, padding).stroke(stroke)} — a rounded,
* padded fill with a thin outline, without a separate wrapping node.
*
- * @param color panel fill color
- * @param radius corner radius in points
+ * @param color panel fill color
+ * @param radius corner radius in points
* @param padding inner padding in points (applied uniformly on all sides)
- * @param stroke border stroke, or {@code null} for no border
+ * @param stroke border stroke, or {@code null} for no border
* @return this builder
* @since 1.7.0
*/
@@ -285,10 +279,10 @@ public T softPanel(DocumentColor color, double radius, double padding, DocumentS
* to the same node. Equivalent to
* {@code softPanel(color, cornerRadius, padding).stroke(stroke)}.
*
- * @param color panel fill color
+ * @param color panel fill color
* @param cornerRadius per-corner radii (see {@link DocumentCornerRadius})
- * @param padding inner padding in points (applied uniformly on all sides)
- * @param stroke border stroke, or {@code null} for no border
+ * @param padding inner padding in points (applied uniformly on all sides)
+ * @param stroke border stroke, or {@code null} for no border
* @return this builder
* @since 1.7.0
*/
@@ -378,7 +372,7 @@ public T addParagraph(String text) {
/**
* Adds a plain paragraph with a public canonical text style.
*
- * @param text paragraph text
+ * @param text paragraph text
* @param textStyle paragraph text style
* @return this builder
*/
@@ -412,7 +406,7 @@ public T addText(String text) {
/**
* Alias for {@link #addParagraph(String, DocumentTextStyle)}.
*
- * @param text paragraph text
+ * @param text paragraph text
* @param textStyle paragraph text style
* @return this builder
*/
@@ -464,8 +458,8 @@ public T addImage(Consumer spec) {
* Adds an image with explicit dimensions — shortcut for the common
* {@code addImage(i -> i.source(data).size(w, h))} call.
*
- * @param data image source bytes/path/url
- * @param width image width in points
+ * @param data image source bytes/path/url
+ * @param width image width in points
* @param height image height in points
* @return this builder
*/
@@ -487,8 +481,8 @@ public T addShape(Consumer spec) {
* Adds a filled shape with explicit dimensions — shortcut for the common
* {@code addShape(s -> s.size(w, h).fillColor(c))} call.
*
- * @param width shape width in points
- * @param height shape height in points
+ * @param width shape width in points
+ * @param height shape height in points
* @param fillColor canonical fill color
* @return this builder
*/
@@ -509,7 +503,7 @@ public T addSpacer(Consumer spec) {
/**
* Adds an invisible fixed-size spacer.
*
- * @param width spacer width in points
+ * @param width spacer width in points
* @param height spacer height in points
* @return this builder
*/
@@ -541,7 +535,7 @@ public T addEllipse(Consumer spec) {
* Adds a filled circle ellipse — shortcut for
* {@code addEllipse(e -> e.circle(diameter).fillColor(fillColor))}.
*
- * @param diameter circle diameter in points
+ * @param diameter circle diameter in points
* @param fillColor canonical fill color
* @return this builder
*/
@@ -553,8 +547,8 @@ public T addEllipse(double diameter, DocumentColor fillColor) {
* Adds a filled ellipse with explicit width and height — shortcut for
* {@code addEllipse(e -> e.size(w, h).fillColor(fillColor))}.
*
- * @param width ellipse width in points
- * @param height ellipse height in points
+ * @param width ellipse width in points
+ * @param height ellipse height in points
* @param fillColor canonical fill color
* @return this builder
*/
@@ -576,7 +570,7 @@ public T addCircle(double diameter) {
* Adds a filled circle — shortcut for
* {@code addCircle(diameter, e -> e.fillColor(fillColor))}.
*
- * @param diameter circle diameter in points
+ * @param diameter circle diameter in points
* @param fillColor canonical fill color
* @return this builder
*/
@@ -588,7 +582,7 @@ public T addCircle(double diameter, DocumentColor fillColor) {
* Adds a circle with equal width and height.
*
* @param diameter circle diameter in points
- * @param spec optional additional ellipse builder callback
+ * @param spec optional additional ellipse builder callback
* @return this builder
*/
public T addCircle(double diameter, Consumer spec) {
@@ -623,9 +617,9 @@ public T addContainer(Consumer spec) {
* .clipPolicy(ClipPolicy.OVERFLOW_VISIBLE));
* }
*
- * @param width canvas width in points
+ * @param width canvas width in points
* @param height canvas height in points
- * @param spec canvas builder callback
+ * @param spec canvas builder callback
* @return this builder
*/
public T addCanvas(double width, double height, Consumer spec) {
@@ -641,9 +635,9 @@ public T addCanvas(double width, double height, Consumer spe
* section.addCircle(60, brand, c -> c.center(label));
* }
*
- * @param diameter circle diameter in points
+ * @param diameter circle diameter in points
* @param fillColor canonical fill colour
- * @param spec callback that appends layers
+ * @param spec callback that appends layers
* @return this builder
*/
public T addCircle(double diameter, DocumentColor fillColor, Consumer spec) {
@@ -657,10 +651,10 @@ public T addCircle(double diameter, DocumentColor fillColor, Consumer spec) {
@@ -700,7 +694,7 @@ public T chart(ChartSpec spec) {
/**
* Adds a chart with an explicit style layered over the chart theme.
*
- * @param spec structural chart description (kind, data, axes, legend)
+ * @param spec structural chart description (kind, data, axes, legend)
* @param style visual style overrides; {@code null} inherits the theme
* @return this builder
* @since 1.8.0
@@ -781,7 +775,7 @@ public T addRich(Consumer spec) {
* text; the link target comes from the supplied URI.
*
* @param text visible link text
- * @param uri target URI
+ * @param uri target URI
* @return this builder
*/
public T addLink(String text, String uri) {
@@ -793,7 +787,7 @@ public T addLink(String text, String uri) {
* Adds a paragraph that contains a single clickable link span configured
* with explicit link options.
*
- * @param text visible link text
+ * @param text visible link text
* @param options link target metadata
* @return this builder
*/
@@ -869,7 +863,7 @@ public T headingBar(String text) {
* paginate as one unit; call {@code headingBar(...)} on the page flow itself
* when the body must break across pages independently of its heading.
*
- * @param text the heading label text
+ * @param text the heading label text
* @param customizer callback to tune the bar look (fill, corners, padding,
* margin, text style, alignment, optional outline); may be
* {@code null} for the default light-grey band
@@ -919,7 +913,7 @@ public T addTimeline(Consumer spec) {
* Adds a titled semantic module.
*
* @param title visible module title
- * @param spec callback that configures module body blocks
+ * @param spec callback that configures module body blocks
* @return this builder
*/
public T module(String title, Consumer spec) {
@@ -940,7 +934,7 @@ public T module(Consumer spec) {
* Alias for {@link #module(String, Consumer)}.
*
* @param title visible module title
- * @param spec callback that configures module body blocks
+ * @param spec callback that configures module body blocks
* @return this builder
*/
public T addModule(String title, Consumer spec) {
diff --git a/src/main/java/com/demcha/compose/document/dsl/BarcodeBuilder.java b/src/main/java/com/demcha/compose/document/dsl/BarcodeBuilder.java
index 94c055bf9..a0c4c46c9 100644
--- a/src/main/java/com/demcha/compose/document/dsl/BarcodeBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/BarcodeBuilder.java
@@ -1,47 +1,16 @@
package com.demcha.compose.document.dsl;
-import com.demcha.compose.document.api.DocumentSession;
-import com.demcha.compose.document.dsl.internal.BuilderSupport;
-import com.demcha.compose.document.dsl.internal.SemanticNameNormalizer;
-import com.demcha.compose.document.image.DocumentImageData;
-import com.demcha.compose.document.node.BarcodeNode;
-import com.demcha.compose.document.node.ContainerNode;
-import com.demcha.compose.document.node.DocumentBarcodeOptions;
-import com.demcha.compose.document.node.DocumentBarcodeType;
-import com.demcha.compose.document.node.DocumentBookmarkOptions;
-import com.demcha.compose.document.node.DocumentLinkOptions;
-import com.demcha.compose.document.node.DocumentNode;
-import com.demcha.compose.document.node.ImageNode;
-import com.demcha.compose.document.node.InlineTextRun;
-import com.demcha.compose.document.node.ListMarker;
-import com.demcha.compose.document.node.ListNode;
-import com.demcha.compose.document.node.PageBreakNode;
-import com.demcha.compose.document.node.ParagraphNode;
-import com.demcha.compose.document.node.SectionNode;
-import com.demcha.compose.document.node.ShapeNode;
-import com.demcha.compose.document.node.TableNode;
-import com.demcha.compose.document.node.TextAlign;
+import com.demcha.compose.document.node.*;
import com.demcha.compose.document.style.DocumentColor;
import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextIndent;
-import com.demcha.compose.document.style.DocumentTextStyle;
import com.demcha.compose.document.style.DocumentTransform;
-import com.demcha.compose.document.table.DocumentTableCell;
-import com.demcha.compose.document.table.DocumentTableColumn;
-import com.demcha.compose.document.table.DocumentTableStyle;
-import java.awt.Color;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
+import java.awt.*;
import java.util.Objects;
-import java.util.function.Consumer;
/**
* Builder for semantic barcode and QR-code nodes.
+ *
* @since 1.0.0
*/
public final class BarcodeBuilder implements Transformable {
@@ -237,7 +206,7 @@ public BarcodeBuilder height(double height) {
/**
* Sets barcode width and height.
*
- * @param width width in points
+ * @param width width in points
* @param height height in points
* @return this builder
*/
diff --git a/src/main/java/com/demcha/compose/document/dsl/CanvasLayerBuilder.java b/src/main/java/com/demcha/compose/document/dsl/CanvasLayerBuilder.java
index b07fd7275..8322368b5 100644
--- a/src/main/java/com/demcha/compose/document/dsl/CanvasLayerBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/CanvasLayerBuilder.java
@@ -24,10 +24,10 @@
*/
public final class CanvasLayerBuilder {
+ private final List placements = new ArrayList<>();
private String name = "";
private double width;
private double height;
- private final List placements = new ArrayList<>();
private ClipPolicy clipPolicy = ClipPolicy.CLIP_BOUNDS;
private DocumentInsets padding = DocumentInsets.zero();
private DocumentInsets margin = DocumentInsets.zero();
@@ -37,7 +37,7 @@ public final class CanvasLayerBuilder {
* canvas reserves a fixed {@code width × height} rectangle
* regardless of where children are placed.
*
- * @param width canvas width in points (must be {@code > 0})
+ * @param width canvas width in points (must be {@code > 0})
* @param height canvas height in points (must be {@code > 0})
*/
public CanvasLayerBuilder(double width, double height) {
@@ -69,7 +69,7 @@ public CanvasLayerBuilder name(String name) {
* overflow if {@code width} or {@code height} shrinks past
* a child's coordinate.
*
- * @param width canvas width in points (must be {@code > 0})
+ * @param width canvas width in points (must be {@code > 0})
* @param height canvas height in points (must be {@code > 0})
* @return this builder
*/
@@ -91,8 +91,8 @@ public CanvasLayerBuilder size(double width, double height) {
* {@code (x, y)} relative to the canvas's top-left origin.
*
* @param child child node to place
- * @param x offset from the canvas's left edge
- * @param y offset from the canvas's top edge (positive = down)
+ * @param x offset from the canvas's left edge
+ * @param y offset from the canvas's top edge (positive = down)
* @return this builder
*/
public CanvasLayerBuilder position(DocumentNode child, double x, double y) {
diff --git a/src/main/java/com/demcha/compose/document/dsl/DividerBuilder.java b/src/main/java/com/demcha/compose/document/dsl/DividerBuilder.java
index 606ce8e7e..506291205 100644
--- a/src/main/java/com/demcha/compose/document/dsl/DividerBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/DividerBuilder.java
@@ -1,46 +1,14 @@
package com.demcha.compose.document.dsl;
-import com.demcha.compose.document.api.DocumentSession;
-import com.demcha.compose.document.dsl.internal.BuilderSupport;
-import com.demcha.compose.document.dsl.internal.SemanticNameNormalizer;
-import com.demcha.compose.document.image.DocumentImageData;
-import com.demcha.compose.document.node.BarcodeNode;
-import com.demcha.compose.document.node.ContainerNode;
-import com.demcha.compose.document.node.DocumentBarcodeOptions;
-import com.demcha.compose.document.node.DocumentBarcodeType;
-import com.demcha.compose.document.node.DocumentBookmarkOptions;
-import com.demcha.compose.document.node.DocumentLinkOptions;
-import com.demcha.compose.document.node.DocumentNode;
-import com.demcha.compose.document.node.ImageNode;
-import com.demcha.compose.document.node.InlineTextRun;
-import com.demcha.compose.document.node.ListMarker;
-import com.demcha.compose.document.node.ListNode;
-import com.demcha.compose.document.node.PageBreakNode;
-import com.demcha.compose.document.node.ParagraphNode;
-import com.demcha.compose.document.node.SectionNode;
import com.demcha.compose.document.node.ShapeNode;
-import com.demcha.compose.document.node.TableNode;
-import com.demcha.compose.document.node.TextAlign;
import com.demcha.compose.document.style.DocumentColor;
import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextIndent;
-import com.demcha.compose.document.style.DocumentTextStyle;
-import com.demcha.compose.document.table.DocumentTableCell;
-import com.demcha.compose.document.table.DocumentTableColumn;
-import com.demcha.compose.document.table.DocumentTableStyle;
-import java.awt.Color;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.function.Consumer;
+import java.awt.*;
/**
* Builder for thin horizontal divider nodes.
+ *
* @since 1.0.0
*/
public final class DividerBuilder extends ShapeBuilder {
diff --git a/src/main/java/com/demcha/compose/document/dsl/DocumentDsl.java b/src/main/java/com/demcha/compose/document/dsl/DocumentDsl.java
index bfa8be3c2..c9d1f20d5 100644
--- a/src/main/java/com/demcha/compose/document/dsl/DocumentDsl.java
+++ b/src/main/java/com/demcha/compose/document/dsl/DocumentDsl.java
@@ -90,9 +90,9 @@ public ParagraphBuilder paragraph() {
*
* @return a detached paragraph builder
* @deprecated since 1.6.0; prefer {@link #paragraph()}. Carrying two
- * names for the same operation on a small facade adds
- * maintenance cost without clarity. Scheduled for removal in
- * v2.0.
+ * names for the same operation on a small facade adds
+ * maintenance cost without clarity. Scheduled for removal in
+ * v2.0.
*/
@Deprecated(since = "1.6.0", forRemoval = true)
public ParagraphBuilder text() {
diff --git a/src/main/java/com/demcha/compose/document/dsl/EllipseBuilder.java b/src/main/java/com/demcha/compose/document/dsl/EllipseBuilder.java
index 5b78fb0e3..af1790882 100644
--- a/src/main/java/com/demcha/compose/document/dsl/EllipseBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/EllipseBuilder.java
@@ -8,7 +8,7 @@
import com.demcha.compose.document.style.DocumentStroke;
import com.demcha.compose.document.style.DocumentTransform;
-import java.awt.Color;
+import java.awt.*;
/**
* Builder for semantic circle and ellipse nodes.
@@ -70,7 +70,7 @@ public EllipseBuilder height(double height) {
/**
* Sets ellipse width and height.
*
- * @param width width in points
+ * @param width width in points
* @param height height in points
* @return this builder
*/
diff --git a/src/main/java/com/demcha/compose/document/dsl/HeadingBarStyle.java b/src/main/java/com/demcha/compose/document/dsl/HeadingBarStyle.java
index 0046ed99a..5586ed87d 100644
--- a/src/main/java/com/demcha/compose/document/dsl/HeadingBarStyle.java
+++ b/src/main/java/com/demcha/compose/document/dsl/HeadingBarStyle.java
@@ -1,12 +1,7 @@
package com.demcha.compose.document.dsl;
import com.demcha.compose.document.node.TextAlign;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentCornerRadius;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextDecoration;
-import com.demcha.compose.document.style.DocumentTextStyle;
+import com.demcha.compose.document.style.*;
import com.demcha.compose.font.FontName;
/**
diff --git a/src/main/java/com/demcha/compose/document/dsl/ImageBuilder.java b/src/main/java/com/demcha/compose/document/dsl/ImageBuilder.java
index 8fa10b75d..61ee9a51f 100644
--- a/src/main/java/com/demcha/compose/document/dsl/ImageBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/ImageBuilder.java
@@ -113,7 +113,7 @@ public ImageBuilder height(double height) {
/**
* Sets image width and height.
*
- * @param width width in points
+ * @param width width in points
* @param height height in points
* @return this builder
*/
@@ -137,7 +137,7 @@ public ImageBuilder scale(double scale) {
/**
* Sets the image bounds and preserves aspect ratio by default.
*
- * @param width maximum drawing width in points
+ * @param width maximum drawing width in points
* @param height maximum drawing height in points
* @return this builder
*/
diff --git a/src/main/java/com/demcha/compose/document/dsl/LayerStackBuilder.java b/src/main/java/com/demcha/compose/document/dsl/LayerStackBuilder.java
index 12273ae48..6b049d682 100644
--- a/src/main/java/com/demcha/compose/document/dsl/LayerStackBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/LayerStackBuilder.java
@@ -22,8 +22,8 @@
* @since 1.0.0
*/
public final class LayerStackBuilder {
- private String name = "";
private final List layers = new ArrayList<>();
+ private String name = "";
private DocumentInsets padding = DocumentInsets.zero();
private DocumentInsets margin = DocumentInsets.zero();
@@ -57,7 +57,7 @@ public LayerStackBuilder layer(DocumentNode node) {
/**
* Appends a layer with explicit alignment inside the stack box.
*
- * @param node child node
+ * @param node child node
* @param align layer alignment
* @return this builder
*/
@@ -71,8 +71,8 @@ public LayerStackBuilder layer(DocumentNode node, LayerAlign align) {
* {@code zIndex} renders on top of lower {@code zIndex} regardless
* of source order; the default is {@code 0}.
*
- * @param node child node
- * @param align layer alignment
+ * @param node child node
+ * @param align layer alignment
* @param zIndex render-order key
* @return this builder
*/
@@ -87,10 +87,10 @@ public LayerStackBuilder layer(DocumentNode node, LayerAlign align, int zIndex)
* offset from that anchor point. Positive {@code offsetX} moves the layer
* to the right, positive {@code offsetY} moves it down.
*
- * @param node child node
+ * @param node child node
* @param offsetX horizontal offset from the anchor (positive = right)
* @param offsetY vertical offset from the anchor (positive = down)
- * @param align anchor inside the stack box
+ * @param align anchor inside the stack box
* @return this builder
*/
public LayerStackBuilder position(DocumentNode node,
@@ -106,11 +106,11 @@ public LayerStackBuilder position(DocumentNode node,
* Appends a layer anchored to {@code align}, nudged by an on-screen
* offset, and assigned an explicit z-index.
*
- * @param node child node
+ * @param node child node
* @param offsetX horizontal offset from the anchor (positive = right)
* @param offsetY vertical offset from the anchor (positive = down)
- * @param align anchor inside the stack box
- * @param zIndex render-order key
+ * @param align anchor inside the stack box
+ * @param zIndex render-order key
* @return this builder
*/
public LayerStackBuilder position(DocumentNode node,
diff --git a/src/main/java/com/demcha/compose/document/dsl/LineBuilder.java b/src/main/java/com/demcha/compose/document/dsl/LineBuilder.java
index 814966f50..054d49a78 100644
--- a/src/main/java/com/demcha/compose/document/dsl/LineBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/LineBuilder.java
@@ -3,11 +3,7 @@
import com.demcha.compose.document.node.DocumentBookmarkOptions;
import com.demcha.compose.document.node.DocumentLinkOptions;
import com.demcha.compose.document.node.LineNode;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentDashPattern;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTransform;
+import com.demcha.compose.document.style.*;
/**
* Builder for fixed-size semantic line nodes.
@@ -73,7 +69,7 @@ public LineBuilder height(double height) {
/**
* Sets the line box width and height.
*
- * @param width width in points
+ * @param width width in points
* @param height height in points
* @return this builder
*/
@@ -118,7 +114,7 @@ public LineBuilder vertical(double height) {
/**
* Configures a diagonal line across the line box.
*
- * @param width line box width
+ * @param width line box width
* @param height line box height
* @return this builder
*/
@@ -330,21 +326,21 @@ public LineNode build() {
private boolean isHorizontalLine() {
return startX != null
- && endX != null
- && startY != null
- && endY != null
- && Double.compare(startX, 0.0) == 0
- && Double.compare(endX, width) == 0
- && Double.compare(startY, endY) == 0;
+ && endX != null
+ && startY != null
+ && endY != null
+ && Double.compare(startX, 0.0) == 0
+ && Double.compare(endX, width) == 0
+ && Double.compare(startY, endY) == 0;
}
private boolean isVerticalLine() {
return startX != null
- && endX != null
- && startY != null
- && endY != null
- && Double.compare(startY, 0.0) == 0
- && Double.compare(endY, height) == 0
- && Double.compare(startX, endX) == 0;
+ && endX != null
+ && startY != null
+ && endY != null
+ && Double.compare(startY, 0.0) == 0
+ && Double.compare(endY, height) == 0
+ && Double.compare(startX, endX) == 0;
}
}
diff --git a/src/main/java/com/demcha/compose/document/dsl/ListBuilder.java b/src/main/java/com/demcha/compose/document/dsl/ListBuilder.java
index 2ed965c11..eef60e9f2 100644
--- a/src/main/java/com/demcha/compose/document/dsl/ListBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/ListBuilder.java
@@ -1,53 +1,24 @@
package com.demcha.compose.document.dsl;
-import com.demcha.compose.document.api.DocumentSession;
-import com.demcha.compose.document.dsl.internal.BuilderSupport;
-import com.demcha.compose.document.dsl.internal.SemanticNameNormalizer;
-import com.demcha.compose.document.image.DocumentImageData;
-import com.demcha.compose.document.node.BarcodeNode;
-import com.demcha.compose.document.node.ContainerNode;
-import com.demcha.compose.document.node.DocumentBarcodeOptions;
-import com.demcha.compose.document.node.DocumentBarcodeType;
-import com.demcha.compose.document.node.DocumentBookmarkOptions;
-import com.demcha.compose.document.node.DocumentLinkOptions;
-import com.demcha.compose.document.node.DocumentNode;
-import com.demcha.compose.document.node.ImageNode;
-import com.demcha.compose.document.node.InlineTextRun;
import com.demcha.compose.document.node.ListItem;
import com.demcha.compose.document.node.ListMarker;
import com.demcha.compose.document.node.ListNode;
-import com.demcha.compose.document.node.PageBreakNode;
-import com.demcha.compose.document.node.ParagraphNode;
-import com.demcha.compose.document.node.SectionNode;
-import com.demcha.compose.document.node.ShapeNode;
-import com.demcha.compose.document.node.TableNode;
import com.demcha.compose.document.node.TextAlign;
-import com.demcha.compose.document.style.DocumentColor;
import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextIndent;
import com.demcha.compose.document.style.DocumentTextStyle;
-import com.demcha.compose.document.table.DocumentTableCell;
-import com.demcha.compose.document.table.DocumentTableColumn;
-import com.demcha.compose.document.table.DocumentTableStyle;
-import java.awt.Color;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
import java.util.function.Consumer;
/**
* Builder for semantic list nodes with marker and spacing controls.
+ *
* @since 1.0.0
*/
public final class ListBuilder {
- private String name = "";
private final List items = new ArrayList<>();
private final Map markerOverrides = new LinkedHashMap<>();
+ private String name = "";
private boolean usedNestedAuthoring = false;
private ListMarker marker = ListMarker.bullet();
private DocumentTextStyle textStyle = DocumentTextStyle.DEFAULT;
@@ -65,6 +36,23 @@ public final class ListBuilder {
public ListBuilder() {
}
+ private static List applyMarkerOverrides(List items,
+ int depth,
+ Map overrides) {
+ if (items.isEmpty()) {
+ return List.of();
+ }
+ List out = new ArrayList<>(items.size());
+ for (ListItem item : items) {
+ ListMarker effective = item.marker() != null
+ ? item.marker()
+ : overrides.get(depth);
+ List resolvedChildren = applyMarkerOverrides(item.children(), depth + 1, overrides);
+ out.add(new ListItem(item.label(), effective, resolvedChildren));
+ }
+ return List.copyOf(out);
+ }
+
/**
* Sets the list node name.
*
@@ -134,7 +122,7 @@ public ListBuilder addItem(String item) {
* leaves alongside the nested entries.
*
* @param label visible label for this item
- * @param body callback that adds children of this item
+ * @param body callback that adds children of this item
* @return this builder
*/
public ListBuilder addItem(String label, Consumer body) {
@@ -157,7 +145,7 @@ public ListBuilder addItem(String label, Consumer body) {
* This setter wins over the cascade but is overridden by an
* explicit per-item marker.
*
- * @param depth zero-based depth (0 = top-level)
+ * @param depth zero-based depth (0 = top-level)
* @param marker marker to render at that depth, or {@code null} to clear an override
* @return this builder
* @throws IllegalArgumentException when {@code depth} is negative
@@ -303,10 +291,10 @@ public ListBuilder padding(DocumentInsets padding) {
/**
* Sets list padding from explicit side values.
*
- * @param top top padding
- * @param right right padding
+ * @param top top padding
+ * @param right right padding
* @param bottom bottom padding
- * @param left left padding
+ * @param left left padding
* @return this builder
*/
public ListBuilder padding(float top, float right, float bottom, float left) {
@@ -327,10 +315,10 @@ public ListBuilder margin(DocumentInsets margin) {
/**
* Sets list margin from explicit side values.
*
- * @param top top margin
- * @param right right margin
+ * @param top top margin
+ * @param right right margin
* @param bottom bottom margin
- * @param left left margin
+ * @param left left margin
* @return this builder
*/
public ListBuilder margin(float top, float right, float bottom, float left) {
@@ -392,23 +380,6 @@ public ListNode build() {
margin);
}
- private static List applyMarkerOverrides(List items,
- int depth,
- Map overrides) {
- if (items.isEmpty()) {
- return List.of();
- }
- List out = new ArrayList<>(items.size());
- for (ListItem item : items) {
- ListMarker effective = item.marker() != null
- ? item.marker()
- : overrides.get(depth);
- List resolvedChildren = applyMarkerOverrides(item.children(), depth + 1, overrides);
- out.add(new ListItem(item.label(), effective, resolvedChildren));
- }
- return List.copyOf(out);
- }
-
/**
* Snapshots the items collected on this builder for use as a
* child sub-tree in a parent {@link #addItem(String, Consumer)}
diff --git a/src/main/java/com/demcha/compose/document/dsl/ModuleBuilder.java b/src/main/java/com/demcha/compose/document/dsl/ModuleBuilder.java
index 59c970c2f..032566ed5 100644
--- a/src/main/java/com/demcha/compose/document/dsl/ModuleBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/ModuleBuilder.java
@@ -1,42 +1,12 @@
package com.demcha.compose.document.dsl;
-import com.demcha.compose.document.api.DocumentSession;
-import com.demcha.compose.document.dsl.internal.BuilderSupport;
import com.demcha.compose.document.dsl.internal.SemanticNameNormalizer;
-import com.demcha.compose.document.image.DocumentImageData;
-import com.demcha.compose.document.node.BarcodeNode;
-import com.demcha.compose.document.node.ContainerNode;
-import com.demcha.compose.document.node.DocumentBarcodeOptions;
-import com.demcha.compose.document.node.DocumentBarcodeType;
-import com.demcha.compose.document.node.DocumentBookmarkOptions;
-import com.demcha.compose.document.node.DocumentLinkOptions;
-import com.demcha.compose.document.node.DocumentNode;
-import com.demcha.compose.document.node.ImageNode;
-import com.demcha.compose.document.node.InlineTextRun;
-import com.demcha.compose.document.node.ListMarker;
-import com.demcha.compose.document.node.ListNode;
-import com.demcha.compose.document.node.PageBreakNode;
-import com.demcha.compose.document.node.ParagraphNode;
-import com.demcha.compose.document.node.SectionNode;
-import com.demcha.compose.document.node.ShapeNode;
-import com.demcha.compose.document.node.TableNode;
-import com.demcha.compose.document.node.TextAlign;
-import com.demcha.compose.document.style.DocumentColor;
+import com.demcha.compose.document.node.*;
import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextIndent;
import com.demcha.compose.document.style.DocumentTextStyle;
-import com.demcha.compose.document.table.DocumentTableCell;
-import com.demcha.compose.document.table.DocumentTableColumn;
-import com.demcha.compose.document.table.DocumentTableStyle;
-import java.awt.Color;
-import java.nio.file.Path;
import java.util.ArrayList;
-import java.util.LinkedHashMap;
import java.util.List;
-import java.util.Map;
-import java.util.Objects;
import java.util.function.Consumer;
/**
@@ -52,6 +22,7 @@ public final class ModuleBuilder extends AbstractFlowBuilder items, Consumer spec) {
@@ -253,7 +224,7 @@ public ModuleBuilder table(Consumer spec) {
* Appends a simple table with auto-width columns.
*
* @param headers header row values
- * @param rows data rows
+ * @param rows data rows
* @return this builder
*/
public ModuleBuilder table(List headers, List> rows) {
@@ -320,8 +291,6 @@ public ModuleBuilder custom(DocumentNode node) {
return add(node);
}
- private boolean keepTogether = false;
-
/**
* Keeps the whole module (title plus body) on one page: when it does not fit
* in the remaining page space but fits on a fresh page, it relocates whole to
diff --git a/src/main/java/com/demcha/compose/document/dsl/PageBreakBuilder.java b/src/main/java/com/demcha/compose/document/dsl/PageBreakBuilder.java
index 4c5eda59c..3106c86a3 100644
--- a/src/main/java/com/demcha/compose/document/dsl/PageBreakBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/PageBreakBuilder.java
@@ -1,46 +1,11 @@
package com.demcha.compose.document.dsl;
-import com.demcha.compose.document.api.DocumentSession;
-import com.demcha.compose.document.dsl.internal.BuilderSupport;
-import com.demcha.compose.document.dsl.internal.SemanticNameNormalizer;
-import com.demcha.compose.document.image.DocumentImageData;
-import com.demcha.compose.document.node.BarcodeNode;
-import com.demcha.compose.document.node.ContainerNode;
-import com.demcha.compose.document.node.DocumentBarcodeOptions;
-import com.demcha.compose.document.node.DocumentBarcodeType;
-import com.demcha.compose.document.node.DocumentBookmarkOptions;
-import com.demcha.compose.document.node.DocumentLinkOptions;
-import com.demcha.compose.document.node.DocumentNode;
-import com.demcha.compose.document.node.ImageNode;
-import com.demcha.compose.document.node.InlineTextRun;
-import com.demcha.compose.document.node.ListMarker;
-import com.demcha.compose.document.node.ListNode;
import com.demcha.compose.document.node.PageBreakNode;
-import com.demcha.compose.document.node.ParagraphNode;
-import com.demcha.compose.document.node.SectionNode;
-import com.demcha.compose.document.node.ShapeNode;
-import com.demcha.compose.document.node.TableNode;
-import com.demcha.compose.document.node.TextAlign;
-import com.demcha.compose.document.style.DocumentColor;
import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextIndent;
-import com.demcha.compose.document.style.DocumentTextStyle;
-import com.demcha.compose.document.table.DocumentTableCell;
-import com.demcha.compose.document.table.DocumentTableColumn;
-import com.demcha.compose.document.table.DocumentTableStyle;
-
-import java.awt.Color;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.function.Consumer;
/**
* Builder for explicit page-break control nodes.
+ *
* @since 1.0.0
*/
public final class PageBreakBuilder {
diff --git a/src/main/java/com/demcha/compose/document/dsl/PageFlowBuilder.java b/src/main/java/com/demcha/compose/document/dsl/PageFlowBuilder.java
index 8e030180b..9f860498c 100644
--- a/src/main/java/com/demcha/compose/document/dsl/PageFlowBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/PageFlowBuilder.java
@@ -1,43 +1,7 @@
package com.demcha.compose.document.dsl;
import com.demcha.compose.document.api.DocumentSession;
-import com.demcha.compose.document.dsl.internal.BuilderSupport;
-import com.demcha.compose.document.dsl.internal.SemanticNameNormalizer;
-import com.demcha.compose.document.image.DocumentImageData;
-import com.demcha.compose.document.node.BarcodeNode;
import com.demcha.compose.document.node.ContainerNode;
-import com.demcha.compose.document.node.DocumentBarcodeOptions;
-import com.demcha.compose.document.node.DocumentBarcodeType;
-import com.demcha.compose.document.node.DocumentBookmarkOptions;
-import com.demcha.compose.document.node.DocumentLinkOptions;
-import com.demcha.compose.document.node.DocumentNode;
-import com.demcha.compose.document.node.ImageNode;
-import com.demcha.compose.document.node.InlineTextRun;
-import com.demcha.compose.document.node.ListMarker;
-import com.demcha.compose.document.node.ListNode;
-import com.demcha.compose.document.node.PageBreakNode;
-import com.demcha.compose.document.node.ParagraphNode;
-import com.demcha.compose.document.node.SectionNode;
-import com.demcha.compose.document.node.ShapeNode;
-import com.demcha.compose.document.node.TableNode;
-import com.demcha.compose.document.node.TextAlign;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextIndent;
-import com.demcha.compose.document.style.DocumentTextStyle;
-import com.demcha.compose.document.table.DocumentTableCell;
-import com.demcha.compose.document.table.DocumentTableColumn;
-import com.demcha.compose.document.table.DocumentTableStyle;
-
-import java.awt.Color;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.function.Consumer;
/**
* Builder for root page-flow containers that attach to a document session.
diff --git a/src/main/java/com/demcha/compose/document/dsl/ParagraphBuilder.java b/src/main/java/com/demcha/compose/document/dsl/ParagraphBuilder.java
index c86f92f24..b279ef8e8 100644
--- a/src/main/java/com/demcha/compose/document/dsl/ParagraphBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/ParagraphBuilder.java
@@ -698,6 +698,3 @@ public ParagraphNode build() {
}
}
-/**
- * Builder for simple semantic lists.
- */
diff --git a/src/main/java/com/demcha/compose/document/dsl/RichText.java b/src/main/java/com/demcha/compose/document/dsl/RichText.java
index c17df8516..a555f1d18 100644
--- a/src/main/java/com/demcha/compose/document/dsl/RichText.java
+++ b/src/main/java/com/demcha/compose/document/dsl/RichText.java
@@ -1,19 +1,10 @@
package com.demcha.compose.document.dsl;
import com.demcha.compose.document.image.DocumentImageData;
-import com.demcha.compose.document.node.DocumentLinkOptions;
-import com.demcha.compose.document.node.InlineImageAlignment;
-import com.demcha.compose.document.node.InlineShapeRun;
-import com.demcha.compose.document.node.InlineImageRun;
-import com.demcha.compose.document.node.InlineRun;
-import com.demcha.compose.document.node.InlineTextRun;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextDecoration;
-import com.demcha.compose.document.style.DocumentTextStyle;
-import com.demcha.compose.document.style.ShapeOutline;
-
-import java.awt.Color;
+import com.demcha.compose.document.node.*;
+import com.demcha.compose.document.style.*;
+
+import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -129,7 +120,7 @@ public RichText strikethrough(String text) {
/**
* Appends a colored text run with the default decoration.
*
- * @param text text fragment
+ * @param text text fragment
* @param color text color
* @return this builder
*/
@@ -140,7 +131,7 @@ public RichText color(String text, DocumentColor color) {
/**
* Convenience overload accepting a {@link Color}.
*
- * @param text text fragment
+ * @param text text fragment
* @param color text color
* @return this builder
*/
@@ -152,7 +143,7 @@ public RichText color(String text, Color color) {
* Appends a bold-and-colored "accent" text run — the typical pattern for
* highlighting status keywords ("Pending", "Paid", "Overdue") inline.
*
- * @param text text fragment
+ * @param text text fragment
* @param color accent color
* @return this builder
*/
@@ -167,7 +158,7 @@ public RichText accent(String text, DocumentColor color) {
* Convenience overload of {@link #accent(String, DocumentColor)} accepting a
* {@link Color}.
*
- * @param text text fragment
+ * @param text text fragment
* @param color accent color
* @return this builder
*/
@@ -190,7 +181,7 @@ public RichText size(String text, double size) {
/**
* Appends a fully-styled text run.
*
- * @param text text fragment
+ * @param text text fragment
* @param style explicit style for this run; when {@code null}, falls back
* to the paragraph default
* @return this builder
@@ -202,7 +193,7 @@ public RichText style(String text, DocumentTextStyle style) {
/**
* Appends a clickable link run with default link styling.
*
- * @param text visible link text
+ * @param text visible link text
* @param options link metadata
* @return this builder
*/
@@ -214,7 +205,7 @@ public RichText link(String text, DocumentLinkOptions options) {
* Convenience link overload using a raw URI string.
*
* @param text visible link text
- * @param uri link target URI
+ * @param uri link target URI
* @return this builder
*/
public RichText link(String text, String uri) {
@@ -225,9 +216,9 @@ public RichText link(String text, String uri) {
* Appends a fully-customized run with both an explicit style and link
* metadata.
*
- * @param text text fragment
+ * @param text text fragment
* @param style explicit style or {@code null}
- * @param link link metadata or {@code null}
+ * @param link link metadata or {@code null}
* @return this builder
*/
public RichText with(String text, DocumentTextStyle style, DocumentLinkOptions link) {
@@ -260,8 +251,8 @@ public RichText append(RichText other) {
* alignment and zero offset.
*
* @param imageData image payload
- * @param width target width in points
- * @param height target height in points
+ * @param width target width in points
+ * @param height target height in points
* @return this builder
*/
public RichText image(DocumentImageData imageData, double width, double height) {
@@ -272,8 +263,8 @@ public RichText image(DocumentImageData imageData, double width, double height)
* Appends an inline image run with explicit vertical alignment.
*
* @param imageData image payload
- * @param width target width in points
- * @param height target height in points
+ * @param width target width in points
+ * @param height target height in points
* @param alignment vertical alignment relative to surrounding text
* @return this builder
*/
@@ -288,12 +279,12 @@ public RichText image(DocumentImageData imageData,
* Appends a clickable inline image run; the link annotation covers the
* image rectangle on supporting backends.
*
- * @param imageData image payload
- * @param width target width in points
- * @param height target height in points
- * @param alignment vertical alignment relative to surrounding text
+ * @param imageData image payload
+ * @param width target width in points
+ * @param height target height in points
+ * @param alignment vertical alignment relative to surrounding text
* @param baselineOffset extra vertical shift in points; positive moves up
- * @param linkOptions optional link metadata
+ * @param linkOptions optional link metadata
* @return this builder
*/
public RichText image(DocumentImageData imageData,
@@ -318,7 +309,7 @@ public RichText image(DocumentImageData imageData,
* should not depend on font glyph coverage.
*
* @param diameter circle diameter in points
- * @param fill fill color
+ * @param fill fill color
* @return this builder
*/
public RichText dot(double diameter, DocumentColor fill) {
@@ -330,8 +321,8 @@ public RichText dot(double diameter, DocumentColor fill) {
* — for example a filled dot ({@code ●}) or an outlined one ({@code ○}).
*
* @param diameter circle diameter in points
- * @param fill optional fill color
- * @param stroke optional outline stroke
+ * @param fill optional fill color
+ * @param stroke optional outline stroke
* @return this builder
*/
public RichText dot(double diameter, DocumentColor fill, DocumentStroke stroke) {
@@ -342,9 +333,9 @@ public RichText dot(double diameter, DocumentColor fill, DocumentStroke stroke)
* Appends an inline ellipse run with default
* {@link InlineImageAlignment#CENTER} alignment and zero offset.
*
- * @param width target width in points
+ * @param width target width in points
* @param height target height in points
- * @param fill optional fill color
+ * @param fill optional fill color
* @param stroke optional outline stroke
* @return this builder
*/
@@ -389,9 +380,9 @@ public RichText star(double size, DocumentColor fill) {
* Appends an inline block arrow sized {@code size × size} pointing in
* {@code direction} — a directional marker between text or a list bullet.
*
- * @param size figure width and height in points
+ * @param size figure width and height in points
* @param direction the way the arrow points
- * @param fill fill color
+ * @param fill fill color
* @return this builder
*/
public RichText arrow(double size, ShapeOutline.Direction direction, DocumentColor fill) {
@@ -403,10 +394,10 @@ public RichText arrow(double size, ShapeOutline.Direction direction, DocumentCol
* swappable-design overload, so a caller (or a future "pick your arrow" UI)
* can choose a block arrow, a triangular arrowhead, etc.
*
- * @param size figure width and height in points
+ * @param size figure width and height in points
* @param direction the way the arrow points
- * @param style the arrow design
- * @param fill fill color
+ * @param style the arrow design
+ * @param fill fill color
* @return this builder
* @since 1.7.0
*/
@@ -422,9 +413,9 @@ public RichText arrow(double size,
* Appends an inline chevron sized {@code size × size} pointing in
* {@code direction} — a lighter directional separator for step lists.
*
- * @param size figure width and height in points
+ * @param size figure width and height in points
* @param direction the way the chevron points
- * @param fill fill color
+ * @param fill fill color
* @return this builder
*/
public RichText chevron(double size, ShapeOutline.Direction direction, DocumentColor fill) {
@@ -437,7 +428,7 @@ public RichText chevron(double size, ShapeOutline.Direction direction, DocumentC
* offset.
*
* @param outline figure geometry; supplies the run's size
- * @param fill fill color
+ * @param fill fill color
* @return this builder
*/
public RichText shape(ShapeOutline outline, DocumentColor fill) {
@@ -448,12 +439,12 @@ public RichText shape(ShapeOutline outline, DocumentColor fill) {
* Appends a fully-specified inline shape run of any {@link ShapeOutline}
* kind. At least one of {@code fill} or {@code stroke} must be present.
*
- * @param outline figure geometry; supplies the run's size
- * @param fill optional fill color
- * @param stroke optional outline stroke
- * @param alignment vertical alignment relative to surrounding text
+ * @param outline figure geometry; supplies the run's size
+ * @param fill optional fill color
+ * @param stroke optional outline stroke
+ * @param alignment vertical alignment relative to surrounding text
* @param baselineOffset extra vertical shift in points; positive moves up
- * @param linkOptions optional inline link metadata
+ * @param linkOptions optional inline link metadata
* @return this builder
*/
public RichText shape(ShapeOutline outline,
@@ -481,9 +472,9 @@ public RichText shape(ShapeOutline outline,
*
*
*
- * @param width sparkline width in points
+ * @param width sparkline width in points
* @param height sparkline height in points
- * @param fill silhouette fill colour
+ * @param fill silhouette fill colour
* @param values data run, at least two finite values
* @return this builder
* @since 1.8.0
@@ -497,11 +488,11 @@ public RichText sparkline(double width, double height, DocumentColor fill, doubl
* Appends an inline line sparkline — the value run as a
* constant-thickness stroked-looking band, without the filled area.
*
- * @param width sparkline width in points
- * @param height sparkline height in points
+ * @param width sparkline width in points
+ * @param height sparkline height in points
* @param thickness line thickness in points (must be smaller than {@code height})
- * @param color line colour
- * @param values data run, at least two finite values
+ * @param color line colour
+ * @param values data run, at least two finite values
* @return this builder
* @since 1.8.0
*/
@@ -520,9 +511,9 @@ public RichText sparklineLine(double width, double height, double thickness,
* centred checkmark inside (the checked state), each in its own colour —
* for todo / checklist markers between text.
*
- * @param size box width and height in points
- * @param checked whether the checkmark is shown
- * @param boxColor frame stroke color
+ * @param size box width and height in points
+ * @param checked whether the checkmark is shown
+ * @param boxColor frame stroke color
* @param checkColor checkmark fill color
* @return this builder
*/
@@ -535,9 +526,9 @@ public RichText checkbox(double size, boolean checked, DocumentColor boxColor, D
* Appends an inline checkbox using one colour for both the frame and the
* checkmark.
*
- * @param size box width and height in points
+ * @param size box width and height in points
* @param checked whether the checkmark is shown
- * @param color frame and checkmark color
+ * @param color frame and checkmark color
* @return this builder
*/
public RichText checkbox(double size, boolean checked, DocumentColor color) {
@@ -548,10 +539,10 @@ public RichText checkbox(double size, boolean checked, DocumentColor color) {
* Appends an inline checkbox whose checked-state tick uses the given
* {@link ShapeOutline.CheckmarkStyle} — the "pick your tick" overload.
*
- * @param size box width and height in points
- * @param checked whether the checkmark is shown
- * @param markStyle design of the checked-state tick
- * @param boxColor frame stroke color
+ * @param size box width and height in points
+ * @param checked whether the checkmark is shown
+ * @param markStyle design of the checked-state tick
+ * @param boxColor frame stroke color
* @param checkColor checkmark fill color
* @return this builder
* @since 1.7.0
@@ -570,11 +561,11 @@ public RichText checkbox(double size,
* {@link ShapeOutline} — the power-user overload. Size the mark to fit the
* frame (≈ {@code 0.6 × size}); it is drawn centred in the box.
*
- * @param size box width and height in points
- * @param checked whether the mark is shown
- * @param mark checked-state mark geometry, already sized; must be non-null
- * when {@code checked} is {@code true}
- * @param boxColor frame stroke color
+ * @param size box width and height in points
+ * @param checked whether the mark is shown
+ * @param mark checked-state mark geometry, already sized; must be non-null
+ * when {@code checked} is {@code true}
+ * @param boxColor frame stroke color
* @param checkColor mark fill color
* @return this builder
* @since 1.7.0
diff --git a/src/main/java/com/demcha/compose/document/dsl/RowBuilder.java b/src/main/java/com/demcha/compose/document/dsl/RowBuilder.java
index 03a0c6999..b4a193617 100644
--- a/src/main/java/com/demcha/compose/document/dsl/RowBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/RowBuilder.java
@@ -2,25 +2,8 @@
import com.demcha.compose.document.dsl.internal.BuilderSupport;
import com.demcha.compose.document.image.DocumentImageData;
-import com.demcha.compose.document.node.BarcodeNode;
-import com.demcha.compose.document.node.ContainerNode;
-import com.demcha.compose.document.node.DocumentNode;
-import com.demcha.compose.document.node.EllipseNode;
-import com.demcha.compose.document.node.ImageNode;
-import com.demcha.compose.document.node.LayerStackNode;
-import com.demcha.compose.document.node.LineNode;
-import com.demcha.compose.document.node.ParagraphNode;
-import com.demcha.compose.document.node.RowNode;
-import com.demcha.compose.document.node.SectionNode;
-import com.demcha.compose.document.node.ShapeNode;
-import com.demcha.compose.document.node.SpacerNode;
-import com.demcha.compose.document.node.TableNode;
-import com.demcha.compose.document.style.DocumentBorders;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentCornerRadius;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextStyle;
+import com.demcha.compose.document.node.*;
+import com.demcha.compose.document.style.*;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -47,9 +30,9 @@
* @since 1.0.0
*/
public final class RowBuilder {
- private String name = "";
private final List children = new ArrayList<>();
private final List weights = new ArrayList<>();
+ private String name = "";
private boolean weightsDirty;
private double gap;
private DocumentInsets padding = DocumentInsets.zero();
@@ -65,6 +48,23 @@ public final class RowBuilder {
public RowBuilder() {
}
+ private static boolean isAllowedRowChild(DocumentNode child) {
+ return child instanceof ParagraphNode
+ || child instanceof ImageNode
+ || child instanceof ShapeNode
+ || child instanceof LineNode
+ || child instanceof EllipseNode
+ || child instanceof SpacerNode
+ || child instanceof BarcodeNode
+ || child instanceof SectionNode
+ || child instanceof ContainerNode
+ // LayerStackNode is an atomic overlay composite: its layers
+ // share the same bounding box and do not compete with the
+ // parent row's horizontal band, so it is safe to drop into a
+ // row slot just like a section column.
+ || child instanceof LayerStackNode;
+ }
+
/**
* Sets the semantic row name.
*
@@ -94,7 +94,7 @@ public RowBuilder spacing(double spacing) {
* @param gap gap in points
* @return this builder
* @deprecated since 1.5.0, use {@link #spacing(double)} instead — vertical
- * flows and rows now share the same {@code spacing(...)} verb.
+ * flows and rows now share the same {@code spacing(...)} verb.
*/
@Deprecated(since = "1.5.0")
public RowBuilder gap(double gap) {
@@ -208,9 +208,9 @@ public RowBuilder evenWeights() {
*
* @param node atomic semantic node
* @return this builder
- * @throws NullPointerException if {@code node} is null
+ * @throws NullPointerException if {@code node} is null
* @throws IllegalArgumentException if {@code node} is a {@link RowNode},
- * a {@link TableNode}, or any other type the row layout cannot host
+ * a {@link TableNode}, or any other type the row layout cannot host
*/
public RowBuilder add(DocumentNode node) {
if (node == null) {
@@ -218,15 +218,15 @@ public RowBuilder add(DocumentNode node) {
}
if (node instanceof RowNode) {
throw new IllegalArgumentException("Row '" + name
- + "' cannot contain another row; use a section as a column instead.");
+ + "' cannot contain another row; use a section as a column instead.");
}
if (node instanceof TableNode) {
throw new IllegalArgumentException("Row '" + name
- + "' cannot contain a table; tables are splittable and would conflict with the row's atomic pagination.");
+ + "' cannot contain a table; tables are splittable and would conflict with the row's atomic pagination.");
}
if (!isAllowedRowChild(node)) {
throw new IllegalArgumentException("Row '" + name + "' does not support child node type '"
- + node.getClass().getSimpleName() + "'.");
+ + node.getClass().getSimpleName() + "'.");
}
this.children.add(node);
return this;
@@ -255,7 +255,7 @@ public RowBuilder addParagraph(String text) {
/**
* Adds a paragraph child with the supplied text style.
*
- * @param text paragraph text content
+ * @param text paragraph text content
* @param textStyle resolved text style
* @return this builder
*/
@@ -410,25 +410,8 @@ public RowNode build() {
private void validate() {
if (weightsDirty && !weights.isEmpty() && weights.size() != children.size()) {
throw new IllegalStateException("RowBuilder weights size " + weights.size()
- + " does not match children size " + children.size()
- + ". Pass " + children.size() + " weights or call evenWeights().");
+ + " does not match children size " + children.size()
+ + ". Pass " + children.size() + " weights or call evenWeights().");
}
}
-
- private static boolean isAllowedRowChild(DocumentNode child) {
- return child instanceof ParagraphNode
- || child instanceof ImageNode
- || child instanceof ShapeNode
- || child instanceof LineNode
- || child instanceof EllipseNode
- || child instanceof SpacerNode
- || child instanceof BarcodeNode
- || child instanceof SectionNode
- || child instanceof ContainerNode
- // LayerStackNode is an atomic overlay composite: its layers
- // share the same bounding box and do not compete with the
- // parent row's horizontal band, so it is safe to drop into a
- // row slot just like a section column.
- || child instanceof LayerStackNode;
- }
}
diff --git a/src/main/java/com/demcha/compose/document/dsl/SectionBuilder.java b/src/main/java/com/demcha/compose/document/dsl/SectionBuilder.java
index f31fa26c5..d4518928a 100644
--- a/src/main/java/com/demcha/compose/document/dsl/SectionBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/SectionBuilder.java
@@ -1,43 +1,6 @@
package com.demcha.compose.document.dsl;
-import com.demcha.compose.document.api.DocumentSession;
-import com.demcha.compose.document.dsl.internal.BuilderSupport;
-import com.demcha.compose.document.dsl.internal.SemanticNameNormalizer;
-import com.demcha.compose.document.image.DocumentImageData;
-import com.demcha.compose.document.node.BarcodeNode;
-import com.demcha.compose.document.node.ContainerNode;
-import com.demcha.compose.document.node.DocumentBarcodeOptions;
-import com.demcha.compose.document.node.DocumentBarcodeType;
-import com.demcha.compose.document.node.DocumentBookmarkOptions;
-import com.demcha.compose.document.node.DocumentLinkOptions;
-import com.demcha.compose.document.node.DocumentNode;
-import com.demcha.compose.document.node.ImageNode;
-import com.demcha.compose.document.node.InlineTextRun;
-import com.demcha.compose.document.node.ListMarker;
-import com.demcha.compose.document.node.ListNode;
-import com.demcha.compose.document.node.PageBreakNode;
-import com.demcha.compose.document.node.ParagraphNode;
import com.demcha.compose.document.node.SectionNode;
-import com.demcha.compose.document.node.ShapeNode;
-import com.demcha.compose.document.node.TableNode;
-import com.demcha.compose.document.node.TextAlign;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextIndent;
-import com.demcha.compose.document.style.DocumentTextStyle;
-import com.demcha.compose.document.table.DocumentTableCell;
-import com.demcha.compose.document.table.DocumentTableColumn;
-import com.demcha.compose.document.table.DocumentTableStyle;
-
-import java.awt.Color;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.function.Consumer;
/**
* Builder for semantic sections inside document flows.
diff --git a/src/main/java/com/demcha/compose/document/dsl/ShapeBuilder.java b/src/main/java/com/demcha/compose/document/dsl/ShapeBuilder.java
index 03a8ae2f7..21821a47d 100644
--- a/src/main/java/com/demcha/compose/document/dsl/ShapeBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/ShapeBuilder.java
@@ -1,45 +1,11 @@
package com.demcha.compose.document.dsl;
-import com.demcha.compose.document.api.DocumentSession;
-import com.demcha.compose.document.dsl.internal.BuilderSupport;
-import com.demcha.compose.document.dsl.internal.SemanticNameNormalizer;
-import com.demcha.compose.document.image.DocumentImageData;
-import com.demcha.compose.document.node.BarcodeNode;
-import com.demcha.compose.document.node.ContainerNode;
-import com.demcha.compose.document.node.DocumentBarcodeOptions;
-import com.demcha.compose.document.node.DocumentBarcodeType;
import com.demcha.compose.document.node.DocumentBookmarkOptions;
import com.demcha.compose.document.node.DocumentLinkOptions;
-import com.demcha.compose.document.node.DocumentNode;
-import com.demcha.compose.document.node.ImageNode;
-import com.demcha.compose.document.node.InlineTextRun;
-import com.demcha.compose.document.node.ListMarker;
-import com.demcha.compose.document.node.ListNode;
-import com.demcha.compose.document.node.PageBreakNode;
-import com.demcha.compose.document.node.ParagraphNode;
-import com.demcha.compose.document.node.SectionNode;
import com.demcha.compose.document.node.ShapeNode;
-import com.demcha.compose.document.node.TableNode;
-import com.demcha.compose.document.node.TextAlign;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentCornerRadius;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextIndent;
-import com.demcha.compose.document.style.DocumentTextStyle;
-import com.demcha.compose.document.style.DocumentTransform;
-import com.demcha.compose.document.table.DocumentTableCell;
-import com.demcha.compose.document.table.DocumentTableColumn;
-import com.demcha.compose.document.table.DocumentTableStyle;
+import com.demcha.compose.document.style.*;
-import java.awt.Color;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.function.Consumer;
+import java.awt.*;
/**
* Builder for rectangle-like semantic shape nodes.
@@ -103,7 +69,7 @@ public ShapeBuilder height(double height) {
/**
* Sets shape width and height.
*
- * @param width width in points
+ * @param width width in points
* @param height height in points
* @return this builder
*/
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 34b0dc5e6..b1c28c50f 100644
--- a/src/main/java/com/demcha/compose/document/dsl/ShapeContainerBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/ShapeContainerBuilder.java
@@ -4,15 +4,9 @@
import com.demcha.compose.document.node.LayerAlign;
import com.demcha.compose.document.node.LayerStackNode;
import com.demcha.compose.document.node.ShapeContainerNode;
-import com.demcha.compose.document.style.ClipPolicy;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentCornerRadius;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTransform;
-import com.demcha.compose.document.style.ShapeOutline;
-
-import java.awt.Color;
+import com.demcha.compose.document.style.*;
+
+import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -31,9 +25,9 @@
* @since 1.0.0
*/
public final class ShapeContainerBuilder implements Transformable {
+ private final List layers = new ArrayList<>();
private String name = "";
private ShapeOutline outline;
- private final List layers = new ArrayList<>();
// Default to CLIP_PATH per ADR §Decision — see ShapeContainerNode for
// the rationale.
private ClipPolicy clipPolicy = ClipPolicy.CLIP_PATH;
@@ -63,7 +57,7 @@ public ShapeContainerBuilder name(String name) {
/**
* Sets a plain rectangle outline.
*
- * @param width outline width in points
+ * @param width outline width in points
* @param height outline height in points
* @return this builder
*/
@@ -75,8 +69,8 @@ public ShapeContainerBuilder rectangle(double width, double height) {
/**
* Sets a rounded-rectangle outline.
*
- * @param width outline width in points
- * @param height outline height in points
+ * @param width outline width in points
+ * @param height outline height in points
* @param cornerRadius corner radius in points
* @return this builder
*/
@@ -90,8 +84,8 @@ public ShapeContainerBuilder roundedRect(double width, double height, double cor
* it to round only one side of a container (e.g.
* {@link DocumentCornerRadius#right(double)}) without a CLIP_PATH parent.
*
- * @param width outline width in points
- * @param height outline height in points
+ * @param width outline width in points
+ * @param height outline height in points
* @param cornerRadius per-corner radii
* @return this builder
* @since 1.7.0
@@ -104,7 +98,7 @@ public ShapeContainerBuilder roundedRect(double width, double height, DocumentCo
/**
* Sets an ellipse outline.
*
- * @param width outline width in points
+ * @param width outline width in points
* @param height outline height in points
* @return this builder
*/
@@ -127,7 +121,7 @@ public ShapeContainerBuilder circle(double diameter) {
/**
* Sets a diamond (rhombus) outline.
*
- * @param width outline width in points
+ * @param width outline width in points
* @param height outline height in points
* @return this builder
*/
@@ -139,7 +133,7 @@ public ShapeContainerBuilder diamond(double width, double height) {
/**
* Sets an upward-pointing triangle outline.
*
- * @param width outline width in points
+ * @param width outline width in points
* @param height outline height in points
* @return this builder
*/
@@ -151,7 +145,7 @@ public ShapeContainerBuilder triangle(double width, double height) {
/**
* Sets a five-pointed star outline.
*
- * @param width outline width in points
+ * @param width outline width in points
* @param height outline height in points
* @return this builder
*/
@@ -163,7 +157,7 @@ public ShapeContainerBuilder star(double width, double height) {
/**
* Sets an {@code n}-pointed star outline.
*
- * @param width outline width in points
+ * @param width outline width in points
* @param height outline height in points
* @param points number of outer points (at least 2)
* @return this builder
@@ -176,8 +170,8 @@ public ShapeContainerBuilder star(double width, double height, int points) {
/**
* Sets a block arrow outline pointing in {@code direction}.
*
- * @param width outline width in points
- * @param height outline height in points
+ * @param width outline width in points
+ * @param height outline height in points
* @param direction the way the arrow points
* @return this builder
*/
@@ -189,8 +183,8 @@ public ShapeContainerBuilder arrow(double width, double height, ShapeOutline.Dir
/**
* Sets a chevron outline pointing in {@code direction}.
*
- * @param width outline width in points
- * @param height outline height in points
+ * @param width outline width in points
+ * @param height outline height in points
* @param direction the way the chevron points
* @return this builder
*/
@@ -321,7 +315,7 @@ public DocumentTransform currentTransform() {
/**
* Appends a layer with explicit alignment.
*
- * @param node child node
+ * @param node child node
* @param align anchor inside the inner box
* @return this builder
*/
@@ -335,8 +329,8 @@ public ShapeContainerBuilder layer(DocumentNode node, LayerAlign align) {
* {@code zIndex} renders on top of lower {@code zIndex} regardless
* of source order; the default is {@code 0}.
*
- * @param node child node
- * @param align anchor inside the inner box
+ * @param node child node
+ * @param align anchor inside the inner box
* @param zIndex render-order key
* @return this builder
*/
@@ -360,10 +354,10 @@ public ShapeContainerBuilder layer(DocumentNode node) {
* Appends a layer anchored to {@code align} and shifted by an on-screen
* offset (positive {@code offsetX} = right, positive {@code offsetY} = down).
*
- * @param node child node
+ * @param node child node
* @param offsetX horizontal offset in points
* @param offsetY vertical offset in points
- * @param align anchor inside the inner box
+ * @param align anchor inside the inner box
* @return this builder
*/
public ShapeContainerBuilder position(DocumentNode node,
@@ -379,11 +373,11 @@ public ShapeContainerBuilder position(DocumentNode node,
* Appends a layer anchored to {@code align}, shifted by an on-screen
* offset, and assigned an explicit z-index.
*
- * @param node child node
+ * @param node child node
* @param offsetX horizontal offset in points
* @param offsetY vertical offset in points
- * @param align anchor inside the inner box
- * @param zIndex render-order key
+ * @param align anchor inside the inner box
+ * @param zIndex render-order key
* @return this builder
*/
public ShapeContainerBuilder position(DocumentNode node,
@@ -510,7 +504,7 @@ public ShapeContainerNode build() {
if (outline == null) {
throw new IllegalStateException(
"ShapeContainerBuilder '" + name + "' requires an outline; "
- + "call rectangle/roundedRect/ellipse/circle before build().");
+ + "call rectangle/roundedRect/ellipse/circle before build().");
}
return new ShapeContainerNode(name, outline, layers, clipPolicy, fillColor, stroke, padding, margin, transform);
}
diff --git a/src/main/java/com/demcha/compose/document/dsl/SpacerBuilder.java b/src/main/java/com/demcha/compose/document/dsl/SpacerBuilder.java
index 5b72ea480..9dd95c305 100644
--- a/src/main/java/com/demcha/compose/document/dsl/SpacerBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/SpacerBuilder.java
@@ -58,7 +58,7 @@ public SpacerBuilder height(double height) {
/**
* Sets spacer width and height.
*
- * @param width width in points
+ * @param width width in points
* @param height height in points
* @return this builder
*/
diff --git a/src/main/java/com/demcha/compose/document/dsl/SparklineGeometry.java b/src/main/java/com/demcha/compose/document/dsl/SparklineGeometry.java
index 12c08287d..a5490475c 100644
--- a/src/main/java/com/demcha/compose/document/dsl/SparklineGeometry.java
+++ b/src/main/java/com/demcha/compose/document/dsl/SparklineGeometry.java
@@ -46,7 +46,7 @@ static List areaPoints(double[] values) {
* offset is vertical (not perpendicular), which is visually equivalent at
* sparkline sizes and keeps the maths exact.
*
- * @param values at least two finite values
+ * @param values at least two finite values
* @param thicknessFraction band thickness as a fraction of the box height, in (0, 1)
* @return closed ring of {@code 2n} normalized vertices
*/
diff --git a/src/main/java/com/demcha/compose/document/dsl/TableBuilder.java b/src/main/java/com/demcha/compose/document/dsl/TableBuilder.java
index dc2922106..07e09c3fa 100644
--- a/src/main/java/com/demcha/compose/document/dsl/TableBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/TableBuilder.java
@@ -1,37 +1,29 @@
package com.demcha.compose.document.dsl;
-import com.demcha.compose.document.dsl.internal.BuilderSupport;
import com.demcha.compose.document.node.DocumentBookmarkOptions;
import com.demcha.compose.document.node.DocumentLinkOptions;
-import com.demcha.compose.document.node.DocumentNode;
import com.demcha.compose.document.node.TableNode;
-import com.demcha.compose.document.node.TextAlign;
import com.demcha.compose.document.style.DocumentColor;
import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
import com.demcha.compose.document.style.DocumentTextDecoration;
import com.demcha.compose.document.style.DocumentTextStyle;
import com.demcha.compose.document.table.DocumentTableCell;
import com.demcha.compose.document.table.DocumentTableColumn;
import com.demcha.compose.document.table.DocumentTableStyle;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.function.Consumer;
+import java.util.*;
/**
* Builder for semantic table nodes.
+ *
* @since 1.0.0
*/
public final class TableBuilder {
- private String name = "";
private final List columns = new ArrayList<>();
private final List> rows = new ArrayList<>();
private final Map rowStyles = new LinkedHashMap<>();
private final Map columnStyles = new LinkedHashMap<>();
+ private String name = "";
private DocumentTableStyle defaultCellStyle = DocumentTableStyle.empty();
private Double width;
private DocumentLinkOptions linkOptions;
@@ -54,6 +46,15 @@ public final class TableBuilder {
public TableBuilder() {
}
+ private static DocumentTableStyle defaultTotalRowStyle() {
+ return DocumentTableStyle.builder()
+ .textStyle(DocumentTextStyle.builder()
+ .decoration(DocumentTextDecoration.BOLD)
+ .build())
+ .fillColor(DocumentColor.rgb(240, 240, 245))
+ .build();
+ }
+
/**
* Sets the table node name.
*
@@ -181,8 +182,8 @@ public TableBuilder headerRow(String... values) {
* row alternation because the row's index is added to {@code rowStyles}
* directly.
*
- * @param style totals-row style override (typically bold + a subtle
- * fill to separate the totals from the data rows)
+ * @param style totals-row style override (typically bold + a subtle
+ * fill to separate the totals from the data rows)
* @param values totals cell text values
* @return this builder
*/
@@ -206,15 +207,6 @@ public TableBuilder totalRow(String... values) {
return totalRow(defaultTotalRowStyle(), values);
}
- private static DocumentTableStyle defaultTotalRowStyle() {
- return DocumentTableStyle.builder()
- .textStyle(DocumentTextStyle.builder()
- .decoration(DocumentTextDecoration.BOLD)
- .build())
- .fillColor(DocumentColor.rgb(240, 240, 245))
- .build();
- }
-
/**
* Configures alternating row fill colours. The {@code odd} style is
* applied to rows at index 0, 2, 4 (visually first, third, fifth);
@@ -228,8 +220,8 @@ private static DocumentTableStyle defaultTotalRowStyle() {
* {@link #headerStyle(DocumentTableStyle)} or
* {@link #totalRow(String...)} take precedence.
*
- * @param odd style for odd-indexed rows (index 0, 2, 4 — first,
- * third, fifth visually)
+ * @param odd style for odd-indexed rows (index 0, 2, 4 — first,
+ * third, fifth visually)
* @param even style for even-indexed rows (index 1, 3, 5)
* @return this builder
*/
@@ -244,7 +236,7 @@ public TableBuilder zebra(DocumentTableStyle odd, DocumentTableStyle even) {
* skipping any other styling. Either colour may be {@code null} to
* leave that parity unstyled.
*
- * @param odd fill colour for odd-indexed rows (1st, 3rd, 5th)
+ * @param odd fill colour for odd-indexed rows (1st, 3rd, 5th)
* @param even fill colour for even-indexed rows (2nd, 4th, 6th)
* @return this builder
*/
@@ -345,7 +337,7 @@ public TableBuilder headerStyle(DocumentTableStyle style) {
* Applies a public canonical style override to a row.
*
* @param rowIndex zero-based row index
- * @param style row style override
+ * @param style row style override
* @return this builder
*/
public TableBuilder rowStyle(int rowIndex, DocumentTableStyle style) {
@@ -360,7 +352,7 @@ public TableBuilder rowStyle(int rowIndex, DocumentTableStyle style) {
* Applies a public canonical style override to a column.
*
* @param columnIndex zero-based column index
- * @param style column style override
+ * @param style column style override
* @return this builder
*/
public TableBuilder columnStyle(int columnIndex, DocumentTableStyle style) {
diff --git a/src/main/java/com/demcha/compose/document/dsl/TimelineBuilder.java b/src/main/java/com/demcha/compose/document/dsl/TimelineBuilder.java
index 989f9bc5a..39d9d2a0a 100644
--- a/src/main/java/com/demcha/compose/document/dsl/TimelineBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/TimelineBuilder.java
@@ -44,7 +44,7 @@ public final class TimelineBuilder {
private static final DocumentColor DEFAULT_RAIL = DocumentColor.rgb(150, 158, 172);
private static final DocumentColor DEFAULT_INK = DocumentColor.rgb(34, 38, 50);
private static final DocumentColor DEFAULT_MUTED = DocumentColor.rgb(120, 124, 136);
-
+ private final List entries = new ArrayList<>();
private DocumentColor connectorColor = DEFAULT_RAIL;
private double connectorWidth = 1.5;
private double gutter = 8.0;
@@ -57,11 +57,38 @@ public final class TimelineBuilder {
private boolean keepTogether = false;
private boolean keepEntriesTogether = false;
- private final List entries = new ArrayList<>();
-
TimelineBuilder() {
}
+ private static boolean notBlank(String value) {
+ return value != null && !value.isBlank();
+ }
+
+ private static DocumentTextStyle defaultTitleStyle() {
+ return DocumentTextStyle.builder()
+ .fontName(FontName.HELVETICA_BOLD)
+ .decoration(DocumentTextDecoration.BOLD)
+ .size(11)
+ .color(DEFAULT_INK)
+ .build();
+ }
+
+ private static DocumentTextStyle defaultMetaStyle() {
+ return DocumentTextStyle.builder()
+ .fontName(FontName.HELVETICA)
+ .size(8.5)
+ .color(DEFAULT_MUTED)
+ .build();
+ }
+
+ private static DocumentTextStyle defaultBodyStyle() {
+ return DocumentTextStyle.builder()
+ .fontName(FontName.HELVETICA)
+ .size(9.5)
+ .color(DEFAULT_INK)
+ .build();
+ }
+
/**
* Sets the connector rail colour and width.
*
@@ -168,7 +195,7 @@ public TimelineBuilder bodyStyle(DocumentTextStyle style) {
/**
* Adds one timeline entry — a marker paired with its content.
*
- * @param marker the marker drawn in the rail for this entry
+ * @param marker the marker drawn in the rail for this entry
* @param content callback configuring the entry's title, meta and body
* @return this builder
* @throws NullPointerException if {@code marker} is {@code null}
@@ -267,35 +294,6 @@ void buildInto(SectionBuilder timeline) {
}
}
- private static boolean notBlank(String value) {
- return value != null && !value.isBlank();
- }
-
- private static DocumentTextStyle defaultTitleStyle() {
- return DocumentTextStyle.builder()
- .fontName(FontName.HELVETICA_BOLD)
- .decoration(DocumentTextDecoration.BOLD)
- .size(11)
- .color(DEFAULT_INK)
- .build();
- }
-
- private static DocumentTextStyle defaultMetaStyle() {
- return DocumentTextStyle.builder()
- .fontName(FontName.HELVETICA)
- .size(8.5)
- .color(DEFAULT_MUTED)
- .build();
- }
-
- private static DocumentTextStyle defaultBodyStyle() {
- return DocumentTextStyle.builder()
- .fontName(FontName.HELVETICA)
- .size(9.5)
- .color(DEFAULT_INK)
- .build();
- }
-
private record Entry(TimelineMarker marker, TimelineEntryBuilder entry) {
}
}
diff --git a/src/main/java/com/demcha/compose/document/dsl/TimelineEntryBuilder.java b/src/main/java/com/demcha/compose/document/dsl/TimelineEntryBuilder.java
index fcb0431f7..aed8216b9 100644
--- a/src/main/java/com/demcha/compose/document/dsl/TimelineEntryBuilder.java
+++ b/src/main/java/com/demcha/compose/document/dsl/TimelineEntryBuilder.java
@@ -78,7 +78,7 @@ public TimelineEntryBuilder meta(String meta) {
/**
* Sets the meta line with a per-entry style override.
*
- * @param meta meta text
+ * @param meta meta text
* @param style meta text style
* @return this builder
*/
@@ -113,7 +113,7 @@ public TimelineEntryBuilder body(String body) {
/**
* Sets the entry body with a per-entry style override.
*
- * @param body body text
+ * @param body body text
* @param style body text style
* @return this builder
*/
diff --git a/src/main/java/com/demcha/compose/document/dsl/TimelineMarker.java b/src/main/java/com/demcha/compose/document/dsl/TimelineMarker.java
index 19e3a2168..3ea83ddac 100644
--- a/src/main/java/com/demcha/compose/document/dsl/TimelineMarker.java
+++ b/src/main/java/com/demcha/compose/document/dsl/TimelineMarker.java
@@ -1,11 +1,7 @@
package com.demcha.compose.document.dsl;
import com.demcha.compose.document.node.TextAlign;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextDecoration;
-import com.demcha.compose.document.style.DocumentTextStyle;
+import com.demcha.compose.document.style.*;
import com.demcha.compose.font.FontName;
import java.util.function.Consumer;
@@ -36,7 +32,7 @@ private TimelineMarker(double size, Consumer recipe) {
/**
* A solid filled dot.
*
- * @param size diameter in points
+ * @param size diameter in points
* @param color fill colour
* @return the marker
*/
@@ -47,8 +43,8 @@ public static TimelineMarker dot(double size, DocumentColor color) {
/**
* An outlined circle (filled and/or stroked).
*
- * @param size diameter in points
- * @param fill fill colour, or {@code null} for an unfilled ring
+ * @param size diameter in points
+ * @param fill fill colour, or {@code null} for an unfilled ring
* @param stroke outline stroke, or {@code null} for no outline
* @return the marker
*/
@@ -66,9 +62,9 @@ public static TimelineMarker circle(double size, DocumentColor fill, DocumentStr
/**
* A numbered disc — a filled circle with a centred number.
*
- * @param number the step number to centre in the disc
- * @param size diameter in points
- * @param fill disc fill colour
+ * @param number the step number to centre in the disc
+ * @param size diameter in points
+ * @param fill disc fill colour
* @param textColor number colour; {@code null} falls back to white
* @return the marker
*/
diff --git a/src/main/java/com/demcha/compose/document/dsl/internal/BuilderSupport.java b/src/main/java/com/demcha/compose/document/dsl/internal/BuilderSupport.java
index ea7f8a42c..eeaf06480 100644
--- a/src/main/java/com/demcha/compose/document/dsl/internal/BuilderSupport.java
+++ b/src/main/java/com/demcha/compose/document/dsl/internal/BuilderSupport.java
@@ -3,7 +3,9 @@
import java.util.Objects;
import java.util.function.Consumer;
-/** Internal helper for applying builder customizers. */
+/**
+ * Internal helper for applying builder customizers.
+ */
public final class BuilderSupport {
private BuilderSupport() {
}
@@ -12,8 +14,8 @@ private BuilderSupport() {
* Applies a non-null customizer to the supplied builder and returns it.
*
* @param builder builder being configured
- * @param spec callback that mutates the builder
- * @param builder type
+ * @param spec callback that mutates the builder
+ * @param builder type
* @return the same builder instance
*/
public static B configure(B builder, Consumer spec) {
diff --git a/src/main/java/com/demcha/compose/document/dsl/internal/SemanticNameNormalizer.java b/src/main/java/com/demcha/compose/document/dsl/internal/SemanticNameNormalizer.java
index c3471bc8d..be92872ef 100644
--- a/src/main/java/com/demcha/compose/document/dsl/internal/SemanticNameNormalizer.java
+++ b/src/main/java/com/demcha/compose/document/dsl/internal/SemanticNameNormalizer.java
@@ -1,6 +1,8 @@
package com.demcha.compose.document.dsl.internal;
-/** Normalizes free-form labels into stable semantic node names. */
+/**
+ * Normalizes free-form labels into stable semantic node names.
+ */
public final class SemanticNameNormalizer {
private SemanticNameNormalizer() {
}
diff --git a/src/main/java/com/demcha/compose/document/exceptions/DocumentRenderingException.java b/src/main/java/com/demcha/compose/document/exceptions/DocumentRenderingException.java
index fc78ef120..46edfb8ef 100644
--- a/src/main/java/com/demcha/compose/document/exceptions/DocumentRenderingException.java
+++ b/src/main/java/com/demcha/compose/document/exceptions/DocumentRenderingException.java
@@ -25,7 +25,7 @@ public class DocumentRenderingException extends RuntimeException {
* Creates a rendering exception with a message and a wrapped cause.
*
* @param message diagnostic message describing what failed
- * @param cause underlying exception thrown by the rendering pipeline
+ * @param cause underlying exception thrown by the rendering pipeline
*/
public DocumentRenderingException(String message, Throwable cause) {
super(message, cause);
diff --git a/src/main/java/com/demcha/compose/document/layout/BoxConstraints.java b/src/main/java/com/demcha/compose/document/layout/BoxConstraints.java
index d89bc5373..49e2d9689 100644
--- a/src/main/java/com/demcha/compose/document/layout/BoxConstraints.java
+++ b/src/main/java/com/demcha/compose/document/layout/BoxConstraints.java
@@ -3,7 +3,7 @@
/**
* Available layout space for one node measurement/layout step.
*
- * @param availableWidth available content width
+ * @param availableWidth available content width
* @param availableHeight available content height
*/
public record BoxConstraints(double availableWidth, double availableHeight) {
diff --git a/src/main/java/com/demcha/compose/document/layout/BuiltInNodeDefinitions.java b/src/main/java/com/demcha/compose/document/layout/BuiltInNodeDefinitions.java
index 69e5b5d19..8a9094951 100644
--- a/src/main/java/com/demcha/compose/document/layout/BuiltInNodeDefinitions.java
+++ b/src/main/java/com/demcha/compose/document/layout/BuiltInNodeDefinitions.java
@@ -1,23 +1,6 @@
package com.demcha.compose.document.layout;
-import com.demcha.compose.document.layout.definitions.BarcodeDefinition;
-import com.demcha.compose.document.layout.definitions.CanvasLayerDefinition;
-import com.demcha.compose.document.layout.definitions.ChartDefinition;
-import com.demcha.compose.document.layout.definitions.ContainerDefinition;
-import com.demcha.compose.document.layout.definitions.EllipseDefinition;
-import com.demcha.compose.document.layout.definitions.ImageDefinition;
-import com.demcha.compose.document.layout.definitions.LayerStackDefinition;
-import com.demcha.compose.document.layout.definitions.LineDefinition;
-import com.demcha.compose.document.layout.definitions.ListDefinition;
-import com.demcha.compose.document.layout.definitions.PageBreakDefinition;
-import com.demcha.compose.document.layout.definitions.ParagraphDefinition;
-import com.demcha.compose.document.layout.definitions.PolygonDefinition;
-import com.demcha.compose.document.layout.definitions.RowDefinition;
-import com.demcha.compose.document.layout.definitions.SectionDefinition;
-import com.demcha.compose.document.layout.definitions.ShapeContainerDefinition;
-import com.demcha.compose.document.layout.definitions.ShapeDefinition;
-import com.demcha.compose.document.layout.definitions.SpacerDefinition;
-import com.demcha.compose.document.layout.definitions.TableDefinition;
+import com.demcha.compose.document.layout.definitions.*;
import java.util.Objects;
diff --git a/src/main/java/com/demcha/compose/document/layout/CompositeLayoutSpec.java b/src/main/java/com/demcha/compose/document/layout/CompositeLayoutSpec.java
index e2281e406..7dd9d0070 100644
--- a/src/main/java/com/demcha/compose/document/layout/CompositeLayoutSpec.java
+++ b/src/main/java/com/demcha/compose/document/layout/CompositeLayoutSpec.java
@@ -10,26 +10,10 @@
* the row's inner width is distributed across children.
*
* @param spacing spacing between child nodes (vertical for {@link Axis#VERTICAL}, horizontal for {@link Axis#HORIZONTAL})
- * @param axis composite stacking axis
+ * @param axis composite stacking axis
* @param weights optional per-child weights (only consulted for {@link Axis#HORIZONTAL})
*/
public record CompositeLayoutSpec(double spacing, Axis axis, List weights) {
- /**
- * Composite stacking axis.
- */
- public enum Axis {
- /** Children stack top to bottom. */
- VERTICAL,
- /** Children flow left to right inside a single row band. */
- HORIZONTAL,
- /**
- * Children share the same bounding box and are painted in source order
- * (first child behind, last child in front). Used by {@code LayerStackNode}
- * to compose background panels, watermarks, and overlay decorations.
- */
- STACK
- }
-
/**
* Creates a validated composite child-layout contract.
*/
@@ -59,9 +43,29 @@ public CompositeLayoutSpec(double spacing) {
* Convenience constructor without explicit weights.
*
* @param spacing spacing between children
- * @param axis stacking axis
+ * @param axis stacking axis
*/
public CompositeLayoutSpec(double spacing, Axis axis) {
this(spacing, axis, List.of());
}
+
+ /**
+ * Composite stacking axis.
+ */
+ public enum Axis {
+ /**
+ * Children stack top to bottom.
+ */
+ VERTICAL,
+ /**
+ * Children flow left to right inside a single row band.
+ */
+ HORIZONTAL,
+ /**
+ * Children share the same bounding box and are painted in source order
+ * (first child behind, last child in front). Used by {@code LayerStackNode}
+ * to compose background panels, watermarks, and overlay decorations.
+ */
+ STACK
+ }
}
diff --git a/src/main/java/com/demcha/compose/document/layout/DocumentLayoutPassContext.java b/src/main/java/com/demcha/compose/document/layout/DocumentLayoutPassContext.java
index ae5b26ee6..1bd885b38 100644
--- a/src/main/java/com/demcha/compose/document/layout/DocumentLayoutPassContext.java
+++ b/src/main/java/com/demcha/compose/document/layout/DocumentLayoutPassContext.java
@@ -30,11 +30,11 @@ public final class DocumentLayoutPassContext implements PrepareContext, Fragment
/**
* Creates a layout-pass context.
*
- * @param registry semantic node registry used for preparation
- * @param canvas active layout canvas
- * @param fontLibrary document font library
+ * @param registry semantic node registry used for preparation
+ * @param canvas active layout canvas
+ * @param fontLibrary document font library
* @param textMeasurementSystem text measurement service for this pass
- * @param markdown whether paragraph markdown parsing is enabled
+ * @param markdown whether paragraph markdown parsing is enabled
*/
public DocumentLayoutPassContext(NodeRegistry registry,
LayoutCanvas canvas,
diff --git a/src/main/java/com/demcha/compose/document/layout/DocumentNodeAdapters.java b/src/main/java/com/demcha/compose/document/layout/DocumentNodeAdapters.java
index d566b88d2..7ec2c4df8 100644
--- a/src/main/java/com/demcha/compose/document/layout/DocumentNodeAdapters.java
+++ b/src/main/java/com/demcha/compose/document/layout/DocumentNodeAdapters.java
@@ -1,11 +1,7 @@
package com.demcha.compose.document.layout;
import com.demcha.compose.document.image.DocumentImageData;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTextDecoration;
-import com.demcha.compose.document.style.DocumentTextIndent;
-import com.demcha.compose.document.style.DocumentTextStyle;
+import com.demcha.compose.document.style.*;
import com.demcha.compose.document.table.DocumentTableCell;
import com.demcha.compose.document.table.DocumentTableColumn;
import com.demcha.compose.document.table.DocumentTableStyle;
diff --git a/src/main/java/com/demcha/compose/document/layout/FixedSlotPlacementContext.java b/src/main/java/com/demcha/compose/document/layout/FixedSlotPlacementContext.java
index 1305405e3..3f27efbdc 100644
--- a/src/main/java/com/demcha/compose/document/layout/FixedSlotPlacementContext.java
+++ b/src/main/java/com/demcha/compose/document/layout/FixedSlotPlacementContext.java
@@ -8,12 +8,12 @@
* place into a fixed page band — the parent flow has already decided which
* page is being filled, so children must not move on by themselves.
*
- * @param pageIndex pinned page index that placements land on
- * @param canvas canvas the placement is happening on
- * @param prepareContext prepare-phase context used to (re)measure children
+ * @param pageIndex pinned page index that placements land on
+ * @param canvas canvas the placement is happening on
+ * @param prepareContext prepare-phase context used to (re)measure children
* @param fragmentContext fragment-emission context forwarded to {@code emitFragments}
- * @param nodes mutable list of placed semantic nodes; helpers append to this
- * @param fragments mutable list of placed render fragments; helpers append to this
+ * @param nodes mutable list of placed semantic nodes; helpers append to this
+ * @param fragments mutable list of placed render fragments; helpers append to this
* @author Artem Demchyshyn
*/
public record FixedSlotPlacementContext(
@@ -34,7 +34,7 @@ public boolean canAdvancePage() {
public void advancePage() {
throw new IllegalStateException(
"FixedSlotPlacementContext is locked to page " + pageIndex
- + " and cannot advance pages.");
+ + " and cannot advance pages.");
}
@Override
diff --git a/src/main/java/com/demcha/compose/document/layout/FragmentContext.java b/src/main/java/com/demcha/compose/document/layout/FragmentContext.java
index ccc2894b3..5bd0572dc 100644
--- a/src/main/java/com/demcha/compose/document/layout/FragmentContext.java
+++ b/src/main/java/com/demcha/compose/document/layout/FragmentContext.java
@@ -1,8 +1,8 @@
package com.demcha.compose.document.layout;
import com.demcha.compose.document.node.DocumentNode;
-import com.demcha.compose.font.FontLibrary;
import com.demcha.compose.engine.measurement.TextMeasurementSystem;
+import com.demcha.compose.font.FontLibrary;
import java.util.List;
@@ -52,15 +52,15 @@ default boolean markdownEnabled() {
* {@code FragmentContext} implementations have to opt-in to the
* recursion.
*
- * @param child prepared child node previously obtained from
- * {@link PrepareContext#prepare(DocumentNode, BoxConstraints)}
+ * @param child prepared child node previously obtained from
+ * {@link PrepareContext#prepare(DocumentNode, BoxConstraints)}
* @param placement placement assigned to the child within the
* composite parent's geometry
- * @param child node type
+ * @param child node type
* @return fragments emitted by the child's {@code NodeDefinition}
* @throws UnsupportedOperationException when the
- * {@code FragmentContext} implementation does not back
- * child-fragment emission
+ * {@code FragmentContext} implementation does not back
+ * child-fragment emission
*/
default List emitChildFragments(
PreparedNode child,
diff --git a/src/main/java/com/demcha/compose/document/layout/FragmentPlacement.java b/src/main/java/com/demcha/compose/document/layout/FragmentPlacement.java
index c02ed6f38..a6be0261d 100644
--- a/src/main/java/com/demcha/compose/document/layout/FragmentPlacement.java
+++ b/src/main/java/com/demcha/compose/document/layout/FragmentPlacement.java
@@ -6,19 +6,19 @@
/**
* Resolved placement context for fragment emission.
*
- * @param path stable semantic path for the placed node
+ * @param path stable semantic path for the placed node
* @param parentPath parent semantic path, or {@code null} for a root
* @param childIndex index within the parent child list
- * @param depth depth in the semantic tree
- * @param pageIndex page that receives this fragment
- * @param x absolute page x coordinate
- * @param y absolute page y coordinate
- * @param width resolved fragment width
- * @param height resolved fragment height
- * @param startPage first page occupied by the owning node
- * @param endPage last page occupied by the owning node
- * @param margin resolved outer margin
- * @param padding resolved inner padding
+ * @param depth depth in the semantic tree
+ * @param pageIndex page that receives this fragment
+ * @param x absolute page x coordinate
+ * @param y absolute page y coordinate
+ * @param width resolved fragment width
+ * @param height resolved fragment height
+ * @param startPage first page occupied by the owning node
+ * @param endPage last page occupied by the owning node
+ * @param margin resolved outer margin
+ * @param padding resolved inner padding
*/
public record FragmentPlacement(
String path,
diff --git a/src/main/java/com/demcha/compose/document/layout/LayoutCanvas.java b/src/main/java/com/demcha/compose/document/layout/LayoutCanvas.java
index 8f916704f..b7d05bbc0 100644
--- a/src/main/java/com/demcha/compose/document/layout/LayoutCanvas.java
+++ b/src/main/java/com/demcha/compose/document/layout/LayoutCanvas.java
@@ -5,18 +5,18 @@
/**
* Page geometry used by the v2 compiler and backends.
*
- * @param width full page width
- * @param height full page height
- * @param innerWidth page width after horizontal margins
+ * @param width full page width
+ * @param height full page height
+ * @param innerWidth page width after horizontal margins
* @param innerHeight page height after vertical margins
- * @param margin page margin
+ * @param margin page margin
*/
public record LayoutCanvas(double width, double height, double innerWidth, double innerHeight, Margin margin) {
/**
* Creates canvas geometry from backend-neutral page dimensions and margin.
*
- * @param width physical page width
+ * @param width physical page width
* @param height physical page height
* @param margin page margin; null becomes zero margin
* @return normalized canvas geometry
diff --git a/src/main/java/com/demcha/compose/document/layout/LayoutCompiler.java b/src/main/java/com/demcha/compose/document/layout/LayoutCompiler.java
index ed846f556..d775f7dee 100644
--- a/src/main/java/com/demcha/compose/document/layout/LayoutCompiler.java
+++ b/src/main/java/com/demcha/compose/document/layout/LayoutCompiler.java
@@ -1,12 +1,12 @@
package com.demcha.compose.document.layout;
+import com.demcha.compose.document.exceptions.AtomicNodeTooLargeException;
import com.demcha.compose.document.layout.payloads.PreparedStackLayout;
import com.demcha.compose.document.node.DocumentNode;
+import com.demcha.compose.document.node.LayerStackNode;
import com.demcha.compose.document.node.PageBreakNode;
-
import com.demcha.compose.engine.components.style.Margin;
import com.demcha.compose.engine.components.style.Padding;
-import com.demcha.compose.document.exceptions.AtomicNodeTooLargeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,26 +40,6 @@ public final class LayoutCompiler {
* full page at all?" check.
*/
private static final double CAPACITY_TOLERANCE = 0.5;
-
- /**
- * Identifies the kind of fixed slot a child is being compiled into,
- * so the validator can distinguish "child of a horizontal row band"
- * (where a nested {@code Row} would create real composition conflict)
- * from "child of a {@link com.demcha.compose.document.node.LayerStackNode}
- * layer" (where a nested {@code Row} is a normal column-row inside an
- * already-fixed layer rectangle).
- *
- *
{@link #compileNodeInFixedSlot} takes the kind as a parameter
- * and propagates it down recursive calls so the validator can
- * relax just for STACK layer parents.
- */
- private enum FixedSlotKind {
- /** Child sits inside a horizontal row band (column of a row). */
- ROW_SLOT,
- /** Child sits inside a {@link LayerStackNode} layer rectangle. */
- STACK_LAYER_SLOT
- }
-
private final NodeRegistry registry;
/**
@@ -72,11 +52,114 @@ public LayoutCompiler(NodeRegistry registry) {
this.registry = Objects.requireNonNull(registry, "registry");
}
+ /**
+ * Returns an iteration order over {@code zIndices} that is stable on
+ * ties. Layers with equal {@code zIndex} keep their source order, so
+ * the default of all-zero zIndices yields the identity permutation
+ * {@code [0, 1, ..., n-1]} and existing snapshots stay deterministic.
+ *
+ * @param zIndices per-layer render-order keys (in source order)
+ * @return source indices sorted by ascending {@code zIndex}, stable
+ * on ties
+ */
+ private static int[] stableZIndexOrder(java.util.List zIndices) {
+ int n = zIndices.size();
+ if (n <= 1) {
+ return identityOrder(n);
+ }
+ // Common case: every layer uses the same zIndex (typically 0). A
+ // stable sort would preserve source order anyway, so skip the boxed
+ // array allocation and the full sort.
+ int firstZ = zIndices.get(0);
+ boolean allEqual = true;
+ for (int i = 1; i < n; i++) {
+ if (zIndices.get(i) != firstZ) {
+ allEqual = false;
+ break;
+ }
+ }
+ if (allEqual) {
+ return identityOrder(n);
+ }
+ Integer[] boxed = new Integer[n];
+ for (int i = 0; i < n; i++) {
+ boxed[i] = i;
+ }
+ // Comparator.comparingInt + java.util.Arrays.sort on boxed array is
+ // documented stable; primitive int[] sort is not.
+ java.util.Arrays.sort(boxed, java.util.Comparator.comparingInt(zIndices::get));
+ int[] order = new int[n];
+ for (int i = 0; i < n; i++) {
+ order[i] = boxed[i];
+ }
+ return order;
+ }
+
+ private static int[] identityOrder(int n) {
+ int[] order = new int[n];
+ for (int i = 0; i < n; i++) {
+ order[i] = i;
+ }
+ return order;
+ }
+
+ private static double horizontalLayerOffset(com.demcha.compose.document.node.LayerAlign align,
+ double innerWidth,
+ double childOuterWidth) {
+ return switch (align) {
+ case TOP_LEFT, CENTER_LEFT, BOTTOM_LEFT -> 0.0;
+ case TOP_CENTER, CENTER, BOTTOM_CENTER -> Math.max(0.0, (innerWidth - childOuterWidth) / 2.0);
+ case TOP_RIGHT, CENTER_RIGHT, BOTTOM_RIGHT -> Math.max(0.0, innerWidth - childOuterWidth);
+ };
+ }
+
+ private static double verticalLayerOffset(com.demcha.compose.document.node.LayerAlign align,
+ double innerHeight,
+ double childOuterHeight) {
+ return switch (align) {
+ case TOP_LEFT, TOP_CENTER, TOP_RIGHT -> 0.0;
+ case CENTER_LEFT, CENTER, CENTER_RIGHT -> Math.max(0.0, (innerHeight - childOuterHeight) / 2.0);
+ case BOTTOM_LEFT, BOTTOM_CENTER, BOTTOM_RIGHT -> Math.max(0.0, innerHeight - childOuterHeight);
+ };
+ }
+
+ private static double[] distributeRowSlotWidths(List children,
+ List weights,
+ double gap,
+ double innerWidth) {
+ int n = children.size();
+ double available = Math.max(0.0, innerWidth - gap * Math.max(0, n - 1));
+ double[] slots = new double[n];
+ if (weights == null || weights.isEmpty()) {
+ double share = n > 0 ? available / n : 0.0;
+ for (int i = 0; i < n; i++) {
+ slots[i] = share;
+ }
+ return slots;
+ }
+ RowSlots.validateWeightsMatchChildren(weights, n);
+ double total = 0.0;
+ for (double w : weights) {
+ total += w;
+ }
+ if (total <= 0.0) {
+ double share = n > 0 ? available / n : 0.0;
+ for (int i = 0; i < n; i++) {
+ slots[i] = share;
+ }
+ return slots;
+ }
+ for (int i = 0; i < n; i++) {
+ slots[i] = available * (weights.get(i) / total);
+ }
+ return slots;
+ }
+
/**
* Compiles semantic roots into placed nodes and renderable fragments.
*
- * @param graph semantic document graph
- * @param prepareContext node preparation context
+ * @param graph semantic document graph
+ * @param prepareContext node preparation context
* @param fragmentContext fragment emission context
* @return fixed-layout graph ready for rendering or snapshot extraction
*/
@@ -157,15 +240,15 @@ private void compileNode(PreparedNode prepared,
if (availableWidth <= EPS) {
throw new IllegalStateException("Node '" + path
- + "' has no horizontal layout space. "
- + "Reduce padding or margin on the parent, or increase the page width.");
+ + "' has no horizontal layout space. "
+ + "Reduce padding or margin on the parent, or increase the page width.");
}
MeasureResult naturalMeasure = prepared.measureResult();
if (naturalMeasure.width() > availableWidth + EPS) {
throw new IllegalStateException("Node '" + path + "' measured width " + naturalMeasure.width()
- + " exceeds available width " + availableWidth + ". "
- + "Reduce the node width, shorten inline content, or wrap content in a smaller container.");
+ + " exceeds available width " + availableWidth + ". "
+ + "Reduce the node width, shorten inline content, or wrap content in a smaller container.");
}
if (prepared.isComposite()) {
@@ -264,7 +347,7 @@ private void compileComposite(PreparedNode prepared,
// existing layouts are unchanged.
double outerHeight = naturalMeasure.height() + margin.vertical();
boolean keepWhole = node.keepTogether()
- && outerHeight <= state.canvas.innerHeight() + CAPACITY_TOLERANCE;
+ && outerHeight <= state.canvas.innerHeight() + CAPACITY_TOLERANCE;
double startReservation = margin.top() + padding.top();
if (keepWhole && outerHeight > state.remainingHeight() + EPS && state.usedHeight > EPS) {
state.newPage();
@@ -412,8 +495,8 @@ private void compileHorizontalRow(PreparedNode prepared,
(NodeDefinition) registry.definitionFor(child);
if (childMeasure.height() > naturalMeasure.height() - padding.vertical() + EPS) {
throw new IllegalStateException("Row '" + path + "' child '" + child.nodeKind()
- + "' measured height " + childMeasure.height() + " exceeds row inner height. "
- + "Reduce the child height, shorten its content, or increase the row height.");
+ + "' measured height " + childMeasure.height() + " exceeds row inner height. "
+ + "Reduce the child height, shorten its content, or increase the row height.");
}
if (childPrepared.isComposite()) {
@@ -671,109 +754,6 @@ private void compileStackedLayer(PreparedNode prepared,
state.usedHeight += stackOuterHeight;
}
- /**
- * Returns an iteration order over {@code zIndices} that is stable on
- * ties. Layers with equal {@code zIndex} keep their source order, so
- * the default of all-zero zIndices yields the identity permutation
- * {@code [0, 1, ..., n-1]} and existing snapshots stay deterministic.
- *
- * @param zIndices per-layer render-order keys (in source order)
- * @return source indices sorted by ascending {@code zIndex}, stable
- * on ties
- */
- private static int[] stableZIndexOrder(java.util.List zIndices) {
- int n = zIndices.size();
- if (n <= 1) {
- return identityOrder(n);
- }
- // Common case: every layer uses the same zIndex (typically 0). A
- // stable sort would preserve source order anyway, so skip the boxed
- // array allocation and the full sort.
- int firstZ = zIndices.get(0);
- boolean allEqual = true;
- for (int i = 1; i < n; i++) {
- if (zIndices.get(i) != firstZ) {
- allEqual = false;
- break;
- }
- }
- if (allEqual) {
- return identityOrder(n);
- }
- Integer[] boxed = new Integer[n];
- for (int i = 0; i < n; i++) {
- boxed[i] = i;
- }
- // Comparator.comparingInt + java.util.Arrays.sort on boxed array is
- // documented stable; primitive int[] sort is not.
- java.util.Arrays.sort(boxed, java.util.Comparator.comparingInt(zIndices::get));
- int[] order = new int[n];
- for (int i = 0; i < n; i++) {
- order[i] = boxed[i];
- }
- return order;
- }
-
- private static int[] identityOrder(int n) {
- int[] order = new int[n];
- for (int i = 0; i < n; i++) {
- order[i] = i;
- }
- return order;
- }
-
- private static double horizontalLayerOffset(com.demcha.compose.document.node.LayerAlign align,
- double innerWidth,
- double childOuterWidth) {
- return switch (align) {
- case TOP_LEFT, CENTER_LEFT, BOTTOM_LEFT -> 0.0;
- case TOP_CENTER, CENTER, BOTTOM_CENTER -> Math.max(0.0, (innerWidth - childOuterWidth) / 2.0);
- case TOP_RIGHT, CENTER_RIGHT, BOTTOM_RIGHT -> Math.max(0.0, innerWidth - childOuterWidth);
- };
- }
-
- private static double verticalLayerOffset(com.demcha.compose.document.node.LayerAlign align,
- double innerHeight,
- double childOuterHeight) {
- return switch (align) {
- case TOP_LEFT, TOP_CENTER, TOP_RIGHT -> 0.0;
- case CENTER_LEFT, CENTER, CENTER_RIGHT -> Math.max(0.0, (innerHeight - childOuterHeight) / 2.0);
- case BOTTOM_LEFT, BOTTOM_CENTER, BOTTOM_RIGHT -> Math.max(0.0, innerHeight - childOuterHeight);
- };
- }
-
- private static double[] distributeRowSlotWidths(List children,
- List weights,
- double gap,
- double innerWidth) {
- int n = children.size();
- double available = Math.max(0.0, innerWidth - gap * Math.max(0, n - 1));
- double[] slots = new double[n];
- if (weights == null || weights.isEmpty()) {
- double share = n > 0 ? available / n : 0.0;
- for (int i = 0; i < n; i++) {
- slots[i] = share;
- }
- return slots;
- }
- RowSlots.validateWeightsMatchChildren(weights, n);
- double total = 0.0;
- for (double w : weights) {
- total += w;
- }
- if (total <= 0.0) {
- double share = n > 0 ? available / n : 0.0;
- for (int i = 0; i < n; i++) {
- slots[i] = share;
- }
- return slots;
- }
- for (int i = 0; i < n; i++) {
- slots[i] = available * (weights.get(i) / total);
- }
- return slots;
- }
-
private void compileAtomicLeaf(PreparedNode prepared,
NodeDefinition definition,
String path,
@@ -911,11 +891,11 @@ private void placeStackLayer(DocumentNode child,
// offsetX > 0 nudges the layer right; offsetY > 0 nudges it down
// (PDF y grows upward, so "down" subtracts from the top-Y).
double alignedSlotX = innerStartX
- + horizontalLayerOffset(align, innerWidth, childOuterWidth)
- + layerOffsetX;
+ + horizontalLayerOffset(align, innerWidth, childOuterWidth)
+ + layerOffsetX;
double alignedSlotTopY = innerTopY
- - verticalLayerOffset(align, innerHeight, childOuterHeight)
- - layerOffsetY;
+ - verticalLayerOffset(align, innerHeight, childOuterHeight)
+ - layerOffsetY;
// Layers always paint into a fixed page band — even when the
// surrounding flow is mutating, the overlay is pinned to ctx's
@@ -923,12 +903,12 @@ private void placeStackLayer(DocumentNode child,
PlacementContext layerCtx = ctx instanceof FixedSlotPlacementContext fixed
? fixed
: new FixedSlotPlacementContext(
- ctx.pageIndex(),
- ctx.canvas(),
- ctx.prepareContext(),
- ctx.fragmentContext(),
- ctx.nodes(),
- ctx.fragments());
+ ctx.pageIndex(),
+ ctx.canvas(),
+ ctx.prepareContext(),
+ ctx.fragmentContext(),
+ ctx.nodes(),
+ ctx.fragments());
// Child sits inside a LayerStack layer rectangle — the validator
// can relax for STACK_LAYER_SLOT because there is no competing
@@ -1033,8 +1013,8 @@ private void compileSplittableLeaf(PreparedNode prepared,
}
if (tail != null && tail.equals(current)) {
throw new IllegalStateException("Split did not make progress for node '" + path
- + "'. The node's NodeDefinition.split() returned the original input as the tail — "
- + "check the definition for an infinite split loop and ensure each split advances.");
+ + "'. The node's NodeDefinition.split() returned the original input as the tail — "
+ + "check the definition for an infinite split loop and ensure each split advances.");
}
DocumentNode headNode = head.node();
@@ -1128,7 +1108,7 @@ private void compileSplittableLeaf(PreparedNode prepared,
* band.
*
* @return outer height (measured height + vertical margin) consumed by the
- * node, used by the caller's local y-cursor
+ * node, used by the caller's local y-cursor
*/
private double compileNodeInFixedSlot(PreparedNode prepared,
String parentPath,
@@ -1174,11 +1154,11 @@ private double compileNodeInFixedSlot(PreparedNode prepared,
// because they are atomic and anchor their children inside
// the existing slot.
if (layoutSpec.axis() == CompositeLayoutSpec.Axis.HORIZONTAL
- && kind == FixedSlotKind.ROW_SLOT) {
+ && kind == FixedSlotKind.ROW_SLOT) {
throw new IllegalStateException("Row '" + path
- + "' cannot contain a nested horizontal row. "
- + "Wrap the inner row in a LayerStack layer (allowed since v1.6.2), "
- + "or stack horizontal content as sections inside a vertical column.");
+ + "' cannot contain a nested horizontal row. "
+ + "Wrap the inner row in a LayerStack layer (allowed since v1.6.2), "
+ + "or stack horizontal content as sections inside a vertical column.");
}
int decorationInsertIndex = fragments.size();
@@ -1512,8 +1492,8 @@ private String pathFor(DocumentNode node, String parentPath, int childIndex) {
base = node.nodeKind();
}
String segment = base.trim()
- .replace('\\', '_')
- .replace('/', '_') + "[" + childIndex + "]";
+ .replace('\\', '_')
+ .replace('/', '_') + "[" + childIndex + "]";
return parentPath == null ? segment : parentPath + "/" + segment;
}
@@ -1527,10 +1507,33 @@ private String semanticName(DocumentNode node) {
private AtomicNodeTooLargeException atomicTooLarge(String path, double outerHeight, double pageHeight) {
return new AtomicNodeTooLargeException(
"Node '" + path + "' requires outer height " + outerHeight
- + " but page capacity is " + pageHeight + ". "
- + "Reduce the node height, split content into multiple atomic blocks, "
- + "or increase the page size. Differences under 0.5 pt are tolerated as "
- + "rounding noise (v1.6.2+).");
+ + " but page capacity is " + pageHeight + ". "
+ + "Reduce the node height, split content into multiple atomic blocks, "
+ + "or increase the page size. Differences under 0.5 pt are tolerated as "
+ + "rounding noise (v1.6.2+).");
+ }
+
+ /**
+ * Identifies the kind of fixed slot a child is being compiled into,
+ * so the validator can distinguish "child of a horizontal row band"
+ * (where a nested {@code Row} would create real composition conflict)
+ * from "child of a {@link com.demcha.compose.document.node.LayerStackNode}
+ * layer" (where a nested {@code Row} is a normal column-row inside an
+ * already-fixed layer rectangle).
+ *
+ *
{@link #compileNodeInFixedSlot} takes the kind as a parameter
+ * and propagates it down recursive calls so the validator can
+ * relax just for STACK layer parents.
+ */
+ private enum FixedSlotKind {
+ /**
+ * Child sits inside a horizontal row band (column of a row).
+ */
+ ROW_SLOT,
+ /**
+ * Child sits inside a {@link LayerStackNode} layer rectangle.
+ */
+ STACK_LAYER_SLOT
}
}
diff --git a/src/main/java/com/demcha/compose/document/layout/LayoutFragment.java b/src/main/java/com/demcha/compose/document/layout/LayoutFragment.java
index 58b5a5f30..5301962e5 100644
--- a/src/main/java/com/demcha/compose/document/layout/LayoutFragment.java
+++ b/src/main/java/com/demcha/compose/document/layout/LayoutFragment.java
@@ -3,13 +3,13 @@
/**
* Page-agnostic fragment emitted by a node definition.
*
- * @param path stable semantic path for the fragment owner
+ * @param path stable semantic path for the fragment owner
* @param fragmentIndex index within the owner's emitted fragments
- * @param localX x offset relative to the owner placement
- * @param localY y offset relative to the owner placement
- * @param width fragment width
- * @param height fragment height
- * @param payload backend-specific fragment payload
+ * @param localX x offset relative to the owner placement
+ * @param localY y offset relative to the owner placement
+ * @param width fragment width
+ * @param height fragment height
+ * @param payload backend-specific fragment payload
*/
public record LayoutFragment(
String path,
diff --git a/src/main/java/com/demcha/compose/document/layout/LayoutGraph.java b/src/main/java/com/demcha/compose/document/layout/LayoutGraph.java
index 48c3db076..d4f6eef58 100644
--- a/src/main/java/com/demcha/compose/document/layout/LayoutGraph.java
+++ b/src/main/java/com/demcha/compose/document/layout/LayoutGraph.java
@@ -6,10 +6,10 @@
/**
* Canonical resolved v2 layout graph.
*
- * @param canvas physical page canvas used for the graph
+ * @param canvas physical page canvas used for the graph
* @param totalPages number of pages required by the graph
- * @param nodes placed semantic nodes in deterministic order
- * @param fragments placed render fragments in deterministic order
+ * @param nodes placed semantic nodes in deterministic order
+ * @param fragments placed render fragments in deterministic order
*/
public record LayoutGraph(
LayoutCanvas canvas,
diff --git a/src/main/java/com/demcha/compose/document/layout/MeasureContext.java b/src/main/java/com/demcha/compose/document/layout/MeasureContext.java
index 66d885684..3292032ff 100644
--- a/src/main/java/com/demcha/compose/document/layout/MeasureContext.java
+++ b/src/main/java/com/demcha/compose/document/layout/MeasureContext.java
@@ -1,9 +1,8 @@
package com.demcha.compose.document.layout;
import com.demcha.compose.document.node.DocumentNode;
-
-import com.demcha.compose.font.FontLibrary;
import com.demcha.compose.engine.measurement.TextMeasurementSystem;
+import com.demcha.compose.font.FontLibrary;
/**
* Shared measurement context passed to node definitions.
@@ -12,7 +11,7 @@ public interface MeasureContext {
/**
* Measures a semantic node under the supplied constraints.
*
- * @param node semantic node
+ * @param node semantic node
* @param constraints available layout constraints
* @return measured box size
*/
diff --git a/src/main/java/com/demcha/compose/document/layout/MeasureResult.java b/src/main/java/com/demcha/compose/document/layout/MeasureResult.java
index bf63c91cc..a52e380da 100644
--- a/src/main/java/com/demcha/compose/document/layout/MeasureResult.java
+++ b/src/main/java/com/demcha/compose/document/layout/MeasureResult.java
@@ -3,7 +3,7 @@
/**
* Measured node box size excluding margin.
*
- * @param width measured content width
+ * @param width measured content width
* @param height measured content height
*/
public record MeasureResult(double width, double height) {
diff --git a/src/main/java/com/demcha/compose/document/layout/NodeDefinition.java b/src/main/java/com/demcha/compose/document/layout/NodeDefinition.java
index e4e253d23..56ab91470 100644
--- a/src/main/java/com/demcha/compose/document/layout/NodeDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/NodeDefinition.java
@@ -35,8 +35,8 @@ public interface NodeDefinition {
/**
* Prepares one semantic node for later measurement, pagination, and fragment emission.
*
- * @param node semantic node instance being compiled
- * @param ctx preparation context with measurement services and caches
+ * @param node semantic node instance being compiled
+ * @param ctx preparation context with measurement services and caches
* @param constraints available layout space for this compilation step
* @return prepared node carrying measured dimensions and optional prepared layout data
*/
@@ -54,7 +54,7 @@ public interface NodeDefinition {
* Splits a prepared node when the current page cannot fit it whole.
*
* @param prepared prepared node candidate
- * @param request split request describing remaining page space
+ * @param request split request describing remaining page space
* @return split head/tail result, or throws when the node does not support splitting
* @throws UnsupportedOperationException when the definition does not implement splitting
*/
@@ -75,8 +75,8 @@ default List children(E node) {
/**
* Emits renderer-facing fragments for one fully placed semantic node.
*
- * @param prepared prepared node being emitted
- * @param ctx fragment emission context
+ * @param prepared prepared node being emitted
+ * @param ctx fragment emission context
* @param placement resolved placement for the node
* @return immutable list of emitted layout fragments
*/
@@ -97,8 +97,8 @@ default List children(E node) {
* emitted here (so it sits after the children, restoring graphics
* state on the same page).
*
- * @param prepared prepared node being emitted
- * @param ctx fragment emission context
+ * @param prepared prepared node being emitted
+ * @param ctx fragment emission context
* @param placement resolved placement for the node
* @return immutable list of overlay fragments, possibly empty
*/
diff --git a/src/main/java/com/demcha/compose/document/layout/NodeDefinitionSupport.java b/src/main/java/com/demcha/compose/document/layout/NodeDefinitionSupport.java
index 5f8a0424c..396f89459 100644
--- a/src/main/java/com/demcha/compose/document/layout/NodeDefinitionSupport.java
+++ b/src/main/java/com/demcha/compose/document/layout/NodeDefinitionSupport.java
@@ -1,30 +1,16 @@
package com.demcha.compose.document.layout;
import com.demcha.compose.document.image.DocumentImageData;
-import com.demcha.compose.document.layout.payloads.ShapeFragmentPayload;
-import com.demcha.compose.document.layout.payloads.SideBorders;
-import com.demcha.compose.document.layout.payloads.TableRowFragmentPayload;
-import com.demcha.compose.engine.components.content.table.TableResolvedCell;
-import com.demcha.compose.document.layout.payloads.TransformBeginPayload;
-import com.demcha.compose.document.layout.payloads.TransformEndPayload;
-import com.demcha.compose.document.node.DocumentBarcodeOptions;
-import com.demcha.compose.document.node.DocumentBarcodeType;
-import com.demcha.compose.document.node.DocumentNode;
-import com.demcha.compose.document.node.ImageNode;
-import com.demcha.compose.document.node.LayerStackNode;
-import com.demcha.compose.document.node.RowNode;
-import com.demcha.compose.document.node.TableNode;
-import com.demcha.compose.document.style.DocumentBorders;
-import com.demcha.compose.document.style.DocumentCornerRadius;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTransform;
+import com.demcha.compose.document.layout.payloads.*;
+import com.demcha.compose.document.node.*;
+import com.demcha.compose.document.style.*;
import com.demcha.compose.engine.components.content.ImageData;
import com.demcha.compose.engine.components.content.barcode.BarcodeData;
import com.demcha.compose.engine.components.content.shape.Stroke;
+import com.demcha.compose.engine.components.content.table.TableResolvedCell;
import com.demcha.compose.engine.components.style.Padding;
-import java.awt.Color;
+import java.awt.*;
import java.util.ArrayList;
import java.util.List;
@@ -82,7 +68,7 @@ public static ImageData toImageData(DocumentImageData imageData) {
* Wraps an atomic leaf fragment with transform-begin / transform-end markers
* when the transform is non-identity.
*
- * @param leaf resolved leaf fragment
+ * @param leaf resolved leaf fragment
* @param placement resolved fragment placement
* @param transform optional render-time transform
* @return the leaf alone for identity transforms, otherwise begin/leaf/end
@@ -123,11 +109,11 @@ public static List wrapAtomicWithTransform(LayoutFragment leaf,
/**
* Emits an optional background/border decoration fragment.
*
- * @param fillColor optional fill color
- * @param stroke optional uniform stroke
+ * @param fillColor optional fill color
+ * @param stroke optional uniform stroke
* @param cornerRadius optional per-corner radius
- * @param sideBorders optional per-side borders
- * @param placement resolved placement
+ * @param sideBorders optional per-side borders
+ * @param placement resolved placement
* @return one shape fragment or an empty list when nothing should render
*/
public static List emitDecorationFragment(Color fillColor,
@@ -142,10 +128,10 @@ public static List emitDecorationFragment(Color fillColor,
/**
* Emits an optional background/border decoration fragment.
*
- * @param fillColor optional fill color
- * @param stroke optional uniform stroke
+ * @param fillColor optional fill color
+ * @param stroke optional uniform stroke
* @param cornerRadius uniform corner radius
- * @param placement resolved placement
+ * @param placement resolved placement
* @return one shape fragment or an empty list when nothing should render
*/
public static List emitDecorationFragment(Color fillColor,
@@ -158,11 +144,11 @@ public static List emitDecorationFragment(Color fillColor,
/**
* Emits an optional background/border decoration fragment.
*
- * @param fillColor optional fill color
- * @param stroke optional uniform stroke
+ * @param fillColor optional fill color
+ * @param stroke optional uniform stroke
* @param cornerRadius uniform corner radius
- * @param sideBorders optional per-side borders
- * @param placement resolved placement
+ * @param sideBorders optional per-side borders
+ * @param placement resolved placement
* @return one shape fragment or an empty list when nothing should render
*/
public static List emitDecorationFragment(Color fillColor,
@@ -219,7 +205,7 @@ public static BarcodeData toBarcodeData(DocumentBarcodeOptions options) {
* Resolves image display dimensions from requested size, scale, intrinsic
* metadata, and available width.
*
- * @param node image node to measure
+ * @param node image node to measure
* @param availableWidth parent available width
* @return resolved image dimensions excluding padding
*/
@@ -266,10 +252,10 @@ public static ImageDimensions resolveImageDimensions(ImageNode node, double avai
* Measures a vertical composite node by preparing children inside the
* padding-adjusted inner width.
*
- * @param children semantic child nodes
- * @param spacing vertical spacing between children
- * @param padding engine padding
- * @param ctx prepare context
+ * @param children semantic child nodes
+ * @param spacing vertical spacing between children
+ * @param padding engine padding
+ * @param ctx prepare context
* @param constraints parent constraints
* @return measured outer size
*/
@@ -302,9 +288,9 @@ public static MeasureResult measureComposite(List children,
/**
* Measures a horizontal row by preparing each child in its weighted slot.
*
- * @param node row node
- * @param padding engine padding
- * @param ctx prepare context
+ * @param node row node
+ * @param padding engine padding
+ * @param ctx prepare context
* @param constraints parent constraints
* @return measured outer row size
*/
@@ -352,9 +338,9 @@ public static MeasureResult measureRow(RowNode node,
* Measures a stack by preparing each layer inside the padding-adjusted
* available width and taking the largest child outer box.
*
- * @param node layer stack node
- * @param padding engine padding
- * @param ctx prepare context
+ * @param node layer stack node
+ * @param padding engine padding
+ * @param ctx prepare context
* @param constraints parent constraints
* @return measured outer stack size
*/
@@ -385,8 +371,8 @@ public static MeasureResult measureStack(LayerStackNode node,
/**
* Prepares a table node through the package-local table layout support.
*
- * @param node table node
- * @param ctx prepare context
+ * @param node table node
+ * @param ctx prepare context
* @param constraints parent constraints
* @return prepared table node
*/
@@ -410,7 +396,7 @@ public static PreparedNode prepareTable(TableNode node,
* Splits a prepared table while preserving repeated-header semantics.
*
* @param prepared prepared table node
- * @param request split request
+ * @param request split request
* @return split result
*/
public static PreparedSplitResult splitTable(PreparedNode prepared, SplitRequest request) {
@@ -458,8 +444,8 @@ public static PreparedSplitResult splitTable(PreparedNode
/**
* Emits row fragments for a prepared table.
*
- * @param prepared prepared table node
- * @param ctx fragment-emission context
+ * @param prepared prepared table node
+ * @param ctx fragment-emission context
* @param placement resolved fragment placement
* @return renderer-facing table row fragments
*/
@@ -628,9 +614,9 @@ private static List emitDecorationFragment(Color fillColor,
FragmentPlacement placement) {
boolean hasFill = fillColor != null;
boolean hasStroke = stroke != null
- && stroke.strokeColor() != null
- && stroke.strokeColor().color() != null
- && stroke.width() > 0;
+ && stroke.strokeColor() != null
+ && stroke.strokeColor().color() != null
+ && stroke.width() > 0;
boolean hasSideBorders = sideBorders != null && sideBorders.hasAny();
if ((!hasFill && !hasStroke && !hasSideBorders) || placement.width() <= EPS || placement.height() <= EPS) {
return List.of();
@@ -652,7 +638,7 @@ private static List emitDecorationFragment(Color fillColor,
/**
* Resolved image dimensions excluding node padding.
*
- * @param width resolved width
+ * @param width resolved width
* @param height resolved height
*/
public record ImageDimensions(double width, double height) {
diff --git a/src/main/java/com/demcha/compose/document/layout/NodeRegistry.java b/src/main/java/com/demcha/compose/document/layout/NodeRegistry.java
index 9c435885c..3c6646407 100644
--- a/src/main/java/com/demcha/compose/document/layout/NodeRegistry.java
+++ b/src/main/java/com/demcha/compose/document/layout/NodeRegistry.java
@@ -40,7 +40,7 @@ public NodeRegistry() {
* Registers a semantic node definition.
*
* @param definition node definition
- * @param semantic node type
+ * @param semantic node type
* @return this registry
*/
public NodeRegistry register(NodeDefinition definition) {
@@ -53,7 +53,7 @@ public NodeRegistry register(NodeDefinition definiti
* Resolves the definition responsible for the supplied node instance.
*
* @param node semantic node
- * @param semantic node type
+ * @param semantic node type
* @return matching node definition
*/
@SuppressWarnings("unchecked")
diff --git a/src/main/java/com/demcha/compose/document/layout/PlacedFragment.java b/src/main/java/com/demcha/compose/document/layout/PlacedFragment.java
index 42171c919..e9bd4f504 100644
--- a/src/main/java/com/demcha/compose/document/layout/PlacedFragment.java
+++ b/src/main/java/com/demcha/compose/document/layout/PlacedFragment.java
@@ -6,16 +6,16 @@
/**
* Concrete fragment resolved to a page and absolute page coordinates.
*
- * @param path stable semantic path for the fragment owner
+ * @param path stable semantic path for the fragment owner
* @param fragmentIndex index within the owner's emitted fragments
- * @param pageIndex page that contains this fragment
- * @param x absolute page x coordinate
- * @param y absolute page y coordinate
- * @param width fragment width
- * @param height fragment height
- * @param margin owner margin used for diagnostics
- * @param padding owner padding used for diagnostics
- * @param payload backend-specific fragment payload
+ * @param pageIndex page that contains this fragment
+ * @param x absolute page x coordinate
+ * @param y absolute page y coordinate
+ * @param width fragment width
+ * @param height fragment height
+ * @param margin owner margin used for diagnostics
+ * @param padding owner padding used for diagnostics
+ * @param payload backend-specific fragment payload
*/
public record PlacedFragment(
String path,
@@ -32,7 +32,7 @@ public record PlacedFragment(
/**
* Places a local fragment into absolute page coordinates.
*
- * @param fragment fragment emitted by a node definition
+ * @param fragment fragment emitted by a node definition
* @param placement owner placement metadata
* @return placed fragment
*/
diff --git a/src/main/java/com/demcha/compose/document/layout/PlacedNode.java b/src/main/java/com/demcha/compose/document/layout/PlacedNode.java
index 119fd8fab..cb136ed46 100644
--- a/src/main/java/com/demcha/compose/document/layout/PlacedNode.java
+++ b/src/main/java/com/demcha/compose/document/layout/PlacedNode.java
@@ -6,25 +6,25 @@
/**
* Canonical laid-out semantic node entry in the v2 layout graph.
*
- * @param path stable semantic path for the node
- * @param semanticName author-provided semantic name
- * @param nodeKind canonical node kind
- * @param parentPath parent semantic path, or {@code null} for a root
- * @param childIndex index within the parent child list
- * @param depth depth in the semantic tree
- * @param layer render/layout layer
- * @param computedX computed x coordinate before final placement offsets
- * @param computedY computed y coordinate before final placement offsets
- * @param placementX final placed x coordinate
- * @param placementY final placed y coordinate
- * @param placementWidth final placed width
+ * @param path stable semantic path for the node
+ * @param semanticName author-provided semantic name
+ * @param nodeKind canonical node kind
+ * @param parentPath parent semantic path, or {@code null} for a root
+ * @param childIndex index within the parent child list
+ * @param depth depth in the semantic tree
+ * @param layer render/layout layer
+ * @param computedX computed x coordinate before final placement offsets
+ * @param computedY computed y coordinate before final placement offsets
+ * @param placementX final placed x coordinate
+ * @param placementY final placed y coordinate
+ * @param placementWidth final placed width
* @param placementHeight final placed height
- * @param startPage first page occupied by the node
- * @param endPage last page occupied by the node
- * @param contentWidth measured content width
- * @param contentHeight measured content height
- * @param margin resolved outer margin
- * @param padding resolved inner padding
+ * @param startPage first page occupied by the node
+ * @param endPage last page occupied by the node
+ * @param contentWidth measured content width
+ * @param contentHeight measured content height
+ * @param margin resolved outer margin
+ * @param padding resolved inner padding
*/
public record PlacedNode(
String path,
diff --git a/src/main/java/com/demcha/compose/document/layout/PrepareContext.java b/src/main/java/com/demcha/compose/document/layout/PrepareContext.java
index b3d091c22..f95cb043b 100644
--- a/src/main/java/com/demcha/compose/document/layout/PrepareContext.java
+++ b/src/main/java/com/demcha/compose/document/layout/PrepareContext.java
@@ -1,9 +1,8 @@
package com.demcha.compose.document.layout;
import com.demcha.compose.document.node.DocumentNode;
-
-import com.demcha.compose.font.FontLibrary;
import com.demcha.compose.engine.measurement.TextMeasurementSystem;
+import com.demcha.compose.font.FontLibrary;
/**
* Shared prepare context passed to node definitions.
@@ -12,9 +11,9 @@ public interface PrepareContext {
/**
* Prepares a semantic node for later layout under the supplied constraints.
*
- * @param node semantic node
+ * @param node semantic node
* @param constraints available layout constraints
- * @param semantic node type
+ * @param semantic node type
* @return prepared node with reusable measurement/layout payload
*/
PreparedNode prepare(E node, BoxConstraints constraints);
diff --git a/src/main/java/com/demcha/compose/document/layout/PreparedNode.java b/src/main/java/com/demcha/compose/document/layout/PreparedNode.java
index 371406127..3f1446f87 100644
--- a/src/main/java/com/demcha/compose/document/layout/PreparedNode.java
+++ b/src/main/java/com/demcha/compose/document/layout/PreparedNode.java
@@ -8,10 +8,10 @@
/**
* Prepared semantic node with reusable measure and layout payload.
*
- * @param semantic node type
- * @param node source semantic node
- * @param measureResult measured node size
- * @param preparedLayout node-specific reusable layout payload
+ * @param semantic node type
+ * @param node source semantic node
+ * @param measureResult measured node size
+ * @param preparedLayout node-specific reusable layout payload
* @param compositeLayout optional composite child-layout metadata
*/
public record PreparedNode(
@@ -20,10 +20,6 @@ public record PreparedNode(
PreparedNodeLayout preparedLayout,
Optional compositeLayout
) {
- private enum EmptyPreparedLayout implements PreparedNodeLayout {
- INSTANCE
- }
-
/**
* Normalizes optional layout payloads and validates required node state.
*/
@@ -37,9 +33,9 @@ private enum EmptyPreparedLayout implements PreparedNodeLayout {
/**
* Creates a prepared leaf node without a custom layout payload.
*
- * @param node semantic node
+ * @param node semantic node
* @param measureResult measured node size
- * @param semantic node type
+ * @param semantic node type
* @return prepared leaf node
*/
public static PreparedNode leaf(E node, MeasureResult measureResult) {
@@ -49,10 +45,10 @@ public static PreparedNode leaf(E node, MeasureResul
/**
* Creates a prepared leaf node with a reusable layout payload.
*
- * @param node semantic node
- * @param measureResult measured node size
+ * @param node semantic node
+ * @param measureResult measured node size
* @param preparedLayout node-specific layout payload
- * @param semantic node type
+ * @param semantic node type
* @return prepared leaf node
*/
public static PreparedNode leaf(E node,
@@ -64,10 +60,10 @@ public static PreparedNode leaf(E node,
/**
* Creates a prepared composite node without a custom layout payload.
*
- * @param node semantic node
- * @param measureResult measured node size
+ * @param node semantic node
+ * @param measureResult measured node size
* @param compositeLayout composite child layout metadata
- * @param semantic node type
+ * @param semantic node type
* @return prepared composite node
*/
public static PreparedNode composite(E node,
@@ -79,11 +75,11 @@ public static PreparedNode composite(E node,
/**
* Creates a prepared composite node with a reusable layout payload.
*
- * @param node semantic node
- * @param measureResult measured node size
- * @param preparedLayout node-specific layout payload
+ * @param node semantic node
+ * @param measureResult measured node size
+ * @param preparedLayout node-specific layout payload
* @param compositeLayout composite child layout metadata
- * @param semantic node type
+ * @param semantic node type
* @return prepared composite node
*/
public static PreparedNode composite(E node,
@@ -116,17 +112,21 @@ public CompositeLayoutSpec requireCompositeLayout() {
* Returns the prepared layout payload as a concrete type.
*
* @param layoutType required layout payload type
- * @param layout payload type
+ * @param layout payload type
* @return typed prepared layout payload
*/
public T requirePreparedLayout(Class layoutType) {
Objects.requireNonNull(layoutType, "layoutType");
if (!layoutType.isInstance(preparedLayout)) {
throw new IllegalStateException("Prepared node '" + node.nodeKind()
- + "' does not carry layout payload " + layoutType.getSimpleName() + ".");
+ + "' does not carry layout payload " + layoutType.getSimpleName() + ".");
}
return layoutType.cast(preparedLayout);
}
+
+ private enum EmptyPreparedLayout implements PreparedNodeLayout {
+ INSTANCE
+ }
}
diff --git a/src/main/java/com/demcha/compose/document/layout/PreparedSplitResult.java b/src/main/java/com/demcha/compose/document/layout/PreparedSplitResult.java
index c1b2d1e4a..1acbfda49 100644
--- a/src/main/java/com/demcha/compose/document/layout/PreparedSplitResult.java
+++ b/src/main/java/com/demcha/compose/document/layout/PreparedSplitResult.java
@@ -5,7 +5,7 @@
/**
* Result of splitting a prepared semantic node into head/tail pieces.
*
- * @param semantic node type
+ * @param semantic node type
* @param head first prepared node fragment, or the whole node when unsplit
* @param tail remaining prepared node fragment, or {@code null} when unsplit
*/
@@ -14,7 +14,7 @@ public record PreparedSplitResult(PreparedNode head,
* Creates an unsplit result where the original node remains whole.
*
* @param node prepared node
- * @param semantic node type
+ * @param semantic node type
* @return whole-node split result
*/
public static PreparedSplitResult whole(PreparedNode node) {
diff --git a/src/main/java/com/demcha/compose/document/layout/RowSlots.java b/src/main/java/com/demcha/compose/document/layout/RowSlots.java
index 8b11eb20d..32cfb3b93 100644
--- a/src/main/java/com/demcha/compose/document/layout/RowSlots.java
+++ b/src/main/java/com/demcha/compose/document/layout/RowSlots.java
@@ -29,7 +29,7 @@ private RowSlots() {
* children count. Callers must skip this check when {@code weights}
* is null or empty — the even-split fallback applies there instead.
*
- * @param weights non-null, non-empty weights list
+ * @param weights non-null, non-empty weights list
* @param childCount number of row children
* @throws IllegalArgumentException if {@code weights.size() != childCount}
*/
@@ -37,8 +37,8 @@ static void validateWeightsMatchChildren(List weights, int childCount) {
if (weights.size() != childCount) {
throw new IllegalArgumentException(
"Row weights size (" + weights.size() + ") must match children size ("
- + childCount + "). Pass exactly " + childCount
- + " weight(s) or leave weights empty for an even split.");
+ + childCount + "). Pass exactly " + childCount
+ + " weight(s) or leave weights empty for an even split.");
}
}
}
diff --git a/src/main/java/com/demcha/compose/document/layout/SplitRequest.java b/src/main/java/com/demcha/compose/document/layout/SplitRequest.java
index 6b367f6a1..8cbce11b3 100644
--- a/src/main/java/com/demcha/compose/document/layout/SplitRequest.java
+++ b/src/main/java/com/demcha/compose/document/layout/SplitRequest.java
@@ -3,10 +3,10 @@
/**
* Split request for a splittable semantic node.
*
- * @param constraints available layout space for the split
+ * @param constraints available layout space for the split
* @param remainingHeight remaining height on the current page
* @param pageInnerHeight full inner page height for tail preparation
- * @param context active prepare context used by split logic
+ * @param context active prepare context used by split logic
*/
public record SplitRequest(
BoxConstraints constraints,
diff --git a/src/main/java/com/demcha/compose/document/layout/SplitResult.java b/src/main/java/com/demcha/compose/document/layout/SplitResult.java
index 11c03171b..363968190 100644
--- a/src/main/java/com/demcha/compose/document/layout/SplitResult.java
+++ b/src/main/java/com/demcha/compose/document/layout/SplitResult.java
@@ -5,7 +5,7 @@
/**
* Result of splitting a semantic node into head/tail pieces.
*
- * @param semantic node type
+ * @param semantic node type
* @param head first semantic node fragment, or the whole node when unsplit
* @param tail remaining semantic node fragment, or {@code null} when unsplit
*/
@@ -14,7 +14,7 @@ public record SplitResult(E head, E tail) {
* Creates an unsplit result where the original node remains whole.
*
* @param node semantic node
- * @param semantic node type
+ * @param semantic node type
* @return whole-node split result
*/
public static SplitResult whole(E node) {
diff --git a/src/main/java/com/demcha/compose/document/layout/TableLayoutSupport.java b/src/main/java/com/demcha/compose/document/layout/TableLayoutSupport.java
index 21d525d35..d830d47ad 100644
--- a/src/main/java/com/demcha/compose/document/layout/TableLayoutSupport.java
+++ b/src/main/java/com/demcha/compose/document/layout/TableLayoutSupport.java
@@ -12,17 +12,9 @@
import com.demcha.compose.engine.components.style.Padding;
import com.demcha.compose.engine.measurement.TextMeasurementSystem;
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import static com.demcha.compose.document.layout.DocumentNodeAdapters.toTableCell;
-import static com.demcha.compose.document.layout.DocumentNodeAdapters.toTableColumns;
-import static com.demcha.compose.document.layout.DocumentNodeAdapters.toTableStyle;
-import static com.demcha.compose.document.layout.DocumentNodeAdapters.toTableStyles;
+import java.util.*;
+
+import static com.demcha.compose.document.layout.DocumentNodeAdapters.*;
/**
* Package-private support helpers for {@code TableNode} layout.
@@ -38,73 +30,6 @@ final class TableLayoutSupport {
private TableLayoutSupport() {
}
- /**
- * Prepared layout payload attached to {@code TableNode} prepared nodes.
- *
- *
{@code preparedContents} carries the prepared sub-tree for any
- * {@code DocumentTableCell} authored via {@link DocumentTableCell#node(DocumentNode)};
- * keyed by the cell's logical {@code (startRow, startColumn)} and
- * empty for tables that contain only plain-text cells.
- */
- record PreparedTableLayout(
- ResolvedTableLayout resolvedLayout,
- boolean emitBookmark,
- Map> preparedContents
- ) implements PreparedNodeLayout {
- PreparedTableLayout {
- preparedContents = preparedContents == null ? Map.of() : Map.copyOf(preparedContents);
- }
-
- /**
- * Back-compat 2-arg constructor for callers that don't carry
- * composed cell content. Defaults {@code preparedContents} to
- * an empty map.
- */
- PreparedTableLayout(ResolvedTableLayout resolvedLayout, boolean emitBookmark) {
- this(resolvedLayout, emitBookmark, Map.of());
- }
- }
-
- /**
- * Logical (row, column) coordinate identifying a cell's starting
- * position. Used as the key for the {@code preparedContents} map
- * on {@link PreparedTableLayout}.
- */
- record CellKey(int row, int column) {
- }
-
- /**
- * Resolved table layout (column widths, row heights, resolved cells).
- */
- record ResolvedTableLayout(
- List columnWidths,
- List rowHeights,
- List> rows,
- double naturalWidth,
- double finalWidth,
- double totalHeight
- ) {
- }
-
- /**
- * Logical cell: a single user-authored cell after the cell-grid pre-pass
- * has resolved its starting position and colSpan/rowSpan extent. A
- * spanning cell appears once at its starting (row, column); the
- * positions it occupies in subsequent rows are tracked by the
- * occupancy grid built in {@link #buildLogicalRows(TableNode, int)} and
- * are skipped when iterating later source rows. {@code source} is the
- * original public {@link DocumentTableCell}, retained so the layout
- * can detect composed-content cells via
- * {@link DocumentTableCell#hasComposedContent()}. {@code sanitizedLines} is
- * the cell's text with control characters cleaned, computed once here and
- * reused by the width, height and resolve passes instead of re-sanitizing the
- * content three times.
- */
- private record LogicalCell(int startRow, int startColumn, int colSpan, int rowSpan,
- TableCellContent content, DocumentTableCell source,
- List sanitizedLines) {
- }
-
/**
* Resolves the table layout. Composed-content cells (those authored
* via {@link DocumentTableCell#node(DocumentNode)}) require a
@@ -114,9 +39,9 @@ private record LogicalCell(int startRow, int startColumn, int colSpan, int rowSp
* will still throw if it encounters a composed cell).
*/
static ResolvedTableLayoutWithContents resolveTableLayout(TableNode node,
- PrepareContext prepareContext,
- TextMeasurementSystem measurement,
- double availableWidth) {
+ PrepareContext prepareContext,
+ TextMeasurementSystem measurement,
+ double availableWidth) {
validateRowsExist(node);
int columnCount = resolveColumnCount(node);
List> logicalRows = buildLogicalRows(node, columnCount);
@@ -130,7 +55,7 @@ static ResolvedTableLayoutWithContents resolveTableLayout(TableNode node,
double innerAvailableWidth = Math.max(0.0, availableWidth - node.padding().horizontal());
if (finalWidth > innerAvailableWidth + EPS) {
throw new IllegalStateException("Table '" + displayName(node) + "' width " + finalWidth
- + " exceeds available width " + innerAvailableWidth + ".");
+ + " exceeds available width " + innerAvailableWidth + ".");
}
// Prepare composed cell content (cells authored via
@@ -229,19 +154,6 @@ static ResolvedTableLayoutWithContents resolveTableLayout(TableNode node,
return new ResolvedTableLayoutWithContents(resolved, preparedContents);
}
- /**
- * Bundles the resolved table layout with the prepared composed-cell
- * content map so {@link com.demcha.compose.document.layout.NodeDefinitionSupport#prepareTable}
- * can attach the map to the {@link PreparedTableLayout}.
- */
- record ResolvedTableLayoutWithContents(
- ResolvedTableLayout layout,
- Map> preparedContents) {
- ResolvedTableLayoutWithContents {
- preparedContents = preparedContents == null ? Map.of() : Map.copyOf(preparedContents);
- }
- }
-
/**
* Walks every logical cell, prepares composed children
* ({@link DocumentTableCell#hasComposedContent()} == true) against
@@ -266,7 +178,7 @@ private static Map> prepareComposedCellContents(
if (prepareContext == null) {
throw new IllegalStateException(
"Table '" + displayName(node) + "' has a composed cell at ("
- + rowIndex + ", " + logical.startColumn() + ") but no PrepareContext was supplied.");
+ + rowIndex + ", " + logical.startColumn() + ") but no PrepareContext was supplied.");
}
double cellOuterWidth = sumRange(finalWidths, logical.startColumn(),
logical.startColumn() + logical.colSpan());
@@ -297,7 +209,7 @@ private static double naturalCellHeight(LogicalCell logical,
if (prepared == null) {
throw new IllegalStateException(
"Composed cell at (" + logical.startRow() + ", " + logical.startColumn()
- + ") was not prepared.");
+ + ") was not prepared.");
}
Padding padding = style.padding() == null ? Padding.zero() : style.padding();
return prepared.measureResult().height() + padding.vertical();
@@ -497,28 +409,28 @@ private static List> buildLogicalRows(TableNode node, int colu
}
if (sourceIdx >= source.size()) {
throw new IllegalStateException("Row " + rowIndex
- + " is missing a cell for column " + col
- + " (table has " + columnCount + " columns; source row provides "
- + source.size() + " cells, prior rowSpan covers some columns).");
+ + " is missing a cell for column " + col
+ + " (table has " + columnCount + " columns; source row provides "
+ + source.size() + " cells, prior rowSpan covers some columns).");
}
DocumentTableCell cell = source.get(sourceIdx++);
if (col + cell.colSpan() > columnCount) {
throw new IllegalStateException("Cell at row " + rowIndex
- + " column " + col + " has colSpan " + cell.colSpan()
- + " but only " + (columnCount - col) + " columns remain.");
+ + " column " + col + " has colSpan " + cell.colSpan()
+ + " but only " + (columnCount - col) + " columns remain.");
}
if (rowIndex + cell.rowSpan() > rowCount) {
throw new IllegalStateException("Cell at row " + rowIndex
- + " column " + col + " has rowSpan " + cell.rowSpan()
- + " but only " + (rowCount - rowIndex) + " rows remain.");
+ + " column " + col + " has rowSpan " + cell.rowSpan()
+ + " but only " + (rowCount - rowIndex) + " rows remain.");
}
for (int r = rowIndex; r < rowIndex + cell.rowSpan(); r++) {
for (int c = col; c < col + cell.colSpan(); c++) {
if (occupied[r][c]) {
throw new IllegalStateException("Cell at row " + rowIndex
- + " column " + col + " (colSpan=" + cell.colSpan()
- + ", rowSpan=" + cell.rowSpan()
- + ") overlaps an already-spanned position (" + r + ", " + c + ").");
+ + " column " + col + " (colSpan=" + cell.colSpan()
+ + ", rowSpan=" + cell.rowSpan()
+ + ") overlaps an already-spanned position (" + r + ", " + c + ").");
}
occupied[r][c] = true;
}
@@ -530,9 +442,9 @@ private static List> buildLogicalRows(TableNode node, int colu
}
if (sourceIdx < source.size()) {
throw new IllegalStateException("Row " + rowIndex
- + " has " + (source.size() - sourceIdx) + " extra source cell(s) "
- + "after the grid was already filled — column slots are accounted for "
- + "by colSpan plus rowSpan from earlier rows.");
+ + " has " + (source.size() - sourceIdx) + " extra source cell(s) "
+ + "after the grid was already filled — column slots are accounted for "
+ + "by colSpan plus rowSpan from earlier rows.");
}
result.add(List.copyOf(logical));
}
@@ -595,7 +507,7 @@ private static double[] resolveNaturalColumnWidths(TableNode node,
if (spec.isFixed()) {
if (spec.requiredFixedWidth() + EPS < singleCellRequired[columnIndex]) {
throw new IllegalStateException("Fixed column " + columnIndex + " width " + spec.requiredFixedWidth()
- + " is smaller than required natural width " + singleCellRequired[columnIndex] + ".");
+ + " is smaller than required natural width " + singleCellRequired[columnIndex] + ".");
}
widths[columnIndex] = spec.requiredFixedWidth();
} else {
@@ -637,8 +549,8 @@ private static void distributeDeficit(double[] widths,
}
if (autoColumns.isEmpty()) {
throw new IllegalStateException("Spanned cell at row " + rowIndex + " over " + colSpan
- + " fixed columns starting at " + startCol + " requires extra width " + deficit
- + " but all spanned columns are fixed.");
+ + " fixed columns starting at " + startCol + " requires extra width " + deficit
+ + " but all spanned columns are fixed.");
}
double share = deficit / autoColumns.size();
for (int col : autoColumns) {
@@ -656,7 +568,7 @@ private static double[] resolveFinalColumnWidths(TableNode node,
}
if (node.width() + EPS < naturalWidth) {
throw new IllegalStateException("Requested table width " + node.width()
- + " is smaller than natural width " + naturalWidth + ".");
+ + " is smaller than natural width " + naturalWidth + ".");
}
double extra = node.width() - naturalWidth;
@@ -700,8 +612,8 @@ private static double cellNaturalHeight(List sanitizedLines,
Padding padding = style.padding() == null ? Padding.zero() : style.padding();
int lineCount = Math.max(1, sanitizedLines.size());
return (lineCount * measurement.lineHeight(style.textStyle()))
- + ((lineCount - 1) * tableCellLineSpacing(style))
- + padding.vertical();
+ + ((lineCount - 1) * tableCellLineSpacing(style))
+ + padding.vertical();
}
private static double tableCellLineSpacing(TableCellLayoutStyle style) {
@@ -738,11 +650,6 @@ private static void validateRowsExist(TableNode node) {
}
}
- // Note: row colSpan-sum validation is no longer a separate pass — the
- // occupancy-grid algorithm in buildLogicalRows enforces both
- // colSpan/rowSpan bounds and per-row coverage with precise diagnostics
- // (missing cell, extra cell, overlap, out-of-bounds span).
-
private static EnumSet borderSides(TableCellLayoutStyle[][] stylesGrid,
int rowIndex,
int startCol,
@@ -808,6 +715,11 @@ private static boolean ownsTopBoundary(TableCellLayoutStyle[][] stylesGrid,
return true;
}
+ // Note: row colSpan-sum validation is no longer a separate pass — the
+ // occupancy-grid algorithm in buildLogicalRows enforces both
+ // colSpan/rowSpan bounds and per-row coverage with precise diagnostics
+ // (missing cell, extra cell, overlap, out-of-bounds span).
+
private static boolean ownsLeftBoundary(TableCellLayoutStyle[][] stylesGrid,
int rowIndex,
int startCol) {
@@ -867,4 +779,84 @@ private static String displayName(DocumentNode node) {
}
return node.name();
}
+
+ /**
+ * Prepared layout payload attached to {@code TableNode} prepared nodes.
+ *
+ *
{@code preparedContents} carries the prepared sub-tree for any
+ * {@code DocumentTableCell} authored via {@link DocumentTableCell#node(DocumentNode)};
+ * keyed by the cell's logical {@code (startRow, startColumn)} and
+ * empty for tables that contain only plain-text cells.
+ */
+ record PreparedTableLayout(
+ ResolvedTableLayout resolvedLayout,
+ boolean emitBookmark,
+ Map> preparedContents
+ ) implements PreparedNodeLayout {
+ PreparedTableLayout {
+ preparedContents = preparedContents == null ? Map.of() : Map.copyOf(preparedContents);
+ }
+
+ /**
+ * Back-compat 2-arg constructor for callers that don't carry
+ * composed cell content. Defaults {@code preparedContents} to
+ * an empty map.
+ */
+ PreparedTableLayout(ResolvedTableLayout resolvedLayout, boolean emitBookmark) {
+ this(resolvedLayout, emitBookmark, Map.of());
+ }
+ }
+
+ /**
+ * Logical (row, column) coordinate identifying a cell's starting
+ * position. Used as the key for the {@code preparedContents} map
+ * on {@link PreparedTableLayout}.
+ */
+ record CellKey(int row, int column) {
+ }
+
+ /**
+ * Resolved table layout (column widths, row heights, resolved cells).
+ */
+ record ResolvedTableLayout(
+ List columnWidths,
+ List rowHeights,
+ List> rows,
+ double naturalWidth,
+ double finalWidth,
+ double totalHeight
+ ) {
+ }
+
+ /**
+ * Logical cell: a single user-authored cell after the cell-grid pre-pass
+ * has resolved its starting position and colSpan/rowSpan extent. A
+ * spanning cell appears once at its starting (row, column); the
+ * positions it occupies in subsequent rows are tracked by the
+ * occupancy grid built in {@link #buildLogicalRows(TableNode, int)} and
+ * are skipped when iterating later source rows. {@code source} is the
+ * original public {@link DocumentTableCell}, retained so the layout
+ * can detect composed-content cells via
+ * {@link DocumentTableCell#hasComposedContent()}. {@code sanitizedLines} is
+ * the cell's text with control characters cleaned, computed once here and
+ * reused by the width, height and resolve passes instead of re-sanitizing the
+ * content three times.
+ */
+ private record LogicalCell(int startRow, int startColumn, int colSpan, int rowSpan,
+ TableCellContent content, DocumentTableCell source,
+ List sanitizedLines) {
+ }
+
+ /**
+ * Bundles the resolved table layout with the prepared composed-cell
+ * content map so {@link com.demcha.compose.document.layout.NodeDefinitionSupport#prepareTable}
+ * can attach the map to the {@link PreparedTableLayout}.
+ */
+ record ResolvedTableLayoutWithContents(
+ ResolvedTableLayout layout,
+ Map> preparedContents) {
+ ResolvedTableLayoutWithContents {
+ preparedContents = preparedContents == null ? Map.of() : Map.copyOf(preparedContents);
+ }
+ }
}
diff --git a/src/main/java/com/demcha/compose/document/layout/TextFlowSupport.java b/src/main/java/com/demcha/compose/document/layout/TextFlowSupport.java
index 7155f88f7..8ec5aa7a5 100644
--- a/src/main/java/com/demcha/compose/document/layout/TextFlowSupport.java
+++ b/src/main/java/com/demcha/compose/document/layout/TextFlowSupport.java
@@ -1,28 +1,7 @@
package com.demcha.compose.document.layout;
-import com.demcha.compose.document.layout.payloads.ParagraphShapeSpan;
-import com.demcha.compose.document.layout.payloads.ResolvedShapeLayer;
-import com.demcha.compose.document.layout.payloads.ParagraphFragmentPayload;
-import com.demcha.compose.document.layout.payloads.ParagraphImageSpan;
-import com.demcha.compose.document.layout.payloads.ParagraphLine;
-import com.demcha.compose.document.layout.payloads.ParagraphSpan;
-import com.demcha.compose.document.layout.payloads.ParagraphTextSpan;
-import com.demcha.compose.document.layout.payloads.PreparedListItemLayout;
-import com.demcha.compose.document.layout.payloads.PreparedListLayout;
-import com.demcha.compose.document.layout.payloads.PreparedParagraphLayout;
-import com.demcha.compose.document.node.DocumentLinkOptions;
-import com.demcha.compose.document.node.InlineShapeRun;
-import com.demcha.compose.document.node.ShapeLayer;
-import com.demcha.compose.document.node.InlineImageAlignment;
-import com.demcha.compose.document.node.InlineImageRun;
-import com.demcha.compose.document.node.InlineRun;
-import com.demcha.compose.document.node.InlineTextRun;
-import com.demcha.compose.document.node.ListItem;
-import com.demcha.compose.document.node.ListMarker;
-import com.demcha.compose.document.node.ListNode;
-import com.demcha.compose.document.node.ParagraphNode;
-import com.demcha.compose.document.node.TextAlign;
-import com.demcha.compose.document.node.TextVerticalAlign;
+import com.demcha.compose.document.layout.payloads.*;
+import com.demcha.compose.document.node.*;
import com.demcha.compose.document.style.DocumentInsets;
import com.demcha.compose.document.style.DocumentTextAutoSize;
import com.demcha.compose.document.style.DocumentTextIndent;
@@ -40,11 +19,7 @@
import java.util.List;
import java.util.Objects;
-import static com.demcha.compose.document.layout.DocumentNodeAdapters.toImageData;
-import static com.demcha.compose.document.layout.DocumentNodeAdapters.toIndentStrategy;
-import static com.demcha.compose.document.layout.DocumentNodeAdapters.toPadding;
-import static com.demcha.compose.document.layout.DocumentNodeAdapters.toStroke;
-import static com.demcha.compose.document.layout.DocumentNodeAdapters.toTextStyle;
+import static com.demcha.compose.document.layout.DocumentNodeAdapters.*;
import static com.demcha.compose.document.layout.NodeDefinitionSupport.EPS;
/**
@@ -58,19 +33,29 @@
* @author Artem Demchyshyn
*/
public final class TextFlowSupport {
- private TextFlowSupport() {
- }
+ /**
+ * Indent unit added per nesting depth in a nested list. Two
+ * non-breaking spaces visually match two regular spaces but are
+ * preserved by paragraph wrapping (which strips leading
+ * {@link Character#isWhitespace whitespace} from the first token
+ * of each line). Switching to NBSP keeps depth indentation intact
+ * without rewriting the wrap pipeline.
+ */
+ private static final String NESTED_LIST_INDENT_UNIT = " ";
// ------------------------------------------------------------------
// Paragraph entry points
// ------------------------------------------------------------------
+ private TextFlowSupport() {
+ }
+
/**
* Measures a paragraph node and wraps it into a prepared leaf carrying its
* visual line layout.
*
- * @param node paragraph node to prepare
- * @param ctx prepare-phase context
+ * @param node paragraph node to prepare
+ * @param ctx prepare-phase context
* @param constraints box constraints for measurement
* @return prepared paragraph node with its line layout
*/
@@ -94,7 +79,7 @@ public static PreparedNode prepareParagraph(ParagraphNode node,
* remaining height.
*
* @param prepared prepared paragraph node
- * @param request split request carrying the remaining height
+ * @param request split request carrying the remaining height
* @return the head/tail split result
*/
public static PreparedSplitResult splitParagraph(PreparedNode prepared,
@@ -120,10 +105,14 @@ public static PreparedSplitResult splitParagraph(PreparedNode(head, tail);
}
+ // ------------------------------------------------------------------
+ // List entry points
+ // ------------------------------------------------------------------
+
/**
* Emits the render fragment for a prepared paragraph.
*
- * @param prepared prepared paragraph node
+ * @param prepared prepared paragraph node
* @param placement resolved fragment placement
* @return renderer-facing paragraph fragments
*/
@@ -153,16 +142,12 @@ public static List emitParagraphFragments(PreparedNode prepareList(ListNode node,
layout);
}
- /**
- * Indent unit added per nesting depth in a nested list. Two
- * non-breaking spaces visually match two regular spaces but are
- * preserved by paragraph wrapping (which strips leading
- * {@link Character#isWhitespace whitespace} from the first token
- * of each line). Switching to NBSP keeps depth indentation intact
- * without rewriting the wrap pipeline.
- */
- private static final String NESTED_LIST_INDENT_UNIT = " ";
-
/**
* Synthesizes a flat {@link ListNode} from a nested one by walking
* the tree depth-first and prefixing each label with
@@ -254,7 +229,7 @@ private static ListMarker defaultMarkerForDepth(int depth) {
* splitting the first item's lines when no whole item fits.
*
* @param prepared prepared list node
- * @param request split request carrying the remaining height
+ * @param request split request carrying the remaining height
* @return the head/tail split result
*/
public static PreparedSplitResult splitList(PreparedNode prepared,
@@ -318,7 +293,7 @@ public static PreparedSplitResult splitList(PreparedNode pre
* Emits one paragraph fragment per list item so items paginate
* independently.
*
- * @param prepared prepared list node
+ * @param prepared prepared list node
* @param placement resolved fragment placement
* @return renderer-facing per-item fragments
*/
@@ -506,7 +481,7 @@ private static PreparedListItemLayout sliceListItem(PreparedListItemLayout item,
.max()
.orElse(0.0);
double totalHeight = source.lineHeight() * lines.size()
- + Math.max(0, lines.size() - 1) * source.lineGap();
+ + Math.max(0, lines.size() - 1) * source.lineGap();
PreparedParagraphLayout layout = new PreparedParagraphLayout(
logicalLines,
lines,
@@ -641,9 +616,9 @@ private static boolean paragraphFitsSingleLine(ParagraphNode node,
}
private static PreparedParagraphLayout prepareParagraphLayout(ParagraphNode node,
- double innerWidth,
- TextMeasurementSystem measurement,
- boolean markdownEnabled) {
+ double innerWidth,
+ TextMeasurementSystem measurement,
+ boolean markdownEnabled) {
List logicalLines = sanitizeLogicalLines(node.text());
boolean useMarkdownLayout = markdownEnabled && logicalLines.stream().anyMatch(TextFlowSupport::containsMarkdownSyntax);
TextStyle textStyle = node.autoSize() != null
@@ -653,33 +628,33 @@ private static PreparedParagraphLayout prepareParagraphLayout(ParagraphNode node
TextMeasurementSystem.LineMetrics lineMetrics = measurement.lineMetrics(textStyle);
List visualLines = !node.inlineRuns().isEmpty()
? wrapInlineParagraph(
- node.inlineRuns(),
- textStyle,
- lineMetrics,
- Math.max(0.0, innerWidth),
- node.bulletOffset(),
- indentStrategy,
- measurement)
+ node.inlineRuns(),
+ textStyle,
+ lineMetrics,
+ Math.max(0.0, innerWidth),
+ node.bulletOffset(),
+ indentStrategy,
+ measurement)
: useMarkdownLayout
- ? wrapMarkdownParagraph(
+ ? wrapMarkdownParagraph(
+ logicalLines,
+ textStyle,
+ lineMetrics,
+ Math.max(0.0, innerWidth),
+ node.bulletOffset(),
+ indentStrategy,
+ measurement)
+ : toParagraphLines(
+ wrapParagraph(
logicalLines,
textStyle,
- lineMetrics,
Math.max(0.0, innerWidth),
node.bulletOffset(),
indentStrategy,
- measurement)
- : toParagraphLines(
- wrapParagraph(
- logicalLines,
- textStyle,
- Math.max(0.0, innerWidth),
- node.bulletOffset(),
- indentStrategy,
- measurement),
- textStyle,
- lineMetrics,
- measurement);
+ measurement),
+ textStyle,
+ lineMetrics,
+ measurement);
if (visualLines.isEmpty()) {
visualLines = List.of(emptyParagraphLine(lineMetrics));
}
@@ -1046,8 +1021,8 @@ private static boolean containsMarkdownSyntax(String value) {
return false;
}
return value.indexOf('*') >= 0
- || value.indexOf('_') >= 0
- || value.indexOf('`') >= 0;
+ || value.indexOf('_') >= 0
+ || value.indexOf('`') >= 0;
}
private static List wrapMarkdownParagraph(List logicalLines,
@@ -1418,7 +1393,7 @@ private static List trimTrailingWhitespaceTokens(List lines, double lineGap, do
// Inline tokens + indent spec
// ------------------------------------------------------------------
+ private sealed interface InlineLayoutToken permits InlineTextToken, InlineImageToken, InlineShapeToken {
+ double width();
+ }
+
private record ParagraphIndentSpec(String firstLinePrefix, String continuationPrefix) {
private static ParagraphIndentSpec from(String bulletOffset,
- TextStyle style,
- TextMeasurementSystem measurement) {
+ TextStyle style,
+ TextMeasurementSystem measurement) {
String raw = bulletOffset == null ? "" : bulletOffset;
boolean hasVisibleChars = raw.chars().anyMatch(ch -> !Character.isWhitespace(ch));
if (hasVisibleChars) {
@@ -1613,10 +1592,6 @@ private static ParagraphIndentSpec from(String bulletOffset,
}
}
- private sealed interface InlineLayoutToken permits InlineTextToken, InlineImageToken, InlineShapeToken {
- double width();
- }
-
private record InlineTextToken(
String text,
TextStyle textStyle,
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/BarcodeDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/BarcodeDefinition.java
index 7f87e9949..899f6e98e 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/BarcodeDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/BarcodeDefinition.java
@@ -1,22 +1,12 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.MeasureResult;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.layout.payloads.BarcodeFragmentPayload;
import com.demcha.compose.document.node.BarcodeNode;
import java.util.List;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.EPS;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.toBarcodeData;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.wrapAtomicWithTransform;
+import static com.demcha.compose.document.layout.NodeDefinitionSupport.*;
/**
* Layout definition for {@link BarcodeNode}: a fixed-size atomic barcode or QR
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/CanvasLayerDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/CanvasLayerDefinition.java
index 697a451f4..8fad5b198 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/CanvasLayerDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/CanvasLayerDefinition.java
@@ -1,15 +1,6 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.CompositeLayoutSpec;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.MeasureResult;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.layout.payloads.PreparedStackLayout;
import com.demcha.compose.document.node.CanvasChild;
import com.demcha.compose.document.node.CanvasLayerNode;
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/ChartDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/ChartDefinition.java
index e731d4342..4049258f0 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/ChartDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/ChartDefinition.java
@@ -1,22 +1,7 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.chart.ChartDefaults;
-import com.demcha.compose.document.chart.ChartLayoutResolver;
-import com.demcha.compose.document.chart.ChartPrimitive;
-import com.demcha.compose.document.chart.ChartSpec;
-import com.demcha.compose.document.chart.ChartStyle;
-import com.demcha.compose.document.chart.ChartTheme;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.ChartTextMetricsSupport;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.MeasureResult;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
-import com.demcha.compose.document.layout.PreparedNodeLayout;
+import com.demcha.compose.document.chart.*;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.node.ChartNode;
import com.demcha.compose.document.node.DocumentNode;
import com.demcha.compose.engine.components.style.Margin;
@@ -59,7 +44,9 @@
*/
public final class ChartDefinition implements NodeDefinition {
- /** Creates the chart layout definition. */
+ /**
+ * Creates the chart layout definition.
+ */
public ChartDefinition() {
}
@@ -158,7 +145,7 @@ public record PreparedChartLayout(List primitives) implements
/**
* One prepared primitive child plus its resolver-assigned placement.
*
- * @param prepared prepared child node
+ * @param prepared prepared child node
* @param primitive the resolver primitive (node + bottom-up box)
*/
public record PreparedPrimitive(PreparedNode prepared, ChartPrimitive primitive) {
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/ContainerDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/ContainerDefinition.java
index b77ea5c7e..1d9c218d2 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/ContainerDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/ContainerDefinition.java
@@ -1,24 +1,12 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.CompositeLayoutSpec;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.node.ContainerNode;
import com.demcha.compose.document.node.DocumentNode;
import java.util.List;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.emitDecorationFragment;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.measureComposite;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.toPadding;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.toSideBorders;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.toStroke;
+import static com.demcha.compose.document.layout.NodeDefinitionSupport.*;
/**
* Layout definition for {@link ContainerNode}: a vertical atomic composite
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/EllipseDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/EllipseDefinition.java
index 568335c40..4e86a11bd 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/EllipseDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/EllipseDefinition.java
@@ -1,22 +1,12 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.MeasureResult;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.layout.payloads.EllipseFragmentPayload;
import com.demcha.compose.document.node.EllipseNode;
import java.util.List;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.EPS;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.toStroke;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.wrapAtomicWithTransform;
+import static com.demcha.compose.document.layout.NodeDefinitionSupport.*;
/**
* Layout definition for {@link EllipseNode}: a fixed-size atomic ellipse or
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/ImageDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/ImageDefinition.java
index 07097565d..e13502f78 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/ImageDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/ImageDefinition.java
@@ -1,24 +1,12 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.MeasureResult;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.NodeDefinitionSupport.ImageDimensions;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.layout.payloads.ImageFragmentPayload;
import com.demcha.compose.document.node.ImageNode;
import java.util.List;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.EPS;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.resolveImageDimensions;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.toImageData;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.wrapAtomicWithTransform;
+import static com.demcha.compose.document.layout.NodeDefinitionSupport.*;
/**
* Layout definition for {@link ImageNode}: resolves image dimensions from
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/LayerStackDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/LayerStackDefinition.java
index 072c99173..36e358e4d 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/LayerStackDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/LayerStackDefinition.java
@@ -1,14 +1,6 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.CompositeLayoutSpec;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.layout.payloads.PreparedStackLayout;
import com.demcha.compose.document.node.DocumentNode;
import com.demcha.compose.document.node.LayerAlign;
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/LineDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/LineDefinition.java
index 8bfe42f63..996e8fec9 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/LineDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/LineDefinition.java
@@ -1,22 +1,12 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.MeasureResult;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.layout.payloads.LineFragmentPayload;
import com.demcha.compose.document.node.LineNode;
import java.util.List;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.EPS;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.toStroke;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.wrapAtomicWithTransform;
+import static com.demcha.compose.document.layout.NodeDefinitionSupport.*;
/**
* Layout definition for {@link LineNode}: a fixed-size atomic line fragment
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/ListDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/ListDefinition.java
index 68b4bbea3..e33738302 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/ListDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/ListDefinition.java
@@ -1,22 +1,11 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
-import com.demcha.compose.document.layout.PreparedSplitResult;
-import com.demcha.compose.document.layout.SplitRequest;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.node.ListNode;
import java.util.List;
-import static com.demcha.compose.document.layout.TextFlowSupport.emitListFragments;
-import static com.demcha.compose.document.layout.TextFlowSupport.prepareList;
-import static com.demcha.compose.document.layout.TextFlowSupport.splitList;
+import static com.demcha.compose.document.layout.TextFlowSupport.*;
/**
* Layout definition for {@link ListNode}: lays out list items as a column of
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/PageBreakDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/PageBreakDefinition.java
index 683205a18..f2dea1f61 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/PageBreakDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/PageBreakDefinition.java
@@ -1,14 +1,6 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.MeasureResult;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.node.PageBreakNode;
import java.util.List;
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/ParagraphDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/ParagraphDefinition.java
index eb60a8452..c7c1ffc5b 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/ParagraphDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/ParagraphDefinition.java
@@ -1,22 +1,11 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
-import com.demcha.compose.document.layout.PreparedSplitResult;
-import com.demcha.compose.document.layout.SplitRequest;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.node.ParagraphNode;
import java.util.List;
-import static com.demcha.compose.document.layout.TextFlowSupport.emitParagraphFragments;
-import static com.demcha.compose.document.layout.TextFlowSupport.prepareParagraph;
-import static com.demcha.compose.document.layout.TextFlowSupport.splitParagraph;
+import static com.demcha.compose.document.layout.TextFlowSupport.*;
/**
* Layout definition for {@link ParagraphNode}: wraps text into visual lines,
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/PolygonDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/PolygonDefinition.java
index ab7cdd79e..0b86b78ae 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/PolygonDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/PolygonDefinition.java
@@ -1,14 +1,6 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.MeasureResult;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.layout.payloads.PolygonFragmentPayload;
import com.demcha.compose.document.node.PolygonNode;
@@ -26,7 +18,9 @@
*/
public final class PolygonDefinition implements NodeDefinition {
- /** Creates the polygon layout definition. */
+ /**
+ * Creates the polygon layout definition.
+ */
public PolygonDefinition() {
}
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/RowDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/RowDefinition.java
index f938aed07..4b416b75e 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/RowDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/RowDefinition.java
@@ -1,24 +1,12 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.CompositeLayoutSpec;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.node.DocumentNode;
import com.demcha.compose.document.node.RowNode;
import java.util.List;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.emitDecorationFragment;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.measureRow;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.toPadding;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.toSideBorders;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.toStroke;
+import static com.demcha.compose.document.layout.NodeDefinitionSupport.*;
/**
* Layout definition for {@link RowNode}: a horizontal atomic composite whose
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/SectionDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/SectionDefinition.java
index 9180ae8fc..c3b6f5736 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/SectionDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/SectionDefinition.java
@@ -1,24 +1,12 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.CompositeLayoutSpec;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.node.DocumentNode;
import com.demcha.compose.document.node.SectionNode;
import java.util.List;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.emitDecorationFragment;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.measureComposite;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.toPadding;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.toSideBorders;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.toStroke;
+import static com.demcha.compose.document.layout.NodeDefinitionSupport.*;
/**
* Layout definition for {@link SectionNode}: a vertical atomic composite with
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/ShapeContainerDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/ShapeContainerDefinition.java
index 6468fddba..fd831594f 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/ShapeContainerDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/ShapeContainerDefinition.java
@@ -1,23 +1,7 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.CompositeLayoutSpec;
-import com.demcha.compose.document.layout.payloads.EllipseFragmentPayload;
-import com.demcha.compose.document.layout.payloads.PolygonFragmentPayload;
-import com.demcha.compose.document.layout.payloads.PreparedStackLayout;
-import com.demcha.compose.document.layout.payloads.ShapeClipBeginPayload;
-import com.demcha.compose.document.layout.payloads.ShapeFragmentPayload;
-import com.demcha.compose.document.layout.payloads.ShapeClipEndPayload;
-import com.demcha.compose.document.layout.payloads.TransformBeginPayload;
-import com.demcha.compose.document.layout.payloads.TransformEndPayload;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.MeasureResult;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
+import com.demcha.compose.document.layout.*;
+import com.demcha.compose.document.layout.payloads.*;
import com.demcha.compose.document.node.DocumentNode;
import com.demcha.compose.document.node.LayerAlign;
import com.demcha.compose.document.node.LayerStackNode;
@@ -27,13 +11,11 @@
import com.demcha.compose.engine.components.content.shape.Stroke;
import com.demcha.compose.engine.components.style.Padding;
-import java.awt.Color;
+import java.awt.*;
import java.util.ArrayList;
import java.util.List;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.EPS;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.toPadding;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.toStroke;
+import static com.demcha.compose.document.layout.NodeDefinitionSupport.*;
/**
* Layout definition for {@link ShapeContainerNode}: an atomic shape-backed
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/ShapeDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/ShapeDefinition.java
index 5b4c91491..10d798828 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/ShapeDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/ShapeDefinition.java
@@ -1,22 +1,12 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.MeasureResult;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.layout.payloads.ShapeFragmentPayload;
import com.demcha.compose.document.node.ShapeNode;
import java.util.List;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.EPS;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.toStroke;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.wrapAtomicWithTransform;
+import static com.demcha.compose.document.layout.NodeDefinitionSupport.*;
/**
* Layout definition for {@link ShapeNode}: a fixed-size atomic rectangle shape
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/SpacerDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/SpacerDefinition.java
index 2e7096d77..ad650a6bd 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/SpacerDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/SpacerDefinition.java
@@ -1,14 +1,6 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.MeasureResult;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.node.SpacerNode;
import java.util.List;
diff --git a/src/main/java/com/demcha/compose/document/layout/definitions/TableDefinition.java b/src/main/java/com/demcha/compose/document/layout/definitions/TableDefinition.java
index 5b02d2d69..31fcb6bb8 100644
--- a/src/main/java/com/demcha/compose/document/layout/definitions/TableDefinition.java
+++ b/src/main/java/com/demcha/compose/document/layout/definitions/TableDefinition.java
@@ -1,22 +1,11 @@
package com.demcha.compose.document.layout.definitions;
-import com.demcha.compose.document.layout.BoxConstraints;
-import com.demcha.compose.document.layout.FragmentContext;
-import com.demcha.compose.document.layout.FragmentPlacement;
-import com.demcha.compose.document.layout.LayoutFragment;
-import com.demcha.compose.document.layout.NodeDefinition;
-import com.demcha.compose.document.layout.PaginationPolicy;
-import com.demcha.compose.document.layout.PrepareContext;
-import com.demcha.compose.document.layout.PreparedNode;
-import com.demcha.compose.document.layout.PreparedSplitResult;
-import com.demcha.compose.document.layout.SplitRequest;
+import com.demcha.compose.document.layout.*;
import com.demcha.compose.document.node.TableNode;
import java.util.List;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.emitTableFragments;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.prepareTable;
-import static com.demcha.compose.document.layout.NodeDefinitionSupport.splitTable;
+import static com.demcha.compose.document.layout.NodeDefinitionSupport.*;
/**
* Layout definition for {@link TableNode}: resolves table geometry through
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/BarcodeFragmentPayload.java b/src/main/java/com/demcha/compose/document/layout/payloads/BarcodeFragmentPayload.java
index 48bf6ab62..14bc0d745 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/BarcodeFragmentPayload.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/BarcodeFragmentPayload.java
@@ -7,8 +7,8 @@
/**
* PDF payload for a resolved barcode fragment.
*
- * @param barcodeData encoded barcode payload
- * @param linkOptions optional fragment-level link metadata
+ * @param barcodeData encoded barcode payload
+ * @param linkOptions optional fragment-level link metadata
* @param bookmarkOptions optional fragment-level bookmark metadata
*/
public record BarcodeFragmentPayload(
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/EllipseFragmentPayload.java b/src/main/java/com/demcha/compose/document/layout/payloads/EllipseFragmentPayload.java
index 56d5d57f7..724dd57f7 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/EllipseFragmentPayload.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/EllipseFragmentPayload.java
@@ -4,14 +4,14 @@
import com.demcha.compose.document.node.DocumentLinkOptions;
import com.demcha.compose.engine.components.content.shape.Stroke;
-import java.awt.Color;
+import java.awt.*;
/**
* PDF payload for a resolved ellipse or circle fragment.
*
- * @param fillColor optional fill color
- * @param stroke optional stroke
- * @param linkOptions optional fragment-level link metadata
+ * @param fillColor optional fill color
+ * @param stroke optional stroke
+ * @param linkOptions optional fragment-level link metadata
* @param bookmarkOptions optional fragment-level bookmark metadata
*/
public record EllipseFragmentPayload(
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/ImageFragmentPayload.java b/src/main/java/com/demcha/compose/document/layout/payloads/ImageFragmentPayload.java
index a48d839b1..2dcc1d009 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/ImageFragmentPayload.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/ImageFragmentPayload.java
@@ -8,9 +8,9 @@
/**
* PDF payload for a resolved image fragment.
*
- * @param imageData image source data
- * @param fitMode image fit policy used inside the resolved fragment
- * @param linkOptions optional fragment-level link metadata
+ * @param imageData image source data
+ * @param fitMode image fit policy used inside the resolved fragment
+ * @param linkOptions optional fragment-level link metadata
* @param bookmarkOptions optional fragment-level bookmark metadata
*/
public record ImageFragmentPayload(
@@ -26,3 +26,4 @@ public record ImageFragmentPayload(
fitMode = fitMode == null ? DocumentImageFitMode.STRETCH : fitMode;
}
}
+
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/LineFragmentPayload.java b/src/main/java/com/demcha/compose/document/layout/payloads/LineFragmentPayload.java
index 333f1b341..82ab56f2a 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/LineFragmentPayload.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/LineFragmentPayload.java
@@ -8,14 +8,14 @@
/**
* PDF payload for a resolved line fragment.
*
- * @param stroke line stroke
- * @param startX line start x offset inside the fragment
- * @param startY line start y offset inside the fragment
- * @param endX line end x offset inside the fragment
- * @param endY line end y offset inside the fragment
- * @param linkOptions optional fragment-level link metadata
+ * @param stroke line stroke
+ * @param startX line start x offset inside the fragment
+ * @param startY line start y offset inside the fragment
+ * @param endX line end x offset inside the fragment
+ * @param endY line end y offset inside the fragment
+ * @param linkOptions optional fragment-level link metadata
* @param bookmarkOptions optional fragment-level bookmark metadata
- * @param dashPattern dash pattern for the stroke; {@link DocumentDashPattern#NONE} is solid
+ * @param dashPattern dash pattern for the stroke; {@link DocumentDashPattern#NONE} is solid
*/
public record LineFragmentPayload(
Stroke stroke,
@@ -38,12 +38,12 @@ public record LineFragmentPayload(
/**
* Backward-compatible constructor for a solid line fragment.
*
- * @param stroke line stroke
- * @param startX line start x offset inside the fragment
- * @param startY line start y offset inside the fragment
- * @param endX line end x offset inside the fragment
- * @param endY line end y offset inside the fragment
- * @param linkOptions optional fragment-level link metadata
+ * @param stroke line stroke
+ * @param startX line start x offset inside the fragment
+ * @param startY line start y offset inside the fragment
+ * @param endX line end x offset inside the fragment
+ * @param endY line end y offset inside the fragment
+ * @param linkOptions optional fragment-level link metadata
* @param bookmarkOptions optional fragment-level bookmark metadata
*/
public LineFragmentPayload(Stroke stroke,
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphFragmentPayload.java b/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphFragmentPayload.java
index 4df155eb7..629387d27 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphFragmentPayload.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphFragmentPayload.java
@@ -12,16 +12,16 @@
/**
* PDF payload for a resolved paragraph fragment.
*
- * @param textStyle base text style for the fragment
- * @param align horizontal text alignment
- * @param padding fragment padding
- * @param lineHeight resolved line height
- * @param lineGap extra spacing between lines
- * @param baselineOffset offset from line bottom to baseline
- * @param lines measured lines contained by the fragment
- * @param linkOptions optional fragment-level link metadata
+ * @param textStyle base text style for the fragment
+ * @param align horizontal text alignment
+ * @param padding fragment padding
+ * @param lineHeight resolved line height
+ * @param lineGap extra spacing between lines
+ * @param baselineOffset offset from line bottom to baseline
+ * @param lines measured lines contained by the fragment
+ * @param linkOptions optional fragment-level link metadata
* @param bookmarkOptions optional fragment-level bookmark metadata
- * @param verticalAlign vertical seating of the text within its line box
+ * @param verticalAlign vertical seating of the text within its line box
*/
public record ParagraphFragmentPayload(
TextStyle textStyle,
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphImageSpan.java b/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphImageSpan.java
index 1911fe3db..b48c15453 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphImageSpan.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphImageSpan.java
@@ -9,12 +9,12 @@
/**
* Measured inline image span inside a paragraph line.
*
- * @param imageData engine image payload, ready for the PDF backend
- * @param width target width in points
- * @param height target height in points
- * @param alignment vertical alignment relative to the surrounding text
+ * @param imageData engine image payload, ready for the PDF backend
+ * @param width target width in points
+ * @param height target height in points
+ * @param alignment vertical alignment relative to the surrounding text
* @param baselineOffset extra vertical offset in points; positive moves up
- * @param linkOptions optional link metadata
+ * @param linkOptions optional link metadata
*/
public record ParagraphImageSpan(
ImageData imageData,
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphLine.java b/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphLine.java
index d67a6d006..809f144aa 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphLine.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphLine.java
@@ -5,17 +5,17 @@
/**
* One measured paragraph line emitted to the PDF backend.
*
- * @param text line text used for diagnostics and simple rendering paths
- * @param width measured line width
- * @param lineHeight resolved line height (max of text and image heights)
- * @param textLineHeight font-line-height for the dominant text style on
- * this line; equals {@code lineHeight} when no
- * inline image enlarges the line
- * @param textAscent ascent of the dominant text style on this line; used
- * to position image spans relative to the baseline
+ * @param text line text used for diagnostics and simple rendering paths
+ * @param width measured line width
+ * @param lineHeight resolved line height (max of text and image heights)
+ * @param textLineHeight font-line-height for the dominant text style on
+ * this line; equals {@code lineHeight} when no
+ * inline image enlarges the line
+ * @param textAscent ascent of the dominant text style on this line; used
+ * to position image spans relative to the baseline
* @param baselineOffsetFromBottom distance from line bottom to the text
* baseline
- * @param spans measured styled spans in source order
+ * @param spans measured styled spans in source order
*/
public record ParagraphLine(
String text,
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphShapeSpan.java b/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphShapeSpan.java
index 94c4b4207..e0872d482 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphShapeSpan.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphShapeSpan.java
@@ -11,12 +11,12 @@
* bounding box, so composite figures (e.g. a checkbox: box + checkmark) place
* on the text baseline as one unit.
*
- * @param layers resolved paint layers, back-to-front
- * @param width bounding width in points
- * @param height bounding height in points
- * @param alignment vertical alignment relative to the surrounding text
+ * @param layers resolved paint layers, back-to-front
+ * @param width bounding width in points
+ * @param height bounding height in points
+ * @param alignment vertical alignment relative to the surrounding text
* @param baselineOffset extra vertical offset in points; positive moves up
- * @param linkOptions optional link metadata
+ * @param linkOptions optional link metadata
*/
public record ParagraphShapeSpan(
List layers,
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphSpan.java b/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphSpan.java
index 095376958..b40761903 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphSpan.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphSpan.java
@@ -26,7 +26,7 @@ public sealed interface ParagraphSpan permits ParagraphTextSpan, ParagraphImageS
* Height this span contributes to its line.
*
* @return effective height contribution for line metrics (font line
- * height for text spans, image height for image spans)
+ * height for text spans, image height for image spans)
*/
double height();
}
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphTextSpan.java b/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphTextSpan.java
index 4cbee69ca..1fc63812e 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphTextSpan.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/ParagraphTextSpan.java
@@ -6,10 +6,10 @@
/**
* Measured text span inside a paragraph line.
*
- * @param text visible text for the span
- * @param textStyle resolved text style
- * @param width measured span width
- * @param height font line height contribution
+ * @param text visible text for the span
+ * @param textStyle resolved text style
+ * @param width measured span width
+ * @param height font line height contribution
* @param linkOptions optional link metadata for the span
*/
public record ParagraphTextSpan(
@@ -30,10 +30,10 @@ public record ParagraphTextSpan(
/**
* Convenience constructor without link metadata.
*
- * @param text visible text for the span
+ * @param text visible text for the span
* @param textStyle resolved text style
- * @param width measured span width
- * @param height font line height contribution
+ * @param width measured span width
+ * @param height font line height contribution
*/
public ParagraphTextSpan(String text, TextStyle textStyle, double width, double height) {
this(text, textStyle, width, height, null);
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/PolygonFragmentPayload.java b/src/main/java/com/demcha/compose/document/layout/payloads/PolygonFragmentPayload.java
index eb5ff1c72..2f1d4b1cf 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/PolygonFragmentPayload.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/PolygonFragmentPayload.java
@@ -5,7 +5,7 @@
import com.demcha.compose.document.style.ShapePoint;
import com.demcha.compose.engine.components.content.shape.Stroke;
-import java.awt.Color;
+import java.awt.*;
import java.util.List;
import java.util.Objects;
@@ -14,10 +14,10 @@
* vertex ring). The normalized vertices are scaled to the placed fragment's
* size by the render handler.
*
- * @param points normalized vertex ring (at least three), in draw order
- * @param fillColor optional fill color
- * @param stroke optional stroke
- * @param linkOptions optional fragment-level link metadata
+ * @param points normalized vertex ring (at least three), in draw order
+ * @param fillColor optional fill color
+ * @param stroke optional stroke
+ * @param linkOptions optional fragment-level link metadata
* @param bookmarkOptions optional fragment-level bookmark metadata
*/
public record PolygonFragmentPayload(
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/PreparedListItemLayout.java b/src/main/java/com/demcha/compose/document/layout/payloads/PreparedListItemLayout.java
index bfb3d81e9..00cc1afe0 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/PreparedListItemLayout.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/PreparedListItemLayout.java
@@ -7,7 +7,7 @@
* Wraps the item's text alongside the prepared paragraph layout that
* the list definition uses to split items across pages.
*
- * @param text raw item text
+ * @param text raw item text
* @param paragraphLayout prepared paragraph layout for this item
*/
public record PreparedListItemLayout(
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/PreparedListLayout.java b/src/main/java/com/demcha/compose/document/layout/payloads/PreparedListLayout.java
index 0a9b632f8..2296adcd3 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/PreparedListLayout.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/PreparedListLayout.java
@@ -9,9 +9,9 @@
* Aggregates the per-item prepared layouts and the resolved width/height
* the list definition uses for the emit pass.
*
- * @param items per-item prepared layouts
- * @param maxLineWidth widest measured line width across items
- * @param totalHeight cumulative list height
+ * @param items per-item prepared layouts
+ * @param maxLineWidth widest measured line width across items
+ * @param totalHeight cumulative list height
* @param resolvedWidth resolved layout width
*/
public record PreparedListLayout(
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/PreparedParagraphLayout.java b/src/main/java/com/demcha/compose/document/layout/payloads/PreparedParagraphLayout.java
index 5c91ed8ac..98b5222c5 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/PreparedParagraphLayout.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/PreparedParagraphLayout.java
@@ -11,15 +11,15 @@
* cumulative measurements computed during the prepare pass; consumed by
* the paragraph definition's split + emit paths.
*
- * @param logicalLines original paragraph lines before wrapping
- * @param visualLines wrapped lines that the renderer paints
- * @param lineMetrics font line metrics for the dominant text style
+ * @param logicalLines original paragraph lines before wrapping
+ * @param visualLines wrapped lines that the renderer paints
+ * @param lineMetrics font line metrics for the dominant text style
* @param baselineOffset baseline offset in points
- * @param lineHeight resolved line height
- * @param lineGap extra spacing between wrapped lines
- * @param maxLineWidth widest measured line width
- * @param totalHeight cumulative paragraph height
- * @param emitBookmark whether the paragraph should emit a bookmark
+ * @param lineHeight resolved line height
+ * @param lineGap extra spacing between wrapped lines
+ * @param maxLineWidth widest measured line width
+ * @param totalHeight cumulative paragraph height
+ * @param emitBookmark whether the paragraph should emit a bookmark
*/
public record PreparedParagraphLayout(
List logicalLines,
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/PreparedStackLayout.java b/src/main/java/com/demcha/compose/document/layout/payloads/PreparedStackLayout.java
index 7ff976ead..17f83aa06 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/PreparedStackLayout.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/PreparedStackLayout.java
@@ -17,9 +17,9 @@
* earlier-declared layer with {@code zIndex = 5}.
*
* @param alignments per-layer alignments resolved from the source order
- * @param offsetsX per-layer horizontal offsets from the alignment anchor
- * @param offsetsY per-layer vertical offsets from the alignment anchor
- * @param zIndices per-layer render-order keys (defaults are {@code 0})
+ * @param offsetsX per-layer horizontal offsets from the alignment anchor
+ * @param offsetsY per-layer vertical offsets from the alignment anchor
+ * @param zIndices per-layer render-order keys (defaults are {@code 0})
*/
public record PreparedStackLayout(
List alignments,
@@ -36,12 +36,12 @@ public record PreparedStackLayout(
offsetsY = List.copyOf(offsetsY);
zIndices = List.copyOf(zIndices);
if (offsetsX.size() != alignments.size()
- || offsetsY.size() != alignments.size()
- || zIndices.size() != alignments.size()) {
+ || offsetsY.size() != alignments.size()
+ || zIndices.size() != alignments.size()) {
throw new IllegalArgumentException(
"PreparedStackLayout: alignments/offsets/zIndices size mismatch ("
- + alignments.size() + "/" + offsetsX.size() + "/"
- + offsetsY.size() + "/" + zIndices.size() + ")");
+ + alignments.size() + "/" + offsetsX.size() + "/"
+ + offsetsY.size() + "/" + zIndices.size() + ")");
}
}
@@ -50,8 +50,8 @@ public record PreparedStackLayout(
* zeros so layers render in source order.
*
* @param alignments per-layer alignments
- * @param offsetsX per-layer horizontal offsets
- * @param offsetsY per-layer vertical offsets
+ * @param offsetsX per-layer horizontal offsets
+ * @param offsetsY per-layer vertical offsets
*/
public PreparedStackLayout(List alignments,
List offsetsX,
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/ResolvedShapeLayer.java b/src/main/java/com/demcha/compose/document/layout/payloads/ResolvedShapeLayer.java
index 9142cd91e..c6f4f33df 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/ResolvedShapeLayer.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/ResolvedShapeLayer.java
@@ -3,16 +3,16 @@
import com.demcha.compose.document.style.ShapeOutline;
import com.demcha.compose.engine.components.content.shape.Stroke;
-import java.awt.Color;
+import java.awt.*;
/**
* One resolved paint layer of a {@link ParagraphShapeSpan}: an outline figure
* whose fill colour and stroke are already resolved to AWT / engine primitives,
* ready for the PDF backend.
*
- * @param outline figure geometry
+ * @param outline figure geometry
* @param fillColor optional resolved fill color
- * @param stroke optional resolved outline stroke
+ * @param stroke optional resolved outline stroke
*/
public record ResolvedShapeLayer(ShapeOutline outline, Color fillColor, Stroke stroke) {
}
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/ShapeClipBeginPayload.java b/src/main/java/com/demcha/compose/document/layout/payloads/ShapeClipBeginPayload.java
index 4f090372b..c8603339b 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/ShapeClipBeginPayload.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/ShapeClipBeginPayload.java
@@ -20,11 +20,11 @@
* Backends that cannot express path clipping (e.g. DOCX/POI) skip both
* fragments and emit a capability warning instead.
*
- * @param outline outline geometry to clip against
- * @param policy clip policy chosen for the container; renderers may
- * degrade {@link ClipPolicy#CLIP_PATH} to
- * {@link ClipPolicy#CLIP_BOUNDS} when path clipping is
- * unavailable
+ * @param outline outline geometry to clip against
+ * @param policy clip policy chosen for the container; renderers may
+ * degrade {@link ClipPolicy#CLIP_PATH} to
+ * {@link ClipPolicy#CLIP_BOUNDS} when path clipping is
+ * unavailable
* @param ownerPath semantic path of the owning container — used by
* architecture-guard tests to verify the begin/end
* pair balance
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/ShapeFragmentPayload.java b/src/main/java/com/demcha/compose/document/layout/payloads/ShapeFragmentPayload.java
index 28fbfa6d1..acd1b6b5c 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/ShapeFragmentPayload.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/ShapeFragmentPayload.java
@@ -6,7 +6,7 @@
import com.demcha.compose.document.style.DocumentPaint;
import com.demcha.compose.engine.components.content.shape.Stroke;
-import java.awt.Color;
+import java.awt.*;
/**
* PDF payload for a resolved shape fragment.
@@ -22,13 +22,13 @@
* {@link DocumentPaint.Radial} and backends without shading support fall
* back to its {@link DocumentPaint#primaryColor()}.
*
- * @param fillColor optional shape fill color
- * @param stroke optional shape stroke
- * @param cornerRadius per-corner radii in points
- * @param linkOptions optional fragment-level link metadata
+ * @param fillColor optional shape fill color
+ * @param stroke optional shape stroke
+ * @param cornerRadius per-corner radii in points
+ * @param linkOptions optional fragment-level link metadata
* @param bookmarkOptions optional fragment-level bookmark metadata
- * @param sideBorders optional per-side border strokes
- * @param fillPaint optional gradient fill; {@code null} for solid fills
+ * @param sideBorders optional per-side border strokes
+ * @param fillPaint optional gradient fill; {@code null} for solid fills
*/
public record ShapeFragmentPayload(
Color fillColor,
@@ -51,12 +51,12 @@ public record ShapeFragmentPayload(
/**
* Backwards-compatible constructor without a gradient fill.
*
- * @param fillColor optional shape fill color
- * @param stroke optional shape stroke
- * @param cornerRadius per-corner radii in points
- * @param linkOptions optional fragment-level link metadata
+ * @param fillColor optional shape fill color
+ * @param stroke optional shape stroke
+ * @param cornerRadius per-corner radii in points
+ * @param linkOptions optional fragment-level link metadata
* @param bookmarkOptions optional fragment-level bookmark metadata
- * @param sideBorders optional per-side border strokes
+ * @param sideBorders optional per-side border strokes
*/
public ShapeFragmentPayload(Color fillColor,
Stroke stroke,
@@ -71,12 +71,12 @@ public ShapeFragmentPayload(Color fillColor,
* Backwards-compatible constructor that accepts a single uniform
* radius (pre-Phase E.1.1 wiring) and applies it to every corner.
*
- * @param fillColor optional shape fill color
- * @param stroke optional shape stroke
- * @param cornerRadius uniform corner radius in points
- * @param linkOptions optional fragment-level link metadata
+ * @param fillColor optional shape fill color
+ * @param stroke optional shape stroke
+ * @param cornerRadius uniform corner radius in points
+ * @param linkOptions optional fragment-level link metadata
* @param bookmarkOptions optional fragment-level bookmark metadata
- * @param sideBorders optional per-side border strokes
+ * @param sideBorders optional per-side border strokes
*/
public ShapeFragmentPayload(Color fillColor,
Stroke stroke,
@@ -94,10 +94,10 @@ public ShapeFragmentPayload(Color fillColor,
/**
* Backwards-compatible constructor without per-side borders.
*
- * @param fillColor optional shape fill color
- * @param stroke optional shape stroke
- * @param cornerRadius uniform corner radius in points
- * @param linkOptions optional fragment-level link metadata
+ * @param fillColor optional shape fill color
+ * @param stroke optional shape stroke
+ * @param cornerRadius uniform corner radius in points
+ * @param linkOptions optional fragment-level link metadata
* @param bookmarkOptions optional fragment-level bookmark metadata
*/
public ShapeFragmentPayload(Color fillColor,
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/SideBorders.java b/src/main/java/com/demcha/compose/document/layout/payloads/SideBorders.java
index f4f6c356d..788b9d650 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/SideBorders.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/SideBorders.java
@@ -9,10 +9,10 @@
* side. The renderer treats this record as a request to draw the four lines
* separately rather than rely on a single uniform rectangle stroke.
*
- * @param top top side stroke, or {@code null} for no border on that side
- * @param right right side stroke, or {@code null} for no border on that side
+ * @param top top side stroke, or {@code null} for no border on that side
+ * @param right right side stroke, or {@code null} for no border on that side
* @param bottom bottom side stroke, or {@code null} for no border on that side
- * @param left left side stroke, or {@code null} for no border on that side
+ * @param left left side stroke, or {@code null} for no border on that side
*/
public record SideBorders(Stroke top, Stroke right, Stroke bottom, Stroke left) {
/**
diff --git a/src/main/java/com/demcha/compose/document/layout/payloads/TableRowFragmentPayload.java b/src/main/java/com/demcha/compose/document/layout/payloads/TableRowFragmentPayload.java
index a894c1189..684e77c62 100644
--- a/src/main/java/com/demcha/compose/document/layout/payloads/TableRowFragmentPayload.java
+++ b/src/main/java/com/demcha/compose/document/layout/payloads/TableRowFragmentPayload.java
@@ -9,10 +9,10 @@
/**
* PDF payload for one resolved table row fragment.
*
- * @param cells resolved cells in column order
+ * @param cells resolved cells in column order
* @param startsPageFragment whether this row starts a table page fragment
- * @param linkOptions optional fragment-level link metadata
- * @param bookmarkOptions optional fragment-level bookmark metadata
+ * @param linkOptions optional fragment-level link metadata
+ * @param bookmarkOptions optional fragment-level bookmark metadata
*/
public record TableRowFragmentPayload(
List cells,
diff --git a/src/main/java/com/demcha/compose/document/node/BarcodeNode.java b/src/main/java/com/demcha/compose/document/node/BarcodeNode.java
index 0d0ddd12e..0f7c1460f 100644
--- a/src/main/java/com/demcha/compose/document/node/BarcodeNode.java
+++ b/src/main/java/com/demcha/compose/document/node/BarcodeNode.java
@@ -56,12 +56,12 @@ public record BarcodeNode(
/**
* Backward-compatible convenience constructor without link/bookmark metadata.
*
- * @param name node name used in snapshots and layout graph paths
- * @param barcodeOptions canonical barcode payload
- * @param width target rendered width
- * @param height target rendered height
- * @param padding inner padding
- * @param margin outer margin
+ * @param name node name used in snapshots and layout graph paths
+ * @param barcodeOptions canonical barcode payload
+ * @param width target rendered width
+ * @param height target rendered height
+ * @param padding inner padding
+ * @param margin outer margin
*/
public BarcodeNode(String name,
DocumentBarcodeOptions barcodeOptions,
diff --git a/src/main/java/com/demcha/compose/document/node/CanvasChild.java b/src/main/java/com/demcha/compose/document/node/CanvasChild.java
index ec1195ddd..f28b5c0f5 100644
--- a/src/main/java/com/demcha/compose/document/node/CanvasChild.java
+++ b/src/main/java/com/demcha/compose/document/node/CanvasChild.java
@@ -15,9 +15,8 @@
* pixel-perfect cover-page elements.
*
* @param node child node placed inside the canvas
- * @param x offset from the canvas's left edge (points)
- * @param y offset from the canvas's top edge (points, positive = down)
- *
+ * @param x offset from the canvas's left edge (points)
+ * @param y offset from the canvas's top edge (points, positive = down)
* @author Artem Demchyshyn
*/
public record CanvasChild(DocumentNode node, double x, double y) {
diff --git a/src/main/java/com/demcha/compose/document/node/CanvasLayerNode.java b/src/main/java/com/demcha/compose/document/node/CanvasLayerNode.java
index 3d86098bc..ad8f0e897 100644
--- a/src/main/java/com/demcha/compose/document/node/CanvasLayerNode.java
+++ b/src/main/java/com/demcha/compose/document/node/CanvasLayerNode.java
@@ -31,16 +31,15 @@
* page. Children must therefore stay short enough to live on a
* single page; oversized canvases throw at layout time.
*
- * @param name canvas name used in snapshots and layout graph paths
- * @param width canvas inner width in points (must be {@code > 0})
- * @param height canvas inner height in points (must be {@code > 0})
+ * @param name canvas name used in snapshots and layout graph paths
+ * @param width canvas inner width in points (must be {@code > 0})
+ * @param height canvas inner height in points (must be {@code > 0})
* @param placements per-child {@link CanvasChild} entries (node + position)
* @param clipPolicy clipping mode applied to children that overflow
* the canvas's bounding box
- * @param padding inner padding between the canvas's outer rectangle
- * and the placement coordinate space
- * @param margin outer margin around the canvas
- *
+ * @param padding inner padding between the canvas's outer rectangle
+ * and the placement coordinate space
+ * @param margin outer margin around the canvas
* @author Artem Demchyshyn
*/
public record CanvasLayerNode(
diff --git a/src/main/java/com/demcha/compose/document/node/ChartNode.java b/src/main/java/com/demcha/compose/document/node/ChartNode.java
index 893bf076b..6e03b880d 100644
--- a/src/main/java/com/demcha/compose/document/node/ChartNode.java
+++ b/src/main/java/com/demcha/compose/document/node/ChartNode.java
@@ -23,12 +23,11 @@
* it places whole on a page or moves to the next, exactly like an inline image
* or a shape container.
*
- * @param name optional semantic name for snapshots / diagnostics
- * @param spec structural chart description (kind, axes, legend, data)
- * @param style visual styling, or {@code null} to inherit the theme entirely
- * @param margin outer spacing
+ * @param name optional semantic name for snapshots / diagnostics
+ * @param spec structural chart description (kind, axes, legend, data)
+ * @param style visual styling, or {@code null} to inherit the theme entirely
+ * @param margin outer spacing
* @param padding inner spacing inside the chart box (insets the plot area)
- *
* @author Artem Demchyshyn
* @since 1.8.0
*/
@@ -40,7 +39,9 @@ public record ChartNode(
DocumentInsets padding
) implements DocumentNode {
- /** Normalizes nullable spacing and name. */
+ /**
+ * Normalizes nullable spacing and name.
+ */
public ChartNode {
name = name == null ? "" : name;
Objects.requireNonNull(spec, "spec");
diff --git a/src/main/java/com/demcha/compose/document/node/ContainerNode.java b/src/main/java/com/demcha/compose/document/node/ContainerNode.java
index 961159645..793e96e69 100644
--- a/src/main/java/com/demcha/compose/document/node/ContainerNode.java
+++ b/src/main/java/com/demcha/compose/document/node/ContainerNode.java
@@ -1,10 +1,6 @@
package com.demcha.compose.document.node;
-import com.demcha.compose.document.style.DocumentBorders;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentCornerRadius;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
+import com.demcha.compose.document.style.*;
import java.util.List;
import java.util.Objects;
@@ -12,16 +8,15 @@
/**
* Vertical flow semantic container.
*
- * @param name node name used in snapshots and layout graph paths
- * @param children child semantic nodes in source order
- * @param spacing vertical spacing between children
- * @param padding inner padding
- * @param margin outer margin
- * @param fillColor optional background fill
- * @param stroke optional uniform border stroke
+ * @param name node name used in snapshots and layout graph paths
+ * @param children child semantic nodes in source order
+ * @param spacing vertical spacing between children
+ * @param padding inner padding
+ * @param margin outer margin
+ * @param fillColor optional background fill
+ * @param stroke optional uniform border stroke
* @param cornerRadius optional render-only corner radius
- * @param borders optional per-side border strokes overriding the uniform stroke
- *
+ * @param borders optional per-side border strokes overriding the uniform stroke
* @author Artem Demchyshyn
*/
public record ContainerNode(
@@ -54,13 +49,13 @@ public record ContainerNode(
/**
* Creates a vertical flow container without per-side borders.
*
- * @param name node name used in snapshots and layout graph paths
- * @param children child semantic nodes in source order
- * @param spacing vertical spacing between children
- * @param padding inner padding
- * @param margin outer margin
- * @param fillColor optional background fill
- * @param stroke optional uniform border stroke
+ * @param name node name used in snapshots and layout graph paths
+ * @param children child semantic nodes in source order
+ * @param spacing vertical spacing between children
+ * @param padding inner padding
+ * @param margin outer margin
+ * @param fillColor optional background fill
+ * @param stroke optional uniform border stroke
* @param cornerRadius optional render-only corner radius
*/
public ContainerNode(String name,
@@ -77,13 +72,13 @@ public ContainerNode(String name,
/**
* Creates a vertical flow container with square corners and no per-side borders.
*
- * @param name node name used in snapshots and layout graph paths
- * @param children child semantic nodes in source order
- * @param spacing vertical spacing between children
- * @param padding inner padding
- * @param margin outer margin
+ * @param name node name used in snapshots and layout graph paths
+ * @param children child semantic nodes in source order
+ * @param spacing vertical spacing between children
+ * @param padding inner padding
+ * @param margin outer margin
* @param fillColor optional background fill
- * @param stroke optional uniform border stroke
+ * @param stroke optional uniform border stroke
*/
public ContainerNode(String name,
List children,
diff --git a/src/main/java/com/demcha/compose/document/node/DocumentBarcodeType.java b/src/main/java/com/demcha/compose/document/node/DocumentBarcodeType.java
index 2a297d40b..792fe3f25 100644
--- a/src/main/java/com/demcha/compose/document/node/DocumentBarcodeType.java
+++ b/src/main/java/com/demcha/compose/document/node/DocumentBarcodeType.java
@@ -6,20 +6,36 @@
* @author Artem Demchyshyn
*/
public enum DocumentBarcodeType {
- /** QR code. */
+ /**
+ * QR code.
+ */
QR_CODE,
- /** Code 128 barcode. */
+ /**
+ * Code 128 barcode.
+ */
CODE_128,
- /** Code 39 barcode. */
+ /**
+ * Code 39 barcode.
+ */
CODE_39,
- /** EAN-13 barcode. */
+ /**
+ * EAN-13 barcode.
+ */
EAN_13,
- /** EAN-8 barcode. */
+ /**
+ * EAN-8 barcode.
+ */
EAN_8,
- /** UPC-A barcode. */
+ /**
+ * UPC-A barcode.
+ */
UPC_A,
- /** PDF417 barcode. */
+ /**
+ * PDF417 barcode.
+ */
PDF_417,
- /** Data Matrix barcode. */
+ /**
+ * Data Matrix barcode.
+ */
DATA_MATRIX
}
diff --git a/src/main/java/com/demcha/compose/document/node/EllipseNode.java b/src/main/java/com/demcha/compose/document/node/EllipseNode.java
index a7e469aa8..c0783cb87 100644
--- a/src/main/java/com/demcha/compose/document/node/EllipseNode.java
+++ b/src/main/java/com/demcha/compose/document/node/EllipseNode.java
@@ -8,17 +8,17 @@
/**
* Atomic ellipse or circle semantic shape.
*
- * @param name node name used in snapshots and layout graph paths
- * @param width resolved ellipse width
- * @param height resolved ellipse height
- * @param fillColor optional fill color
- * @param stroke optional stroke descriptor
- * @param linkOptions optional node-level link metadata
+ * @param name node name used in snapshots and layout graph paths
+ * @param width resolved ellipse width
+ * @param height resolved ellipse height
+ * @param fillColor optional fill color
+ * @param stroke optional stroke descriptor
+ * @param linkOptions optional node-level link metadata
* @param bookmarkOptions optional node-level bookmark metadata
- * @param padding inner padding
- * @param margin outer margin
- * @param transform render-time affine transform; defaults to
- * {@link DocumentTransform#NONE}.
+ * @param padding inner padding
+ * @param margin outer margin
+ * @param transform render-time affine transform; defaults to
+ * {@link DocumentTransform#NONE}.
* @author Artem Demchyshyn
*/
public record EllipseNode(
@@ -53,15 +53,15 @@ public record EllipseNode(
* Backward-compatible convenience constructor without transform — defaults
* to {@link DocumentTransform#NONE}.
*
- * @param name node name used in snapshots and layout graph paths
- * @param width resolved ellipse width
- * @param height resolved ellipse height
- * @param fillColor optional fill color
- * @param stroke optional stroke descriptor
- * @param linkOptions optional node-level link metadata
+ * @param name node name used in snapshots and layout graph paths
+ * @param width resolved ellipse width
+ * @param height resolved ellipse height
+ * @param fillColor optional fill color
+ * @param stroke optional stroke descriptor
+ * @param linkOptions optional node-level link metadata
* @param bookmarkOptions optional node-level bookmark metadata
- * @param padding inner padding
- * @param margin outer margin
+ * @param padding inner padding
+ * @param margin outer margin
*/
public EllipseNode(String name,
double width,
diff --git a/src/main/java/com/demcha/compose/document/node/ImageNode.java b/src/main/java/com/demcha/compose/document/node/ImageNode.java
index b5c055075..d8a3556f7 100644
--- a/src/main/java/com/demcha/compose/document/node/ImageNode.java
+++ b/src/main/java/com/demcha/compose/document/node/ImageNode.java
@@ -10,19 +10,18 @@
/**
* Atomic semantic image node.
*
- * @param name node name used in snapshots and layout graph paths
- * @param imageData semantic image payload
- * @param width optional target width
- * @param height optional target height
- * @param scale optional uniform scale applied when width and height are omitted
- * @param fitMode image fit policy used when drawing inside explicit bounds
- * @param linkOptions optional node-level link metadata
+ * @param name node name used in snapshots and layout graph paths
+ * @param imageData semantic image payload
+ * @param width optional target width
+ * @param height optional target height
+ * @param scale optional uniform scale applied when width and height are omitted
+ * @param fitMode image fit policy used when drawing inside explicit bounds
+ * @param linkOptions optional node-level link metadata
* @param bookmarkOptions optional node-level bookmark metadata
- * @param padding inner padding
- * @param margin outer margin
- * @param transform render-time affine transform; defaults to
- * {@link DocumentTransform#NONE}.
- *
+ * @param padding inner padding
+ * @param margin outer margin
+ * @param transform render-time affine transform; defaults to
+ * {@link DocumentTransform#NONE}.
* @author Artem Demchyshyn
*/
public record ImageNode(
@@ -62,12 +61,12 @@ public record ImageNode(
/**
* Backward-compatible convenience constructor without link/bookmark metadata.
*
- * @param name node name used in snapshots and layout graph paths
+ * @param name node name used in snapshots and layout graph paths
* @param imageData semantic image payload
- * @param width optional target width
- * @param height optional target height
- * @param padding inner padding
- * @param margin outer margin
+ * @param width optional target width
+ * @param height optional target height
+ * @param padding inner padding
+ * @param margin outer margin
*/
public ImageNode(String name,
DocumentImageData imageData,
@@ -81,14 +80,14 @@ public ImageNode(String name,
/**
* Backward-compatible convenience constructor without image fit options.
*
- * @param name node name used in snapshots and layout graph paths
- * @param imageData semantic image payload
- * @param width optional target width
- * @param height optional target height
- * @param linkOptions optional node-level link metadata
+ * @param name node name used in snapshots and layout graph paths
+ * @param imageData semantic image payload
+ * @param width optional target width
+ * @param height optional target height
+ * @param linkOptions optional node-level link metadata
* @param bookmarkOptions optional node-level bookmark metadata
- * @param padding inner padding
- * @param margin outer margin
+ * @param padding inner padding
+ * @param margin outer margin
*/
public ImageNode(String name,
DocumentImageData imageData,
@@ -105,16 +104,16 @@ public ImageNode(String name,
* Backward-compatible convenience constructor without transform — defaults
* to {@link DocumentTransform#NONE}.
*
- * @param name node name used in snapshots and layout graph paths
- * @param imageData semantic image payload
- * @param width optional target width
- * @param height optional target height
- * @param scale optional uniform scale applied when width and height are omitted
- * @param fitMode image fit policy used when drawing inside explicit bounds
- * @param linkOptions optional node-level link metadata
+ * @param name node name used in snapshots and layout graph paths
+ * @param imageData semantic image payload
+ * @param width optional target width
+ * @param height optional target height
+ * @param scale optional uniform scale applied when width and height are omitted
+ * @param fitMode image fit policy used when drawing inside explicit bounds
+ * @param linkOptions optional node-level link metadata
* @param bookmarkOptions optional node-level bookmark metadata
- * @param padding inner padding
- * @param margin outer margin
+ * @param padding inner padding
+ * @param margin outer margin
*/
public ImageNode(String name,
DocumentImageData imageData,
diff --git a/src/main/java/com/demcha/compose/document/node/InlineImageRun.java b/src/main/java/com/demcha/compose/document/node/InlineImageRun.java
index a2445e37a..97b6bfb7f 100644
--- a/src/main/java/com/demcha/compose/document/node/InlineImageRun.java
+++ b/src/main/java/com/demcha/compose/document/node/InlineImageRun.java
@@ -13,16 +13,15 @@
* can carry their own link metadata so the resulting PDF annotation covers
* the icon (or icon + label, when callers split the link across runs).
*
- * @param imageData semantic image payload; never {@code null}
- * @param width target width in points; must be finite and positive
- * @param height target height in points; must be finite and positive
- * @param alignment vertical alignment relative to the surrounding text;
- * defaults to {@link InlineImageAlignment#CENTER}
+ * @param imageData semantic image payload; never {@code null}
+ * @param width target width in points; must be finite and positive
+ * @param height target height in points; must be finite and positive
+ * @param alignment vertical alignment relative to the surrounding text;
+ * defaults to {@link InlineImageAlignment#CENTER}
* @param baselineOffset extra vertical offset in points applied after
* {@code alignment} resolution; positive values move
* the image up
- * @param linkOptions optional per-run link metadata
- *
+ * @param linkOptions optional per-run link metadata
* @author Artem Demchyshyn
*/
public record InlineImageRun(
@@ -55,8 +54,8 @@ public record InlineImageRun(
* alignment and zero offset.
*
* @param imageData image payload
- * @param width target width in points
- * @param height target height in points
+ * @param width target width in points
+ * @param height target height in points
*/
public InlineImageRun(DocumentImageData imageData, double width, double height) {
this(imageData, width, height, InlineImageAlignment.CENTER, 0.0, null);
@@ -67,8 +66,8 @@ public InlineImageRun(DocumentImageData imageData, double width, double height)
* link metadata.
*
* @param imageData image payload
- * @param width target width in points
- * @param height target height in points
+ * @param width target width in points
+ * @param height target height in points
* @param alignment vertical alignment
*/
public InlineImageRun(DocumentImageData imageData,
diff --git a/src/main/java/com/demcha/compose/document/node/InlineShapeRun.java b/src/main/java/com/demcha/compose/document/node/InlineShapeRun.java
index a2b0a6073..06237bc15 100644
--- a/src/main/java/com/demcha/compose/document/node/InlineShapeRun.java
+++ b/src/main/java/com/demcha/compose/document/node/InlineShapeRun.java
@@ -26,15 +26,14 @@
* layers overlaid and centred: a checkbox is a box layer plus an optional
* checkmark layer, each with its own colour.
*
- * @param layers one or more paint layers, drawn back-to-front and centred in the
- * run's bounding box
- * @param alignment vertical alignment relative to the surrounding text;
- * defaults to {@link InlineImageAlignment#CENTER}
+ * @param layers one or more paint layers, drawn back-to-front and centred in the
+ * run's bounding box
+ * @param alignment vertical alignment relative to the surrounding text;
+ * defaults to {@link InlineImageAlignment#CENTER}
* @param baselineOffset extra vertical offset in points applied after
* {@code alignment} resolution; positive values move the
* figure up
- * @param linkOptions optional per-run link metadata
- *
+ * @param linkOptions optional per-run link metadata
* @author Artem Demchyshyn
* @since 1.7.0
*/
@@ -63,12 +62,12 @@ public record InlineShapeRun(
/**
* Single-layer convenience constructor.
*
- * @param outline figure geometry
- * @param fill optional fill color
- * @param stroke optional outline stroke
- * @param alignment vertical alignment relative to surrounding text
+ * @param outline figure geometry
+ * @param fill optional fill color
+ * @param stroke optional outline stroke
+ * @param alignment vertical alignment relative to surrounding text
* @param baselineOffset extra vertical shift in points; positive moves up
- * @param linkOptions optional inline link metadata
+ * @param linkOptions optional inline link metadata
*/
public InlineShapeRun(ShapeOutline outline,
DocumentColor fill,
@@ -84,7 +83,7 @@ public InlineShapeRun(ShapeOutline outline,
* {@link InlineImageAlignment#CENTER} alignment and zero offset.
*
* @param outline figure geometry
- * @param fill fill color; must not be {@code null}
+ * @param fill fill color; must not be {@code null}
*/
public InlineShapeRun(ShapeOutline outline, DocumentColor fill) {
this(outline, Objects.requireNonNull(fill, "fill"), null, InlineImageAlignment.CENTER, 0.0, null);
@@ -123,9 +122,9 @@ public double height() {
* own colour. The frame is stroke-only; the checkmark, when present, is a
* smaller filled figure centred inside the frame.
*
- * @param size box width and height in points
- * @param checked whether the checkmark is shown
- * @param boxColor frame stroke color
+ * @param size box width and height in points
+ * @param checked whether the checkmark is shown
+ * @param boxColor frame stroke color
* @param checkColor checkmark fill color
* @return checkbox shape run
*/
@@ -142,10 +141,10 @@ public static InlineShapeRun checkbox(double size,
* mark is sized to fit the frame automatically; an unchecked box ignores the
* style and renders the frame alone.
*
- * @param size box width and height in points
- * @param checked whether the checkmark is shown
- * @param markStyle design of the checked-state tick
- * @param boxColor frame stroke color
+ * @param size box width and height in points
+ * @param checked whether the checkmark is shown
+ * @param markStyle design of the checked-state tick
+ * @param boxColor frame stroke color
* @param checkColor checkmark fill color
* @return checkbox shape run
* @since 1.7.0
@@ -168,11 +167,11 @@ public static InlineShapeRun checkbox(double size,
* own size, so size it to fit (≈ {@code 0.6 × size}); an unchecked box
* renders the frame alone and the {@code mark} is ignored.
*
- * @param size box width and height in points
- * @param checked whether the mark is shown
- * @param mark checked-state mark geometry, already sized; must be non-null
- * when {@code checked} is {@code true}
- * @param boxColor frame stroke color
+ * @param size box width and height in points
+ * @param checked whether the mark is shown
+ * @param mark checked-state mark geometry, already sized; must be non-null
+ * when {@code checked} is {@code true}
+ * @param boxColor frame stroke color
* @param checkColor mark fill color
* @return checkbox shape run
* @since 1.7.0
diff --git a/src/main/java/com/demcha/compose/document/node/InlineTextRun.java b/src/main/java/com/demcha/compose/document/node/InlineTextRun.java
index 661900a79..79a917e01 100644
--- a/src/main/java/com/demcha/compose/document/node/InlineTextRun.java
+++ b/src/main/java/com/demcha/compose/document/node/InlineTextRun.java
@@ -1,13 +1,12 @@
package com.demcha.compose.document.node;
-import com.demcha.compose.document.node.DocumentLinkOptions;
import com.demcha.compose.document.style.DocumentTextStyle;
/**
* One styled inline text run inside a semantic paragraph.
*
- * @param text visible text for the run
- * @param textStyle style for this run; falls back to the paragraph style when null
+ * @param text visible text for the run
+ * @param textStyle style for this run; falls back to the paragraph style when null
* @param linkOptions optional link metadata scoped only to this run
* @author Artem Demchyshyn
*/
@@ -26,7 +25,7 @@ public record InlineTextRun(
/**
* Creates a styled inline run without link metadata.
*
- * @param text visible text
+ * @param text visible text
* @param textStyle style for this run
*/
public InlineTextRun(String text, DocumentTextStyle textStyle) {
diff --git a/src/main/java/com/demcha/compose/document/node/LayerAlign.java b/src/main/java/com/demcha/compose/document/node/LayerAlign.java
index 6039688b6..3ae175183 100644
--- a/src/main/java/com/demcha/compose/document/node/LayerAlign.java
+++ b/src/main/java/com/demcha/compose/document/node/LayerAlign.java
@@ -10,22 +10,40 @@
* @author Artem Demchyshyn
*/
public enum LayerAlign {
- /** Anchored to the top-left corner of the stack box. */
+ /**
+ * Anchored to the top-left corner of the stack box.
+ */
TOP_LEFT,
- /** Centered horizontally and anchored to the top edge. */
+ /**
+ * Centered horizontally and anchored to the top edge.
+ */
TOP_CENTER,
- /** Anchored to the top-right corner of the stack box. */
+ /**
+ * Anchored to the top-right corner of the stack box.
+ */
TOP_RIGHT,
- /** Centered vertically and anchored to the left edge. */
+ /**
+ * Centered vertically and anchored to the left edge.
+ */
CENTER_LEFT,
- /** Centered both horizontally and vertically. */
+ /**
+ * Centered both horizontally and vertically.
+ */
CENTER,
- /** Centered vertically and anchored to the right edge. */
+ /**
+ * Centered vertically and anchored to the right edge.
+ */
CENTER_RIGHT,
- /** Anchored to the bottom-left corner of the stack box. */
+ /**
+ * Anchored to the bottom-left corner of the stack box.
+ */
BOTTOM_LEFT,
- /** Centered horizontally and anchored to the bottom edge. */
+ /**
+ * Centered horizontally and anchored to the bottom edge.
+ */
BOTTOM_CENTER,
- /** Anchored to the bottom-right corner of the stack box. */
+ /**
+ * Anchored to the bottom-right corner of the stack box.
+ */
BOTTOM_RIGHT
}
diff --git a/src/main/java/com/demcha/compose/document/node/LayerStackNode.java b/src/main/java/com/demcha/compose/document/node/LayerStackNode.java
index efb21e459..863657d26 100644
--- a/src/main/java/com/demcha/compose/document/node/LayerStackNode.java
+++ b/src/main/java/com/demcha/compose/document/node/LayerStackNode.java
@@ -17,10 +17,10 @@
*
Pagination is atomic: the entire stack moves to the next page when its
* measured height does not fit on the current page.
*
- * @param name node name used in snapshots and layout graph paths
- * @param layers child layers in back-to-front order
+ * @param name node name used in snapshots and layout graph paths
+ * @param layers child layers in back-to-front order
* @param padding inner padding applied around all layers
- * @param margin outer margin around the stack
+ * @param margin outer margin around the stack
* @author Artem Demchyshyn
*/
public record LayerStackNode(
@@ -74,12 +74,12 @@ public List children() {
* share a {@code zIndex} keep source order. The default is
* {@code 0} which preserves source order entirely.
*
- * @param node child node painted in this layer
- * @param align alignment of the layer inside the stack box
+ * @param node child node painted in this layer
+ * @param align alignment of the layer inside the stack box
* @param offsetX horizontal offset from the anchor (positive = right)
* @param offsetY vertical offset from the anchor (positive = down)
- * @param zIndex render-order key; higher values render on top of
- * lower values in the same parent stack/container
+ * @param zIndex render-order key; higher values render on top of
+ * lower values in the same parent stack/container
*/
public record Layer(DocumentNode node, LayerAlign align, double offsetX, double offsetY, int zIndex) {
/**
@@ -103,7 +103,7 @@ public Layer(DocumentNode node) {
/**
* Creates a layer with explicit alignment and zero offset / zero zIndex.
*
- * @param node child node
+ * @param node child node
* @param align alignment of the layer
*/
public Layer(DocumentNode node, LayerAlign align) {
@@ -115,8 +115,8 @@ public Layer(DocumentNode node, LayerAlign align) {
* shape (node + align + offsets) compiling for callers that
* pre-date Phase C.3. Defaults {@code zIndex} to {@code 0}.
*
- * @param node child node
- * @param align alignment of the layer
+ * @param node child node
+ * @param align alignment of the layer
* @param offsetX horizontal offset from the anchor
* @param offsetY vertical offset from the anchor
*/
@@ -147,7 +147,7 @@ public static Layer center(DocumentNode node) {
/**
* Convenience factory for an explicitly aligned layer with no offset.
*
- * @param node child node
+ * @param node child node
* @param align alignment of the layer
* @return aligned layer
*/
@@ -158,8 +158,8 @@ public static Layer of(DocumentNode node, LayerAlign align) {
/**
* Convenience factory for a layer positioned by anchor + screen-space offset.
*
- * @param node child node
- * @param align anchor inside the stack box
+ * @param node child node
+ * @param align anchor inside the stack box
* @param offsetX horizontal offset from the anchor (positive = right)
* @param offsetY vertical offset from the anchor (positive = down)
* @return positioned layer
diff --git a/src/main/java/com/demcha/compose/document/node/LineNode.java b/src/main/java/com/demcha/compose/document/node/LineNode.java
index 02007c201..e0c744c14 100644
--- a/src/main/java/com/demcha/compose/document/node/LineNode.java
+++ b/src/main/java/com/demcha/compose/document/node/LineNode.java
@@ -8,22 +8,22 @@
/**
* Atomic semantic line drawn inside a fixed-size box.
*
- * @param name node name used in snapshots and layout graph paths
- * @param width resolved line box width
- * @param height resolved line box height
- * @param startX line start x offset inside the box
- * @param startY line start y offset inside the box
- * @param endX line end x offset inside the box
- * @param endY line end y offset inside the box
- * @param stroke line stroke descriptor
- * @param linkOptions optional node-level link metadata
+ * @param name node name used in snapshots and layout graph paths
+ * @param width resolved line box width
+ * @param height resolved line box height
+ * @param startX line start x offset inside the box
+ * @param startY line start y offset inside the box
+ * @param endX line end x offset inside the box
+ * @param endY line end y offset inside the box
+ * @param stroke line stroke descriptor
+ * @param linkOptions optional node-level link metadata
* @param bookmarkOptions optional node-level bookmark metadata
- * @param padding inner padding
- * @param margin outer margin
- * @param transform render-time affine transform; defaults to
- * {@link DocumentTransform#NONE}.
- * @param dashPattern dash pattern for the stroke; defaults to
- * {@link DocumentDashPattern#NONE} (solid)
+ * @param padding inner padding
+ * @param margin outer margin
+ * @param transform render-time affine transform; defaults to
+ * {@link DocumentTransform#NONE}.
+ * @param dashPattern dash pattern for the stroke; defaults to
+ * {@link DocumentDashPattern#NONE} (solid)
* @author Artem Demchyshyn
*/
public record LineNode(
@@ -63,19 +63,19 @@ public record LineNode(
* Backward-compatible constructor without a dash pattern — defaults to a
* solid stroke ({@link DocumentDashPattern#NONE}).
*
- * @param name node name used in snapshots and layout graph paths
- * @param width resolved line box width
- * @param height resolved line box height
- * @param startX line start x offset inside the box
- * @param startY line start y offset inside the box
- * @param endX line end x offset inside the box
- * @param endY line end y offset inside the box
- * @param stroke line stroke descriptor
- * @param linkOptions optional node-level link metadata
+ * @param name node name used in snapshots and layout graph paths
+ * @param width resolved line box width
+ * @param height resolved line box height
+ * @param startX line start x offset inside the box
+ * @param startY line start y offset inside the box
+ * @param endX line end x offset inside the box
+ * @param endY line end y offset inside the box
+ * @param stroke line stroke descriptor
+ * @param linkOptions optional node-level link metadata
* @param bookmarkOptions optional node-level bookmark metadata
- * @param padding inner padding
- * @param margin outer margin
- * @param transform render-time affine transform
+ * @param padding inner padding
+ * @param margin outer margin
+ * @param transform render-time affine transform
*/
public LineNode(String name,
double width,
@@ -97,18 +97,18 @@ public LineNode(String name,
* Backward-compatible convenience constructor without transform — defaults
* to {@link DocumentTransform#NONE}.
*
- * @param name node name used in snapshots and layout graph paths
- * @param width resolved line box width
- * @param height resolved line box height
- * @param startX line start x offset inside the box
- * @param startY line start y offset inside the box
- * @param endX line end x offset inside the box
- * @param endY line end y offset inside the box
- * @param stroke line stroke descriptor
- * @param linkOptions optional node-level link metadata
+ * @param name node name used in snapshots and layout graph paths
+ * @param width resolved line box width
+ * @param height resolved line box height
+ * @param startX line start x offset inside the box
+ * @param startY line start y offset inside the box
+ * @param endX line end x offset inside the box
+ * @param endY line end y offset inside the box
+ * @param stroke line stroke descriptor
+ * @param linkOptions optional node-level link metadata
* @param bookmarkOptions optional node-level bookmark metadata
- * @param padding inner padding
- * @param margin outer margin
+ * @param padding inner padding
+ * @param margin outer margin
*/
public LineNode(String name,
double width,
diff --git a/src/main/java/com/demcha/compose/document/node/ListItem.java b/src/main/java/com/demcha/compose/document/node/ListItem.java
index 965d1332e..7a17a0357 100644
--- a/src/main/java/com/demcha/compose/document/node/ListItem.java
+++ b/src/main/java/com/demcha/compose/document/node/ListItem.java
@@ -16,11 +16,10 @@
* item. Direct {@code new ListItem(...)} construction is supported but
* should be reserved for record-shaped fixtures and serialization.
*
- * @param label visible item text
- * @param marker per-item marker override, or {@code null} to inherit
- * the per-depth default from the parent list
+ * @param label visible item text
+ * @param marker per-item marker override, or {@code null} to inherit
+ * the per-depth default from the parent list
* @param children nested child items, empty for leaves
- *
* @author Artem Demchyshyn
*/
public record ListItem(String label, ListMarker marker, List children) {
@@ -46,7 +45,7 @@ public static ListItem of(String label) {
* Creates an item with the given label, inherited marker, and
* child sub-tree.
*
- * @param label visible item text
+ * @param label visible item text
* @param children nested child items
* @return parent item
*/
diff --git a/src/main/java/com/demcha/compose/document/node/ListNode.java b/src/main/java/com/demcha/compose/document/node/ListNode.java
index a6242a260..43bb2b217 100644
--- a/src/main/java/com/demcha/compose/document/node/ListNode.java
+++ b/src/main/java/com/demcha/compose/document/node/ListNode.java
@@ -30,18 +30,18 @@
* are ignored. When {@code nestedItems} is empty, the node behaves
* exactly like the v1.5 flat list.
*
- * @param name optional semantic name used in snapshots and diagnostics
- * @param items item texts in source order — used when {@code nestedItems} is empty
- * @param nestedItems nested item tree, empty for flat lists
- * @param marker top-level marker rendered before each flat item
- * @param textStyle shared item text style
- * @param align horizontal alignment for item text
- * @param lineSpacing extra space between wrapped lines within one item
- * @param itemSpacing extra space between list items
+ * @param name optional semantic name used in snapshots and diagnostics
+ * @param items item texts in source order — used when {@code nestedItems} is empty
+ * @param nestedItems nested item tree, empty for flat lists
+ * @param marker top-level marker rendered before each flat item
+ * @param textStyle shared item text style
+ * @param align horizontal alignment for item text
+ * @param lineSpacing extra space between wrapped lines within one item
+ * @param itemSpacing extra space between list items
* @param continuationIndent prefix used only for wrapped continuation lines when the marker is hidden
- * @param normalizeMarkers whether leading user-supplied bullets or dashes are stripped
- * @param padding inner list padding
- * @param margin outer list margin
+ * @param normalizeMarkers whether leading user-supplied bullets or dashes are stripped
+ * @param padding inner list padding
+ * @param margin outer list margin
* @author Artem Demchyshyn
*/
public record ListNode(
@@ -83,17 +83,17 @@ public record ListNode(
* Back-compat constructor matching the v1.4 / v1.5 11-component
* signature. Treats the list as flat (no nested items).
*
- * @param name optional semantic name used in snapshots and diagnostics
- * @param items item texts in source order — used when {@code nestedItems} is empty
- * @param marker top-level marker rendered before each flat item
- * @param textStyle shared item text style
- * @param align horizontal alignment for item text
- * @param lineSpacing extra space between wrapped lines within one item
- * @param itemSpacing extra space between list items
+ * @param name optional semantic name used in snapshots and diagnostics
+ * @param items item texts in source order — used when {@code nestedItems} is empty
+ * @param marker top-level marker rendered before each flat item
+ * @param textStyle shared item text style
+ * @param align horizontal alignment for item text
+ * @param lineSpacing extra space between wrapped lines within one item
+ * @param itemSpacing extra space between list items
* @param continuationIndent prefix used only for wrapped continuation lines when the marker is hidden
- * @param normalizeMarkers whether leading user-supplied bullets or dashes are stripped
- * @param padding inner list padding
- * @param margin outer list margin
+ * @param normalizeMarkers whether leading user-supplied bullets or dashes are stripped
+ * @param padding inner list padding
+ * @param margin outer list margin
*/
public ListNode(String name,
List items,
diff --git a/src/main/java/com/demcha/compose/document/node/PageBreakNode.java b/src/main/java/com/demcha/compose/document/node/PageBreakNode.java
index 814d0fe6d..eaface920 100644
--- a/src/main/java/com/demcha/compose/document/node/PageBreakNode.java
+++ b/src/main/java/com/demcha/compose/document/node/PageBreakNode.java
@@ -9,7 +9,7 @@
* uses it as a control signal that forces subsequent content onto the next
* page.
*
- * @param name semantic name used in snapshots and diagnostics
+ * @param name semantic name used in snapshots and diagnostics
* @param margin optional surrounding spacing; {@code null} resolves to zero
*/
public record PageBreakNode(String name, DocumentInsets margin) implements DocumentNode {
@@ -17,7 +17,7 @@ public record PageBreakNode(String name, DocumentInsets margin) implements Docum
/**
* Creates a page-break node.
*
- * @param name semantic name used in snapshots and diagnostics
+ * @param name semantic name used in snapshots and diagnostics
* @param margin optional surrounding spacing; {@code null} resolves to zero
*/
public PageBreakNode {
diff --git a/src/main/java/com/demcha/compose/document/node/ParagraphNode.java b/src/main/java/com/demcha/compose/document/node/ParagraphNode.java
index 7befed545..ca831884a 100644
--- a/src/main/java/com/demcha/compose/document/node/ParagraphNode.java
+++ b/src/main/java/com/demcha/compose/document/node/ParagraphNode.java
@@ -1,7 +1,5 @@
package com.demcha.compose.document.node;
-import com.demcha.compose.document.node.DocumentBookmarkOptions;
-import com.demcha.compose.document.node.DocumentLinkOptions;
import com.demcha.compose.document.style.DocumentInsets;
import com.demcha.compose.document.style.DocumentTextAutoSize;
import com.demcha.compose.document.style.DocumentTextIndent;
@@ -13,22 +11,22 @@
/**
* Semantic paragraph block that may split across pages.
*
- * @param name node name used in snapshots and layout graph paths
- * @param text paragraph text when inline runs are not supplied
- * @param inlineRuns optional inline runs in source order; may mix text and
- * image runs and is wrapped on a single baseline
- * @param textStyle base paragraph text style
- * @param align horizontal text alignment
- * @param lineSpacing extra space between wrapped lines
- * @param bulletOffset first-line prefix used by list-style paragraph paths
- * @param indentStrategy hanging/first-line indent strategy
- * @param linkOptions optional node-level link metadata
+ * @param name node name used in snapshots and layout graph paths
+ * @param text paragraph text when inline runs are not supplied
+ * @param inlineRuns optional inline runs in source order; may mix text and
+ * image runs and is wrapped on a single baseline
+ * @param textStyle base paragraph text style
+ * @param align horizontal text alignment
+ * @param lineSpacing extra space between wrapped lines
+ * @param bulletOffset first-line prefix used by list-style paragraph paths
+ * @param indentStrategy hanging/first-line indent strategy
+ * @param linkOptions optional node-level link metadata
* @param bookmarkOptions optional node-level bookmark metadata
- * @param padding inner padding
- * @param margin outer margin
- * @param autoSize optional automatic font down-scaling policy
- * @param verticalAlign vertical seating of the text within its line box
- * ({@link TextVerticalAlign#DEFAULT} keeps baseline seating)
+ * @param padding inner padding
+ * @param margin outer margin
+ * @param autoSize optional automatic font down-scaling policy
+ * @param verticalAlign vertical seating of the text within its line box
+ * ({@link TextVerticalAlign#DEFAULT} keeps baseline seating)
* @author Artem Demchyshyn
*/
public record ParagraphNode(
@@ -80,19 +78,19 @@ public record ParagraphNode(
* Backwards-compatible 13-arg constructor without a vertical-alignment
* override; defaults {@link TextVerticalAlign#DEFAULT}.
*
- * @param name node name used in snapshots and layout graph paths
- * @param text paragraph text when inline runs are not supplied
- * @param inlineRuns optional inline runs in source order
- * @param textStyle base paragraph text style
- * @param align horizontal text alignment
- * @param lineSpacing extra space between wrapped lines
- * @param bulletOffset first-line prefix used by list-style paragraph paths
- * @param indentStrategy hanging/first-line indent strategy
- * @param linkOptions optional node-level link metadata
+ * @param name node name used in snapshots and layout graph paths
+ * @param text paragraph text when inline runs are not supplied
+ * @param inlineRuns optional inline runs in source order
+ * @param textStyle base paragraph text style
+ * @param align horizontal text alignment
+ * @param lineSpacing extra space between wrapped lines
+ * @param bulletOffset first-line prefix used by list-style paragraph paths
+ * @param indentStrategy hanging/first-line indent strategy
+ * @param linkOptions optional node-level link metadata
* @param bookmarkOptions optional node-level bookmark metadata
- * @param padding inner padding
- * @param margin outer margin
- * @param autoSize optional automatic font down-scaling policy
+ * @param padding inner padding
+ * @param margin outer margin
+ * @param autoSize optional automatic font down-scaling policy
*/
public ParagraphNode(String name,
String text,
@@ -114,19 +112,19 @@ public ParagraphNode(String name,
/**
* Backwards-compatible 12-arg canonical constructor without auto-size.
*
- * @param name node name used in snapshots and layout graph paths
- * @param text paragraph text when inline runs are not supplied
- * @param inlineRuns optional inline runs in source order; may mix text and
- * image runs and is wrapped on a single baseline
- * @param textStyle base paragraph text style
- * @param align horizontal text alignment
- * @param lineSpacing extra space between wrapped lines
- * @param bulletOffset first-line prefix used by list-style paragraph paths
- * @param indentStrategy hanging/first-line indent strategy
- * @param linkOptions optional node-level link metadata
+ * @param name node name used in snapshots and layout graph paths
+ * @param text paragraph text when inline runs are not supplied
+ * @param inlineRuns optional inline runs in source order; may mix text and
+ * image runs and is wrapped on a single baseline
+ * @param textStyle base paragraph text style
+ * @param align horizontal text alignment
+ * @param lineSpacing extra space between wrapped lines
+ * @param bulletOffset first-line prefix used by list-style paragraph paths
+ * @param indentStrategy hanging/first-line indent strategy
+ * @param linkOptions optional node-level link metadata
* @param bookmarkOptions optional node-level bookmark metadata
- * @param padding inner padding
- * @param margin outer margin
+ * @param padding inner padding
+ * @param margin outer margin
*/
public ParagraphNode(String name,
String text,
@@ -147,17 +145,17 @@ public ParagraphNode(String name,
/**
* Creates a paragraph from plain text with optional link and bookmark metadata.
*
- * @param name node name used in snapshots and layout graph paths
- * @param text paragraph text
- * @param textStyle paragraph style
- * @param align horizontal alignment
- * @param lineSpacing extra spacing between wrapped lines
- * @param bulletOffset first-line marker or prefix
- * @param indentStrategy text indent strategy
- * @param linkOptions optional link metadata
+ * @param name node name used in snapshots and layout graph paths
+ * @param text paragraph text
+ * @param textStyle paragraph style
+ * @param align horizontal alignment
+ * @param lineSpacing extra spacing between wrapped lines
+ * @param bulletOffset first-line marker or prefix
+ * @param indentStrategy text indent strategy
+ * @param linkOptions optional link metadata
* @param bookmarkOptions optional bookmark metadata
- * @param padding inner padding
- * @param margin outer margin
+ * @param padding inner padding
+ * @param margin outer margin
*/
public ParagraphNode(String name,
String text,
@@ -176,15 +174,15 @@ public ParagraphNode(String name,
/**
* Creates a paragraph from plain text without link or bookmark metadata.
*
- * @param name node name used in snapshots and layout graph paths
- * @param text paragraph text
- * @param textStyle paragraph style
- * @param align horizontal alignment
- * @param lineSpacing extra spacing between wrapped lines
- * @param bulletOffset first-line marker or prefix
+ * @param name node name used in snapshots and layout graph paths
+ * @param text paragraph text
+ * @param textStyle paragraph style
+ * @param align horizontal alignment
+ * @param lineSpacing extra spacing between wrapped lines
+ * @param bulletOffset first-line marker or prefix
* @param indentStrategy text indent strategy
- * @param padding inner padding
- * @param margin outer margin
+ * @param padding inner padding
+ * @param margin outer margin
*/
public ParagraphNode(String name,
String text,
@@ -201,13 +199,13 @@ public ParagraphNode(String name,
/**
* Creates a paragraph without marker indentation.
*
- * @param name node name used in snapshots and layout graph paths
- * @param text paragraph text
- * @param textStyle paragraph style
- * @param align horizontal alignment
+ * @param name node name used in snapshots and layout graph paths
+ * @param text paragraph text
+ * @param textStyle paragraph style
+ * @param align horizontal alignment
* @param lineSpacing extra spacing between wrapped lines
- * @param padding inner padding
- * @param margin outer margin
+ * @param padding inner padding
+ * @param margin outer margin
*/
public ParagraphNode(String name,
String text,
@@ -219,6 +217,23 @@ public ParagraphNode(String name,
this(name, text, textStyle, align, lineSpacing, "", DocumentTextIndent.NONE, null, null, padding, margin);
}
+ private static List normalizeInlineRuns(List runs) {
+ if (runs == null || runs.isEmpty()) {
+ return List.of();
+ }
+ List normalized = new java.util.ArrayList<>(runs.size());
+ for (InlineRun run : runs) {
+ if (run == null) {
+ continue;
+ }
+ if (run instanceof InlineTextRun textRun && textRun.text().isEmpty()) {
+ continue;
+ }
+ normalized.add(run);
+ }
+ return List.copyOf(normalized);
+ }
+
/**
* Returns inline text runs in source order, filtering out image runs.
*
@@ -240,23 +255,6 @@ public List inlineTextRuns() {
}
return List.copyOf(textRuns);
}
-
- private static List normalizeInlineRuns(List runs) {
- if (runs == null || runs.isEmpty()) {
- return List.of();
- }
- List normalized = new java.util.ArrayList<>(runs.size());
- for (InlineRun run : runs) {
- if (run == null) {
- continue;
- }
- if (run instanceof InlineTextRun textRun && textRun.text().isEmpty()) {
- continue;
- }
- normalized.add(run);
- }
- return List.copyOf(normalized);
- }
}
diff --git a/src/main/java/com/demcha/compose/document/node/PolygonNode.java b/src/main/java/com/demcha/compose/document/node/PolygonNode.java
index 258017e28..f75fc7e3d 100644
--- a/src/main/java/com/demcha/compose/document/node/PolygonNode.java
+++ b/src/main/java/com/demcha/compose/document/node/PolygonNode.java
@@ -19,15 +19,14 @@
* tomorrow. It renders through the existing polygon fragment pipeline — no
* backend gains any new handler for it.
*
- * @param name node name used in snapshots and layout graph paths
- * @param width resolved box width
- * @param height resolved box height
- * @param points normalized vertices in draw order; at least three
+ * @param name node name used in snapshots and layout graph paths
+ * @param width resolved box width
+ * @param height resolved box height
+ * @param points normalized vertices in draw order; at least three
* @param fillColor optional fill colour
- * @param stroke optional outline stroke
- * @param padding inner padding
- * @param margin outer margin
- *
+ * @param stroke optional outline stroke
+ * @param padding inner padding
+ * @param margin outer margin
* @author Artem Demchyshyn
* @since 1.8.0
*/
@@ -41,7 +40,9 @@ public record PolygonNode(
DocumentInsets padding,
DocumentInsets margin
) implements DocumentNode {
- /** Validates dimensions and the vertex list; copy-protects the vertices. */
+ /**
+ * Validates dimensions and the vertex list; copy-protects the vertices.
+ */
public PolygonNode {
name = name == null ? "" : name;
Objects.requireNonNull(points, "points");
diff --git a/src/main/java/com/demcha/compose/document/node/RowNode.java b/src/main/java/com/demcha/compose/document/node/RowNode.java
index 70309cff9..d0899d21e 100644
--- a/src/main/java/com/demcha/compose/document/node/RowNode.java
+++ b/src/main/java/com/demcha/compose/document/node/RowNode.java
@@ -1,10 +1,6 @@
package com.demcha.compose.document.node;
-import com.demcha.compose.document.style.DocumentBorders;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentCornerRadius;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
+import com.demcha.compose.document.style.*;
import java.util.List;
import java.util.Objects;
@@ -23,17 +19,16 @@
* {@link ContainerNode}) acting as columns. Nested rows and tables are
* disallowed at the DSL boundary.
*
- * @param name node name used in snapshots and layout graph paths
- * @param children child semantic nodes in source order
- * @param weights optional per-child weights (length must match children, or be empty)
- * @param gap horizontal gap between children
- * @param padding inner padding
- * @param margin outer margin
- * @param fillColor optional background fill
- * @param stroke optional border stroke
+ * @param name node name used in snapshots and layout graph paths
+ * @param children child semantic nodes in source order
+ * @param weights optional per-child weights (length must match children, or be empty)
+ * @param gap horizontal gap between children
+ * @param padding inner padding
+ * @param margin outer margin
+ * @param fillColor optional background fill
+ * @param stroke optional border stroke
* @param cornerRadius optional render-only corner radius
- * @param borders optional per-side border strokes overriding the uniform stroke
- *
+ * @param borders optional per-side border strokes overriding the uniform stroke
* @author Artem Demchyshyn
*/
public record RowNode(
@@ -58,7 +53,7 @@ public record RowNode(
weights = weights == null ? List.of() : List.copyOf(weights);
if (!weights.isEmpty() && weights.size() != children.size()) {
throw new IllegalArgumentException("RowNode weights size " + weights.size()
- + " does not match children size " + children.size());
+ + " does not match children size " + children.size());
}
for (Double weight : weights) {
if (weight == null || Double.isNaN(weight) || Double.isInfinite(weight) || weight <= 0.0) {
@@ -77,14 +72,14 @@ public record RowNode(
/**
* Backwards-compatible constructor without per-side borders.
*
- * @param name node name used in snapshots and layout graph paths
- * @param children child semantic nodes in source order
- * @param weights optional per-child weights (length must match children, or be empty)
- * @param gap horizontal gap between children
- * @param padding inner padding
- * @param margin outer margin
- * @param fillColor optional background fill
- * @param stroke optional border stroke
+ * @param name node name used in snapshots and layout graph paths
+ * @param children child semantic nodes in source order
+ * @param weights optional per-child weights (length must match children, or be empty)
+ * @param gap horizontal gap between children
+ * @param padding inner padding
+ * @param margin outer margin
+ * @param fillColor optional background fill
+ * @param stroke optional border stroke
* @param cornerRadius optional render-only corner radius
*/
public RowNode(String name,
diff --git a/src/main/java/com/demcha/compose/document/node/SectionNode.java b/src/main/java/com/demcha/compose/document/node/SectionNode.java
index 51e651ecf..f9aa0e3f4 100644
--- a/src/main/java/com/demcha/compose/document/node/SectionNode.java
+++ b/src/main/java/com/demcha/compose/document/node/SectionNode.java
@@ -1,10 +1,6 @@
package com.demcha.compose.document.node;
-import com.demcha.compose.document.style.DocumentBorders;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentCornerRadius;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
+import com.demcha.compose.document.style.*;
import java.util.List;
import java.util.Objects;
@@ -12,19 +8,18 @@
/**
* Vertical semantic section node.
*
- * @param name node name used in snapshots and layout graph paths
- * @param children child semantic nodes in source order
- * @param spacing vertical spacing between children
- * @param padding inner padding
- * @param margin outer margin
- * @param fillColor optional background fill
- * @param stroke optional uniform border stroke
+ * @param name node name used in snapshots and layout graph paths
+ * @param children child semantic nodes in source order
+ * @param spacing vertical spacing between children
+ * @param padding inner padding
+ * @param margin outer margin
+ * @param fillColor optional background fill
+ * @param stroke optional uniform border stroke
* @param cornerRadius optional render-only corner radius
- * @param borders optional per-side border strokes overriding the uniform stroke
+ * @param borders optional per-side border strokes overriding the uniform stroke
* @param keepTogether when {@code true}, the section relocates whole to the next
* page instead of orphaning its leading children when it does
* not fit in the remaining page space (and fits on a fresh page)
- *
* @author Artem Demchyshyn
*/
public record SectionNode(
@@ -59,15 +54,15 @@ public record SectionNode(
* Backward-compatible constructor without the keep-together flag (defaults to
* normal flow).
*
- * @param name node name
- * @param children child nodes
- * @param spacing vertical spacing
- * @param padding inner padding
- * @param margin outer margin
- * @param fillColor optional background fill
- * @param stroke optional uniform border stroke
+ * @param name node name
+ * @param children child nodes
+ * @param spacing vertical spacing
+ * @param padding inner padding
+ * @param margin outer margin
+ * @param fillColor optional background fill
+ * @param stroke optional uniform border stroke
* @param cornerRadius optional render-only corner radius
- * @param borders optional per-side borders
+ * @param borders optional per-side borders
*/
public SectionNode(String name,
List children,
@@ -84,13 +79,13 @@ public SectionNode(String name,
/**
* Creates a vertical semantic section without per-side borders.
*
- * @param name node name used in snapshots and layout graph paths
- * @param children child semantic nodes in source order
- * @param spacing vertical spacing between children
- * @param padding inner padding
- * @param margin outer margin
- * @param fillColor optional background fill
- * @param stroke optional uniform border stroke
+ * @param name node name used in snapshots and layout graph paths
+ * @param children child semantic nodes in source order
+ * @param spacing vertical spacing between children
+ * @param padding inner padding
+ * @param margin outer margin
+ * @param fillColor optional background fill
+ * @param stroke optional uniform border stroke
* @param cornerRadius optional render-only corner radius
*/
public SectionNode(String name,
@@ -107,13 +102,13 @@ public SectionNode(String name,
/**
* Creates a vertical semantic section with square corners and no per-side borders.
*
- * @param name node name used in snapshots and layout graph paths
- * @param children child semantic nodes in source order
- * @param spacing vertical spacing between children
- * @param padding inner padding
- * @param margin outer margin
+ * @param name node name used in snapshots and layout graph paths
+ * @param children child semantic nodes in source order
+ * @param spacing vertical spacing between children
+ * @param padding inner padding
+ * @param margin outer margin
* @param fillColor optional background fill
- * @param stroke optional uniform border stroke
+ * @param stroke optional uniform border stroke
*/
public SectionNode(String name,
List children,
diff --git a/src/main/java/com/demcha/compose/document/node/ShapeContainerNode.java b/src/main/java/com/demcha/compose/document/node/ShapeContainerNode.java
index 1ffc771da..74f282619 100644
--- a/src/main/java/com/demcha/compose/document/node/ShapeContainerNode.java
+++ b/src/main/java/com/demcha/compose/document/node/ShapeContainerNode.java
@@ -1,11 +1,6 @@
package com.demcha.compose.document.node;
-import com.demcha.compose.document.style.ClipPolicy;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTransform;
-import com.demcha.compose.document.style.ShapeOutline;
+import com.demcha.compose.document.style.*;
import java.util.ArrayList;
import java.util.List;
@@ -32,23 +27,22 @@
*
Pagination is atomic: the outline plus all of its layers stays on the
* same page or moves to the next as one unit.
*
- * @param name node name used in snapshots and layout graph paths
- * @param outline geometric outline that drives the bounding box
- * @param layers child layers in back-to-front order; must contain at least one
+ * @param name node name used in snapshots and layout graph paths
+ * @param outline geometric outline that drives the bounding box
+ * @param layers child layers in back-to-front order; must contain at least one
* @param clipPolicy how children are clipped relative to the outline
- * @param fillColor optional outline fill colour
- * @param stroke optional outline stroke
- * @param padding inner padding applied around all layers (subtracted from outline)
- * @param margin outer margin around the container
- * @param transform render-time affine transform (rotation around the
- * placement centre and/or scaling) applied to the
- * outline + layers as a single unit; defaults to
- * {@link DocumentTransform#NONE}. The canonical layout
- * layer measures and places the node against its
- * natural bounding box — backends apply the transform
- * during render so layout snapshots stay deterministic
- * regardless of rotation/scale.
- *
+ * @param fillColor optional outline fill colour
+ * @param stroke optional outline stroke
+ * @param padding inner padding applied around all layers (subtracted from outline)
+ * @param margin outer margin around the container
+ * @param transform render-time affine transform (rotation around the
+ * placement centre and/or scaling) applied to the
+ * outline + layers as a single unit; defaults to
+ * {@link DocumentTransform#NONE}. The canonical layout
+ * layer measures and places the node against its
+ * natural bounding box — backends apply the transform
+ * during render so layout snapshots stay deterministic
+ * regardless of rotation/scale.
* @author Artem Demchyshyn
*/
public record ShapeContainerNode(
@@ -68,14 +62,14 @@ public record ShapeContainerNode(
* {@link DocumentTransform#NONE}. Lets existing callers built before
* Phase C compile without changes.
*
- * @param name node name used in snapshots and layout graph paths
- * @param outline geometric outline that drives the bounding box
- * @param layers child layers in back-to-front order
+ * @param name node name used in snapshots and layout graph paths
+ * @param outline geometric outline that drives the bounding box
+ * @param layers child layers in back-to-front order
* @param clipPolicy how children are clipped relative to the outline
- * @param fillColor optional outline fill colour
- * @param stroke optional outline stroke
- * @param padding inner padding applied around all layers
- * @param margin outer margin around the container
+ * @param fillColor optional outline fill colour
+ * @param stroke optional outline stroke
+ * @param padding inner padding applied around all layers
+ * @param margin outer margin around the container
*/
public ShapeContainerNode(String name,
ShapeOutline outline,
@@ -119,8 +113,8 @@ public ShapeContainerNode(String name,
/**
* @return ordered child node references — equivalent to
- * {@code layers.stream().map(Layer::node)}, kept aligned with
- * {@link DocumentNode#children()}'s contract
+ * {@code layers.stream().map(Layer::node)}, kept aligned with
+ * {@link DocumentNode#children()}'s contract
*/
@Override
public List children() {
diff --git a/src/main/java/com/demcha/compose/document/node/ShapeLayer.java b/src/main/java/com/demcha/compose/document/node/ShapeLayer.java
index 54aafafc4..644374619 100644
--- a/src/main/java/com/demcha/compose/document/node/ShapeLayer.java
+++ b/src/main/java/com/demcha/compose/document/node/ShapeLayer.java
@@ -17,9 +17,8 @@
*
* @param outline figure geometry; its {@link ShapeOutline#width()} /
* {@link ShapeOutline#height()} size this layer
- * @param fill optional fill color; {@code null} leaves the interior empty
- * @param stroke optional outline stroke; {@code null} leaves no border
- *
+ * @param fill optional fill color; {@code null} leaves the interior empty
+ * @param stroke optional outline stroke; {@code null} leaves no border
* @author Artem Demchyshyn
* @since 1.7.0
*/
@@ -38,7 +37,7 @@ public record ShapeLayer(ShapeOutline outline, DocumentColor fill, DocumentStrok
* Creates a filled layer with no stroke.
*
* @param outline figure geometry
- * @param fill fill color; must not be {@code null}
+ * @param fill fill color; must not be {@code null}
*/
public ShapeLayer(ShapeOutline outline, DocumentColor fill) {
this(outline, Objects.requireNonNull(fill, "fill"), null);
diff --git a/src/main/java/com/demcha/compose/document/node/ShapeNode.java b/src/main/java/com/demcha/compose/document/node/ShapeNode.java
index ae4e0cdc8..bb833ad8a 100644
--- a/src/main/java/com/demcha/compose/document/node/ShapeNode.java
+++ b/src/main/java/com/demcha/compose/document/node/ShapeNode.java
@@ -1,37 +1,31 @@
package com.demcha.compose.document.node;
-import com.demcha.compose.document.style.DocumentColor;
-import com.demcha.compose.document.style.DocumentCornerRadius;
-import com.demcha.compose.document.style.DocumentInsets;
-import com.demcha.compose.document.style.DocumentPaint;
-import com.demcha.compose.document.style.DocumentStroke;
-import com.demcha.compose.document.style.DocumentTransform;
+import com.demcha.compose.document.style.*;
-import java.awt.Color;
+import java.awt.*;
/**
* Atomic rectangle-like semantic shape.
*
- * @param name node name used in snapshots and layout graph paths
- * @param width resolved shape width
- * @param height resolved shape height
- * @param fillColor optional fill color
- * @param stroke optional stroke descriptor
- * @param cornerRadius optional render-only corner radius
- * @param linkOptions optional node-level link metadata
+ * @param name node name used in snapshots and layout graph paths
+ * @param width resolved shape width
+ * @param height resolved shape height
+ * @param fillColor optional fill color
+ * @param stroke optional stroke descriptor
+ * @param cornerRadius optional render-only corner radius
+ * @param linkOptions optional node-level link metadata
* @param bookmarkOptions optional node-level bookmark metadata
- * @param padding inner padding
- * @param margin outer margin
- * @param transform render-time affine transform (rotation around the
- * placement centre and/or scaling); defaults to
- * {@link DocumentTransform#NONE}. Layout snapshots stay
- * deterministic regardless of rotation/scale — backends
- * apply the transform during render only.
- * @param fillPaint optional paint fill; when set it wins over
- * {@code fillColor}. Gradients render as native shadings in
- * the PDF backend; backends without shading support fall
- * back to {@link DocumentPaint#primaryColor()}.
- *
+ * @param padding inner padding
+ * @param margin outer margin
+ * @param transform render-time affine transform (rotation around the
+ * placement centre and/or scaling); defaults to
+ * {@link DocumentTransform#NONE}. Layout snapshots stay
+ * deterministic regardless of rotation/scale — backends
+ * apply the transform during render only.
+ * @param fillPaint optional paint fill; when set it wins over
+ * {@code fillColor}. Gradients render as native shadings in
+ * the PDF backend; backends without shading support fall
+ * back to {@link DocumentPaint#primaryColor()}.
* @author Artem Demchyshyn
*/
public record ShapeNode(
@@ -51,17 +45,17 @@ public record ShapeNode(
/**
* Backwards-compatible canonical constructor without a paint fill.
*
- * @param name node name used in snapshots and layout graph paths
- * @param width resolved shape width
- * @param height resolved shape height
- * @param fillColor optional fill color
- * @param stroke optional stroke descriptor
- * @param cornerRadius optional render-only corner radius
- * @param linkOptions optional node-level link metadata
+ * @param name node name used in snapshots and layout graph paths
+ * @param width resolved shape width
+ * @param height resolved shape height
+ * @param fillColor optional fill color
+ * @param stroke optional stroke descriptor
+ * @param cornerRadius optional render-only corner radius
+ * @param linkOptions optional node-level link metadata
* @param bookmarkOptions optional node-level bookmark metadata
- * @param padding inner padding
- * @param margin outer margin
- * @param transform render-time affine transform
+ * @param padding inner padding
+ * @param margin outer margin
+ * @param transform render-time affine transform
*/
public ShapeNode(String name,
double width,
@@ -98,13 +92,13 @@ public ShapeNode(String name,
/**
* Backward-compatible convenience constructor without link/bookmark metadata.
*
- * @param name node name used in snapshots and layout graph paths
- * @param width resolved shape width
- * @param height resolved shape height
+ * @param name node name used in snapshots and layout graph paths
+ * @param width resolved shape width
+ * @param height resolved shape height
* @param fillColor optional fill color
- * @param stroke optional stroke descriptor
- * @param padding inner padding
- * @param margin outer margin
+ * @param stroke optional stroke descriptor
+ * @param padding inner padding
+ * @param margin outer margin
*/
public ShapeNode(String name,
double width,
@@ -120,15 +114,15 @@ public ShapeNode(String name,
/**
* Backward-compatible convenience constructor without corner radius.
*
- * @param name node name used in snapshots and layout graph paths
- * @param width resolved shape width
- * @param height resolved shape height
- * @param fillColor optional fill color
- * @param stroke optional stroke descriptor
- * @param linkOptions optional node-level link metadata
+ * @param name node name used in snapshots and layout graph paths
+ * @param width resolved shape width
+ * @param height resolved shape height
+ * @param fillColor optional fill color
+ * @param stroke optional stroke descriptor
+ * @param linkOptions optional node-level link metadata
* @param bookmarkOptions optional node-level bookmark metadata
- * @param padding inner padding
- * @param margin outer margin
+ * @param padding inner padding
+ * @param margin outer margin
*/
public ShapeNode(String name,
double width,
@@ -146,16 +140,16 @@ public ShapeNode(String name,
* Backward-compatible convenience constructor without transform — defaults
* to {@link DocumentTransform#NONE}.
*
- * @param name node name used in snapshots and layout graph paths
- * @param width resolved shape width
- * @param height resolved shape height
- * @param fillColor optional fill color
- * @param stroke optional stroke descriptor
- * @param cornerRadius optional render-only corner radius
- * @param linkOptions optional node-level link metadata
+ * @param name node name used in snapshots and layout graph paths
+ * @param width resolved shape width
+ * @param height resolved shape height
+ * @param fillColor optional fill color
+ * @param stroke optional stroke descriptor
+ * @param cornerRadius optional render-only corner radius
+ * @param linkOptions optional node-level link metadata
* @param bookmarkOptions optional node-level bookmark metadata
- * @param padding inner padding
- * @param margin outer margin
+ * @param padding inner padding
+ * @param margin outer margin
*/
public ShapeNode(String name,
double width,
diff --git a/src/main/java/com/demcha/compose/document/node/SpacerNode.java b/src/main/java/com/demcha/compose/document/node/SpacerNode.java
index 538a9f93c..b643b83c9 100644
--- a/src/main/java/com/demcha/compose/document/node/SpacerNode.java
+++ b/src/main/java/com/demcha/compose/document/node/SpacerNode.java
@@ -5,11 +5,11 @@
/**
* Invisible fixed-size semantic spacer.
*
- * @param name node name used in snapshots and layout graph paths
- * @param width spacer width contribution
- * @param height spacer height contribution
+ * @param name node name used in snapshots and layout graph paths
+ * @param width spacer width contribution
+ * @param height spacer height contribution
* @param padding inner padding
- * @param margin outer margin
+ * @param margin outer margin
* @author Artem Demchyshyn
*/
public record SpacerNode(
diff --git a/src/main/java/com/demcha/compose/document/node/TableNode.java b/src/main/java/com/demcha/compose/document/node/TableNode.java
index 671078c3a..7c86bf021 100644
--- a/src/main/java/com/demcha/compose/document/node/TableNode.java
+++ b/src/main/java/com/demcha/compose/document/node/TableNode.java
@@ -1,7 +1,5 @@
package com.demcha.compose.document.node;
-import com.demcha.compose.document.node.DocumentBookmarkOptions;
-import com.demcha.compose.document.node.DocumentLinkOptions;
import com.demcha.compose.document.style.DocumentInsets;
import com.demcha.compose.document.table.DocumentTableCell;
import com.demcha.compose.document.table.DocumentTableColumn;
@@ -15,17 +13,17 @@
/**
* Semantic table node with row-atomic pagination.
*
- * @param name table node name used in snapshots and layout graph paths
- * @param columns negotiated table columns
- * @param rows table rows in source order
- * @param defaultCellStyle default style applied to cells without overrides
- * @param rowStyles row-specific style overrides
- * @param columnStyles column-specific style overrides
- * @param width optional explicit table width
- * @param linkOptions optional node-level link metadata
- * @param bookmarkOptions optional node-level bookmark metadata
- * @param padding outer table padding
- * @param margin outer table margin
+ * @param name table node name used in snapshots and layout graph paths
+ * @param columns negotiated table columns
+ * @param rows table rows in source order
+ * @param defaultCellStyle default style applied to cells without overrides
+ * @param rowStyles row-specific style overrides
+ * @param columnStyles column-specific style overrides
+ * @param width optional explicit table width
+ * @param linkOptions optional node-level link metadata
+ * @param bookmarkOptions optional node-level bookmark metadata
+ * @param padding outer table padding
+ * @param margin outer table margin
* @param repeatedHeaderRowCount number of leading rows to repeat at the
* top of every continuation page when the
* table is split across pages; {@code 0}
@@ -50,13 +48,13 @@ public record TableNode(
* authoring shape for callers that do not need row-level or column-level
* style overrides.
*
- * @param name table node name used in snapshots and layout graph paths
- * @param columns negotiated table columns
- * @param rows table rows in source order
+ * @param name table node name used in snapshots and layout graph paths
+ * @param columns negotiated table columns
+ * @param rows table rows in source order
* @param defaultCellStyle default cell style applied to every cell
- * @param width optional explicit table width
- * @param padding outer table padding
- * @param margin outer table margin
+ * @param width optional explicit table width
+ * @param padding outer table padding
+ * @param margin outer table margin
*/
public TableNode(String name,
List columns,
@@ -72,15 +70,15 @@ public TableNode(String name,
* Backward-compatible constructor that retains row and column style
* overrides without content-scoped PDF metadata.
*
- * @param name table node name used in snapshots and layout graph paths
- * @param columns negotiated table columns
- * @param rows table rows in source order
+ * @param name table node name used in snapshots and layout graph paths
+ * @param columns negotiated table columns
+ * @param rows table rows in source order
* @param defaultCellStyle default cell style applied to every cell
- * @param rowStyles row-specific style overrides
- * @param columnStyles column-specific style overrides
- * @param width optional explicit table width
- * @param padding outer table padding
- * @param margin outer table margin
+ * @param rowStyles row-specific style overrides
+ * @param columnStyles column-specific style overrides
+ * @param width optional explicit table width
+ * @param padding outer table padding
+ * @param margin outer table margin
*/
public TableNode(String name,
List columns,
@@ -98,17 +96,17 @@ public TableNode(String name,
* Backward-compatible 11-arg constructor (pre-Phase D.3) that defaults
* {@code repeatedHeaderRowCount} to {@code 0}.
*
- * @param name table node name used in snapshots and layout graph paths
- * @param columns negotiated table columns
- * @param rows table rows in source order
+ * @param name table node name used in snapshots and layout graph paths
+ * @param columns negotiated table columns
+ * @param rows table rows in source order
* @param defaultCellStyle default cell style applied to every cell
- * @param rowStyles row-specific style overrides
- * @param columnStyles column-specific style overrides
- * @param width optional explicit table width
- * @param linkOptions optional node-level link metadata
- * @param bookmarkOptions optional node-level bookmark metadata
- * @param padding outer table padding
- * @param margin outer table margin
+ * @param rowStyles row-specific style overrides
+ * @param columnStyles column-specific style overrides
+ * @param width optional explicit table width
+ * @param linkOptions optional node-level link metadata
+ * @param bookmarkOptions optional node-level bookmark metadata
+ * @param padding outer table padding
+ * @param margin outer table margin
*/
public TableNode(String name,
List columns,
@@ -150,7 +148,7 @@ public TableNode(String name,
if (repeatedHeaderRowCount > rows.size()) {
throw new IllegalArgumentException(
"repeatedHeaderRowCount " + repeatedHeaderRowCount
- + " exceeds row count " + rows.size() + ".");
+ + " exceeds row count " + rows.size() + ".");
}
}
diff --git a/src/main/java/com/demcha/compose/document/node/TextVerticalAlign.java b/src/main/java/com/demcha/compose/document/node/TextVerticalAlign.java
index d9352c41c..f10f15359 100644
--- a/src/main/java/com/demcha/compose/document/node/TextVerticalAlign.java
+++ b/src/main/java/com/demcha/compose/document/node/TextVerticalAlign.java
@@ -21,13 +21,19 @@
*/
public enum TextVerticalAlign {
- /** Engine default baseline seating — unchanged from pre-1.7.0 behaviour. */
+ /**
+ * Engine default baseline seating — unchanged from pre-1.7.0 behaviour.
+ */
DEFAULT,
- /** Seat the cap top at the top of the line box (text hugs the top). */
+ /**
+ * Seat the cap top at the top of the line box (text hugs the top).
+ */
TOP,
- /** Optically centre the text by cap height within its line box. */
+ /**
+ * Optically centre the text by cap height within its line box.
+ */
CENTER,
/**
diff --git a/src/main/java/com/demcha/compose/document/output/DocumentHeaderFooterZone.java b/src/main/java/com/demcha/compose/document/output/DocumentHeaderFooterZone.java
index b8b3b983b..115fe135e 100644
--- a/src/main/java/com/demcha/compose/document/output/DocumentHeaderFooterZone.java
+++ b/src/main/java/com/demcha/compose/document/output/DocumentHeaderFooterZone.java
@@ -6,8 +6,12 @@
* @author Artem Demchyshyn
*/
public enum DocumentHeaderFooterZone {
- /** Top-of-page header zone. */
+ /**
+ * Top-of-page header zone.
+ */
HEADER,
- /** Bottom-of-page footer zone. */
+ /**
+ * Bottom-of-page footer zone.
+ */
FOOTER
}
diff --git a/src/main/java/com/demcha/compose/document/output/DocumentOutputOptions.java b/src/main/java/com/demcha/compose/document/output/DocumentOutputOptions.java
index 6324891dd..36143b295 100644
--- a/src/main/java/com/demcha/compose/document/output/DocumentOutputOptions.java
+++ b/src/main/java/com/demcha/compose/document/output/DocumentOutputOptions.java
@@ -12,11 +12,10 @@
* into their native representations; backends that cannot honour a particular
* option simply ignore it.
*
- * @param metadata document information (title, author, ...)
- * @param watermark optional document-wide watermark
- * @param protection optional access protection
+ * @param metadata document information (title, author, ...)
+ * @param watermark optional document-wide watermark
+ * @param protection optional access protection
* @param headersAndFooters repeating header/footer entries
- *
* @author Artem Demchyshyn
*/
public record DocumentOutputOptions(
@@ -25,7 +24,9 @@ public record DocumentOutputOptions(
DocumentProtection protection,
List headersAndFooters
) {
- /** All-empty defaults. */
+ /**
+ * All-empty defaults.
+ */
public static final DocumentOutputOptions EMPTY = new DocumentOutputOptions(null, null, null, List.of());
/**
diff --git a/src/main/java/com/demcha/compose/document/output/DocumentWatermarkLayer.java b/src/main/java/com/demcha/compose/document/output/DocumentWatermarkLayer.java
index 5b35b57e5..6c04140e7 100644
--- a/src/main/java/com/demcha/compose/document/output/DocumentWatermarkLayer.java
+++ b/src/main/java/com/demcha/compose/document/output/DocumentWatermarkLayer.java
@@ -6,8 +6,12 @@
* @author Artem Demchyshyn
*/
public enum DocumentWatermarkLayer {
- /** Watermark renders behind page content. */
+ /**
+ * Watermark renders behind page content.
+ */
BEHIND_CONTENT,
- /** Watermark renders on top of page content. */
+ /**
+ * Watermark renders on top of page content.
+ */
ABOVE_CONTENT
}
diff --git a/src/main/java/com/demcha/compose/document/output/DocumentWatermarkPosition.java b/src/main/java/com/demcha/compose/document/output/DocumentWatermarkPosition.java
index 02189f794..f83a0ebea 100644
--- a/src/main/java/com/demcha/compose/document/output/DocumentWatermarkPosition.java
+++ b/src/main/java/com/demcha/compose/document/output/DocumentWatermarkPosition.java
@@ -8,16 +8,28 @@
* @author Artem Demchyshyn
*/
public enum DocumentWatermarkPosition {
- /** Single watermark centred on the page. */
+ /**
+ * Single watermark centred on the page.
+ */
CENTER,
- /** Single watermark anchored to the top-left corner. */
+ /**
+ * Single watermark anchored to the top-left corner.
+ */
TOP_LEFT,
- /** Single watermark anchored to the top-right corner. */
+ /**
+ * Single watermark anchored to the top-right corner.
+ */
TOP_RIGHT,
- /** Single watermark anchored to the bottom-left corner. */
+ /**
+ * Single watermark anchored to the bottom-left corner.
+ */
BOTTOM_LEFT,
- /** Single watermark anchored to the bottom-right corner. */
+ /**
+ * Single watermark anchored to the bottom-right corner.
+ */
BOTTOM_RIGHT,
- /** Repeated tiled watermark pattern across the page. */
+ /**
+ * Repeated tiled watermark pattern across the page.
+ */
TILE
}
diff --git a/src/main/java/com/demcha/compose/document/snapshot/LayoutCanvasSnapshot.java b/src/main/java/com/demcha/compose/document/snapshot/LayoutCanvasSnapshot.java
index 1541f6646..75ced682b 100644
--- a/src/main/java/com/demcha/compose/document/snapshot/LayoutCanvasSnapshot.java
+++ b/src/main/java/com/demcha/compose/document/snapshot/LayoutCanvasSnapshot.java
@@ -3,11 +3,11 @@
/**
* Snapshot-friendly projection of the resolved document canvas.
*
- * @param pageWidth full page width
- * @param pageHeight full page height
- * @param innerWidth drawable width after margins
+ * @param pageWidth full page width
+ * @param pageHeight full page height
+ * @param innerWidth drawable width after margins
* @param innerHeight drawable height after margins
- * @param margin resolved canvas margin
+ * @param margin resolved canvas margin
*/
public record LayoutCanvasSnapshot(
double pageWidth,
diff --git a/src/main/java/com/demcha/compose/document/snapshot/LayoutInsetsSnapshot.java b/src/main/java/com/demcha/compose/document/snapshot/LayoutInsetsSnapshot.java
index 9cca8d088..0ce11cd97 100644
--- a/src/main/java/com/demcha/compose/document/snapshot/LayoutInsetsSnapshot.java
+++ b/src/main/java/com/demcha/compose/document/snapshot/LayoutInsetsSnapshot.java
@@ -3,10 +3,10 @@
/**
* Snapshot-friendly inset model used for margins and padding.
*
- * @param top top inset
- * @param right right inset
+ * @param top top inset
+ * @param right right inset
* @param bottom bottom inset
- * @param left left inset
+ * @param left left inset
*/
public record LayoutInsetsSnapshot(double top, double right, double bottom, double left) {
}
diff --git a/src/main/java/com/demcha/compose/document/snapshot/LayoutNodeSnapshot.java b/src/main/java/com/demcha/compose/document/snapshot/LayoutNodeSnapshot.java
index fe3751476..cbb295edd 100644
--- a/src/main/java/com/demcha/compose/document/snapshot/LayoutNodeSnapshot.java
+++ b/src/main/java/com/demcha/compose/document/snapshot/LayoutNodeSnapshot.java
@@ -3,25 +3,25 @@
/**
* Stable, test-oriented projection of a single resolved document node.
*
- * @param path full deterministic node path built from parent path and local segment
- * @param entityName semantic entity name when available, otherwise {@code null}
- * @param entityKind stable node kind used as a fallback identity hint
- * @param parentPath full parent path, or {@code null} for root nodes
- * @param childIndex zero-based position among siblings
- * @param depth resolved tree depth for debugging and ordering checks
- * @param layer resolved layer value after layout
- * @param computedX resolved computed x-coordinate
- * @param computedY resolved computed y-coordinate
- * @param placementX resolved placement box x-coordinate
- * @param placementY resolved placement box y-coordinate
- * @param placementWidth resolved placement box width
+ * @param path full deterministic node path built from parent path and local segment
+ * @param entityName semantic entity name when available, otherwise {@code null}
+ * @param entityKind stable node kind used as a fallback identity hint
+ * @param parentPath full parent path, or {@code null} for root nodes
+ * @param childIndex zero-based position among siblings
+ * @param depth resolved tree depth for debugging and ordering checks
+ * @param layer resolved layer value after layout
+ * @param computedX resolved computed x-coordinate
+ * @param computedY resolved computed y-coordinate
+ * @param placementX resolved placement box x-coordinate
+ * @param placementY resolved placement box y-coordinate
+ * @param placementWidth resolved placement box width
* @param placementHeight resolved placement box height
- * @param startPage zero-based first page touched by this node
- * @param endPage zero-based last page touched by this node
- * @param contentWidth resolved content width
- * @param contentHeight resolved content height
- * @param margin normalized margin insets captured for debugging
- * @param padding normalized padding insets captured for debugging
+ * @param startPage zero-based first page touched by this node
+ * @param endPage zero-based last page touched by this node
+ * @param contentWidth resolved content width
+ * @param contentHeight resolved content height
+ * @param margin normalized margin insets captured for debugging
+ * @param padding normalized padding insets captured for debugging
*/
public record LayoutNodeSnapshot(
String path,
diff --git a/src/main/java/com/demcha/compose/document/snapshot/LayoutSnapshot.java b/src/main/java/com/demcha/compose/document/snapshot/LayoutSnapshot.java
index 13c68b582..87cc778f3 100644
--- a/src/main/java/com/demcha/compose/document/snapshot/LayoutSnapshot.java
+++ b/src/main/java/com/demcha/compose/document/snapshot/LayoutSnapshot.java
@@ -10,9 +10,9 @@
* stable layout state so JSON baselines stay readable and maintainable.
*
* @param formatVersion snapshot schema version used to interpret the JSON shape
- * @param canvas resolved canvas metadata for the composed document
- * @param totalPages total number of pages touched by the resolved layout
- * @param nodes deterministic depth-first list of resolved document nodes
+ * @param canvas resolved canvas metadata for the composed document
+ * @param totalPages total number of pages touched by the resolved layout
+ * @param nodes deterministic depth-first list of resolved document nodes
*/
public record LayoutSnapshot(
String formatVersion,
diff --git a/src/main/java/com/demcha/compose/document/style/DocumentBorders.java b/src/main/java/com/demcha/compose/document/style/DocumentBorders.java
index cbb5e0ea6..d02ef9c83 100644
--- a/src/main/java/com/demcha/compose/document/style/DocumentBorders.java
+++ b/src/main/java/com/demcha/compose/document/style/DocumentBorders.java
@@ -9,15 +9,16 @@
* bottom-only divider under a row) without importing internal engine shape
* components.
*
- * @param top stroke applied to the top side, or {@code null} for none
- * @param right stroke applied to the right side, or {@code null} for none
+ * @param top stroke applied to the top side, or {@code null} for none
+ * @param right stroke applied to the right side, or {@code null} for none
* @param bottom stroke applied to the bottom side, or {@code null} for none
- * @param left stroke applied to the left side, or {@code null} for none
- *
+ * @param left stroke applied to the left side, or {@code null} for none
* @author Artem Demchyshyn
*/
public record DocumentBorders(DocumentStroke top, DocumentStroke right, DocumentStroke bottom, DocumentStroke left) {
- /** All-sides empty borders. */
+ /**
+ * All-sides empty borders.
+ */
public static final DocumentBorders NONE = new DocumentBorders(null, null, null, null);
/**
diff --git a/src/main/java/com/demcha/compose/document/style/DocumentColor.java b/src/main/java/com/demcha/compose/document/style/DocumentColor.java
index 1207f321c..7b1aab610 100644
--- a/src/main/java/com/demcha/compose/document/style/DocumentColor.java
+++ b/src/main/java/com/demcha/compose/document/style/DocumentColor.java
@@ -1,6 +1,6 @@
package com.demcha.compose.document.style;
-import java.awt.Color;
+import java.awt.*;
import java.util.Objects;
/**
@@ -61,9 +61,9 @@ public static DocumentColor of(Color color) {
/**
* Creates a document color from RGB components.
*
- * @param red red channel from 0 to 255
+ * @param red red channel from 0 to 255
* @param green green channel from 0 to 255
- * @param blue blue channel from 0 to 255
+ * @param blue blue channel from 0 to 255
* @return immutable document color
*/
public static DocumentColor rgb(int red, int green, int blue) {
@@ -79,9 +79,9 @@ public static DocumentColor rgb(int red, int green, int blue) {
* constant. Text, lines, and the DOCX backend currently render the colour
* fully opaque.
*
- * @param red red channel from 0 to 255
+ * @param red red channel from 0 to 255
* @param green green channel from 0 to 255
- * @param blue blue channel from 0 to 255
+ * @param blue blue channel from 0 to 255
* @param alpha alpha channel from 0 (transparent) to 255 (opaque)
* @return immutable document color
* @since 1.8.0
diff --git a/src/main/java/com/demcha/compose/document/style/DocumentCornerRadius.java b/src/main/java/com/demcha/compose/document/style/DocumentCornerRadius.java
index 5d68b6e5e..4c1e71c47 100644
--- a/src/main/java/com/demcha/compose/document/style/DocumentCornerRadius.java
+++ b/src/main/java/com/demcha/compose/document/style/DocumentCornerRadius.java
@@ -19,11 +19,10 @@
* need asymmetry use the four-arg form or one of the convenience
* helpers below.
*
- * @param topLeft top-left radius in points
- * @param topRight top-right radius in points
+ * @param topLeft top-left radius in points
+ * @param topRight top-right radius in points
* @param bottomRight bottom-right radius in points
- * @param bottomLeft bottom-left radius in points
- *
+ * @param bottomLeft bottom-left radius in points
* @author Artem Demchyshyn
*/
public record DocumentCornerRadius(double topLeft, double topRight, double bottomRight, double bottomLeft) {
@@ -66,10 +65,10 @@ public static DocumentCornerRadius of(double radius) {
* Creates a corner radius with explicit values per corner. Order
* matches CSS-style top-left, top-right, bottom-right, bottom-left.
*
- * @param topLeft top-left radius
- * @param topRight top-right radius
+ * @param topLeft top-left radius
+ * @param topRight top-right radius
* @param bottomRight bottom-right radius
- * @param bottomLeft bottom-left radius
+ * @param bottomLeft bottom-left radius
* @return per-corner radius
*/
public static DocumentCornerRadius of(double topLeft, double topRight, double bottomRight, double bottomLeft) {
diff --git a/src/main/java/com/demcha/compose/document/style/DocumentDashPattern.java b/src/main/java/com/demcha/compose/document/style/DocumentDashPattern.java
index cdd2cd465..8f400f6e5 100644
--- a/src/main/java/com/demcha/compose/document/style/DocumentDashPattern.java
+++ b/src/main/java/com/demcha/compose/document/style/DocumentDashPattern.java
@@ -22,7 +22,9 @@
*/
public record DocumentDashPattern(List segments) {
- /** Solid (un-dashed) stroke — the default for every line. */
+ /**
+ * Solid (un-dashed) stroke — the default for every line.
+ */
public static final DocumentDashPattern NONE = new DocumentDashPattern(List.of());
/**
diff --git a/src/main/java/com/demcha/compose/document/style/DocumentInsets.java b/src/main/java/com/demcha/compose/document/style/DocumentInsets.java
index 735a940f1..2b4365d68 100644
--- a/src/main/java/com/demcha/compose/document/style/DocumentInsets.java
+++ b/src/main/java/com/demcha/compose/document/style/DocumentInsets.java
@@ -7,10 +7,10 @@
* document spacing without importing low-level engine components. Instances are
* immutable and thread-safe.
*
- * @param top top inset in points
- * @param right right inset in points
+ * @param top top inset in points
+ * @param right right inset in points
* @param bottom bottom inset in points
- * @param left left inset in points
+ * @param left left inset in points
* @author Artem Demchyshyn
*/
public record DocumentInsets(double top, double right, double bottom, double left) {
@@ -37,7 +37,7 @@ public static DocumentInsets of(double value) {
/**
* Creates spacing from vertical and horizontal values.
*
- * @param vertical top and bottom inset in points
+ * @param vertical top and bottom inset in points
* @param horizontal left and right inset in points
* @return symmetric insets
*/
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 209761540..034629a9c 100644
--- a/src/main/java/com/demcha/compose/document/style/DocumentPaint.java
+++ b/src/main/java/com/demcha/compose/document/style/DocumentPaint.java
@@ -40,7 +40,7 @@ static DocumentPaint solid(DocumentColor color) {
* Two-stop linear gradient along a normalized angle (0 = left→right).
*
* @param from start colour
- * @param to end colour
+ * @param to end colour
* @return linear paint
*/
static DocumentPaint linear(DocumentColor from, DocumentColor to) {
@@ -53,12 +53,15 @@ static DocumentPaint linear(DocumentColor from, DocumentColor to) {
* @param color fill colour
*/
record Solid(DocumentColor color) implements DocumentPaint {
- /** Validates the colour. */
+ /**
+ * Validates the colour.
+ */
public Solid {
Objects.requireNonNull(color, "color");
}
- @Override public DocumentColor primaryColor() {
+ @Override
+ public DocumentColor primaryColor() {
return color;
}
}
@@ -66,11 +69,13 @@ record Solid(DocumentColor color) implements DocumentPaint {
/**
* Linear gradient.
*
- * @param stops ordered colour stops, offsets in [0,1]; at least two
+ * @param stops ordered colour stops, offsets in [0,1]; at least two
* @param angleDegrees gradient direction, 0 = left→right, 90 = bottom→top
*/
record Linear(List stops, double angleDegrees) implements DocumentPaint {
- /** Copy-protects and validates stops. */
+ /**
+ * Copy-protects and validates stops.
+ */
public Linear {
Objects.requireNonNull(stops, "stops");
stops = List.copyOf(stops);
@@ -79,7 +84,8 @@ record Linear(List stops, double angleDegrees) implements DocumentPaint {
}
}
- @Override public DocumentColor primaryColor() {
+ @Override
+ public DocumentColor primaryColor() {
return stops.get(0).color();
}
}
@@ -88,11 +94,13 @@ record Linear(List