diff options
5 files changed, 137 insertions, 101 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/font/Font.java b/src/jogl/classes/com/jogamp/graph/font/Font.java index 36f00f628..fdef6a612 100644 --- a/src/jogl/classes/com/jogamp/graph/font/Font.java +++ b/src/jogl/classes/com/jogamp/graph/font/Font.java @@ -81,42 +81,42 @@ public interface Font { */ public interface Metrics { /** - * @return ascent in font-units to be divided by {@link #getUnitsPerEM()} + * @return ascent in font-units, sourced from `hheaTable' table. */ int getAscentFU(); /** - * @return ascent in font em-size [0..1] + * @return ascent in font em-size [0..1], sourced from `hheaTable' table. */ float getAscent(); /** - * @return descent in font-units to be divided by {@link #getUnitsPerEM()} + * @return descent in font-units, sourced from `hheaTable' table. */ int getDescentFU(); /** - * @return descend in font em-size [0..1] + * @return descend in font em-size [0..1], sourced from `hheaTable' table. */ float getDescent(); /** - * @return line-gap in font-units to be divided by {@link #getUnitsPerEM()} + * @return line-gap in font-units, sourced from `hheaTable' table. */ int getLineGapFU(); /** - * @return line-gap in font em-size [0..1] + * @return line-gap in font em-size [0..1], sourced from `hheaTable' table. */ float getLineGap(); /** - * @return max-extend in font-units to be divided by {@link #getUnitsPerEM()} + * @return max-extend in font-units, sourced from `hheaTable' table. */ int getMaxExtendFU(); /** - * @return max-extend in font em-size [0..1] + * @return max-extend in font em-size [0..1], sourced from `hheaTable' table. */ float getMaxExtend(); @@ -176,25 +176,31 @@ public interface Font { float getScale(final int funits); /** - * Return the AABBox in font-units to be divided by unitsPerEM + * Return the AABBox in font-units, borrowing internal instance. */ AABBox getBBoxFU(); /** - * Return the AABBox in font-units to be divided by unitsPerEM + * Return the AABBox in font-units, copying into given dest. * @param dest AABBox instance set to this metrics boundary in font-units * @return the given and set AABBox 'dest' in font-units */ AABBox getBBoxFU(final AABBox dest); /** + * Return the AABBox in font em-size [0..1], copying into given dest. * @param dest AABBox instance set to this metrics boundary in font em-size [0..1] * @param tmpV3 caller provided temporary 3-component vector * @return the given and set AABBox 'dest' in font em-size [0..1] */ AABBox getBBox(final AABBox dest, float[] tmpV3); - /** Return advance in font units to be divided by unitsPerEM */ + /** + * Return the AABBox in font em-size [0..1], creating a new copy. + */ + AABBox getBBox(); + + /** Return advance in font units, sourced from `hmtx` table. */ int getAdvanceFU(); /** Return advance in font em-size [0..1] */ @@ -209,10 +215,10 @@ public interface Font { int getKerningPairCount(); /** - * Returns the optional kerning inter-glyph distance within words between this glyph and the given right glyph_id in font-units to be divided by unitsPerEM + * Returns the optional kerning inter-glyph distance within words between this glyph and the given right glyph_id in font-units. * * @param right_glyphid right glyph code id - * @return font-units to be divided by unitsPerEM + * @return font-units */ int getKerningFU(final int right_glyphid); @@ -246,7 +252,7 @@ public interface Font { StringBuilder getAllNames(final StringBuilder string, final String separator); /** - * Return advance-width of given glyphID in font-units to be divided by unitsPerEM + * Return advance-width of given glyphID in font-units, sourced from `hmtx` table. * @param glyphID */ int getAdvanceWidthFU(final int glyphID); @@ -266,7 +272,17 @@ public interface Font { int getNumGlyphs(); /** - * Return line height in font-units to be divided by unitsPerEM + * Return line height in font-units, composed from `hheaTable' table entries. + * <pre> + * return abs(lineGap) + abs(descent) abs(ascent); + * </pre> + * or + * <pre> + * // lineGap negative value + * // descent positive value + * // ascent negative value + * return -1 * ( lineGap - descent + ascent ); + * </pre> */ int getLineHeightFU(); @@ -275,47 +291,89 @@ public interface Font { */ float getLineHeight(); - /** Return metric-width in font-units */ - int getMetricWidthFU(final CharSequence string); - - /** Return metric-width in font em-size */ - float getMetricWidth(final CharSequence string); - - /** Return metric-height in font-units */ - int getMetricHeightFU(final CharSequence string); - - /** Return metric-height in font em-size */ - float getMetricHeight(final CharSequence string); - - /** Return layout metric-bounds in font-units, see {@link #getMetricBounds(CharSequence, float)} */ + /** + * Returns metric-bounds in font-units. + * <p> + * Metric bounds is based on the `hmtx` table's advance of each glyph and `hheaTable' composed line height. + * </p> + * <p> + * For accurate layout consider using {@link #getGlyphBoundsFU(CharSequence)}. + * </p> + * @see #getMetricBounds(CharSequence) + * @see #getGlyphBoundsFU(CharSequence) + */ AABBox getMetricBoundsFU(final CharSequence string); - /** Return layout metric-bounds in font em-size, see {@link #getMetricBounds(CharSequence, float)} */ + /** + * Returns metric-bounds in font em-size. + * <p> + * Metric bounds is based on the `hmtx` table's advance of each glyph and `hheaTable' composed line height. + * </p> + * <p> + * For accurate layout consider using {@link #getGlyphBounds(CharSequence)}. + * </p> + * @see #getMetricBoundsFU(CharSequence) + * @see #getGlyphBounds(CharSequence) + * @see #getGlyphShapeBounds(CharSequence) + */ AABBox getMetricBounds(final CharSequence string); /** - * Return the bounding box by taking each glyph's font em-sized bounding box into account. - * @param transform optional given transform + * Returns accurate bounding box by taking each glyph's font em-sized bounding box into account. + * <p> + * Glyph bounds is based on each glyph's bounding box and `hheaTable' composed line height. + * </p> * @param string string text * @return the bounding box of the given string in font em-size [0..1] + * @see #getGlyphBoundsFU(CharSequence) + * @see #getGlyphShapeBounds(CharSequence) + * @see #getMetricBounds(CharSequence) */ - AABBox getPointsBounds(final AffineTransform transform, final CharSequence string); + AABBox getGlyphBounds(final CharSequence string); /** - * Return the bounding box by taking each glyph's font-units sized bounding box into account. - * @param transform optional given transform + * Returns accurate bounding box by taking each glyph's font-units sized bounding box into account. + * <p> + * Glyph bounds is based on each glyph's bounding box and `hheaTable' composed line height. + * </p> * @param string string text * @return the bounding box of the given string in font-units [0..1] + * @see #getGlyphBounds(CharSequence) */ - AABBox getPointsBoundsFU(final AffineTransform transform, final CharSequence string); + AABBox getGlyphBoundsFU(final CharSequence string); /** - * Return the bounding box of the given string by taking each glyph's font em-sized OutlineShape into account. + * Returns accurate bounding box by taking each glyph's font em-sized {@link OutlineShape} into account. + * <p> + * Glyph shape bounds is based on each glyph's {@link OutlineShape} and `hheaTable' composed line height. + * </p> + * <p> + * This method is only exposed to validate the produced {@link OutlineShape} against {@link #getGlyphBounds(CharSequence)}. + * </p> * @param transform optional given transform * @param string string text * @return the bounding box of the given string in font-units [0..1] + * @see #getGlyphShapeBounds(CharSequence) + * @see #getGlyphBounds(CharSequence) + * @see #getMetricBounds(CharSequence) + */ + AABBox getGlyphShapeBounds(final AffineTransform transform, final CharSequence string); + + /** + * Returns accurate bounding box by taking each glyph's font em-sized {@link OutlineShape} into account. + * <p> + * Glyph shape bounds is based on each glyph's {@link OutlineShape} and `hheaTable' composed line height. + * </p> + * <p> + * This method is only exposed to validate the produced {@link OutlineShape} against {@link #getGlyphBounds(CharSequence)}. + * </p> + * @param string string text + * @return the bounding box of the given string in font-units [0..1] + * @see #getGlyphShapeBounds(AffineTransform, CharSequence) + * @see #getGlyphBounds(CharSequence) + * @see #getMetricBounds(CharSequence) */ - AABBox getPointsBounds2(final AffineTransform transform, final CharSequence string); + AABBox getGlyphShapeBounds(final CharSequence string); boolean isPrintableChar(final char c); @@ -329,7 +387,7 @@ public interface Font { * @param transform optional given transform * @param font the target {@link Font} * @param string string text - * @return the bounding box of the given string by taking each glyph's font em-sized [0..1] OutlineShape into account. + * @return the bounding box of the given string by taking each glyph's font em-sized [0..1] {@link OutlineShape} into account. */ AABBox processString(final OutlineShape.Visitor visitor, final AffineTransform transform, final CharSequence string); @@ -346,7 +404,7 @@ public interface Font { * @param string string text * @param temp1 temporary AffineTransform storage, mandatory * @param temp2 temporary AffineTransform storage, mandatory - * @return the bounding box of the given string by taking each glyph's font em-sized [0..1] OutlineShape into account. + * @return the bounding box of the given string by taking each glyph's font em-sized [0..1] {@link OutlineShape} into account. */ AABBox processString(final OutlineShape.Visitor visitor, final AffineTransform transform, final CharSequence string, diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java index eeee14365..f5358b74b 100644 --- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java +++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java @@ -254,53 +254,13 @@ 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) ); - } - - @Override - public int getMetricWidthFU(final CharSequence string) { - int width = 0; - final int len = string.length(); - for (int i=0; i< len; i++) { - final char character = string.charAt(i); - if (character == '\n') { - width = 0; - } else { - final Glyph glyph = getGlyph(getGlyphID(character)); - width += glyph.getAdvanceFU(); - } - } - return width; - } - - @Override - public float getMetricHeight(final CharSequence string) { - return metrics.getScale( getMetricHeightFU(string) ); - } - - @Override - public int getMetricHeightFU(final CharSequence string) { - int height = 0; - - for (int i=0; i<string.length(); i++) { - final char character = string.charAt(i); - if (character != ' ') { - final Glyph glyph = getGlyph(getGlyphID(character)); - height = (int)Math.ceil(Math.max(glyph.getBBoxFU().getHeight(), height)); - } - } - return height; - } - - @Override public AABBox getMetricBounds(final CharSequence string) { return getMetricBoundsFU(string).scale2(1.0f/metrics.getUnitsPerEM(), new float[3]); } @@ -310,6 +270,7 @@ class TypecastFont implements Font { if (null == string || 0 == string.length() ) { return new AABBox(); } + final AABBox res = new AABBox(); final int charCount = string.length(); final int lineHeight = getLineHeightFU(); @@ -322,23 +283,28 @@ class TypecastFont implements Font { if (character == '\n') { advanceTotal = 0; y -= lineHeight; - continue; + } else if (character == ' ') { + advanceTotal += getAdvanceWidthFU(Glyph.ID_SPACE); + } else { + advanceTotal += getAdvanceWidthFU( getGlyphID( character ) ); } - advanceTotal += getAdvanceWidthFU( getGlyphID( character ) ); + res.resize(advanceTotal, y, 0f); } - if (advanceTotal > 0) { + if( 0 < advanceTotal ) { + // add one line for current non '\n' terminated y -= lineHeight; + res.resize(advanceTotal, y, 0f); } - return new AABBox(0,y,0, advanceTotal,0,0); + return res; } @Override - public AABBox getPointsBounds(final AffineTransform transform, final CharSequence string) { - return getPointsBoundsFU(transform, string).scale2(1.0f/metrics.getUnitsPerEM(), new float[3]); + public AABBox getGlyphBounds(final CharSequence string) { + return getGlyphBoundsFU(string).scale2(1.0f/metrics.getUnitsPerEM(), new float[3]); } @Override - public AABBox getPointsBoundsFU(final AffineTransform transform, final CharSequence string) { + public AABBox getGlyphBoundsFU(final CharSequence string) { if (null == string || 0 == string.length() ) { return new AABBox(); } @@ -366,11 +332,7 @@ class TypecastFont implements Font { left_glyph = null; } else { // reset transform - if( null != transform ) { - temp1.setTransform(transform); - } else { - temp1.setToIdentity(); - } + temp1.setToIdentity(); final int glyph_id = getGlyphID(character); final Font.Glyph glyph = getGlyph(glyph_id); final OutlineShape glyphShape = glyph.getShape(); @@ -391,7 +353,11 @@ class TypecastFont implements Font { } @Override - public AABBox getPointsBounds2(final AffineTransform transform, final CharSequence string) { + public AABBox getGlyphShapeBounds(final CharSequence string) { + return getGlyphShapeBounds(null, string); + } + @Override + public AABBox getGlyphShapeBounds(final AffineTransform transform, final CharSequence string) { if (null == string || 0 == string.length() ) { return new AABBox(); } diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java index 9db8fc6d5..12d492f6e 100644 --- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java +++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java @@ -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 @@ -187,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/ot/Glyph.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/Glyph.java index 03a2394d9..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 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/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java index 4d62cb2b1..59514375c 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java @@ -95,7 +95,7 @@ public class LabelButton extends RoundButton { // Precompute text-box size .. guessing pixelSize final float lw = width * ( 1f - spacingX ) ; final float lh = height * ( 1f - spacingY ) ; - final AABBox lbox0_em = label.font.getPointsBounds(null, label.text); + final AABBox lbox0_em = label.font.getGlyphBounds(label.text); final float lsx = lw / lbox0_em.getWidth(); final float lsy = lh / lbox0_em.getHeight(); final float lScale = lsx < lsy ? lsx : lsy; |