RichTextBox/RichTextBox.axaml line 199, the title of the "Insert Hyperlink" popup:
<TextBlock x:Name="HyperlinkPopupTitle" Text="Insert Hyperlink" FontWeight="SemiBold" FontSize="13"/>
FontWeight is set without a FontFamily, so the request goes to the platform default family with
weight 600. On a device whose default family only ships a static regular face — Android 11 with a
static Roboto 400 is the common case — the nearest match differs from the requested key, and
Avalonia synthesises a faux-bold by copying the whole font file into native memory. The
synthetic face is then cached under the source font's real name, never under the key that was asked
for, so the next request repeats the copy.
The popup itself is never shown in our application, which is what makes this hard to spot: the
template is materialised with the control, so every RichTextBox instance pays for it. Our app
builds three per screen and rebuilds screens continuously (digital signage), which turned it into
1 834 224 bytes retained per screen rebuild — 6 × 305 608, exactly six copies of
Roboto-Regular.ttf, with frees=0.
Attribution is measured, not inferred: changing that single attribute to FontWeight="Normal",
rebuilding, and re-running the same heap profile took the allocation site from 24 allocations /
1 834 224 bytes per rebuild to zero. Devices with a variable Roboto (Android 13) or a real 600
face are unaffected, and so is Windows.
The root cause is in Avalonia, and there is a PR open for it —
AvaloniaUI/Avalonia#21993 — so this may well
fix itself for you once that lands. Until then, any FontWeight set without a FontFamily is a
trap on font-poor devices.
I did not send a PR because the fix is a design call that is yours to make: dropping the weight
changes how the popup looks. The options I see are to remove FontWeight, or to pair it with an
explicit FontFamily that actually ships the face. Happy to send whichever you prefer.
Filed for the same reason as #49: we vendor this control and would rather not carry a local
divergence.
RichTextBox/RichTextBox.axamlline 199, the title of the "Insert Hyperlink" popup:FontWeightis set without aFontFamily, so the request goes to the platform default family withweight 600. On a device whose default family only ships a static regular face — Android 11 with a
static Roboto 400 is the common case — the nearest match differs from the requested key, and
Avalonia synthesises a faux-bold by copying the whole font file into native memory. The
synthetic face is then cached under the source font's real name, never under the key that was asked
for, so the next request repeats the copy.
The popup itself is never shown in our application, which is what makes this hard to spot: the
template is materialised with the control, so every
RichTextBoxinstance pays for it. Our appbuilds three per screen and rebuilds screens continuously (digital signage), which turned it into
1 834 224 bytes retained per screen rebuild — 6 × 305 608, exactly six copies of
Roboto-Regular.ttf, withfrees=0.Attribution is measured, not inferred: changing that single attribute to
FontWeight="Normal",rebuilding, and re-running the same heap profile took the allocation site from 24 allocations /
1 834 224 bytes per rebuild to zero. Devices with a variable Roboto (Android 13) or a real 600
face are unaffected, and so is Windows.
The root cause is in Avalonia, and there is a PR open for it —
AvaloniaUI/Avalonia#21993 — so this may well
fix itself for you once that lands. Until then, any
FontWeightset without aFontFamilyis atrap on font-poor devices.
I did not send a PR because the fix is a design call that is yours to make: dropping the weight
changes how the popup looks. The options I see are to remove
FontWeight, or to pair it with anexplicit
FontFamilythat actually ships the face. Happy to send whichever you prefer.Filed for the same reason as #49: we vendor this control and would rather not carry a local
divergence.