summaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/com/jogamp/graph
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-02-10 14:20:35 +0100
committerSven Gothel <[email protected]>2023-02-10 14:20:35 +0100
commitfeb8de27f848b5213423389cf0e19cbd88095682 (patch)
treeec7051b6fec0a78a4f78b1958a3f7999a063c1d9 /src/jogl/classes/com/jogamp/graph
parentbc951476c67282d9676f33ee25fb0f697a4dbe45 (diff)
Font/Graph, {Font, Glyph}/Typecast: Add kerning and expose values in original font-units (FU) to have them scaled later ( fu * pixelScale / unitsPerEM )
Scaling from font-units (funits, or FU) is now performed by the renderer itself, i.e. applying the scale-factor 'fontPixelSize / font.getMetrics().getUnitsPerEM()' to the PMV matrix to render the whole graph GLRegion. This finally provides proper device and resolution independent font utilization. Further, preliminary kerning has been added. +++ Also ... TypecastFont: - getGlyphID(..) getGlyph(..) enforce symbol mapping to Glyph.ID_SPACE Glyph.ID_CR, as some fonts ave an erroneous cmap (FreeSerif-Regular) - add getKerning(..) TODO: Add binary search - Set TypecastFont.USE_PRESCALED_ADVANCE := false, i.e. dropping all prescaled pixel-sized advance values mapped to font pixel-size as we utilize font-units only for later uniform scaling. - Drop virtual getPixelSize() and add static FontScale.toPixels(..) - Add fullString() for debugging purposed, including some font tables
Diffstat (limited to 'src/jogl/classes/com/jogamp/graph')
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java119
-rw-r--r--src/jogl/classes/com/jogamp/graph/font/Font.java250
-rw-r--r--src/jogl/classes/com/jogamp/graph/font/FontScale.java70
3 files changed, 317 insertions, 122 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java
index 344e1e51f..5aa2be258 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java
@@ -74,41 +74,41 @@ public class TextRegionUtil {
/**
* Visit each {@link Font.Glyph}'s {@link OutlineShape} with the given {@link ShapeVisitor}
- * additionally passing the progressed {@link AffineTransform}.
- * The latter reflects the given font metric, pixelSize and hence character position.
+ * additionally passing the progressed {@link AffineTransform} in font-units.
+ * The latter reflects the given font metric in font-units and hence character position.
* @param visitor
* @param transform optional given transform
* @param font the target {@link Font}
- * @param pixelSize Use {@link Font#getPixelSize(float, float)} for resolution correct pixel-size.
* @param str string text
* @param temp1 temporary AffineTransform storage, mandatory, will be passed to {@link ShapeVisitor#visit(OutlineShape, AffineTransform)} and can be modified.
* @param temp2 temporary AffineTransform storage, mandatory, can be re-used in {@link ShapeVisitor#visit(OutlineShape, AffineTransform)} by user code.
*/
public static void processString(final ShapeVisitor visitor, final AffineTransform transform,
- final Font font, final float pixelSize, final CharSequence str,
+ final Font font, final CharSequence str,
final AffineTransform temp1, final AffineTransform temp2) {
final int charCount = str.length();
// region.setFlipped(true);
final Font.Metrics metrics = font.getMetrics();
- final float lineHeight = font.getLineHeight(pixelSize);
+ final int lineHeight = font.getLineHeightFU();
- final float scale = metrics.getScale(pixelSize);
-
- float y = 0;
- float advanceTotal = 0;
+ int y = 0;
+ int advanceTotal = 0;
+ char left_character = 0;
+ int left_glyphid = 0;
for(int i=0; i< charCount; i++) {
final char character = str.charAt(i);
if( '\n' == character ) {
y -= lineHeight;
advanceTotal = 0;
+ left_glyphid = 0;
+ left_character = 0;
} else if (character == ' ') {
- advanceTotal += font.getAdvanceWidth(Glyph.ID_SPACE, pixelSize);
+ advanceTotal += font.getAdvanceWidthFU(Glyph.ID_SPACE);
+ left_glyphid = 0;
+ left_character = character;
} else {
- if(Region.DEBUG_INSTANCE) {
- System.err.println("XXXXXXXXXXXXXXx char: "+character+", scale: "+scale+"; translate: "+advanceTotal+", "+y);
- }
// reset transform
if( null != transform ) {
temp1.setTransform(transform);
@@ -116,51 +116,65 @@ public class TextRegionUtil {
temp1.setToIdentity();
}
temp1.translate(advanceTotal, y, temp2);
- temp1.scale(scale, scale, temp2);
final Font.Glyph glyph = font.getGlyph(character);
final OutlineShape glyphShape = glyph.getShape();
if( null == glyphShape ) {
+ left_glyphid = 0;
continue;
}
visitor.visit(glyphShape, temp1);
-
- advanceTotal += glyph.getAdvance(pixelSize, true);
+ final int right_glyphid = glyph.getID();
+ final int kern = font.getKerningFU(left_glyphid, right_glyphid);
+ final int advance = glyph.getAdvanceFU();
+ advanceTotal += advance + kern;
+ if( Region.DEBUG_INSTANCE && 0 != left_character && kern > 0f ) {
+ System.err.println(": '"+left_character+"'/"+left_glyphid+" -> '"+character+"'/"+right_glyphid+
+ ": a "+advance+"px + k ["+kern+"em, "+kern+"px = "+(advance+kern)+"px -> "+advanceTotal+"px, y "+y);
+ }
+ // advanceTotal += glyph.getAdvance(pixelSize, true)
+ // + font.getKerning(left_glyphid, right_glyphid);
+ left_glyphid = right_glyphid;
+ left_character = character;
}
}
}
/**
- * Add the string in 3D space w.r.t. the font and pixelSize at the end of the {@link GLRegion}.
+ * Add the string in 3D space w.r.t. the font using font-units at the end of the {@link GLRegion}.
+ * <p>
+ * The resulting GLRegion should be scaled by the chosen pixelSize of the font divided by the font's unitsPerEM.
+ * </p>
* @param region the {@link GLRegion} sink
* @param vertexFactory vertex impl factory {@link Factory}
* @param font the target {@link Font}
- * @param pixelSize Use {@link Font#getPixelSize(float, float)} for resolution correct pixel-size.
* @param str string text
* @param rgbaColor if {@link Region#hasColorChannel()} RGBA color must be passed, otherwise value is ignored.
* @param temp1 temporary AffineTransform storage, mandatory
* @param temp2 temporary AffineTransform storage, mandatory
*/
public static void addStringToRegion(final GLRegion region, final Factory<? extends Vertex> vertexFactory,
- final Font font, final float pixelSize, final CharSequence str, final float[] rgbaColor,
+ final Font font, final CharSequence str, final float[] rgbaColor,
final AffineTransform temp1, final AffineTransform temp2) {
final ShapeVisitor visitor = new ShapeVisitor() {
+ @Override
public final void visit(final OutlineShape shape, final AffineTransform t) {
region.addOutlineShape(shape, t, region.hasColorChannel() ? rgbaColor : null);
} };
- processString(visitor, null, font, pixelSize, str, temp1, temp2);
+ processString(visitor, null, font, str, temp1, temp2);
}
/**
- * Render the string in 3D space w.r.t. the font and pixelSize
- * using a cached {@link GLRegion} for reuse.
+ * Render the string in 3D space w.r.t. the font using font-units at the end of an internally cached {@link GLRegion}.
+ * <p>
+ * The resulting GLRegion should be scaled by the chosen pixelSize of the font divided by the font's unitsPerEM.
+ * </p>
* <p>
* Cached {@link GLRegion}s will be destroyed w/ {@link #clear(GL2ES2)} or to free memory.
* </p>
* @param gl the current GL state
* @param renderer TODO
* @param font {@link Font} to be used
- * @param pixelSize Use {@link Font#getPixelSize(float, float)} for resolution correct pixel-size.
* @param str text to be rendered
* @param rgbaColor if {@link Region#hasColorChannel()} RGBA color must be passed, otherwise value is ignored.
* @param sampleCount desired multisampling sample count for msaa-rendering.
@@ -168,34 +182,35 @@ public class TextRegionUtil {
* @throws Exception if TextRenderer not initialized
*/
public void drawString3D(final GL2ES2 gl,
- final RegionRenderer renderer, final Font font, final float pixelSize,
- final CharSequence str, final float[] rgbaColor, final int[/*1*/] sampleCount) {
+ final RegionRenderer renderer, final Font font, final CharSequence str,
+ final float[] rgbaColor, final int[/*1*/] sampleCount) {
if( !renderer.isInitialized() ) {
throw new GLException("TextRendererImpl01: not initialized!");
}
final int special = 0;
- GLRegion region = getCachedRegion(font, str, pixelSize, special);
+ GLRegion region = getCachedRegion(font, str, special);
if(null == region) {
region = GLRegion.create(renderModes, null);
- addStringToRegion(region, renderer.getRenderState().getVertexFactory(), font, pixelSize, str, rgbaColor, tempT1, tempT2);
- addCachedRegion(gl, font, str, pixelSize, special, region);
+ addStringToRegion(region, renderer.getRenderState().getVertexFactory(), font, str, rgbaColor, tempT1, tempT2);
+ addCachedRegion(gl, font, str, special, region);
}
region.draw(gl, renderer, sampleCount);
}
/**
- * Render the string in 3D space w.r.t. the font and pixelSize
- * using a temporary {@link GLRegion}, which will be destroyed afterwards.
+ * Render the string in 3D space w.r.t. the font using font-units at the end of an internally temporary {@link GLRegion}.
+ * <p>
+ * The resulting GLRegion should be scaled by the chosen pixelSize of the font divided by the font's unitsPerEM.
+ * </p>
* <p>
* In case of a multisampling region renderer, i.e. {@link Region#VBAA_RENDERING_BIT}, recreating the {@link GLRegion}
* is a huge performance impact.
- * In such case better use {@link #drawString3D(GL2ES2, GLRegion, RegionRenderer, Font, float, CharSequence, float[], int[], AffineTransform, AffineTransform)}
+ * In such case better use {@link #drawString3D(GL2ES2, GLRegion, RegionRenderer, Font, CharSequence, float[], int[], AffineTransform, AffineTransform)}
* instead.
* </p>
* @param gl the current GL state
* @param renderModes TODO
* @param font {@link Font} to be used
- * @param pixelSize Use {@link Font#getPixelSize(float, float)} for resolution correct pixel-size.
* @param str text to be rendered
* @param rgbaColor if {@link Region#hasColorChannel()} RGBA color must be passed, otherwise value is ignored.
* @param sampleCount desired multisampling sample count for msaa-rendering.
@@ -205,24 +220,26 @@ public class TextRegionUtil {
* @throws Exception if TextRenderer not initialized
*/
public static void drawString3D(final GL2ES2 gl, final int renderModes,
- final RegionRenderer renderer, final Font font, final float pixelSize,
- final CharSequence str, final float[] rgbaColor, final int[/*1*/] sampleCount,
- final AffineTransform temp1, final AffineTransform temp2) {
+ final RegionRenderer renderer, final Font font, final CharSequence str,
+ final float[] rgbaColor, final int[/*1*/] sampleCount, final AffineTransform temp1,
+ final AffineTransform temp2) {
if(!renderer.isInitialized()){
throw new GLException("TextRendererImpl01: not initialized!");
}
final GLRegion region = GLRegion.create(renderModes, null);
- addStringToRegion(region, renderer.getRenderState().getVertexFactory(), font, pixelSize, str, rgbaColor, temp1, temp2);
+ addStringToRegion(region, renderer.getRenderState().getVertexFactory(), font, str, rgbaColor, temp1, temp2);
region.draw(gl, renderer, sampleCount);
region.destroy(gl);
}
/**
- * Render the string in 3D space w.r.t. the font and pixelSize
- * using the given {@link GLRegion}, which will {@link GLRegion#clear(GL2ES2) cleared} beforehand.
+ * Render the string in 3D space w.r.t. the font using font-units at the end of the given {@link GLRegion},
+ * which will {@link GLRegion#clear(GL2ES2) cleared} beforehand.
+ * <p>
+ * The resulting GLRegion should be scaled by the chosen pixelSize of the font divided by the font's unitsPerEM.
+ * </p>
* @param gl the current GL state
* @param font {@link Font} to be used
- * @param pixelSize Use {@link Font#getPixelSize(float, float)} for resolution correct pixel-size.
* @param str text to be rendered
* @param rgbaColor if {@link Region#hasColorChannel()} RGBA color must be passed, otherwise value is ignored.
* @param sampleCount desired multisampling sample count for msaa-rendering.
@@ -232,14 +249,14 @@ public class TextRegionUtil {
* @throws Exception if TextRenderer not initialized
*/
public static void drawString3D(final GL2ES2 gl, final GLRegion region, final RegionRenderer renderer,
- final Font font, final float pixelSize, final CharSequence str,
- final float[] rgbaColor, final int[/*1*/] sampleCount,
- final AffineTransform temp1, final AffineTransform temp2) {
+ final Font font, final CharSequence str, final float[] rgbaColor,
+ final int[/*1*/] sampleCount, final AffineTransform temp1,
+ final AffineTransform temp2) {
if(!renderer.isInitialized()){
throw new GLException("TextRendererImpl01: not initialized!");
}
region.clear(gl);
- addStringToRegion(region, renderer.getRenderState().getVertexFactory(), font, pixelSize, str, rgbaColor, temp1, temp2);
+ addStringToRegion(region, renderer.getRenderState().getVertexFactory(), font, str, rgbaColor, temp1, temp2);
region.draw(gl, renderer, sampleCount);
}
@@ -297,13 +314,13 @@ public class TextRegionUtil {
}
}
- protected final GLRegion getCachedRegion(final Font font, final CharSequence str, final float pixelSize, final int special) {
- return stringCacheMap.get(getKey(font, str, pixelSize, special));
+ protected final GLRegion getCachedRegion(final Font font, final CharSequence str, final int special) {
+ return stringCacheMap.get(getKey(font, str, special));
}
- protected final void addCachedRegion(final GL2ES2 gl, final Font font, final CharSequence str, final float pixelSize, final int special, final GLRegion glyphString) {
+ protected final void addCachedRegion(final GL2ES2 gl, final Font font, final CharSequence str, final int special, final GLRegion glyphString) {
if ( 0 != getCacheLimit() ) {
- final String key = getKey(font, str, pixelSize, special);
+ final String key = getKey(font, str, special);
final GLRegion oldRegion = stringCacheMap.put(key, glyphString);
if ( null == oldRegion ) {
// new entry ..
@@ -313,8 +330,8 @@ public class TextRegionUtil {
}
}
- protected final void removeCachedRegion(final GL2ES2 gl, final Font font, final CharSequence str, final int pixelSize, final int special) {
- final String key = getKey(font, str, pixelSize, special);
+ protected final void removeCachedRegion(final GL2ES2 gl, final Font font, final CharSequence str, final int special) {
+ final String key = getKey(font, str, special);
final GLRegion region = stringCacheMap.remove(key);
if(null != region) {
region.destroy(gl);
@@ -332,10 +349,10 @@ public class TextRegionUtil {
}
}
- protected final String getKey(final Font font, final CharSequence str, final float pixelSize, final int special) {
+ protected final String getKey(final Font font, final CharSequence str, final int special) {
final StringBuilder sb = new StringBuilder();
return font.getName(sb, Font.NAME_UNIQUNAME)
- .append(".").append(str.hashCode()).append(".").append(Float.floatToIntBits(pixelSize)).append(special).toString();
+ .append(".").append(str.hashCode()).append(".").append(special).toString();
}
/** Default cache limit, see {@link #setCacheLimit(int)} */
diff --git a/src/jogl/classes/com/jogamp/graph/font/Font.java b/src/jogl/classes/com/jogamp/graph/font/Font.java
index 597a7e76f..9f25b5481 100644
--- a/src/jogl/classes/com/jogamp/graph/font/Font.java
+++ b/src/jogl/classes/com/jogamp/graph/font/Font.java
@@ -37,7 +37,7 @@ import com.jogamp.opengl.math.geom.AABBox;
* TrueType Font Specification:
* <ul>
* <li>http://www.freetype.org/freetype2/documentation.html</li>
- * <li>http://developer.apple.com/fonts/ttrefman/rm06/Chap6.html</li>
+ * <li>https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6.html</li>
* <li>http://www.microsoft.com/typography/SpecificationsOverview.mspx</li>
* <li>http://www.microsoft.com/typography/otspec/</li>
* </ul>
@@ -76,20 +76,54 @@ public interface Font {
* Depending on the font's direction, horizontal or vertical,
* the following tables shall be used:
*
- * Vertical http://developer.apple.com/fonts/TTRefMan/RM06/Chap6vhea.html
- * Horizontal http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html
+ * Vertical https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6vhea.html
+ * Horizontal https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6hhea.html
*/
public interface Metrics {
- float getAscent(final float pixelSize);
- float getDescent(final float pixelSize);
- float getLineGap(final float pixelSize);
- float getMaxExtend(final float pixelSize);
- float getScale(final float pixelSize);
+ /**
+ * @return ascent in font-units to be divided by {@link #getUnitsPerEM()}
+ */
+ int getAscentFU();
+
+ /**
+ * @return descent in font-units to be divided by {@link #getUnitsPerEM()}
+ */
+ int getDescentFU();
+
+ /**
+ * @return line-gap in font-units to be divided by {@link #getUnitsPerEM()}
+ */
+ int getLineGapFU();
+
+ /**
+ * @return max-extend in font-units to be divided by {@link #getUnitsPerEM()}
+ */
+ int getMaxExtendFU();
+
+ /** Returns the font's units per EM from the 'head' table. One em square covers one glyph. */
+ int getUnitsPerEM();
+
+ /**
+ * Return fractional font em-size [0..1], i.e. funits divided by {@link #getUnitsPerEM()}, i.e.
+ * <pre>
+ * return funits / head.unitsPerEM;
+ * </pre>
+ * @param funits smallest font unit, where {@link #getUnitsPerEM()} square covers whole glyph
+ * @return fractional font em-size [0..1]
+ */
+ float getScale(final int funits);
+
+ /**
+ * @param dest AABBox instance set to this metrics boundary in font-units
+ * @return the given and set AABBox 'dest' in font units
+ */
+ AABBox getBBox(final AABBox dest);
+
/**
* @param dest AABBox instance set to this metrics boundary w/ given pixelSize
- * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link Font#getPixelSize(float, float)}
+ * @param pixelSize pixel-size of font, for resolution correct pixel-size use {@link FontScale#toPixels(float, float)}
* @param tmpV3 caller provided temporary 3-component vector
- * @return the given and set AABBox 'dest'
+ * @return the given and set AABBox 'dest' in pixel size
*/
AABBox getBBox(final AABBox dest, final float pixelSize, final float[] tmpV3);
}
@@ -108,118 +142,192 @@ public interface Font {
public static final int ID_CR = 2;
public static final int ID_SPACE = 3;
- public Font getFont();
- public char getSymbol();
- public short getID();
- public AABBox getBBox();
+ Font getFont();
+ char getSymbol();
+ int getID();
+
/**
- *
- * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link Font#getPixelSize(float, float)}
- * @return
+ * Return fractional font em-size [0..1], i.e. funits divided by {@link #getUnitsPerEM()}, i.e.
+ * <pre>
+ * return funits / head.unitsPerEM;
+ * </pre>
+ * @param funits smallest font unit, where {@link #getUnitsPerEM()} square covers whole glyph
+ * @return fractional font em-size [0..1]
*/
- public float getScale(final float pixelSize);
+ float getScale(final int funits);
+
/**
* @param dest AABBox instance set to this metrics boundary w/ given pixelSize
- * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link Font#getPixelSize(float, float)}
+ * @param pixelSize pixel-size of font, for resolution correct pixel-size use {@link FontScale#toPixels(float, float)}
* @param tmpV3 caller provided temporary 3-component vector
- * @return the given and set AABBox 'dest'
+ * @return the given and set AABBox 'dest' in pixel size
+ */
+ AABBox getBBox(final AABBox dest, final float pixelSize, float[] tmpV3);
+
+ /**
+ * Return the AABBox in font-units to be divided by unitsPerEM
+ * @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-units to be divided by unitsPerEM
*/
- public AABBox getBBox(final AABBox dest, final float pixelSize, float[] tmpV3);
+ AABBox getBBoxFU();
+
+ /** Return advance in font units to be divided by unitsPerEM */
+ int getAdvanceFU();
+
+ /** Return advance in font em-size [0..1] */
+ float getAdvance();
+
/**
- *
- * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link Font#getPixelSize(float, float)}
- * @param useFrationalMetrics
- * @return
+ * @param pixelSize pixel-size of font, for resolution correct pixel-size use {@link FontScale#toPixels(float, float)}
+ * @return pixel size of advance
*/
- public float getAdvance(final float pixelSize, boolean useFrationalMetrics);
- public OutlineShape getShape();
- public int hashCode();
+ float getAdvance(final float pixelSize);
+
+ OutlineShape getShape();
+
+ @Override
+ int hashCode();
}
- public String getName(final int nameIndex);
- public StringBuilder getName(final StringBuilder string, final int nameIndex);
+ String getName(final int nameIndex);
+ StringBuilder getName(final StringBuilder string, final int nameIndex);
/** Shall return the family and subfamily name, separated a dash.
* <p>{@link #getName(StringBuilder, int)} w/ {@link #NAME_FAMILY} and {@link #NAME_SUBFAMILY}</p>
* <p>Example: "{@code Ubuntu-Regular}"</p> */
- public StringBuilder getFullFamilyName(final StringBuilder buffer);
+ StringBuilder getFullFamilyName(final StringBuilder buffer);
+
+ StringBuilder getAllNames(final StringBuilder string, final String separator);
- public StringBuilder getAllNames(final StringBuilder string, final String separator);
+ /**
+ *
+ * @param glyphID
+ * @param pixelSize pixel-size of font, for resolution correct pixel-size use {@link FontScale#toPixels(float, float)}
+ * @return pixel size of advance width
+ */
+ float getAdvanceWidth(final int glyphID, final float pixelSize);
/**
- * <pre>
- Font Scale Formula:
- inch: 25.4 mm
- pointSize: [point] = [1/72 inch]
-
- [1] Scale := pointSize * resolution / ( 72 points per inch * units_per_em )
- [2] PixelSize := pointSize * resolution / ( 72 points per inch )
- [3] Scale := PixelSize / units_per_em
- * </pre>
- * @param fontSize in point-per-inch
- * @param resolution display resolution in dots-per-inch
- * @return pixel-per-inch, pixelSize scale factor for font operations.
+ * Return advance-width of given glyphID in font em-size [0..1]
+ * @param glyphID
*/
- public float getPixelSize(final float fontSize /* points per inch */, final float resolution);
+ float getAdvanceWidth(final int glyphID);
/**
- *
+ * Return advance-width of given glyphID in font-units to be divided by unitsPerEM
* @param glyphID
- * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link #getPixelSize(float, float)}
- * @return
*/
- public float getAdvanceWidth(final int glyphID, final float pixelSize);
- public Metrics getMetrics();
- public Glyph getGlyph(final char symbol);
- public int getNumGlyphs();
+ int getAdvanceWidthFU(final int glyphID);
/**
+ * Returns the optional kerning inter-glyph distance within words in fractional font em-size [0..1].
*
- * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link #getPixelSize(float, float)}
- * @return
+ * @param left_glyphid left glyph code id
+ * @param right_glyphid right glyph code id
+ * @return fractional font em-size distance [0..1]
*/
- public float getLineHeight(final float pixelSize);
+ float getKerning(final int left_glyphid, final int right_glyphid);
+
+ /**
+ * Returns the optional kerning inter-glyph distance within words in fractional font-units to be divided by unitsPerEM
+ *
+ * @param left_glyphid left glyph code id
+ * @param right_glyphid right glyph code id
+ * @return font-units to be divided by unitsPerEM
+ */
+ int getKerningFU(final int left_glyphid, final int right_glyphid);
+
+ Metrics getMetrics();
+ int getGlyphID(final char symbol);
+ Glyph getGlyph(final char symbol);
+ int getNumGlyphs();
+
+ /**
+ *
+ * @param pixelSize pixel-size of font, for resolution correct pixel-size use {@link FontScale#toPixels(float, float)}
+ * @return pixel size of line height
+ */
+ float getLineHeight(final float pixelSize);
+
+ /**
+ * Return line height in font em-size [0..1]
+ */
+ float getLineHeight();
+
+ /**
+ * Return line height in font-units to be divided by unitsPerEM
+ */
+ int getLineHeightFU();
+
/**
*
* @param string
- * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link #getPixelSize(float, float)}
- * @return
+ * @param pixelSize pixel-size of font, for resolution correct pixel-size use {@link FontScale#toPixels(float, float)}
+ * @return pixel size of metric width
*/
- public float getMetricWidth(final CharSequence string, final float pixelSize);
+ float getMetricWidth(final CharSequence string, final float pixelSize);
+
+ /** Return metric-width in font em-size */
+ float getMetricWidth(final CharSequence string);
+
+ /** Return metric-width in font-units */
+ int getMetricWidthFU(final CharSequence string);
+
/**
*
* @param string
- * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link #getPixelSize(float, float)}
- * @param tmp
- * @return
+ * @param pixelSize pixel-size of font, for resolution correct pixel-size use {@link FontScale#toPixels(float, float)}
+ * @return pixel size of metric height
*/
- public float getMetricHeight(final CharSequence string, final float pixelSize, final AABBox tmp);
+ float getMetricHeight(final CharSequence string, final float pixelSize);
+
+ /** Return metric-height in font em-size */
+ float getMetricHeight(final CharSequence string);
+
+ /** Return metric-height in font-units */
+ int getMetricHeightFU(final CharSequence string);
+
/**
* Return the <i>layout</i> bounding box as computed by each glyph's metrics.
- * The result is not pixel correct, bit reflects layout specific metrics.
+ * The result is not pixel correct, but reflects layout specific metrics.
* <p>
* See {@link #getPointsBounds(AffineTransform, CharSequence, float, AffineTransform, AffineTransform)} for pixel correct results.
* </p>
* @param string string text
- * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link #getPixelSize(float, float)}
+ * @param pixelSize pixel-size of font, for resolution correct pixel-size use {@link FontScale#toPixels(float, float)}
*/
- public AABBox getMetricBounds(final CharSequence string, final float pixelSize);
+ AABBox getMetricBounds(final CharSequence string, final float pixelSize);
+
+ /** Return layout metric-bounds in font em-size, see {@link #getMetricBounds(CharSequence, float)} */
+ AABBox getMetricBounds(final CharSequence string);
+
+ /** Return layout metric-bounds in font-units, see {@link #getMetricBounds(CharSequence, float)} */
+ AABBox getMetricBoundsFU(final CharSequence string);
/**
* Return the bounding box by taking each glyph's point-based bounding box into account.
* @param transform optional given transform
* @param string string text
- * @param pixelSize Use <code>pointSize * resolution</code> for resolution correct pixel-size, see {@link #getPixelSize(float, float)}
- * @param temp1 temporary AffineTransform storage, mandatory
- * @param temp2 temporary AffineTransform storage, mandatory
+ * @param pixelSize pixel-size of font, for resolution correct pixel-size use {@link FontScale#toPixels(float, float)}
*/
- public AABBox getPointsBounds(final AffineTransform transform, final CharSequence string, final float pixelSize,
- final AffineTransform temp1, final AffineTransform temp2);
+ AABBox getPointsBounds(final AffineTransform transform, final CharSequence string, final float pixelSize);
+
+ AABBox getPointsBounds(final AffineTransform transform, final CharSequence string);
- public boolean isPrintableChar(final char c);
+ AABBox getPointsBoundsFU(final AffineTransform transform, final CharSequence string);
+
+ boolean isPrintableChar(final char c);
/** Shall return {@link #getFullFamilyName()} */
@Override
public String toString();
+
+ /** Return all font details as string. */
+ String fullString();
}
diff --git a/src/jogl/classes/com/jogamp/graph/font/FontScale.java b/src/jogl/classes/com/jogamp/graph/font/FontScale.java
new file mode 100644
index 000000000..a0f2ef4e0
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/graph/font/FontScale.java
@@ -0,0 +1,70 @@
+package com.jogamp.graph.font;
+
+/**
+ * Simple static font scale methods for unit conversion.
+ */
+public class FontScale {
+ /**
+ * Converts typical font size in points (per-inch) and screen resolution in dpi to font size in pixels (per-inch),
+ * which can be used for pixel-size font scaling operations.
+ * <p>
+ * Note that 1em == size of the selected font.<br/>
+ * In case the pixel per em size is required (advance etc),
+ * the resulting pixel-size (per-inch) of this method shall be used if rendering directly into the screen resolution!
+ * </p>
+ * <pre>
+ Font Scale Formula:
+ 1 inch = 25.4 mm
+
+ 1 inch = 72 points
+ pointSize: [point] = [1/72 inch]
+
+ [1] Scale := pointSize * resolution / ( 72 points per inch * units_per_em )
+ [2] PixelSize := pointSize * resolution / ( 72 points per inch )
+ [3] Scale := PixelSize / units_per_em
+ * </pre>
+ * @param font_sz_pt in points (per-inch)
+ * @param res_dpi display resolution in dots-per-inch
+ * @return pixel-per-inch, pixelSize scale factor for font operations.
+ * @see #toPixels2(float, float)
+ */
+ public static float toPixels(final float font_sz_pt /* points per inch */, final float res_dpi /* dots per inch */) {
+ return ( font_sz_pt / 72f /* points per inch */ ) * res_dpi;
+ }
+
+ /**
+ * Converts typical font size in points-per-inch and screen resolution in points-per-mm to font size in pixels (per-inch),
+ * which can be used for pixel-size font scaling operations.
+ *
+ * @param font_sz_pt in points (per-inch)
+ * @param res_ppmm display resolution in dots-per-mm
+ * @return pixel-per-inch, pixelSize scale factor for font operations.
+ * @see #toPixels(float, float)
+ */
+ public static float toPixels2(final float font_sz_pt /* points per inch */, final float res_ppmm /* pixels per mm */) {
+ return ( font_sz_pt / 72f /* points per inch */ ) * ( res_ppmm * 25.4f /* mm per inch */ ) ;
+ }
+
+ /**
+ * Converts [1/mm] to [1/inch] in place
+ * @param ppmm float[2] [1/mm] value
+ * @return return [1/inch] value
+ */
+ public static float[/*2*/] perMMToPerInch(final float[/*2*/] ppmm) {
+ ppmm[0] *= 25.4f;
+ ppmm[1] *= 25.4f;
+ return ppmm;
+ }
+
+ /**
+ * Converts [1/mm] to [1/inch] into res storage
+ * @param ppmm float[2] [1/mm] value
+ * @param res the float[2] result storage
+ * @return return [1/inch] value, i.e. the given res storage
+ */
+ public static float[/*2*/] ppmmToPPI(final float[/*2*/] ppmm, final float[/*2*/] res) {
+ res[0] = ppmm[0] * 25.4f;
+ res[1] = ppmm[1] * 25.4f;
+ return res;
+ }
+}