FontSet.java

net.minecraft.client.gui.font.FontSet

信息

  • 全限定名:net.minecraft.client.gui.font.FontSet
  • 类型:public class
  • 包:net.minecraft.client.gui.font
  • 源码路径:src/main/java/net/minecraft/client/gui/font/FontSet.java
  • 起始行号:L32
  • 实现:AutoCloseable
  • 职责:

    TODO

字段/常量

  • LARGE_FORWARD_ADVANCE

    • 类型: float
    • 修饰符: private static final
    • 源码定位: L33
    • 说明:

      TODO

  • INVISIBLE_MISSING_GLYPH

    • 类型: BakedGlyph
    • 修饰符: private static final public public
    • 源码定位: L34
    • 说明:

      TODO

  • stitcher

    • 类型: GlyphStitcher
    • 修饰符: private final
    • 源码定位: L45
    • 说明:

      TODO

  • wrappedStitcher

    • 类型: UnbakedGlyph.Stitcher
    • 修饰符: private final public public
    • 源码定位: L46
    • 说明:

      TODO

  • allProviders

    • 类型: List<GlyphProvider.Conditional>
    • 修饰符: private
    • 源码定位: L61
    • 说明:

      TODO

  • activeProviders

    • 类型: List<GlyphProvider>
    • 修饰符: private
    • 源码定位: L62
    • 说明:

      TODO

  • glyphsByWidth

    • 类型: Int2ObjectMap<IntList>
    • 修饰符: private final
    • 源码定位: L63
    • 说明:

      TODO

  • glyphCache

    • 类型: CodepointMap<FontSet.SelectedGlyphs>
    • 修饰符: private final
    • 源码定位: L64
    • 说明:

      TODO

  • glyphGetter

    • 类型: IntFunction<FontSet.SelectedGlyphs>
    • 修饰符: private final
    • 源码定位: L65
    • 说明:

      TODO

  • missingGlyph

    • 类型: BakedGlyph
    • 修饰符: private
    • 源码定位: L66
    • 说明:

      TODO

  • missingGlyphGetter

    • 类型: Supplier<BakedGlyph>
    • 修饰符: private final
    • 源码定位: L67
    • 说明:

      TODO

  • missingSelectedGlyphs

    • 类型: FontSet.SelectedGlyphs
    • 修饰符: private final
    • 源码定位: L68
    • 说明:

      TODO

  • whiteGlyph

    • 类型: EffectGlyph
    • 修饰符: private
    • 源码定位: L69
    • 说明:

      TODO

  • anyGlyphs

    • 类型: GlyphSource
    • 修饰符: private final
    • 源码定位: L70
    • 说明:

      TODO

  • nonFishyGlyphs

    • 类型: GlyphSource
    • 修饰符: private final
    • 源码定位: L71
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.client.gui.font.FontSet.DelayedBake

    • 类型: class
    • 修饰符: private
    • 源码定位: L179
    • 说明:

      TODO

  • net.minecraft.client.gui.font.FontSet.SelectedGlyphs

    • 类型: record
    • 修饰符: private
    • 源码定位: L199
    • 说明:

      TODO

  • net.minecraft.client.gui.font.FontSet.Source

    • 类型: class
    • 修饰符: public
    • 源码定位: L206
    • 说明:

      TODO

构造器

public FontSet(GlyphStitcher stitcher) @ L73

  • 构造器名:FontSet
  • 源码定位:L73
  • 修饰符:public

参数:

  • stitcher: GlyphStitcher

说明:

TODO

方法

下面的方法块按源码顺序生成。

public void reload(List<GlyphProvider.Conditional> providers, Set<FontOption> options) @ L77

  • 方法名:reload
  • 源码定位:L77
  • 返回类型:void
  • 修饰符:public

参数:

  • providers: List<GlyphProvider.Conditional>
  • options: Set

说明:

TODO

public void reload(Set<FontOption> options) @ L82

  • 方法名:reload
  • 源码定位:L82
  • 返回类型:void
  • 修饰符:public

参数:

  • options: Set

说明:

TODO

private void resetTextures() @ L88

  • 方法名:resetTextures
  • 源码定位:L88
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

private List<GlyphProvider> selectProviders(List<GlyphProvider.Conditional> providers, Set<FontOption> options) @ L96

  • 方法名:selectProviders
  • 源码定位:L96
  • 返回类型:List
  • 修饰符:private

参数:

  • providers: List<GlyphProvider.Conditional>
  • options: Set

说明:

TODO

public void close() @ L123

  • 方法名:close
  • 源码定位:L123
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

private static boolean hasFishyAdvance(GlyphInfo glyph) @ L128

  • 方法名:hasFishyAdvance
  • 源码定位:L128
  • 返回类型:boolean
  • 修饰符:private static

参数:

  • glyph: GlyphInfo

说明:

TODO

private FontSet.SelectedGlyphs computeGlyphInfo(int codepoint) @ L138

  • 方法名:computeGlyphInfo
  • 源码定位:L138
  • 返回类型:FontSet.SelectedGlyphs
  • 修饰符:private

参数:

  • codepoint: int

说明:

TODO

private FontSet.SelectedGlyphs getGlyph(int codepoint) @ L161

  • 方法名:getGlyph
  • 源码定位:L161
  • 返回类型:FontSet.SelectedGlyphs
  • 修饰符:private

参数:

  • codepoint: int

说明:

TODO

public BakedGlyph getRandomGlyph(RandomSource random, int width) @ L165

  • 方法名:getRandomGlyph
  • 源码定位:L165
  • 返回类型:BakedGlyph
  • 修饰符:public

参数:

  • random: RandomSource
  • width: int

说明:

TODO

public EffectGlyph whiteGlyph() @ L170

  • 方法名:whiteGlyph
  • 源码定位:L170
  • 返回类型:EffectGlyph
  • 修饰符:public

参数:

说明:

TODO

public GlyphSource source(boolean nonFishyOnly) @ L174

  • 方法名:source
  • 源码定位:L174
  • 返回类型:GlyphSource
  • 修饰符:public

参数:

  • nonFishyOnly: boolean

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public class FontSet implements AutoCloseable {
    private static final float LARGE_FORWARD_ADVANCE = 32.0F;
    private static final BakedGlyph INVISIBLE_MISSING_GLYPH = new BakedGlyph() {
        @Override
        public GlyphInfo info() {
            return SpecialGlyphs.MISSING;
        }
 
        @Override
        public TextRenderable.@Nullable Styled createGlyph(float x, float y, int color, int shadowColor, Style style, float boldOffset, float shadowOffset) {
            return null;
        }
    };
    private final GlyphStitcher stitcher;
    private final UnbakedGlyph.Stitcher wrappedStitcher = new UnbakedGlyph.Stitcher() {
        {
            Objects.requireNonNull(FontSet.this);
        }
 
        @Override
        public BakedGlyph stitch(GlyphInfo glyphInfo, GlyphBitmap glyphBitmap) {
            return Objects.requireNonNullElse(FontSet.this.stitcher.stitch(glyphInfo, glyphBitmap), FontSet.this.missingGlyph);
        }
 
        @Override
        public BakedGlyph getMissing() {
            return FontSet.this.missingGlyph;
        }
    };
    private List<GlyphProvider.Conditional> allProviders = List.of();
    private List<GlyphProvider> activeProviders = List.of();
    private final Int2ObjectMap<IntList> glyphsByWidth = new Int2ObjectOpenHashMap<>();
    private final CodepointMap<FontSet.SelectedGlyphs> glyphCache = new CodepointMap<>(FontSet.SelectedGlyphs[]::new, FontSet.SelectedGlyphs[][]::new);
    private final IntFunction<FontSet.SelectedGlyphs> glyphGetter = this::computeGlyphInfo;
    private BakedGlyph missingGlyph = INVISIBLE_MISSING_GLYPH;
    private final Supplier<BakedGlyph> missingGlyphGetter = () -> this.missingGlyph;
    private final FontSet.SelectedGlyphs missingSelectedGlyphs = new FontSet.SelectedGlyphs(this.missingGlyphGetter, this.missingGlyphGetter);
    private @Nullable EffectGlyph whiteGlyph;
    private final GlyphSource anyGlyphs = new FontSet.Source(false);
    private final GlyphSource nonFishyGlyphs = new FontSet.Source(true);
 
    public FontSet(GlyphStitcher stitcher) {
        this.stitcher = stitcher;
    }
 
    public void reload(List<GlyphProvider.Conditional> providers, Set<FontOption> options) {
        this.allProviders = providers;
        this.reload(options);
    }
 
    public void reload(Set<FontOption> options) {
        this.activeProviders = List.of();
        this.resetTextures();
        this.activeProviders = this.selectProviders(this.allProviders, options);
    }
 
    private void resetTextures() {
        this.stitcher.reset();
        this.glyphCache.clear();
        this.glyphsByWidth.clear();
        this.missingGlyph = Objects.requireNonNull(SpecialGlyphs.MISSING.bake(this.stitcher));
        this.whiteGlyph = SpecialGlyphs.WHITE.bake(this.stitcher);
    }
 
    private List<GlyphProvider> selectProviders(List<GlyphProvider.Conditional> providers, Set<FontOption> options) {
        IntSet supportedGlyphs = new IntOpenHashSet();
        List<GlyphProvider> selectedProviders = new ArrayList<>();
 
        for (GlyphProvider.Conditional conditionalProvider : providers) {
            if (conditionalProvider.filter().apply(options)) {
                selectedProviders.add(conditionalProvider.provider());
                supportedGlyphs.addAll(conditionalProvider.provider().getSupportedGlyphs());
            }
        }
 
        Set<GlyphProvider> usedProviders = Sets.newHashSet();
        supportedGlyphs.forEach(codepoint -> {
            for (GlyphProvider provider : selectedProviders) {
                UnbakedGlyph glyph = provider.getGlyph(codepoint);
                if (glyph != null) {
                    usedProviders.add(provider);
                    if (glyph.info() != SpecialGlyphs.MISSING) {
                        this.glyphsByWidth.computeIfAbsent(Mth.ceil(glyph.info().getAdvance(false)), w -> new IntArrayList()).add(codepoint);
                    }
                    break;
                }
            }
        });
        return selectedProviders.stream().filter(usedProviders::contains).toList();
    }
 
    @Override
    public void close() {
        this.stitcher.close();
    }
 
    private static boolean hasFishyAdvance(GlyphInfo glyph) {
        float advance = glyph.getAdvance(false);
        if (!(advance < 0.0F) && !(advance > 32.0F)) {
            float boldAdvance = glyph.getAdvance(true);
            return boldAdvance < 0.0F || boldAdvance > 32.0F;
        } else {
            return true;
        }
    }
 
    private FontSet.SelectedGlyphs computeGlyphInfo(int codepoint) {
        FontSet.DelayedBake firstGlyph = null;
 
        for (GlyphProvider provider : this.activeProviders) {
            UnbakedGlyph glyph = provider.getGlyph(codepoint);
            if (glyph != null) {
                if (firstGlyph == null) {
                    firstGlyph = new FontSet.DelayedBake(glyph);
                }
 
                if (!hasFishyAdvance(glyph.info())) {
                    if (firstGlyph.unbaked == glyph) {
                        return new FontSet.SelectedGlyphs(firstGlyph, firstGlyph);
                    }
 
                    return new FontSet.SelectedGlyphs(firstGlyph, new FontSet.DelayedBake(glyph));
                }
            }
        }
 
        return firstGlyph != null ? new FontSet.SelectedGlyphs(firstGlyph, this.missingGlyphGetter) : this.missingSelectedGlyphs;
    }
 
    private FontSet.SelectedGlyphs getGlyph(int codepoint) {
        return this.glyphCache.computeIfAbsent(codepoint, this.glyphGetter);
    }
 
    public BakedGlyph getRandomGlyph(RandomSource random, int width) {
        IntList chars = this.glyphsByWidth.get(width);
        return chars != null && !chars.isEmpty() ? this.getGlyph(chars.getInt(random.nextInt(chars.size()))).nonFishy().get() : this.missingGlyph;
    }
 
    public EffectGlyph whiteGlyph() {
        return Objects.requireNonNull(this.whiteGlyph);
    }
 
    public GlyphSource source(boolean nonFishyOnly) {
        return nonFishyOnly ? this.nonFishyGlyphs : this.anyGlyphs;
    }
 
    @OnlyIn(Dist.CLIENT)
    private class DelayedBake implements Supplier<BakedGlyph> {
        private final UnbakedGlyph unbaked;
        private @Nullable BakedGlyph baked;
 
        private DelayedBake(UnbakedGlyph unbaked) {
            Objects.requireNonNull(FontSet.this);
            super();
            this.unbaked = unbaked;
        }
 
        public BakedGlyph get() {
            if (this.baked == null) {
                this.baked = this.unbaked.bake(FontSet.this.wrappedStitcher);
            }
 
            return this.baked;
        }
    }
 
    @OnlyIn(Dist.CLIENT)
    private record SelectedGlyphs(Supplier<BakedGlyph> any, Supplier<BakedGlyph> nonFishy) {
        private Supplier<BakedGlyph> select(boolean filterFishy) {
            return filterFishy ? this.nonFishy : this.any;
        }
    }
 
    @OnlyIn(Dist.CLIENT)
    public class Source implements GlyphSource {
        private final boolean filterFishyGlyphs;
 
        public Source(boolean filterFishyGlyphs) {
            Objects.requireNonNull(FontSet.this);
            super();
            this.filterFishyGlyphs = filterFishyGlyphs;
        }
 
        @Override
        public BakedGlyph getGlyph(int codepoint) {
            return FontSet.this.getGlyph(codepoint).select(this.filterFishyGlyphs).get();
        }
 
        @Override
        public BakedGlyph getRandomGlyph(RandomSource random, int width) {
            return FontSet.this.getRandomGlyph(random, width);
        }
    }
}

引用的其他类