# BST-TIMEOUT: 600 # FOURTEEN runs of the 7.8 MB data/freetype-probe, where
# # 99-ttf-bitstream-vera does ten, 99-ttf-droid seven and
# # 99-cantarell-fonts one. The bound is deliberately the SAME
# # 600 all four of those carry, for the reason vera's header
# # gives: all five drive the same binary, whose load cost
# # dominates, and a suite whose cost is dominated by one
# # binary should not claim a different bound for it.
# # MEASURED on target -- read off the ==BST-SUITE elapsed=
# # line, not estimated -- and recorded in the design doc and
# # the test plan rather than re-edited into this comment,
# # which would cost a further image build to keep the shipped
# # suite byte-identical to the branch.
#
# source-code-pro-fonts 2.030 -- Adobe Source Code Pro, the monospace family
# designed for code, under SIL OFL 1.1. meta-openembedded/meta-oe
# recipes-graphics/ttf-fonts/source-code-pro-fonts_2.030_1.050.bb.
#
# ============================================================================
# FOURTEEN FACES, AND A FIFTEENTH FILE THAT IS THE WHOLE STORY OF THIS PORT.
# ============================================================================
#
# The recipe requires ttf.inc and then REPLACES its do_install: where the inc
# globs `*.tt[cf]`, this one globs `*.otf` and additionally installs a fontconfig
# fragment. The zip carries TTF/, WOFF/, WOFF2/ and EOT/ beside OTF/, so the .otf
# set is a DECISION of this recipe rather than a property of the tarball --
# ttf-no-extras is anchored on the extension for exactly that reason.
#
# source-code-pro-fonts /usr/share/fonts/truetype/SourceCodePro-*.otf x14
# /etc/fonts/conf.d/44-source-code-pro-fonts-fontconfig.conf
# source-code-pro-fonts-dev, -dbg empty placeholders, not installed
# source-code-pro-fonts-doc DOES NOT EXIST -- see below
#
# NO -doc PACKAGE, AND NO LICENCE FILE ON THE IMAGE. The zip's LICENSE.txt is
# never installed -- do_install writes the fourteen faces and the fragment and
# nothing else -- and FILES:${PN} is an ASSIGNMENT naming ${sysconfdir}/fonts and
# ${datadir}/fonts, so ${PN}-doc is empty and dpkg builds none. That is the
# recipe's behaviour, not this port's choice, and requirement 3 is every file the
# RECIPE DECLARES, all fifteen of which ship. pkg-no-doc-package asserts the
# absence, because "the -doc line was forgotten" and "there is no -doc package to
# install" look identical from the file layer alone. The licence is not lost:
# name IDs 13/14 inside every face carry the OFL notice and its URL.
#
# ============================================================================
# THIS PORT TAKES A GENERIC -- monospace -- AND IT IS THE FIRST FONT PORT ON
# THIS IMAGE THAT SHIPS THE CONFIGURATION THAT DOES IT.
# ============================================================================
#
# Every font port before this one either took no generic (ttf-gentium, ttf-droid,
# cantarell-fonts, terminus-font) or took one on MERIT out of fontconfig's own
# shipped ranking (ttf-inconsolata, which displaced Liberation Mono because
# 60-latin.conf ranks Inconsolata third among monospace families and Liberation
# Mono is not on that list at all). This port takes one because its RECIPE SHIPS
# A FRAGMENT THAT ASKS FOR IT:
#
# 44-source-code-pro-fonts-fontconfig.conf
# monospace
# Source Code Pro
# Source Code Pro
# monospace
#
# 44 sorts BEFORE 60-latin.conf, and prepends, so Source Code Pro goes
# to the head of monospace's family list ahead of Inconsolata's rank-3 claim.
# THE PRECONDITION IS ALSO SATISFIED, WHICH IS WHY THIS ACTUALLY BITES: all
# fourteen faces carry spacing=100 (FC_MONO) -- fontconfig derives that from the
# advance widths and this is a code face -- so there is no proportional-face
# mismatch for the sort to reject. fcq-spacing-mono in the verify awk asserts the
# precondition and fc-match-monospace here asserts the outcome.
#
# MEASURED BEFORE IT WAS ASSERTED, AND WITH A NULL CONTROL. A native fontconfig
# 2.15.0 -- the same release this image ships, built from this image's own recipe
# -- was driven over a fake root holding EXACTLY this image's font set and
# /etc/fonts tree. WITHOUT this package it answers sans-serif => Liberation Sans,
# serif => Liberation Serif, monospace => Inconsolata, system-ui => Liberation
# Mono, which is what the image itself answers, so the rig reproduces the target
# baseline and its verdict means something. WITH this package installed the ONLY
# generic that moves is monospace, to Source Code Pro; sans-serif, serif,
# system-ui, fantasy and cursive are all unchanged. This suite asserts both
# halves -- the one that moves and the ones that do not.
#
# FOUR SIBLING SUITES ASSERTED `fc-match monospace` => Inconsolata AND ARE
# AMENDED BY THIS TICKET: 99-liberation-fonts, 99-ttf-inconsolata, 99-ttf-droid
# and 99-cantarell-fonts. That is the same repair ttf-inconsolata itself had to
# make to 99-liberation-fonts one round earlier, for the same reason and in the
# same direction: the generic resolves to the highest-ranked family actually
# installed, it is still doing that, and the case now says so from the new side.
# The three `-unchanged` cases in those suites keep their names, because what
# they assert is that THEIR OWN port did not move the generic, and that is still
# true. A disagreement between any two of the five is visible rather than silent.
#
# ============================================================================
# THE fontcache POSTINST IS THE THING THE TICKET SAYS TO CHECK RATHER THAN
# ASSUME, AND IT IS CHECKED IN THE ONE FORM THAT IS BOOT-MODE INDEPENDENT.
# ============================================================================
#
# fontcache.bbclass appends fontconfig-utils to RDEPENDS -- read back off the
# target here, not off the recipe -- and registers an update_font_cache intercept
# that runs fc-cache under qemu-user. There is no wasm32 qemu-user, so it is
# deferred to run-postinsts at first boot, which /etc/inittab does run
# (BRINTOS-53). Whether it HAS run depends on the pid 1 the harness booted -- the
# local runner goes straight to a shell and never reaches inittab -- so asserting
# the configured state would report the runner's choice as a package red. What is
# asserted instead is boot-mode independent and is the actual risk the ticket
# names: the scriptlet is on the image, it calls fc-cache, and fc-cache is
# present, so the deferred run cannot fail for want of the tool. Nothing had to
# be overridden. Image-wide postinst success stays 79-run-postinsts' no-unpacked
# case and is not re-litigated here; the fc-* block forces `fc-cache -f` itself
# so no other case depends on any of this.
#
# ============================================================================
# FOUR LAYERS, AND A RED IN AN EARLIER ONE LOCALISES A RED IN A LATER ONE:
#
# file-*, ttf-*, the payload arrived intact -- size, bytes, mode, type --
# conf-*, cotenant-* the fragment is a regular file and the only one of ours,
# pkgfiles-* three co-tenants in the shared directory survived, the
# OTHER font directory is untouched, and the package claims
# exactly the fifteen paths and no more. No font machinery
# involved at all.
# pkg-*, postinst-* the packages the image really installs, the fontcache
# class's RDEPENDS, and the deferred scriptlet.
# ft-* the image's OWN freetype PARSES each face through its CFF
# driver and agrees about num_faces, num_glyphs,
# units_per_EM, family and style -- the layer the ticket
# asks for by name. The STYLE is the load-bearing field:
# ten of the fourteen name themselves differently under name
# IDs 1/2 than under 16/17, and freetype takes 16/17.
# fcq-*, fc-* fontconfig's independent parse (fc-scan, against a native
# x86-64 control), then discovery and matching THROUGH THE
# CACHE, which is a different path again -- and where the
# generic handover this port performs is finally visible.
. "$BST_LIB"
S=source-code-pro-fonts
# THE CANARY, which asserts nothing about source-code-pro-fonts.
#
# A suite's FIRST BST result line is lost between the guest's printf and the
# host's read -- per-suite, deterministic, and NOT a defect in the host tool
# (BRINTOS-1149 established that and filed it as linux-in-the-browser#177).
# The harness reports the deficit but computes its pass count as total-minus-
# failures, so THE DROPPED LINE IS COUNTED AS A PASS. A nothing-case therefore
# stands in that position and the eaten line costs nothing; every real case below
# is still counted. It sits ahead of the `require` guards deliberately, because a
# `require` that skips would emit its skip as the first line and be eaten too.
#
# Remove this case when linux-in-the-browser#177 is fixed.
bst_ok $S/suite-canary
D=$BST_DATA
REF=$D/source-code-pro-fonts-manifest.txt
FACTS=$D/source-code-pro-fonts-fontfacts.txt
FACES=$D/source-code-pro-fonts-fcfaces.txt
PROBE_SRC=$D/freetype-probe
TTFDIR=/usr/share/fonts/truetype
CONFDIR=/etc/fonts/conf.d
COTDIR=/usr/share/fonts/ttf
CONF=$CONFDIR/44-source-code-pro-fonts-fontconfig.conf
REG=$TTFDIR/SourceCodePro-Regular.otf
PKGLIST=/var/lib/dpkg/info/source-code-pro-fonts.list
PI=/var/lib/dpkg/info/source-code-pro-fonts.postinst
tmp=${TMPDIR:-/tmp}
W=$tmp/bst-scp.$$
require gawk $S/gawk-present
require sha256sum $S/sha256sum-present
require find $S/find-present
# fc-scan runs in the payload block, ahead of the consumer block's own check, so
# its absence is guarded here. It is NOT a `require`: fontconfig-utils is a hard
# Depends of source-code-pro-fonts, so an absent fc-scan is a defect in the port
# rather than a legitimately absent tool, and a skip would report it green.
if [ -x /usr/bin/fc-scan ]; then bst_ok $S/fc-scan-present
else bst_notok $S/fc-scan-present "fontconfig-utils is a Depends of source-code-pro-fonts but /usr/bin/fc-scan is absent"; fi
if [ ! -f "$REF" ] || [ ! -f "$FACTS" ] || [ ! -f "$FACES" ]; then
bst_notok $S/ref-present "the reference data did not ship: $REF / $FACTS / $FACES"
exit 0
fi
bst_ok $S/ref-present
# ------------------------------------------------------------- payload shape
# One find over this port's own directory, the fragment directory, AND the other
# font directory, so every count is a measurement from the same pass. %y catches
# a symlink where a regular file is meant and %m the mode -- neither of which
# `test -f` can see, and %y is what conf-regular-file rests on. There is no doc
# directory to walk: this recipe installs none (see the header).
find "$TTFDIR" "$CONFDIR" "$COTDIR" \
-maxdepth 1 -printf '%p %y %s %m %l\n' 2>/dev/null | LC_ALL=C sort > "$W.inv"
# One sha256sum over the fifteen payload files. The faces are globbed on OUR OWN
# basename shape rather than on `*.otf`, so a co-tenant that arrived as an OTF
# would not silently join the digest set; the manifest is the list, and
# ttf-no-extras is what says the directory holds nothing our shape does not name.
sha256sum "$TTFDIR"/SourceCodePro-*.otf "$CONF" > "$W.sums" 2>&1
# The package's own file list, copied to tmpfs rather than read from the rootfs
# in a redirect (brintos/linux#73). An absent list is not fatal here -- the awk's
# pkgfiles-loaded case reports it -- so this is not guarded with an exit.
cat "$PKGLIST" > "$W.pkgf" 2>/dev/null || : > "$W.pkgf"
# One fc-scan over the fourteen installed faces. fontconfig opens them through
# FreeType, so this is a second, independent parse -- and it reads fields
# freetype's own API does not name (the PostScript name, the derived
# slant/weight/spacing, the format and the charset).
#
# ONE PATTERN PER FILE, unlike 99-cantarell-fonts. None of these is a variable
# font -- no fvar, no CFF2 -- so `fc-scan` returns exactly fourteen lines and the
# de-dup trap that suite documents does not apply here.
LC_ALL=C fc-scan --format '%{file|basename}|%{family}|%{style}|%{slant}|%{weight}|%{spacing}|%{postscriptname}|%{fontformat}|%{scalable}|%{outline}|%{charset}\n' \
"$TTFDIR"/SourceCodePro-*.otf 2>/dev/null | LC_ALL=C sort > "$W.scan"
LC_ALL=C gawk -v REF="$REF" -v SUMS="$W.sums" -v INV="$W.inv" -v PKGF="$W.pkgf" \
-v FACES="$FACES" -v SCAN="$W.scan" \
-f "$D/source-code-pro-fonts-verify.awk" "$REF" "$W.sums" "$W.inv" "$W.pkgf" "$FACES" "$W.scan"
# ---------------------------------------------------- the packaging on target
# THE PACKAGE DATABASE IS THE ONLY PLACE THE SPLIT IS VISIBLE ON TARGET. The
# file-* cases would look identical if some other package had installed the same
# bytes, so they cannot say that source-code-pro-fonts is a real package the
# image installs rather than an IMAGE_INSTALL line that resolved to nothing. One
# sed pulls every stanza; the loop is shell builtins. The stanzas are read from a
# tmpfs copy, never redirected from the rootfs (brintos/linux#73).
#
# THE ANCHORS ARE EXACT ON PURPOSE. `source-code-pro-fonts` is a PREFIX of
# `source-code-pro-fonts-dev`, `-dbg` and `-doc`, so an unanchored match would
# report one stanza as another and make pkg-no-doc-package unfalsifiable.
sed -n '/^Package: source-code-pro-fonts$/,/^$/p; /^Package: source-code-pro-fonts-doc$/,/^$/p;
/^Package: source-code-pro-fonts-dev$/,/^$/p; /^Package: source-code-pro-fonts-dbg$/,/^$/p' \
/var/lib/dpkg/status > "$W.st" 2>/dev/null
_pkg=""; _main=0; _doc=0; _dev=0; _dbg=0; _arch=0; _dep=0
while IFS= read -r l; do
case "$l" in
"Package: source-code-pro-fonts") _pkg=main; _main=1 ;;
"Package: source-code-pro-fonts-doc") _pkg=doc; _doc=1 ;;
"Package: source-code-pro-fonts-dev") _pkg=dev; _dev=1 ;;
"Package: source-code-pro-fonts-dbg") _pkg=dbg; _dbg=1 ;;
"Architecture: all")
[ "$_pkg" = main ] && _arch=1 ;;
"Depends: "*)
case "$l" in *fontconfig-utils*) [ "$_pkg" = main ] && _dep=1 ;; esac ;;
esac
done < "$W.st"
# THE ONE PACKAGE THIS IMAGE INSTALLS. A dropped IMAGE_INSTALL line would take
# every file-* and ft-* case with it; this case says the cause is a missing
# PACKAGE rather than missing files.
if [ "$_main" -eq 1 ]; then bst_ok $S/pkg-known
else bst_notok $S/pkg-known "dpkg does not know the package source-code-pro-fonts"; fi
# THERE IS NO -doc PACKAGE, AND ITS ABSENCE IS THE RECIPE. Nothing but the faces
# and the fragment is installed -- LICENSE.txt stays in ${S} -- so ${PN}-doc is
# empty and dpkg builds none. This case names that, because a future recipe
# revision that installed LICENSE.txt would change what the image must ask for --
# and because ttf-inconsolata, whose OFL.txt IS the only copy of its licence on
# the image, does ship a -doc and this one deliberately does not.
if [ "$_doc" -eq 0 ]; then bst_ok $S/pkg-no-doc-package
else bst_notok $S/pkg-no-doc-package "dpkg knows a source-code-pro-fonts-doc package -- the recipe now installs documentation"; fi
# ...AND -dev / -dbg ARE NOT INSTALLED. Both are built and both are empty. They
# are asserted absent rather than ignored: an IMAGE_INSTALL that pulled them in
# would add two packages to the manifest for no payload at all, and nothing else
# in this suite would notice.
if [ "$_dev" -eq 0 ]; then bst_ok $S/pkg-no-dev
else bst_notok $S/pkg-no-dev "source-code-pro-fonts-dev is installed -- it is an empty placeholder"; fi
if [ "$_dbg" -eq 0 ]; then bst_ok $S/pkg-no-dbg
else bst_notok $S/pkg-no-dbg "source-code-pro-fonts-dbg is installed -- it is an empty placeholder"; fi
# `allarch` reached the package metadata, which is what makes the byte-identity
# reference in the manifest a statement about this build rather than a
# coincidence.
if [ "$_arch" -eq 1 ]; then bst_ok $S/pkg-arch-all
else bst_notok $S/pkg-arch-all "source-code-pro-fonts is not Architecture: all"; fi
# THE fontcache CLASS'S RDEPENDS, READ BACK OFF THE TARGET. The recipe declares
# no runtime dependency at all -- fontcache.bbclass appends fontconfig-utils to
# each FONT_PACKAGES entry -- so this is the case that says the class did its
# half and that the dependency resolved against a package this image already
# carried (fontconfig-utils has been here since BRINTOS-1032).
if [ "$_dep" -eq 1 ]; then bst_ok $S/pkg-depends-fontconfig
else bst_notok $S/pkg-depends-fontconfig "source-code-pro-fonts does not Depend on fontconfig-utils"; fi
# ------------------------------------------------- the deferred fontcache hook
if [ -f "$PI" ]; then bst_ok $S/postinst-present
else bst_notok $S/postinst-present "$PI is absent -- the fontcache postinst did not reach the image"; fi
# It calls fc-cache on the branch run-postinsts takes ($D unset at first boot).
check_out $S/postinst-runs-fc-cache "fc-cache" cat "$PI"
# ...and the tool that branch needs is present, so the deferred run cannot fail
# for want of it. This is the ticket's stated risk, and it is a shell builtin.
if [ -x /usr/bin/fc-cache ]; then bst_ok $S/fc-cache-present
else bst_notok $S/fc-cache-present "fontconfig-utils is a Depends of source-code-pro-fonts but /usr/bin/fc-cache is absent"; fi
# ------------------------------------------------------ freetype parses them
# The rootfs is read-only at browser runtime and data/ arrives 0644, so the probe
# is copied to /tmp (mode=1777 tmpfs, no noexec) and the bit is set there. Never
# `test -x` the shipped payload: that passes against a hand-placed copy and fails
# against every image that ever built the package.
if [ ! -f "$PROBE_SRC" ]; then
bst_notok $S/probe-present "$PROBE_SRC did not ship"
rm -f "$W.inv" "$W.sums" "$W.scan" "$W.st" "$W.pkgf" 2>/dev/null
exit 0
fi
bst_ok $S/probe-present
probe=$tmp/bst-scp-probe.$$
if cp "$PROBE_SRC" "$probe" 2>/dev/null && chmod +x "$probe" 2>/dev/null; then
bst_ok $S/probe-stage
else
bst_notok $S/probe-stage "cannot stage $PROBE_SRC"
rm -f "$probe" "$W.inv" "$W.sums" "$W.scan" "$W.st" "$W.pkgf" 2>/dev/null
exit 0
fi
# The face list comes from the FACTS file rather than from a glob, so a face the
# manifest knows about but the image lost is reported as "the probe was never run
# over X" instead of silently dropping out of the loop.
#
# NO TRAILING == ON THE FENCE. `==FONT SourceCodePro-It.otf==` puts
# "SourceCodePro-It.otf==" in awk's $2, which matches no key in the facts table,
# and every per-face case then reds with "the probe was never run over ..." while
# ft-ran stays green -- the defect BRINTOS-1449's host pre-flight caught, and
# which this suite's own pre-flight re-ran as a mutation before shipping.
: > "$W.ft"
_faces=$(LC_ALL=C gawk '!/^#/ && NF >= 5 { print $1 }' "$FACTS")
for _f in $_faces; do
printf '==FONT %s\n' "$_f" >> "$W.ft"
"$probe" "$TTFDIR/$_f" >> "$W.ft" 2>&1
_rc=$?
printf '==RC %s %d\n' "$_f" "$_rc" >> "$W.ft"
done
rm -f "$probe" 2>/dev/null
LC_ALL=C gawk -v FACTS="$FACTS" -v FT="$W.ft" \
-f "$D/source-code-pro-fonts-ftverify.awk" "$FACTS" "$W.ft"
# --------------------------------------------------------- the consumer block
#
# EVERYTHING BELOW THIS LINE CAN COST THE GUEST, AND THAT IS WHY IT IS LAST.
# fc-cache mmaps each face it walks, and file-backed mmap on this arm is REFUSED
# above a mapping-length threshold (linux-in-the-browser#165) -- and the consumer
# does not get a failed mmap and fall back, it PARKS, beyond the reach of both
# SIGTERM and SIGKILL, taking the guest and every suite behind it in the same
# boot. Ordering this block last is the only thing that actually protects the
# evidence: every case above has already been emitted by the time the first
# mapping happens.
#
# THESE FOURTEEN FACES SIT WELL INSIDE THE IMAGE'S EXISTING WORKING SET. #165's
# bracket on this image is ~66 kB to 577,708 bytes; the largest face here is
# 149,272, the 53 font files already walked by every fc-cache run are 23,895 to
# 415,816, and TWENTY-THREE of those 53 are larger than our largest. So this
# package cannot introduce a new failure mode or a new maximum. Nothing is held
# out and there are no held-out-* cases, which is what distinguishes this suite
# from 99-ttf-droid's.
#
# THE BOUND IS BEST-EFFORT AND IS NOT WHAT MAKES THIS SAFE. #165 measured that a
# parked fc-cache survives SIGKILL, so `timeout` cannot reclaim it and will
# itself hang when the park is the unkillable kind. It is here for the case where
# the call merely runs long, and the ordering above is here for the case where it
# does not come back at all. Recorded rather than dressed up, because a bound
# that looks protective and is not is worse than none.
#
# BRINTOS-WORKAROUND: linux-in-the-browser#165 remove -- bound the fc-cache call
# and order the consumer block last; both go when the mmap population path
# tolerates a parking read.
# `fc-cache`, NOT `fc-cache -f`, SINCE BRINTOS-1725. The -f rebuilt every
# directory whether or not its cache was valid, which means mapping every face on
# the image; a file-backed mapping above roughly 578 kB is REFUSED over the cloud
# FUSE bridge and the caller PARKS, beyond SIGKILL (linux-in-the-browser#165,
# bracketed by BRINTOS-1450). Before ttf-pt-sans the image's largest face was
# Ubuntu-L.ttf at 415,552 bytes, under the bracket, and this call was harmless;
# that port adds four faces above it, the largest 584,812, and MEASURED on the
# resulting image this suite parked here -- reaching 86 of its 96 cases against
# a full run on the same base pin without the port. Without -f, fc-cache rebuilds
# only what is stale, and nothing is: /var/cache/fontconfig ships populated, and
# `fc-cache` returns 0 in 3 s on that image where `timeout -k 5 150 fc-cache -f`
# never returned. The case still asserts what it always did -- fc-cache runs and
# returns 0.
#
# BRINTOS-WORKAROUND: linux-in-the-browser#165 revisit -- drop -f so only a stale
# cache is rebuilt; it goes back in when the mmap population path tolerates a
# parking read.
# BST-TIMEOUT-OK: fc-cache walks the font dirs and exits; -k 5 90 is belt-and-braces.
timeout -k 5 90 fc-cache > "$W.cache" 2>&1
_rc=$?
if [ "$_rc" -eq 0 ]; then bst_ok $S/fc-cache-rc
elif [ "$_rc" -eq 124 ] || [ "$_rc" -eq 137 ]; then
bst_notok $S/fc-cache-rc "fc-cache did not return within 90s -- linux-in-the-browser#165 (mmap population parked)"
else bst_notok $S/fc-cache-rc "fc-cache exited $_rc: $(_bst_1line "$(cat "$W.cache")")"; fi
# THE FRAGMENT IS LOADED, ASKED DIRECTLY RATHER THAN INFERRED FROM THE MATCH
# BELOW. fc-match monospace answering Source Code Pro is consistent with the
# fragment being loaded AND with fontconfig having decided the same thing some
# other way; only fc-conflist distinguishes them, and if this case is the one
# that reds then the generic handover below is an accident rather than a
# configuration this port controls.
# A `+` line is a file fontconfig LOADED; a `-` line is one merely available
# under conf.avail. The path is matched inside the line rather than anchored
# immediately after the "+ ", because fc-conflist appends a description field and
# the exact spacing is its business, not this suite's.
fc-conflist > "$W.conf" 2>/dev/null
_loaded=0
while IFS= read -r l; do
case "$l" in "+ "*"$CONF"*) _loaded=1 ;; esac
done < "$W.conf"
if [ "$_loaded" -eq 1 ]; then bst_ok $S/fc-conf-loaded
else bst_notok $S/fc-conf-loaded "fc-conflist does not list $CONF among the loaded (+) configuration files"; fi
# One fc-list for the whole consumer read; the parsing below is shell builtins.
#
# THE OBJECT SET CARRIES `style` FOR THE REASON 99-cantarell-fonts DOCUMENTS --
# fc-list dedupes on the properties it was ASKED for -- even though it is not
# strictly needed here. None of these fourteen is a variable font, so each
# contributes ONE pattern and each pattern already differs in `file`; asking for
# style costs nothing and keeps the five font suites' queries the same shape.
fc-list : file family style > "$W.list" 2>&1
# ALL FOURTEEN ARE DISCOVERABLE, not merely present on disk. A cache that
# serialised wrongly, or a FreeType that refused the CFF outlines, shows up here
# while every file-* case above stays green -- which is the split that says where
# to look.
#
# THE FAMILY FIELD IS MULTI-VALUED ON TEN OF THE FOURTEEN. The line format is
# ": :style=", and fontconfig comma-joins ID16 then ID1 --
# so the assertion is on the FIRST value, which is the typographic family and the
# one fc-match answers. Comparing the whole field would red on ten working faces.
_seen=0; _badfam=""
while IFS= read -r l; do
case "$l" in "$TTFDIR"/SourceCodePro-*.otf:*) ;; *) continue ;; esac
_seen=$((_seen+1))
_rest=${l#*: }; _fam=${_rest%%:style=*}; _first=${_fam%%,*}
[ "$_first" = "Source Code Pro" ] || _badfam="$_badfam '$_first'"
done < "$W.list"
if [ "$_seen" -eq 14 ] && [ -z "$_badfam" ]; then
bst_ok $S/fc-list-faces
else
bst_notok $S/fc-list-faces "fc-list reports $_seen patterns for $TTFDIR/SourceCodePro-*.otf (want 14), families:$_badfam"
fi
# ...AND THE FAMILY RESOLVES BACK TO OUR FILE. fc-match never fails -- it always
# returns some face -- so this is real only because 53 other font files are
# installed alongside: a family name that did not reach the cache falls through
# to Liberation, which is exactly what 99-terminus-font's first on-target run
# reported for its own family. The Regular is what a bare family with no weight
# should select out of seven weights, so this pins the weight sort too.
_out=$(fc-match --format '%{file} %{family}\n' 'Source Code Pro' 2>&1)
case "$_out" in
"$REG Source Code Pro") bst_ok $S/fc-match-family ;;
*) bst_notok $S/fc-match-family "fc-match 'Source Code Pro' => '$(_bst_1line "$_out")', want '$REG Source Code Pro'" ;;
esac
# THE ONE GENERIC THIS PORT **DOES** TAKE. This is the only positive
# generic-handover case on this image: every other font suite asserts that its
# own port left the generics alone, and ttf-inconsolata's fc-match-monospace --
# which asserted Inconsolata until this ticket -- is the one this replaces.
#
# IT IS NOT A RESTATEMENT OF fc-match-family ABOVE. That case would stay green if
# the family had reached the cache and the fragment had NOT been applied; this
# one would then be the only red, and fc-conf-loaded above says which of the two
# went wrong. The file is asserted as well as the family because `monospace`
# resolving to some OTHER Source Code Pro weight would be a different bug from it
# resolving to Inconsolata, and only the file distinguishes them.
_out=$(fc-match --format '%{file} %{family}\n' monospace 2>&1)
case "$_out" in
"$REG Source Code Pro") bst_ok $S/fc-match-monospace ;;
*) bst_notok $S/fc-match-monospace "fc-match monospace => '$(_bst_1line "$_out")', want '$REG Source Code Pro' -- this port's 44-*.conf prefers Source Code Pro for monospace" ;;
esac
# THE FIVE GENERICS THIS PORT DOES **NOT** TAKE. These are NOT restatements of
# the two cases above: both would stay green if installing this family had ALSO
# displaced a generic it has no business touching. The fragment names `monospace`
# and nothing else, and Source Code Pro appears nowhere in fontconfig 2.15.0's
# own conf.avail -- checked exhaustively, not sampled -- so the only route to any
# other generic is through 49-sansserif.conf's seeding or a sort accident, and
# these five cases are what would see either.
#
# MEASURED WITH A NULL CONTROL BEFORE THEY WERE WRITTEN: the same native
# fontconfig rig that predicted the monospace handover answers all five
# identically with and without this package installed. 99-liberation-fonts,
# 99-ttf-droid, 99-ttf-gentium and 99-cantarell-fonts assert the first four from
# their side, so a disagreement between the suites stays visible.
#
# system-ui, fantasy AND cursive READ `Roboto` FROM BRINTOS-1723 AND ARE
# RE-MEASURED HERE ON THE MERGED FONT SET. All three are generics no shipped
# fragment seeds, so each falls to the highest-ranked family actually installed;
# that is precisely why they move again whenever a port adds faces, and
# BRINTOS-1729 adds 58. The values below are measured on the MERGED image rather
# than carried from either side of the merge.
#
# sans-serif AND serif MOVED FOR BRINTOS-1729, BY CONFIGURATION AND NOT BY RANK.
# ttf-tlwg ships ten fragments at 64; PREPENDS ahead of
# the generic while 30-liberation-aliases.conf's only APPENDS behind it,
# so Kinnari takes `serif` and Waree takes `sans-serif` regardless of font-set
# size. monospace is untouched -- source-code-pro-fonts' own loads at
# 44, ahead of these.
#
# THESE CASES KEEP THEIR -unchanged NAMES, because what they assert is that
# SOURCE CODE PRO did not move the generic, which is still true; only the values
# they are compared against moved.
for _pair in "sans-serif:DejaVu Sans" "serif:DejaVu Serif" \
"system-ui:DejaVu Sans" "fantasy:DejaVu Sans" "cursive:DejaVu Sans"; do
_gen=${_pair%%:*}; _want=${_pair#*:}
_out=$(fc-match --format '%{family}\n' "$_gen" 2>&1)
case "$_out" in
"$_want") bst_ok "$S/fc-match-$_gen-unchanged" ;;
*) bst_notok "$S/fc-match-$_gen-unchanged" "fc-match $_gen => '$(_bst_1line "$_out")', want '$_want' -- this port must not take this generic" ;;
esac
done
rm -f "$W.inv" "$W.sums" "$W.scan" "$W.st" "$W.pkgf" "$W.ft" "$W.cache" "$W.list" "$W.conf" 2>/dev/null