Skip to content

Commit

Permalink
Check SDF_OUTLINE fonts in PreviewGenerator.
Browse files Browse the repository at this point in the history
There are still some weird issues with some fonts, where it looks like the space character is getting partly outlined.
  • Loading branch information
tommyettinger committed Feb 17, 2024
1 parent a67e850 commit 10d94c8
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 102 deletions.
129 changes: 43 additions & 86 deletions src/main/java/com/github/tommyettinger/textra/Font.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,35 @@
*/
public class Font implements Disposable {

/**
* A {@link DistanceFieldType} that should be {@link DistanceFieldType#STANDARD} for most fonts, and can be
* {@link DistanceFieldType#SDF}, {@link DistanceFieldType#MSDF}, or {@link DistanceFieldType#SDF_OUTLINE} if you
* know you have a font made to be used with one of those rendering techniques. See {@link #distanceFieldCrispness}
* for one way to configure SDF and MSDF fonts, and {@link #resizeDistanceField(int, int)} for a convenience method
* to handle window-resizing sharply.
*/
public DistanceFieldType getDistanceField() {
return distanceField;
}

public void setDistanceField(DistanceFieldType distanceField) {
this.distanceField = distanceField;
if (distanceField == DistanceFieldType.MSDF) {
shader = new ShaderProgram(vertexShader, msdfFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "MSDF shader failed to compile: " + shader.getLog());
} else if (distanceField == DistanceFieldType.SDF) {
shader = new ShaderProgram(vertexShader, sdfFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "SDF shader failed to compile: " + shader.getLog());
} else if (distanceField == DistanceFieldType.SDF_OUTLINE) {
shader = new ShaderProgram(vertexShader, sdfBlackOutlineFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "SDF_OUTLINE shader failed to compile: " + shader.getLog());
} else shader = null;

}

/**
* Describes the region of a glyph in a larger TextureRegion, carrying a little more info about the offsets that
* apply to where the glyph is rendered.
Expand Down Expand Up @@ -418,14 +447,7 @@ public enum DistanceFieldType {
* drawn from a TextureAtlas that the font shares with other images.
*/
public Array<TextureRegion> parents;
/**
* A {@link DistanceFieldType} that should be {@link DistanceFieldType#STANDARD} for most fonts, and can be
* {@link DistanceFieldType#SDF}, {@link DistanceFieldType#MSDF}, or {@link DistanceFieldType#SDF_OUTLINE} if you
* know you have a font made to be used with one of those rendering techniques. See {@link #distanceFieldCrispness}
* for one way to configure SDF and MSDF fonts, and {@link #resizeDistanceField(int, int)} for a convenience method
* to handle window-resizing sharply.
*/
public DistanceFieldType distanceField;
private DistanceFieldType distanceField;
/**
* If true, this is a fixed-width (monospace) font; if false, this is probably a variable-width font. This affects
* some rendering decisions Font makes, such as whether subscript chars should take up half-width (for variable
Expand Down Expand Up @@ -1167,7 +1189,7 @@ public Font(String fntName, String textureName, DistanceFieldType distanceField)
* @param toCopy another Font to copy
*/
public Font(Font toCopy) {
distanceField = toCopy.distanceField;
this.distanceField = toCopy.distanceField;
isMono = toCopy.isMono;
actualCrispness = toCopy.actualCrispness;
distanceFieldCrispness = toCopy.distanceFieldCrispness;
Expand Down Expand Up @@ -1315,20 +1337,7 @@ public Font(String fntName, DistanceFieldType distanceField,
*/
public Font(String fntName, DistanceFieldType distanceField,
float xAdjust, float yAdjust, float widthAdjust, float heightAdjust, boolean makeGridGlyphs) {
this.distanceField = distanceField;
if (distanceField == DistanceFieldType.MSDF) {
shader = new ShaderProgram(vertexShader, msdfFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "MSDF shader failed to compile: " + shader.getLog());
} else if (distanceField == DistanceFieldType.SDF) {
shader = new ShaderProgram(vertexShader, sdfFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "SDF shader failed to compile: " + shader.getLog());
} else if (distanceField == DistanceFieldType.SDF_OUTLINE) {
shader = new ShaderProgram(vertexShader, sdfBlackOutlineFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "SDF_OUTLINE shader failed to compile: " + shader.getLog());
}
this.setDistanceField(distanceField);
loadFNT(fntName, xAdjust, yAdjust, widthAdjust, heightAdjust, makeGridGlyphs);
}

Expand Down Expand Up @@ -1398,20 +1407,7 @@ public Font(String fntName, String textureName, DistanceFieldType distanceField,
*/
public Font(String fntName, String textureName, DistanceFieldType distanceField,
float xAdjust, float yAdjust, float widthAdjust, float heightAdjust, boolean makeGridGlyphs) {
this.distanceField = distanceField;
if (distanceField == DistanceFieldType.MSDF) {
shader = new ShaderProgram(vertexShader, msdfFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "MSDF shader failed to compile: " + shader.getLog());
} else if (distanceField == DistanceFieldType.SDF) {
shader = new ShaderProgram(vertexShader, sdfFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "SDF shader failed to compile: " + shader.getLog());
} else if (distanceField == DistanceFieldType.SDF_OUTLINE) {
shader = new ShaderProgram(vertexShader, sdfBlackOutlineFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "SDF_OUTLINE shader failed to compile: " + shader.getLog());
}
this.setDistanceField(distanceField);
FileHandle textureHandle;
if ((textureHandle = Gdx.files.internal(textureName)).exists()
|| (textureHandle = Gdx.files.local(textureName)).exists()) {
Expand Down Expand Up @@ -1490,20 +1486,7 @@ public Font(String fntName, TextureRegion textureRegion, DistanceFieldType dista
*/
public Font(String fntName, TextureRegion textureRegion, DistanceFieldType distanceField,
float xAdjust, float yAdjust, float widthAdjust, float heightAdjust, boolean makeGridGlyphs) {
this.distanceField = distanceField;
if (distanceField == DistanceFieldType.MSDF) {
shader = new ShaderProgram(vertexShader, msdfFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "MSDF shader failed to compile: " + shader.getLog());
} else if (distanceField == DistanceFieldType.SDF) {
shader = new ShaderProgram(vertexShader, sdfFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "SDF shader failed to compile: " + shader.getLog());
} else if (distanceField == DistanceFieldType.SDF_OUTLINE) {
shader = new ShaderProgram(vertexShader, sdfBlackOutlineFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "SDF_OUTLINE shader failed to compile: " + shader.getLog());
}
this.setDistanceField(distanceField);
this.parents = Array.with(textureRegion);
if (distanceField != DistanceFieldType.STANDARD) {
textureRegion.getTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
Expand Down Expand Up @@ -1574,20 +1557,7 @@ public Font(String fntName, Array<TextureRegion> textureRegions, DistanceFieldTy
*/
public Font(String fntName, Array<TextureRegion> textureRegions, DistanceFieldType distanceField,
float xAdjust, float yAdjust, float widthAdjust, float heightAdjust, boolean makeGridGlyphs) {
this.distanceField = distanceField;
if (distanceField == DistanceFieldType.MSDF) {
shader = new ShaderProgram(vertexShader, msdfFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "MSDF shader failed to compile: " + shader.getLog());
} else if (distanceField == DistanceFieldType.SDF) {
shader = new ShaderProgram(vertexShader, sdfFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "SDF shader failed to compile: " + shader.getLog());
} else if (distanceField == DistanceFieldType.SDF_OUTLINE) {
shader = new ShaderProgram(vertexShader, sdfBlackOutlineFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "SDF_OUTLINE shader failed to compile: " + shader.getLog());
}
this.setDistanceField(distanceField);
this.parents = textureRegions;
if (distanceField != DistanceFieldType.STANDARD && textureRegions != null) {
for (TextureRegion parent : textureRegions)
Expand Down Expand Up @@ -1654,20 +1624,7 @@ public Font(BitmapFont bmFont, DistanceFieldType distanceField,
*/
public Font(BitmapFont bmFont, DistanceFieldType distanceField,
float xAdjust, float yAdjust, float widthAdjust, float heightAdjust, boolean makeGridGlyphs) {
this.distanceField = distanceField;
if (distanceField == DistanceFieldType.MSDF) {
shader = new ShaderProgram(vertexShader, msdfFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "MSDF shader failed to compile: " + shader.getLog());
} else if (distanceField == DistanceFieldType.SDF) {
shader = new ShaderProgram(vertexShader, sdfFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "SDF shader failed to compile: " + shader.getLog());
} else if (distanceField == DistanceFieldType.SDF_OUTLINE) {
shader = new ShaderProgram(vertexShader, sdfBlackOutlineFragmentShader);
if (!shader.isCompiled())
Gdx.app.error("textratypist", "SDF_OUTLINE shader failed to compile: " + shader.getLog());
}
this.setDistanceField(distanceField);
this.parents = bmFont.getRegions();
if (distanceField != DistanceFieldType.STANDARD && parents != null) {
for (TextureRegion parent : parents)
Expand Down Expand Up @@ -1808,7 +1765,7 @@ public Font(BitmapFont bmFont, DistanceFieldType distanceField,
* @param ignoredSadConsoleFlag the value is ignored here; the presence of this parameter says to load a SadConsole .font file
*/
public Font(String prefix, String fntName, boolean ignoredSadConsoleFlag) {
this.distanceField = DistanceFieldType.STANDARD;
this.setDistanceField(DistanceFieldType.STANDARD);
loadSad(prefix == null ? "" : prefix, fntName);
}

Expand Down Expand Up @@ -1864,7 +1821,7 @@ protected void loadFNT(String fntName, float xAdjust, float yAdjust, float width
if ((textureHandle = Gdx.files.internal(textureName)).exists()
|| (textureHandle = Gdx.files.local(textureName)).exists()) {
parents.add(new TextureRegion(new Texture(textureHandle)));
if (distanceField != DistanceFieldType.STANDARD)
if (getDistanceField() != DistanceFieldType.STANDARD)
parents.peek().getTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
} else {
throw new RuntimeException("Missing texture file: " + textureName);
Expand Down Expand Up @@ -2686,14 +2643,14 @@ public int atlasLookup(String name) {
* @param batch the Batch to instruct to use the appropriate shader for this font; should usually be a SpriteBatch
*/
public void enableShader(Batch batch) {
if (distanceField == DistanceFieldType.MSDF) {
if (getDistanceField() == DistanceFieldType.MSDF) {
if (batch.getShader() != shader) {
batch.setShader(shader);
shader.setUniformf("u_weight", 0f);
// shader.setUniformf("u_smoothing", 2f * distanceFieldCrispness);
shader.setUniformf("u_smoothing", 7f * actualCrispness * Math.max(cellHeight / originalCellHeight, cellWidth / originalCellWidth));
}
} else if (distanceField == DistanceFieldType.SDF || distanceField == DistanceFieldType.SDF_OUTLINE) {
} else if (getDistanceField() == DistanceFieldType.SDF || getDistanceField() == DistanceFieldType.SDF_OUTLINE) {
if (batch.getShader() != shader) {
batch.setShader(shader);
final float scale = Math.max(cellHeight / originalCellHeight, cellWidth / originalCellWidth) * 0.5f + 0.125f;
Expand Down Expand Up @@ -6310,15 +6267,15 @@ public void removeStoredState(String name) {
* @param height the new window height; usually a parameter in {@link com.badlogic.gdx.ApplicationListener#resize(int, int)}
*/
public void resizeDistanceField(int width, int height) {
if (distanceField == DistanceFieldType.MSDF) {
if (getDistanceField() == DistanceFieldType.MSDF) {
if (Gdx.graphics.getBackBufferWidth() == 0 || Gdx.graphics.getBackBufferHeight() == 0) {
actualCrispness = distanceFieldCrispness;
} else {
actualCrispness = distanceFieldCrispness * (float) Math.pow(8f,
Math.max((float) width / Gdx.graphics.getBackBufferWidth(),
(float) height / Gdx.graphics.getBackBufferHeight()) * 1.9f - 2.15f + cellHeight * 0.01f);
}
} else if (distanceField == DistanceFieldType.SDF || distanceField == DistanceFieldType.SDF_OUTLINE) {
} else if (getDistanceField() == DistanceFieldType.SDF || getDistanceField() == DistanceFieldType.SDF_OUTLINE) {
if (Gdx.graphics.getBackBufferWidth() == 0 || Gdx.graphics.getBackBufferHeight() == 0) {
actualCrispness = distanceFieldCrispness;
} else {
Expand Down Expand Up @@ -6494,7 +6451,7 @@ public String toString() {

public String debugString() {
return "Font{" +
"distanceField=" + distanceField +
"distanceField=" + getDistanceField() +
", isMono=" + isMono +
", kerning=" + kerning +
", actualCrispness=" + actualCrispness +
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/com/github/tommyettinger/textra/KnownFonts.java
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ public static Font getGentiumSDF() {
if (instance.gentiumSDF == null) {
try {
instance.gentiumSDF = new Font(instance.prefix + "Gentium-sdf.fnt",
instance.prefix + "Gentium-sdf.png", SDF, 4f, -45f, 0f, 0f, true)
instance.prefix + "Gentium-sdf.png", SDF, 4f, -45f, 0f, 0f, false)
.scaleTo(50, 45).adjustLineHeight(0.625f).setFancyLinePosition(0f, 1.1f)
.setLineMetrics(0.05f, 1f, 0f, -0.5f).setInlineImageMetrics(0f, -42f, 8f)
.setCrispness(1.5f).setName("Gentium (SDF)");
Expand Down Expand Up @@ -726,7 +726,7 @@ public static Font getGoNotoUniversalSDF() {
if (instance.goNotoUniversalSDF == null) {
try {
instance.goNotoUniversalSDF = new Font(instance.prefix + "GoNotoUniversal-sdf.fnt",
instance.prefix + "GoNotoUniversal-sdf.png", SDF, 0f, -16f, 0f, 0f, true)
instance.prefix + "GoNotoUniversal-sdf.png", SDF, 0f, -16f, 0f, 0f, false)
.scaleTo(43.25f, 34).adjustLineHeight(0.625f)
.setCrispness(1.8f).setFancyLinePosition(0f, 1.15f)
.setLineMetrics(0.25f, 0.85f, 0.2f, -0.5f).setInlineImageMetrics(0f, -28f, 16f)
Expand Down Expand Up @@ -1026,7 +1026,7 @@ public static Font getIosevkaSDF() {
// NOTE: If the .fnt file is changed, the manual adjustment to '_' (id=95) will be lost. yoffset was changed to 4.
// This should be OK now that this uses the box-drawing underline.
instance.iosevkaSDF = new Font(instance.prefix + "Iosevka-sdf.fnt",
instance.prefix + "Iosevka-sdf.png", SDF, 2f, 0f, -2f, -2f, true)
instance.prefix + "Iosevka-sdf.png", SDF, 2f, 0f, -2f, -2f, false)
.setLineMetrics(0.25f, -0.125f, 0f, -0.4f).setInlineImageMetrics(8f, 12f, 12f)
.setCrispness(0.75f).scaleTo(12, 26).fitCell(10, 25, false)
.setName("Iosevka (SDF)");
Expand Down Expand Up @@ -1159,7 +1159,7 @@ public static Font getIosevkaSlabSDF() {
// NOTE: If the .fnt file is changed, the manual adjustment to '_' (id=95) will be lost. yoffset was changed to 4.
// This might be OK now that this uses the box-drawing underline.
instance.iosevkaSlabSDF = new Font(instance.prefix + "Iosevka-Slab-sdf.fnt",
instance.prefix + "Iosevka-Slab-sdf.png", SDF, 2f, 0f, -2f, -2f, true)
instance.prefix + "Iosevka-Slab-sdf.png", SDF, 2f, 0f, -2f, -2f, false)
.setLineMetrics(0.25f, -0.125f, 0f, -0.4f).setInlineImageMetrics(8f, 12f, 12f)
.setCrispness(0.75f).scaleTo(12, 26).fitCell(10, 25, false)
.setName("Iosevka Slab (SDF)");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ public void draw(Batch batch, float parentAlpha) {
if (layout.lines.isEmpty() || parentAlpha <= 0f) return;

// we only change the shader or batch color if we actually are drawing something.
boolean resetShader = font.distanceField != Font.DistanceFieldType.STANDARD && batch.getShader() != font.shader;
boolean resetShader = font.getDistanceField() != Font.DistanceFieldType.STANDARD && batch.getShader() != font.shader;
if (resetShader)
font.enableShader(batch);
batch.getColor().set(getColor()).a *= parentAlpha;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,7 @@ public void draw(Batch batch, float parentAlpha) {
// baseY += workingLayout.lines.first().height * 0.25f;

int o = 0, s = 0, r = 0, gi = 0;
boolean resetShader = font.distanceField != Font.DistanceFieldType.STANDARD && batch.getShader() != font.shader;
boolean resetShader = font.getDistanceField() != Font.DistanceFieldType.STANDARD && batch.getShader() != font.shader;
if (resetShader)
font.enableShader(batch);
batch.getColor().set(getColor()).a *= parentAlpha;
Expand Down
Loading

0 comments on commit 10d94c8

Please sign in to comment.