Skip to content

feat: v0.4.0 Creator API — page sizes, custom dimensions, landscape, text rotation#44

Merged
kolkov merged 8 commits into
mainfrom
feat/v0.4.0-creator-api
Feb 21, 2026
Merged

feat: v0.4.0 Creator API — page sizes, custom dimensions, landscape, text rotation#44
kolkov merged 8 commits into
mainfrom
feat/v0.4.0-creator-api

Conversation

@kolkov

@kolkov kolkov commented Feb 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Creator API enhancements for v0.4.0, driven by community feedback from @ajstarks (#41, #42) building a deck client on gxpdf.

  • 35+ built-in page sizes — ISO A/B/C series, ANSI engineering, photo, book, JIS, envelopes, presentation slides. Map-based architecture replaces dual-switch.
  • Custom page dimensionsNewPageWithDimensions(widthPt, heightPt) with unit conversion helpers (inches, mm, cm + reverse).
  • Landscape orientationNewPageWithSize(size, Landscape) using industry-standard swapped-MediaBox approach (researched 16 libraries across 7 languages).
  • Text rotationAddTextRotated / AddTextColorRotated + custom font variants. Uses PDF Tm operator per ISO 32000 §9.4.2.
  • Code quality — staticcheck QF1012 fixes, stale godoc corrections, domain-layer test coverage.

Closes #41, closes #42.

Test plan

  • All 17 packages pass (go test ./... -count=1)
  • go fmt, go vet, golangci-lint run — 0 issues
  • New tests: custom dimensions (validation, margins, content area, PDF output)
  • New tests: landscape/portrait (5 sizes, explicit portrait, PDF output)
  • New tests: text rotation (0°/45°/90°/180°/270°, negative, Tm matrix verification, end-to-end PDF)
  • New tests: domain-layer AddPageWithRect, iota mirror guard (38 sizes)
  • Content stream byte-level assertions for rotation matrix values

Add 27 new page size constants to both domain and creator layers:
- Extended ISO A series: A0, A1, A2, A6, A7, A8
- Extended ISO B series: B0, B1, B2, B3, B6
- ISO C/Envelope: C4, C5, C6, DL
- North American: Executive, HalfLetter
- ANSI Engineering: ANSIC, ANSID, ANSIE
- Photo: Photo4x6, Photo5x7, Photo8x10
- Book Publishing: Digest, USTradeBook
- Presentation (unique): Slide16x9, Slide4x3
- US Envelope: Envelope10
- JIS B (Japanese): JISB4, JISB5

Domain layer uses single pageSizeMap as source of truth (no switch
duplication). Creator layer iota values mirror domain 1:1 via direct
cast — validated by compile-time structural test.

Tests cover all 35+ sizes, A-series halving invariant, JIS vs ISO
B-series distinction, presentation aspect ratios, and iota order guard.
Add document.AddPageWithRect for domain-level custom page creation.
Add creator.NewPageWithDimensions(widthPt, heightPt) for ergonomic
custom dimensions at the creator layer.

Both methods initialize all page fields identically to the existing
AddPage/NewPageWithSize methods. Negative and zero dimensions are
rejected with descriptive errors.

Unit conversion helpers (InchesToPoints, MMToPoints, CMToPoints) and
their constants are now also exported from the creator package,
delegating to the domain layer implementations to avoid duplication.

Tests cover: correct dimensions, validation errors, page count
increment, mixed use with standard sizes, PDF write round-trip,
default margins, and content area calculation.
Add Rotation float64 field to creator.TextOperation and writer.TextOp
structs. Rotation is in degrees, counter-clockwise, around the text
origin point (X, Y).

New creator.Page methods:
  AddTextRotated(text, x, y, font, size, rotation) error
  AddTextColorRotated(text, x, y, font, size, color, rotation) error

Content stream generation now uses the Tm (text matrix) PDF operator
when Rotation != 0, computing cos/sin from the degree value. Zero
rotation continues to use the Td (MoveTextPosition) operator, preserving
backward compatibility.

convertTextOps propagates the Rotation field from creator to writer.

Tests cover: 0/90/45/negative degree values, color and validation, Tm
vs Td operator selection, matrix math correctness, end-to-end PDF
write, multiple rotations on one page, and AddText regression guard.
…eWithSize

NewPageWithSize now accepts an optional orientation parameter — the
industry-standard approach used by PDFKit, jsPDF, gofpdf, TCPDF, and others.
Uses swapped-MediaBox (93% industry consensus), no /Rotate.
- Fix stale godoc: ToRectangle() referenced SetRotation for landscape,
  now points to NewPageWithSize with Landscape option
- Fix misleading comment: 'compile-time check' → 'runtime check'
- Add reverse conversion functions to creator layer (PointsToInches,
  PointsToMM, PointsToCM) for API symmetry with forward conversions
- Add domain-layer test for AddPageWithRect (was only tested indirectly)
- Fix rotation tests: now assert actual content stream matrix bytes
  instead of testing Go math library
- CHANGELOG: add v0.4.0 section (35+ page sizes, custom dimensions,
  landscape orientation, text rotation)
- README: add new features to Key Features section, update version plan
- ROADMAP: add v0.4.0 'Creator API' section, shift encryption/signatures
  to v0.5.0, update feature status table and backlog
This was referenced Feb 20, 2026
- Add normalizeAngle() helper for consistent angle representation
- Apply normalization in AddTextColorRotated and AddTextCustomFontColorRotated
- Negative angles accepted: -90 becomes 270, -45 becomes 315
- Fractional angles (22.5°, 33.3°) fully supported
- Document CCW-positive convention per ISO 32000 §8.3
- Clarify Slide16x9/Slide4x3 are already landscape-oriented
- Note Orientation behavior with presentation sizes
- Add 16 normalization test cases + equivalence tests
@kolkov kolkov merged commit 1e84281 into main Feb 21, 2026
7 checks passed
@kolkov kolkov deleted the feat/v0.4.0-creator-api branch February 21, 2026 07:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add text rotation options Wrapper to make a deck client

1 participant