summaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/jogamp/graph/font
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-03-22 16:53:05 +0100
committerSven Gothel <[email protected]>2023-03-22 16:53:05 +0100
commit960af62429aef3ec573a7f6fa3ed6b0f5552376f (patch)
treed0d06e83cd2f41e965ba756fbe47a0d2a6527e58 /src/jogl/classes/jogamp/graph/font
parentf1784eda1866181a1e008c2f935705bf7b0baeb6 (diff)
Graph Font Processing: Produce a 'whitespace' Glyph w/ an OutlineShape (box) to allow better handling of such non-contour symbols.
Diffstat (limited to 'src/jogl/classes/jogamp/graph/font')
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java9
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java10
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java62
3 files changed, 76 insertions, 5 deletions
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
index 5720b9a17..ca27b9164 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
@@ -31,6 +31,8 @@ import com.jogamp.common.util.IntObjectHashMap;
import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
+import com.jogamp.graph.geom.Vertex;
+import com.jogamp.graph.geom.Vertex.Factory;
import com.jogamp.graph.geom.plane.AffineTransform;
import com.jogamp.opengl.math.geom.AABBox;
@@ -200,17 +202,20 @@ class TypecastFont implements Font {
final int glyph_leftsidebearings;
final AABBox glyph_bbox;
final OutlineShape shape;
+ final boolean isWhiteSpace;
if( null != glyph ) {
glyph_advance = glyph.getAdvanceWidth();
glyph_leftsidebearings = glyph.getLeftSideBearing();
glyph_bbox = glyph.getBBox();
shape = TypecastRenderer.buildShape(metrics.getUnitsPerEM(), glyph, OutlineShape.getDefaultVertexFactory());
+ isWhiteSpace = false;
} else {
final int glyph_height = metrics.getAscentFU() - metrics.getDescentFU();
glyph_advance = getAdvanceWidthFU(glyph_id);
glyph_leftsidebearings = 0;
glyph_bbox = new AABBox(0f,0f,0f, glyph_advance, glyph_height, 0f);
- shape = null;
+ shape = TypecastRenderer.buildEmptyShape(metrics.getUnitsPerEM(), glyph_bbox, OutlineShape.getDefaultVertexFactory());
+ isWhiteSpace = true;
}
KernSubtable kernSub = null;
{
@@ -219,7 +224,7 @@ class TypecastFont implements Font {
kernSub = kern.getSubtable0();
}
}
- result = new TypecastGlyph(this, glyph_id, glyph_name, glyph_bbox, glyph_advance, glyph_leftsidebearings, kernSub, shape);
+ result = new TypecastGlyph(this, glyph_id, glyph_name, glyph_bbox, glyph_advance, glyph_leftsidebearings, kernSub, shape, isWhiteSpace);
if(DEBUG) {
System.err.println("New glyph: " + glyph_id + "/'"+glyph_name+"', shape " + (null != shape));
System.err.println(" tc_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 f097b1225..d8864fb65 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
@@ -66,6 +66,7 @@ public final class TypecastGlyph implements Font.Glyph {
private final int id;
private final String name;
+ private final boolean isWhiteSpace;
private final TypecastFont font;
private final AABBox bbox; // in font-units
@@ -89,9 +90,10 @@ 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 KernSubtable kernSub, final OutlineShape shape, final boolean isWhiteSpace) {
this.id = id;
this.name = name;
+ this.isWhiteSpace = isWhiteSpace;
this.font = font;
this.bbox = bbox;
this.advance = advance;
@@ -132,6 +134,9 @@ public final class TypecastGlyph implements Font.Glyph {
public final String getName() { return name; }
@Override
+ public final boolean isWhiteSpace() { return this.isWhiteSpace; }
+
+ @Override
public final AABBox getBBoxFU() { return bbox; }
@Override
@@ -219,7 +224,8 @@ public final class TypecastGlyph implements Font.Glyph {
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
- sb.append("Glyph[id ").append(id).append(" '").append(name).append("'")
+ final String ws_s = isWhiteSpace() ? ", ws" : "";
+ sb.append("Glyph[id ").append(id).append(" '").append(name).append("'").append(ws_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("]")
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java
index b8a07cf8b..7b0e1b5c9 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java
@@ -35,14 +35,24 @@ import jogamp.opengl.Debug;
import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.geom.Vertex;
import com.jogamp.graph.geom.Vertex.Factory;
+import com.jogamp.opengl.math.geom.AABBox;
/**
* Factory to build an {@link OutlineShape} from
* {@link jogamp.graph.font.typecast.ot.OTGlyph Glyph}s.
*
+ * <p>
* TTF Glyph's have Winding.CW, hence we add the OutlineShape in reverse order,
* i.e. each new vertex at position 0.
- *
+ * </p>
+ * <p>
+ * Outer TTF glyph winding is expected Winding.CW,
+ * moved into OutlineShape in reverse as Winding.CCW.
+ * </p>
+ * <p>
+ * Inner TTF glyph winding is expected Winding.CCW
+ * moved into OutlineShape in reverse as Winding.CW.
+ * </p>
* http://www.freetype.org/freetype2/docs/glyphs/glyphs-3.html
* http://walon.org/pub/ttf/ttf_glyphs.htm
*/
@@ -72,6 +82,17 @@ public class TypecastRenderer {
shape.addEmptyOutline();
shape.addVertex(0, p1x/unitsPerEM, p1y/unitsPerEM, true);
}
+ private static void addShapeMoveTo(final OutlineShape shape, final float p1x, final float p1y) {
+ if( PRINT_CODE ) {
+ System.err.println("// Shape.MoveTo:");
+ System.err.printf("shape.closeLastOutline(false);%n");
+ System.err.printf("shape.addEmptyOutline();%n");
+ System.err.printf("shape.addVertex(%d, %ff, %ff, %b);%n", 0, p1x, p1y, true);
+ }
+ shape.closeLastOutline(false);
+ shape.addEmptyOutline();
+ shape.addVertex(0, p1x, p1y, true);
+ }
private static void addShapeLineTo(final float unitsPerEM, final OutlineShape shape, final Point p1) {
if( PRINT_CODE ) {
System.err.println("// Shape.LineTo:");
@@ -79,6 +100,13 @@ public class TypecastRenderer {
}
shape.addVertex(0, p1.x/unitsPerEM, p1.y/unitsPerEM, true);
}
+ private static void addShapeLineTo(final OutlineShape shape, final float p1x, final float p1y) {
+ if( PRINT_CODE ) {
+ System.err.println("// Shape.LineTo:");
+ System.err.printf("shape.addVertex(%d, %ff, %ff, %b);%n", 0, p1x, p1y, true);
+ }
+ shape.addVertex(0, p1x, p1y, true);
+ }
private static void addShapeQuadTo(final float unitsPerEM, final OutlineShape shape, final Point p1, final Point p2) {
if( PRINT_CODE ) {
System.err.println("// Shape.QuadTo:");
@@ -109,6 +137,38 @@ public class TypecastRenderer {
shape.addVertex(0, p3.x/unitsPerEM, p3.y/unitsPerEM, true);
}
+ public static OutlineShape buildEmptyShape(final int unitsPerEM, final AABBox box, final Factory<? extends Vertex> vertexFactory) {
+ final OutlineShape shape = new OutlineShape(vertexFactory);
+ if( PRINT_CODE ) { System.err.printf("%n// Start Empty Shape%n"); }
+ final float x1 = box.getMinX() / unitsPerEM;
+ final float x2 = box.getMaxX() / unitsPerEM;
+ final float y1 = box.getMinY() / unitsPerEM;
+ final float y2 = box.getMaxY() / unitsPerEM;
+ {
+ // Outer TTF glyph winding is expected Winding.CW, moved into OutlineShape in reverse as Winding.CCW.
+ addShapeMoveTo(shape, x1, y1);
+ addShapeLineTo(shape, x1, y2);
+ addShapeLineTo(shape, x2, y2);
+ addShapeLineTo(shape, x2, y1);
+ addShapeLineTo(shape, x1, y1);
+ shape.closeLastOutline(false);
+ }
+ {
+ // Inner TTF glyph winding is expected Winding.CCW, moved into OutlineShape in reverse as Winding.CW.
+ final float dxy_FU = box.getWidth() < box.getHeight() ? box.getWidth() : box.getHeight();
+ final float dxy = dxy_FU / unitsPerEM / 20f;
+ addShapeMoveTo(shape, x1+dxy, y1+dxy);
+ addShapeLineTo(shape, x2-dxy, y1+dxy);
+ addShapeLineTo(shape, x2-dxy, y2-dxy);
+ addShapeLineTo(shape, x1+dxy, y2-dxy);
+ addShapeLineTo(shape, x1+dxy, y1+dxy);
+ shape.closeLastOutline(false);
+ }
+ shape.setIsQuadraticNurbs();
+ if( PRINT_CODE ) { System.err.printf("// End Empty Shape%n%n"); }
+ return shape;
+ }
+
public static OutlineShape buildShape(final int unitsPerEM, final Glyph glyph, final Factory<? extends Vertex> vertexFactory) {
if (glyph == null) {
return null;