BitmapProvider.java
net.minecraft.client.gui.font.providers.BitmapProvider
信息
- 全限定名:net.minecraft.client.gui.font.providers.BitmapProvider
- 类型:public class
- 包:net.minecraft.client.gui.font.providers
- 源码路径:src/main/java/net/minecraft/client/gui/font/providers/BitmapProvider.java
- 起始行号:L33
- 实现:GlyphProvider
- 职责:
TODO
字段/常量
-
LOGGER- 类型:
Logger - 修饰符:
private static final - 源码定位:
L34 - 说明:
TODO
- 类型:
-
image- 类型:
NativeImage - 修饰符:
private final - 源码定位:
L35 - 说明:
TODO
- 类型:
-
glyphs- 类型:
CodepointMap<BitmapProvider.Glyph> - 修饰符:
private final - 源码定位:
L36 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
net.minecraft.client.gui.font.providers.BitmapProvider.Definition- 类型:
record - 修饰符:
public - 源码定位:
L59 - 说明:
TODO
- 类型:
-
net.minecraft.client.gui.font.providers.BitmapProvider.Glyph- 类型:
record - 修饰符:
private - 源码定位:
L197 - 说明:
TODO
- 类型:
构造器
private BitmapProvider(NativeImage image, CodepointMap<BitmapProvider.Glyph> glyphs) @ L38
- 构造器名:BitmapProvider
- 源码定位:L38
- 修饰符:private
参数:
- image: NativeImage
- glyphs: CodepointMap<BitmapProvider.Glyph>
说明:
TODO
方法
下面的方法块按源码顺序生成。
public void close() @ L43
- 方法名:close
- 源码定位:L43
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public UnbakedGlyph getGlyph(int codepoint) @ L48
- 方法名:getGlyph
- 源码定位:L48
- 返回类型:UnbakedGlyph
- 修饰符:public
参数:
- codepoint: int
说明:
TODO
public IntSet getSupportedGlyphs() @ L53
- 方法名:getSupportedGlyphs
- 源码定位:L53
- 返回类型:IntSet
- 修饰符:public
参数:
- 无
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public class BitmapProvider implements GlyphProvider {
private static final Logger LOGGER = LogUtils.getLogger();
private final NativeImage image;
private final CodepointMap<BitmapProvider.Glyph> glyphs;
private BitmapProvider(NativeImage image, CodepointMap<BitmapProvider.Glyph> glyphs) {
this.image = image;
this.glyphs = glyphs;
}
@Override
public void close() {
this.image.close();
}
@Override
public @Nullable UnbakedGlyph getGlyph(int codepoint) {
return this.glyphs.get(codepoint);
}
@Override
public IntSet getSupportedGlyphs() {
return IntSets.unmodifiable(this.glyphs.keySet());
}
@OnlyIn(Dist.CLIENT)
public record Definition(Identifier file, int height, int ascent, int[][] codepointGrid) implements GlyphProviderDefinition {
private static final Codec<int[][]> CODEPOINT_GRID_CODEC = Codec.STRING.listOf().xmap(input -> {
int lineCount = input.size();
int[][] result = new int[lineCount][];
for (int i = 0; i < lineCount; i++) {
result[i] = input.get(i).codePoints().toArray();
}
return result;
}, grid -> {
List<String> result = new ArrayList<>(grid.length);
for (int[] line : grid) {
result.add(new String(line, 0, line.length));
}
return result;
}).validate(BitmapProvider.Definition::validateDimensions);
public static final MapCodec<BitmapProvider.Definition> CODEC = RecordCodecBuilder.<BitmapProvider.Definition>mapCodec(
i -> i.group(
Identifier.CODEC.fieldOf("file").forGetter(BitmapProvider.Definition::file),
Codec.INT.optionalFieldOf("height", 8).forGetter(BitmapProvider.Definition::height),
Codec.INT.fieldOf("ascent").forGetter(BitmapProvider.Definition::ascent),
CODEPOINT_GRID_CODEC.fieldOf("chars").forGetter(BitmapProvider.Definition::codepointGrid)
)
.apply(i, BitmapProvider.Definition::new)
)
.validate(BitmapProvider.Definition::validate);
private static DataResult<int[][]> validateDimensions(int[][] grid) {
int lineCount = grid.length;
if (lineCount == 0) {
return DataResult.error(() -> "Expected to find data in codepoint grid");
} else {
int[] firstLine = grid[0];
int lineWidth = firstLine.length;
if (lineWidth == 0) {
return DataResult.error(() -> "Expected to find data in codepoint grid");
} else {
for (int i = 1; i < lineCount; i++) {
int[] line = grid[i];
if (line.length != lineWidth) {
return DataResult.error(
() -> "Lines in codepoint grid have to be the same length (found: "
+ line.length
+ " codepoints, expected: "
+ lineWidth
+ "), pad with \\u0000"
);
}
}
return DataResult.success(grid);
}
}
}
private static DataResult<BitmapProvider.Definition> validate(BitmapProvider.Definition builder) {
return builder.ascent > builder.height
? DataResult.error(() -> "Ascent " + builder.ascent + " higher than height " + builder.height)
: DataResult.success(builder);
}
@Override
public GlyphProviderType type() {
return GlyphProviderType.BITMAP;
}
@Override
public Either<GlyphProviderDefinition.Loader, GlyphProviderDefinition.Reference> unpack() {
return Either.left(this::load);
}
private GlyphProvider load(ResourceManager resourceManager) throws IOException {
Identifier texture = this.file.withPrefix("textures/");
BitmapProvider var22;
try (InputStream resource = resourceManager.open(texture)) {
NativeImage image = NativeImage.read(NativeImage.Format.RGBA, resource);
int w = image.getWidth();
int h = image.getHeight();
int glyphWidth = w / this.codepointGrid[0].length;
int glyphHeight = h / this.codepointGrid.length;
float pixelScale = (float)this.height / glyphHeight;
CodepointMap<BitmapProvider.Glyph> charMap = new CodepointMap<>(BitmapProvider.Glyph[]::new, BitmapProvider.Glyph[][]::new);
for (int slotY = 0; slotY < this.codepointGrid.length; slotY++) {
int linePos = 0;
for (int c : this.codepointGrid[slotY]) {
int slotX = linePos++;
if (c != 0) {
int actualGlyphWidth = this.getActualGlyphWidth(image, glyphWidth, glyphHeight, slotX, slotY);
BitmapProvider.Glyph prev = charMap.put(
c,
new BitmapProvider.Glyph(
pixelScale,
image,
slotX * glyphWidth,
slotY * glyphHeight,
glyphWidth,
glyphHeight,
(int)(0.5 + actualGlyphWidth * pixelScale) + 1,
this.ascent
)
);
if (prev != null) {
BitmapProvider.LOGGER.warn("Codepoint '{}' declared multiple times in {}", Integer.toHexString(c), texture);
}
}
}
}
var22 = new BitmapProvider(image, charMap);
}
return var22;
}
private int getActualGlyphWidth(NativeImage image, int glyphWidth, int glyphHeight, int xGlyph, int yGlyph) {
int width;
for (width = glyphWidth - 1; width >= 0; width--) {
int xPixel = xGlyph * glyphWidth + width;
for (int y = 0; y < glyphHeight; y++) {
int yPixel = yGlyph * glyphHeight + y;
if (image.getLuminanceOrAlpha(xPixel, yPixel) != 0) {
return width + 1;
}
}
}
return width + 1;
}
}
@OnlyIn(Dist.CLIENT)
private record Glyph(float scale, NativeImage image, int offsetX, int offsetY, int width, int height, int advance, int ascent) implements UnbakedGlyph {
@Override
public GlyphInfo info() {
return GlyphInfo.simple(this.advance);
}
@Override
public BakedGlyph bake(UnbakedGlyph.Stitcher stitcher) {
return stitcher.stitch(
this.info(),
new GlyphBitmap() {
{
Objects.requireNonNull(Glyph.this);
}
@Override
public float getOversample() {
return 1.0F / Glyph.this.scale;
}
@Override
public int getPixelWidth() {
return Glyph.this.width;
}
@Override
public int getPixelHeight() {
return Glyph.this.height;
}
@Override
public float getBearingTop() {
return Glyph.this.ascent;
}
@Override
public void upload(int x, int y, GpuTexture texture) {
RenderSystem.getDevice()
.createCommandEncoder()
.writeToTexture(texture, Glyph.this.image, 0, 0, x, y, Glyph.this.width, Glyph.this.height, Glyph.this.offsetX, Glyph.this.offsetY);
}
@Override
public boolean isColored() {
return Glyph.this.image.format().components() > 1;
}
}
);
}
}
}引用的其他类
-
- 引用位置:
构造调用 - 关联成员:
GlyphBitmap()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
GlyphInfo.simple()
- 引用位置:
-
- 引用位置:
实现
- 引用位置:
-
- 引用位置:
返回值
- 引用位置:
-
- 引用位置:
参数/字段/方法调用 - 关联成员:
NativeImage.read()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
RenderSystem.getDevice()
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置: