Releases: Macawls/ogre
v1.4.0
Performance
Major rendering speed improvements across the PNG/JPEG pipeline.
Gradient Strip Precomputation
Instead of computing color interpolation per-pixel, gradients now build a 1D color lookup table along the gradient line and sample from it. This eliminates redundant srgbToLinear/linearToSrgb conversions and interpolateLinearStops calls.
- Linear gradients: 8x faster (49ms β 6ms at component level)
- Radial gradients: 7x faster (54ms β 8ms at component level)
Buffer Pooling (sync.Pool)
Temporary full-viewport RGBA images (3MB+ each at 1200Γ630) used for opacity compositing, border-radius clipping, overflow:hidden, and border rendering are now pooled and reused instead of allocated fresh each time.
- Up to 56% memory reduction per render
Rounded Mask Cache
Supersampled anti-aliased border-radius masks are cached by (width, height, tl, tr, br, bl). Elements sharing the same dimensions and border-radius reuse a single cached mask instead of recomputing.
Parallel Box Blur
Shadow blur passes now split rows/columns across goroutines with direct Pix slice access, eliminating method call overhead.
- Shadow blur: 4.3x faster (5ms β 1.15ms at component level)
End-to-End Results
Benchmarked on AMD Ryzen 5 5600H, 1200Γ630 PNG output:
| Fixture | Before | After | Improvement |
|---|---|---|---|
| Linear gradient | 145ms | 100ms | 31% faster |
| Radial gradient | 319ms | 266ms | 17% faster |
| Box shadow | 33ms | 24ms | 28% faster |
| Product pricing | 129ms | 83ms | 36% faster |
| Blog card | 73ms | 53ms | 27% faster |
| Dashboard stat | 24ms / 12MB | 19ms / 5MB | 22% faster, 58% less memory |
Component-level benchmarks added in render/bench_test.go for ongoing tracking.
v1.3.0
Layout Engine Fixes
Text overflow in column-direction flex containers
determineFlexBaseSize and determineCrossSize in the flexbox engine passed the main-axis size as maxWidth to the text measure function. In column layouts (main axis = height), text received the container height as its width constraint and never wrapped. Fixed by swapping Measure() arguments when isRow is false.
Containers grow to fit content height
Containers without explicit CSS height now shrink to fit their content. Previously, computeNode() set Layout.Height from availableHeight and never updated it after children were laid out. Now recalculates from line cross sizes (row) or item main sizes (column) after layout completes.
Performance
sRGB lookup tables for gradient rendering
Replaced per-pixel math.Pow calls in gradient interpolation with precomputed lookup tables β 256-entry decode table and 4096-entry encode table (32KB, fits L1 cache). Eliminates millions of transcendental function calls per gradient render.
Docs & Site
- Updated design goals to emphasize output quality over raw benchmarks
- Added comparison tool commands to AGENTS.md
- Cache busting for example images via Astro asset pipeline
- Dark mode default, emoji card layout fixes
Full Changelog: v1.2.0...v1.3.0
v1.2.0
What's New
SVG Rasterization & Inline SVGs
- SVG data URIs in
<img>tags now render in PNG and JPEG output (previously SVG-only) - Inline
<svg>elements are fully supported in all output formats - Minimal SVG rasterizer with path, rect, circle, ellipse, polygon, stroke, and translate transform support
- Even-odd fill rule via sub-path XOR compositing
Gradient Rendering Overhaul
- Fixed gradient direction (was reversed vs CSS spec in PNG/JPEG)
- Linear RGB color interpolation with ordered dithering eliminates visible banding
- SVG gradients now use
color-interpolation="linearRGB"to match PNG output
Tailwind Gradient Utilities
bg-gradient-to-{t,tr,r,br,b,bl,l,tl}direction classesfrom-*,via-*,to-*gradient stop color classes- Composes into
background-image: linear-gradient(...)automatically
PNG/JPEG Rendering Fixes
- Fixed premultiplied alpha compositing β eliminates bright-edge artifacts on semi-transparent rounded rects
- Sub-pixel text positioning for better SVG/PNG parity
- 2x supersampled rounded corner masks for smoother curves
- Rounded borders now clip through the mask (fixes angular corners on small elements)
- RTL text shaping in PNG via ShapedTextToPath + vector.Rasterizer
- 4:4:4 chroma JPEG encoder prevents color shifts on dark backgrounds
Other Fixes
- HTML
width/heightattributes now map to CSS styles (like browsers) font-familyCSS parsing correctly extracts first family from comma-separated fallback lists- Open SVG subpaths implicitly closed for fill operations
Docs & Site
- Shared template constants between playground and examples
- Fullscreen image viewer with zoom, pan, and SVG/PNG/JPEG format switching
- New RTL (Arabic) and Tailwind gradient examples
- Fixed dependency claims β
go-text/typesettingnow listed - Rate limit warning on playground
- curl example in rendering guide
Full Changelog: v1.1.0...v1.2.0
v1.1.0
Changelog
Features
- 4c4ace0 feat: add client-side navigation + external links open in new tab
- 0695507 feat: environment variable configuration for server
Bug Fixes
- 3173ba2 fix: add site URL for sitemap generation
- e8296b9 fix: light mode accent color, simplify CLAUDE.md, docs commit scope
- 744e44d fix: remove redundant Docs link from header, reorder nav
Performance
- bf200ff perf: aggressive prefetch + client prerendering + fast transitions
Other
- ef471d0 revert: remove client-side navigation, prefetch, and view transitions
v1.0.0
Changelog
Features
- fa0c535 feat: initial release v1.0.0
Bug Fixes
- a0fafd8 fix: CI β use golangci-lint-action v7, relax perf test timeout for race detector
- ce2f89d fix: add .node-version for Nixpacks (Node 22 required by Astro)
- fe027bf fix: add version field to golangci-lint config for v2 compatibility
- d19a92f fix: gitignore was blocking cmd/ogre/ β change 'ogre' to '/ogre'
- 4b0fb7a fix: install golangci-lint from source for Go 1.25 compat
- 51126b8 fix: pin golangci-lint to v2.1 for Go 1.25 compatibility
- 1863f18 fix: remove gosimple linter (merged into staticcheck in v2)
- e9ea8bc fix: use golangci-lint v2.11.4 for Go 1.25 support