Draw text with an embedded font, so charts are not blank on Linux - #61
Merged
Conversation
#60) Charts rendered on Linux contained no text at all - no axis labels, no tick values, no legend text, no titles - while the bars, lines and colours were correct. The same build on Windows rendered fully: 16,132 bytes against 10,565, the difference being the entire text layer. The cause is not missing fonts. Consumers commonly reference SkiaSharp.NativeAssets.Linux.NoDependencies, a libSkiaSharp built without fontconfig, and with that build SkiaSharp can enumerate no system fonts at all, so every text node resolves to nothing and draws nothing. That is unusually well hidden. fc-list and fc-match work perfectly in the same container - they are fontconfig's own tools and SkiaSharp never consults them - so a font can be installed, aliased and confirmed present while being entirely unavailable to the renderer. It also fails silently: a chart missing every label still looks like a chart. Two obvious fixes were measured first and neither works. Installing more fonts changes nothing, because the font manager is empty rather than under-stocked. Naming a font-family changes nothing either - probing this Svg.Skia version directly, an unresolvable family still draws via a fallback, and comma-separated stacks are ignored: "NoSuchFont, Arial" renders identically to "NoSuchFont", not to Arial. So carry the font. Liberation Sans is embedded and supplied through an ITypefaceProvider registered ahead of the system providers, which also makes a chart render identically on a developer's machine and on a server - worth having in its own right, since this output is routinely compared against another renderer and a font difference would read as a rendering difference. It is SIL OFL 1.1, which permits embedding; the copyright file is included, and its GPL-2+ section covers Debian packaging that is not shipped. The SVG path now always names a font too. Our raster path ignores the attribute - the provider answers every request - but SVG is a public output format, and a browser opening one would otherwise pick its own default and disagree with the PNG of the same chart. TextRenderingTests asserts the resource is present, that it loads with glyphs, and that adding an axis title changes the pixels - with a longer title changing more of them than a shorter one, which is only true if glyphs are really drawn. The existing raster tests could not have caught this: they look for many colours and content across the canvas, and a chart with no text satisfies both. Full suite 92/92. Removing the embedded resource fails the two mechanism tests, confirming they bite; the pixel assertions are the red check on Linux CI, which runs the NoDependencies build that fails today. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
davidnmbond
force-pushed
the
fix/issue-60-embed-font
branch
from
August 29, 2026 16:46
8a09168 to
2e92aaa
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #60.
The problem
Charts rendered on Linux contained no text at all — no axis labels, no tick values, no legend text, no titles — while the bars, lines and colours were correct. Same build on Windows: 16,132 bytes against 10,565, the difference being the entire text layer.
The cause, and two fixes that don't work
Not missing fonts. Consumers commonly reference
SkiaSharp.NativeAssets.Linux.NoDependencies, alibSkiaSharpbuilt without fontconfig, and with that build SkiaSharp can enumerate no system fonts at all.It hides well:
fc-listandfc-matchwork perfectly in the same container, because they're fontconfig's own tools and SkiaSharp never consults them. A font can be installed, aliased and confirmed present while being entirely unavailable to the renderer.Both obvious fixes were measured before this one was written:
font-family— changes nothing either. Probing this Svg.Skia version directly:The fix
Carry the font. Liberation Sans embedded, supplied through an
ITypefaceProviderregistered ahead of the system providers viaSKSvgSettings.TypefaceProviders.Registering it first rather than as a fallback is deliberate: it makes a chart render identically on a developer's machine and on a server. That's worth having on its own, since this output is routinely compared against another renderer and a font difference would read as a rendering difference.
Liberation Sans is metrically compatible with Arial, so label widths and wrapping match the reference renderer.
Licensing: SIL OFL 1.1, which permits embedding and redistribution. The copyright file is included; its GPL-2+ section covers Debian packaging that is not shipped.
The SVG path now always names a font too. Our raster path ignores the attribute — the provider answers every request — but SVG is a public output format, and a browser opening one would otherwise pick its own default and disagree with the PNG of the same chart.
Tests
TextRenderingTestsasserts the resource is present, loads with glyphs, and that adding an axis title changes the pixels — with a longer title changing more of them than a shorter one, which is only true if glyphs are really being drawn.The existing raster tests could not have caught this: they look for many distinct colours and content across the canvas, and a chart with no text satisfies both. That's why this shipped.
Verification
NoDependenciesbuild that fails today — they should fail there without this change and pass with it.