diff options
author | Sven Gothel <[email protected]> | 2023-03-22 16:53:05 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2023-03-22 16:53:05 +0100 |
commit | 960af62429aef3ec573a7f6fa3ed6b0f5552376f (patch) | |
tree | d0d06e83cd2f41e965ba756fbe47a0d2a6527e58 /src/jogl/classes/jogamp/graph/font | |
parent | f1784eda1866181a1e008c2f935705bf7b0baeb6 (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')
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; |