Added
- Transparent page backgrounds:
--transparentfor--device png,
andPageBackgroundin the library. Pages normally render onto white
paper; with the option, every pixel no mark covers is left at alpha 0 and
the output is straight-alpha RGBA, so artwork (EPS, AI, PDF) can be
placed over other content with its unpainted areas clear. PostScript and
PDF input both honour it, on every page. In the library,
InterpreterBuilder::page_background(PageBackground::Transparent)makes
Interpreter::renderreturn clear pages, andstet-renderadds
render_to_rgba_with_backgroundandSkiaDevice::set_page_background,
andstet-pdf-readeraddsPdfDocument::render_page_to_rgba_with_background
(withPageBackgroundre-exported);render_to_rgba,
render_to_rgba_with_layersandrender_page_to_rgbakeep their
signatures and white paper. Contributed by @jungseohaan (#4). stet-fontswrites CFF and converts Type 1 charstrings to Type 2.
cff_writerserialises a CID-keyed CFF font (andread_cid_font/
CidFont::subsetread and subset one);type1_to_type2converts a
Type 1 charstring to Type 2, keeping stem hints, hint replacement (as
hintmask) and flex;cid_type0reads the glyph data of a CIDFontType 0
font with Type 1 charstrings. They are what PDF output of those fonts is
built on.setoverprintmodeandcurrentoverprintmode, the PostScript
spelling of PDF's/OPM. They are Adobe extensions outside the PLRM,
which Ghostscript also provides. Withtrue setoverprintmodeand
overprint on, a DeviceCMYK paint leaves the plates whose component is 0
untouched, so0 1 0 0 setcmykcolorover cyan gives blue rather than
magenta, and0 0 0 0 setcmykcolorpaints nothing, as in Ghostscript.
pdftops output tests for the operator before calling it, so until now
every/OPM 1in a PDF converted to PostScript was silently treated as
mode 0. Converting PostScript to PDF now carries the mode into/OPM.
As withsetoverprint, images do not overprint yet.
Changed
stet_core::graphics_state::GraphicsStatehas a new field,
overprint_mode, whichsetoverprintmodesets (see Added). Code that
builds aGraphicsStatewith a struct literal no longer compiles; use
GraphicsState::new()and set the fields you need. Reading the struct is
unaffected. It is the interpreter's graphics state, public only because
its module is, and will be marked#[non_exhaustive]in a later release
likePdfGraphicsState.- The embedded URW++ base 35 fonts are distributed under the SIL Open
Font License 1.1 instead of the GNU AGPL v3 with a font exception. In
2017 URW++ licensed the Version 2.0 fonts under a choice of AGPL, LPPL
1.3c or OFL 1.1; stet takes the OFL option. The fonts are unchanged. A
program that linksstet,stet-pdf-readerorstet-wasmno longer
carries AGPL-licensed data: the OFL allows bundling the fonts with any
software, commercial included, as long as they are not sold on their own
and their licence goes with them.LICENSE-URW-FONTSin each of those
crates, andTHIRD-PARTY-NOTICES.txtin the release archives, carry the
OFL text and the basis for it.
Fixed
-
A bare
stetnow opens the viewer when a page is shown. With no
input file, stet starts the PostScript REPL as before, and the first
showpageopens the viewer on the page drawn.--helpand both READMEs
described this behaviour, but a barestetselected thepngdevice,
soshowpagein the REPL wrote nothing and opened no window. A session
that never shows a page still opens no window. Builds without the
viewer are unchanged. -
-owithout--devicenow writes a PNG in viewer builds. The
--helpexamplesstet -o out.png --pages 1 doc.pdfand
stet -o 'p-%03d.png' doc.pdffailed with "--output does not apply to
--device viewer", naming a device the command never asked for.-o
now selectspngunless a device is given, as headless builds
already did. -
The REPL banner shows the real version. It printed
stet Version 0.1.0 (2026-02-25)whatever the release, and
revisionstringandrevisiondateinsystemdictheld the same stale
values, and the integerrevisionwas always1. They now carry the
release version and date;revisionis the version with two digits
each for minor and patch, so 0.8.2 is802. -
setoverprintnow works for spot colours in PostScript. A
Separation or DeviceN colour painted with overprint on knocked out the
process colours beneath it, where PDF input with the same content
overprinted correctly. Now only the colorants the colour space names are
painted: a spot over cyan keeps the cyan, and/Separation /Magentaor
a DeviceN of[/Yellow …]leaves the other process plates alone. This
covers fills, strokes and text; images andimagemaskdo not overprint
yet. DeviceCMYK still paints all four plates unlesssetoverprintmode
selects mode 1 (see Added). Two related bugs went with it: a cached Type 3 glyph kept
the overprint setting from when it was first drawn, and PostScript
overprint turned off entirely on pages small enough to render in one
piece, so the same file could overprint at 300 dpi and not at 72. -
Text in CIDFontType 0 fonts built with
StartDatais drawn. These
CID fonts carry Type 1 charstrings reached through a CID map, and pdftops
writes every CFF-based CID font this way, Chinese, Japanese and Korean
text and subset OpenType fonts included. stet read the glyph data only to
skip it, soshowraisedinvalidfontand the text vanished: 161 files
in the test corpus lost some or all of theirs.show,stringwidth,
charpathandxshow/yshow/xyshownow draw them, in both writing
modes, with eachFDArrayfont's ownFontMatrix,lenIVand
subroutines. A CID the font has no glyph for shows CID 0, as the CIDFont
specification requires, instead of an empty advance.Converting such PostScript to PDF embeds the fonts, subset to the CIDs
used, as CFF (/CIDFontType0C, the only CIDFont program PDF has for
them): each Type 1 charstring is converted to Type 2 with its hints,
hint replacement and flex kept. CFF CID fonts loaded through
FontSetInitare embedded the same way. Both used to fall back to an
unembedded simple font, which garbled the text. -
TrueType CID fonts find their glyphs through
CIDMap. A Type 2
CIDFont maps each CID to a TrueType glyph through itsCIDMaptable
(PLRM Table 5.17), which pdftops writes for every CID-keyed TrueType
font it converts. stet used the CID itself as the glyph index, correct
only when the map is the identity, so text in subset fonts came out as
gibberish (22 files in the test corpus). PDF output did worse: it looked
CIDs up in the font's TrueTypecmaptable, which these fonts do not
have, so every glyph became.notdef. Both now readCIDMapin its
string and array forms, and in the integer and dictionary forms
Ghostscript also accepts; a CID the map does not define shows CID 0's
glyph. -
Vertical CID text follows the PLRM, and PDF output keeps it
vertical. A glyph gets its vertical (writing mode 1) metrics from the
CIDFont'sMetrics2orCDevProc(PLRM 5.9.2), which stet now
supports;CDevProcmay change widths in horizontal text too. A font
with neither has one set of metrics, and the PLRM ignores the writing
mode for it: its text runs horizontally, as in Ghostscript. stet instead
gave every CIDFont default vertical metrics, and readDW2, which is a
PDF key, not a PostScript one; pdftops' conversions of vertical text,
whose fonts carry no vertical metrics, now render as Ghostscript renders
them. PDF output wrote every CID font with a horizontal CMap, so
vertical text ran across the page; it now usesIdentity-Vwith/W2
holding the metrics the interpreter used, and a CIDFont shown in both
directions becomes one PDF font per direction. -
Loading a CFF FontSet leaves the dictionary stack as it was, and
defines the FontSet. A FontSet file begins theFontSetInitProcSet
and has noendafter its binary data (Adobe TN 5176, Appendix E), so
StartDatamust end it, as Ghostscript's does; stet's left the ProcSet
on the dictionary stack for the rest of the job.StartDataalso
discarded the FontSet's name: it now defines the fonts as that FontSet
resource, and/NimbusRoman-Regular-CFF /FontSet findresourcefinds
stet's own FontSet, whose file named it differently. -
Text in PDF output keeps its spacing. Strings on one line are
joined into aTJrun spaced by the glyph widths, which were looked up
byte by byte instead of by 2-byte CID: when the page also used the CIDs
matching those bytes (CID0x0105read as CIDs 1 and 5), the next
string landed in the wrong place.ashowandwidthshowspacing on CID
text was dropped altogether. And in any font, each kern in a run was
rounded to a thousandth of an em, so a line of separately placed glyphs,
as pdftops writes, drifted by a fraction of a point by its end. All
three now match the interpreter. -
definefontno longer replaces the font a copy was made from. It
filed each font inFontDirectoryunder its/FontNamerather than
under the key it was defined with, which the PLRM requires. A re-encoded
copy keeps its original'sFontName, so defining one — pdftops does it
for every font a page uses,/F1_0from/Helvetica— silently
replaced the original, and a later/Helvetica findfontreturned the
copy with its encoding. -
PDF output keeps each encoding of a font. Two instances of one font
with different encodings — pdftops writes ZapfDingbats re-encoded beside
the standard one — shared one PDF font resource, whose encoding was
merged code by code, first come first served, so the second instance
drew the first one's glyphs. Each such instance now gets its own
resource; instances whose encodings agree, like dvips's re-encoded
copies, still share one, and the font program keeps every instance's
glyphs. -
Subset CFF CID fonts draw the right glyphs. A CID-keyed CFF font
loaded throughFontSetInithad its glyphs looked up as if each CID
were the glyph's index in the font, which holds only for a complete
font; in a subset one, as producers embed them, text drew the wrong
glyphs or none. -
Type 1 glyphs that draw without an explicit
rmovetono longer
sprout lines from the page corner. The Type 1 format lets a glyph
start drawing at the pointhsbwsets, andclosepath, unlike
PostScript's, leaves the current point in place, so a following line
needs normovetoeither. stet began such a path with a line and no
move, which the renderer drew from the device origin. This affects Type
1 fonts in PostScript and in PDF alike; pdftops' conversions of CFF
fonts rely on it. -
Separation and DeviceN colorant names given as strings are now
recognised. The PLRM lets a colorant be a name or a string, and
pdftops writes every one as a string ((Black),(PANTONE 273 C),
(All)), but stet read any string as an empty name. Under overprint,
process colorants were then taken for spots, so(Black)or(Magenta)
knocked out the other plates, and a DeviceN backdrop of(Black)plus a
spot lost its black. The GWG 3.0 gray-overprint test page converted with
pdftops now matches Ghostscript. PDF output carries the real spot names
rather than empty ones. A colorant that is neither a name nor a string is
now atypecheck, as in Ghostscript, instead of being accepted silently. -
initgraphicsandshowpageno longer reset the whole graphics
state. The PLRM hasinitgraphicsreset the transformation matrix,
path, clip, colour and line settings only, and leave everything else
alone: stroke adjustment, the font, and all the device-dependent
parameters (overprint, flatness, smoothness, transfer, halftone, black
generation and undercolor removal). stet reset all of them, and since
showpageperforms aninitgraphics, a program that set overprint or a
transfer function once lost it from the second page on. Ghostscript
keeps them. Two smaller fixes go with it:setpagedevicenow keeps the
current font, as the PLRM requires, and a clip set afterinitgraphics
inside agsaveis now undone bygrestore, which could previously
leave the inner clip in force. -
stet-cli's crates.io page no longer shows a failing docs.rs badge.
docs.rs documents libraries only, andstet-cliis a binary, so its
build has failed for every release. The badge is gone and the
crate's Documentation link now leads to the command-line usage.
Downloads
stet-<version>-x86_64-unknown-linux-musl.tar.gz is the one most people
want: statically linked, no glibc requirement, no runtime libraries, no GUI.
It is the right choice for servers, CI and containers.
The -gnu Linux build adds the desktop viewer and needs glibc 2.35 or newer
(Debian 12, Ubuntu 22.04 and later) plus X11 or Wayland and OpenGL to open a
window. Rendering to files works without them.
macOS: the binaries are unsigned, so opening a downloaded archive from
Finder trips Gatekeeper ("cannot be opened because the developer cannot be
verified"). Installing with curl avoids it entirely, because the quarantine
attribute is set by the downloading application and curl does not set one:
curl -L <asset-url> | tar xz
If you already downloaded it in a browser, clear the flag with
xattr -dr com.apple.quarantine stet.
Windows: SmartScreen will warn that the publisher is unknown; choose
More info -> Run anyway. Code signing certificates cost money and stet does
not have one.
Rendering is identical across these artifacts with one caveat: the musl
build's libm differs from glibc's in the last bits, which can shift
antialiasing coverage by a pixel or two on heavily curved PostScript
artwork (measured: 265 of 5.4M pixels on one sample, invisible in practice;
all PDF samples tested were byte-identical). Do not generate rendering
baselines with one build and compare them against another.
Verify a download against SHA256SUMS.