aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-09-24 16:50:49 +0200
committerSven Gothel <[email protected]>2023-09-24 16:50:49 +0200
commita8de1673ca83475227fcc914fd94a9a0be1cba79 (patch)
treef180bafeb037fd66eed565236a054322fe5e229e
parent0c8700589abffe13e42f18d3c755541268d44a34 (diff)
Bug 1462 - Graph Font: Add name + codepoint to ID and Glyph mapping plus traversing through all Glyphs
See UISceneDemo03 new Button(options.renderModes, fontSymbols, " "+fontSymbols.getUTF16String("pause")+" ", buttonWidth, buttonHeight); // pause Unicode codepoint symbol is also contained in FontGlyph
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java38
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UIGraphDemoU01a.java6
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBox01.java2
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBoxGridOffset01.java2
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutGrid01.java2
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03.java14
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/AnimGroup.java4
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/Container.java2
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/Scene.java2
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/shapes/GlyphShape.java29
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/shapes/Label.java2
-rw-r--r--src/graphui/classes/jogamp/graph/ui/TreeTool.java8
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java2
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java4
-rw-r--r--src/jogl/classes/com/jogamp/graph/font/Font.java96
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java299
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java32
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/FontViewListener01.java7
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/TestFontsNEWT00.java13
19 files changed, 352 insertions, 212 deletions
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java
index d2c314764..99d491ae8 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java
@@ -37,6 +37,7 @@ import com.jogamp.common.util.IOUtil;
import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.font.Font;
+import com.jogamp.graph.font.Font.Glyph;
import com.jogamp.graph.font.FontFactory;
import com.jogamp.graph.font.FontScale;
import com.jogamp.graph.ui.Group;
@@ -127,6 +128,7 @@ public class FontView01 {
final Font fontStatus = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeMono.ttf", FontSetDemos.class.getClassLoader(), FontSetDemos.class).getInputStream(), true);
final Font fontInfo = FontFactory.get(FontFactory.UBUNTU).getDefault();
System.err.println("Status Font "+fontStatus.getFullFamilyName());
+ System.err.println("Info Font "+fontInfo.getFullFamilyName());
final GLProfile reqGLP = GLProfile.get(options.glProfileName);
System.err.println("GLProfile: "+reqGLP);
@@ -187,11 +189,11 @@ public class FontView01 {
final Shape.MouseGestureListener glyphMouseListener;
{
final Group glyphShapeBox = new Group( new BoxLayout( 1f, 1f, Alignment.FillCenter, new Margin(0.025f) ) );
- glyphShapeBox.addShape( new GlyphShape(options.renderModes, 'A', font.getGlyph( font.getGlyphID('A')), 0, 0) );
+ glyphShapeBox.addShape( new GlyphShape(options.renderModes, font.getGlyph( 'A' ), 0, 0) );
final Group glyphInfoBox = new Group( new BoxLayout( 1f, 1f, Alignment.FillCenter, new Margin(0.05f, 0.025f, 0.05f, 0.025f) ) );
final Label glyphInfo = new Label(options.renderModes, fontStatus, "Nothing there yet");
- setGlyphInfo(fontStatus, glyphInfo, 'A', font.getGlyph(font.getGlyphID('A')));
+ setGlyphInfo(fontStatus, glyphInfo, font.getGlyph( 'A' ));
glyphInfo.setColor(0.1f, 0.1f, 0.1f, 1.0f);
glyphInfoBox.addShape(glyphInfo);
@@ -220,7 +222,7 @@ public class FontView01 {
if( 1 == glyphShapeBox.getShapeCount() ) {
final GlyphShape old = (GlyphShape) glyphShapeBox.getShapes().get(0);
if( null != old ) {
- if( !doScreenshot && old.getSymbol() == g0.getSymbol() ) {
+ if( !doScreenshot && old.getGlyph().getCodepoint() == g0.getGlyph().getCodepoint() ) {
// System.err.println("GlyphShape Same: "+old);
return true; // abort - no change
}
@@ -238,7 +240,7 @@ public class FontView01 {
final GlyphShape gs = new GlyphShape( g0 ); // copy GlyphShape
gs.setColor(0, 0, 0, 1);
glyphShapeBox.addShape( gs );
- setGlyphInfo(fontStatus, glyphInfo, gs.getSymbol(), gs.getGlyph());
+ setGlyphInfo(fontStatus, glyphInfo, gs.getGlyph());
glyphInfo.validate(d.getGL().getGL2ES2()); // avoid group re-validate
// System.err.println("GlyphInfo "+glyphInfo.getBounds());
if( doScreenshot ) {
@@ -436,14 +438,12 @@ public class FontView01 {
public int scanContourGlyphs(final Font font) {
contourChars.clear();
maxNameLen = 1;
- for(int i=0; i <= Character.MAX_VALUE; ++i) {
- final int glyphID = font.getGlyphID((char)i);
- final Font.Glyph fg = font.getGlyph(glyphID);
+ font.forAllGlyphs((final Glyph fg) -> {
if( !fg.isNonContour() ) {
- contourChars.add((char)i);
+ contourChars.add( fg.getCodepoint() );
maxNameLen = Math.max(maxNameLen, fg.getName().length());
}
- }
+ });
return contourChars.size();
}
@@ -483,15 +483,13 @@ public class FontView01 {
static void addGlyphs(final GLProfile glp, final Font font, final Group sink,
final GridDim gridDim, final boolean showUnderline, final boolean showLabel,
final Font fontStatus, final Font fontInfo, final Shape.MouseGestureListener glyphMouseListener) {
- int glyphID = -1; // startGlyphID;
gridDim.nextLine = Math.min(gridDim.start + gridDim.columns, gridDim.contourChars.size()-1);
gridDim.nextPage = Math.min(gridDim.start + gridDim.elemCount, gridDim.contourChars.size()-1);
for(int idx = gridDim.start; idx < gridDim.nextPage; ++idx) {
- final char charID = gridDim.contourChars.get(idx);
- glyphID = font.getGlyphID( charID );
- final Font.Glyph fg = font.getGlyph(glyphID);
+ final char codepoint = gridDim.contourChars.get(idx);
+ final Font.Glyph fg = font.getGlyph(codepoint);
- final GlyphShape g = new GlyphShape(options.renderModes, charID, fg, 0, 0);
+ final GlyphShape g = new GlyphShape(options.renderModes, fg, 0, 0);
g.setColor(0.1f, 0.1f, 0.1f, 1);
g.setDragAndResizeable(false);
@@ -508,7 +506,7 @@ public class FontView01 {
c1.addShape(g);
c1.addMouseListener(glyphMouseListener);
if( 0 == ( idx - gridDim.start ) % gridDim.columns ) {
- addLabel(sink, fontStatus, String.format("%04x", (int)charID));
+ addLabel(sink, fontStatus, String.format("%04x", (int)codepoint));
}
if( showLabel ) {
final Group c2 = new Group( new GridLayout( 1, 0, 0, Alignment.None) ); // Alignment(Alignment.Bit.CenterHoriz) ) );
@@ -529,14 +527,14 @@ public class FontView01 {
c.addShape( new Label(options.renderModes, font, 1f, text).setColor(0, 0, 0, 1).setInteractive(false).setDragAndResizeable(false) );
}
- static void setGlyphInfo(final Font font, final Label label, final char symbol, final Font.Glyph g) {
- label.setText( getGlyphInfo(symbol, g) );
+ static void setGlyphInfo(final Font font, final Label label, final Font.Glyph g) {
+ label.setText( getGlyphInfo(g) );
if( VERBOSE_GLYPHS ) {
System.err.println( label.getText() );
}
}
- static String getGlyphInfo(final char symbol, final Font.Glyph g) {
+ static String getGlyphInfo(final Font.Glyph g) {
final OutlineShape os = g.getShape();
final int osVertices = null != os ? os.getVertexCount() : 0;
final String name_s = null != g.getName() ? g.getName() : "";
@@ -546,9 +544,9 @@ public class FontView01 {
g.getFont().getFullFamilyName(),
g.getFont().getMetrics().getAscent() - g.getFont().getMetrics().getDescent(), // font hhea table
g.getFont().getLineHeight(), // font hhea table
- (int)symbol, g.getID(), name_s,
+ (int)g.getCodepoint(), g.getID(), name_s,
bounds.getWidth(), bounds.getHeight(), box_s,
- g.getAdvance(),
+ g.getAdvanceWidth(),
g.getLeftSideBearings(),
osVertices);
}
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UIGraphDemoU01a.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UIGraphDemoU01a.java
index e495186c3..5048e911e 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UIGraphDemoU01a.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UIGraphDemoU01a.java
@@ -353,7 +353,7 @@ public class UIGraphDemoU01a {
final Font.GlyphVisitor visitor = new Font.GlyphVisitor() {
int idx = 0;
@Override
- public void visit(final char symbol, final Glyph glyph, final AffineTransform t) {
+ public void visit(final Glyph glyph, final AffineTransform t) {
System.err.println("idx["+idx+"]: "+glyph);
++idx;
}
@@ -361,11 +361,11 @@ public class UIGraphDemoU01a {
final AABBox txt_box_r2 = font.processString(visitor, null, text, new AffineTransform(), new AffineTransform());
System.err.println("XXX: txt_box_r2 "+txt_box_r2);
{
- final Glyph g = font.getGlyph( font.getGlyphID(' '));
+ final Glyph g = font.getGlyph( ' ' );
System.err.println("XXX: space "+g);
}
{
- final Glyph g = font.getGlyph( font.getGlyphID('\t'));
+ final Glyph g = font.getGlyph( '\t' );
System.err.println("XXX: tab "+g);
}
}
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBox01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBox01.java
index 396e5b07b..495739f7e 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBox01.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBox01.java
@@ -446,7 +446,7 @@ public class UILayoutBox01 {
g.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
scene.addShape(g);
{
- final float X_width = font.getGlyph(font.getGlyphID(' ')).getAdvance();
+ final float X_width = font.getGlyph( ' ' ).getAdvanceWidth();
/**
* G 23, size[total 2.1 x 1.7, cell 1.0 x 0.5]
* Padding[t 0.05, r 0.05, b 0.05, l 0.05]
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBoxGridOffset01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBoxGridOffset01.java
index dc865045a..97a1d81f0 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBoxGridOffset01.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutBoxGridOffset01.java
@@ -326,7 +326,7 @@ public class UILayoutBoxGridOffset01 {
g.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
scene.addShape(g);
{
- final float X_width = font.getGlyph(font.getGlyphID(' ')).getAdvance();
+ final float X_width = font.getGlyph( ' ' ).getAdvanceWidth();
/**
* ID 23: G 23, size[total 2.1 x 1.7, cell 1.0 x 0.5]
* Padding[t 0.05, r 0.05, b 0.05, l 0.05]
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutGrid01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutGrid01.java
index ac2663c43..82a91d53c 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutGrid01.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UILayoutGrid01.java
@@ -414,7 +414,7 @@ public class UILayoutGrid01 {
g.forAll( (shape) -> { System.err.println("Shape... "+shape); return false; });
scene.addShape(g);
{
- final float X_width = font.getGlyph(font.getGlyphID(' ')).getAdvance();
+ final float X_width = font.getGlyph( ' ' ).getAdvanceWidth();
/**
* ID 23: G 23, size[total 2.1 x 1.7, cell 1.0 x 0.5]
* Padding[t 0.05, r 0.05, b 0.05, l 0.05]
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03.java
index ef492a207..9e0ac22ff 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03.java
@@ -175,9 +175,9 @@ public class UISceneDemo03 {
//
final Font font = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeSerif.ttf",FontSetDemos.class.getClassLoader(), FontSetDemos.class).getInputStream(), true);
// final Font font = FontFactory.get(IOUtil.getResource("jogamp/graph/font/fonts/ubuntu/Ubuntu-R.ttf",FontSetDemos.class.getClassLoader(), FontSetDemos.class).getInputStream(), true);
- System.err.println("Font: " + font.getFullFamilyName());
+ System.err.println("Font FreeSerif: " + font.getFullFamilyName());
final Font fontStatus = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeMono.ttf", FontSetDemos.class.getClassLoader(), FontSetDemos.class).getInputStream(), true);
- final Font fontSymbols = FontFactory.get(FontFactory.SYMBOLS).getDefault();
+ System.err.println("Font Status: " + fontStatus.getFullFamilyName());
final Scene scene = new Scene(options.graphAASamples);
scene.setClearParams(new float[] { 1f, 1f, 1f, 1f }, GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
@@ -608,7 +608,7 @@ public class UISceneDemo03 {
buttonsRight.setLayout(new GridLayout(buttonWidth, buttonHeight, Alignment.Fill, new Gap(buttonHeight*0.50f, buttonWidth*0.10f), 7));
{
- final Button button = new Button(options.renderModes, fontSymbols, " \uE034 ", buttonWidth, buttonHeight); // pause
+ final Button button = new Button(options.renderModes, fontSymbols, " "+fontSymbols.getUTF16String("pause")+" ", buttonWidth, buttonHeight); // pause
button.setToggleable(true);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
@@ -626,7 +626,7 @@ public class UISceneDemo03 {
buttonsRight.addShape(button);
}
{
- final Button button = new Button(options.renderModes, fontSymbols, " \uE01F ", buttonWidth, buttonHeight); // next (ffwd)
+ final Button button = new Button(options.renderModes, fontSymbols, " "+fontSymbols.getUTF16String("fast_forward")+" ", buttonWidth, buttonHeight); // next (ffwd)
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
@@ -638,7 +638,7 @@ public class UISceneDemo03 {
buttonsRight.addShape(button);
}
{
- final Button button = new Button(options.renderModes, fontSymbols, " \uE042 ", buttonWidth, buttonHeight); // rotate
+ final Button button = new Button(options.renderModes, fontSymbols, " "+fontSymbols.getUTF16String("replay")+" ", buttonWidth, buttonHeight); // rotate (replay)
button.setToggleable(true);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
@@ -687,7 +687,7 @@ public class UISceneDemo03 {
buttonsRight.addShape(button);
}
{
- final Button button = new Button(options.renderModes, fontSymbols, " \uE3AF ", buttonWidth, buttonHeight); // snapshot (camera)
+ final Button button = new Button(options.renderModes, fontSymbols, " "+fontSymbols.getUTF16String("camera")+" ", buttonWidth, buttonHeight); // snapshot (camera)
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
@@ -697,7 +697,7 @@ public class UISceneDemo03 {
buttonsRight.addShape(button);
}
{
- final Button button = new Button(options.renderModes, fontSymbols, " \uE8AC ", buttonWidth, buttonHeight); // exit (power off)
+ final Button button = new Button(options.renderModes, fontSymbols, " "+fontSymbols.getUTF16String("power_settings_new")+" ", buttonWidth, buttonHeight); // exit (power_settings_new)
button.setColor(0.7f, 0.3f, 0.3f, 1.0f);
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
diff --git a/src/graphui/classes/com/jogamp/graph/ui/AnimGroup.java b/src/graphui/classes/com/jogamp/graph/ui/AnimGroup.java
index 99021b35f..b17399a01 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/AnimGroup.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/AnimGroup.java
@@ -405,9 +405,9 @@ public class AnimGroup extends Group {
{
final Font.GlyphVisitor fgv = new Font.GlyphVisitor() {
@Override
- public void visit(final char symbol, final Glyph glyph, final AffineTransform t) {
+ public void visit(final Glyph glyph, final AffineTransform t) {
if( !glyph.isNonContour() ) {
- final GlyphShape gs = new GlyphShape(renderModes, symbol, glyph, t.getTranslateX(), t.getTranslateY());
+ final GlyphShape gs = new GlyphShape(renderModes, glyph, t.getTranslateX(), t.getTranslateY());
gs.setScale(fontScale, fontScale, 1f);
gs.moveTo(gs.getOrigPos().x()*fontScale, gs.getOrigPos().y()*fontScale, gs.getOrigPos().z());
res.add( new ShapeData( gs ) );
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Container.java b/src/graphui/classes/com/jogamp/graph/ui/Container.java
index 8a5d34ea8..d4bd6c9f8 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/Container.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/Container.java
@@ -108,7 +108,7 @@ public interface Container {
boolean forAll(final PMVMatrix4f pmv, Visitor2 v);
/**
- * Traverses through the graph and apply {@link Visitor#visit(Shape, PMVMatrix4f)} for each, stop if it returns true.
+ * Traverses through the graph and apply {@link Visitor2#visit(Shape, PMVMatrix4f)} for each, stop if it returns true.
*
* Each {@link Container} level is sorted using {@code sortComp}
* @param sortComp
diff --git a/src/graphui/classes/com/jogamp/graph/ui/Scene.java b/src/graphui/classes/com/jogamp/graph/ui/Scene.java
index 2822ddc09..305b9babc 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/Scene.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/Scene.java
@@ -726,7 +726,7 @@ public final class Scene implements Container, GLEventListener {
}
/**
- * Traverses through the graph and apply {@link Visitor#visit(Shape, PMVMatrix4f)} for each, stop if it returns true.
+ * Traverses through the graph and apply {@link Visitor2#visit(Shape, PMVMatrix4f)} for each, stop if it returns true.
*
* Each {@link Container} level is sorted using {@code sortComp}
* @param sortComp
diff --git a/src/graphui/classes/com/jogamp/graph/ui/shapes/GlyphShape.java b/src/graphui/classes/com/jogamp/graph/ui/shapes/GlyphShape.java
index 55a19949a..f55bd927f 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/shapes/GlyphShape.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/shapes/GlyphShape.java
@@ -51,7 +51,6 @@ import com.jogamp.opengl.util.texture.TextureSequence;
* Scaling, if any, should be applied via {@link #setScale(float, float, float)} etc.
*/
public class GlyphShape extends GraphShape {
- private final char symbol;
private final Glyph glyph;
private final int regionVertCount;
private final int regionIdxCount;
@@ -60,15 +59,13 @@ public class GlyphShape extends GraphShape {
/**
* Creates a new GlyphShape
* @param renderModes Graph's {@link Region} render modes, see {@link GLRegion#create(GLProfile, int, TextureSequence) create(..)}.
- * @param symbol the represented character
* @param glyph the {@link Font.Glyph}
* @param x the intended unscaled X position of this Glyph, e.g. if part of a string - otherwise use zero.
* @param y the intended unscaled Y position of this Glyph, e.g. if part of a string - otherwise use zero.
* @see #processString(List, int, Font, String)
*/
- public GlyphShape(final int renderModes, final char symbol, final Glyph glyph, final float x, final float y) {
+ public GlyphShape(final int renderModes, final Glyph glyph, final float x, final float y) {
super(renderModes);
- this.symbol = symbol;
this.glyph = glyph;
this.origPos = new Vec3f(x, y, 0f);
if( glyph.isNonContour() ) {
@@ -82,35 +79,29 @@ public class GlyphShape extends GraphShape {
/**
* Creates a new GlyphShape
* @param renderModes Graph's {@link Region} render modes, see {@link GLRegion#create(GLProfile, int, TextureSequence) create(..)}.
- * @param symbol the represented character
* @param glyph the {@link Font.Glyph}
* @param pos the intended unscaled Vec3f position of this Glyph, e.g. if part of a string - otherwise use zero.
* @see #processString(List, int, Font, String)
*/
- public GlyphShape(final int renderModes, final char symbol, final Glyph glyph, final Vec3f pos) {
- this(renderModes, symbol, glyph, pos.x(), pos.y());
+ public GlyphShape(final int renderModes, final Glyph glyph, final Vec3f pos) {
+ this(renderModes, glyph, pos.x(), pos.y());
}
/**
* Creates a new GlyphShape
* @param renderModes Graph's {@link Region} render modes, see {@link GLRegion#create(GLProfile, int, TextureSequence) create(..)}.
* @param font the {@link Font} to lookup the symbol's {@link Font.Glyph}
- * @param symbol the represented character
+ * @param codepoint the represented character unicode `codepoint` symbol
* @param x the intended unscaled X position of this Glyph, e.g. if part of a string - otherwise use zero.
* @param y the intended unscaled Y position of this Glyph, e.g. if part of a string - otherwise use zero.
*/
- public GlyphShape(final int renderModes, final Font font, final char symbol, final float x, final float y) {
- this(renderModes, symbol, font.getGlyph( font.getGlyphID(symbol) ), x, y);
+ public GlyphShape(final int renderModes, final Font font, final char codepoint, final float x, final float y) {
+ this(renderModes, font.getGlyph( codepoint ), x, y);
}
/** GlyphShape copy-ctor */
public GlyphShape(final GlyphShape orig) {
- this(orig.renderModes, orig.symbol, orig.glyph, orig.origPos);
- }
-
- /** Returns the char symbol to be rendered. */
- public char getSymbol() {
- return symbol;
+ this(orig.renderModes, orig.glyph, orig.origPos);
}
/**
@@ -155,9 +146,9 @@ public class GlyphShape extends GraphShape {
{
final Font.GlyphVisitor fgv = new Font.GlyphVisitor() {
@Override
- public void visit(final char symbol, final Glyph glyph, final AffineTransform t) {
+ public void visit(final Glyph glyph, final AffineTransform t) {
if( !glyph.isNonContour() ) {
- res.add( new GlyphShape(renderModes, symbol, glyph, t.getTranslateX(), t.getTranslateY()) );
+ res.add( new GlyphShape(renderModes, glyph, t.getTranslateX(), t.getTranslateY()) );
}
}
};
@@ -188,6 +179,6 @@ public class GlyphShape extends GraphShape {
@Override
public String getSubString() {
- return super.getSubString()+", origPos " + origPos.x() + " / " + origPos.y() + ", '" + symbol + "'";
+ return super.getSubString()+", origPos " + origPos.x() + " / " + origPos.y() + ", cp 0x" + Integer.toHexString(glyph.getCodepoint());
}
}
diff --git a/src/graphui/classes/com/jogamp/graph/ui/shapes/Label.java b/src/graphui/classes/com/jogamp/graph/ui/shapes/Label.java
index b98e93174..06e82d659 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/shapes/Label.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/shapes/Label.java
@@ -202,7 +202,7 @@ public class Label extends GraphShape {
private final Font.GlyphVisitor glyphVisitor = new Font.GlyphVisitor() {
@Override
- public void visit(final char symbol, final Glyph glyph, final AffineTransform t) {
+ public void visit(final Glyph glyph, final AffineTransform t) {
if( !glyph.isNonContour() ) {
final OutlineShape shape = glyph.getShape();
shape.setSharpness(oshapeSharpness);
diff --git a/src/graphui/classes/jogamp/graph/ui/TreeTool.java b/src/graphui/classes/jogamp/graph/ui/TreeTool.java
index 9591f0e85..b26ec8417 100644
--- a/src/graphui/classes/jogamp/graph/ui/TreeTool.java
+++ b/src/graphui/classes/jogamp/graph/ui/TreeTool.java
@@ -94,10 +94,10 @@ public class TreeTool {
}
/**
- * Traverses through the graph and apply {@link Visitor2#visit(Shape, PMVMatrix)} for each, stop if it returns true.
+ * Traverses through the graph and apply {@link Visitor2#visit(Shape, PMVMatrix4f)} for each, stop if it returns true.
* @param pmv
* @param v
- * @return true to signal operation complete and to stop traversal, i.e. {@link Visitor2#visit(Shape, PMVMatrix)} returned true, otherwise false
+ * @return true to signal operation complete and to stop traversal, i.e. {@link Visitor2#visit(Shape, PMVMatrix4f)} returned true, otherwise false
*/
public static boolean forAll(final List<Shape> shapes, final PMVMatrix4f pmv, final Visitor2 v) {
for(int i=0; i<shapes.size(); ++i) {
@@ -118,13 +118,13 @@ public class TreeTool {
}
/**
- * Traverses through the graph and apply {@link Visitor#visit(Shape, PMVMatrix)} for each, stop if it returns true.
+ * Traverses through the graph and apply {@link Visitor2#visit(Shape, PMVMatrix4f)} for each, stop if it returns true.
*
* Each {@link Container} level is sorted using {@code sortComp}
* @param sortComp
* @param pmv
* @param v
- * @return true to signal operation complete and to stop traversal, i.e. {@link Visitor2#visit(Shape, PMVMatrix)} returned true, otherwise false
+ * @return true to signal operation complete and to stop traversal, i.e. {@link Visitor2#visit(Shape, PMVMatrix4f)} returned true, otherwise false
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static boolean forSortedAll(final Comparator<Shape> sortComp, final List<Shape> shapes, final PMVMatrix4f pmv, final Visitor2 v) {
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java
index 47f8e1b2a..2cd40c6e4 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java
@@ -186,7 +186,7 @@ public abstract class GLRegion extends Region {
final int[] vertIndexCount = { 0, 0 };
final Font.GlyphVisitor2 visitor = new Font.GlyphVisitor2() {
@Override
- public final void visit(final char symbol, final Font.Glyph glyph) {
+ public final void visit(final Font.Glyph glyph) {
if( !glyph.isNonContour() ) {
Region.countOutlineShape(glyph.getShape(), vertIndexCount);
}
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java
index 782615c3e..e6e4f3e0c 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java
@@ -144,7 +144,7 @@ public class TextRegionUtil {
final AffineTransform temp1, final AffineTransform temp2) {
final Font.GlyphVisitor visitor = new Font.GlyphVisitor() {
@Override
- public void visit(final char symbol, final Glyph glyph, final AffineTransform t) {
+ public void visit(final Glyph glyph, final AffineTransform t) {
if( !glyph.isNonContour() ) {
region.addOutlineShape(glyph.getShape(), t, rgbaColor);
}
@@ -173,7 +173,7 @@ public class TextRegionUtil {
public static int[] countStringRegion(final Font font, final CharSequence str, final int[/*2*/] vertIndexCount) {
final Font.GlyphVisitor2 visitor = new Font.GlyphVisitor2() {
@Override
- public final void visit(final char symbol, final Font.Glyph glyph) {
+ public final void visit(final Font.Glyph glyph) {
if( !glyph.isNonContour() ) {
Region.countOutlineShape(glyph.getShape(), vertIndexCount);
}
diff --git a/src/jogl/classes/com/jogamp/graph/font/Font.java b/src/jogl/classes/com/jogamp/graph/font/Font.java
index 997eacbb8..c8682a4e5 100644
--- a/src/jogl/classes/com/jogamp/graph/font/Font.java
+++ b/src/jogl/classes/com/jogamp/graph/font/Font.java
@@ -240,11 +240,11 @@ public interface Font {
*/
AABBox getBounds();
- /** Return advance in font units, sourced from `hmtx` table. */
- int getAdvanceFU();
+ /** Returns advance in font units, sourced from `hmtx` table. */
+ int getAdvanceWidthFU();
- /** Return advance in font em-size [0..1], sourced from `hmtx` table. */
- float getAdvance();
+ /** Returns advance in font em-size [0..1], sourced from `hmtx` table. */
+ float getAdvanceWidth();
/** Return leftSideBearings in font units, sourced from `hmtx` table. */
int getLeftSideBearingsFU();
@@ -258,7 +258,7 @@ public interface Font {
/** True if kerning values are perpendicular to text flow, otherwise along with flow */
boolean isKerningCrossstream();
- /** Return the number of kerning values stored for this glyph, associated to a right hand glyph. */
+ /** Returns the number of kerning values stored for this glyph, associated to a right hand glyph. */
int getKerningPairCount();
/**
@@ -295,25 +295,47 @@ public interface Font {
public static interface GlyphVisitor {
/**
* Visiting the given {@link Font.Glyph} having an {@link OutlineShape} with it's corresponding {@link AffineTransform}.
- * @param symbol the character symbol matching the given glyph
* @param glyph {@link Font.Glyph} which contains an {@link OutlineShape} via {@link Font.Glyph#getShape()}.
* @param t may be used immediately as is, otherwise a copy shall be made if stored.
*/
- public void visit(final char symbol, final Glyph glyph, final AffineTransform t);
+ public void visit(final Glyph glyph, final AffineTransform t);
}
/**
- * Constrained {@link Font.Glyph} visitor w/o {@link AffineTransform}.
+ * General purpose {@link Font.Glyph} visitor w/o {@link AffineTransform}.
*/
public static interface GlyphVisitor2 {
/**
- * Visiting the given {@link Font.Glyph} having an {@link OutlineShape}.
- * @param symbol the character symbol matching the given glyph
- * @param glyph {@link Font.Glyph} which contains an {@link OutlineShape} via {@link Font.Glyph#getShape()}.
+ * Visiting the given {@link Font.Glyph}
+ * @param glyph {@link Font.Glyph} which may contain an {@link OutlineShape} via {@link Font.Glyph#getShape()}.
*/
- public void visit(final char symbol, final Glyph glyph);
+ public void visit(final Glyph glyph);
}
+ /**
+ * General purpose (unicode) `codepoint` symbol and {@link Font.Glyph} ID visitor without enforcing {@link Glyph} caching.
+ */
+ public static interface CodepointIDVisitor {
+ /**
+ * Visiting the given (unicode) `codepoint` symbol and {@link Font.Glyph} ID.
+ * @param codepoint (unicode) `codepoint` symbol
+ * @param glyph_id {@link Font.Glyph} ID
+ */
+ public void visit(final char codepoint, final int glyph_id);
+ }
+
+ /**
+ * Returns UTF-16 representation of the specified (unicode) `codepoint` symbol like {@link Character#toChars(int)} or {@link Character#toString()}.
+ * <p>
+ * The returned string can be inserted in any text.
+ * </p>
+ * @param codepoint the (unicode) `codepoint` symbol
+ * @return the Java {@link String} conforming result
+ */
+ public static String getUTF16String(final char codepoint) {
+ return Character.toString(codepoint);
+ // return new String(Character.toChars(codepoint));
+ }
String getName(final int nameIndex);
@@ -343,32 +365,64 @@ public interface Font {
boolean equals(final Object o);
/**
- * Return advance-width of given glyphID in font-units, sourced from `hmtx` table.
+ * Returns advance-width of given glyphID in font-units, sourced from `hmtx` table - same as {@link Glyph#getAdvanceWidthFU()}.
* @param glyphID
*/
int getAdvanceWidthFU(final int glyphID);
/**
- * Return advance-width of given glyphID in font em-size [0..1], sourced from `hmtx` table.
+ * Returns advance-width of given glyphID in font em-size [0..1], sourced from `hmtx` table - same as {@link Glyph#getAdvanceWidth()}.
* @param glyphID
*/
float getAdvanceWidth(final int glyphID);
Metrics getMetrics();
- /** Return the {@link Glyph} ID mapped to given `symbol`, usually UTF16 unicode. Returned ID can be used to retrieve the {@link Glyph} via {@link #getGlyph(int)}. */
- int getGlyphID(final char symbol);
-
- /** Return number of {@link Glyph} IDs available, i.e. retrievable via {@link #getGlyph(int)} [0..count). */
+ /** Returns number of {@link Glyph} IDs available, i.e. retrievable via {@link #getGlyph(int)} [0..count). */
int getGlyphCount();
- /** Return the {@link Glyph} using given ID, see {@link #getGlyphCount()}. */
+ /** Returns the {@link Glyph} (unicode) `codepoint` symbol mapped to given {@link Glyph} `name`. */
+ char getGlyphCodepoint(final String name);
+
+ /**
+ * Returns UTF-16 representation of the specified {@link Glyph} `name` using {@link #getGlyphCodepoint(String)} and {@link #getUTF16String(char)}.
+ * <p>
+ * The returned string can be inserted in any text.
+ * </p>
+ * @param codepoint the (unicode) `codepoint` symbol
+ * @return the Java {@link String} conforming result
+ */
+ String getUTF16String(final String name);
+
+ /** Returns the {@link Glyph} ID mapped to given UTF16 (unicode) `codepoint` symbol. */
+ int getGlyphID(final char codepoint);
+
+ /** Returns the {@link Glyph} mapped to given `name`. */
+ Glyph getGlyph(final String name);
+
+ /** Returns the {@link Glyph} mapped to given (unicode) `codepoint` symbol. */
+ Glyph getGlyph(final char codepoint);
+
+ /** Returns the {@link Glyph} using given ID. */
Glyph getGlyph(final int glyph_id);
- int getNumGlyphs();
+ /**
+ * Visit all (unicode) `codepoint` symbol and {@link Glyph} ID tuple of this font.
+ * @param visitor handling each (unicode) `codepoint` symbol and {@link Glyph} ID tuple.
+ */
+ void forAllCodepoints(final Font.CodepointIDVisitor visitor);
+
+ /**
+ * Visit all {@link Glyph}s of this font.
+ * <p>
+ * Warning: All {@link Glyph}s will be cached.
+ * </p>
+ * @param visitor handling each {@link Glyph}
+ */
+ void forAllGlyphs(final Font.GlyphVisitor2 visitor);
/**
- * Return line height, baseline-to-baseline in font-units, composed from `hhea' table entries.
+ * Returns line height, baseline-to-baseline in font-units, composed from `hhea' table entries.
* <pre>
* return ascent - descent + linegap;
* </pre>
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
index a8651389c..e8c6a4ed8 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
@@ -27,6 +27,9 @@
*/
package jogamp.graph.font.typecast;
+import java.util.HashMap;
+import java.util.Map;
+
import com.jogamp.common.util.IntObjectHashMap;
import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.font.Font;
@@ -52,14 +55,24 @@ import jogamp.opengl.Debug;
class TypecastFont implements Font {
private static final boolean DEBUG = Debug.debug("graph.font.Font");
+ private static final char UNDEF_SYMBOL = 0xffff;
+ static class SymAndID {
+ public final char codepoint;
+ public final int id;
+ public final String name;
+ public TypecastGlyph glyph;
+ SymAndID(final char codepoint, final int id, final String name) { this.codepoint = codepoint; this.id = id; this.name = name; this.glyph = null; }
+ }
+ private static final SymAndID UNDEF_VALUE = new SymAndID(UNDEF_SYMBOL, Glyph.ID_UNKNOWN, TypecastGlyph.dot_undef_NAME);
// private final OTFontCollection fontset;
/* pp */ final TTFont font;
private final CmapFormat cmapFormat;
private final int cmapentries;
private final IntObjectHashMap idToGlyph;
+ private final IntObjectHashMap cpToGlyph;
+ private final Map<String, SymAndID> nameToGlyph;
private final TypecastHMetrics metrics;
- // FIXME: Add cache size to limit memory usage ??
private static final boolean forceAscii = false; // FIXME ??? (ASCII/Macintosh cmap format)
@@ -92,27 +105,58 @@ class TypecastFont implements Font {
throw new RuntimeException("Cannot find a suitable cmap table");
}
cmapFormat = cmapFmt;
- if(DEBUG) {
- System.err.println("Selected CmapFormat: platform " + platform + ", encoding "+encoding + ": "+cmapFormat);
- }
-
{
int _cmapentries = 0;
- for (int i = 0; i < cmapFormat.getRangeCount(); ++i) {
+ for(int i=0; i<cmapFormat.getRangeCount(); ++i) {
final CmapFormat.Range range = cmapFormat.getRange(i);
_cmapentries += range.getEndCode() - range.getStartCode() + 1; // end included
}
cmapentries = _cmapentries;
+ idToGlyph = new IntObjectHashMap(cmapentries + cmapentries/4);
+ idToGlyph.setKeyNotFoundValue(UNDEF_VALUE);
+ cpToGlyph = new IntObjectHashMap(cmapentries + cmapentries/4);
+ cpToGlyph.setKeyNotFoundValue(UNDEF_VALUE);
+ nameToGlyph = new HashMap<String, SymAndID>(cmapentries + cmapentries/4);
+ final PostTable post = font.getPostTable();
+ for(int i=0; i<cmapFormat.getRangeCount(); ++i) {
+ final CmapFormat.Range range = cmapFormat.getRange(i);
+ for(int codepoint = range.getStartCode(); codepoint <= range.getEndCode(); ++codepoint) {
+ final int id = cmapFormat.mapCharCode(codepoint);
+ if( 0 < id ) {
+ boolean mapped = false;
+ if( null != post ) {
+ final String name = post.getGlyphName(id);
+ if( null != name && name.length() > 0 ) {
+ final SymAndID value = new SymAndID((char)codepoint, id, name);
+ nameToGlyph.put(name, value);
+ idToGlyph.put(id, value);
+ cpToGlyph.put(codepoint, value);
+ mapped = true;
+ }
+ }
+ if( !mapped ) {
+ final SymAndID value = new SymAndID((char)codepoint, id, "");
+ idToGlyph.put(id, value);
+ cpToGlyph.put(codepoint, value);
+ }
+ }
+ }
+ }
+ if( DEBUG ) {
+ System.err.println("Selected CmapFormat: platform " + platform + ", encoding "+encoding + ": "+cmapFormat.getClass().getSimpleName());
+ System.err.println("Map Result");
+ System.err.println("Map: idToGlyph: "+idToGlyph.size());
+ System.err.println("Map: nameToGlyph: "+nameToGlyph.size());
+ System.err.println("CMap entries: "+cmapentries);
+ System.err.println("Font glyph-count "+this.getGlyphCount()+", num-glyphs "+font.getNumGlyphs());
+ }
}
- idToGlyph = new IntObjectHashMap(cmapentries + cmapentries/4);
metrics = new TypecastHMetrics(this);
+ getGlyphImpl(UNDEF_VALUE);
if(DEBUG) {
final int max_id = 36; // "A"
System.err.println("font direction hint: "+font.getHeadTable().getFontDirectionHint());
- System.err.println("num glyphs: "+font.getNumGlyphs());
- System.err.println("num cmap entries: "+cmapentries);
- System.err.println("num cmap ranges: "+cmapFormat.getRangeCount());
for (int i = 0; i < cmapFormat.getRangeCount(); ++i) {
final CmapFormat.Range range = cmapFormat.getRange(i);
@@ -177,12 +221,31 @@ class TypecastFont implements Font {
}
@Override
- public int getGlyphID(final char symbol) {
- final int glyphID = cmapFormat.mapCharCode(symbol);
- if( 0 < glyphID ) {
- return glyphID;
+ public int getGlyphCount() { return font.getGlyphCount(); }
+
+ @Override
+ public char getGlyphCodepoint(final String name) {
+ final SymAndID value = nameToGlyph.get(name);
+ if( null != value ) {
+ return value.codepoint;
+ } else {
+ return UNDEF_VALUE.codepoint;
+ }
+ }
+
+ @Override
+ public String getUTF16String(final String name) {
+ return Font.getUTF16String( getGlyphCodepoint( name ) );
+ }
+
+ @Override
+ public int getGlyphID(final char codepoint) {
+ final SymAndID value = (SymAndID) cpToGlyph.get(codepoint);
+ if( null != value ) {
+ return value.id;
+ } else {
+ return UNDEF_VALUE.id;
}
- return Glyph.ID_UNKNOWN;
}
/** pp **/ PostTable getPostTable() {
@@ -190,73 +253,112 @@ class TypecastFont implements Font {
}
@Override
- public int getGlyphCount() { return font.getGlyphCount(); }
+ public synchronized Glyph getGlyph(final String name) {
+ final SymAndID value = nameToGlyph.get(name);
+ if( null != value ) {
+ return getGlyphImpl(value);
+ } else {
+ return UNDEF_VALUE.glyph;
+ }
+ }
+
+ @Override
+ public synchronized Glyph getGlyph(final char codepoint) {
+ final SymAndID value = (SymAndID) cpToGlyph.get(codepoint);
+ if( null != value ) {
+ return getGlyphImpl(value);
+ } else {
+ return UNDEF_VALUE.glyph;
+ }
+ }
@Override
- public Glyph getGlyph(final int glyph_id) {
- TypecastGlyph result = (TypecastGlyph) idToGlyph.get(glyph_id);
- if (null == result) {
- final jogamp.graph.font.typecast.ot.Glyph glyph = font.getGlyph(glyph_id);
- final String glyph_name;
- {
- final PostTable post = font.getPostTable();
- glyph_name = null != post ? post.getGlyphName(glyph_id) : "";
+ public synchronized Glyph getGlyph(final int glyph_id) {
+ final SymAndID value = (SymAndID) idToGlyph.get(glyph_id);
+ if( null != value ) {
+ return getGlyphImpl(value);
+ } else {
+ return UNDEF_VALUE.glyph;
+ }
+ }
+
+ @Override
+ public void forAllCodepoints(final Font.CodepointIDVisitor visitor) {
+ for(int i=0; i<cmapFormat.getRangeCount(); ++i) {
+ final CmapFormat.Range range = cmapFormat.getRange(i);
+ for(int codepoint = range.getStartCode(); codepoint <= range.getEndCode(); ++codepoint) {
+ visitor.visit( (char)codepoint, getGlyphID((char)codepoint) );
}
- final boolean isUndefined = Glyph.ID_UNKNOWN == glyph_id || TypecastGlyph.isUndefName(glyph_name);
- final int glyph_height = metrics.getAscentFU() - metrics.getDescentFU();
- final int glyph_advance;
- final int glyph_leftsidebearings;
- final boolean isWhitespace;
- final AABBox glyph_bbox;
- final OutlineShape shape;
- final int mode;
- if( null != glyph ) {
- glyph_advance = glyph.getAdvanceWidth();
- glyph_leftsidebearings = glyph.getLeftSideBearing();
- final AABBox sb = glyph.getBBox();
- final OutlineShape os = TypecastRenderer.buildShape(metrics.getUnitsPerEM(), glyph);
- if( 0 < os.getVertexCount() ) {
- // Case 1: Either valid contour glyph, undefined or a whitespace (Case 2 with zero-area shape)
- isWhitespace = isUndefined ? false : os.getBounds().hasZero2DArea();
- glyph_bbox = sb;
- shape = ( !isWhitespace && !isUndefined ) || Glyph.ID_UNKNOWN == glyph_id ? os : null;
- mode = 1;
- } else {
- // Case 2: Non-contour glyph -> whitespace or undefined
- isWhitespace = !isUndefined;
- glyph_bbox = new AABBox(0f,0f,0f, glyph_advance, glyph_height, 0f);
- shape = Glyph.ID_UNKNOWN == glyph_id ? TypecastRenderer.buildEmptyShape(metrics.getUnitsPerEM(), glyph_bbox) : null;
- mode = 2;
- }
+ }
+ }
+ @Override
+ public void forAllGlyphs(final Font.GlyphVisitor2 visitor) {
+ for(int i=0; i<cmapFormat.getRangeCount(); ++i) {
+ final CmapFormat.Range range = cmapFormat.getRange(i);
+ for(int codepoint = range.getStartCode(); codepoint <= range.getEndCode(); ++codepoint) {
+ visitor.visit( getGlyph( (char)codepoint ) );
+ }
+ }
+ }
+
+ private Glyph getGlyphImpl(final SymAndID key) {
+ if( null != key.glyph ) {
+ return key.glyph;
+ }
+ final jogamp.graph.font.typecast.ot.Glyph glyph = font.getGlyph(key.id);
+ final boolean isUndefined = Glyph.ID_UNKNOWN == key.id || TypecastGlyph.isUndefName(key.name);
+ final int glyph_height = metrics.getAscentFU() - metrics.getDescentFU();
+ final int glyph_advance;
+ final int glyph_leftsidebearings;
+ final boolean isWhitespace;
+ final AABBox glyph_bbox;
+ final OutlineShape shape;
+ final int mode;
+ if( null != glyph ) {
+ glyph_advance = glyph.getAdvanceWidth();
+ glyph_leftsidebearings = glyph.getLeftSideBearing();
+ final AABBox sb = glyph.getBBox();
+ final OutlineShape os = TypecastRenderer.buildShape(metrics.getUnitsPerEM(), glyph);
+ if( 0 < os.getVertexCount() ) {
+ // Case 1: Either valid contour glyph, undefined or a whitespace (Case 2 with zero-area shape)
+ isWhitespace = isUndefined ? false : os.getBounds().hasZero2DArea();
+ glyph_bbox = sb;
+ shape = ( !isWhitespace && !isUndefined ) || Glyph.ID_UNKNOWN == key.id ? os : null;
+ mode = 1;
} else {
- // Case 3: Non-contour glyph -> whitespace or undefined
- glyph_advance = getAdvanceWidthFU(glyph_id);
- glyph_leftsidebearings = 0;
+ // Case 2: Non-contour glyph -> whitespace or undefined
isWhitespace = !isUndefined;
glyph_bbox = new AABBox(0f,0f,0f, glyph_advance, glyph_height, 0f);
- shape = Glyph.ID_UNKNOWN == glyph_id ? TypecastRenderer.buildEmptyShape(metrics.getUnitsPerEM(), glyph_bbox) : null;
- mode = 3;
- }
- KernSubtable kernSub = null;
- {
- final KernTable kern = font.getKernTable();
- if (kern != null ) {
- kernSub = kern.getSubtable0();
- }
+ shape = Glyph.ID_UNKNOWN == key.id ? TypecastRenderer.buildEmptyShape(metrics.getUnitsPerEM(), glyph_bbox) : null;
+ mode = 2;
}
- result = new TypecastGlyph(this, glyph_id, glyph_name, glyph_bbox, glyph_advance, glyph_leftsidebearings, kernSub, shape,
- isUndefined, isWhitespace);
- if( DEBUG || TypecastRenderer.DEBUG ) {
- System.err.println("New glyph: " + glyph_id + "/'"+glyph_name+"', shape " + (null != shape)+", mode "+mode);
- System.err.println(" tc_glyph "+glyph);
- System.err.println(" glyph "+result);
- }
- if( null != glyph ) {
- glyph.clearPointData();
+ } else {
+ // Case 3: Non-contour glyph -> whitespace or undefined
+ glyph_advance = getAdvanceWidthFU(key.id);
+ glyph_leftsidebearings = 0;
+ isWhitespace = !isUndefined;
+ glyph_bbox = new AABBox(0f,0f,0f, glyph_advance, glyph_height, 0f);
+ shape = Glyph.ID_UNKNOWN == key.id ? TypecastRenderer.buildEmptyShape(metrics.getUnitsPerEM(), glyph_bbox) : null;
+ mode = 3;
+ }
+ KernSubtable kernSub = null;
+ {
+ final KernTable kern = font.getKernTable();
+ if (kern != null ) {
+ kernSub = kern.getSubtable0();
}
-
- idToGlyph.put(glyph_id, result);
}
+ final TypecastGlyph result = new TypecastGlyph(this, key.codepoint, key.id, key.name, glyph_bbox, glyph_advance, glyph_leftsidebearings, kernSub,
+ shape, isUndefined, isWhitespace);
+ if( DEBUG || TypecastRenderer.DEBUG ) {
+ System.err.println("New glyph: id 0x" + Integer.toHexString(key.id) + "/'"+key.name+"', sym 0x"+Integer.toHexString(key.codepoint)+", shape " + (null != shape)+", mode "+mode);
+ System.err.println(" tc_glyph "+glyph);
+ System.err.println(" glyph "+result);
+ }
+ if( null != glyph ) {
+ glyph.clearPointData();
+ }
+ key.glyph = result;
return result;
}
@@ -336,34 +438,33 @@ class TypecastFont implements Font {
final AABBox temp_box = new AABBox();
for(int i=0; i< charCount; i++) {
- final char character = string.charAt(i);
- if( '\n' == character ) {
+ final char codepoint = string.charAt(i);
+ if( '\n' == codepoint ) {
y -= lineHeight;
advanceTotal = 0;
left_glyph = null;
} else {
// reset transform
temp1.setToIdentity();
- final int glyph_id = getGlyphID(character);
- final Font.Glyph glyph = getGlyph(glyph_id);
+ final Font.Glyph glyph = getGlyph( codepoint );
if( glyph.isUndefined() ) {
// break kerning, drop undefined
- advanceTotal += glyph.getAdvanceFU();
+ advanceTotal += glyph.getAdvanceWidthFU();
left_glyph = null;
} else if( glyph.isWhitespace() ) {
// break kerning, but include its bounding box space
left_glyph = null;
temp1.translate(advanceTotal, y, temp2);
res.resize(temp1.transform(glyph.getBoundsFU(), temp_box));
- advanceTotal += glyph.getAdvanceFU();
+ advanceTotal += glyph.getAdvanceWidthFU();
} else {
// regular contour
if( null != left_glyph ) {
- advanceTotal += left_glyph.getKerningFU(glyph_id);
+ advanceTotal += left_glyph.getKerningFU( glyph.getID() );
}
temp1.translate(advanceTotal, y, temp2);
res.resize(temp1.transform(glyph.getBoundsFU(), temp_box));
- advanceTotal += glyph.getAdvanceFU();
+ advanceTotal += glyph.getAdvanceWidthFU();
left_glyph = glyph;
}
}
@@ -383,7 +484,7 @@ class TypecastFont implements Font {
}
final Font.GlyphVisitor visitor = new Font.GlyphVisitor() {
@Override
- public final void visit(final char symbol, final Font.Glyph shape, final AffineTransform t) {
+ public final void visit(final Font.Glyph shape, final AffineTransform t) {
// nop
} };
return processString(visitor, transform, string, temp1, temp2);
@@ -414,8 +515,8 @@ class TypecastFont implements Font {
final AABBox temp_box = new AABBox();
for(int i=0; i< charCount; i++) {
- final char character = string.charAt(i);
- if( '\n' == character ) {
+ final char codepoint = string.charAt(i);
+ if( '\n' == codepoint ) {
y -= lineHeight;
advanceTotal = 0;
left_glyph = null;
@@ -426,29 +527,27 @@ class TypecastFont implements Font {
} else {
temp1.setToIdentity();
}
- final int glyph_id = getGlyphID(character);
-
- final Font.Glyph glyph = getGlyph(glyph_id);
+ final Font.Glyph glyph = getGlyph( codepoint );
if( glyph.isUndefined() ) {
// break kerning, drop undefined
- advanceTotal += glyph.getAdvance();
+ advanceTotal += glyph.getAdvanceWidth();
left_glyph = null;
} else if( glyph.isWhitespace() ) {
// break kerning, but include its bounding box space and visit the visitor
left_glyph = null;
temp1.translate(advanceTotal, y, temp2);
res.resize(temp1.transform(glyph.getBounds(), temp_box));
- visitor.visit(character, glyph, temp1);
- advanceTotal += glyph.getAdvance();
+ visitor.visit(glyph, temp1);
+ advanceTotal += glyph.getAdvanceWidth();
} else {
// regular contour
if( null != left_glyph ) {
- advanceTotal += left_glyph.getKerning(glyph_id);
+ advanceTotal += left_glyph.getKerning( glyph.getID() );
}
temp1.translate(advanceTotal, y, temp2);
res.resize(temp1.transform(glyph.getShape().getBounds(), temp_box));
- visitor.visit(character, glyph, temp1);
- advanceTotal += glyph.getAdvance();
+ visitor.visit(glyph, temp1);
+ advanceTotal += glyph.getAdvanceWidth();
left_glyph = glyph;
}
}
@@ -464,22 +563,14 @@ class TypecastFont implements Font {
final int charCount = string.length();
for(int i=0; i< charCount; i++) {
- final char character = string.charAt(i);
- if( '\n' != character ) {
- final Glyph glyph = getGlyph(getGlyphID(character));
- if( null != glyph.getShape() ) { // also covers 'space' and all non-contour symbols
- visitor.visit(character, glyph);
- }
+ final char codepoint = string.charAt(i);
+ if( '\n' != codepoint ) {
+ visitor.visit( getGlyph( codepoint ) );
}
}
}
@Override
- final public int getNumGlyphs() {
- return font.getNumGlyphs();
- }
-
- @Override
public boolean isPrintableChar( final char c ) {
return FontFactory.isPrintableChar(c);
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
index fa8271088..d49fb7393 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
@@ -39,7 +39,7 @@ public final class TypecastGlyph implements Font.Glyph {
public static final short INVALID_ID = (short)((1 << 16) - 1);
public static final short MAX_ID = (short)((1 << 16) - 2);
- private static final String dot_undef_NAME = ".notdef";
+ /* pp */ static final String dot_undef_NAME = ".notdef";
private static final String NULL_NAME = "NULL";
private static final String null_NAME = "null";
private static final String dot_null_NAME = ".null";
@@ -83,6 +83,7 @@ public final class TypecastGlyph implements Font.Glyph {
return dst;
}
+ private final char codepoint;
private final int id;
private final String name;
private final boolean isUndefined;
@@ -101,17 +102,19 @@ public final class TypecastGlyph implements Font.Glyph {
/**
*
* @param font
- * @param name from `post` table
+ * @param codepoint TODO
* @param id
+ * @param name from `post` table
* @param bbox in font-units
* @param advance from hmtx in font-units
* @param leftSideBearings from hmtx in font-units
* @param shape
*/
- protected TypecastGlyph(final TypecastFont font, final int id, final String name,
- final AABBox bbox, final int advance, final int leftSideBearings,
- final KernSubtable kernSub, final OutlineShape shape,
- final boolean isUndefined, final boolean isWhiteSpace) {
+ protected TypecastGlyph(final TypecastFont font, final char codepoint, final int id,
+ final String name, final AABBox bbox, final int advance,
+ final int leftSideBearings, final KernSubtable kernSub,
+ final OutlineShape shape, final boolean isUndefined, final boolean isWhiteSpace) {
+ this.codepoint = codepoint;
this.id = id;
this.name = name;
this.isUndefined = isUndefined;
@@ -155,6 +158,9 @@ public final class TypecastGlyph implements Font.Glyph {
}
@Override
+ public char getCodepoint() { return codepoint; }
+
+ @Override
public final int getID() { return id; }
@Override
@@ -187,10 +193,10 @@ public final class TypecastGlyph implements Font.Glyph {
}
@Override
- public final int getAdvanceFU() { return advance; }
+ public final int getAdvanceWidthFU() { return advance; }
@Override
- public float getAdvance() { return font.getMetrics().getScale( advance ); }
+ public float getAdvanceWidth() { return font.getMetrics().getScale( advance ); }
@Override
public final int getLeftSideBearingsFU() { return leftSideBearings; }
@@ -267,9 +273,10 @@ public final class TypecastGlyph implements Font.Glyph {
}
final String name_s = null != name ? name : "";
final String shape_s = null != shape ? "shape "+shape.getVertexCount()+"v" : "shape null";
- sb.append("Glyph[id ").append(id).append(" '").append(name_s).append("', ").append(contour_s)
+ sb.append("Glyph[id 0x").append(Integer.toHexString(id)).append(", cp 0x").append(Integer.toHexString(codepoint))
+ .append(", name '").append(name_s).append("', ").append(contour_s)
.append(", ").append(shape_s)
- .append(", advance ").append(getAdvanceFU())
+ .append(", advance ").append(getAdvanceWidthFU())
.append(", leftSideBearings ").append(getLeftSideBearingsFU())
.append(", kerning[size ").append(kerning.length).append(", horiz ").append(this.isKerningHorizontal()).append(", cross ").append(this.isKerningCrossstream()).append("]")
.append("]");
@@ -290,9 +297,10 @@ public final class TypecastGlyph implements Font.Glyph {
}
final String name_s = null != name ? name : "";
final String shape_s = null != shape ? "shape "+shape.getVertexCount()+"v" : "shape null";
- sb.append("Glyph id ").append(id).append(" '").append(name_s).append("', ").append(contour_s)
+ sb.append("Glyph[id 0x").append(Integer.toHexString(id)).append(", cp 0x").append(Integer.toHexString(codepoint))
+ .append(" name '").append(name_s).append("', ").append(contour_s)
.append(", shape ").append(shape_s)
- .append(", advance ").append(getAdvanceFU())
+ .append(", advance ").append(getAdvanceWidthFU())
.append(", leftSideBearings ").append(getLeftSideBearingsFU())
.append(", ").append(getBoundsFU());
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/FontViewListener01.java b/src/test/com/jogamp/opengl/test/junit/graph/FontViewListener01.java
index e5a5ad24e..6c3bd692a 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/FontViewListener01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/FontViewListener01.java
@@ -138,13 +138,12 @@ public class FontViewListener01 implements GLEventListener {
scene.addShape(grid);
for(int idx=0; idx<Character.MAX_VALUE && grid.getShapeCount() < cellCount ; ++idx) {
- final char symbol = (char)(startCharSymbol+idx);
- final int glyphID = font.getGlyphID(symbol);
- final Font.Glyph glyph = font.getGlyph(glyphID);
+ final char codepoint = (char)(startCharSymbol+idx);
+ final Font.Glyph glyph = font.getGlyph( codepoint );
if( glyph.isNonContour() ) {
continue;
}
- final GlyphShape glyphShape = new GlyphShape(renderModes, symbol, glyph, 0, 0);
+ final GlyphShape glyphShape = new GlyphShape(renderModes, glyph, 0, 0);
glyphShape.setColor(0.1f, 0.1f, 0.1f, 1);
glyphShape.setDragAndResizeable(false);
glyphShape.onClicked( new Shape.Listener() {
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestFontsNEWT00.java b/src/test/com/jogamp/opengl/test/junit/graph/TestFontsNEWT00.java
index 6516b2b1b..6050de8b5 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/TestFontsNEWT00.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TestFontsNEWT00.java
@@ -81,20 +81,19 @@ public class TestFontsNEWT00 extends UITestCase {
}
}
void testFontGlyph01(final Font font, final char c, final float pixelSize) {
- final int glyphID = font.getGlyphID(c);
- final int s0 = font.getAdvanceWidthFU(glyphID);
- final Font.Glyph glyph = font.getGlyph(glyphID);
- final int s1 = glyph.getAdvanceFU();
+ final Font.Glyph glyph = font.getGlyph( c );
+ final int s0 = font.getAdvanceWidthFU( glyph.getID() );
+ final int s1 = glyph.getAdvanceWidthFU();
final int unitsPerEM = font.getMetrics().getUnitsPerEM();
- final float s0_em = font.getAdvanceWidth(glyphID);
- final float s1_em = glyph.getAdvance();
+ final float s0_em = font.getAdvanceWidth( glyph.getID() );
+ final float s1_em = glyph.getAdvanceWidth();
final float s0_px = s0_em * pixelSize;
final float s1_px = s1_em * pixelSize;
- System.err.println(" Char '"+c+"', id "+glyphID+", font-px "+pixelSize+", unitsPerEM "+unitsPerEM+":");
+ System.err.println(" Char '"+c+"', id "+glyph.getID()+", font-px "+pixelSize+", unitsPerEM "+unitsPerEM+":");
System.err.println(" "+glyph);
System.err.println(" Advance");
System.err.println(" funits "+s0+", "+s1);