All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jvmMain.io.nacular.doodle.drawing.impl.FontLoaderImpl.kt Maven / Gradle / Ivy

There is a newer version: 0.10.4
Show newest version
package io.nacular.doodle.drawing.impl

import io.nacular.doodle.drawing.Font
import io.nacular.doodle.drawing.Font.Style.Italic
import io.nacular.doodle.drawing.Font.Style.Oblique
import io.nacular.doodle.drawing.FontInfo
import io.nacular.doodle.drawing.FontLoader
import org.jetbrains.skia.Data
import org.jetbrains.skia.FontSlant.OBLIQUE
import org.jetbrains.skia.FontSlant.UPRIGHT
import org.jetbrains.skia.FontStyle
import org.jetbrains.skia.Typeface
import org.jetbrains.skia.paragraph.BaselineMode
import org.jetbrains.skia.paragraph.FontCollection
import org.jetbrains.skia.paragraph.TextStyle
import org.jetbrains.skia.paragraph.TypefaceFontProvider

/**
 * Created by Nicholas Eddy on 5/20/21.
 */
internal class FontLoaderImpl(private val fontCollection: FontCollection): FontLoader {
    private val loadedFonts = mutableMapOf()

    private val typefaceFontProvider = TypefaceFontProvider()

    init {
        fontCollection.setAssetFontManager(typefaceFontProvider)
    }

    override suspend fun invoke(info: FontInfo.() -> Unit): Font? = FontInfo().apply(info).let { fontInfo ->
        var result = loadedFonts[fontInfo]

        if (result == null) {
            val slant = when (fontInfo.style) {
                Italic     -> OBLIQUE
                is Oblique -> OBLIQUE
                else       -> UPRIGHT
            }

            result = fontCollection.findTypefaces(fontInfo.families.toTypedArray(), FontStyle(fontInfo.weight, 5, slant)).firstOrNull()?.toFont(fontInfo)?.also {
                loadedFonts[fontInfo] = it
            }
        }

        return result
    }

    override suspend fun invoke(source: String, info: FontInfo.() -> Unit): Font? = FontInfo().apply(info).let { modifiedInfo ->
        loadedFonts[modifiedInfo] ?: Thread.currentThread().contextClassLoader.getResourceAsStream(source)?.let { file ->
            val typeface = Typeface.makeFromData(Data.makeFromBytes(file.readBytes()))
            typefaceFontProvider.registerTypeface(typeface, modifiedInfo.family)

            typeface.toFont(modifiedInfo).also { loadedFonts[modifiedInfo] = it }
        }
    }

    private val Font.Style.skia get() = when (this) {
        Italic     -> OBLIQUE
        is Oblique -> OBLIQUE
        else       -> UPRIGHT
    }

    private fun Typeface.toFont(info: FontInfo): Font = FontImpl(TextStyle().also {
        it.fontSize     = info.size.toFloat()
        it.typeface     = this
        it.fontStyle    = fontStyle.withWeight(info.weight).withSlant(info.style.skia)
        it.fontFamilies = info.families.toTypedArray()
        it.baselineMode = BaselineMode.IDEOGRAPHIC
    })
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy