Skip to content

Releases: edadma/texish

v0.26.0 — Tamil, and a release you can install

Choose a tag to compare

@edadma edadma released this 27 Jul 03:31

A minor release with one new script and one new asset. Tamil is the fifth Indic script texish shapes, and
every release from this one on carries the font catalogue and the packages as a downloadable tarball — so a
downloaded binary is a complete installation rather than the compiled-in core on its own.

Tamil

\font tamil sets Tamil, shaped through the same IndicScript framework as Devanagari, Bengali, Gurmukhi
and Telugu, with Noto Serif Tamil joining the bundled catalogue in regular and bold.

Tamil turned out to need a change to shared behaviour, for a reason worth stating. The framework lifted a
pre-base vowel sign to the front of its cluster, which is right for the first three scripts — but only
because their virama is consumed by a half-form or a conjunct ligature before the sign is placed, so nothing
stands between the front of the cluster and the base and the two placements coincide.

Tamil keeps the virama visible as the pulli. A silenced consonant is a complete letter, not a half-form, and
the sign leaps only over the consonant it belongs to: க்கே sets ka, pulli, the ee sign, ka — not ee,
ka, pulli, ka. So IndicScript gains preBaseMatraBeforeBase, and reorderPreBaseMatra now takes the
font's halant glyph so it can insert after the last virama the cluster still shows, falling back to the
front of the cluster when a ligature has swallowed them all (க்ஷே → ee, ksha).

Also handled: no reph, the three two-part vowel signs (ொ ோ ௌ) and their canonical decomposition, the
short-i staying post-base unlike Bengali's, and the two surviving Sanskrit conjuncts — க்ஷ ksha and
ஸ்ரீ shrii, each one ligature. The bundled face carries only akhn, abvs and psts in GSUB, so most of
what Tamil needs is reordering rather than substitution.

Thirty new tests, and every glyph sequence asserted at the font level was confirmed against hb-shape.
Demo: scripts/tamil-demo.script.

A release you can install

Until now a release attached three bare binaries. Download one and you got the compiled-in core: \use{diagram}
failed, Hebrew failed. Self-location worked perfectly and had nothing to find.

Every release now also attaches texish-<version>-share.tar.gz — the font catalogue and the packages,
about 92MB compressed, laid out under a share/texish/ prefix. Unpack it at the prefix holding the binary
and the installation is complete, with no wrapper script and no environment variable:

curl -L -o ~/.local/bin/texish \
  "https://github.com/edadma/texish/releases/download/v0.26.0/texish-0.26.0-macos-arm64"
chmod +x ~/.local/bin/texish

curl -L "https://github.com/edadma/texish/releases/download/v0.26.0/texish-0.26.0-share.tar.gz" \
  | tar -xz -C ~/.local

The archive is built deterministically — sorted members, zeroed timestamps and ownership, no gzip mtime — so
rebuilding it against an existing tag produces the same bytes, and a checksum a package manager has pinned
stays valid. A .sha256 is attached beside it.

A Homebrew formula template ships in the repository at packaging/homebrew/, with the version and checksums
left as markers and a README covering how to fill them in.

Rendering the demos in CI

Three defects shipped in the previous release that ~1500 unit tests could not see. They were all invisible
for the same structural reason: the suite runs from the checkout, where \use searches . and ./packages
and the font tree sits at the repository root, so everything is always found — whether or not an installation
would have found it.

tools/render-corpus.sh renders every demo in scripts/ with a real binary from an empty working directory,
in the two configurations a user can actually be in. With nothing installed, the outcome is compared exactly
against a checked-in list of the demos that render from the compiled-in core alone, in both directions, so a
demo silently dropping out of that set fails the build. Installed in a prefix and reached without
$TEXISHHOME, all 36 must render — which exercises self-location too. A demo that fails must also fail for
the right reason: a missing face or a missing package, not a crash wearing the same exit code.

It runs in .github/workflows/ci.yml, which is the first workflow in this repository to run tests at all.

Fixes

  • The installation and CLI reference pages named a build target that does not existtexishNative/nativeLink
    producing native/target/scala-3.8.4/texish, where it is texishCli/nativeLink producing
    cli/target/scala-3.8.4/texish-cli.

A note on API

IndicScript.reorderPreBaseMatra gained a fourth parameter. The trait is public with no private[texish],
so this is technically a breaking change, though it is an internal extension point that nothing outside the
engine plausibly implements. It is on the list to be narrowed before 1.0.

v0.25.0 — Zero-configuration shipping: an embedded core, and an installation that finds itself

Choose a tag to compare

@edadma edadma released this 26 Jul 20:35

A minor release about shipping: texish now works as a plain library dependency with nothing installed and
nothing configured, and an installed copy finds its own fonts and packages without an environment variable.
Getting there meant deciding what belongs inside the artifact and what does not, which is where the breaking
changes come from.

Nothing to configure

The core is compiled into the artifact as base64 and is there on every platform:

  • Latin Modern — the roman body with its bold, italic, slanted and small-caps cuts, plus the sans and
    typewriter roles.
  • Latin Modern Math — the default math font.
  • New Computer Modern, all four cuts — the glyph-fallback face.
  • JetBrains Mono, regular and bold — the face \code sets a listing in.

Plus the base and document packages. So a program that adds texish as a dependency and configures nothing
sets an ordinary document: Latin, Greek, Cyrillic, mathematics, syntax-highlighted source code.

Two of those were shipping broken before and nobody had noticed. Glyph fallback is configured from New
Computer Modern, which was not embedded, so every zero-configuration install drew missing-glyph boxes for
the first Greek or Cyrillic word. And \code's TextMate grammars were compiled in while the face they are
drawn in was not, so any document with a listing failed outright — including the project's own flagship demo.
Both were found by rendering every demo against a binary with no font tree beside it, which is a thing the
1500-test suite structurally cannot catch.

An installation finds itself

A packaged texish locates its own executable and looks upward for a share/texish/ directory, or a fonts/
and packages/ beside it. A package needs no wrapper script and no environment variablebin.install
and share.install is the whole formula. It works the same invoked by absolute path, through $PATH, or
through a package manager's link farm.

Install.configure() is in the Native library rather than in the command-line tool, because the tool is not
the only program that needs it: an application embedding texish, whose package depends on texish's, has the
same question to answer. It searches from the executable path both as reached and as symlink-resolved, which
are two different installations — the resolved path lands in the versioned directory holding a program's own
data, while the path as reached lands in the shared prefix, which is the only way a program finds files
belonging to a different package.

$TEXISHHOME still works, as a fallback for a tree in neither place.

Fonts: a core and a catalogue

The full bundled set is 151MB, far too much to compile in, so it stays on disk and a host asks for it:

Typesetter.home = "/opt/texish"   // where the fonts/ and packages/ live
val t = new CairoPDFTypesetter("out.pdf")
t.loadBundledCatalogue()          // then ask for the families

FontSource replaces the ad-hoc root probing. A source answers with a file or with bytes, whichever it holds,
and a file wins where both are available since a backend reads a face from a path lazily. registerFontSource
and clearFontSources are the general form; Typesetter.home is the one-liner.

Loading the catalogue is tolerant, because a font tree may be partial — and it now records what it skipped, so
a missing family gets a diagnostic that points at the installation rather than at the document:

typeface 'hebrew' is one texish bundles, but its font files were not found —
no font source has 'fonts/NotoSerifHebrew/NotoSerifHebrew-Regular.ttf'

Naming a bundled family when the catalogue was never loaded says that instead, and a name texish does not
bundle still gets the bare "not found". The three are fixed in three different places, so they read
differently.

Mathematics needs no package

The math package is gone; its eleven macros are built into the engine. The line it drew through the standard
operator set was arbitrary — \tan built in, \arctan not — and eight of the eleven were plain LaTeX rather
than the amsmath additions the package claimed to supply.

\arcsin, \arccos, \arctan and \Pr join the standard operator names (\Pr with limits, like \max).
\bmod is an upright binary "mod"; \pmod{m}, \mod{m} and \pod{m} set a congruence's modulus off by a
quad. \implies, \impliedby and \iff are heavy arrows with a thick space on either side. $\arcsin x$
needs no preamble.

Fixes

  • Footnotes were set in literal black rather than the document's ink, so a document with a coloured pen
    had black footnotes. They now take the colour in force where the footnote sits.
  • Uncoloured picture marks were black too — an arrow, arrowhead or placed glyph with no \stroke or
    \fill of its own fell back to a fixed black instead of the pen. A picture that names no colour now draws
    in the document's ink and follows it into a dark scheme.
  • \loadfont now resolves a relative path against the document's own directory, so a font kept beside the
    document is found however the host was launched.
  • A \loadfont naming a file nothing has is an error rather than a silently registered face over a bad
    path.

Breaking changes

  • Typesetter.fontsDir is now Typesetter.home. It names a directory holding both fonts/ and
    packages/ — the programmatic $TEXISHHOME — and is consulted by the font search and by \use alike.
  • TEXISH_FONTS_DIR is gone. TEXISHHOME is the only environment variable, and is now a fallback rather
    than the documented route.
  • \use{math} no longer resolves. Delete the line; everything it defined is built in.
  • Only base and document are compiled into the artifact. Every other package — diagram, plot,
    book, usfm, railroad, music, … — resolves from a packages/ folder on disk. An installed texish
    finds it automatically; a library consumer needs Typesetter.home.
  • The bundled font families beyond the core are opt-in, through loadBundledCatalogue(). The
    command-line tool calls it for you.
  • The SMuFL music faces are catalogue fonts, and music is not embedded, so the two travel together.
  • Scala.js is no longer in the cross-build. The browser backends are kept on disk and in git, and
    build.sbt, the README and the browser guide all say how to bring them back; the effort of keeping a third
    platform green was not paying for itself.

v0.24.0 — Telugu, Thai line breaking, French spacing, and a run of shaping fixes

Choose a tag to compare

@edadma edadma released this 25 Jul 18:48

A minor release: a new script, French typography, and a run of shaping and line-breaking fixes — most of
them found by diffing texish against HarfBuzz rather than by anyone reporting them.

Telugu

texish now sets Telugu (\font telugu, with a bold cut). Telugu builds downward: a consonant joined by
the virama is drawn as a subscript beneath the base, which inverts the base — a conjunct's base is its
first consonant, not its last — and a consonant with its vowel sign commonly fuses into a single drawn
glyph. A vowel sign belongs to the base, so it is moved back across the subscripts to reach it: ప్రేమ
joins its vowel to the pa, not to the subjoined ra. The ai sign is split into the two parts the font
draws, and a word-initial ra with a virama forms no reph.

Thirty everyday Telugu words shape glyph for glyph as hb-shape does. Noto Serif Telugu is bundled;
there is a guide page and a demo.

Thai line breaking

Thai is written without spaces between words, so a run of it reached the line breaker as one box and
overflowed the measure. The breaker now offers somewhere to break between orthographic clusters, never
parting a vowel or tone mark from its consonant nor stranding a pre-posed vowel from the consonant that
follows it. Proper Thai breaks fall at word boundaries and finding those needs a dictionary, which
texish does not carry, so a cluster break may land inside a word — the limitation is documented.

French spacing

French sets a space before the colon, semicolon, exclamation and question marks, and inside its
guillemets. texish set an ordinary interword space there, which is wrong twice over: it stretches when
the line is justified, so the mark drifts from the word it belongs to, and it offers the breaker a place
to break, so the mark is carried alone to the head of the next line.

Declaring the document French — \usehyphenation{fr}, or any regional tag built on it — now spaces
these marks the way French does: a full space before the colon, half that before the rest, neither
stretching nor breaking. Type the space or leave it out as you prefer, « Oui ! » and «Oui!» set
alike. The comma and full stop, which French sets tight as English does, are untouched, as is every
other language.

Breaking change

Typesetter.hyphenationLanguage is now Typesetter.language. It decides both the hyphenation
patterns the line breaker uses and the typography a language sets its punctuation by, so naming it after
hyphenation alone had stopped being true. No document syntax changes: \usehyphenation,
\loadhyphenation and \language are as they were.

Fixed: hyphenation patterns broke French, Spanish, Italian and Portuguese

A TeX comment runs from its % to the end of the line. The pattern-file reader dropped only the
whitespace-separated tokens that began with one, so the prose of a comment was read as patterns — the
French file heads its table with % phonetic patterns % etymological patterns % — and a brace inside a
comment ended the pattern block early, losing every pattern after it.

The English file is almost uncommented and so came out right, which is exactly why this went unseen.
Every other bundled language is heavily commented and broke words where no break belongs: French set
fr-ançais, pr-o-phète, par-ole, dif-fé-r-ent, ré-surr-ec-tion, none of them possible breaks,
and lost others entirely. All four now break their words where the language breaks them; English is
unchanged.

Fixed: whole GSUB lookups were being skipped

Two kinds, both silent, and both wider than the script that exposed them.

Context formats 1 and 2 were never read. Only the coverage-based format 3 was, so the rule- and
class-based lookups parsed to nothing and were passed over — and Indic fonts write a great deal of their
behaviour that way. Devanagari विद्या shaped to six glyphs where HarfBuzz gives four, the द्य never
forming.

A contextual lookup named by another contextual lookup was not followed. Noto Serif Telugu reaches
its subjoined ra through two levels of chaining context, so క్ర kept the generic subscript instead of
the variant drawn under a ka.

Fixed: vocalized Arabic stacked the shadda and its vowel the wrong way up

A letter carrying both is stored with the vowel first — that is canonical order, the vowel's combining
class being the lower — but is drawn the other way round, the shadda on the letter and the vowel above
it. The marks of a syllable are now put into drawing order before shaping, following Unicode's rules for
Arabic mark rendering, so both ways of typing a shadda and its vowel converge. In Amiri the wrong order
had also cost the word for God its calligraphic ligature.

Fixed: pointed Hebrew set the dagesh beside its letter, not inside it

A face cut for pointed Hebrew draws a letter and the point inside it as one glyph and gives no anchor for
placing that point alone. Hebrew ran no substitution at all, so in the bundled Ezra SIL — the scholarly
face for Biblical Hebrew, whose one job this is — the dagesh landed beside its letter. The font's own
composition feature now runs, with the points first put into drawing order so the rule can match, and
whether a pair combines is left to the font: Ezra combines a letter with its dagesh but leaves an alef
and its patah to be placed by anchor, and Noto Serif Hebrew combines nothing at all. Both are set
correctly without any choice on your part.

Fixed: line breaking

A tie could still be broken. The greedy setter — the fallback used when Knuth-Plass finds no solution
within the tolerance — treated every glue as a place to break, ignoring the flag that says otherwise.

A hyphenated word could be given a second hyphen. The optimal breaker hyphenated a word that already
carried one, and a break offered beside it ended the line with the word's own hyphen and the one added
for the break: Croyez--. The greedy setter never had the fault, breaking such words only at their own
hyphens; the two now agree.

A spacing mark lost its advance. Marks were assumed weightless, but Indic fonts carry spacing
subjoined forms that the font classes as marks, so syllables overlapped. The pen now moves by a glyph's
own advance unless the glyph attached to another.

Demos and docs

New: a Telugu guide page and demo, a Telugu section in the command reference, and an Ezra SIL section in
the Hebrew demo — which had only ever exercised the Noto face, and so never showed the fault above.

v0.23.0 — Review fixes: glyph-fallback weight, Korean breaking, error typing

Choose a tag to compare

@edadma edadma released this 25 Jul 03:29

A minor release: the fixes from a whole-codebase review. Two of them are user-visible, and one removes a public type.

Breaking change

ParserException is gone, folded into TexishException (io.github.edadma.texish). Catch that instead. The two types encoded one concept — differing only in whether a source position was known yet, which is a field and not a type — and the name was a leftover from when the parser was a separate library, reading oddly on an error about a font.

Fixed: bold and italic were dropped on Cyrillic and Greek

A codepoint the current face has no glyph for is set from the fallback face (New Computer Modern). That substitution always used the fallback's regular cut, so Cyrillic or Greek inside a bold or italic run silently lost its weight and slant — in a single \bold{Привет Bold} the Cyrillic set regular while the Latin beside it set bold, breaking the weight mid-phrase.

The fallback now resolves the cut matching the surrounding text, and the bold, italic and bold-italic cuts of New Computer Modern are bundled so there is one to resolve to. The family role is deliberately not carried over: the fallback stands in for a face's coverage, not its family, so Cyrillic inside \mono is set in the fallback's roman rather than being sent to the typewriter family, which is no likelier to have the glyph.

Fixed: unspaced Korean ran off the page

Korean breaks at its interword spaces like Latin, which is right for prose but left no escape hatch: a run with no space in it — a long compound, a spaceless title, a very narrow column — had no legal breakpoint at all and overflowed the measure.

A break between two Hangul syllables is now offered at a heavy penalty, so the breaker takes one only when no break at a space can be made to fit, the same bargain TeX strikes with hyphenation. Ordinary Korean prose is untouched: at a normal measure it breaks on exactly the same words as before.

Fixed: a bug in texish was reported as a mistake in your document

Every failure used to arrive as the same thing. The processor caught RuntimeException indiscriminately and reported whatever it found at the current token's position, so a null dereference in layout was presented to the author exactly as a misspelled font name was — and the original exception was dropped, taking with it the stack trace that would have located the bug.

TexishException now marks the errors texish raises on purpose, where the document is at fault. Anything else escaping the engine is labelled internal error (…), names the exception class, and keeps the original as its cause. For an embedder the two are worth telling apart: one is your user's mistake to fix, the other is a bug report.

Added

  • aliasTypeface(alias, target) — a typeface with a second name (\font hindi, \font korean) now shares the faces its family already opened instead of loading the same files again under the new name.

Docs

The glyph fallback is now documented in the command reference (Cyrillic and Greek set in ordinary text with no setup), and the installation guide describes how errors reach an embedder.

Suites are green at JVM 1398. Native CLI binaries for Linux (x86_64, arm64) and macOS (arm64) attach below; other platforms use the JVM build.

v0.22.0 — Gurmukhi (Punjabi) + Japanese & Korean scripts

Choose a tag to compare

@edadma edadma released this 25 Jul 00:44

A minor release adding two more of the world's most-read scripts: Gurmukhi (Punjabi) and the Japanese and Korean members of the CJK family.

New: Gurmukhi (Punjabi) syllable shaping

Gurmukhi joins Devanagari and Bengali on texish's Indic-shaping framework, set a syllable at a time from ordinary Unicode text:

  • Subjoined pairin forms — a virama-joined consonant hangs below the base (ਪ੍ਰੇਮ, ਸ੍ਰੀ). Unlike Devanagari and Bengali, Gurmukhi has no reph: a joined ra always subjoins, never rising as a mark.
  • Pre-base sihari reordering — the i-sign is typed after its consonant but drawn before it (ਦਿਨ, ਪਿਤਾ).
  • Addak, tippi and bindi placed as marks over the base by GPOS (ਇੱਕ, ਪੰਜਾਬ, ਸਿੰਘ).

Select the bundled Noto Serif Gurmukhi with \font gurmukhi (or \font punjabi), regular and bold.

New: Japanese and Korean

The three CJK scripts share the Han characters but draw them with region-specific forms, and Korean adds its own Hangul — so each region gets its own cut of Noto Serif CJK, in regular and bold.

  • Japanese\font japanese (alias \font cjkjp). Kanji set with their Japanese letterforms rather than the Chinese ones, plus hiragana and katakana. Sets like Chinese, with the same kinsoku inter-character breaking.
  • Korean\font korean (alias \font cjkkr). Renders the Hangul syllables the Chinese faces have no glyph for at all, plus Hanja.

Korean line breaking: Korean is written with spaces between words, so — unlike Chinese and Japanese — its lines break at those spaces the way Latin does, and a Korean word is never split across a line. Hangul is kept off the per-character break path (removed from CJK.isCJK).

{\font gurmukhi 14 regular ਸਤਿ ਸ੍ਰੀ ਅਕਾਲ!}

{\font japanese 12 regular これは日本語の組版の例です。}

{\font korean 12 regular 이것은 한국어 조판의 예입니다.}

Engine

  • New Gurmukhi Indic front end (U+0A00–U+0A7F), registered alongside Devanagari and Bengali; startsWithReph overridden to false.
  • New bundled CJK faces \font cjkjp/japanese and \font cjkkr/korean (Noto Serif CJK JP/KR), each regular and bold.
  • CJK.isCJK no longer treats Hangul as break-anywhere, so spaced Korean breaks at its word spaces.

Tests

  • Gurmukhi: font-free cluster tests (GurmukhiTests) + font-level GSUB/GPOS tests (GsubGurmukhiFontTests) against the bundled face, confirmed with hb-shape --shaper=ot.
  • CJK: CJKFontCoverageTests (JP kanji+kana, KR Hangul+Hanja, and that the Chinese face has no Hangul) + CJKLineBreakTests (Hangul off the break path; Japanese still breaks per character).

Demos & docs

  • scripts/gurmukhi-demo.script and scripts/japanese-korean-demo.script.
  • New guide pages Gurmukhi (Punjabi) and Chinese, Japanese & Korean, plus reference updates.

Native CLI binaries for Linux (x86_64, arm64) and macOS (arm64) attach below; other platforms use the JVM build.

v0.21.1 — Pixel-native default resolution

Choose a tag to compare

@edadma edadma released this 19 Jul 17:06

A patch release: a saner default resolution for the raster backends.

The default dpi on the image backends is now 72 instead of 100

CairoImageTypesetter (Native) and Graphics2DTypesetter (JVM) apply a device transform of dpi / 72 when mapping the engine's point coordinates onto their pixel surface. The default was 100, a value that silently scaled every layout by 100/72 ≈ 1.389× — so an embedder who set paperwidth = 1280 and constructed a backend with no argument got a 1778-pixel surface.

The default is now 72, so the device transform is the identity and one point renders as exactly one pixel: a page of N points is an N-pixel image, with no hidden scaling. This is the least-surprising default for a library whose raster output is mostly pixel-native (video frames, GPU textures, GUI previews), and it matches the point-native PDF backend so switching PDF↔PNG no longer rescales coordinates. Pass a higher dpi (e.g. 144 or 216) to supersample the same layout for crisper output.

This only affects code that constructs a raster backend without a dpi argument. The command-line tool is unaffected — it always passes an explicit resolution (-r, default hd) — and every test already passed an explicit value.

Suites are green at JVM 1360 / JS 1234 / Native 1250.

Native CLI binaries for Linux (x86_64, arm64) and macOS (arm64) attach below; other platforms use the JVM build.

v0.21.0 — The base package and engine-native text commands

Choose a tag to compare

@edadma edadma released this 19 Jul 16:18

A minor release: a new lightweight base package, engine-native text commands in place of the LaTeX-style aliases, and a pixel-native option for the CLI.

Breaking changes

The LaTeX-spelled markup aliases are gone — texish is not aiming at LaTeX source compatibility, and each was only a second name for a command the engine already has. Rewrite call sites to the engine-native names:

removed use instead
\emph{…} \textit{…} \italic{…}
\textbf{…} \bold{…}
\textsl{…} \slanted{…}
\textsc{…} \smallcaps{…}
\texttt{…} \textsf{…} \textrm{…} \mono{…} \sans{…} \serif{…}
\textnormal{…} {\normalfont …}
\textsuperscript{…} \textsubscript{…} \textsup{…} \textsub{…}
\ifthenelse{c}{a}{b} \if {c} a \else b \fi
\equal{a}{b} \={a}{b}

The family-role forms \texttt / \textsf / \textrm are renamed to the plain wrapping primitives \mono / \sans / \serif, so the engine's shape and role commands now share one naming convention: \bold \italic \slanted \smallcaps \mono \sans \serif. The declarations (\bfseries, \itshape, \scshape, \ttfamily, …) are unchanged.

New: the base package

The everyday conveniences that used to live inside document are now a lighter package on their own:

\use{base}

base carries a font-size ladder (\tiny\Huge), the vertical skips (\smallskip / \medskip / \bigskip), single-line alignment (\centerline / \leftline / \rightline, \centering, \rlap / \llap), the center / flushleft / flushright and quote / quotation environments, and the \TeX / \LaTeX / \TeXish logos — and nothing else. A page that wants only these — a caption, a flyer, a title card — can load \use{base} and skip titles, sections and page numbering. \use{document} now begins with \use{base} and adds the article furniture on top, so every existing document keeps working.

CLI: a numeric DPI for -r

--resolution now accepts a DPI number in addition to the named sizes. At -r 72 one point renders as exactly one pixel, so a document laid out in points reads directly in pixels — handy for fixed-size raster targets such as video frames:

texish frame.texish -t png -r 72     # a 1280x720pt page becomes a 1280x720 PNG

Demos

A new scripts/lowerthird-demo.script shows a broadcast-style lower third for compositing over video: a translucent-black panel across the foot of a transparent frame, with a large scripture verse set in EB Garamond — built from \pagecolor{transparent}, \colorbox[alpha] and a \parbox, rendered at -r 72.

Suites are green at JVM 1359 / JS 1234 / Native 1249.

Native CLI binaries for Linux (x86_64, arm64) and macOS (arm64) attach below; other platforms use the JVM build.

texish 0.20.4 — Fix \parbox/\minipage newline leak

Choose a tag to compare

@edadma edadma released this 19 Jul 02:03

A patch release: a \parbox / \minipage newline-leak fix.

Fix: a trailing newline in a box body no longer leaks a break into the following text

A source newline at the end of a \parbox or \minipage body left the pending-newline state set; on return to the surrounding paragraph the next newline was then read as a second one and forced a spurious paragraph break — an empty full-width line the line-setter reported as an underfull box. It surfaced with the natural way to write a fixed-size band:

\colorbox[0.6]{black}{\parbox[c][180pt][c]{\linewidth}{
  ...content on its own lines...
}}

Both builders now clear the pending-newline state when they finish, as they already did on entry, so content laid out on its own lines inside a full-width box no longer warns.

Suites are green at JVM 1352 / JS 1227 / Native 1242.

Native CLI binaries for Linux (x86_64, arm64) and macOS (arm64) attach below; other platforms use the JVM build.

texish 0.20.3 — Fixed-height \parbox and \minipage

Choose a tag to compare

@edadma edadma released this 19 Jul 01:00

A patch release: \parbox and \minipage gain a fixed height.

Fixed-size boxes

\parbox and \minipage now take the rest of LaTeX's signature — \parbox[pos][height][inner-pos]{width}{body}. The optional [height] fixes the box height, and [inner-pos] places the content within it: t (top), c (centre), b (bottom), or s (stretch), defaulting to the outer [pos]. The box then keeps its size no matter how much text it holds (the text overflows if it does not fit), so a block of flowing text can occupy a fixed region.

This makes a fixed-size band of normal, flowing text — a video lower-third, say — a fixed-height \parbox inside a translucent \colorbox:

\pagecolor{transparent}
\vfill
\noindent\colorbox[0.6]{black}{\parbox[c][180pt][c]{\linewidth}{
  \color{white}\font lmroman 40 {sans bold}A Lower-Third Heading

  \color{white}\font lmroman 22 {sans}A paragraph of normal flowing text beneath it, which
  wraps as usual while the band around it stays a fixed 180pt tall.
}}

Suites are green at JVM 1351 / JS 1226 / Native 1241.

Native CLI binaries for Linux (x86_64, arm64) and macOS (arm64) attach below; other platforms use the JVM build.

texish 0.20.2 — Page-background colour and translucent colours

Choose a tag to compare

@edadma edadma released this 18 Jul 17:46

A patch release: a page-background colour primitive and translucent colours throughout.

\pagecolor

\pagecolor[alpha]{colour} sets the colour painted across the whole page, under all content. With a translucent or transparent colour the page composites correctly when the output is used as an overlay — a video lower-third, for instance:

\pagecolor[0.6]{black}   % a 60%-opaque black band the video shows through
\pagecolor{transparent}  % clear page; only the drawn content is opaque

It applies to the document's pages, so give it in the preamble. All four backends now paint the page background consistently: the PDF backend, which previously left the page unpainted, now fills it like the image, SVG and Graphics2D backends already did (so a transparent PDF page is possible too).

Translucent colours

Any colour may now carry alpha, three interchangeable ways:

  • an optional [alpha] (0–1) on \color, \textcolor, \pagecolor and \colorbox\color[0.5]{firebrick}
  • an eight-digit #RRGGBBAA code in any colour string, so it works everywhere a colour is taken, including \fill, \stroke and \fcolorbox\colorbox{#00000066}{…}
  • the keyword transparent

The two forms are equivalent: \textcolor[0.5]{firebrick}{…} and \textcolor{#b2222280}{…} set the same half-opaque word.

Suites are green at JVM 1348 / JS 1223 / Native 1238.

Native CLI binaries for Linux (x86_64, arm64) and macOS (arm64) attach below; other platforms use the JVM build.