BBFontProvider
class BBFontProvider internal constructor(
private val _loader: TypefaceLoader,
private val _frozen: Boolean
)
One owner's answer to "what Typeface goes on this TextView?" (#20290). An owner is a
BBNativePlayerView (fed by its playout) or a BBNativeShortsView (fed by the Shorts app
config, serving the shelf in list mode).
Deliberately not a singleton: two BBNativePlayerViews on one screen can be on different
playouts, and a shared role -> face map would let one repaint the other. The only global part
is [BBFontRegistry], a path -> Typeface cache, which carries no role state.
Two independent roles, per #20288:
HEADING video title (start/pause/end), "Related videos", CTA label, Shorts title
BODY everything else - times, LIVE, settings, ads, dates, authors, related items, ...
A role that resolves to nothing renders in Lato, exactly as the SDK did before this ticket. The [BBFontStyle] axis only ever picks between the three bundled Lato files; a custom file is used as-is (heading) or with OS-synthesised bold (body).
Properties
currentSpecs
var currentSpecs: Map<FontRole, FontSpec>
The specs the owner last asked for, per role. Kept here so the runtime-playout delta ([FontPlayoutDelta]) has a "current" to compare an incoming payload against - an absent key means "leave this role alone", which is only expressible against a remembered state.
unavailableRoles
val unavailableRoles: Set<FontRole>
Roles whose last applied [FontResolution] was [FontResolution.Unavailable] - a transient
failure (network hiccup, or the shared module's resolution timeout) rather than a final
answer. The download for these keeps running in the background and lands in the cache, but
nobody asks again unless prompted (#20290: BBNativePlayerView retries once on a timer, and
re-resolves a re-sent playout even when its specs did not change). [FontResolution.Unusable]
is a permanent, contractual answer and must never show up here.
Functions
hasUnavailableRole
fun hasUnavailableRole() : Boolean
True while at least one role is stuck on [FontResolution.Unavailable] (see [unavailableRoles]).
typeface
fun typeface(role: FontRole, style: BBFontStyle) : Typeface
The Typeface for [role] at [style]. Never null: it falls all the way back to the platform default if even Lato fails to load.
apply
fun apply(heading: FontResolution, body: FontResolution)
Both roles at once, one listener fire. This is what a [FontResolution] pair lands in.
applyRole
fun applyRole(role: FontRole, resolution: FontResolution)
One role. The other keeps whatever it had - the roles never cover for each other.
addListener
fun addListener(listener: () -> Unit)
Called exactly once after every [apply] / [applyRole], so owners can re-sweep their view
trees. Fired even when nothing changed: a re-apply is also how a freshly inflated subtree
gets its fonts, and a redundant sweep is cheaper than a missed one. Listeners run on
whatever thread called apply - in practice the resolver's callbackDispatcher, i.e. Main.
latoFallback
fun latoFallback(context: Context) : BBFontProvider
A shared, frozen, Lato-only provider for views that have not been handed their owner's
provider yet (a screen's init block runs before BBNativePlayerView can inject one).
It refuses [apply], so it can never pick up another player's font, and its loader holds
the application context, so it leaks nothing.