diff --git a/src/br/nullexcept/mux/C.java b/src/br/nullexcept/mux/C.java index 274b0f7..fa19e19 100644 --- a/src/br/nullexcept/mux/C.java +++ b/src/br/nullexcept/mux/C.java @@ -1,6 +1,7 @@ package br.nullexcept.mux; import br.nullexcept.mux.graphics.BitmapFactory; +import br.nullexcept.mux.graphics.fonts.TypefaceFactory; import br.nullexcept.mux.utils.Log; import java.util.ArrayList; @@ -11,6 +12,7 @@ public class C { public static long VG_CONTEXT = -1; public static long GLFW_CONTEXT = 0; public static BitmapFactory BITMAP_FACTORY; + public static TypefaceFactory TYPEFACE_FACTORY; public static class Config { public static boolean SET_WINDOW_GL_HINT = true; diff --git a/src/br/nullexcept/mux/core/texel/TexelFont.java b/src/br/nullexcept/mux/core/texel/TexelFont.java new file mode 100644 index 0000000..45aa37d --- /dev/null +++ b/src/br/nullexcept/mux/core/texel/TexelFont.java @@ -0,0 +1,84 @@ +package br.nullexcept.mux.core.texel; + +import br.nullexcept.mux.C; +import br.nullexcept.mux.graphics.Paint; +import br.nullexcept.mux.graphics.fonts.FontMetrics; +import br.nullexcept.mux.graphics.fonts.Typeface; +import br.nullexcept.mux.utils.Log; +import org.lwjgl.nanovg.NVGGlyphPosition; +import org.lwjgl.nanovg.NanoVG; + +import java.nio.ByteBuffer; +import java.util.UUID; + +class TexelFont extends Typeface { + protected static final float SCALE = 1024.0f; + + protected final float ascent; + protected final float descent; + protected final float lineHeight; + protected final ByteBuffer buffer; + + private final int font; + private final String id = UUID.randomUUID().toString(); + private final short[] bounds = new short[1024*16]; //64KB of buffer for store characters bounds + + TexelFont(ByteBuffer buffer){ + this.buffer = buffer; + long context = C.VG_CONTEXT; + font = NanoVG.nvgCreateFontMem(context, id,buffer,false); + NanoVG.nvgFontFaceId(context, font); + NanoVG.nvgTextLetterSpacing(context, 0.0f); + NanoVG.nvgFontSize(context, SCALE); + NanoVG.nvgFontBlur(context,0); + float[] ascent = new float[1]; + float[] descent = new float[1]; + float[] lineHeight = new float[1]; + NanoVG.nvgTextMetrics(context, ascent,descent,lineHeight); + this.ascent = ascent[0]; + this.descent = descent[0]; + this.lineHeight = lineHeight[0]; + NVGGlyphPosition.create(); + NVGGlyphPosition.Buffer b = NVGGlyphPosition.create(1); + for (int i = 0; i < this.bounds.length; i++){ + String character = String.valueOf((char)i); + NanoVG.nvgTextGlyphPositions(context,0,0,character,b); + this.bounds[i] = (short) ((short) Math.abs(b.maxx()) + Math.abs(b.minx())); + } + } + + protected int measureChar(char ch){ + if (ch > bounds.length){ + Log.log("Typeface","INVALID MEASURE OUTBOUNDS CHAR: "+(int)ch); + ch = 'Z'; + } + switch (ch){ + case '\t': + case '\f': + return bounds[' ']; + case '\n': + case '\r': + return 0; + } + return bounds[ch]; + } + + public int hashCode(){ + return font; + } + + @Override + public String toString() { + return id; + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + } + + @Override + public FontMetrics getMetricsFor(Paint paint) { + return new TexelFontMetrics(paint); + } +} diff --git a/src/br/nullexcept/mux/core/texel/TexelFontFactory.java b/src/br/nullexcept/mux/core/texel/TexelFontFactory.java new file mode 100644 index 0000000..a58b2ae --- /dev/null +++ b/src/br/nullexcept/mux/core/texel/TexelFontFactory.java @@ -0,0 +1,20 @@ +package br.nullexcept.mux.core.texel; + +import br.nullexcept.mux.graphics.fonts.Typeface; +import br.nullexcept.mux.graphics.fonts.TypefaceFactory; +import br.nullexcept.mux.res.AssetsManager; +import br.nullexcept.mux.utils.BufferUtils; + +import java.io.InputStream; + +public class TexelFontFactory extends TypefaceFactory { + + public TexelFontFactory() { + Typeface.DEFAULT = decodeTypeface(TexelFontFactory.class.getResourceAsStream("/res/fonts/Roboto/Roboto-Regular.ttf")); + } + + @Override + protected Typeface decodeTypeface(InputStream input) { + return new TexelFont(BufferUtils.allocateStream(input)); + } +} diff --git a/src/br/nullexcept/mux/core/texel/TexelFontMetrics.java b/src/br/nullexcept/mux/core/texel/TexelFontMetrics.java new file mode 100644 index 0000000..55e2925 --- /dev/null +++ b/src/br/nullexcept/mux/core/texel/TexelFontMetrics.java @@ -0,0 +1,44 @@ +package br.nullexcept.mux.core.texel; + +import br.nullexcept.mux.graphics.Paint; +import br.nullexcept.mux.graphics.fonts.FontMetrics; + +public class TexelFontMetrics extends FontMetrics { + private final Paint paint; + + protected TexelFontMetrics(Paint paint){ + this.paint = paint; + } + + private TexelFont typeface() { + return ((TexelFont)paint.getTypeface()); + } + + public float getAscent(){ + return typeface().ascent * scale(); + } + public float getDescent(){ + return typeface().descent * scale(); + } + + public float getLineHeight() { + return typeface().lineHeight * scale(); + } + + public float measureChar(char ch){ + return typeface().measureChar(ch) * scale(); + } + + private float scale(){ + return (paint.getTextSize()/ TexelFont.SCALE); + } + public float measureText(CharSequence line){ + float width = 0; + TexelFont typeface = typeface(); + float scale = scale(); + for (int i = 0; i < line.length(); i++){ + width += typeface.measureChar(line.charAt(i)) * scale; + } + return width; + } +} diff --git a/src/br/nullexcept/mux/core/texel/VgTexel.java b/src/br/nullexcept/mux/core/texel/VgTexel.java index e50235e..049fb12 100644 --- a/src/br/nullexcept/mux/core/texel/VgTexel.java +++ b/src/br/nullexcept/mux/core/texel/VgTexel.java @@ -27,6 +27,7 @@ public static void initialize(){ clipContext = NanoVGGLES2.nvgCreate(NanoVGGLES2.NVG_ANTIALIAS); globalPaint.setTextSize(-1f); C.VG_CONTEXT = globalContext; + C.TYPEFACE_FACTORY = new TexelFontFactory(); C.BITMAP_FACTORY = new TexelBitmapFactory(); GLShaderList.build(); diff --git a/src/br/nullexcept/mux/graphics/Paint.java b/src/br/nullexcept/mux/graphics/Paint.java index 351dbdd..63a71eb 100644 --- a/src/br/nullexcept/mux/graphics/Paint.java +++ b/src/br/nullexcept/mux/graphics/Paint.java @@ -9,7 +9,7 @@ public class Paint { private int color = Color.WHITE; private float textSize = 18.0f; private float strokeWidth = 0.0f; - private final FontMetrics metrics; + private FontMetrics metrics; private Mode mode = Mode.FILL; public Paint(){ @@ -20,7 +20,6 @@ public Paint(int flags){ this.flags = flags; setTypeface(Typeface.DEFAULT); setTextSize(18.0f); - metrics = new PaintMetrics(this); } public Mode getMode() { @@ -57,6 +56,8 @@ public Typeface getTypeface() { public void setTypeface(Typeface typeface) { this.typeface = typeface; + if (typeface != null) + this.metrics = typeface.getMetricsFor(this); } public void setFlags(int flags) { @@ -75,12 +76,6 @@ public FontMetrics getFontMetrics() { return metrics; } - private class PaintMetrics extends FontMetrics { - protected PaintMetrics(Paint paint) { - super(paint); - } - } - public void from(Paint paint){ color = paint.color; mode = paint.mode; diff --git a/src/br/nullexcept/mux/graphics/fonts/FontMetrics.java b/src/br/nullexcept/mux/graphics/fonts/FontMetrics.java index d2a7100..80de509 100644 --- a/src/br/nullexcept/mux/graphics/fonts/FontMetrics.java +++ b/src/br/nullexcept/mux/graphics/fonts/FontMetrics.java @@ -1,41 +1,11 @@ package br.nullexcept.mux.graphics.fonts; -import br.nullexcept.mux.graphics.Paint; - public abstract class FontMetrics { - private final Paint paint; - - protected FontMetrics(Paint paint){ - this.paint = paint; - } - - public float getAscent(){ - return paint.getTypeface().ascent * scale(); - } - - public float getDescent(){ - return paint.getTypeface().descent * scale(); - } - - public float getLineHeight() { - return paint.getTypeface().lineHeight * scale(); - } - - public float measureChar(char ch){ - return paint.getTypeface().measureChar(ch) * scale(); - } - - private float scale(){ - return (paint.getTextSize()/Typeface.SCALE); - } + protected FontMetrics(){} - public float measureText(CharSequence line){ - float width = 0; - Typeface typeface = paint.getTypeface(); - float scale = scale(); - for (int i = 0; i < line.length(); i++){ - width += typeface.measureChar(line.charAt(i)) * scale; - } - return width; - } + public abstract float getAscent(); + public abstract float getDescent(); + public abstract float getLineHeight(); + public abstract float measureChar(char ch); + public abstract float measureText(CharSequence line); } diff --git a/src/br/nullexcept/mux/graphics/fonts/Typeface.java b/src/br/nullexcept/mux/graphics/fonts/Typeface.java index ad3cd34..750c919 100644 --- a/src/br/nullexcept/mux/graphics/fonts/Typeface.java +++ b/src/br/nullexcept/mux/graphics/fonts/Typeface.java @@ -1,83 +1,12 @@ package br.nullexcept.mux.graphics.fonts; -import br.nullexcept.mux.C; -import br.nullexcept.mux.utils.Log; -import org.lwjgl.nanovg.NVGGlyphPosition; -import org.lwjgl.nanovg.NanoVG; -import org.lwjgl.system.MemoryUtil; - -import java.nio.ByteBuffer; -import java.util.UUID; - -public class Typeface { - protected static final float SCALE = 1024.0f; +import br.nullexcept.mux.graphics.Paint; +public abstract class Typeface { public static final int STYLE_NORMAL = 0; public static final int STYLE_BOLD = 1; public static final int STYLE_ITALIC = 2; - public static Typeface DEFAULT; - protected final float ascent; - protected final float descent; - protected final float lineHeight; - protected final ByteBuffer buffer; - - private final int font; - private final String id = UUID.randomUUID().toString(); - private final short[] bounds = new short[1024*16]; //64KB of buffer for store characters bounds - - Typeface(ByteBuffer buffer){ - this.buffer = buffer; - long context = C.VG_CONTEXT; - font = NanoVG.nvgCreateFontMem(context, id,buffer,false); - NanoVG.nvgFontFaceId(context, font); - NanoVG.nvgTextLetterSpacing(context, 0.0f); - NanoVG.nvgFontSize(context, SCALE); - NanoVG.nvgFontBlur(context,0); - float[] ascent = new float[1]; - float[] descent = new float[1]; - float[] lineHeight = new float[1]; - NanoVG.nvgTextMetrics(context, ascent,descent,lineHeight); - this.ascent = ascent[0]; - this.descent = descent[0]; - this.lineHeight = lineHeight[0]; - NVGGlyphPosition.create(); - NVGGlyphPosition.Buffer b = NVGGlyphPosition.create(1); - for (int i = 0; i < this.bounds.length; i++){ - String character = String.valueOf((char)i); - NanoVG.nvgTextGlyphPositions(context,0,0,character,b); - this.bounds[i] = (short) ((short) Math.abs(b.maxx()) + Math.abs(b.minx())); - } - } - - protected int measureChar(char ch){ - if (ch > bounds.length){ - Log.log("Typeface","INVALID MEASURE OUTBOUNDS CHAR: "+(int)ch); - ch = 'Z'; - } - switch (ch){ - case '\t': - case '\f': - return bounds[' ']; - case '\n': - case '\r': - return 0; - } - return bounds[ch]; - } - - public int hashCode(){ - return font; - } - - @Override - public String toString() { - return id; - } - - @Override - protected void finalize() throws Throwable { - super.finalize(); - } + public abstract FontMetrics getMetricsFor(Paint paint); } diff --git a/src/br/nullexcept/mux/graphics/fonts/TypefaceFactory.java b/src/br/nullexcept/mux/graphics/fonts/TypefaceFactory.java index 582088a..92465a9 100644 --- a/src/br/nullexcept/mux/graphics/fonts/TypefaceFactory.java +++ b/src/br/nullexcept/mux/graphics/fonts/TypefaceFactory.java @@ -1,12 +1,15 @@ package br.nullexcept.mux.graphics.fonts; +import br.nullexcept.mux.C; import br.nullexcept.mux.utils.BufferUtils; import java.io.InputStream; -public class TypefaceFactory { +public abstract class TypefaceFactory { + + protected abstract Typeface decodeTypeface(InputStream input); public static Typeface create(InputStream stream){ - return new Typeface(BufferUtils.allocateStream(stream)); + return C.TYPEFACE_FACTORY.decodeTypeface(stream); } } diff --git a/src/br/nullexcept/mux/res/FallbackLanguage.java b/src/br/nullexcept/mux/res/FallbackLanguage.java index 529d42a..664ee8a 100644 --- a/src/br/nullexcept/mux/res/FallbackLanguage.java +++ b/src/br/nullexcept/mux/res/FallbackLanguage.java @@ -5,7 +5,7 @@ import java.util.HashMap; class FallbackLanguage { - private HashMap values = new HashMap<>(); + private final HashMap values = new HashMap<>(); public String getString(String id) { return values.getOrDefault(id, id); diff --git a/src/br/nullexcept/mux/text/TextLayout.java b/src/br/nullexcept/mux/text/TextLayout.java index 4ef6b2f..d099f33 100644 --- a/src/br/nullexcept/mux/text/TextLayout.java +++ b/src/br/nullexcept/mux/text/TextLayout.java @@ -11,7 +11,7 @@ public class TextLayout { private final FontMetrics font; private final Size viewport = new Size(); private final Selection selection; - private final TextRenderer drawer; + private TextRenderer drawer; private int gravity; // [INTERNAL LINE] => LINE | START | END | WIDTH @@ -26,6 +26,10 @@ public TextLayout(Editable text, Paint paint, TextRenderer drawer) { this.drawer = drawer; } + public void setRenderer(TextRenderer drawer) { + this.drawer = drawer; + } + public int getWidth() { return viewport.width; } diff --git a/src/br/nullexcept/mux/widget/TextView.java b/src/br/nullexcept/mux/widget/TextView.java index dcbb28d..01d41a7 100644 --- a/src/br/nullexcept/mux/widget/TextView.java +++ b/src/br/nullexcept/mux/widget/TextView.java @@ -74,6 +74,10 @@ public void setTextColor(int color){ invalidate(); } + protected TextLayout getLayout() { + return layout; + } + @Override protected void changeDrawableState() { super.changeDrawableState();