Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(7.x.x) FontLibrary / FontClass #188

Merged
merged 9 commits into from
Apr 25, 2022

Conversation

swingingtom
Copy link
Collaborator

this PR handle #153, #154 and also propose a tool/workaround for #161

API Changes

Defining + Using fonts

const fontFamily = ThreeMeshUI.FontLibrary.addFontFamily( "Roboto" );
// [...]
new ThreeMeshUI.Text( { content: "Display in Roboto", fontFamily: fontFamily} );
// same as
new ThreeMeshUI.Text( { content: "Display in Roboto", fontFamily: "Roboto"} );

The example above miss to define a variant!

Defining variants (required)

ThreeMeshUI.FontLibrary.addFontFamily( "Roboto" )
    .addFontVariant( '400', 'normal', "roboto-regular.json", "roboto-regular.png") // Roboto Regular variant
    .addFontVariant( '700', 'normal', "roboto-bold.json", "roboto-bold.png") // Roboto Bold variant
    .addFontVariant( '700', 'italic', "roboto-bold-italic.json", "roboto-bold-italic.png") // Roboto Bold-Italic variant
// [...]

new ThreeMeshUI.Text( { content: "Hello!", fontFamily: "Roboto"} ); // Roboto Regular variant
new ThreeMeshUI.Text( { content: "Hello!", fontFamily: "Roboto", fontWeight: '700' } ); // Roboto Bold variant
new ThreeMeshUI.Text( { content: "Hello!", fontFamily: "Roboto", fontWeight: '700', fontStyle: 'italic' } ); // Roboto Bold-Italic variant

Compatibility

Previous ways of using msdf fonts are still available as being not recommended.

new ThreeMeshUI.Block( { fontFamily: "./assets/roboto.json", fontTexture: "./assets/roboto.png"} );
// or 
new ThreeMeshUI.Block( { fontFamily: msdfJsonData, fontTexture: "./assets/roboto.png"} );
// or 
new ThreeMeshUI.Block( { fontFamily: "./assets/roboto.json", fontTexture: alreadyLoadedTexture } );
// or
new ThreeMeshUI.Block( { fontFamily: msdfJsonData, fontTexture: alreadyLoadedTexture } );

This will automatically; create new FontFamily, retrieve existing FontFamily, create new FontVariant(MSDF ONLY), retrieve existing variant according to context

Preloading fonts

1 Recommended way : Project side loading
If you are building a production application, chances are high that you'll already have some kind of asset loader, loader queue, loader sequences, etc... USE IT then add variants with your loaded assets.

ThreeMeshUI.FontLibrary
    .addFontFamily( "Roboto" )
        .addFontVariant( '400', 'normal', loadedJson, loadedTexture );
// do your stuff here

2 FontLibrary.load() Async
Rely FontLibrary.load() which return a Promise

ThreeMeshUI.FontLibrary.load( 
    ThreeMeshUI.FontLibrary
        .addFontFamily( "Roboto" )
            .addFontVariant( '400', 'normal', loadedJson, existingTexture)
            .addFontVariant( '400', 'italic', "./assets/roboto-italic.json", "./assets/roboto-italic.png"),
    ThreeMeshUI.FontLibrary
        .addFontFamily( "Arial" )
            .addFontVariant( '400', 'normal', "./assets/arial.json", "./assets/arial.png")
). then( whenFontsAreLoadedOrReady );

function whenFontsAreLoadedOrReady () {
    // do stuff here
}

3 FontLibrary.load() Sync
Rely FontLibrary.load() which return a Promise that can be await

( async () => { 

await ThreeMeshUI.FontLibrary.load( 
    ThreeMeshUI.FontLibrary
        .addFontFamily( "Roboto" )
            .addFontVariant( '400', 'normal', "./assets/roboto.json", "./assets/roboto.png")
            .addFontVariant( '400', 'italic', "./assets/roboto-italic.json", "./assets/roboto-italic.png"),
    ThreeMeshUI.FontLibrary
        .addFontFamily( "Arial" )
            .addFontVariant( '400', 'normal', "./assets/arial.json", "./assets/arial.png")
);
// Do stuff here


})( );
ThreeMeshUI.FontLibrary.load( 
    ThreeMeshUI.FontLibrary
        .addFontFamily( "Roboto" )
            .addFontVariant( '400', 'normal', "./assets/roboto.json", "./assets/roboto.png")
            .addFontVariant( '400', 'italic', "./assets/roboto-italic.json", "./assets/roboto-italic.png"),
    ThreeMeshUI.FontLibrary
        .addFontFamily( "Arial" )
            .addFontVariant( '400', 'normal', "./assets/arial.json", "./assets/arial.png")
). then( whenFontLoaded );

function whenFontLoaded () {

}

Under-the-hood

This FontLibrary FontClass proposal highly rely on classes, interfaces and abstract (typescript should be the way).
Note that this is under-the-hood, and users won't have to deal with it

FontFamily

Reference a fontFamily(string) that can be used to set .fontFamily of any MeshUIComponent.

A FontFamily holds variants Array.<FontVariant> which really are the fonts.

FontVariant

FontVariant class is abstract.

TextTypes are now handled via FontVariant class extension.
MSDFFontVariant is the default text-type implementation implemented.
FontFamily::addFontVariant() currently always goes for msdf implementation.
FontFamily::addFontVariant(variant:FontVariant) is the way to create a variant that is not msdf.

FontVariant holds .font as TypographyFont which is the static informations of the font : lineHeight, lineBase, size
FontVariant holds ._chars as Array.<TypographyCharacter> which are the static information of each character in that font variant.

ThreeMeshUI.Text

Text holds .content as string which is the string representation

Text holds ._textContent as string which is .content after being whitespaced (according to .whiteSpace property)

Text holds ._textContentGlyphs as Array.<TypographyCharacter> which is the mapping of ._textContent in TypographyCharacter. This should be only rebuilt when content, font (fontWeight/fontStyle) or whitespace change.

Text holds ._textContentInlines as Array.<InlineCharacter> which is the contextual mapping of ._textContentGlyphs in InlineCharacter. Contextual is : String Sequence(kerning), fontSize,

Character Adjustement

As described in under-the-hood, font are highly OOP and lots of pointers are shared. It was therefore not hard to provide a way to tweak / fine-tune glyph alignment issue #161

await FontLibrary.load(
    FontLibrary
        .addFontFamily("Roboto")
            .addVariant(FontWeight.NORMAL, FontStyle.NORMAL, "./assets/fonts/msdf/roboto/regular.json", "./assets/fonts/msdf/roboto/regular.png" )
);

// adjust fonts
FontLibrary.getFontFamily("Roboto");
    .getVariant('700','normal')
        .adjustCharactersDescription( { k:{yoffset:2} } ); // Change the yoffset typographic property of the "k" character

Development example is already prepared
Screenshot_4

And a codesandbox with ability to load custom fonts might also be on the way

Next

  • Some naming changes will occurs.
  • MSDF Implementation still need to provide its own shader, but this will handled by another refactor.
  • Types checks

@swingingtom swingingtom changed the base branch from master to 7.x.x April 20, 2022 13:02
@swingingtom swingingtom merged commit 6271e3e into 7.x.x Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant