aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/jogamp/graph/font
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-08-28 22:57:53 +0200
committerSven Gothel <[email protected]>2023-08-28 22:57:53 +0200
commit920e529516bb264f04138ed1caca80d4925e3773 (patch)
tree498bce9425f880cab2cd36b4251eaa4e231e912c /src/jogl/classes/jogamp/graph/font
parent733cc5272cfed10fa07b707e29fd756f44581508 (diff)
Graph Font + Glyph: More robust detetection and API definition of non-contour/whitespace Glyphs (detect and allow to skip 'em)
We also drop shapes for both, but for id 0 (unknown).
Diffstat (limited to 'src/jogl/classes/jogamp/graph/font')
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java99
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java65
2 files changed, 109 insertions, 55 deletions
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
index ce490bdf0..8bc832633 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
@@ -48,9 +48,10 @@ import jogamp.graph.font.typecast.ot.table.KernSubtableFormat0;
import jogamp.graph.font.typecast.ot.table.KernTable;
import jogamp.graph.font.typecast.ot.table.KerningPair;
import jogamp.graph.font.typecast.ot.table.PostTable;
+import jogamp.opengl.Debug;
class TypecastFont implements Font {
- static final boolean DEBUG = false;
+ private static final boolean DEBUG = Debug.debug("graph.font.Font");
// private final OTFontCollection fontset;
/* pp */ final TTFont font;
@@ -203,34 +204,36 @@ class TypecastFont implements Font {
} else {
glyph_name = "";
}
+ final boolean isUndefined = Glyph.ID_UNKNOWN == glyph_id || null == glyph || 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 boolean isWhiteSpace;
if( null != glyph ) {
glyph_advance = glyph.getAdvanceWidth();
glyph_leftsidebearings = glyph.getLeftSideBearing();
final AABBox sb = glyph.getBBox();
- final OutlineShape s = TypecastRenderer.buildShape(metrics.getUnitsPerEM(), glyph);
- if( 0 < s.getVertexCount() ) {
+ 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 = s;
- isWhiteSpace = false;
+ shape = ( !isWhitespace && !isUndefined ) || Glyph.ID_UNKNOWN == glyph_id ? os : null;
} else {
- // non-contour glyph -> whitespace
+ // Case 2: Non-contour glyph -> whitespace or undefined
+ isWhitespace = !isUndefined;
glyph_bbox = new AABBox(0f,0f,0f, glyph_advance, glyph_height, 0f);
- shape = TypecastRenderer.buildEmptyShape(metrics.getUnitsPerEM(), glyph_bbox);
- isWhiteSpace = true;
+ shape = Glyph.ID_UNKNOWN == glyph_id ? TypecastRenderer.buildEmptyShape(metrics.getUnitsPerEM(), glyph_bbox) : null;
}
} else {
- // non-contour glyph -> whitespace
+ // Case 3: Non-contour glyph -> undefined
glyph_advance = getAdvanceWidthFU(glyph_id);
glyph_leftsidebearings = 0;
+ isWhitespace = false;
glyph_bbox = new AABBox(0f,0f,0f, glyph_advance, glyph_height, 0f);
- shape = TypecastRenderer.buildEmptyShape(metrics.getUnitsPerEM(), glyph_bbox);
- isWhiteSpace = true;
+ shape = Glyph.ID_UNKNOWN == glyph_id ? TypecastRenderer.buildEmptyShape(metrics.getUnitsPerEM(), glyph_bbox) : null;
}
KernSubtable kernSub = null;
{
@@ -239,8 +242,9 @@ class TypecastFont implements Font {
kernSub = kern.getSubtable0();
}
}
- result = new TypecastGlyph(this, glyph_id, glyph_name, glyph_bbox, glyph_advance, glyph_leftsidebearings, kernSub, shape, isWhiteSpace);
- if(DEBUG) {
+ 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));
System.err.println(" tc_glyph "+glyph);
System.err.println(" glyph "+result);
@@ -340,22 +344,24 @@ class TypecastFont implements Font {
temp1.setToIdentity();
final int glyph_id = getGlyphID(character);
final Font.Glyph glyph = getGlyph(glyph_id);
- final OutlineShape glyphShape = glyph.getShape();
- if( null == glyphShape ) { // also covers 'space' and all non-contour symbols
+ if( glyph.isUndefined() ) {
+ // break kerning, drop undefined
+ advanceTotal += glyph.getAdvanceFU();
+ 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();
+ } else {
+ // regular contour
+ if( null != left_glyph ) {
+ advanceTotal += left_glyph.getKerningFU(glyph_id);
+ }
+ temp1.translate(advanceTotal, y, temp2);
+ res.resize(temp1.transform(glyph.getBoundsFU(), temp_box));
advanceTotal += glyph.getAdvanceFU();
- left_glyph = null; // break kerning
- continue;
- } else if( glyph.isWhiteSpace() ) { // covers 'space' and all non-contour symbols
- left_glyph = null; // break kerning
- }
- if( null != left_glyph ) {
- advanceTotal += left_glyph.getKerningFU(glyph_id);
- }
- temp1.translate(advanceTotal, y, temp2);
- res.resize(temp1.transform(glyph.getBoundsFU(), temp_box));
-
- advanceTotal += glyph.getAdvanceFU();
- if( !glyph.isWhiteSpace() ) {
left_glyph = glyph;
}
}
@@ -421,23 +427,26 @@ class TypecastFont implements Font {
final int glyph_id = getGlyphID(character);
final Font.Glyph glyph = getGlyph(glyph_id);
- final OutlineShape glyphShape = glyph.getShape();
-
- if( null == glyphShape ) { // also covers 'space' and all non-contour symbols
+ if( glyph.isUndefined() ) {
+ // break kerning, drop undefined
+ advanceTotal += glyph.getAdvance();
+ 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();
+ } else {
+ // regular contour
+ if( null != left_glyph ) {
+ advanceTotal += left_glyph.getKerning(glyph_id);
+ }
+ temp1.translate(advanceTotal, y, temp2);
+ res.resize(temp1.transform(glyph.getShape().getBounds(), temp_box));
+ visitor.visit(character, glyph, temp1);
advanceTotal += glyph.getAdvance();
- left_glyph = null; // break kerning
- continue;
- } else if( glyph.isWhiteSpace() ) { // covers 'space' and all non-contour symbols
- left_glyph = null; // break kerning
- }
- if( null != left_glyph ) {
- advanceTotal += left_glyph.getKerning(glyph_id);
- }
- temp1.translate(advanceTotal, y, temp2);
- res.resize(temp1.transform(glyphShape.getBounds(), temp_box));
- visitor.visit(character, glyph, temp1);
- advanceTotal += glyph.getAdvance();
- if( !glyph.isWhiteSpace() ) {
left_glyph = glyph;
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
index d851efc3e..3ace5c480 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
@@ -39,6 +39,25 @@ 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";
+ private static final String NULL_NAME = "NULL";
+ private static final String null_NAME = "null";
+ private static final String dot_null_NAME = ".null";
+
+ /* pp */ static final boolean isUndefName(final String name) {
+ if( null != name ) {
+ if( TypecastGlyph.dot_undef_NAME.equals(name) ) {
+ return true;
+ } else if( TypecastGlyph.NULL_NAME.equals(name) ) {
+ return true;
+ } else if( TypecastGlyph.null_NAME.equals(name) ) {
+ return true;
+ } else if( TypecastGlyph.dot_null_NAME.equals(name) ) {
+ return true;
+ }
+ }
+ return false;
+ }
private static int[][] growPairArray(final int[][] src) {
final int length = src.length;
@@ -66,7 +85,8 @@ public final class TypecastGlyph implements Font.Glyph {
private final int id;
private final String name;
- private final boolean isWhiteSpace;
+ private final boolean isUndefined;
+ private final boolean isWhitespace;
private final TypecastFont font;
private final AABBox bbox; // in font-units
@@ -90,10 +110,12 @@ public final class TypecastGlyph implements Font.Glyph {
*/
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 isWhiteSpace) {
+ final KernSubtable kernSub, final OutlineShape shape,
+ final boolean isUndefined, final boolean isWhiteSpace) {
this.id = id;
this.name = name;
- this.isWhiteSpace = isWhiteSpace;
+ this.isUndefined = isUndefined;
+ this.isWhitespace = isWhiteSpace;
this.font = font;
this.bbox = bbox;
this.advance = advance;
@@ -139,10 +161,13 @@ public final class TypecastGlyph implements Font.Glyph {
public final String getName() { return name; }
@Override
- public final boolean isWhiteSpace() { return this.isWhiteSpace; }
+ public final boolean isWhitespace() { return this.isWhitespace; }
+
+ @Override
+ public final boolean isUndefined() { return this.isUndefined; }
@Override
- public final boolean isUndefined() { return name == ".notdef"; }
+ public final boolean isNonContour() { return isUndefined() || isWhitespace(); }
@Override
public final AABBox getBoundsFU() { return bbox; }
@@ -232,21 +257,41 @@ public final class TypecastGlyph implements Font.Glyph {
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
- final String ws_s = isWhiteSpace() ? ", ws" : "";
- sb.append("Glyph[id ").append(id).append(" '").append(name).append("'").append(ws_s)
+ final String contour_s;
+ if( isNonContour() ) {
+ final String ws_s = isWhitespace() ? "whitespace" : "";
+ final String undef_s = isUndefined() ? "undefined" : "";
+ contour_s = "non-cont("+ws_s+undef_s+")";
+ } else {
+ contour_s = "contour";
+ }
+ 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)
+ .append(", ").append(shape_s)
.append(", advance ").append(getAdvanceFU())
.append(", leftSideBearings ").append(getLeftSideBearingsFU())
.append(", kerning[size ").append(kerning.length).append(", horiz ").append(this.isKerningHorizontal()).append(", cross ").append(this.isKerningCrossstream()).append("]")
- .append(", shape ").append(null != shape).append("]");
+ .append("]");
return sb.toString();
}
@Override
public String fullString() {
final PostTable post = font.getPostTable();
- final String glyph_name = null != post ? post.getGlyphName(id) : "n/a";
final StringBuilder sb = new StringBuilder();
- sb.append("Glyph id ").append(id).append(" '").append(glyph_name).append("'")
+ final String contour_s;
+ if( isNonContour() ) {
+ final String ws_s = isWhitespace() ? "whitespace" : "";
+ final String undef_s = isUndefined() ? "undefined" : "";
+ contour_s = "non-cont("+ws_s+undef_s+")";
+ } else {
+ contour_s = "contour";
+ }
+ 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)
+ .append(", shape ").append(shape_s)
.append(", advance ").append(getAdvanceFU())
.append(", leftSideBearings ").append(getLeftSideBearingsFU())
.append(", ").append(getBoundsFU());