Skip to main content

com.bluebillywig.bbnativeplayersdk.fonts — Functions

fromResource​

fun fromResource(@FontRes id: Int) : Typeface?

/** A downloaded font file, validated by [BBFontRegistry]. Null when it is not usable. */
fun fromFile(path: String): Typeface?

/** `Typeface.create(name, style)`. Never null in practice; Android substitutes silently. */
fun system(name: String, style: Int): Typeface?

/**
* True when [tf] renders identically to the platform default for [style], which is how
* Android reports "I have never heard of that family name" - it substitutes instead of
* failing. Measured, not compared by identity: `Typeface.create` may hand back a distinct
* object that still wraps the default family.
*/
fun isDefaultSubstitution(tf: Typeface, style: Int): Boolean

/** `Typeface.create(tf, style)`; picks a real face from the family or lets the OS synthesise. */
fun withStyle(tf: Typeface, style: Int): Typeface
}

/**
* @suppress
*/
class AndroidTypefaceLoader(context: Context) : TypefaceLoader

The bundled Lato faces. Null when the resource cannot be loaded.

fromFile​

fun fromFile(path: String) : Typeface?

/** `Typeface.create(name, style)`. Never null in practice; Android substitutes silently. */
fun system(name: String, style: Int): Typeface?

/**
* True when [tf] renders identically to the platform default for [style], which is how
* Android reports "I have never heard of that family name" - it substitutes instead of
* failing. Measured, not compared by identity: `Typeface.create` may hand back a distinct
* object that still wraps the default family.
*/
fun isDefaultSubstitution(tf: Typeface, style: Int): Boolean

/** `Typeface.create(tf, style)`; picks a real face from the family or lets the OS synthesise. */
fun withStyle(tf: Typeface, style: Int): Typeface
}

/**
* @suppress
*/
class AndroidTypefaceLoader(context: Context) : TypefaceLoader

A downloaded font file, validated by [BBFontRegistry]. Null when it is not usable.

system​

fun system(name: String, style: Int) : Typeface?

/**
* True when [tf] renders identically to the platform default for [style], which is how
* Android reports "I have never heard of that family name" - it substitutes instead of
* failing. Measured, not compared by identity: `Typeface.create` may hand back a distinct
* object that still wraps the default family.
*/
fun isDefaultSubstitution(tf: Typeface, style: Int): Boolean

/** `Typeface.create(tf, style)`; picks a real face from the family or lets the OS synthesise. */
fun withStyle(tf: Typeface, style: Int): Typeface
}

/**
* @suppress
*/
class AndroidTypefaceLoader(context: Context) : TypefaceLoader

Typeface.create(name, style). Never null in practice; Android substitutes silently.

isDefaultSubstitution​

fun isDefaultSubstitution(tf: Typeface, style: Int) : Boolean

/** `Typeface.create(tf, style)`; picks a real face from the family or lets the OS synthesise. */
fun withStyle(tf: Typeface, style: Int): Typeface
}

/**
* @suppress
*/
class AndroidTypefaceLoader(context: Context) : TypefaceLoader

True when [tf] renders identically to the platform default for [style], which is how Android reports "I have never heard of that family name" - it substitutes instead of failing. Measured, not compared by identity: Typeface.create may hand back a distinct object that still wraps the default family.

withStyle​

fun withStyle(tf: Typeface, style: Int) : Typeface
}

/**
* @suppress
*/
class AndroidTypefaceLoader(context: Context) : TypefaceLoader

Typeface.create(tf, style); picks a real face from the family or lets the OS synthesise.

specs​

fun specs(rawJson: String, current: Map<FontRole, FontSpec>) : Map<FontRole, FontSpec>

The new spec per role for a raw playout payload, e.g. the playoutDataJsonString handed to updatePlayoutWithJson. Returns [current] unchanged when the payload is not a json object.

specsFromOptions​

fun specsFromOptions(options: Map<String, Any?>?, current: Map<FontRole, FontSpec>) : Map<FontRole, FontSpec>

The same rule for the create-options map handed to BBNativePlayer.createPlayerView. The option keys are the playout's own (skin_fontHeadingId, skin_fontHeading, skin_fontBodyId, skin_fontBody) so the semantics are identical, and a present key overrides the playout for the lifetime of the view.

optionOverrides​

fun optionOverrides(options: Map<String, Any?>?) : Map<FontRole, FontSpec>

Which roles carry a create-time option override, and what into. Unlike [specsFromOptions] this never falls back to a "current" map: a role absent from [options] is simply absent from the result, so the caller can tell "no override" apart from "overridden to [FontSpec.None]" and keep the override across every later playout update - a runtime updatePlayoutWithJson must not be able to erase a create-time option, and in player mode Shorts' AppConfig fonts travel through this same options map into the inner player (#20290 review finding 2). In list mode there is no inner player: BBNativeShortsView resolves the same specs with its own provider for the shelf, without this map.

effective​

fun effective(playout: Map<FontRole, FontSpec>, options: Map<FontRole, FontSpec>) : Map<FontRole, FontSpec>

Effective spec per role: [options] wins when it carries an entry for the role, else [playout] decides, else [FontSpec.None]. However [playout] changes afterwards, an option entry already in [options] is never overwritten (#20290 review finding 2).

compute​

fun compute(
rootIds: Map<FontRole, String?>,
rootNames: Map<FontRole, String?>,
options: Map<String, Any?>?
) : Layers

[rootIds] / [rootNames] are the app config's raw values per role, [options] the map the host passed at creation. Presence of a role's id key in [options] is what makes it an override - the name key alone never decides anything, exactly as in FontPlayoutDelta.

needed​

fun needed(current: FontResolver?, baseUrl: String, defaultMediaAssetPath: String) : Boolean

True when [current] cannot serve [baseUrl] + [defaultMediaAssetPath], so the caller must construct a resolver that can, __destruct this one and cancel any retry queued for it.

False keeps the instance, and that is the point of asking: its per-clip-id memo and its in-flight downloads were resolved against exactly this pair and are still the right answers, so replacing a resolver on a repeat embed of the same publication throws away a working memo and re-downloads fonts the view already has.

typefaceFor​

fun typefaceFor(path: String) : Typeface?

The Typeface for [path], or null when the file is missing, empty, unparseable or renders no glyphs. Failures are remembered so a broken file is not re-parsed on every re-apply.

apply​

fun apply(root: View?, provider: BBFontProvider?)

XML opt-in for a body-role TextView.

apply​

fun apply(root: View?, provider: BBFontProvider?)

XML opt-in for a heading-role TextView.

apply​

fun apply(root: View?, provider: BBFontProvider?)

Depth-first over [root]; a no-op only when [root] itself is null. A null [provider] - routinely the case from a screen's init, which runs before BBNativePlayerView can inject its own - applies [BBFontProvider.latoFallback] instead of doing nothing, so the tree never sits in the platform default between inflate and owner assignment (#20290 review).

set​

fun set(view: TextView, provider: BBFontProvider?, role: FontRole, style: BBFontStyle)

Mark [view] as belonging to [role] at [style] and give it the matching typeface now. Programmatic sites use this instead of ResourcesCompat.getFont, so a later [apply] can find them again.

tag​

fun tag(view: View, role: FontRole, style: BBFontStyle)

Tags only, no typeface change.

onResolved​

fun onResolved(
specs: Map<FontRole, FontSpec>,
heading: FontResolution,
body: FontResolution,
isRetry: Boolean,
retryPending: Boolean,
startedWith: FontResolver?,
current: FontResolver?,
provider: BBFontProvider,
scheduleRetry: (specs: Map<FontRole, FontSpec>) -> Unit
)

Apply [heading] and [body] to [provider], unless this verdict is stale or its resolver is no longer the owner's, and schedule a retry when a role came back transiently [FontResolution.Unavailable].

Parameters:

NameDescription
specsthe specs this resolution was started for
isRetrytrue for the resolution [scheduleRetry] itself started: one retry per
resolution, never a chain
retryPendingtrue while a retry runnable is already queued - the one-shot budget for
the current specs, which the owner cancels when the specs change
startedWiththe resolver resolveBoth was called on, captured when this resolution
started
currentthe owner's resolver now, read at callback time: another instance once
the publication changed, null once the owner has let go of it
scheduleRetrycalled with [specs] when this verdict earns a retry