Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,15 @@ See [docs/contributing/release-process.md](./docs/contributing/release-process.m
- `src/main/java/com/demcha/compose/document/layout`
Canonical functional layout pipeline: `LayoutCompiler`, `BuiltInNodeDefinitions`, `TableLayoutSupport`, `PreparedNode`, `PlacedFragment`
- `src/main/java/com/demcha/compose/document/backend/fixed/pdf`
PDF backend: `PdfFixedLayoutBackend`, fragment handlers, and the option translators that bridge canonical types to PDFBox
PDF backend: `PdfFixedLayoutBackend`, fragment handlers, the option translators that bridge canonical types to PDFBox, and `FontShowcase` (bundled-font preview renderer)
- `src/main/java/com/demcha/compose/document/backend/semantic`
Semantic exporters: `DocxSemanticBackend` (Apache POI based), `PptxSemanticBackend` (manifest skeleton)
- `src/main/java/com/demcha/compose/document/templates/*`
Built-in templates (CV, cover letter, invoice, proposal, weekly schedule), DTOs, themes, registries, and scene composition helpers
- `src/main/java/com/demcha/compose/engine/*`
Internal shared engine foundation under the canonical surface (measure, paginate, place, render). Not part of the recommended public API
- `src/main/java/com/demcha/compose/font`
Public font registry, `FontName`, default fonts, `FontShowcase`
Public font registry, `FontName`, default fonts
- `src/test/java/com/demcha/documentation/*`
Examples used to keep README/documentation snippets honest
- `src/test/java/com/demcha/compose/engine/integration/*`
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/demcha/compose/GraphCompose.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.demcha.compose.font.FontFamilyDefinition;
import com.demcha.compose.font.FontName;
import com.demcha.compose.font.FontShowcase;
import com.demcha.compose.document.backend.fixed.pdf.FontShowcase;
import com.demcha.compose.font.DefaultFonts;
import com.demcha.compose.document.api.DocumentPageSize;
import com.demcha.compose.document.api.DocumentSession;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.demcha.compose.font;
package com.demcha.compose.document.backend.fixed.pdf;

import com.demcha.compose.GraphCompose;
import com.demcha.compose.document.api.DocumentPageSize;
Expand All @@ -9,6 +9,8 @@
import com.demcha.compose.document.style.DocumentInsets;
import com.demcha.compose.document.style.DocumentTextDecoration;
import com.demcha.compose.document.style.DocumentTextStyle;
import com.demcha.compose.font.DefaultFonts;
import com.demcha.compose.font.FontName;

import java.awt.Color;
import java.nio.file.Path;
Expand All @@ -28,6 +30,12 @@ public final class FontShowcase {
private FontShowcase() {
}

/**
* Renders a preview of every bundled font family to a PDF file on disk.
*
* @param outputFile destination path for the generated preview PDF
* @throws Exception if the document cannot be built or written
*/
public static void renderAvailableFontsPreview(Path outputFile) throws Exception {
try (DocumentSession document = GraphCompose.document(outputFile)
.pageSize(DocumentPageSize.A4)
Expand All @@ -40,6 +48,12 @@ public static void renderAvailableFontsPreview(Path outputFile) throws Exception
}
}

/**
* Renders a preview of every bundled font family and returns the PDF bytes.
*
* @return the generated preview document as PDF bytes
* @throws Exception if the document cannot be built or rendered
*/
public static byte[] renderAvailableFontsPreview() throws Exception {
try (DocumentSession document = GraphCompose.document()
.pageSize(DocumentPageSize.A4)
Expand All @@ -52,6 +66,14 @@ public static byte[] renderAvailableFontsPreview() throws Exception {
}
}

/**
* Renders a preview of the given font families and returns the PDF bytes.
*
* @param fonts logical font names to include; when {@code null} the full
* bundled catalog is used
* @return the generated preview document as PDF bytes
* @throws Exception if the document cannot be built or rendered
*/
public static byte[] renderFontsPreview(Collection<FontName> fonts) throws Exception {
try (DocumentSession document = GraphCompose.document()
.pageSize(DocumentPageSize.A4)
Expand All @@ -64,6 +86,13 @@ public static byte[] renderFontsPreview(Collection<FontName> fonts) throws Excep
}
}

/**
* Builds the font-preview content into an existing document session.
*
* @param document open document session to populate; must not be {@code null}
* @param fonts logical font names to showcase; when {@code null} the full
* bundled catalog is used
*/
public static void buildShowcase(DocumentSession document, Collection<FontName> fonts) {
Objects.requireNonNull(document, "document").pageFlow(flow -> {
flow.name("AvailableFontsPreview")
Expand Down
23 changes: 0 additions & 23 deletions src/main/java/com/demcha/compose/font/DefaultFonts.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package com.demcha.compose.font;

import com.demcha.compose.document.backend.fixed.pdf.PdfFontLibraryFactory;
import org.apache.pdfbox.pdmodel.PDDocument;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
Expand Down Expand Up @@ -76,27 +74,6 @@ public static FontLibrary standardLibrary() {
return PdfFontLibraryFactory.standardLibrary();
}

/**
* Creates a PDF-backed font library containing bundled families.
*
* @param document PDF document that owns loaded fonts
* @return font library
*/
public static FontLibrary library(PDDocument document) {
return PdfFontLibraryFactory.library(document);
}

/**
* Creates a PDF-backed font library containing bundled and custom families.
*
* @param document PDF document that owns loaded fonts
* @param customFamilies document-local custom font families
* @return font library
*/
public static FontLibrary library(PDDocument document, Collection<FontFamilyDefinition> customFamilies) {
return PdfFontLibraryFactory.library(document, customFamilies);
}

/**
* Returns bundled font family definitions.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
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.PdfWatermarkOptions;
import com.demcha.compose.font.DefaultFonts;
import com.demcha.compose.document.backend.fixed.pdf.PdfFontLibraryFactory;
import com.demcha.compose.font.FontLibrary;
import com.demcha.compose.engine.components.content.table.TableCellContent;
import com.demcha.compose.engine.components.content.table.TableCellLayoutStyle;
Expand Down Expand Up @@ -1097,7 +1097,7 @@ private CountingPrepareContext(NodeRegistry registry, PDRectangle pageSize, Marg
this.registry = registry;
this.canvas = LayoutCanvas.from(pageSize.getWidth(), pageSize.getHeight(), margin);
this.measurementDocument = new PDDocument();
this.fonts = DefaultFonts.library(measurementDocument);
this.fonts = PdfFontLibraryFactory.library(measurementDocument);
this.textMeasurement = new CountingTextMeasurementSystem(
new FontLibraryTextMeasurementSystem(fonts, PdfFont.class));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.demcha.compose.font;
package com.demcha.compose.document.backend.fixed.pdf;

import com.demcha.compose.GraphCompose;
import com.demcha.compose.document.api.DocumentPageSize;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.demcha.compose.font;
package com.demcha.compose.document.backend.fixed.pdf;

import com.demcha.compose.GraphCompose;
import com.demcha.compose.font.FontName;
import com.demcha.testing.VisualTestOutputs;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.demcha.compose.engine.integration;

import com.demcha.compose.GraphCompose;
import com.demcha.compose.font.DefaultFonts;
import com.demcha.compose.document.backend.fixed.pdf.PdfFontLibraryFactory;
import com.demcha.compose.testsupport.engine.assembly.ComponentBuilder;
import com.demcha.compose.engine.components.content.text.TextIndentStrategy;
import com.demcha.compose.engine.components.content.text.BlockTextData;
Expand Down Expand Up @@ -167,7 +167,7 @@ void shouldIncreaseVerticalGapAroundMarkdownHeading() throws Exception {

double baseStep;
try (PDDocument fontDocument = new PDDocument()) {
PdfFont font = (PdfFont) DefaultFonts.library(fontDocument)
PdfFont font = (PdfFont) PdfFontLibraryFactory.library(fontDocument)
.getFont(style.fontName(), PdfFont.class)
.orElseThrow();
baseStep = font.getLineHeight(style) + 2.0;
Expand Down Expand Up @@ -206,7 +206,7 @@ void shouldRespectOwnPaddingWhenPositioningBlockTextLines() throws Exception {

double baselineOffsetFromBottom;
try (PDDocument fontDocument = new PDDocument()) {
PdfFont font = (PdfFont) DefaultFonts.library(fontDocument)
PdfFont font = (PdfFont) PdfFontLibraryFactory.library(fontDocument)
.getFont(style.fontName(), PdfFont.class)
.orElseThrow();
baselineOffsetFromBottom = font.verticalMetrics(style).baselineOffsetFromBottom();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.demcha.compose.engine.integration;

import com.demcha.compose.GraphCompose;
import com.demcha.compose.font.DefaultFonts;
import com.demcha.compose.document.backend.fixed.pdf.PdfFontLibraryFactory;
import com.demcha.compose.engine.components.content.text.TextStyle;
import com.demcha.compose.engine.components.core.Entity;
import com.demcha.compose.engine.components.layout.Anchor;
Expand Down Expand Up @@ -48,7 +48,7 @@ void shouldRenderAutosizedSingleLineTextAtPaddingAdjustedBaseline() throws Excep
Placement placement = textEntity.getComponent(Placement.class).orElseThrow();
PdfFont.VerticalMetrics metrics;
try (PDDocument fontDocument = new PDDocument()) {
PdfFont pdfFont = (PdfFont) DefaultFonts.library(fontDocument)
PdfFont pdfFont = (PdfFont) PdfFontLibraryFactory.library(fontDocument)
.getFont(style.fontName(), PdfFont.class)
.orElseThrow();
metrics = pdfFont.verticalMetrics(style);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.demcha.compose.font;

import com.demcha.compose.GraphCompose;
import com.demcha.compose.document.backend.fixed.pdf.PdfFontLibraryFactory;
import com.demcha.compose.testsupport.EngineComposerHarness;
import com.demcha.compose.engine.render.pdf.PdfFont;
import com.demcha.compose.engine.render.word.WordFont;
Expand All @@ -24,7 +25,7 @@ void shouldExposeBundledGoogleFontsInEngineComposerHarness() throws Exception {
}

try (PDDocument document = new PDDocument()) {
FontLibrary fonts = DefaultFonts.library(document);
FontLibrary fonts = PdfFontLibraryFactory.library(document);
assertThat(fonts.getFont(FontName.LATO, PdfFont.class)).isPresent();
assertThat(fonts.getFont(FontName.LATO, WordFont.class)).isPresent();
assertThat(fonts.getFont(FontName.KANIT, PdfFont.class)).isPresent();
Expand Down Expand Up @@ -61,7 +62,7 @@ void shouldRegisterCustomFontFamilyFromFilePaths() throws Exception {
.build();

try (PDDocument document = new PDDocument()) {
FontLibrary fonts = DefaultFonts.library(document, List.of(customDefinition));
FontLibrary fonts = PdfFontLibraryFactory.library(document, List.of(customDefinition));
assertThat(fonts.getFont(customFamily, PdfFont.class)).isPresent();
assertThat(fonts.getFont(customFamily, WordFont.class)).isPresent();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.demcha.compose.testsupport;

import com.demcha.compose.font.DefaultFonts;
import com.demcha.compose.document.backend.fixed.pdf.PdfFontLibraryFactory;
import com.demcha.compose.font.FontFamilyDefinition;
import com.demcha.compose.font.FontName;
import com.demcha.compose.testsupport.engine.assembly.ComponentBuilder;
Expand Down Expand Up @@ -72,7 +72,7 @@ private EngineComposerHarness(Path outputFile,
Margin margin,
Collection<FontFamilyDefinition> customFontFamilies) {
this.doc = new PDDocument();
this.entityManager = new EntityManager(DefaultFonts.library(doc, customFontFamilies), markdown);
this.entityManager = new EntityManager(PdfFontLibraryFactory.library(doc, customFontFamilies), markdown);
this.entityManager.setGuideLines(guideLines);
this.componentBuilder = createComponentBuilder(entityManager);
this.canvas = new PdfCanvas(pageSize, 0.0f, 0.0f);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@

/**
* Architectural guard that keeps PDFBox out of the canonical document API, the
* layered template surface, and non-PDF fixed-layout contracts. Templates
* compose against the canonical DSL and must stay backend-neutral, so a preset
* or component that reached for a PDFBox type would fail here.
* layered template surface, non-PDF fixed-layout contracts, and the public font
* catalog. Templates compose against the canonical DSL and must stay
* backend-neutral, so a preset or component that reached for a PDFBox type would
* fail here. The {@code compose.font} package is the logical font catalog — it
* names fonts, it never loads them (PDFBox loading belongs to the pdf backend
* factory), so it is guarded too.
*/
class PdfBackendIsolationGuardTest {

Expand All @@ -37,7 +40,12 @@ class PdfBackendIsolationGuardTest {
PROJECT_ROOT.resolve("src/main/java/com/demcha/compose/document/layout"),
PROJECT_ROOT.resolve("src/main/java/com/demcha/compose/document/snapshot"),
PROJECT_ROOT.resolve("src/main/java/com/demcha/compose/document/templates"),
PROJECT_ROOT.resolve("src/main/java/com/demcha/compose/document/backend/fixed"));
PROJECT_ROOT.resolve("src/main/java/com/demcha/compose/document/backend/fixed"),
// The public font catalog names logical fonts; it never loads them.
// PDFBox loading lives in the pdf backend factory, so compose.font
// must stay PDFBox-free (FontShowcase, which renders a preview PDF,
// lives under backend/fixed/pdf and is exempted like the rest of it).
PROJECT_ROOT.resolve("src/main/java/com/demcha/compose/font"));

@Test
void pdfboxShouldStayOutOfCanonicalAndNonPdfBackendContracts() throws IOException {
Expand Down
Loading