diff options
author | Sven Gothel <[email protected]> | 2023-09-24 16:50:49 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2023-09-24 16:50:49 +0200 |
commit | a8de1673ca83475227fcc914fd94a9a0be1cba79 (patch) | |
tree | f180bafeb037fd66eed565236a054322fe5e229e | |
parent | 0c8700589abffe13e42f18d3c755541268d44a34 (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
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); |