Skip to content

Commit c3c8fb4

Browse files
committed
docs(examples): SVG icon gallery - 34 real-world multicolour icons via SvgIcon
New SvgIconGalleryExample (features/svg, new 'SVG Import' showcase group): a 5-column captioned grid of 34 svgrepo icons (fruit, UI, objects - up to 19 layers each) read by SvgIcon.parse from committed .svg resources (156 KB total) and placed with addSvgIcon. Triage of the whole set against the beta reader: 38/38 files parsed with zero failures. The rendered sheet is a single 65 KB page - the strongest real-world evidence the icon subset covers practice. Icon artwork from svgrepo.com (licence per icon page, attributed in the example Javadoc).
1 parent 740db51 commit c3c8fb4

39 files changed

Lines changed: 296 additions & 0 deletions
64.9 KB
Binary file not shown.

examples/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ are with the canonical DSL, then jump to its detailed section below.
8989
|---|---|---|
9090
| [Shape containers](#shape-containers) | Circles, ellipses, rounded cards with `ClipPolicy.CLIP_PATH` | [PDF](../assets/readme/examples/shape-container.pdf) · [Source](src/main/java/com/demcha/examples/features/shapes/ShapeContainerExample.java) |
9191
| [Vector paths (Bézier)](#vector-paths-bézier) | `addPath(...)` + `SvgPath.parse(...)` — design shapes and imported SVG icons as native curves; zero tessellation | [PDF](../assets/readme/examples/vector-path.pdf) · [Source](src/main/java/com/demcha/examples/features/shapes/VectorPathExample.java) |
92+
| [SVG icon gallery](#svg-icon-gallery) | 34 real-world multicolour svgrepo icons via `SvgIcon.parse` — up to 19 layers each, the whole set 156 KB of sources | [PDF](../assets/readme/examples/svg-icon-gallery.pdf) · [Source](src/main/java/com/demcha/examples/features/svg/SvgIconGalleryExample.java) |
9293
| [Advanced tables](#advanced-tables) | Row span, zebra rows, totals, repeating header on page break | [PDF](../assets/readme/examples/table-advanced.pdf) · [Source](src/main/java/com/demcha/examples/features/tables/TableAdvancedExample.java) |
9394
| [Barcodes](#barcodes) | QR, Code 128, Code 39, EAN-13, EAN-8, branded QR with theme colours | [PDF](../assets/readme/examples/barcode-showcase.pdf) · [Source](src/main/java/com/demcha/examples/features/barcodes/BarcodeShowcaseExample.java) |
9495
| [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) |
@@ -380,6 +381,21 @@ flow.addPath(path -> path
380381
[📄 View PDF](../assets/readme/examples/vector-path.pdf) ·
381382
[📜 Full source](src/main/java/com/demcha/examples/features/shapes/VectorPathExample.java)
382383

384+
### SVG icon gallery
385+
386+
A stress-test sheet for the beta SVG reader: 34 real-world multicolour
387+
icons (svgrepo.com) parsed by `SvgIcon.parse` and placed with
388+
`addSvgIcon(icon, 50)` — captions under every icon, every layer a native
389+
vector path. The entire icon set weighs 156 KB of `.svg` sources; the
390+
rendered page is a 65 KB PDF.
391+
392+
```java
393+
flow.addSvgIcon(SvgIcon.parse(readResource("/icons/apple.svg")), 50);
394+
```
395+
396+
[📄 View PDF](../assets/readme/examples/svg-icon-gallery.pdf) ·
397+
[📜 Full source](src/main/java/com/demcha/examples/features/svg/SvgIconGalleryExample.java)
398+
383399
### Advanced tables
384400

385401
`DocumentTableCell.rowSpan(int)` mirrors `colSpan(int)`.

examples/src/main/java/com/demcha/examples/GenerateAllExamples.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.demcha.examples.features.shapes.VectorPathExample;
1212
import com.demcha.examples.features.snapshots.LayoutSnapshotRegressionExample;
1313
import com.demcha.examples.features.streaming.HttpStreamingExample;
14+
import com.demcha.examples.features.svg.SvgIconGalleryExample;
1415
import com.demcha.examples.features.tables.ComposedTableCellExample;
1516
import com.demcha.examples.features.tables.TableAdvancedExample;
1617
import com.demcha.examples.features.text.InlineShapesExample;
@@ -130,6 +131,7 @@ public static void main(String[] args) throws Exception {
130131
// v1.5 visual primitives
131132
System.out.println("Generated: " + ShapeContainerExample.generate());
132133
System.out.println("Generated: " + VectorPathExample.generate());
134+
System.out.println("Generated: " + SvgIconGalleryExample.generate());
133135
System.out.println("Generated: " + TransformsExample.generate());
134136
System.out.println("Generated: " + TableAdvancedExample.generate());
135137

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package com.demcha.examples.features.svg;
2+
3+
import com.demcha.compose.GraphCompose;
4+
import com.demcha.compose.document.api.DocumentSession;
5+
import com.demcha.compose.document.dsl.SectionBuilder;
6+
import com.demcha.compose.document.node.DocumentNode;
7+
import com.demcha.compose.document.node.TextAlign;
8+
import com.demcha.compose.document.style.DocumentColor;
9+
import com.demcha.compose.document.style.DocumentInsets;
10+
import com.demcha.compose.document.style.DocumentTextStyle;
11+
import com.demcha.compose.document.svg.SvgIcon;
12+
import com.demcha.examples.support.ExampleOutputPaths;
13+
14+
import java.io.InputStream;
15+
import java.nio.charset.StandardCharsets;
16+
import java.nio.file.Path;
17+
import java.util.List;
18+
import java.util.Locale;
19+
import java.util.Objects;
20+
21+
/**
22+
* Runnable stress-test gallery for the beta SVG icon reader: 34 real-world
23+
* multicolour icons (up to 19 layers each) read straight from {@code .svg}
24+
* resources via {@link SvgIcon#parse(String)} and stacked on the page with
25+
* {@code addSvgIcon(...)} — every curve a native PDF Bézier, the whole icon
26+
* set a fraction of one screenshot's weight.
27+
*
28+
* <pre>{@code
29+
* flow.addSvgIcon(SvgIcon.read(Path.of("icons/apple.svg")), 52);
30+
* }</pre>
31+
*
32+
* <p>Icon artwork: <a href="https://www.svgrepo.com">svgrepo.com</a>
33+
* collections (see each icon's page for its licence).</p>
34+
*
35+
* @author Artem Demchyshyn
36+
*/
37+
public final class SvgIconGalleryExample {
38+
39+
private static final List<String> ICONS = List.of(
40+
"apple", "avocado", "banana", "boxing", "calendar",
41+
"camera-take-pictures", "chat-chat", "cherry", "diagnosis", "eye-password-eye-password",
42+
"feet", "food", "grape", "headphones-music", "key-password",
43+
"kiwi-fruit", "magnifying-glass-find-search", "microphone-singing", "movie", "peach",
44+
"pencil-revision", "personal-account-account", "picture", "record", "reminder-alert",
45+
"setting", "shopping-cart", "shopping", "social-contact", "starfish",
46+
"steak", "store-homepage-home", "toolbox", "upload");
47+
48+
private static final int COLUMNS = 5;
49+
private static final double ICON_SIZE = 50;
50+
51+
private SvgIconGalleryExample() {
52+
}
53+
54+
/**
55+
* Renders the 34-icon gallery sheet with a caption under every icon.
56+
*
57+
* @return path to the generated PDF
58+
* @throws Exception if rendering or resource IO fails
59+
*/
60+
public static Path generate() throws Exception {
61+
Path pdfFile = ExampleOutputPaths.prepare("features/svg", "svg-icon-gallery.pdf");
62+
63+
DocumentTextStyle caption = DocumentTextStyle.DEFAULT
64+
.withSize(7.5)
65+
.withColor(DocumentColor.rgb(90, 96, 105));
66+
67+
try (DocumentSession document = GraphCompose.document(pdfFile)
68+
.pageSize(595, 842)
69+
.margin(DocumentInsets.of(34))
70+
.create()) {
71+
document.pageFlow(page -> {
72+
page.addParagraph(p -> p
73+
.text("SVG icon gallery")
74+
.textStyle(DocumentTextStyle.DEFAULT.withSize(22)));
75+
page.addParagraph(p -> p
76+
.text("34 real-world multicolour icons (svgrepo.com) read by SvgIcon.parse "
77+
+ "— every layer a native vector path, the whole set 156 KB of sources.")
78+
.textStyle(DocumentTextStyle.DEFAULT.withSize(9.5)
79+
.withColor(DocumentColor.rgb(90, 96, 105)))
80+
.padding(DocumentInsets.bottom(14)));
81+
82+
for (int start = 0; start < ICONS.size(); start += COLUMNS) {
83+
List<String> chunk = ICONS.subList(start, Math.min(start + COLUMNS, ICONS.size()));
84+
page.addRow(row -> {
85+
row.spacing(10).evenWeights().margin(DocumentInsets.bottom(12));
86+
for (String name : chunk) {
87+
row.add(cell(name, caption));
88+
}
89+
});
90+
}
91+
});
92+
93+
document.buildPdf();
94+
}
95+
96+
return pdfFile;
97+
}
98+
99+
private static DocumentNode cell(String name, DocumentTextStyle caption) {
100+
SvgIcon icon = loadIcon(name);
101+
return new SectionBuilder()
102+
.name("Icon" + name.replace('-', '_'))
103+
.spacing(4)
104+
.addSvgIcon(icon, ICON_SIZE)
105+
.addParagraph(p -> p
106+
.text(pretty(name))
107+
.align(TextAlign.LEFT)
108+
.textStyle(caption))
109+
.build();
110+
}
111+
112+
private static SvgIcon loadIcon(String name) {
113+
try (InputStream in = Objects.requireNonNull(
114+
SvgIconGalleryExample.class.getResourceAsStream("/icons/" + name + ".svg"),
115+
"icon resource missing: " + name)) {
116+
return SvgIcon.parse(new String(in.readAllBytes(), StandardCharsets.UTF_8));
117+
} catch (Exception e) {
118+
throw new IllegalStateException("failed to load icon: " + name, e);
119+
}
120+
}
121+
122+
/** {@code "camera-take-pictures"} → {@code "Camera take pictures"}. */
123+
private static String pretty(String name) {
124+
String spaced = name.replace('-', ' ');
125+
return Character.toUpperCase(spaced.charAt(0)) + spaced.substring(1).toLowerCase(Locale.ROOT);
126+
}
127+
128+
public static void main(String[] args) throws Exception {
129+
System.out.println("Generated: " + generate());
130+
}
131+
}

examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ record Entry(String title, String description, List<String> tags, String codeUrl
9595
feature("tables", "composed-table-cell-showcase", "Composed Table Cells", "DocumentTableCell.node(DocumentNode) — paragraphs, lists, sub-tables inside cells with two-pass measurement.", "tables", "v1.6");
9696
feature("canvas", "canvas-layer-showcase", "Canvas Layer (free-canvas)", "CanvasLayerNode — pixel-precise (x,y) placement of children inside a fixed bounding box.", "canvas", "v1.6", "absolute");
9797
feature("shapes", "shape-container", "Shape-as-Container", "Rounded rect, ellipse, circle containers with ClipPolicy and layered children.", "shapes", "clip");
98+
feature("svg", "svg-icon-gallery", "SVG Icon Gallery", "34 real-world multicolour svgrepo icons through SvgIcon.parse — native vector layers, the whole set 156 KB of sources.", "svg", "icons", "v1.8");
9899
feature("shapes", "vector-path", "Vector Paths (Bézier)", "addPath(...) — free-form design shapes with native cubic Bézier curves: stroked waves, filled blobs, mixed line/curve ribbons. No tessellation.", "shapes", "bezier", "v1.8");
99100
feature("transforms", "transforms", "Layers + Transforms", "rotate / scale on every leaf builder + LayerStack with explicit z-index.", "transforms", "layers");
100101
feature("text", "rich-text-showcase", "Rich Text", "Inline runs with bold / italic / colour / link options, markdown parsing.", "text", "rich");
@@ -143,6 +144,7 @@ static String groupLabel(String category, String group) {
143144
case "features/chrome" -> "PDF Chrome (header / footer / watermark)";
144145
case "features/streaming" -> "Streaming & I/O";
145146
case "features/snapshots" -> "Snapshot Testing";
147+
case "features/svg" -> "SVG Import";
146148
case "features/debug" -> "Debug & Diagnostics";
147149
case "flagships/default" -> "Flagship Demos";
148150
default -> capitalize(group);
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)