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(); } }