libgdx implements text centering, libgdx text centering, and GlyphLayout text centering

libgdx implements text centering, libgdx text centering, and GlyphLayout text centering

libgdx implements text centering, libgdx text centering, and GlyphLayout text centering, environment jdk 17 + , latest on November 1, 2023 14:20:18.
Reprinted from: https://lingkang.top/archives/libgdx-shi-xian-wen-ben-ju-zhong

Dependencies

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>top.lingkang</groupId>
    <artifactId>yzcy</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <gdx.version>1.12.0</gdx.version>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.badlogicgames.gdx/gdx -->
        <dependency>
            <groupId>com.badlogicgames.gdx</groupId>
            <artifactId>gdx</artifactId>
            <version>${gdx.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.badlogicgames.gdx/gdx-backend-lwjgl3 -->
        <dependency>
            <groupId>com.badlogicgames.gdx</groupId>
            <artifactId>gdx-backend-lwjgl3</artifactId>
            <version>${gdx.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.badlogicgames.gdx/gdx-platform -->
        <dependency>
            <groupId>com.badlogicgames.gdx</groupId>
            <artifactId>gdx-platform</artifactId>
            <version>${gdx.version}</version>
            <classifier>natives-desktop</classifier>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.badlogicgames.gdx/gdx-freetype -->
        <dependency>
            <groupId>com.badlogicgames.gdx</groupId>
            <artifactId>gdx-freetype</artifactId>
            <version>${gdx.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.badlogicgames.gdx/gdx-freetype-platform -->
        <dependency>
            <groupId>com.badlogicgames.gdx</groupId>
            <artifactId>gdx-freetype-platform</artifactId>
            <version>${gdx.version}</version>
            <classifier>natives-desktop</classifier>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.9</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>2.0.9</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                    <!-- Keep method parameter names unchanged after compilation -->
                    <!--<compilerArgs>
                        <arg>-parameters</arg>
                    </compilerArgs>-->
                </configuration>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>tencent</id>
            <name>tencent</name>
            <layout>default</layout>
            <url>http://mirrors.cloud.tencent.com/nexus/repository/maven-public/</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <releases>
                <enabled>true</enabled>
            </releases>
        </repository>
        <repository>
            <id>nexus</id>
            <name>Nexus</name>
            <layout>default</layout>
            <url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
            <releases>
                <enabled>true</enabled>
            </releases>
        </repository>
        <repository>
            <id>aliyunmaven</id>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>

Overriding classes

package top.lingkang.yzcy.utils;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.g2d.freetype.FreeType;
import com.badlogic.gdx.graphics.g2d.freetype.FreeType.Face;
import com.badlogic.gdx.graphics.g2d.freetype.FreeType.SizeMetrics;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeBitmapFontData;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.GlyphAndBitmap;
import com.badlogic.gdx.utils.GdxRuntimeException;

import java.lang.reflect.Field;

/**
 * Rewrite BitmapFont so that text can be obtained directly from the font
 * Calling method:
 * <pre>
 * protected BitmapFont bitmapFont; <br/>
 * //Load imitation Song font
 * FreeTypeFontGenerator generator = new FreeTypeFontGenerator(new FileHandle("C:\\Windows\Fonts\simfang.ttf"));
 * <br/> <br/>
 * bitmapFont = new SmartBitmapFont(generator,50);
 *
 * <br/>
 * bitmapFont.draw(batch, "Welcome", 0, 300);//Start from the lower left corner, 300 heights upward
 * 

*/
public class SmartBitmapFont extends BitmapFont {

// This should not be disposed here, let the upper layer dispose it
private FreeTypeFontGenerator generator;
private FreeTypeBitmapFontData data;
private FreeTypeFontParameter parameter;

public SmartBitmapFont(FreeTypeFontGenerator generator, int fontSize) {
if (generator == null)
throw new GdxRuntimeException(“lazyBitmapFont global generator must be not null to use this constructor.”);
this.generator = generator;
FreeTypeFontParameter param = new FreeTypeFontParameter();
param.size = fontSize;
this.parameter = param;
this.data = new LazyBitmapFontData(generator, fontSize, this);
try {
Field f = getClass().getSuperclass().getDeclaredField(“data”);
f.setAccessible(true);
f.set(this, data);
} catch (Exception e) {
e.printStackTrace();
}

generateData();
}

private void genrateData() {
Face face = null;
try {
Field field = generator.getClass().getDeclaredField(“face”);
field.setAccessible(true);
face = (Face) field.get(generator);
} catch (Exception e) {
e.printStackTrace();
return;
}

// set general font data
SizeMetrics fontMetrics = face.getSize().getMetrics();

// Set space glyph.
Glyph spaceGlyph = data.getGlyph(‘ ‘);
if (spaceGlyph == null) {
spaceGlyph = new Glyph();
spaceGlyph.xadvance = (int) data.scaleX;//spaceWidth
spaceGlyph.id = (int) ‘ ‘;
data.setGlyph(‘ ‘, spaceGlyph);
}
if (spaceGlyph. width == 0)
spaceGlyph.width = (int) (spaceGlyph.xadvance + data.padRight);

// set general font data
data.flipped = parameter.flip;
data.ascent = FreeType.toInt(fontMetrics.getAscender());
data.descent = FreeType.toInt(fontMetrics.getDescender());
data.lineHeight = FreeType.toInt(fontMetrics.getHeight());

// determine x-height
for (char xChar : data.xChars) {
if (!face.loadChar(xChar, FreeType.FT_LOAD_DEFAULT))
continue;
data.xHeight = FreeType.toInt(face.getGlyph().getMetrics().getHeight());
break;
}
if (data.xHeight == 0)
throw new GdxRuntimeException(“No x-height character found in font”);
for (char capChar : data.capChars) {
if (!face.loadChar(capChar, FreeType.FT_LOAD_DEFAULT))
continue;
data.capHeight = FreeType.toInt(face.getGlyph().getMetrics().getHeight());
break;
}

// determine cap height
if (data.capHeight == 1)
throw new GdxRuntimeException(“No cap character found in font”);
data.ascent = data.ascent – data.capHeight;
data.down = -data.lineHeight;
if (parameter.flip) {
data.ascent = -data.ascent;
data.down = -data.down;
}

}

@Override
public void dispose() {
setOwnsTexture(true);
super.dispose();
data.dispose();
}

class LazyBitmapFontData extends FreeTypeBitmapFontData {

private FreeTypeFontGenerator generator;
private int fontSize;
private SmartBitmapFont font;
private int page = 1;

public LazyBitmapFontData(FreeTypeFontGenerator generator, int fontSize, SmartBitmapFont lbf) {
this.generator = generator;
this.fontSize = fontSize;
this.font = lbf;
}

public Glyph getGlyph(char ch) {
Glyph glyph = super.getGlyph(ch);
if (glyph == null)
glyph = generateGlyph(ch);
return glyph;
}

protected Glyph generateGlyph(char ch) {
GlyphAndBitmap gab = generator.generateGlyphAndBitmap(ch, fontSize, false);
if (gab == null || gab.bitmap == null)//Literal character not found: ch
return null;

Pixmap map = gab.bitmap.getPixmap(Format.RGBA8888, Color.WHITE, 9);
TextureRegion rg = new TextureRegion(new Texture(map));
map.dispose();

font.getRegions().add(rg);

gab.glyph.page = page + + ;
super.setGlyph(ch, gab.glyph);
setGlyphRegion(gab.glyph, rg);
return gab.glyph;
}
}
}

Centered text

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.utils.Align;
import org.junit.Test;
import top.lingkang.yzcy.utils.SmartBitmapFont;

/**
 * @authorlingkang
 * created by 2023/11/1
 */
public class TestTxtCenter extends ApplicationAdapter {<!-- -->
    @Test
    public void test() {<!-- -->
        Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
        config.setForegroundFPS(30);
        config.setTitle("yzcy");
        config.setWindowedMode(800, 600);
        new Lwjgl3Application(this, config);
    }

    protectedSpriteBatch batch;
    protected BitmapFont bitmapFont;
    GlyphLayout layout = new GlyphLayout();
    //Load imitation Song font
    FreeTypeFontGenerator generator = new FreeTypeFontGenerator(new FileHandle("C:\\Windows\Fonts\simfang.ttf"));

    @Override
    public void create() {<!-- -->
        bitmapFont = new SmartBitmapFont(generator, 50);
        batch = new SpriteBatch();

        // center
        layout.setText(bitmapFont, "Welcome", Color.WHITE, Gdx.graphics.getWidth(), Align.center, true);
    }

    @Override
    public void render() {<!-- -->
        batch.begin();
        bitmapFont.draw(batch, layout, 0, 300);//Start from the lower left corner, 300 heights upward
        batch.end();
    }

    @Override
    public void dispose() {<!-- -->
        batch.dispose();
        bitmapFont.dispose();
        generator.dispose();
    }
}

Effect

The external link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly