TrueTypeGlyphProvider.java
com.mojang.blaze3d.font.TrueTypeGlyphProvider
信息
- 全限定名:com.mojang.blaze3d.font.TrueTypeGlyphProvider
- 类型:public class
- 包:com.mojang.blaze3d.font
- 源码路径:src/main/java/com/mojang/blaze3d/font/TrueTypeGlyphProvider.java
- 起始行号:L28
- 实现:GlyphProvider
- 职责:
TODO
字段/常量
-
fontMemory- 类型:
ByteBuffer - 修饰符:
private - 源码定位:
L29 - 说明:
TODO
- 类型:
-
face- 类型:
FT_Face - 修饰符:
private - 源码定位:
L30 - 说明:
TODO
- 类型:
-
oversample- 类型:
float - 修饰符:
private final - 源码定位:
L31 - 说明:
TODO
- 类型:
-
glyphs- 类型:
CodepointMap<TrueTypeGlyphProvider.GlyphEntry> - 修饰符:
private final - 源码定位:
L32 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
com.mojang.blaze3d.font.TrueTypeGlyphProvider.Glyph- 类型:
class - 修饰符:
private - 源码定位:
L140 - 说明:
TODO
- 类型:
-
com.mojang.blaze3d.font.TrueTypeGlyphProvider.GlyphEntry- 类型:
class - 修饰符:
private static - 源码定位:
L221 - 说明:
TODO
- 类型:
构造器
public TrueTypeGlyphProvider(ByteBuffer fontMemory, FT_Face face, float size, float oversample, float shiftX, float shiftY, String skip) @ L36
- 构造器名:TrueTypeGlyphProvider
- 源码定位:L36
- 修饰符:public
参数:
- fontMemory: ByteBuffer
- face: FT_Face
- size: float
- oversample: float
- shiftX: float
- shiftY: float
- skip: String
说明:
TODO
方法
下面的方法块按源码顺序生成。
public UnbakedGlyph getGlyph(int codepoint) @ L68
- 方法名:getGlyph
- 源码定位:L68
- 返回类型:UnbakedGlyph
- 修饰符:public
参数:
- codepoint: int
说明:
TODO
private UnbakedGlyph getOrLoadGlyphInfo(int codepoint, TrueTypeGlyphProvider.GlyphEntry entry) @ L74
- 方法名:getOrLoadGlyphInfo
- 源码定位:L74
- 返回类型:UnbakedGlyph
- 修饰符:private
参数:
- codepoint: int
- entry: TrueTypeGlyphProvider.GlyphEntry
说明:
TODO
private UnbakedGlyph loadGlyph(int codepoint, FT_Face face, int index) @ L90
- 方法名:loadGlyph
- 源码定位:L90
- 返回类型:UnbakedGlyph
- 修饰符:private
参数:
- codepoint: int
- face: FT_Face
- index: int
说明:
TODO
private FT_Face validateFontOpen() @ L112
- 方法名:validateFontOpen
- 源码定位:L112
- 返回类型:FT_Face
- 修饰符:private
参数:
- 无
说明:
TODO
public void close() @ L120
- 方法名:close
- 源码定位:L120
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public IntSet getSupportedGlyphs() @ L134
- 方法名:getSupportedGlyphs
- 源码定位:L134
- 返回类型:IntSet
- 修饰符:public
参数:
- 无
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public class TrueTypeGlyphProvider implements GlyphProvider {
private @Nullable ByteBuffer fontMemory;
private @Nullable FT_Face face;
private final float oversample;
private final CodepointMap<TrueTypeGlyphProvider.GlyphEntry> glyphs = new CodepointMap<>(
TrueTypeGlyphProvider.GlyphEntry[]::new, TrueTypeGlyphProvider.GlyphEntry[][]::new
);
public TrueTypeGlyphProvider(ByteBuffer fontMemory, FT_Face face, float size, float oversample, float shiftX, float shiftY, String skip) {
this.fontMemory = fontMemory;
this.face = face;
this.oversample = oversample;
IntSet skipSet = new IntArraySet();
skip.codePoints().forEach(skipSet::add);
int pixelsPerEm = Math.round(size * oversample);
FreeType.FT_Set_Pixel_Sizes(face, pixelsPerEm, pixelsPerEm);
float transformX = shiftX * oversample;
float transformY = -shiftY * oversample;
try (MemoryStack stack = MemoryStack.stackPush()) {
FT_Vector vector = FreeTypeUtil.setVector(FT_Vector.malloc(stack), transformX, transformY);
FreeType.FT_Set_Transform(face, null, vector);
IntBuffer indexPtr = stack.mallocInt(1);
int codepoint = (int)FreeType.FT_Get_First_Char(face, indexPtr);
while (true) {
int index = indexPtr.get(0);
if (index == 0) {
return;
}
if (!skipSet.contains(codepoint)) {
this.glyphs.put(codepoint, new TrueTypeGlyphProvider.GlyphEntry(index));
}
codepoint = (int)FreeType.FT_Get_Next_Char(face, codepoint, indexPtr);
}
}
}
@Override
public @Nullable UnbakedGlyph getGlyph(int codepoint) {
TrueTypeGlyphProvider.GlyphEntry entry = this.glyphs.get(codepoint);
return entry != null ? this.getOrLoadGlyphInfo(codepoint, entry) : null;
}
private UnbakedGlyph getOrLoadGlyphInfo(int codepoint, TrueTypeGlyphProvider.GlyphEntry entry) {
UnbakedGlyph result = entry.glyph;
if (result == null) {
FT_Face face = this.validateFontOpen();
synchronized (face) {
result = entry.glyph;
if (result == null) {
result = this.loadGlyph(codepoint, face, entry.index);
entry.glyph = result;
}
}
}
return result;
}
private UnbakedGlyph loadGlyph(int codepoint, FT_Face face, int index) {
int errorCode = FreeType.FT_Load_Glyph(face, index, 4194312);
if (errorCode != 0) {
FreeTypeUtil.assertError(errorCode, String.format(Locale.ROOT, "Loading glyph U+%06X", codepoint));
}
FT_GlyphSlot glyph = face.glyph();
if (glyph == null) {
throw new NullPointerException(String.format(Locale.ROOT, "Glyph U+%06X not initialized", codepoint));
} else {
float scaledAdvance = FreeTypeUtil.x(glyph.advance());
FT_Bitmap bitmap = glyph.bitmap();
int left = glyph.bitmap_left();
int top = glyph.bitmap_top();
int width = bitmap.width();
int height = bitmap.rows();
return (UnbakedGlyph)(width > 0 && height > 0
? new TrueTypeGlyphProvider.Glyph((float)left, (float)top, width, height, scaledAdvance, index)
: new EmptyGlyph(scaledAdvance / this.oversample));
}
}
private FT_Face validateFontOpen() {
if (this.fontMemory != null && this.face != null) {
return this.face;
} else {
throw new IllegalStateException("Provider already closed");
}
}
@Override
public void close() {
if (this.face != null) {
synchronized (FreeTypeUtil.LIBRARY_LOCK) {
FreeTypeUtil.checkError(FreeType.FT_Done_Face(this.face), "Deleting face");
}
this.face = null;
}
MemoryUtil.memFree(this.fontMemory);
this.fontMemory = null;
}
@Override
public IntSet getSupportedGlyphs() {
return this.glyphs.keySet();
}
@OnlyIn(Dist.CLIENT)
private class Glyph implements UnbakedGlyph {
private final int width;
private final int height;
private final float bearingX;
private final float bearingY;
private final GlyphInfo info;
private final int index;
private Glyph(float left, float top, int width, int height, float advance, int index) {
Objects.requireNonNull(TrueTypeGlyphProvider.this);
super();
this.width = width;
this.height = height;
this.info = GlyphInfo.simple(advance / TrueTypeGlyphProvider.this.oversample);
this.bearingX = left / TrueTypeGlyphProvider.this.oversample;
this.bearingY = top / TrueTypeGlyphProvider.this.oversample;
this.index = index;
}
@Override
public GlyphInfo info() {
return this.info;
}
@Override
public BakedGlyph bake(UnbakedGlyph.Stitcher stitcher) {
return stitcher.stitch(
this.info,
new GlyphBitmap() {
{
Objects.requireNonNull(Glyph.this);
}
@Override
public int getPixelWidth() {
return Glyph.this.width;
}
@Override
public int getPixelHeight() {
return Glyph.this.height;
}
@Override
public float getOversample() {
return TrueTypeGlyphProvider.this.oversample;
}
@Override
public float getBearingLeft() {
return Glyph.this.bearingX;
}
@Override
public float getBearingTop() {
return Glyph.this.bearingY;
}
@Override
public void upload(int x, int y, GpuTexture texture) {
FT_Face face = TrueTypeGlyphProvider.this.validateFontOpen();
try (NativeImage image = new NativeImage(NativeImage.Format.LUMINANCE, Glyph.this.width, Glyph.this.height, false)) {
if (image.copyFromFont(face, Glyph.this.index)) {
RenderSystem.getDevice()
.createCommandEncoder()
.writeToTexture(texture, image, 0, 0, x, y, Glyph.this.width, Glyph.this.height, 0, 0);
}
}
}
@Override
public boolean isColored() {
return false;
}
}
);
}
}
@OnlyIn(Dist.CLIENT)
private static class GlyphEntry {
private final int index;
private volatile @Nullable UnbakedGlyph glyph;
private GlyphEntry(int index) {
this.index = index;
}
}
}引用的其他类
-
- 引用位置:
构造调用 - 关联成员:
GlyphBitmap()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
GlyphInfo.simple()
- 引用位置:
-
- 引用位置:
实现
- 引用位置:
-
- 引用位置:
返回值
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
NativeImage()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
RenderSystem.getDevice()
- 引用位置:
-
- 引用位置:
字段
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
EmptyGlyph()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
FreeTypeUtil.assertError(), FreeTypeUtil.checkError(), FreeTypeUtil.setVector(), FreeTypeUtil.x()
- 引用位置: