stet 0.5.0 — 64-bit integers, Type 3 font fixes, --page
Minor release. PostScript integers are now 64-bit, which fixes the standard
LCG idiom that programs use for pseudo-randomness and is the reason this is a
breaking release rather than a patch. Three Type 3 font defects and a
clippath coordinate-space bug are also fixed, and the CLI gains --page.
Breaking
Downstream Rust code that reads PostScript integers needs attention; nothing
in the PostScript language surface changed incompatibly.
PsValue::Intnow carriesi64instead ofi32. A
match obj.value { PsValue::Int(v) => … }binds ani64, so any use site
that needs ani32no longer compiles.DictKey::IntandToken::Int
widened with it, as didContext::rand_seed.PsObject::as_i32()now range-checks. It returnsNonefor a value
outsidei32, where before it always returnedSomefor an integer. This
is the one change with no compiler error behind it — audit call sites that
treatNoneas "not an integer". Use the newas_i64()for the full
range; keepas_i32()where the value is genuinely bounded (array and
string indices, character codes), since a too-large value should fail those
callers' range checks rather than wrap into a valid-looking index.PsObject::int()takesimpl Into<i64>. Calls are unaffected; only
code coercing it to afn(i32) -> PsObjectpointer breaks.
Fixed
- Type 3 fonts supplying only
BuildGlyphraisedinvalidfont. The show
path requiredBuildCharunconditionally and pushed the character code.
PLRM 5.7 listsBuildGlyphas preferred and makesBuildCharrequired only
"for LanguageLevel 1 or ifBuildGlyphis absent", so such a font is
well-formed and must be handed the character name fromEncoding.
Ghostscript renders these; stet refused them.xshow/yshow/xyshowhad
the identical defect. stringwidthraisedinvalidfonton every Type 3 font,BuildChar
ones included. It branched for font types 2, 0 and 42 and then fell through
to the Type 1 path, which looks forCharStrings— a Type 3 font has none.
There is no width table to consult: the width is whatever the build
procedure handssetcachedevice/setcharwidth, so the procedure now runs
inside agsave/grestorewith its marks drained, and measuring paints
nothing.glyphshowraisedinvalidfonton every Type 3 font. It read
FontTypebut never branched on 3, going straight to theCharStrings
lookup. Per the PLRM it now invokesBuildGlyphwith the name directly —
bypassingEncoding, which is what letsglyphshowreach glyphs no
character code maps to — or, with onlyBuildChar, reverse-searches
Encodingfor the name and pushes the array index, retrying with
/.notdefand raisinginvalidfontonly when neither is encoded.- PostScript integers are now 64-bit, matching Ghostscript, which fixes the
standard LCG idiom PostScript programs use for pseudo-randomness:
/seed seed 1103515245 mul 12345 add 2147483648 mod def. On 32-bit integers
the product overflowed, promoted to a real, andmod— which is
integer-only — raisedtypecheck. Widening only the real fallback would not
have fixed it: the product needs 55 bits and a real carries 53, so the seed
would have come out one too high and every later draw would have diverged
silently from what other interpreters produce. PLRM Appendix B's 32-bit
range is listed under "Typical Limits" for interpreters "running on 32-bit
machines" which "do not necessarily apply to all PostScript
implementations", so this is not a conformance change. Overflow past the
64-bit range still promotes to a real.bitshiftis correspondingly 64-bit
wide, andcviaccepts the wider range. clippathreturned the page in device space instead of current user
space, so a program that had transformed its coordinate system got a clip
rectangle dragged along with the transform. Theclippath fillidiom for
painting a background then filled an offset region and left part of the page
bare — visible in the tiger EPS, whose grey backdrop was displaced by its
%%BoundingBoxorigin. The default clip is a fixed region of the device, so
it is now derived with the default CTM;pathbboxandfillmap it back
through the current CTM, which is what puts it in user space for the caller.
Ghostscript's values now match exactly under translate, scale and rotate.cvion a long integer-valued string was off by one. The string scanner
returnedf64, so(22358003463039195) cvicame back as...196after the
round trip through a 53-bit mantissa. Integer literals now stay integral.
Added
- The CLI reports a page that was painted but never shown. A program that
paints marks and then ends without a matchingshowpageleaves them on a
page the device is never asked to emit, and the page is discarded. That is
correct — it is what the PLRM specifies and what Ghostscript's file devices
do — but it was indistinguishable from a broken renderer: no file appeared
and nothing said why. The warning distinguishes a program that produced no
output at all from one that lost only its trailing page. Interpreter::warnings()surfaces the same diagnostic to library
callers, where the silence was worse:render()returnedOk(vec![]), an
empty page list that reads as a legitimate result. New public types
ExecWarningandExecWarningKindinstet::diagnostics; the CLI shares
the detector, so the two cannot drift. Programs that installnulldevice
are exempt — that is the PLRM-sanctioned way to ask for no output, so marks
left unemitted are the point rather than a mistake.--pagesets the page size for PostScript/EPS input — a named size
(letter,legal,tabloid,ledger,executive,a0-a6,b4,b5)
orWIDTHxHEIGHTin points, with an optional-landscape/-portrait
suffix that swaps the dimensions. There was previously no way to render a
plain%!PSprogram whose artwork is larger than the default page:
%%BoundingBoxsets the page only for EPS — for a non-EPS document DSC
makes it a description of the artwork's extent, not a page-size request, so
both stet and Ghostscript fall back to US Letter and clip.--page
overrides an EPS%%BoundingBoxwhen both apply, and is rejected for PDF
input, whose pages carry their own size.GlyphCache::by_type3_name, a name-keyed Type 3 glyph cache.glyphshow
can name a glyph that no character code maps to, which leaves nothing for
the existing code-keyed cache to key on.
WebAssembly
stet-wasm0.2.0. Its JavaScript API is unchanged, but the browser
build inherits everything above, so rendering output moves:clippath
backgrounds fill the page, Type 3 fonts that previously raised
invalidfontrender, and PostScript programs using the standard LCG for
pseudo-randomness run instead of failing. A minor rather than a patch
because the pixels change, not because anything you call does.