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

commonMain.ru.casperix.multiplatform.font.pixel.PixelFontPacker.kt Maven / Gradle / Ivy

There is a newer version: 1.1.1
Show newest version
package ru.casperix.multiplatform.font.pixel

import ru.casperix.multiplatform.font.FontReference
import ru.casperix.multiplatform.pixel_map.PixelMapRegion
import ru.casperix.multiplatform.loader.resourceLoader
import ru.casperix.math.axis_aligned.int32.Box2i
import ru.casperix.math.color.Colors
import ru.casperix.math.vector.int32.Vector2i
import ru.casperix.multiplatform.rectangle_packer.RectanglePacker
import ru.casperix.multiplatform.rectangle_packer.RectangleSource
import ru.casperix.renderer.material.Texture2D
import ru.casperix.renderer.pixel_map.PixelMap
import ru.casperix.multiplatform.text.TextRenderConfig.debugDrawFontAtlas
import ru.casperix.multiplatform.text.TextRenderConfig.debugSaveFontAtlas
import ru.casperix.multiplatform.util.PixelMapDrawer

@ExperimentalUnsignedTypes
object PixelFontPacker {

    fun packFont(font: PixelFont): PixelFont {
        val symbols = font.symbols
        val withGraphic = symbols.filter { it.graphic != null }
        val withoutGraphic = symbols.filter { it.graphic == null }

        val packedSymbols = packGraphicSymbols(font.reference, withGraphic)
        return PixelFont(font.reference, font.metrics, packedSymbols + withoutGraphic)
    }

    private fun packGraphicSymbols(reference: FontReference, symbols: Collection): Collection {
        val containers = symbols.map {
            RectangleSource(it, it.size)
        }

        val packed = RectanglePacker.pack(containers)
            ?: throw Exception("Cant pack items")

        val atlas = PixelMap.RGBA(packed.dimension)

        packed.containers.forEach { container ->
            val pixelRegion = container.source.graphic
                ?: throw Exception("Only graphic symbol must packed to atlas")

            if (debugDrawFontAtlas) {
                PixelMapDrawer.fillColor(
                    atlas,
                    container.position,
                    Colors.RED.toColor4b(),
                    pixelRegion.dimension,
                    false
                )
                PixelMapDrawer.fillColor(
                    atlas,
                    container.position + Vector2i.ONE,
                    Colors.BLUE.toColor4b(),
                    pixelRegion.dimension - Vector2i(2),
                    false
                )
            }
            PixelMapDrawer.drawImage(
                atlas,
                container.position,
                pixelRegion.atlas.map,
                Vector2i.ZERO,
                pixelRegion.region.dimension,
                debugDrawFontAtlas
            )
        }

        val packedSymbols = packed.containers.map { container ->
            val original = container.source
            val config = original.graphic!!.atlas.config
            val graphic = PixelMapRegion(Texture2D( atlas, config), Box2i.byDimension(container.position, original.size))
            original.copy(graphic = graphic)
        }
        if (debugSaveFontAtlas) {
            val postfix = "_" + reference.name + "_" + reference.size
            resourceLoader.saveImage("font_atlas$postfix.png", atlas)
        }
        return packedSymbols
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy