summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/jogamp/graph/curve/text/HwTextRenderer.java29
-rw-r--r--src/com/jogamp/graph/font/Font.java44
-rw-r--r--src/com/jogamp/graph/font/FontFactory.java6
-rw-r--r--src/com/jogamp/graph/geom/AABBox.java7
-rw-r--r--src/demo/GPUTextGLListenerBase01.java53
-rw-r--r--src/demo/GPUTextNewtDemo01.java5
-rw-r--r--src/demo/GPUTextNewtDemo02.java6
-rw-r--r--src/jogamp/graph/font/FontInt.java9
-rw-r--r--src/jogamp/graph/font/typecast/TypecastFont.java99
-rw-r--r--src/jogamp/graph/font/typecast/TypecastFontFactory.java11
-rw-r--r--src/jogamp/graph/font/typecast/TypecastGlyph.java135
-rw-r--r--src/jogamp/graph/font/typecast/TypecastMetrics.java65
-rw-r--r--src/jogamp/graph/font/typecast/TypecastRenderer.java14
-rw-r--r--src/net/java/dev/typecast/ot/table/HdmxTable.java13
-rwxr-xr-xsrc/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java165
15 files changed, 432 insertions, 229 deletions
diff --git a/src/com/jogamp/graph/curve/text/HwTextRenderer.java b/src/com/jogamp/graph/curve/text/HwTextRenderer.java
index b16d2e6fd..f30f42cc5 100644
--- a/src/com/jogamp/graph/curve/text/HwTextRenderer.java
+++ b/src/com/jogamp/graph/curve/text/HwTextRenderer.java
@@ -114,8 +114,8 @@ public class HwTextRenderer {
this.regionType = type;
}
- public Font createFont(Vertex.Factory<? extends Vertex> factory, String name, int size) {
- return fontFactory.createFont(factory, name, size);
+ public Font createFont(Vertex.Factory<? extends Vertex> factory, String name) {
+ return fontFactory.createFont(factory, name);
}
@@ -123,9 +123,8 @@ public class HwTextRenderer {
String[] families,
String style,
String variant,
- String weight,
- String size) {
- return fontFactory.createFont(factory, families, style, variant, weight, size);
+ String weight) {
+ return fontFactory.createFont(factory, families, style, variant, weight);
}
/**
@@ -312,11 +311,11 @@ public class HwTextRenderer {
return true;
}
- private GlyphString createString(GL2ES2 gl, Font font, String str) {
+ private GlyphString createString(GL2ES2 gl, Font font, int size, String str) {
AffineTransform affineTransform = new AffineTransform(pointFactory);
Path2D[] paths = new Path2D[str.length()];
- ((FontInt)font).getOutline(str, affineTransform, paths);
+ ((FontInt)font).getOutline(str, size, affineTransform, paths);
GlyphString glyphString = new GlyphString(pointFactory, font.getName(), str);
glyphString.createfromFontPath(paths, affineTransform);
@@ -337,25 +336,27 @@ public class HwTextRenderer {
* @param font font to be used
* @param str text to be rendered
* @param position the lower left corner of the string
- * @param size texture size for multipass render
+ * @param fontSize font size
+ * @param texSize texture size for multipass render
* @throws Exception if TextRenderer not initialized
*/
- public void renderString3D(GL2ES2 gl, Font font, String str, float[] position, int size) {
+ public void renderString3D(GL2ES2 gl, Font font, String str, float[] position, int fontSize, int texSize) {
if(!initialized){
throw new GLException("HWTextRenderer: not initialized!");
}
- String fontStrHash = getTextHashCode(font, str);
+ String fontStrHash = getTextHashCode(font, str, fontSize);
GlyphString glyphString = strings.get(fontStrHash);
if(null == glyphString) {
- glyphString = createString(gl, font, str);
+ glyphString = createString(gl, font, fontSize, str);
strings.put(fontStrHash, glyphString);
}
- glyphString.renderString3D(pmvMatrix, win_width, win_height, size);
+ glyphString.renderString3D(pmvMatrix, win_width, win_height, texSize);
}
- private String getTextHashCode(Font font, String str){
- return "" + str.hashCode() + font.getSize();
+ private String getTextHashCode(Font font, String str, int fontSize) {
+ // FIXME: use integer hash code
+ return font.getName() + "." + str.hashCode() + "." + fontSize;
}
/** Clears the cached string curves
diff --git a/src/com/jogamp/graph/font/Font.java b/src/com/jogamp/graph/font/Font.java
index 0abaad5b5..fbdf1f474 100644
--- a/src/com/jogamp/graph/font/Font.java
+++ b/src/com/jogamp/graph/font/Font.java
@@ -29,46 +29,44 @@ package com.jogamp.graph.font;
import com.jogamp.graph.geom.AABBox;
+/**
+ * Interface wrapper for font implementation.
+ *
+ * TrueType Font Specification:
+ * http://developer.apple.com/fonts/ttrefman/rm06/Chap6.html
+ */
+
public interface Font {
/**
- * Metrics for font based on pixel size !
- *
- * If no pixelSize is given, this font's static pixelSize is being used.
- *
- * value = Table.value * fontSize * 1.0f / HeadTable.UnitsPerEm
+ * Metrics for font
*/
public interface Metrics {
- public float getAscent();
- public float getDescent();
- public float getLineGap();
- public float getScale();
- public float getScaleForPixelSize(float pixelSize);
- public AABBox getBBox();
+ float getAscent(float pixelSize);
+ float getDescent(float pixelSize);
+ float getLineGap(float pixelSize);
+ float getScale(float pixelSize);
+ AABBox getBBox(float pixelSize);
}
/**
- * Glyph for font symbols based on pixel size !
- *
- * If no pixelSize is given, this font's static pixelSize is being used.
+ * Glyph for font
*/
public interface Glyph {
public Font getFont();
public char getSymbol();
- public AABBox getBBox();
- public float getAdvance();
- public float getAdvanceForPixelSize(float pixelSize, boolean useFrationalMetrics);
+ public AABBox getBBox(float pixelSize);
+ public float getAdvance(float pixelSize, boolean useFrationalMetrics);
}
public String getName();
- public float getSize();
+
public Metrics getMetrics();
public Glyph getGlyph(char symbol);
-
- public float getStringWidth(String string);
- public float getStringHeight(String string);
- public AABBox getStringBounds(CharSequence string);
-
public int getNumGlyphs();
+
+ public float getStringWidth(String string, float pixelSize);
+ public float getStringHeight(String string, float pixelSize);
+ public AABBox getStringBounds(CharSequence string, float pixelSize);
} \ No newline at end of file
diff --git a/src/com/jogamp/graph/font/FontFactory.java b/src/com/jogamp/graph/font/FontFactory.java
index a96dac1b8..b595413ba 100644
--- a/src/com/jogamp/graph/font/FontFactory.java
+++ b/src/com/jogamp/graph/font/FontFactory.java
@@ -35,10 +35,8 @@ public interface FontFactory {
String[] families,
String style,
String variant,
- String weight,
- String size);
+ String weight);
Font createFont(Vertex.Factory<? extends Vertex> factory,
- String name,
- int size);
+ String name);
} \ No newline at end of file
diff --git a/src/com/jogamp/graph/geom/AABBox.java b/src/com/jogamp/graph/geom/AABBox.java
index 9199e5253..2e99daa83 100644
--- a/src/com/jogamp/graph/geom/AABBox.java
+++ b/src/com/jogamp/graph/geom/AABBox.java
@@ -47,6 +47,11 @@ public class AABBox {
computeCenter();
}
+
+ public String toString() {
+ return "[ "+low[0]+"/"+low[1]+"/"+low[1]+" .. "+high[0]+"/"+high[0]+"/"+high[0]+", ctr "+
+ center[0]+"/"+center[1]+"/"+center[1]+" ]";
+ }
public AABBox(float[] low, float[] high)
@@ -56,7 +61,7 @@ public class AABBox {
computeCenter();
}
-
+
public float[] getHigh()
{
return high;
diff --git a/src/demo/GPUTextGLListenerBase01.java b/src/demo/GPUTextGLListenerBase01.java
index 96a06085e..f894f4142 100644
--- a/src/demo/GPUTextGLListenerBase01.java
+++ b/src/demo/GPUTextGLListenerBase01.java
@@ -27,10 +27,14 @@
*/
package demo;
+import java.io.File;
+import java.io.IOException;
+
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
import javax.media.opengl.GLPipelineFactory;
import com.jogamp.graph.curve.text.HwTextRenderer;
@@ -39,16 +43,20 @@ import com.jogamp.graph.geom.Vertex;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.util.awt.Screenshot;
public abstract class GPUTextGLListenerBase01 implements GLEventListener {
Vertex.Factory<? extends Vertex> vfactory;
- HwTextRenderer textRenderer;
+ protected HwTextRenderer textRenderer;
+ Font font;
+ boolean debug;
+ boolean trace;
+
KeyAction keyAction;
boolean updateFont = true;
int fontSize = 40;
final int fontSizeModulo = 100;
- Font font;
final float[] position = new float[] {0,0,0};
@@ -56,12 +64,9 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener {
float yTran = 10;
float ang = 0f;
float zoom = -70f;
- // float zoom = -1000f;
- int texSize = 400; // FBO/tex size ..
+ int texSize = 400;
boolean updateMatrix = true;
- boolean debug;
- boolean trace;
static final String text1;
static final String text2;
@@ -71,8 +76,9 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener {
}
public GPUTextGLListenerBase01(Vertex.Factory<? extends Vertex> vfactory, int mode, boolean debug, boolean trace) {
- this.textRenderer = new HwTextRenderer(vfactory, mode);
this.vfactory = vfactory;
+ this.textRenderer = new HwTextRenderer(vfactory, mode);
+ this.font = textRenderer.createFont(vfactory, "Lucida Sans Regular");
this.debug = debug;
this.trace = trace;
}
@@ -82,7 +88,8 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener {
this.yTran = ytrans;
this.ang = angle;
this.zoom = zoom;
- this.texSize = fbosize;
+ this.texSize = fbosize;
+ updateMatrix = true;
}
public void init(GLAutoDrawable drawable) {
@@ -103,9 +110,9 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener {
gl.glViewport(xstart, ystart, width, height);
textRenderer.reshape(gl, 45.0f, width, height, 0.1f, 7000.0f);
- dumpMatrix();
+ dumpMatrix(true);
}
-
+ protected boolean printScreen = true;
public void display(GLAutoDrawable drawable) {
GL2ES2 gl = drawable.getGL().getGL2ES2();
@@ -119,11 +126,7 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener {
updateMatrix = false;
}
- if(updateFont) {
- font = textRenderer.createFont(vfactory, "Lucida Sans Regular", fontSize);
- updateFont = false;
- }
- textRenderer.renderString3D(gl, font, text2, position, texSize);
+ textRenderer.renderString3D(gl, font, text2, position, fontSize, texSize);
}
public void dispose(GLAutoDrawable drawable) {
@@ -134,30 +137,33 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener {
public void fontIncr(int v) {
fontSize = Math.abs((fontSize + v) % fontSizeModulo) ;
updateFont = true;
- dumpMatrix();
+ dumpMatrix(true);
}
public void zoom(int v){
zoom += v;
updateMatrix = true;
- dumpMatrix();
+ dumpMatrix(false);
}
public void move(float x, float y){
xTran += x;
yTran += y;
updateMatrix = true;
- dumpMatrix();
+ dumpMatrix(false);
}
public void rotate(float delta){
ang += delta;
ang %= 360.0f;
updateMatrix = true;
- dumpMatrix();
+ dumpMatrix(false);
}
- void dumpMatrix() {
+ void dumpMatrix(boolean bbox) {
System.err.println("Matrix: " + xTran + "/" + yTran + " x"+zoom + " @"+ang +" fontSize "+fontSize);
+ if(bbox) {
+ System.err.println("bbox: "+font.getStringBounds(text2, fontSize));
+ }
}
public void attachTo(GLWindow window) {
@@ -176,6 +182,11 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener {
window.removeKeyListener(keyAction);
}
+ public void printScreen(GLWindow window, String dir, String tech, boolean exportAlpha) throws GLException, IOException{
+ String filename = dir + tech + "-" + window.getWidth()+ "x" + window.getHeight() + "-" + texSize+ ".tga";
+ Screenshot.writeToTargaFile(new File(filename), window.getWidth(), window.getHeight(), exportAlpha);
+ }
+
public class KeyAction implements KeyListener {
public void keyPressed(KeyEvent arg0) {
if(arg0.getKeyCode() == KeyEvent.VK_1){
@@ -215,7 +226,7 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener {
}
else if(arg0.getKeyCode() == KeyEvent.VK_9){
rotate(-1);
- }
+ }
}
public void keyTyped(KeyEvent arg0) {}
public void keyReleased(KeyEvent arg0) {}
diff --git a/src/demo/GPUTextNewtDemo01.java b/src/demo/GPUTextNewtDemo01.java
index ad1020122..362627e56 100644
--- a/src/demo/GPUTextNewtDemo01.java
+++ b/src/demo/GPUTextNewtDemo01.java
@@ -27,6 +27,7 @@
*/
package demo;
+
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
@@ -47,7 +48,7 @@ public class GPUTextNewtDemo01 {
}
TextGLListener textGLListener = null;
-
+ GLWindow window;
public void testMe() {
GLProfile.initSingleton(true);
GLProfile glp = GLProfile.getGL2ES2();
@@ -57,7 +58,7 @@ public class GPUTextNewtDemo01 {
caps.setNumSamples(4); // 2 samples is not enough ..
System.out.println("Requested: "+caps);
- final GLWindow window = GLWindow.create(caps);
+ window = GLWindow.create(caps);
window.setPosition(10, 10);
window.setSize(500, 500);
diff --git a/src/demo/GPUTextNewtDemo02.java b/src/demo/GPUTextNewtDemo02.java
index c7e7504ab..bda7fe0e2 100644
--- a/src/demo/GPUTextNewtDemo02.java
+++ b/src/demo/GPUTextNewtDemo02.java
@@ -27,10 +27,13 @@
*/
package demo;
+import java.io.IOException;
+
import javax.media.opengl.GL;
import javax.media.opengl.GL3;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import com.jogamp.graph.curve.Region;
@@ -53,6 +56,7 @@ public class GPUTextNewtDemo02 {
public static void main(String[] args) {
GPUTextNewtDemo02 test = new GPUTextNewtDemo02();
test.testMe();
+
}
GLWindow window;
@@ -85,7 +89,7 @@ public class GPUTextNewtDemo02 {
private class TextGLListener extends GPUTextGLListenerBase01 {
public TextGLListener() {
super(SVertex.factory(), Region.TWO_PASS, DEBUG, TRACE);
- setMatrix(-10, 10, 0f, -1000, window.getWidth());
+ setMatrix(-10, 10, 0f, -1000, 400);
}
public void init(GLAutoDrawable drawable) {
diff --git a/src/jogamp/graph/font/FontInt.java b/src/jogamp/graph/font/FontInt.java
index 5b938bdbf..c18787723 100644
--- a/src/jogamp/graph/font/FontInt.java
+++ b/src/jogamp/graph/font/FontInt.java
@@ -35,11 +35,10 @@ import com.jogamp.graph.font.Font;
public interface FontInt extends Font {
public interface Glyph extends Font.Glyph {
- public Path2D getPath();
- public Path2D getPathForPixelSize(float pixelSize);
+ public Path2D getPath(); // unscaled path
+ public Path2D getPath(float pixelSize);
}
- public void getOutline(String string,
- AffineTransform transform,
- Path2D[] result);
+ public void getOutline(String string, float pixelSize,
+ AffineTransform transform, Path2D[] result);
}
diff --git a/src/jogamp/graph/font/typecast/TypecastFont.java b/src/jogamp/graph/font/typecast/TypecastFont.java
index 86c9601de..b95dccf21 100644
--- a/src/jogamp/graph/font/typecast/TypecastFont.java
+++ b/src/jogamp/graph/font/typecast/TypecastFont.java
@@ -38,6 +38,7 @@ import net.java.dev.typecast.ot.OTFont;
import net.java.dev.typecast.ot.OTFontCollection;
import net.java.dev.typecast.ot.table.CmapFormat;
import net.java.dev.typecast.ot.table.CmapTable;
+import net.java.dev.typecast.ot.table.HdmxTable;
import net.java.dev.typecast.ot.table.ID;
import com.jogamp.common.util.IntObjectHashMap;
@@ -50,30 +51,28 @@ class TypecastFont implements FontInt {
final Vertex.Factory<? extends Vertex> pointFactory;
final OTFontCollection fontset;
final OTFont font;
- final int size;
- Metrics metrics;
+ TypecastMetrics metrics;
final CmapFormat cmapFormat;
int cmapentries;
// final IntIntHashMap char2Code;
IntObjectHashMap char2Glyph;
- public static TypecastFont create(Vertex.Factory<? extends Vertex> factory, String name, int size) {
+ public static TypecastFont create(Vertex.Factory<? extends Vertex> factory, String name) {
String path = JavaFontLoader.getByName(name);
OTFontCollection fontset;
try {
fontset = OTFontCollection.create(new File(path));
- return new TypecastFont(factory, fontset, size);
+ return new TypecastFont(factory, fontset);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
- public TypecastFont(Vertex.Factory<? extends Vertex> factory, OTFontCollection fontset, int size) {
+ public TypecastFont(Vertex.Factory<? extends Vertex> factory, OTFontCollection fontset) {
this.pointFactory = factory;
this.fontset = fontset;
this.font = fontset.getFont(0);
- this.size = size;
CmapTable cmapTable = font.getCmapTable();
CmapFormat _cmapFormat = null;
@@ -124,10 +123,6 @@ class TypecastFont implements FontInt {
return fontset.getFileName();
}
- public float getSize() {
- return size;
- }
-
public Metrics getMetrics() {
if (metrics == null) {
metrics = new TypecastMetrics(this);
@@ -146,28 +141,90 @@ class TypecastFont implements FontInt {
if(DEBUG) {
System.err.println("New glyph: " + (int)symbol + " ( " + (char)symbol +" ) -> " + code + ", contours " + glyph.getPointCount() + ": " + path);
}
+ final HdmxTable hdmx = font.getHdmxTable();
+ if (null != hdmx) {
+ /*if(DEBUG) {
+ System.err.println("hdmx "+hdmx);
+ }*/
+ for (int i=0; i<hdmx.getNumberOfRecords(); i++)
+ {
+ final HdmxTable.DeviceRecord dr = hdmx.getRecord(i);
+ result.addAdvance(dr.getWidth(code), dr.getPixelSize());
+ if(DEBUG) {
+ System.err.println("hdmx advance : pixelsize = "+dr.getWidth(code)+" : "+ dr.getPixelSize());
+ }
+ }
+ }
char2Glyph.put(symbol, result);
}
return result;
}
- public void getOutline(String string, AffineTransform transform, Path2D[] result) {
- TypecastRenderer.getOutline(pointFactory, this, string, transform, result);
+ public void getOutline(String string, float pixelSize, AffineTransform transform, Path2D[] result) {
+ TypecastRenderer.getOutline(pointFactory, this, string, pixelSize, transform, result);
}
- public float getStringWidth(String string) {
- // return 0f; // FIXME font.getStringWidthForPixelSize(string, size);
- throw new RuntimeException("n/a");
+ public float getStringWidth(String string, float pixelSize) {
+ float width = 0;
+ final int len = string.length();
+ for (int i=0; i< len; i++)
+ {
+ char character = string.charAt(i);
+ if (character == '\n') {
+ width = 0;
+ } else {
+ Glyph glyph = getGlyph(character);
+ width += glyph.getAdvance(pixelSize, false);
+ }
+ }
+
+ return (int)(width + 0.5f);
}
- public float getStringHeight(String string) {
- // return 0f; // FIXME font.getStringHeightForPixelSize(string, size);
- throw new RuntimeException("n/a");
+ public float getStringHeight(String string, float pixelSize) {
+ int height = 0;
+
+ for (int i=0; i<string.length(); i++)
+ {
+ char character = string.charAt(i);
+ if (character != ' ')
+ {
+ Glyph glyph = getGlyph(character);
+ AABBox bbox = glyph.getBBox(pixelSize);
+ height = (int)Math.ceil(Math.max(bbox.getHeight(), height));
+ }
+ }
+ return height;
}
- public AABBox getStringBounds(CharSequence string) {
- // return null; // FIXME font.getStringBoundsForPixelSize(string, size);
- throw new RuntimeException("n/a");
+ public AABBox getStringBounds(CharSequence string, float pixelSize) {
+ if (string == null) {
+ return new AABBox();
+ }
+ final Metrics metrics = getMetrics();
+ final float lineGap = metrics.getLineGap(pixelSize);
+ final float ascent = metrics.getAscent(pixelSize);
+ final float descent = metrics.getDescent(pixelSize);
+ final float advanceY = lineGap - descent + ascent;
+ float totalHeight = 0;
+ float totalWidth = 0;
+ float curLineWidth = 0;
+ for (int i=0; i<string.length(); i++) {
+ char character = string.charAt(i);
+ if (character == '\n') {
+ totalWidth = Math.max(curLineWidth, totalWidth);
+ curLineWidth = 0;
+ totalHeight -= advanceY;
+ continue;
+ }
+ Glyph glyph = getGlyph(character);
+ curLineWidth += glyph.getAdvance(pixelSize, true);
+ }
+ if (curLineWidth > 0) {
+ totalHeight -= advanceY;
+ totalWidth = Math.max(curLineWidth, totalWidth);
+ }
+ return new AABBox(0, 0, 0, totalWidth, totalHeight,0);
}
final public int getNumGlyphs() {
diff --git a/src/jogamp/graph/font/typecast/TypecastFontFactory.java b/src/jogamp/graph/font/typecast/TypecastFontFactory.java
index 6179986fe..04559a138 100644
--- a/src/jogamp/graph/font/typecast/TypecastFontFactory.java
+++ b/src/jogamp/graph/font/typecast/TypecastFontFactory.java
@@ -40,12 +40,12 @@ public class TypecastFontFactory implements FontFactory {
Map<String, Font> fonts = new HashMap<String, Font>();
- public Font createFont(Factory<? extends Vertex> factory, String name, int size) {
- Font result = fonts.get(name + ":"+size);
+ public Font createFont(Factory<? extends Vertex> factory, String name) {
+ Font result = fonts.get(name);
if (result == null) {
- result = TypecastFont.create(factory, name, size);
+ result = TypecastFont.create(factory, name);
if(result != null) {
- fonts.put(name+":"+size, result);
+ fonts.put(name, result);
}
}
return result;
@@ -56,8 +56,7 @@ public class TypecastFontFactory implements FontFactory {
String[] families,
String style,
String variant,
- String weight,
- String size) {
+ String weight) {
throw new Error("not implemented");
}
diff --git a/src/jogamp/graph/font/typecast/TypecastGlyph.java b/src/jogamp/graph/font/typecast/TypecastGlyph.java
index 9bb582974..88d865f9c 100644
--- a/src/jogamp/graph/font/typecast/TypecastGlyph.java
+++ b/src/jogamp/graph/font/typecast/TypecastGlyph.java
@@ -27,6 +27,8 @@
*/
package jogamp.graph.font.typecast;
+import java.util.HashMap;
+
import jogamp.graph.font.FontInt;
import jogamp.graph.geom.plane.AffineTransform;
import jogamp.graph.geom.plane.Path2D;
@@ -37,93 +39,58 @@ import com.jogamp.graph.geom.AABBox;
public class TypecastGlyph implements FontInt.Glyph {
public class Advance
{
- Font font;
- float advance;
- float advances[]; // in pixels
- float sizes[];
- float advanceCached = -1; // in pixels
- float sizeCached = -1;
+ final Font font;
+ final float advance;
+ HashMap<Float, Float> size2advance = new HashMap<Float, Float>();
public Advance(Font font, float advance)
{
this.font = font;
this.advance = advance;
-
- this.advances = new float[0];
- this.sizes = new float[0];
}
- public float getScaleForPixelSize(float pixelSize)
+ public void reset() {
+ size2advance.clear();
+ }
+
+ public float getScale(float pixelSize)
{
- return this.font.getMetrics().getScaleForPixelSize(pixelSize);
+ return this.font.getMetrics().getScale(pixelSize);
}
public void add(float advance, float size)
{
- float advancesNew[] = new float[this.advances.length+1];
- float sizesNew[] = new float[this.sizes.length+1];
-
- for (int i=0; i<this.advances.length; i++) {
- advancesNew[i] = this.advances[i];
- sizesNew[i] = this.sizes[i];
- }
-
- advancesNew[advancesNew.length-1] = advance;
- sizesNew[sizesNew.length-1] = size;
-
- this.advances = advancesNew;
- this.sizes = sizesNew;
+ size2advance.put(size, advance);
}
public float get(float size, boolean useFrationalMetrics)
{
- if (this.sizeCached != size) {
- this.sizeCached = size;
-
- float value = (this.advance * getScaleForPixelSize(size));
+ Float fo = size2advance.get(size);
+ if(null == fo) {
+ float value = (this.advance * getScale(size));
if (useFrationalMetrics == false) {
//value = (float)Math.ceil(value);
// value = (int)value;
value = (int) ( value + 0.5f ) ; // TODO: check
}
-
- if (true)
- {
- for (int i=0; i<this.advances.length; i++)
- {
- if (this.sizes[i] == size)
- {
- value = this.advances[i];
- break;
- }
- }
- }
-
- this.advanceCached = value;
+ size2advance.put(size, value);
+ return value;
}
- return this.advanceCached;
+ return fo.floatValue();
}
public String toString()
{
- String string = "";
- for (int i=0; i<this.advances.length; i++) {
- string += " size: "+this.sizes[i]+" advance: "+this.advances[i]+"\n";
- }
- if (string.length() > 0) {
- string = "\n advances: \n"+string;
- }
return "\nAdvance:"+
"\n advance: "+this.advance+
- string;
+ "\n advances: \n"+size2advance;
}
}
public class Metrics
{
AABBox bbox;
- AABBox bbox_sized;
- Advance advance;
+ Advance advance;
public Metrics(Font font, AABBox bbox, float advance)
{
@@ -131,9 +98,13 @@ public class TypecastGlyph implements FontInt.Glyph {
this.advance = new Advance(font, advance);
}
- public float getScaleForPixelSize(float pixelSize)
+ public void reset() {
+ advance.reset();
+ }
+
+ public float getScale(float pixelSize)
{
- return this.advance.getScaleForPixelSize(pixelSize);
+ return this.advance.getScale(pixelSize);
}
public AABBox getBBox()
@@ -146,7 +117,7 @@ public class TypecastGlyph implements FontInt.Glyph {
this.advance.add(advance, size);
}
- public float getAdvanceForPixelSize(float size, boolean useFrationalMetrics)
+ public float getAdvance(float size, boolean useFrationalMetrics)
{
return this.advance.get(size, useFrationalMetrics);
}
@@ -197,6 +168,11 @@ public class TypecastGlyph implements FontInt.Glyph {
this.metrics = new Metrics(this.font, bbox, this.advance);
}
+ public void reset(Path2D path) {
+ this.path = path;
+ this.metrics.reset();
+ }
+
public Font getFont() {
return this.font;
}
@@ -221,51 +197,36 @@ public class TypecastGlyph implements FontInt.Glyph {
return this.id;
}
- public float getScaleForPixelSize(float pixelSize) {
- return this.metrics.getScaleForPixelSize(pixelSize);
+ public float getScale(float pixelSize) {
+ return this.metrics.getScale(pixelSize);
}
- public AABBox getBBox(float size) {
- AABBox newBox = getBBox().clone();
- newBox.scale(size);
- return newBox;
- }
-
- public AABBox getBBoxForPixelSize(float pixelSize) {
- return getBBox(getScaleForPixelSize(pixelSize));
+ public AABBox getBBox(float pixelSize) {
+ final float size = getScale(pixelSize);
+ AABBox newBox = getBBox().clone();
+ newBox.scale(size);
+ return newBox;
}
protected void addAdvance(float advance, float size) {
this.metrics.addAdvance(advance, size);
}
- public float getAdvanceForPixelSize(float size, boolean useFrationalMetrics) {
- return this.metrics.getAdvanceForPixelSize(size, useFrationalMetrics);
- }
-
- public float getAdvance() {
- return getAdvanceForPixelSize(font.getSize(), false);
+ public float getAdvance(float pixelSize, boolean useFrationalMetrics) {
+ return this.metrics.getAdvance(pixelSize, useFrationalMetrics);
}
public Path2D getPath() {
- return getPath(getScaleForPixelSize(font.getSize()));
+ return this.path;
}
- private Path2D getPath(float size)
- {
+ public Path2D getPath(float pixelSize) {
+ final float size = getScale(pixelSize);
+
if (this.numberSized != size) {
- this.numberSized = size;
- this.pathSized = AffineTransform.getScaleInstance(null, size, size).createTransformedShape(getPath());
+ this.numberSized = size;
+ this.pathSized = AffineTransform.getScaleInstance(null, size, size).createTransformedShape(getPath());
}
return this.pathSized;
- }
-
- public Path2D getPathForPixelSize(float pixelSize) {
- return getPath(getScaleForPixelSize(pixelSize));
- }
-
- public Path2D getNormalPath() {
- return this.path;
- }
-
+ }
}
diff --git a/src/jogamp/graph/font/typecast/TypecastMetrics.java b/src/jogamp/graph/font/typecast/TypecastMetrics.java
index 541ed90d8..9ca1e3bf7 100644
--- a/src/jogamp/graph/font/typecast/TypecastMetrics.java
+++ b/src/jogamp/graph/font/typecast/TypecastMetrics.java
@@ -37,51 +37,42 @@ class TypecastMetrics implements Metrics {
private final TypecastFont fontImpl;
// HeadTable
+ private final HeadTable headTable;
private final float unitsPerEM_Inv;
- private final float unitsPerEM_Inv_sized;
- private final AABBox bbox_sized;
-
+ private final AABBox bbox;
// HheaTable
- private final float ascend_sized;
- private final float descent_sized;
- private final float linegap_sized;
+ private final HheaTable hheaTable;
public TypecastMetrics(TypecastFont fontImpl) {
this.fontImpl = fontImpl;
- final HeadTable headTable = this.fontImpl.font.getHeadTable();
- unitsPerEM_Inv = 1.0f / ( (float) headTable.getUnitsPerEm() );
- unitsPerEM_Inv_sized = this.fontImpl.size * unitsPerEM_Inv;
- int maxWidth = headTable.getXMax() - headTable.getXMin();
- int maxHeight = headTable.getYMax() - headTable.getYMin();
- float lowx= headTable.getXMin();
- float lowy = -(headTable.getYMin()+maxHeight);
- float highx = lowx + maxWidth;
- float highy = lowy + maxHeight;
- bbox_sized = new AABBox(lowx, lowy, 0, highx, highy, 0); // invert
- bbox_sized.scale(unitsPerEM_Inv_sized);
-
- final HheaTable hheaTable = this.fontImpl.font.getHheaTable();
- ascend_sized = unitsPerEM_Inv_sized * -hheaTable.getAscender(); // invert
- descent_sized = unitsPerEM_Inv_sized * -hheaTable.getDescender(); // invert
- linegap_sized = unitsPerEM_Inv_sized * -hheaTable.getLineGap(); // invert
+ headTable = this.fontImpl.font.getHeadTable();
+ hheaTable = this.fontImpl.font.getHheaTable();
+ unitsPerEM_Inv = 1.0f / ( (float) headTable.getUnitsPerEm() );
+
+ int maxWidth = headTable.getXMax() - headTable.getXMin();
+ int maxHeight = headTable.getYMax() - headTable.getYMin();
+ float lowx= headTable.getXMin();
+ float lowy = -(headTable.getYMin()+maxHeight);
+ float highx = lowx + maxWidth;
+ float highy = lowy + maxHeight;
+ bbox = new AABBox(lowx, lowy, 0, highx, highy, 0); // invert
}
-
- public final float getAscent() {
- return ascend_sized;
+
+ public final float getAscent(float pixelSize) {
+ return getScale(pixelSize) * -hheaTable.getAscender(); // invert
}
- public final float getDescent() {
- return descent_sized;
+ public final float getDescent(float pixelSize) {
+ return getScale(pixelSize) * -hheaTable.getDescender(); // invert
}
- public final float getLineGap() {
- return linegap_sized;
+ public final float getLineGap(float pixelSize) {
+ return getScale(pixelSize) * -hheaTable.getLineGap(); // invert
}
- public final float getScale() {
- return unitsPerEM_Inv_sized;
- }
- public float getScaleForPixelSize(float pixelSize) {
- return pixelSize * unitsPerEM_Inv;
- }
- public final AABBox getBBox() {
- return bbox_sized;
+ public final float getScale(float pixelSize) {
+ return pixelSize * unitsPerEM_Inv;
+ }
+ public final AABBox getBBox(float pixelSize) {
+ AABBox res = new AABBox(bbox.getLow(), bbox.getHigh());
+ res.scale(getScale(pixelSize));
+ return res;
}
} \ No newline at end of file
diff --git a/src/jogamp/graph/font/typecast/TypecastRenderer.java b/src/jogamp/graph/font/typecast/TypecastRenderer.java
index 74e5cd604..11f1ec028 100644
--- a/src/jogamp/graph/font/typecast/TypecastRenderer.java
+++ b/src/jogamp/graph/font/typecast/TypecastRenderer.java
@@ -44,16 +44,16 @@ import net.java.dev.typecast.ot.OTGlyph;
public class TypecastRenderer {
public static void getOutline(Factory<? extends Vertex> factory, TypecastFont font,
- String string, AffineTransform transform, Path2D[] p)
+ String string, float pixelSize, AffineTransform transform, Path2D[] p)
{
if (string == null) {
return;
}
Font.Metrics metrics = font.getMetrics();
float advanceTotal = 0;
- float lineGap = metrics.getLineGap() ;
- float ascent = metrics.getAscent() ;
- float descent = metrics.getDescent() ;
+ float lineGap = metrics.getLineGap(pixelSize) ;
+ float ascent = metrics.getAscent(pixelSize) ;
+ float descent = metrics.getDescent(pixelSize) ;
if (transform == null) {
transform = new AffineTransform(factory);
}
@@ -73,12 +73,12 @@ public class TypecastRenderer {
continue;
}
TypecastGlyph glyph = (TypecastGlyph) font.getGlyph(character);
- Path2D gp = glyph.getNormalPath();
- float scale = metrics.getScale();
+ Path2D gp = glyph.getPath();
+ float scale = metrics.getScale(pixelSize);
t.translate(advanceTotal, y);
t.scale(scale, scale);
p[i].append(gp.iterator(t), false);
- advanceTotal += glyph.getAdvanceForPixelSize(font.getSize(), true);
+ advanceTotal += glyph.getAdvance(pixelSize, true);
}
}
diff --git a/src/net/java/dev/typecast/ot/table/HdmxTable.java b/src/net/java/dev/typecast/ot/table/HdmxTable.java
index e47c0a316..68a03c590 100644
--- a/src/net/java/dev/typecast/ot/table/HdmxTable.java
+++ b/src/net/java/dev/typecast/ot/table/HdmxTable.java
@@ -57,6 +57,11 @@ public class HdmxTable implements Table {
public short[] getWidths() {
return _widths;
}
+
+ public short getWidth(int glyphidx) {
+ return _widths[glyphidx];
+ }
+
}
private DirectoryEntry _de;
@@ -80,6 +85,14 @@ public class HdmxTable implements Table {
}
}
+ public int getNumberOfRecords() {
+ return _numRecords;
+ }
+
+ public DeviceRecord getRecord(int i) {
+ return _records[i];
+ }
+
public int getType() {
return hdmx;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java
new file mode 100755
index 000000000..0d48206f9
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java
@@ -0,0 +1,165 @@
+package test.com.jogamp.opengl.test.junit.graph;
+
+import java.io.IOException;
+
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.geom.opengl.SVertex;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.util.FPSAnimator;
+
+import demo.GPUTextGLListenerBase01;
+
+public class TestHwTextRenderer01 {
+
+ @BeforeClass
+ public static void initClass() {
+ GLProfile.initSingleton(true);
+ NativeWindowFactory.initSingleton(true);
+ }
+
+ static void destroyWindow(Window window) {
+ if(null!=window) {
+ window.destroy();
+ }
+ }
+
+ static GLWindow createWindow(String title, GLCapabilities caps, int width, int height) {
+ Assert.assertNotNull(caps);
+
+ GLWindow window = GLWindow.create(caps);
+ window.setSize(width, height);
+ window.setPosition(10, 10);
+ window.setTitle(title);
+ Assert.assertNotNull(window);
+ window.setVisible(true);
+
+ return window;
+ }
+
+ @Test
+ public void testTextRendererR2T01() throws InterruptedException {
+ GLProfile glp = GLProfile.get(GLProfile.GL3bc);
+ GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(4);
+
+ GLWindow window = createWindow("r2t1msaa0", caps, 400,400);
+ TextGLListener textGLListener = new TextGLListener(Region.TWO_PASS);
+ textGLListener.setTech(-10, 10, 0f, -1000, 400);
+ textGLListener.attachTo(window);
+
+ FPSAnimator animator = new FPSAnimator(10);
+ animator.add(window);
+ animator.start();
+
+ while(!textGLListener.isPrinted()){
+ Thread.sleep(100);
+ }
+
+ textGLListener.resetPrinting();
+ textGLListener.setTech(-111, 74, 0, -380, 900);
+ Thread.sleep(100);
+ while(!textGLListener.isPrinted()){
+ Thread.sleep(100);
+ }
+
+ animator.stop();
+ destroyWindow(window);
+
+ Thread.sleep(1000);
+ }
+
+ //@Test
+ public void testTextRendererMSAA01() throws InterruptedException {
+ GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
+ GLCapabilities caps = new GLCapabilities(glp);
+ //caps.setAlphaBits(4);
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(4);
+
+ GLWindow window = createWindow("r2t0msaa1", caps, 400,0);
+ TextGLListener textGLListener = new TextGLListener(Region.SINGLE_PASS);
+ textGLListener.setTech(-10, 10, 0f, -1000, 0);
+ textGLListener.attachTo(window);
+
+ FPSAnimator animator = new FPSAnimator(10);
+ animator.add(window);
+ animator.start();
+
+ while(!textGLListener.isPrinted()){
+ Thread.sleep(100);
+ }
+
+ //textGLListener.resetPrinting();
+ //textGLListener.setTech(-111, 74, 0, -380, 0);
+ //Thread.sleep(100);
+ //while(!textGLListener.isPrinted()){
+ // Thread.sleep(100);
+ //}
+
+ animator.stop();
+ destroyWindow(window);
+
+ Thread.sleep(1000);
+ }
+
+ private class TextGLListener extends GPUTextGLListenerBase01 {
+ GLWindow glwindow;
+ public TextGLListener(int type) {
+ super(SVertex.factory(), type, false, false);
+ }
+
+ public void setTech(float xt, float yt, float angle, int zoom, int fboSize){
+ setMatrix(xt, yt, angle, zoom, fboSize);
+ }
+
+ public void init(GLAutoDrawable drawable) {
+ GL2ES2 gl = drawable.getGL().getGL2ES2();
+ super.init(drawable);
+ gl.setSwapInterval(1);
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ textRenderer.init(gl);
+ textRenderer.setAlpha(gl, 1.0f);
+ textRenderer.setColor(gl, 0.0f, 0.0f, 0.0f);
+ }
+ public void attachTo(GLWindow window) {
+ super.attachTo(window);
+ glwindow = window;
+ }
+
+ public boolean isPrinted(){
+ return !printScreen;
+ }
+
+ public void resetPrinting(){
+ printScreen = true;
+ }
+
+ public void display(GLAutoDrawable drawable) {
+ super.display(drawable);
+
+ try {
+ if(printScreen){
+ printScreen(glwindow, "./", glwindow.getTitle(), false);
+ printScreen = false;
+ }
+ } catch (GLException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}