diff options
Diffstat (limited to 'src/jogl/classes')
5 files changed, 293 insertions, 140 deletions
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()); |