@@ -4,6 +4,8 @@ import com.google.common.math.IntMath.pow
44import com.lambda.Lambda.LOG
55import com.lambda.graphics.texture.MipmapTexture
66import com.lambda.module.modules.client.RenderSettings
7+ import com.lambda.threading.runGameScheduled
8+ import com.lambda.threading.runIO
79import com.lambda.util.math.Vec2d
810import java.awt.Color
911import java.awt.Graphics2D
@@ -20,70 +22,74 @@ import kotlin.system.measureTimeMillis
2022// TODO: AbstractGlyphs to use for both Font & Emoji glyphs?
2123class EmojiGlyphs (zipUrl : String ) {
2224 private val emojiMap = mutableMapOf<String , GlyphInfo >()
23- private val fontTexture: MipmapTexture
25+ private lateinit var fontTexture: MipmapTexture
2426
25- private val image: BufferedImage
26- private val graphics: Graphics2D
27+ private lateinit var image: BufferedImage
28+ private lateinit var graphics: Graphics2D
2729
2830 init {
29- var x = 0
30- var y = 0
31+ runCatching {
32+ val time = measureTimeMillis {
33+ downloadAndProcessZip(zipUrl)
34+ }
35+ LOG .info(" Loaded ${emojiMap.size} emojis in $time ms" )
36+ }.onFailure {
37+ LOG .error(" Failed to load emojis: ${it.message} " , it)
38+ }
39+ }
3140
32- val time = measureTimeMillis {
33- val file = File .createTempFile(" emoji" , " .zip" )
34- file.deleteOnExit()
41+ private fun downloadAndProcessZip (zipUrl : String ) {
42+ val file = File .createTempFile(" emoji" , " .zip" ).apply { deleteOnExit() }
3543
44+ URL (zipUrl).openStream().use { input ->
3645 file.outputStream().use { output ->
37- URL (zipUrl).openStream().use { input ->
38- input.copyTo(output)
39- }
46+ input.copyTo(output)
4047 }
48+ }
4149
42- ZipFile (file).use { zip ->
43- val firstImage = ImageIO .read(zip.getInputStream(zip.entries().nextElement()))
50+ ZipFile (file).use { zip ->
51+ val firstImage = ImageIO .read(zip.getInputStream(zip.entries().nextElement()))
52+ val length = zip.size().toDouble()
4453
45- val length = zip.size().toDouble()
54+ val textureDimensionLength: (Int ) -> Int = { dimLength ->
55+ pow(2 , ceil(log2((dimLength + STEP ) * sqrt(length))).toInt())
56+ }
4657
47- fun getTextureDimensionLength (dimLength : Int ) =
48- pow(2 , ceil(log2((dimLength + STEP ) * sqrt(length))).toInt())
58+ val width = textureDimensionLength(firstImage.width)
59+ val height = textureDimensionLength(firstImage.height)
60+ val texelSize = Vec2d .ONE / Vec2d (width, height)
4961
50- val width = getTextureDimensionLength(firstImage.width )
51- val height = getTextureDimensionLength(firstImage.height)
52- val texelSize = Vec2d . ONE / Vec2d (width, height )
62+ image = BufferedImage ( width, height, BufferedImage . TYPE_INT_ARGB )
63+ graphics = image.graphics as Graphics2D
64+ graphics.color = Color ( 0 , 0 , 0 , 0 )
5365
54- image = BufferedImage (width, height, BufferedImage .TYPE_INT_ARGB )
55- graphics = image.graphics as Graphics2D
56- graphics.color = Color (0 , 0 , 0 , 0 )
66+ var x = 0
67+ var y = 0
5768
58- for (entry in zip.entries()) {
59- val name = entry.name.substringAfterLast(" /" ).substringBeforeLast(" ." )
60- val emoji = ImageIO .read(zip.getInputStream(entry))
69+ for (entry in zip.entries()) {
70+ val name = entry.name.substringAfterLast(" /" ).substringBeforeLast(" ." )
71+ val emoji = ImageIO .read(zip.getInputStream(entry))
6172
62- if (x + emoji.width >= image.width) {
63- y + = emoji.height + STEP
64- x = 0
65- }
73+ if (x + emoji.width >= image.width) {
74+ y + = emoji.height + STEP
75+ x = 0
76+ }
6677
67- check(y + emoji.height < image.height) { " Can't load emoji glyphs. Texture size is too small" }
78+ check(y + emoji.height < image.height) { " Can't load emoji glyphs. Texture size is too small" }
6879
69- graphics.drawImage(emoji, x, y, null )
80+ graphics.drawImage(emoji, x, y, null )
7081
71- val size = Vec2d (emoji.width, emoji.height)
72- val uv1 = Vec2d (x, y) * texelSize
73- val uv2 = Vec2d (x, y).plus(size) * texelSize
82+ val size = Vec2d (emoji.width, emoji.height)
83+ val uv1 = Vec2d (x, y) * texelSize
84+ val uv2 = Vec2d (x, y).plus(size) * texelSize
7485
75- emojiMap[name] = GlyphInfo (size, - uv1, - uv2)
86+ emojiMap[name] = GlyphInfo (size, - uv1, - uv2)
7687
77- x + = emoji.width + STEP
78- }
88+ x + = emoji.width + STEP
7989 }
80-
81- // ImageIO.write(image, "png", File("emoji.png"))
82-
83- fontTexture = MipmapTexture (image)
8490 }
8591
86- LOG .info( " Loaded ${emojiMap.size} emojis in $time ms " )
92+ fontTexture = MipmapTexture (image )
8793 }
8894
8995 fun bind () {
@@ -93,12 +99,10 @@ class EmojiGlyphs(zipUrl: String) {
9399 }
94100 }
95101
96- fun getEmoji (emoji : String ): GlyphInfo ? =
97- emojiMap[emoji]
102+ fun emojiFromString (emoji : String ) = emojiMap[emoji]
98103
99104 companion object {
100105 private const val STEP = 2
101-
102106 private const val GL_TEXTURE_SLOT = 1 // TODO: Texture slot borrowing
103107 }
104108}
0 commit comments