Commit Graph

3 Commits

Author SHA1 Message Date
funman300 dd101b3d54 fix(engine): render bottom-right card glyph upright (no 180° rotation)
The user noticed the bottom-right large suit glyphs were
rendering upside-down — point-up hearts, stem-up spades — because
the SVG transform pipeline applied a `rotate(180)` to match the
traditional playing-card inverted-corner convention.

That convention exists so a card reads correctly when flipped or
read from the opposite side of the table. Single-orientation
digital play doesn't benefit from it; most modern digital decks
have abandoned it. User preference is upright.

Drops the rotate from face_svg's bottom-right `<g transform>`
and adjusts the translate so the visible glyph still lands at
(178, 286)–(242, 350) — same screen footprint, same scale, just
no flip.

design-system.md § Game Cards updated in lockstep — line 220
no longer says "rotated 180°", instead documents the deliberate
deviation from the traditional convention.

Knock-on lockstep changes in this commit:
- EXPECTED in tests/card_face_svg_pin.rs rebaselined: 52 face
  hashes shift, 5 back hashes unchanged.
- assets/cards/faces/*.png regenerated (52 face PNGs).
- solitaire_engine/assets/themes/default/*_*.svg regenerated
  (52 theme face SVGs that production rasterises at startup).

Workspace clippy + cargo test --workspace clean. Pin test
passes against the new hashes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 10:09:55 -07:00
funman300 af414b6aed fix(engine): render card suit glyphs as SVG paths instead of text
The user's first post-migration screenshot showed near-invisible
suit glyphs on every card — the rank rendered at correct size but
the ♠ ♥ ♦ ♣ marks were tiny dots regardless of the requested
20px / 64px font-size.

Root cause: the bundled FiraMono in svg_loader::shared_fontdb
doesn't carry usable Unicode suit glyphs (U+2660-2666). usvg
silently fell back to a substitute rendering at default size,
producing the "tofu" effect.

Fixes by replacing the `<text>` glyph rendering with inline SVG
paths. `suit_path_d(suit)` returns a single closed-perimeter path
authored in a 32 × 32 logical box, then face_svg wraps it in two
`<g transform>` blocks (top-left small + bottom-right rotated
large). Path-based rendering bypasses the font system entirely
— same bytes on every machine, no fontdb dependency, no
substitution risk.

Same path data renders correctly whether filled (♥ ♠) or
outlined (♦ ♣ — the always-on color-blind glyph differentiation
from the design system).

Knock-on changes that must land in this commit per the migration
plan's lockstep rule:

- `EXPECTED` in tests/card_face_svg_pin.rs rebaselined: 52 face
  hashes change (text → path), 5 back hashes unchanged
  (back_svg untouched). The bootstrap pattern in the test
  handled the rebaseline cleanly — empty EXPECTED, re-run,
  paste, re-run.
- assets/cards/faces/*.png regenerated (the 52 face PNGs).
- solitaire_engine/assets/themes/default/*_*.svg regenerated
  (the 52 theme face SVGs that production rasterises at
  startup). Both rendering paths must agree.

Workspace clippy + cargo test --workspace clean. Pin test
passes against the new hashes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 10:02:04 -07:00
funman300 48b28d29f8 test(engine): pin card-face SVG output against rasteriser drift
Step 3 of the migration plan in docs/ui-mockups/card-face-migration.md.

Extracts face_svg / back_svg + palette constants from the
card_face_generator example into a new
solitaire_engine::assets::card_face_svg module so an integration
test can call them. The example becomes a thin wrapper.

The new tests/card_face_svg_pin.rs hashes the raw RGBA8 pixel
bytes from rasterising every face × suit + every back accent and
compares each FNV-1a fingerprint against an embedded constant.
Catches silent rendering drift if usvg / resvg / tiny_skia / the
bundled FiraMono ever change in a way that perturbs pixels.

Hashing is FNV-1a inline (~5 lines) rather than adding sha2 or
blake3 — cryptographic strength isn't load-bearing here, just
stable byte fingerprints.

When the SVG builders intentionally change, empty EXPECTED to
`&[]` and re-run the test once; it panics with the new hashes
formatted as Rust source ready to paste back in.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 09:21:00 -07:00