aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/jogamp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes/jogamp')
-rw-r--r--src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java31
-rw-r--r--src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java8
-rw-r--r--src/jogl/classes/jogamp/graph/curve/tess/Loop.java107
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java200
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java20
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java2
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java341
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/Glyph.java20
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfDescript.java27
9 files changed, 497 insertions, 259 deletions
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java b/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java
index 369d0b493..331116f7e 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java
@@ -80,20 +80,20 @@ public class CDTriangulator2D implements Triangulator {
@Override
public final void addCurve(final List<Triangle> sink, final Outline polyline, final float sharpness) {
- Loop loop = null;
-
- if(!loops.isEmpty()) {
- loop = getContainerLoop(polyline);
- }
+ Loop loop = getContainerLoop(polyline);
if(loop == null) {
- final GraphOutline outline = new GraphOutline(polyline);
+ final Winding winding = Winding.CCW; // -> HEdge.BOUNDARY
+ // Too late: polyline.setWinding(winding);
+ final GraphOutline outline = new GraphOutline(polyline); // , winding);
final GraphOutline innerPoly = extractBoundaryTriangles(sink, outline, false, sharpness);
// vertices.addAll(polyline.getVertices());
- loop = new Loop(innerPoly, Winding.CCW);
+ loop = new Loop(innerPoly, winding);
loops.add(loop);
} else {
- final GraphOutline outline = new GraphOutline(polyline);
+ // final Winding winding = Winding.CW; // -> HEdge.HOLE
+ // Not required, handled in Loop.initFromPolyline(): polyline.setWinding(winding);
+ final GraphOutline outline = new GraphOutline(polyline); // , winding);
final GraphOutline innerPoly = extractBoundaryTriangles(sink, outline, true, sharpness);
// vertices.addAll(innerPoly.getVertices());
loop.addConstraintCurve(innerPoly);
@@ -221,12 +221,15 @@ public class CDTriangulator2D implements Triangulator {
}
private Loop getContainerLoop(final Outline polyline) {
- final ArrayList<Vertex> vertices = polyline.getVertices();
- for(int i=0; i < loops.size(); i++) {
- final Loop loop = loops.get(i);
- for(int j=0; j < vertices.size(); j++) {
- if( loop.checkInside( vertices.get(j) ) ) {
- return loop;
+ final int count = loops.size();
+ if( 0 < count ) {
+ final ArrayList<Vertex> vertices = polyline.getVertices();
+ for(int i=0; i < count; i++) {
+ final Loop loop = loops.get(i);
+ for(int j=0; j < vertices.size(); j++) {
+ if( loop.checkInside( vertices.get(j) ) ) {
+ return loop;
+ }
}
}
}
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java b/src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java
index 81e6efdad..75192d45a 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java
@@ -31,6 +31,7 @@ import java.util.ArrayList;
import com.jogamp.graph.geom.Outline;
import com.jogamp.graph.geom.Vertex;
+import com.jogamp.graph.geom.plane.Winding;
public class GraphOutline {
final private Outline outline;
@@ -40,11 +41,14 @@ public class GraphOutline {
this.outline = new Outline();
}
- /**Create a control polyline of control vertices
+ /**
+ * Create a control polyline of control vertices
* the curve pieces can be identified by onCurve flag
* of each cp the control polyline is open by default
+ *
+ * @param ol the source {@link Outline}
*/
- public GraphOutline(final Outline ol){
+ public GraphOutline(final Outline ol) {
this.outline = ol;
final ArrayList<Vertex> vertices = this.outline.getVertices();
for(int i = 0; i< vertices.size(); i++){
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/Loop.java b/src/jogl/classes/jogamp/graph/curve/tess/Loop.java
index 5d1bc051f..1d8264607 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/Loop.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/Loop.java
@@ -34,6 +34,7 @@ import com.jogamp.graph.geom.Vertex;
import com.jogamp.graph.geom.plane.Winding;
import com.jogamp.graph.geom.Triangle;
import com.jogamp.opengl.math.VectorUtil;
+import com.jogamp.opengl.math.Vert2fImmutable;
import com.jogamp.opengl.math.geom.AABBox;
public class Loop {
@@ -91,9 +92,24 @@ public class Loop {
return (root.getNext().getNext().getNext() == root);
}
- /**Create a connected list of half edges (loop)
+ private static float area(final ArrayList<GraphVertex> vertices) {
+ final int n = vertices.size();
+ float area = 0.0f;
+ for (int p = n - 1, q = 0; q < n; p = q++) {
+ final float[] pCoord = vertices.get(p).getCoord();
+ final float[] qCoord = vertices.get(q).getCoord();
+ area += pCoord[0] * qCoord[1] - qCoord[0] * pCoord[1];
+ }
+ return area;
+ }
+ private static Winding getWinding(final ArrayList<GraphVertex> vertices) {
+ return area(vertices) >= 0 ? Winding.CCW : Winding.CW ;
+ }
+
+ /**
+ * Create a connected list of half edges (loop)
* from the boundary profile
- * @param reqWinding requested winding of edges (CCW or CW)
+ * @param reqWinding requested winding of edges, either {@link Winding#CCW} for {@link HEdge#BOUNDARY} or {@link Winding#CW} for {@link HEdge#HOLE}
*/
private HEdge initFromPolyline(final GraphOutline outline, final Winding reqWinding){
final ArrayList<GraphVertex> vertices = outline.getGraphPoint();
@@ -101,57 +117,64 @@ public class Loop {
if(vertices.size()<3) {
throw new IllegalArgumentException("outline's vertices < 3: " + vertices.size());
}
- final Winding hasWinding = VectorUtil.getWinding(
- vertices.get(0).getPoint(),
- vertices.get(1).getPoint(),
- vertices.get(2).getPoint());
- //FIXME: handle case when vertices come inverted - Rami
- // skips inversion CW -> CCW
- final boolean invert = hasWinding != reqWinding &&
- reqWinding == Winding.CW;
-
- final int max;
+ final Winding hasWinding = getWinding( vertices ); // requires area-winding detection
+
final int edgeType = reqWinding == Winding.CCW ? HEdge.BOUNDARY : HEdge.HOLE ;
- int index;
HEdge firstEdge = null;
HEdge lastEdge = null;
- if(!invert) {
- max = vertices.size();
- index = 0;
- } else {
- max = -1;
- index = vertices.size() -1;
- }
-
- while(index != max){
- final GraphVertex v1 = vertices.get(index);
- box.resize(v1.getX(), v1.getY(), v1.getZ());
-
- final HEdge edge = new HEdge(v1, edgeType);
-
- v1.addEdge(edge);
- if(lastEdge != null) {
- lastEdge.setNext(edge);
- edge.setPrev(lastEdge);
- } else {
- firstEdge = edge;
- }
-
- if(!invert) {
- if(index == vertices.size()-1) {
+ /**
+ * The winding conversion CW -> CCW can't be resolved here (-> Rami?)
+ * Therefore we require outline boundaries to be in CCW, see API-doc comment in OutlineShape.
+ *
+ * Original comment:
+ * FIXME: handle case when vertices come inverted - Rami
+ * Skips inversion CW -> CCW
+ */
+ if( hasWinding == reqWinding || reqWinding == Winding.CCW ) {
+ // Correct Winding or skipped CW -> CCW (no inversion possible here, too late ??)
+ final int max = vertices.size() - 1;
+ for(int index = 0; index <= max; ++index) {
+ final GraphVertex v1 = vertices.get(index);
+ box.resize(v1.getX(), v1.getY(), v1.getZ());
+
+ final HEdge edge = new HEdge(v1, edgeType);
+
+ v1.addEdge(edge);
+ if(lastEdge != null) {
+ lastEdge.setNext(edge);
+ edge.setPrev(lastEdge);
+ } else {
+ firstEdge = edge;
+ }
+ if(index == max ) {
edge.setNext(firstEdge);
firstEdge.setPrev(edge);
}
- index++;
- } else {
+ lastEdge = edge;
+ }
+ } else { // if( reqWinding == Winding.CW ) {
+ // CCW -> CW
+ for(int index = vertices.size() - 1; index >= 0; --index) {
+ final GraphVertex v1 = vertices.get(index);
+ box.resize(v1.getX(), v1.getY(), v1.getZ());
+
+ final HEdge edge = new HEdge(v1, edgeType);
+
+ v1.addEdge(edge);
+ if(lastEdge != null) {
+ lastEdge.setNext(edge);
+ edge.setPrev(lastEdge);
+ } else {
+ firstEdge = edge;
+ }
+
if (index == 0) {
edge.setNext(firstEdge);
firstEdge.setPrev(edge);
}
- index--;
+ lastEdge = edge;
}
- lastEdge = edge;
}
return firstEdge;
}
@@ -159,7 +182,7 @@ public class Loop {
public void addConstraintCurve(final GraphOutline polyline) {
// GraphOutline outline = new GraphOutline(polyline);
/**needed to generate vertex references.*/
- initFromPolyline(polyline, Winding.CW);
+ initFromPolyline(polyline, Winding.CW); // -> HEdge.HOLE
final GraphVertex v3 = locateClosestVertex(polyline);
final HEdge v3Edge = v3.findBoundEdge();
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
index 382d35a73..f5358b74b 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2011 JogAmp Community. All rights reserved.
+ * Copyright 2011-2023 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -56,7 +56,7 @@ class TypecastFont implements Font {
/* pp */ final TTFont font;
private final CmapFormat cmapFormat;
private final int cmapentries;
- private final IntObjectHashMap char2Glyph;
+ private final IntObjectHashMap idToGlyph;
private final TypecastHMetrics metrics;
// FIXME: Add cache size to limit memory usage ??
@@ -147,7 +147,7 @@ class TypecastFont implements Font {
}
}
}
- char2Glyph = new IntObjectHashMap(cmapentries + cmapentries/4);
+ idToGlyph = new IntObjectHashMap(cmapentries + cmapentries/4);
metrics = new TypecastHMetrics(this);
}
@@ -197,11 +197,9 @@ class TypecastFont implements Font {
}
@Override
- public Glyph getGlyph(final char symbol) {
- TypecastGlyph result = (TypecastGlyph) char2Glyph.get(symbol);
+ public Glyph getGlyph(final int glyph_id) {
+ TypecastGlyph result = (TypecastGlyph) idToGlyph.get(glyph_id);
if (null == result) {
- final int glyph_id = getGlyphID( symbol );
-
jogamp.graph.font.typecast.ot.Glyph glyph = font.getGlyph(glyph_id);
final int glyph_advance;
final AABBox glyph_bbox;
@@ -222,9 +220,9 @@ class TypecastFont implements Font {
break;
}
if(null == glyph) {
- throw new RuntimeException("Could not retrieve glyph for symbol: <"+symbol+"> "+(int)symbol+" -> glyph id "+glyph_id);
+ throw new RuntimeException("Could not retrieve glyph for glyph id "+glyph_id);
}
- final OutlineShape shape = TypecastRenderer.buildShape(metrics.getUnitsPerEM(), symbol, glyph, vertexFactory);
+ final OutlineShape shape = TypecastRenderer.buildShape(metrics.getUnitsPerEM(), glyph, vertexFactory);
KernSubtable kernSub = null;
{
final KernTable kern = font.getKernTable();
@@ -232,17 +230,17 @@ class TypecastFont implements Font {
kernSub = kern.getSubtable0();
}
}
- result = new TypecastGlyph(this, symbol, glyph_id, glyph_bbox, glyph_advance, kernSub, shape);
+ result = new TypecastGlyph(this, glyph_id, glyph_bbox, glyph_advance, kernSub, shape);
if(DEBUG) {
final PostTable post = font.getPostTable();
final String glyph_name = null != post ? post.getGlyphName(glyph_id) : "n/a";
- System.err.println("New glyph: " + (int)symbol + " ( " + symbol +" ) -> " + glyph_id + "/'"+glyph_name+"', contours " + glyph.getPointCount() + ": " + shape);
+ System.err.println("New glyph: " + glyph_id + "/'"+glyph_name+"', contours " + glyph.getPointCount() + ": " + shape);
System.err.println(" "+glyph);
System.err.println(" "+result);
}
glyph.clearPointData();
- char2Glyph.put(symbol, result);
+ idToGlyph.put(glyph_id, result);
}
return result;
}
@@ -256,106 +254,154 @@ class TypecastFont implements Font {
public int getLineHeightFU() {
final Metrics metrics = getMetrics();
final int lineGap = metrics.getLineGapFU() ; // negative value!
- final int ascent = metrics.getAscentFU() ; // negative value!
final int descent = metrics.getDescentFU() ; // positive value!
+ final int ascent = metrics.getAscentFU() ; // negative value!
final int advanceY = lineGap - descent + ascent; // negative value!
return -advanceY;
}
@Override
- public float getMetricWidth(final CharSequence string) {
- return metrics.getScale( getMetricWidthFU(string) );
+ public AABBox getMetricBounds(final CharSequence string) {
+ return getMetricBoundsFU(string).scale2(1.0f/metrics.getUnitsPerEM(), new float[3]);
}
@Override
- public int getMetricWidthFU(final CharSequence string) {
- int width = 0;
- final int len = string.length();
- for (int i=0; i< len; i++) {
+ public AABBox getMetricBoundsFU(final CharSequence string) {
+ if (null == string || 0 == string.length() ) {
+ return new AABBox();
+ }
+ final AABBox res = new AABBox();
+ final int charCount = string.length();
+
+ final int lineHeight = getLineHeightFU();
+
+ int y = 0;
+ int advanceTotal = 0;
+
+ for (int i=0; i<charCount; i++) {
final char character = string.charAt(i);
if (character == '\n') {
- width = 0;
+ advanceTotal = 0;
+ y -= lineHeight;
+ } else if (character == ' ') {
+ advanceTotal += getAdvanceWidthFU(Glyph.ID_SPACE);
} else {
- final Glyph glyph = getGlyph(character);
- width += glyph.getAdvanceFU();
+ advanceTotal += getAdvanceWidthFU( getGlyphID( character ) );
}
+ res.resize(advanceTotal, y, 0f);
+ }
+ if( 0 < advanceTotal ) {
+ // add one line for current non '\n' terminated
+ y -= lineHeight;
+ res.resize(advanceTotal, y, 0f);
}
- return width;
+ return res;
}
@Override
- public float getMetricHeight(final CharSequence string) {
- return metrics.getScale( getMetricHeightFU(string) );
+ public AABBox getGlyphBounds(final CharSequence string) {
+ return getGlyphBoundsFU(string).scale2(1.0f/metrics.getUnitsPerEM(), new float[3]);
}
@Override
- public int getMetricHeightFU(final CharSequence string) {
- int height = 0;
+ public AABBox getGlyphBoundsFU(final CharSequence string) {
+ if (null == string || 0 == string.length() ) {
+ return new AABBox();
+ }
+ final AffineTransform temp1 = new AffineTransform();
+ final AffineTransform temp2 = new AffineTransform();
+
+ final AABBox res = new AABBox();
+ final int charCount = string.length();
+
+ final int lineHeight = getLineHeightFU();
- for (int i=0; i<string.length(); i++) {
+ int y = 0;
+ int advanceTotal = 0;
+ Font.Glyph left_glyph = null;
+ final AABBox temp_box = new AABBox();
+
+ for(int i=0; i< charCount; i++) {
final char character = string.charAt(i);
- if (character != ' ') {
- final Glyph glyph = getGlyph(character);
- height = (int)Math.ceil(Math.max(glyph.getBBoxFU().getHeight(), height));
+ if( '\n' == character ) {
+ y -= lineHeight;
+ advanceTotal = 0;
+ left_glyph = null;
+ } else if (character == ' ') {
+ advanceTotal += getAdvanceWidthFU(Glyph.ID_SPACE);
+ left_glyph = null;
+ } else {
+ // reset transform
+ temp1.setToIdentity();
+ final int glyph_id = getGlyphID(character);
+ final Font.Glyph glyph = getGlyph(glyph_id);
+ final OutlineShape glyphShape = glyph.getShape();
+ if( null == glyphShape ) {
+ left_glyph = null;
+ continue;
+ }
+ if( null != left_glyph ) {
+ advanceTotal += left_glyph.getKerningFU(glyph_id);
+ }
+ temp1.translate(advanceTotal, y, temp2);
+ res.resize(temp1.transform(glyph.getBBoxFU(), temp_box));
+ advanceTotal += glyph.getAdvanceFU();
+ left_glyph = glyph;
}
}
- return height;
+ return res;
}
@Override
- public AABBox getMetricBounds(final CharSequence string) {
- return getMetricBoundsFU(string).scale2(1.0f/metrics.getUnitsPerEM(), new float[3]);
+ public AABBox getGlyphShapeBounds(final CharSequence string) {
+ return getGlyphShapeBounds(null, string);
}
-
@Override
- public AABBox getMetricBoundsFU(final CharSequence string) {
- if (string == null) {
+ public AABBox getGlyphShapeBounds(final AffineTransform transform, final CharSequence string) {
+ if (null == string || 0 == string.length() ) {
return new AABBox();
}
- final int charCount = string.length();
- final int lineHeight = getLineHeightFU();
- int totalHeight = 0;
- int totalWidth = 0;
- int curLineWidth = 0;
- for (int i=0; i<charCount; i++) {
- final char character = string.charAt(i);
- if (character == '\n') {
- totalWidth = Math.max(curLineWidth, totalWidth);
- curLineWidth = 0;
- totalHeight += lineHeight;
- continue;
- }
- curLineWidth += getAdvanceWidthFU( getGlyphID( character ) );
- }
- if (curLineWidth > 0) {
- totalHeight += lineHeight;
- totalWidth = Math.max(curLineWidth, totalWidth);
- }
- return new AABBox(0, 0, 0, totalWidth, totalHeight,0);
+ final OutlineShape.Visitor visitor = new OutlineShape.Visitor() {
+ @Override
+ public final void visit(final OutlineShape shape, final AffineTransform t) {
+ // nop
+ } };
+ return processString(visitor, transform, string);
+ }
+
+ @Override
+ public AABBox processString(final OutlineShape.Visitor visitor, final AffineTransform transform,
+ final CharSequence string) {
+ return processString(visitor, transform, string, new AffineTransform(), new AffineTransform());
}
@Override
- public AABBox getPointsBoundsFU(final AffineTransform transform, final CharSequence string) {
- if (string == null) {
+ public AABBox processString(final OutlineShape.Visitor visitor, final AffineTransform transform,
+ final CharSequence string,
+ final AffineTransform temp1, final AffineTransform temp2) {
+ if (null == string || 0 == string.length() ) {
return new AABBox();
}
- final AffineTransform temp1 = new AffineTransform();
- final AffineTransform temp2 = new AffineTransform();
- final int charCount = string.length();
- final int lineHeight = getLineHeightFU();
- final AABBox tbox = new AABBox();
final AABBox res = new AABBox();
+ final int charCount = string.length();
+
+ // region.setFlipped(true);
+ final float lineHeight = getLineHeight();
float y = 0;
float advanceTotal = 0;
+ Font.Glyph left_glyph = null;
+ final AABBox temp_box = new AABBox();
for(int i=0; i< charCount; i++) {
final char character = string.charAt(i);
if( '\n' == character ) {
y -= lineHeight;
advanceTotal = 0;
+ left_glyph = null;
} else if (character == ' ') {
- advanceTotal += getAdvanceWidthFU(Glyph.ID_SPACE);
+ advanceTotal += getAdvanceWidth(Glyph.ID_SPACE);
+ left_glyph = null;
} else {
// reset transform
if( null != transform ) {
@@ -363,28 +409,28 @@ class TypecastFont implements Font {
} else {
temp1.setToIdentity();
}
- temp1.translate(advanceTotal, y, temp2);
- tbox.reset();
-
- final Font.Glyph glyph = getGlyph(character);
- res.resize(temp1.transform(glyph.getBBoxFU(), tbox));
-
+ final int glyph_id = getGlyphID(character);
+ final Font.Glyph glyph = getGlyph(glyph_id);
final OutlineShape glyphShape = glyph.getShape();
if( null == glyphShape ) {
+ left_glyph = null;
continue;
}
- advanceTotal += glyph.getAdvanceFU();
+ 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(glyphShape, temp1);
+ advanceTotal += glyph.getAdvance();
+ left_glyph = glyph;
}
}
return res;
}
@Override
- public AABBox getPointsBounds(final AffineTransform transform, final CharSequence string) {
- return getPointsBoundsFU(transform, string).scale2(1.0f/metrics.getUnitsPerEM(), new float[3]);
- }
-
- @Override
final public int getNumGlyphs() {
return font.getNumGlyphs();
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
index e6a655661..12d492f6e 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2011 JogAmp Community. All rights reserved.
+ * Copyright 2011-2023 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -65,7 +65,7 @@ public final class TypecastGlyph implements Font.Glyph {
/** in font-units */
public final AABBox getBBoxFU() { return this.bbox; }
- /** Return advance in font units to be divided by unitsPerEM */
+ /** Return advance in font units, sourced from `hmtx` table. */
public final int getAdvanceFU() { return this.advance; }
@Override
@@ -104,7 +104,6 @@ public final class TypecastGlyph implements Font.Glyph {
return dst;
}
- private final char symbol;
private final int id;
private final int[/*right_glyphid*/][/*value*/] kerning;
private final boolean kerning_horizontal;
@@ -115,15 +114,13 @@ public final class TypecastGlyph implements Font.Glyph {
/**
*
* @param font
- * @param symbol
* @param id
* @param bbox in font-units
* @param advance from hmtx in font-units
* @param shape
*/
- protected TypecastGlyph(final TypecastFont font, final char symbol, final int id, final AABBox bbox, final int advance,
+ protected TypecastGlyph(final TypecastFont font, final int id, final AABBox bbox, final int advance,
final KernSubtable kernSub, final OutlineShape shape) {
- this.symbol = symbol;
this.id = id;
if( null != kernSub && kernSub.areKerningValues() ) {
int pair_sz = 64;
@@ -160,11 +157,6 @@ public final class TypecastGlyph implements Font.Glyph {
return this.metrics.getFont();
}
- @Override
- public final char getSymbol() {
- return this.symbol;
- }
-
public final Metrics getMetrics() {
return this.metrics;
}
@@ -195,6 +187,12 @@ public final class TypecastGlyph implements Font.Glyph {
}
@Override
+ public final AABBox getBBox() {
+ final AABBox dest = new AABBox();
+ return dest.copy(metrics.getBBoxFU()).scale2(1.0f/metrics.getUnitsPerEM(), new float[2]);
+ }
+
+ @Override
public final int getAdvanceFU() { return metrics.getAdvanceFU(); }
@Override
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java
index 274114e4a..cae8b2755 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2011 JogAmp Community. All rights reserved.
+ * Copyright 2011-2023 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java
index 60319d842..2a895a2f1 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2011 JogAmp Community. All rights reserved.
+ * Copyright 2011-2023 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -27,7 +27,9 @@
*/
package jogamp.graph.font.typecast;
+import jogamp.graph.font.typecast.ot.Glyph;
import jogamp.graph.font.typecast.ot.Point;
+import jogamp.graph.font.typecast.ot.T2Glyph;
import jogamp.opengl.Debug;
import com.jogamp.graph.curve.OutlineShape;
@@ -46,50 +48,76 @@ import com.jogamp.graph.geom.Vertex.Factory;
*/
public class TypecastRenderer {
private static final boolean DEBUG = Debug.debug("graph.font.Renderer");
+ private static final boolean PRINT_CODE = Debug.debug("graph.font.Renderer.Code");
private static void addShapeMoveTo(final float unitsPerEM, final OutlineShape shape, final Point p1) {
- if( DEBUG ) { System.err.println("Shape.MoveTo: "+p1); }
+ 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, p1.x/unitsPerEM, p1.y/unitsPerEM, true);
+ }
shape.closeLastOutline(false);
shape.addEmptyOutline();
- shape.addVertex(0, p1.x/unitsPerEM, p1.y/unitsPerEM, p1.onCurve);
+ shape.addVertex(0, p1.x/unitsPerEM, p1.y/unitsPerEM, true);
}
private static void addShapeLineTo(final float unitsPerEM, final OutlineShape shape, final Point p1) {
- if( DEBUG ) { System.err.println("Shape.LineTo: "+p1); }
- shape.addVertex(0, p1.x/unitsPerEM, p1.y/unitsPerEM, p1.onCurve);
+ if( PRINT_CODE ) {
+ System.err.println("// Shape.LineTo:");
+ System.err.printf("shape.addVertex(%d, %ff, %ff, %b);%n", 0, p1.x/unitsPerEM, p1.y/unitsPerEM, true);
+ }
+ shape.addVertex(0, p1.x/unitsPerEM, p1.y/unitsPerEM, true);
}
private static void addShapeQuadTo(final float unitsPerEM, final OutlineShape shape, final Point p1, final Point p2) {
- if( DEBUG ) { System.err.println("Shape.QuadTo: "+p1+", "+p2); }
- shape.addVertex(0, p1.x/unitsPerEM, p1.y/unitsPerEM, p1.onCurve);
- shape.addVertex(0, p2.x/unitsPerEM, p2.y/unitsPerEM, p2.onCurve);
+ if( PRINT_CODE ) {
+ System.err.println("// Shape.QuadTo:");
+ System.err.printf("shape.addVertex(%d, %ff, %ff, %b);%n", 0, p1.x/unitsPerEM, p1.y/unitsPerEM, false);
+ System.err.printf("shape.addVertex(%d, %ff, %ff, %b);%n", 0, p2.x/unitsPerEM, p2.y/unitsPerEM, true);
+ }
+ shape.addVertex(0, p1.x/unitsPerEM, p1.y/unitsPerEM, false);
+ shape.addVertex(0, p2.x/unitsPerEM, p2.y/unitsPerEM, true);
+ }
+ private static void addShapeQuadTo(final float unitsPerEM, final OutlineShape shape, final Point p1, final float p2x, final float p2y) {
+ if( PRINT_CODE ) {
+ System.err.println("// Shape.QuadTo:");
+ System.err.printf("shape.addVertex(%d, %ff, %ff, %b);%n", 0, p1.x/unitsPerEM, p1.y/unitsPerEM, false);
+ System.err.printf("shape.addVertex(%d, %ff, %ff, %b);%n", 0, p2x/unitsPerEM, p2y/unitsPerEM, true);
+ }
+ shape.addVertex(0, p1.x/unitsPerEM, p1.y/unitsPerEM, false);
+ shape.addVertex(0, p2x/unitsPerEM, p2y/unitsPerEM, true);
}
- private static void addShapeQuadTo(final float unitsPerEM, final OutlineShape shape, final Point p1,
- final float p2x, final float p2y, final boolean p2OnCurve) {
- if( DEBUG ) { System.err.println("Shape.QuadTo: "+p1+", p2 "+p2x+", "+p2y+", onCurve "+p2OnCurve); }
- shape.addVertex(0, p1.x/unitsPerEM, p1.y/unitsPerEM, p1.onCurve);
- shape.addVertex(0, p2x/unitsPerEM, p2y/unitsPerEM, p2OnCurve);
+ private static void addShapeCubicTo(final float unitsPerEM, final OutlineShape shape, final Point p1, final Point p2, final Point p3) {
+ if( PRINT_CODE ) {
+ System.err.println("// Shape.CubicTo:");
+ System.err.printf("shape.addVertex(%d, %ff, %ff, %b);%n", 0, p1.x/unitsPerEM, p1.y/unitsPerEM, false);
+ System.err.printf("shape.addVertex(%d, %ff, %ff, %b);%n", 0, p2.x/unitsPerEM, p2.y/unitsPerEM, false);
+ System.err.printf("shape.addVertex(%d, %ff, %ff, %b);%n", 0, p3.x/unitsPerEM, p3.y/unitsPerEM, true);
+ }
+ shape.addVertex(0, p1.x/unitsPerEM, p1.y/unitsPerEM, false);
+ shape.addVertex(0, p2.x/unitsPerEM, p2.y/unitsPerEM, false);
+ shape.addVertex(0, p3.x/unitsPerEM, p3.y/unitsPerEM, true);
}
- /**
- private static void addShapeCubicTo(final float unitsPerEM, final OutlineShape shape, Factory<? extends Vertex> vertexFactory, Point p1, Point p2, Point p3) {
- shape.addVertex(0, p1.x/unitsPerEM, p1.y/unitsPerEM, p1.onCurve);
- shape.addVertex(0, p2.x/unitsPerEM, p2.y/unitsPerEM, p2.onCurve);
- shape.addVertex(0, p3.x/unitsPerEM, p3.y/unitsPerEM, p3.onCurve);
- } */
- public static OutlineShape buildShape(final int unitsPerEM, final char symbol, final jogamp.graph.font.typecast.ot.Glyph glyph, final Factory<? extends Vertex> vertexFactory) {
- //
- // See Typecast: GlyphPathFactory.addContourToPath(..)
- //
+ public static OutlineShape buildShape(final int unitsPerEM, final Glyph glyph, final Factory<? extends Vertex> vertexFactory) {
if (glyph == null) {
return null;
}
-
final OutlineShape shape = new OutlineShape(vertexFactory);
- buildShapeImpl(unitsPerEM, shape, symbol, glyph);
- shape.setIsQuadraticNurbs();
+ if (glyph instanceof T2Glyph) {
+ // Type 1/2: Cubic
+ if( PRINT_CODE ) { System.err.printf("%n// Start Type-2 Shape for Glyph %d%n", glyph.getID()); }
+ buildShapeType2(unitsPerEM, shape, (T2Glyph)glyph);
+ } else {
+ // TTF: quadratic only
+ if( PRINT_CODE ) { System.err.printf("%n// Start TTF Shape for Glyph %d%n", glyph.getID()); }
+ buildShapeTTF(unitsPerEM, shape, glyph);
+ shape.setIsQuadraticNurbs();
+ }
+ if( PRINT_CODE ) { System.err.printf("// End Shape for Glyph %d%n%n", glyph.getID()); }
return shape;
}
- private static void buildShapeImpl(final float unitsPerEM, final OutlineShape shape, final char symbol, final jogamp.graph.font.typecast.ot.Glyph glyph) {
+ private static void buildShapeTTF(final float unitsPerEM, final OutlineShape shape, final Glyph glyph) {
// Iterate through all of the points in the glyph. Each time we find a
// contour end point, add the point range to the path.
int startIndex = 0;
@@ -99,98 +127,125 @@ public class TypecastRenderer {
count++;
if ( glyph.getPoint(i).endOfContour ) {
int offset = 0;
- while ( offset < count - 1 ) { // require at least +1 point (last one is end-of-contour)
- final Point p0 = glyph.getPoint(startIndex + offset%count);
- final Point p1 = glyph.getPoint(startIndex + (offset+1)%count);
- final Point p2 = glyph.getPoint(startIndex + (offset+2)%count);
- final Point p3 = offset+3 < count ? glyph.getPoint(startIndex + offset+3) : null;
+ while ( offset < count ) {
+ final int point_0_idx = startIndex + offset%count;
+ final Point point_m = glyph.getPoint((offset==0) ? startIndex+count-1 : startIndex+(offset-1)%count);
+ final Point point_0 = glyph.getPoint(point_0_idx);
+ final Point point_1 = glyph.getPoint(startIndex + (offset+1)%count);
+ final Point point_2 = glyph.getPoint(startIndex + (offset+2)%count);
+ // final Point point_3 = offset+3 < count ? glyph.getPoint(startIndex + offset+3) : null;
if( DEBUG ) {
- System.err.println("GlyphShape<"+symbol+">: offset "+offset+" of "+count+"/"+totalPoints+" points");
- final int pMIdx= (offset==0) ? startIndex+count-1 : startIndex+(offset-1)%count;
- final Point pM = glyph.getPoint(pMIdx);
- final int p0Idx = startIndex + offset%count;
- final int p1Idx = startIndex + (offset+1)%count;
- final int p2Idx = startIndex + (offset+2)%count;
- final int p3Idx = startIndex + (offset+3)%count;
- System.err.println("\t pM["+pMIdx+"] "+pM);
- System.err.println("\t p0["+p0Idx+"] "+p0);
- System.err.println("\t p1["+p1Idx+"] "+p1);
- System.err.println("\t p2["+p2Idx+"] "+p2);
- System.err.println("\t p3["+p3Idx+"] "+p3);
+ System.err.println("GlyphShape<"+glyph.getID()+">: offset "+offset+" of "+count+"/"+totalPoints+" points");
+ final int point_m_idx= (offset==0) ? startIndex+count-1 : startIndex+(offset-1)%count;
+ final int point_1_idx = startIndex + (offset+1)%count;
+ final int point_2_idx = startIndex + (offset+2)%count;
+ // final int point_3_idx = startIndex + (offset+3)%count;
+ System.err.println("\t pM["+point_m_idx+"] "+point_m);
+ System.err.println("\t p0["+point_0_idx+"] "+point_0);
+ System.err.println("\t p1["+point_1_idx+"] "+point_1);
+ System.err.println("\t p2["+point_2_idx+"] "+point_2);
+ // System.err.println("\t p3["+point_3_idx+"] "+point_3);
}
if(offset == 0) {
- addShapeMoveTo(unitsPerEM, shape, p0);
- // gp.moveTo(point.x, point.y);
+ addShapeMoveTo(unitsPerEM, shape, point_0); // OK
}
-
- if( p0.endOfContour ) {
- // Branch-0: EOC ** SHALL NEVER HAPPEN **
- if( DEBUG ) { System.err.println("B0 .. end-of-contour **** EOC"); }
- shape.closeLastOutline(false);
- break;
- } else if (p0.onCurve) {
- if (p1.onCurve) {
+ if (point_0.onCurve) {
+ if (point_1.onCurve) {
// Branch-1: point.onCurve && p1.onCurve
- if( DEBUG ) { System.err.println("B1 .. line-to p0-p1"); }
-
- // s = new Line2D.Float(point.x, point.y, p1.x, p1.y);
- // gp.lineTo( p1.x, p1.y );
- addShapeLineTo(unitsPerEM, shape, p1);
+ if( PRINT_CODE ) { System.err.printf("// %03d: B1: line-to p0-p1%n", point_0_idx); }
+ addShapeLineTo(unitsPerEM, shape, point_1); // OK
offset++;
} else {
- if (p2.onCurve) {
+ if (point_2.onCurve) {
// Branch-2: point.onCurve && !p1.onCurve && p2.onCurve
- if( DEBUG ) { System.err.println("B2 .. quad-to p0-p1-p2"); }
-
- // s = new QuadCurve2D.Float( point.x, point.y, p1.x, p1.y, p2.x, p2.y);
- // gp.quadTo(p1.x, p1.y, p2.x, p2.y);
- addShapeQuadTo(unitsPerEM, shape, p1, p2);
+ if( PRINT_CODE ) { System.err.printf("// %03d: B2: quad-to p0-p1-p2%n", point_0_idx); }
+ addShapeQuadTo(unitsPerEM, shape, point_1, point_2); // OK
offset+=2;
} else {
- if (null != p3 && p3.onCurve) {
+ /** if (null != point_3 && point_3.onCurve) {
+ // Not required, handled via B4 and subsequent B6!
// Branch-3: point.onCurve && !p1.onCurve && !p2.onCurve && p3.onCurve
- if( DEBUG ) { System.err.println("B3 .. 2-quad p0-p1-p1_2, p1_2-p2-p3 **** 2QUAD"); }
- // addShapeCubicTo(shape, vertexFactory, p1, p2, p3);
- addShapeQuadTo(unitsPerEM, shape, p1, midValue(p1.x, p2.x),
- midValue(p1.y, p2.y),
- true);
- addShapeQuadTo(unitsPerEM, shape, p2, p3);
+ if( PRINT_CODE ) { System.err.printf("// %03d: B3: p0-p1-p1_2, p1_2-p2-p3 **** 2QUAD%n", point_0_idx); }
+ addShapeQuadTo(unitsPerEM, shape, point_1, midValue(point_1.x, point_2.x),
+ midValue(point_1.y, point_2.y));
+ addShapeQuadTo(unitsPerEM, shape, point_2, point_3);
offset+=3;
- } else {
+ } else */ {
// Branch-4: point.onCurve && !p1.onCurve && !p2.onCurve && !p3.onCurve
- if( DEBUG ) { System.err.println("B4 .. quad-to p0-p1-p2h **** MID"); }
-
- // s = new QuadCurve2D.Float(point.x,point.y,p1.x,p1.y,
- // midValue(p1.x, p2.x), midValue(p1.y, p2.y));
- // gp.quadTo(p1.x, p1.y, midValue(p1.x, p2.x), midValue(p1.y, p2.y));
- addShapeQuadTo(unitsPerEM, shape, p1, midValue(p1.x, p2.x),
- midValue(p1.y, p2.y),
- true);
+ if( PRINT_CODE ) { System.err.printf("// %03d: B4: quad-to p0-p1-p2h **** MID%n", point_0_idx); }
+ addShapeQuadTo(unitsPerEM, shape, point_1, midValue(point_1.x, point_2.x),
+ midValue(point_1.y, point_2.y));
offset+=2; // Skip p2 as done in Typecast
}
}
}
} else {
- if (!p1.onCurve) {
+ if (!point_1.onCurve) {
// Branch-5: !point.onCurve && !p1.onCurve
- if( DEBUG ) { System.err.println("B5 .. quad-to pMh-p0-p1h ***** MID"); }
- // s = new QuadCurve2D.Float(midValue(pM.x, point.x), midValue(pM.y, point.y),
- // point.x, point.y,
- // midValue(point.x, p1.x), midValue(point.y, p1.y));
- addShapeQuadTo(unitsPerEM, shape, p0, midValue(p0.x, p1.x),
- midValue(p0.y, p1.y), true);
+ if( PRINT_CODE ) { System.err.printf("// %03d: B5: quad-to pMh-p0-p1h ***** MID%n", point_0_idx); }
+ addShapeQuadTo(unitsPerEM, shape, point_0, midValue(point_0.x, point_1.x), // OK
+ midValue(point_0.y, point_1.y) );
offset++;
} else {
// Branch-6: !point.onCurve && p1.onCurve
- if( DEBUG ) { System.err.println("B6 .. quad-to pMh-p0-p1"); }
- // s = new QuadCurve2D.Float(midValue(pM.x, point.x), midValue(pM.y, point.y),
- // point.x, point.y, p1.x, p1.y);
- // gp.quadTo(point.x, point.y, p1.x, p1.y);
- addShapeQuadTo(unitsPerEM, shape, p0, p1);
+ if( PRINT_CODE ) { System.err.printf("// %03d: B6: quad-to pMh-p0-p1%n", point_0_idx); }
+ addShapeQuadTo(unitsPerEM, shape, point_0, point_1); // OK
offset++;
}
}
}
+ if( PRINT_CODE ) { System.err.printf("shape.closeLastOutline(false);%n%n"); }
+ shape.closeLastOutline(false);
+ startIndex = i + 1;
+ count = 0;
+ }
+ }
+ }
+
+ private static void buildShapeType2(final float unitsPerEM, final OutlineShape shape, final T2Glyph glyph) {
+ // Iterate through all of the points in the glyph. Each time we find a
+ // contour end point, add the point range to the path.
+ int startIndex = 0;
+ int count = 0;
+ final int totalPoints = glyph.getPointCount();
+ for (int i = 0; i < totalPoints; i++) {
+ count++;
+ if ( glyph.getPoint(i).endOfContour ) {
+ int offset = 0;
+ while ( offset < count ) {
+ final int point_0_idx = startIndex + offset%count;
+ final Point point_0 = glyph.getPoint(point_0_idx);
+ final Point point_1 = glyph.getPoint(startIndex + (offset+1)%count);
+ final Point point_2 = glyph.getPoint(startIndex + (offset+2)%count);
+ final Point point_3 = glyph.getPoint(startIndex + (offset+3)%count);
+ if( DEBUG ) {
+ System.err.println("GlyphShape<"+glyph.getID()+">: offset "+offset+" of "+count+"/"+totalPoints+" points");
+ final int point_1_idx = startIndex + (offset+1)%count;
+ final int point_2_idx = startIndex + (offset+2)%count;
+ final int point_3_idx = startIndex + (offset+3)%count;
+ System.err.println("\t p0["+point_0_idx+"] "+point_0);
+ System.err.println("\t p1["+point_1_idx+"] "+point_1);
+ System.err.println("\t p2["+point_2_idx+"] "+point_2);
+ System.err.println("\t p3["+point_3_idx+"] "+point_3);
+ }
+ if(offset == 0) {
+ addShapeMoveTo(unitsPerEM, shape, point_0); // OK
+ }
+ if (point_0.onCurve && point_1.onCurve) {
+ // Branch-1: point.onCurve && p1.onCurve
+ if( PRINT_CODE ) { System.err.printf("// %03d: C1: line-to p0-p1%n", point_0_idx); }
+ addShapeLineTo(unitsPerEM, shape, point_1); // OK
+ offset++;
+ } else if (point_0.onCurve && !point_1.onCurve && !point_2.onCurve && point_3.onCurve) {
+ if( PRINT_CODE ) { System.err.printf("// %03d: C2: cubic-to p0-p1-p2%n", point_0_idx); }
+ addShapeCubicTo(unitsPerEM, shape, point_0, point_2, point_3);
+ offset+=3;
+ } else {
+ System.out.println("addContourToPath case not catered for!!");
+ break;
+ }
+ }
+ if( PRINT_CODE ) { System.err.printf("shape.closeLastOutline(false);%n%n"); }
shape.closeLastOutline(false);
startIndex = i + 1;
count = 0;
@@ -198,7 +253,103 @@ public class TypecastRenderer {
}
}
- private static float midValue(final float a, final float b) {
- return a + (b - a)/2f;
+ /**
+ * Returns the mid-value of two.
+ * <p>
+ * Intentionally using integer arithmetic on unitPerEM sized values w/o rounding.
+ * </p>
+ */
+ private static int midValue(final int a, final int b) {
+ return a + (b - a)/2;
+ }
+
+ //
+ // Leaving Typecast's orig rendering loop in here, transformed to using our OutlineShape.
+ // This is now actually the same since ours has been re-aligned on 2023-02-15.
+ //
+
+ @SuppressWarnings("unused")
+ private static void buildShapeImplX(final float unitsPerEM, final OutlineShape shape, final Glyph glyph) {
+ // Iterate through all of the points in the glyph. Each time we find a
+ // contour end point, add the point range to the path.
+ int firstIndex = 0;
+ int count = 0;
+ final int totalPoints = glyph.getPointCount();
+ if (glyph instanceof T2Glyph) {
+ // addContourToPath(unitsPerEM, shape, (T2Glyph) glyph, firstIndex, count);
+ throw new RuntimeException("T2Glyph Not Yet Supported: "+glyph);
+ }
+ if( PRINT_CODE ) { System.err.printf("%n// Start Shape for Glyph %d%n", glyph.getID()); }
+ for (int i = 0; i < totalPoints; i++) {
+ count++;
+ if ( glyph.getPoint(i).endOfContour ) {
+ addContourToPathX1(unitsPerEM, shape, glyph, firstIndex, count);
+ firstIndex = i + 1;
+ count = 0;
+ }
+ }
+ if( PRINT_CODE ) { System.err.printf("// End Shape for Glyph %d%n%n", glyph.getID()); }
+ }
+ private static void addContourToPathX1(final float unitsPerEM, final OutlineShape shape, final Glyph glyph, final int startIndex, final int count) {
+ int offset = 0;
+ while ( offset < count ) {
+ final int point_0_idx = startIndex + offset%count;
+ final Point point_m = glyph.getPoint((offset==0) ? startIndex+count-1 : startIndex+(offset-1)%count);
+ final Point point_0 = glyph.getPoint(point_0_idx);
+ final Point point_1 = glyph.getPoint(startIndex + (offset+1)%count);
+ final Point point_2 = glyph.getPoint(startIndex + (offset+2)%count);
+ // final Point point_3 = offset+3 < count ? glyph.getPoint(startIndex + offset+3) : null;
+ if( DEBUG ) {
+ System.err.println("GlyphShape<"+glyph.getID()+">: offset "+offset+" of "+count+" points");
+ final int point_m_idx= (offset==0) ? startIndex+count-1 : startIndex+(offset-1)%count;
+ final int point_1_idx = startIndex + (offset+1)%count;
+ final int point_2_idx = startIndex + (offset+2)%count;
+ // final int p3Idx = startIndex + (offset+3)%count;
+ System.err.println("\t pM["+point_m_idx+"] "+point_m);
+ System.err.println("\t p0["+point_0_idx+"] "+point_0);
+ System.err.println("\t p1["+point_1_idx+"] "+point_1);
+ System.err.println("\t p2["+point_2_idx+"] "+point_2);
+ // System.err.println("\t p3["+p3Idx+"] "+point_3);
+ }
+ if(offset == 0) {
+ addShapeMoveTo(unitsPerEM, shape, point_0);
+ }
+ if (point_0.onCurve && point_1.onCurve) {
+ // Branch-1: point.onCurve && p1.onCurve
+ if( PRINT_CODE ) { System.err.printf("// %03d: B1: line-to p0-p1%n", point_0_idx); }
+ addShapeLineTo(unitsPerEM, shape, point_1);
+ offset++;
+ } else if (point_0.onCurve && !point_1.onCurve && point_2.onCurve) {
+ // Branch-2: point.onCurve && !p1.onCurve && p2.onCurve
+ if( PRINT_CODE ) { System.err.printf("// %03d: B2: quad-to p0-p1-p2%n", point_0_idx); }
+ addShapeQuadTo(unitsPerEM, shape, point_1, point_2);
+ offset+=2;
+ } else if (point_0.onCurve && !point_1.onCurve && !point_2.onCurve) {
+ // Branch-4: point.onCurve && !p1.onCurve && !p2.onCurve && !p3.onCurve
+ if( PRINT_CODE ) { System.err.printf("// %03d: B4: quad-to p0-p1-p2h **** MID%n", point_0_idx); }
+ addShapeQuadTo(unitsPerEM, shape, point_1,
+ midValue(point_1.x, point_2.x),
+ midValue(point_1.y, point_2.y));
+
+ offset+=2;
+ } else if (!point_0.onCurve && !point_1.onCurve) {
+ // Branch-5: !point.onCurve && !p1.onCurve
+ if( PRINT_CODE ) { System.err.printf("// %03d: B5: quad-to pMh-p0-p1h ***** MID%n", point_0_idx); }
+ addShapeQuadTo(unitsPerEM, shape, point_0,
+ midValue(point_0.x, point_1.x),
+ midValue(point_0.y, point_1.y) );
+ offset++;
+ } else if (!point_0.onCurve && point_1.onCurve) {
+ // Branch-6: !point.onCurve && p1.onCurve
+ if( PRINT_CODE ) { System.err.printf("// %03d: B6: quad-to pMh-p0-p1%n", point_0_idx); }
+ addShapeQuadTo(unitsPerEM, shape, point_0, point_1);
+ offset++;
+ } else {
+ System.out.println("addContourToPath case not catered for!!");
+ break;
+ }
+ }
+ if( PRINT_CODE ) { System.err.printf("shape.closeLastOutline(false);%n%n"); }
+ shape.closeLastOutline(false);
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/Glyph.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/Glyph.java
index 7b29a6c48..5bb610a1c 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/Glyph.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/Glyph.java
@@ -31,25 +31,31 @@ public abstract class Glyph {
public Glyph(final int glyph_id) {
_glyph_id = glyph_id;
}
-
+
/** Return the assigned glyph ID of this instance */
- public final int getGlyphIndex() { return _glyph_id; }
-
+ public final int getID() { return _glyph_id; }
+
public abstract void clearPointData();
- /** Return the AABBox in font-units */
+ /**
+ * Return the AABBox in font-units.
+ * <p>
+ * This is either the GlyphDescripton's min- and maximum for TTF
+ * or the calculated box over all points.
+ * </p>
+ */
public final AABBox getBBox() { return _bbox; }
-
+
/** hmtx value */
public abstract int getAdvanceWidth();
-
+
/** hmtx value */
public abstract short getLeftSideBearing();
public abstract Point getPoint(int i);
public abstract int getPointCount();
-
+
@Override
public abstract String toString();
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfDescript.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfDescript.java
index 2a8deaeeb..45d06e8cb 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfDescript.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/table/GlyfDescript.java
@@ -67,19 +67,20 @@ public abstract class GlyfDescript extends Program implements GlyphDescription {
static final byte yDual = 0x20;
final GlyfTable _parentTable;
- private int _glyphIndex;
+ private final int _glyphIndex;
private final int _numberOfContours;
- private short _xMin;
- private short _yMin;
- private short _xMax;
- private short _yMax;
+ private final short _xMin;
+ private final short _yMin;
+ private final short _xMax;
+ private final short _yMax;
GlyfDescript(
- GlyfTable parentTable,
- int glyphIndex,
- short numberOfContours,
- DataInput di) throws IOException {
+ final GlyfTable parentTable,
+ final int glyphIndex,
+ final short numberOfContours,
+ final DataInput di) throws IOException {
_parentTable = parentTable;
+ _glyphIndex = glyphIndex;
_numberOfContours = numberOfContours;
_xMin = di.readShort();
_yMin = di.readShort();
@@ -91,26 +92,32 @@ public abstract class GlyfDescript extends Program implements GlyphDescription {
return _numberOfContours;
}
+ @Override
public int getGlyphIndex() {
return _glyphIndex;
}
+ @Override
public short getXMaximum() {
return _xMax;
}
+ @Override
public short getXMinimum() {
return _xMin;
}
+ @Override
public short getYMaximum() {
return _yMax;
}
+ @Override
public short getYMinimum() {
return _yMin;
}
-
+
+ @Override
public String toString() {
return " numberOfContours: " + _numberOfContours +
"\n xMin: " + _xMin +