aboutsummaryrefslogtreecommitdiffstats
path: root/src
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
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')
-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
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java362
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java185
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java55
-rw-r--r--src/newt/classes/com/jogamp/newt/opengl/util/NEWTDemoListener.java21
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/TestFontsNEWT00.java58
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java9
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java6
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWTBugXXXX.java6
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java22
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java5
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo.java26
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java123
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java12
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/LabelButton.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java3
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java9
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java11
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java13
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtReparentingKeyAdapter.java6
22 files changed, 1019 insertions, 354 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;
+ }
+}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
index b3c1885d4..885261bf9 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
@@ -34,6 +34,10 @@ import jogamp.graph.font.typecast.ot.table.CmapIndexEntry;
import jogamp.graph.font.typecast.ot.table.CmapTable;
import jogamp.graph.font.typecast.ot.table.HdmxTable;
import jogamp.graph.font.typecast.ot.table.ID;
+import jogamp.graph.font.typecast.ot.table.KernSubtableFormat0;
+import jogamp.graph.font.typecast.ot.table.KernTable;
+import jogamp.graph.font.typecast.ot.table.KerningPair;
+import jogamp.graph.font.typecast.ot.table.PostTable;
import com.jogamp.common.util.IntObjectHashMap;
import com.jogamp.graph.curve.OutlineShape;
@@ -45,6 +49,7 @@ import com.jogamp.graph.geom.plane.AffineTransform;
import com.jogamp.opengl.math.geom.AABBox;
class TypecastFont implements Font {
+ static final boolean USE_PRESCALED_ADVANCE = false;
static final boolean DEBUG = false;
private static final Vertex.Factory<SVertex> vertexFactory = SVertex.factory();
@@ -54,7 +59,6 @@ class TypecastFont implements Font {
private final int cmapentries;
private final IntObjectHashMap char2Glyph;
private final TypecastHMetrics metrics;
- private final float[] tmpV3 = new float[3];
// FIXME: Add cache size to limit memory usage ??
public TypecastFont(final OTFontCollection fontset) {
@@ -169,7 +173,15 @@ class TypecastFont implements Font {
@Override
public float getAdvanceWidth(final int glyphID, final float pixelSize) {
- return font.getHmtxTable().getAdvanceWidth(glyphID) * metrics.getScale(pixelSize);
+ return pixelSize * metrics.getScale( font.getHmtxTable().getAdvanceWidth(glyphID) );
+ }
+ @Override
+ public float getAdvanceWidth(final int glyphID) {
+ return metrics.getScale( font.getHmtxTable().getAdvanceWidth(glyphID) );
+ }
+ @Override
+ public int getAdvanceWidthFU(final int glyphID) {
+ return font.getHmtxTable().getAdvanceWidth(glyphID);
}
@Override
@@ -178,46 +190,104 @@ class TypecastFont implements Font {
}
@Override
+ public final float getKerning(final int left_glyphid, final int right_glyphid) {
+ return metrics.getScale( getKerningFU(left_glyphid, right_glyphid) );
+ }
+
+ @Override
+ public int getKerningFU(final int left_glyphid, final int right_glyphid) {
+ if( 0 == left_glyphid || 0 == right_glyphid ) {
+ return 0;
+ }
+ final KernTable kern = font.getKernTable();
+ if (kern != null) {
+ final int kernSubtableCount = kern.getSubtableCount();
+ if( 0 < kernSubtableCount ) {
+ final KernSubtableFormat0 kst0 = kern.getSubtable0();
+ if( null != kst0 && kst0.areKerningValues() && kst0.isHorizontal() && !kst0.isCrossstream() ) {
+ for (int i = 0; i < kst0.getKerningPairCount(); i++) {
+ final KerningPair kpair = kst0.getKerningPair(i);
+ if( kpair.getLeft() == left_glyphid && kpair.getRight() == right_glyphid ) {
+ return kpair.getValue();
+ }
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public int getGlyphID(final char symbol) {
+ // enforce mapping as some fonts have an erroneous cmap (FreeSerif-Regular)
+ switch(symbol) {
+ case ' ': return Glyph.ID_SPACE;
+ case '\n': return Glyph.ID_CR;
+ }
+ final int glyphID = cmapFormat.mapCharCode(symbol);
+ if( 0 != glyphID ) {
+ return glyphID;
+ }
+ return Glyph.ID_UNKNOWN;
+ }
+
+ /** pp **/ PostTable getPostTable() {
+ return font.getPostTable();
+ }
+
+ @Override
public Glyph getGlyph(final char symbol) {
TypecastGlyph result = (TypecastGlyph) char2Glyph.get(symbol);
if (null == result) {
- // final short code = (short) char2Code.get(symbol);
- short code = (short) cmapFormat.mapCharCode(symbol);
- if(0 == code && 0 != symbol) {
- // reserved special glyph IDs by convention
- switch(symbol) {
- case ' ': code = Glyph.ID_SPACE; break;
- case '\n': code = Glyph.ID_CR; break;
- default: code = Glyph.ID_UNKNOWN;
- }
- }
+ final int glyph_id = getGlyphID( symbol );
- jogamp.graph.font.typecast.ot.OTGlyph glyph = font.getGlyph(code);
+ jogamp.graph.font.typecast.ot.OTGlyph glyph = font.getGlyph(glyph_id);
+ final int glyph_advance;
+ final AABBox glyph_bbox;
if(null == glyph) {
+ // fallback
glyph = font.getGlyph(Glyph.ID_UNKNOWN);
}
+ switch( glyph_id ) {
+ case Glyph.ID_SPACE:
+ /** fallthrough */
+ case Glyph.ID_CR:
+ glyph_advance = getAdvanceWidthFU(glyph_id);
+ glyph_bbox = new AABBox(0, 0, 0, glyph_advance, getLineHeightFU(), 0);
+ break;
+ default:
+ glyph_advance = glyph.getAdvanceWidth();
+ glyph_bbox = glyph.getBBox();
+ break;
+ }
if(null == glyph) {
- throw new RuntimeException("Could not retrieve glyph for symbol: <"+symbol+"> "+(int)symbol+" -> glyph id "+code);
+ throw new RuntimeException("Could not retrieve glyph for symbol: <"+symbol+"> "+(int)symbol+" -> glyph id "+glyph_id);
}
final OutlineShape shape = TypecastRenderer.buildShape(symbol, glyph, vertexFactory);
- result = new TypecastGlyph(this, symbol, code, glyph.getBBox(), glyph.getAdvanceWidth(), shape);
+ result = new TypecastGlyph(this, symbol, glyph_id, glyph_bbox, glyph_advance, shape);
if(DEBUG) {
- System.err.println("New glyph: " + (int)symbol + " ( " + symbol +" ) -> " + code + ", contours " + glyph.getPointCount() + ": " + shape);
+ 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(" "+glyph);
+ System.err.println(" "+result);
}
glyph.clearPointData();
- final HdmxTable hdmx = font.getHdmxTable();
- if (null!= result && null != hdmx) {
- /*if(DEBUG) {
- System.err.println("hdmx "+hdmx);
- }*/
- for (int i=0; i<hdmx.getNumberOfRecords(); i++)
- {
- final HdmxTable.DeviceRecord dr = hdmx.getRecord(i);
- result.addAdvance(dr.getWidth(code), dr.getPixelSize());
- /* if(DEBUG) {
- System.err.println("hdmx advance : pixelsize = "+dr.getWidth(code)+" : "+ dr.getPixelSize());
- } */
+ if( TypecastFont.USE_PRESCALED_ADVANCE ) {
+ final HdmxTable hdmx = font.getHdmxTable();
+ if (null!= result && null != hdmx) {
+ /*if(DEBUG) {
+ System.err.println("hdmx "+hdmx);
+ }*/
+ for (int i=0; i<hdmx.getNumberOfRecords(); i++)
+ {
+ final HdmxTable.DeviceRecord dr = hdmx.getRecord(i);
+ if(DEBUG) {
+ System.err.println("hdmx advance : pixelsize "+dr.getPixelSize()+" -> advance "+dr.getWidth(glyph_id));
+ }
+ result.addAdvance(dr.getPixelSize(), dr.getWidth(glyph_id));
+ }
}
}
char2Glyph.put(symbol, result);
@@ -226,23 +296,53 @@ class TypecastFont implements Font {
}
@Override
- public final float getPixelSize(final float fontSize /* points per inch */, final float resolution) {
- return fontSize * resolution / ( 72f /* points per inch */ );
+ public float getLineHeight(final float pixelSize) {
+ return pixelSize * metrics.getScale( getLineHeightFU() );
}
@Override
- public float getLineHeight(final float pixelSize) {
+ public float getLineHeight() {
+ return metrics.getScale( getLineHeightFU() );
+ }
+
+ @Override
+ public int getLineHeightFU() {
final Metrics metrics = getMetrics();
- final float lineGap = metrics.getLineGap(pixelSize) ; // negative value!
- final float ascent = metrics.getAscent(pixelSize) ; // negative value!
- final float descent = metrics.getDescent(pixelSize) ; // positive value!
- final float advanceY = lineGap - descent + ascent; // negative value!
+ final int lineGap = metrics.getLineGapFU() ; // negative value!
+ final int ascent = metrics.getAscentFU() ; // negative value!
+ final int descent = metrics.getDescentFU() ; // positive value!
+ final int advanceY = lineGap - descent + ascent; // negative value!
return -advanceY;
}
@Override
public float getMetricWidth(final CharSequence string, final float pixelSize) {
- float width = 0;
+ if( !TypecastFont.USE_PRESCALED_ADVANCE ) {
+ return pixelSize * getMetricWidth(string);
+ } else {
+ float 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(character);
+ width += glyph.getAdvance(pixelSize); // uses pixelSize mapping, different than glyph.getAdvanceFU()
+ }
+ }
+ return width;
+ }
+ }
+
+ @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);
@@ -250,22 +350,31 @@ class TypecastFont implements Font {
width = 0;
} else {
final Glyph glyph = getGlyph(character);
- width += glyph.getAdvance(pixelSize, false);
+ width += glyph.getAdvanceFU();
}
}
- return (int)(width + 0.5f);
+ return width;
+ }
+
+ @Override
+ public float getMetricHeight(final CharSequence string, final float pixelSize) {
+ return pixelSize * getMetricHeight(string);
+ }
+
+ @Override
+ public float getMetricHeight(final CharSequence string) {
+ return metrics.getScale( getMetricHeightFU(string) );
}
@Override
- public float getMetricHeight(final CharSequence string, final float pixelSize, final AABBox tmp) {
+ 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(character);
- final AABBox bbox = glyph.getBBox(tmp, pixelSize, tmpV3);
- height = (int)Math.ceil(Math.max(bbox.getHeight(), height));
+ height = (int)Math.ceil(Math.max(glyph.getBBoxFU().getHeight(), height));
}
}
return height;
@@ -273,14 +382,51 @@ class TypecastFont implements Font {
@Override
public AABBox getMetricBounds(final CharSequence string, final float pixelSize) {
+ if( !TypecastFont.USE_PRESCALED_ADVANCE ) {
+ return getMetricBoundsFU(string).scale(pixelSize/metrics.getUnitsPerEM(), new float[3]);
+ } else {
+ if (string == null) {
+ return new AABBox();
+ }
+ final int charCount = string.length();
+ final float lineHeight = getLineHeight(pixelSize);
+ float totalHeight = 0;
+ float totalWidth = 0;
+ float 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;
+ }
+ final Glyph glyph = getGlyph(character);
+ curLineWidth += glyph.getAdvance(pixelSize); // uses pixelSize mapping, different than glyph.getAdvanceFU()
+ }
+ if (curLineWidth > 0) {
+ totalHeight += lineHeight;
+ totalWidth = Math.max(curLineWidth, totalWidth);
+ }
+ return new AABBox(0, 0, 0, totalWidth, totalHeight,0);
+ }
+ }
+
+ @Override
+ public AABBox getMetricBounds(final CharSequence string) {
+ return getMetricBoundsFU(string).scale(1.0f/metrics.getUnitsPerEM(), new float[3]);
+ }
+
+ @Override
+ public AABBox getMetricBoundsFU(final CharSequence string) {
if (string == null) {
return new AABBox();
}
final int charCount = string.length();
- final float lineHeight = getLineHeight(pixelSize);
- float totalHeight = 0;
- float totalWidth = 0;
- float curLineWidth = 0;
+ 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') {
@@ -289,8 +435,7 @@ class TypecastFont implements Font {
totalHeight += lineHeight;
continue;
}
- final Glyph glyph = getGlyph(character);
- curLineWidth += glyph.getAdvance(pixelSize, true);
+ curLineWidth += getAdvanceWidthFU( getGlyphID( character ) );
}
if (curLineWidth > 0) {
totalHeight += lineHeight;
@@ -298,15 +443,72 @@ class TypecastFont implements Font {
}
return new AABBox(0, 0, 0, totalWidth, totalHeight,0);
}
+
+ @Override
+ public AABBox getPointsBounds(final AffineTransform transform, final CharSequence string, final float pixelSize) {
+ if( !TypecastFont.USE_PRESCALED_ADVANCE ) {
+ return getPointsBoundsFU(transform, string).scale(pixelSize/metrics.getUnitsPerEM(), new float[3]);
+ } else {
+ if (string == null) {
+ return new AABBox();
+ }
+ final AffineTransform temp1 = new AffineTransform();
+ final AffineTransform temp2 = new AffineTransform();
+ final float pixelSize2 = pixelSize / metrics.getUnitsPerEM();
+ final int charCount = string.length();
+ final float lineHeight = getLineHeight(pixelSize);
+ final AABBox tbox = new AABBox();
+ final AABBox res = new AABBox();
+
+ float y = 0;
+ float advanceTotal = 0;
+
+ for(int i=0; i< charCount; i++) {
+ final char character = string.charAt(i);
+ if( '\n' == character ) {
+ y -= lineHeight;
+ advanceTotal = 0;
+ } else if (character == ' ') {
+ advanceTotal += getAdvanceWidth(Glyph.ID_SPACE, pixelSize);
+ } else {
+ // reset transform
+ if( null != transform ) {
+ temp1.setTransform(transform);
+ } else {
+ temp1.setToIdentity();
+ }
+ temp1.translate(advanceTotal, y, temp2);
+ temp1.scale(pixelSize2, pixelSize2, temp2);
+ tbox.reset();
+
+ final Font.Glyph glyph = getGlyph(character);
+ res.resize(temp1.transform(glyph.getBBoxFU(), tbox));
+
+ final OutlineShape glyphShape = glyph.getShape();
+ if( null == glyphShape ) {
+ continue;
+ }
+ advanceTotal += glyph.getAdvance(pixelSize);
+ }
+ }
+ return res;
+ }
+ }
+
@Override
- public AABBox getPointsBounds(final AffineTransform transform, final CharSequence string, final float pixelSize,
- final AffineTransform temp1, final AffineTransform temp2) {
+ public AABBox getPointsBounds(final AffineTransform transform, final CharSequence string) {
+ return getPointsBoundsFU(transform, string).scale(1.0f/metrics.getUnitsPerEM(), new float[3]);
+ }
+
+ @Override
+ public AABBox getPointsBoundsFU(final AffineTransform transform, final CharSequence string) {
if (string == null) {
return new AABBox();
}
+ final AffineTransform temp1 = new AffineTransform();
+ final AffineTransform temp2 = new AffineTransform();
final int charCount = string.length();
- final float lineHeight = getLineHeight(pixelSize);
- final float scale = getMetrics().getScale(pixelSize);
+ final int lineHeight = getLineHeightFU();
final AABBox tbox = new AABBox();
final AABBox res = new AABBox();
@@ -319,7 +521,7 @@ class TypecastFont implements Font {
y -= lineHeight;
advanceTotal = 0;
} else if (character == ' ') {
- advanceTotal += getAdvanceWidth(Glyph.ID_SPACE, pixelSize);
+ advanceTotal += getAdvanceWidthFU(Glyph.ID_SPACE);
} else {
// reset transform
if( null != transform ) {
@@ -328,17 +530,16 @@ class TypecastFont implements Font {
temp1.setToIdentity();
}
temp1.translate(advanceTotal, y, temp2);
- temp1.scale(scale, scale, temp2);
tbox.reset();
final Font.Glyph glyph = getGlyph(character);
- res.resize(temp1.transform(glyph.getBBox(), tbox));
+ res.resize(temp1.transform(glyph.getBBoxFU(), tbox));
final OutlineShape glyphShape = glyph.getShape();
if( null == glyphShape ) {
continue;
}
- advanceTotal += glyph.getAdvance(pixelSize, true);
+ advanceTotal += glyph.getAdvanceFU();
}
}
return res;
@@ -358,4 +559,55 @@ class TypecastFont implements Font {
public String toString() {
return getFullFamilyName(null).toString();
}
+
+ @Override
+ public String fullString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(toString()).append("[ ").append(font.toString());
+ sb.append("\n").append(font.getHeadTable());
+ sb.append("\n\n").append(font.getHheaTable());
+ if( null != font.getVheaTable() ) {
+ sb.append("\n\n").append(font.getVheaTable());
+ }
+ if( null != font.getKernTable() ) {
+ final PostTable post = font.getPostTable();
+ final KernTable kern = font.getKernTable();
+ sb.append("\n\n").append(kern);
+ final KernSubtableFormat0 ks0 = kern.getSubtable0();
+ if( null != ks0 ) {
+ final int sz = ks0.getKerningPairCount();
+ for(int i=0; i<sz; ++i) {
+ final KerningPair kp = ks0.getKerningPair(i);
+ final int left = kp.getLeft();
+ final int right = kp.getRight();
+ final String leftS;
+ final String rightS;
+ if( null == post ) {
+ leftS = String.valueOf(left);
+ rightS = String.valueOf(left);
+ } else {
+ leftS = post.getGlyphName(left)+"/"+String.valueOf(left);
+ rightS = post.getGlyphName(right)+"/"+String.valueOf(right);
+ }
+ sb.append("\n kp[").append(i).append("]: ").append(leftS).append(" -> ").append(rightS).append(" = ").append(kp.getValue());
+ }
+ }
+ }
+
+ sb.append("\n\n").append(font.getCmapTable());
+ /* if( null != font.getHdmxTable() ) {
+ sb.append("\n").append(font.getHdmxTable()); // too too long
+ } */
+ // glyf
+ // sb.append("\n").append(font.getHmtxTable()); // too long
+ /* if( null != font.getLocaTable() ) {
+ sb.append("\n").append(font.getLocaTable()); // too long
+ } */
+ sb.append("\n").append(font.getMaxpTable());
+ // sb.append("\n\n").append(font.getNameTable()); // no toString()
+ sb.append("\n\n").append(font.getOS2Table());
+ // sb.append("\n\n").append(font.getPostTable()); // too long
+ sb.append("\n]");
+ return sb.toString();
+ }
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
index 97570d605..b36196ee5 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
@@ -32,52 +32,63 @@ import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.font.Font;
import com.jogamp.opengl.math.geom.AABBox;
+import jogamp.graph.font.typecast.ot.table.PostTable;
+
public final class TypecastGlyph implements Font.Glyph {
+
+ /** Scaled hmtx value */
public static final class Advance
{
private final Font font;
- private final float advance;
- private final IntIntHashMap size2advanceI = new IntIntHashMap();
+ private final int advance; // in font-units
+ private final IntIntHashMap size2advanceI;
- public Advance(final Font font, final float advance)
+ public Advance(final Font font, final int advance)
{
this.font = font;
this.advance = advance;
- size2advanceI.setKeyNotFoundValue(0);
+ if( TypecastFont.USE_PRESCALED_ADVANCE ) {
+ size2advanceI = new IntIntHashMap();
+ size2advanceI.setKeyNotFoundValue(0);
+ } else {
+ size2advanceI = null;
+ }
}
public final void reset() {
- size2advanceI.clear();
+ if( TypecastFont.USE_PRESCALED_ADVANCE ) {
+ size2advanceI.clear();
+ }
}
public final Font getFont() { return font; }
- public final float getScale(final float pixelSize)
+ public final int getUnitsPerEM() { return this.font.getMetrics().getUnitsPerEM(); }
+
+ public final float getScale(final int funits)
{
- return this.font.getMetrics().getScale(pixelSize);
+ return this.font.getMetrics().getScale(funits);
}
- public final void add(final float advance, final float size)
+ public final void add(final float pixelSize, final float advance)
{
- size2advanceI.put(Float.floatToIntBits(size), Float.floatToIntBits(advance));
+ if( TypecastFont.USE_PRESCALED_ADVANCE ) {
+ size2advanceI.put(Float.floatToIntBits(pixelSize), Float.floatToIntBits(advance));
+ }
}
- public final float get(final float pixelSize, final boolean useFrationalMetrics)
+ public final float get(final float pixelSize)
{
- final int sI = Float.floatToIntBits(pixelSize);
- final int aI = size2advanceI.get(sI);
- if( 0 != aI ) {
- return Float.intBitsToFloat(aI);
- }
- final float a;
- if ( useFrationalMetrics ) {
- a = this.advance * getScale(pixelSize);
+ if( !TypecastFont.USE_PRESCALED_ADVANCE ) {
+ return pixelSize * font.getMetrics().getScale( advance );
} else {
- // a = Math.ceil(this.advance * getScale(pixelSize));
- a = Math.round(this.advance * getScale(pixelSize)); // TODO: check whether ceil should be used instead?
+ final int sI = Float.floatToIntBits( (float) Math.ceil( pixelSize ) );
+ final int aI = size2advanceI.get(sI);
+ if( 0 != aI ) {
+ return Float.intBitsToFloat(aI);
+ }
+ return pixelSize * font.getMetrics().getScale( advance );
}
- size2advanceI.put(sI, Float.floatToIntBits(a));
- return a;
}
@Override
@@ -91,39 +102,59 @@ public final class TypecastGlyph implements Font.Glyph {
public static final class Metrics
{
- private final AABBox bbox;
- private final Advance advance;
-
- public Metrics(final Font font, final AABBox bbox, final float advance)
+ private final TypecastFont font;
+ private final AABBox bbox; // in font-units
+ private final int advance; // in font-units
+ private final Advance advance2;
+
+ /**
+ *
+ * @param font
+ * @param bbox in font-units
+ * @param advance hmtx value in font-units
+ */
+ public Metrics(final TypecastFont font, final AABBox bbox, final int advance)
{
+ this.font = font;
this.bbox = bbox;
- this.advance = new Advance(font, advance);
+ this.advance = advance;
+ if( TypecastFont.USE_PRESCALED_ADVANCE ) {
+ this.advance2 = new Advance(font, advance);
+ } else {
+ this.advance2 = null;
+ }
}
public final void reset() {
- advance.reset();
+ if( TypecastFont.USE_PRESCALED_ADVANCE ) {
+ advance2.reset();
+ }
}
- public final Font getFont() { return advance.getFont(); }
+ public final TypecastFont getFont() { return font; }
- public final float getScale(final float pixelSize)
- {
- return this.advance.getScale(pixelSize);
- }
+ public final int getUnitsPerEM() { return font.getMetrics().getUnitsPerEM(); }
- public final AABBox getBBox()
- {
- return this.bbox;
- }
+ public final float getScale(final int funits) { return font.getMetrics().getScale(funits); }
- public final void addAdvance(final float advance, final float size)
- {
- this.advance.add(advance, size);
+ /** in font-units */
+ public final AABBox getBBoxFU() { return this.bbox; }
+
+ /** Return advance in font units to be divided by unitsPerEM */
+ public final int getAdvanceFU() { return this.advance; }
+
+ public final void addAdvance(final float pixelSize, final float advance) {
+ if( TypecastFont.USE_PRESCALED_ADVANCE ) {
+ this.advance2.add(pixelSize, advance);
+ }
}
- public final float getAdvance(final float pixelSize, final boolean useFrationalMetrics)
- {
- return this.advance.get(pixelSize, useFrationalMetrics);
+ public final float getAdvance(final float pixelSize) {
+ if( TypecastFont.USE_PRESCALED_ADVANCE ) {
+ return this.advance2.get(pixelSize);
+ } else {
+ return pixelSize * font.getMetrics().getScale( advance );
+ }
}
@Override
@@ -131,7 +162,8 @@ public final class TypecastGlyph implements Font.Glyph {
{
return "\nMetrics:"+
"\n bbox: "+this.bbox+
- this.advance;
+ "\n advance: "+this.advance+
+ "\n advance2: "+this.advance2;
}
}
@@ -140,10 +172,19 @@ public final class TypecastGlyph implements Font.Glyph {
private final char symbol;
private final OutlineShape shape; // in EM units
- private final short id;
+ private final int id;
private final Metrics metrics;
- protected TypecastGlyph(final Font font, final char symbol, final short id, final AABBox bbox, final int advance, final OutlineShape shape) {
+ /**
+ *
+ * @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, final OutlineShape shape) {
this.symbol = symbol;
this.shape = shape;
this.id = id;
@@ -160,41 +201,50 @@ public final class TypecastGlyph implements Font.Glyph {
return this.symbol;
}
- final AABBox getBBoxUnsized() {
- return this.metrics.getBBox();
+ public final Metrics getMetrics() {
+ return this.metrics;
}
@Override
- public final AABBox getBBox() {
- return this.metrics.getBBox();
+ public final int getID() {
+ return this.id;
}
- public final Metrics getMetrics() {
- return this.metrics;
+ @Override
+ public final float getScale(final int funits) {
+ return this.metrics.getScale(funits);
}
@Override
- public final short getID() {
- return this.id;
+ public final AABBox getBBox(final AABBox dest, final float pixelSize, final float[] tmpV3) {
+ return dest.copy(metrics.getBBoxFU()).scale(pixelSize/metrics.getUnitsPerEM(), tmpV3);
}
@Override
- public final float getScale(final float pixelSize) {
- return this.metrics.getScale(pixelSize);
+ public final AABBox getBBoxFU(final AABBox dest) {
+ return dest.copy(metrics.getBBoxFU());
}
@Override
- public final AABBox getBBox(final AABBox dest, final float pixelSize, final float[] tmpV3) {
- return dest.copy(getBBox()).scale(getScale(pixelSize), tmpV3);
+ public final AABBox getBBoxFU() {
+ return metrics.getBBoxFU();
}
- protected final void addAdvance(final float advance, final float size) {
- this.metrics.addAdvance(advance, size);
+ @Override
+ public final int getAdvanceFU() { return metrics.getAdvanceFU(); }
+
+ @Override
+ public float getAdvance() { return getScale( getAdvanceFU() ); }
+
+ protected final void addAdvance(final float pixelSize, final float advance) {
+ if( TypecastFont.USE_PRESCALED_ADVANCE ) {
+ this.metrics.addAdvance(pixelSize, advance);
+ }
}
@Override
- public final float getAdvance(final float pixelSize, final boolean useFrationalMetrics) {
- return this.metrics.getAdvance(pixelSize, useFrationalMetrics);
+ public final float getAdvance(final float pixelSize) {
+ return metrics.getAdvance(pixelSize);
}
@Override
@@ -208,4 +258,15 @@ public final class TypecastGlyph implements Font.Glyph {
final int hash = 31 + getFont().getName(Font.NAME_UNIQUNAME).hashCode();
return ((hash << 5) - hash) + id;
}
+
+ @Override
+ public String toString() {
+ final PostTable post = metrics.getFont().getPostTable();
+ final String glyph_name = null != post ? post.getGlyphName(id) : "n/a";
+ return new StringBuilder()
+ .append("Glyph id ").append(id).append(" '").append(glyph_name).append("'")
+ .append(", advance ").append(getAdvanceFU())
+ .append(", ").append(getBBoxFU())
+ .toString();
+ }
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java
index d5e30a500..705246822 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java
@@ -33,12 +33,13 @@ import jogamp.graph.font.typecast.ot.table.HheaTable;
import com.jogamp.graph.font.Font.Metrics;
import com.jogamp.opengl.math.geom.AABBox;
-class TypecastHMetrics implements Metrics {
+final class TypecastHMetrics implements Metrics {
private final TypecastFont fontImpl;
// HeadTable
private final HeadTable headTable;
- private final float unitsPerEM_Inv;
+ private final int unitsPerEM;
+ private final float unitsPerEM_inv;
private final AABBox bbox;
// HheaTable
private final HheaTable hheaTable;
@@ -50,39 +51,55 @@ class TypecastHMetrics implements Metrics {
headTable = this.fontImpl.font.getHeadTable();
hheaTable = this.fontImpl.font.getHheaTable();
// vheaTable = this.fontImpl.font.getVheaTable();
- unitsPerEM_Inv = 1.0f / ( headTable.getUnitsPerEm() );
+ unitsPerEM = headTable.getUnitsPerEm();
+ unitsPerEM_inv = 1.0f / unitsPerEM;
final int maxWidth = headTable.getXMax() - headTable.getXMin();
final int maxHeight = headTable.getYMax() - headTable.getYMin();
- final float lowx= headTable.getXMin();
- final float lowy = -(headTable.getYMin()+maxHeight);
- final float highx = lowx + maxWidth;
- final float highy = lowy + maxHeight;
+ final int lowx= headTable.getXMin();
+ final int lowy = -(headTable.getYMin()+maxHeight);
+ final int highx = lowx + maxWidth;
+ final int highy = lowy + maxHeight;
bbox = new AABBox(lowx, lowy, 0, highx, highy, 0); // invert
}
@Override
- public final float getAscent(final float pixelSize) {
- return getScale(pixelSize) * -hheaTable.getAscender(); // invert
+ public int getAscentFU() {
+ return -hheaTable.getAscender(); // inverted
}
+
@Override
- public final float getDescent(final float pixelSize) {
- return getScale(pixelSize) * -hheaTable.getDescender(); // invert
+ public int getDescentFU() {
+ return -hheaTable.getDescender(); // inverted
}
+
@Override
- public final float getLineGap(final float pixelSize) {
- return getScale(pixelSize) * -hheaTable.getLineGap(); // invert
+ public int getLineGapFU() {
+ return -hheaTable.getLineGap(); // inverted
}
+
@Override
- public final float getMaxExtend(final float pixelSize) {
- return getScale(pixelSize) * hheaTable.getXMaxExtent();
+ public int getMaxExtendFU() {
+ return hheaTable.getXMaxExtent();
}
+
@Override
- public final float getScale(final float pixelSize) {
- return pixelSize * unitsPerEM_Inv;
+ public final int getUnitsPerEM() {
+ return unitsPerEM;
}
+
+ @Override
+ public final float getScale(final int funits) {
+ return funits * unitsPerEM_inv;
+ }
+
+ @Override
+ public final AABBox getBBox(final AABBox dest) {
+ return dest.copy(bbox);
+ }
+
@Override
public final AABBox getBBox(final AABBox dest, final float pixelSize, final float[] tmpV3) {
- return dest.setSize(bbox.getLow(), bbox.getHigh()).scale(getScale(pixelSize), tmpV3);
+ return dest.setSize(bbox.getLow(), bbox.getHigh()).scale(pixelSize*unitsPerEM_inv, tmpV3);
}
-} \ No newline at end of file
+}
diff --git a/src/newt/classes/com/jogamp/newt/opengl/util/NEWTDemoListener.java b/src/newt/classes/com/jogamp/newt/opengl/util/NEWTDemoListener.java
index 7507e772f..aaed713a8 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/util/NEWTDemoListener.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/util/NEWTDemoListener.java
@@ -32,6 +32,7 @@ import java.util.ArrayList;
import java.util.List;
import com.jogamp.common.util.IOUtil;
+import com.jogamp.graph.font.FontScale;
import com.jogamp.nativewindow.CapabilitiesImmutable;
import com.jogamp.nativewindow.ScalableSurface;
import com.jogamp.newt.Window;
@@ -126,6 +127,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
case KeyEvent.VK_SPACE:
e.setConsumed(true);
glWindow.invokeOnCurrentThread(new Runnable() {
+ @Override
public void run() {
final GLAnimatorControl anim = glWindow.getAnimator();
if( null != anim ) {
@@ -140,6 +142,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
case KeyEvent.VK_A:
e.setConsumed(true);
glWindow.invokeOnNewThread(null, false, new Runnable() {
+ @Override
public void run() {
printlnState("[set alwaysontop pre]");
glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop());
@@ -149,6 +152,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
case KeyEvent.VK_B:
e.setConsumed(true);
glWindow.invokeOnNewThread(null, false, new Runnable() {
+ @Override
public void run() {
printlnState("[set alwaysonbottom pre]");
glWindow.setAlwaysOnBottom(!glWindow.isAlwaysOnBottom());
@@ -158,6 +162,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
case KeyEvent.VK_C:
e.setConsumed(true);
glWindow.invokeOnNewThread(null, false, new Runnable() {
+ @Override
public void run() {
if( null != pointerIcons ) {
printlnState("[set pointer-icon pre]");
@@ -177,6 +182,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
case KeyEvent.VK_D:
e.setConsumed(true);
glWindow.invokeOnNewThread(null, false, new Runnable() {
+ @Override
public void run() {
printlnState("[set undecorated pre]");
glWindow.setUndecorated(!glWindow.isUndecorated());
@@ -187,6 +193,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
e.setConsumed(true);
quitAdapterOff();
glWindow.invokeOnNewThread(null, false, new Runnable() {
+ @Override
public void run() {
printlnState("[set fullscreen pre]");
if( glWindow.isFullscreen() ) {
@@ -205,6 +212,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
case KeyEvent.VK_G:
e.setConsumed(true);
glWindow.invokeOnNewThread(null, false, new Runnable() {
+ @Override
public void run() {
final float newGamma = gamma + ( e.isShiftDown() ? -0.1f : 0.1f );
System.err.println("[set gamma]: "+gamma+" -> "+newGamma);
@@ -216,6 +224,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
case KeyEvent.VK_I:
e.setConsumed(true);
glWindow.invokeOnNewThread(null, false, new Runnable() {
+ @Override
public void run() {
printlnState("[set pointer-visible pre]");
glWindow.setPointerVisible(!glWindow.isPointerVisible());
@@ -225,6 +234,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
case KeyEvent.VK_J:
e.setConsumed(true);
glWindow.invokeOnNewThread(null, false, new Runnable() {
+ @Override
public void run() {
printlnState("[set pointer-confined pre]", "warp-center: "+e.isShiftDown());
final boolean confine = !glWindow.isPointerConfined();
@@ -240,6 +250,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
case KeyEvent.VK_M:
e.setConsumed(true);
glWindow.invokeOnNewThread(null, false, new Runnable() {
+ @Override
public void run() {
// none: max-v
// alt: max-h
@@ -271,6 +282,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
case KeyEvent.VK_P:
e.setConsumed(true);
glWindow.invokeOnNewThread(null, false, new Runnable() {
+ @Override
public void run() {
printlnState("[set position pre]");
glWindow.setPosition(100, 100);
@@ -286,6 +298,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
case KeyEvent.VK_R:
e.setConsumed(true);
glWindow.invokeOnNewThread(null, false, new Runnable() {
+ @Override
public void run() {
printlnState("[set resizable pre]");
glWindow.setResizable(!glWindow.isResizable());
@@ -295,6 +308,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
case KeyEvent.VK_S:
e.setConsumed(true);
glWindow.invokeOnNewThread(null, false, new Runnable() {
+ @Override
public void run() {
printlnState("[set sticky pre]");
glWindow.setSticky(!glWindow.isSticky());
@@ -331,6 +345,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
});
} else {
glWindow.invokeOnNewThread(null, false, new Runnable() {
+ @Override
public void run() {
final boolean wasVisible = glWindow.isVisible();
{
@@ -354,6 +369,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
case KeyEvent.VK_W:
e.setConsumed(true);
glWindow.invokeOnNewThread(null, false, new Runnable() {
+ @Override
public void run() {
printlnState("[set pointer-pos pre]");
glWindow.warpPointer(glWindow.getSurfaceWidth()/2, glWindow.getSurfaceHeight()/2);
@@ -441,6 +457,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
public boolean shouldQuit() { return quitAdapterShouldQuit; }
public void doQuit() { quitAdapterShouldQuit=true; }
+ @Override
public void windowDestroyNotify(final WindowEvent e) {
if( quitAdapterEnabled && quitAdapterEnabled2 ) {
System.err.println("QUIT Window "+Thread.currentThread());
@@ -458,9 +475,7 @@ public class NEWTDemoListener extends WindowAdapter implements KeyListener, Mous
final CapabilitiesImmutable reqCaps = win.getRequestedCapabilities();
final CapabilitiesImmutable caps = null != chosenCaps ? chosenCaps : reqCaps;
final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl";
- final float[] sDPI = win.getPixelsPerMM(new float[2]);
- sDPI[0] *= 25.4f;
- sDPI[1] *= 25.4f;
+ final float[] sDPI = FontScale.perMMToPerInch( win.getPixelsPerMM(new float[2]) );
final float[] minSurfacePixelScale = win.getMinimumSurfaceScale(new float[2]);
final float[] maxSurfacePixelScale = win.getMaximumSurfaceScale(new float[2]);
final float[] reqSurfacePixelScale = win.getRequestedSurfaceScale(new float[2]);
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestFontsNEWT00.java b/src/test/com/jogamp/opengl/test/junit/graph/TestFontsNEWT00.java
index e0c6d2ac0..9592a06cf 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/TestFontsNEWT00.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TestFontsNEWT00.java
@@ -35,7 +35,10 @@ import org.junit.FixMethodOrder;
import org.junit.runners.MethodSorters;
import com.jogamp.graph.font.Font;
+import com.jogamp.graph.font.FontScale;
import com.jogamp.graph.font.Font.Glyph;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.geom.AABBox;
import com.jogamp.opengl.test.junit.util.UITestCase;
@@ -64,30 +67,45 @@ public class TestFontsNEWT00 extends UITestCase {
final float dpi = 96;
for(int i=0; i<fonts.length; i++) {
final Font font = fonts[i];
- final float pixelSize = font.getPixelSize(fontSize, dpi);
+ final float pixelSize = FontScale.toPixels(fontSize, dpi);
System.err.println(font.getFullFamilyName(null).toString()+": "+fontSize+"p, "+dpi+"dpi -> "+pixelSize+"px:");
- testFontGlyphAdvancedSize(font, ' ', Glyph.ID_SPACE, fontSize, dpi, pixelSize);
- testFontGlyphAdvancedSize(font, 'X', 'X', fontSize, dpi, pixelSize);
+ testFontGlyphAdvancedSize(font, 'X', pixelSize);
+ testFontGlyphAdvancedSize(font, 'j', pixelSize);
+ testFontGlyphAdvancedSize(font, ' ', pixelSize);
}
}
- void testFontGlyphAdvancedSize(final Font font, final char c, final int glyphID,
- final float fontSize, final float dpi, final float pixelSize) {
- final float glyphScale = font.getGlyph(c).getScale(pixelSize);
- final float fontScale = font.getMetrics().getScale(pixelSize);
+ void testFontGlyphAdvancedSize(final Font font, final char c, final float pixelSize) {
+ final int glyphID = font.getGlyphID(c);
+ final int s0 = font.getAdvanceWidthFU(glyphID);
+ final Font.Glyph glyph = font.getGlyph(c);
+ final int s1 = glyph.getAdvanceFU();
- // return this.metrics.getAdvance(pixelSize, useFrationalMetrics);
- // this.metrics.getAdvance(pixelSize, useFrationalMetrics)
- // this.advance * this.font.getMetrics().getScale(pixelSize)
- // font.getHmtxTable().getAdvanceWidth(glyphID) * this.font.getMetrics().getScale(pixelSize)
- final float spaceAdvanceSizeOfGlyph = font.getGlyph(c).getAdvance(pixelSize, true);
+ final int unitsPerEM = font.getMetrics().getUnitsPerEM();
- // font.getHmtxTable().getAdvanceWidth(glyphID) * metrics.getScale(pixelSize);
- // font.getHmtxTable().getAdvanceWidth(glyphID) * pixelSize * unitsPerEM_Inv;
- final float spaceAdvanceWidth = font.getAdvanceWidth(glyphID, pixelSize);
- System.err.println(" Char '"+c+"', "+glyphID+":");
- System.err.println(" glyphScale "+glyphScale);
- System.err.println(" glyphSize "+spaceAdvanceSizeOfGlyph);
- System.err.println(" fontScale "+fontScale);
- System.err.println(" fontWidth "+spaceAdvanceWidth);
+ final float s0_em = font.getAdvanceWidth(glyphID);
+ final float s1_em = glyph.getAdvance();
+
+ final float s0_px = font.getAdvanceWidth(glyphID, pixelSize);
+ final float s1_px = glyph.getAdvance(pixelSize);
+
+ System.err.println(" Char '"+c+"', id "+glyphID+", font-px "+pixelSize+", unitsPerEM "+unitsPerEM+":");
+ System.err.println(" "+glyph);
+ System.err.println(" Advance");
+ System.err.println(" funits "+s0+", "+s1);
+ System.err.println(" em "+s0_em+", "+s1_em);
+ System.err.println(" px "+s0_px+", "+s1_px);
+ System.err.println(" AABBox");
+ System.err.println(" funits "+glyph.getBBoxFU());
+ System.err.println(" px "+glyph.getBBox(new AABBox(), pixelSize, new float[3]));
+
+ Assert.assertEquals(s0, s1);
+
+ Assert.assertEquals((float)s0/(float)unitsPerEM, s0_em, FloatUtil.EPSILON);
+ Assert.assertEquals((float)s1/(float)unitsPerEM, s1_em, FloatUtil.EPSILON);
+ Assert.assertEquals(s0_em, s1_em, FloatUtil.EPSILON);
+
+ Assert.assertEquals(s0_em*pixelSize, s0_px, FloatUtil.EPSILON);
+ Assert.assertEquals(s1_em*pixelSize, s1_px, FloatUtil.EPSILON);
+ Assert.assertEquals(s0_px, s1_px, FloatUtil.EPSILON);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java
index 66785b2ab..9cb29365c 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java
@@ -54,6 +54,7 @@ import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.curve.opengl.RenderState;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
+import com.jogamp.graph.font.FontScale;
import com.jogamp.graph.geom.SVertex;
import com.jogamp.junit.util.JunitTracer;
import com.jogamp.newt.Window;
@@ -338,10 +339,10 @@ public class TestTextRendererNEWT00 extends UITestCase {
final Window win = (Window)drawable.getUpstreamWidget();
final float[] pixelsPerMM = win.getPixelsPerMM(new float[2]);
- final float[] dotsPerInch = new float[] { pixelsPerMM[0]*25.4f, pixelsPerMM[1]*25.4f };
+ final float[] dotsPerInch = FontScale.ppmmToPPI(pixelsPerMM, new float[2]);
dpiH = dotsPerInch[1];
System.err.println(getFontInfo());
- System.err.println("fontSize "+fontSizeFixed+", dotsPerMM "+pixelsPerMM[0]+"x"+pixelsPerMM[1]+", dpi "+dotsPerInch[0]+"x"+dotsPerInch[1]+", pixelSize "+font.getPixelSize(fontSizeFixed, dotsPerInch[1] /* dpi display */));
+ System.err.println("fontSize "+fontSizeFixed+", dotsPerMM "+pixelsPerMM[0]+"x"+pixelsPerMM[1]+", dpi "+dotsPerInch[0]+"x"+dotsPerInch[1]+", pixelSize "+FontScale.toPixels(fontSizeFixed, dotsPerInch[1] /* dpi display */));
}
@Override
@@ -395,8 +396,8 @@ public class TestTextRendererNEWT00 extends UITestCase {
fontSizeDelta *= -1f;
}
- final float pixelSize = font.getPixelSize(fontSizeFixed, dpiH);
- final float pixelSizeAnim = font.getPixelSize(fontSizeAnim, dpiH);
+ final float pixelSize = FontScale.toPixels(fontSizeFixed, dpiH);
+ final float pixelSizeAnim = FontScale.toPixels(fontSizeAnim, dpiH);
final String modeS = Region.getRenderModeString(renderModes);
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java
index b452e091d..cdd2bc750 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java
@@ -231,7 +231,11 @@ public class TestTextRendererNEWT10 extends UITestCase {
pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmv.glLoadIdentity();
pmv.glTranslatef(dx, dy, z0);
- textRenderUtil.drawString3D(gl, renderer, font, fontSize, text, null, sampleCount);
+ {
+ final float sxy = fontSize / font.getMetrics().getUnitsPerEM();
+ pmv.glScalef(sxy, sxy, 1.0f);
+ }
+ textRenderUtil.drawString3D(gl, renderer, font, text, null, sampleCount);
lastRow = row;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWTBugXXXX.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWTBugXXXX.java
index e6ae83911..7d285fe43 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWTBugXXXX.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWTBugXXXX.java
@@ -201,7 +201,11 @@ public class TestTextRendererNEWTBugXXXX extends UITestCase {
pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmv.glLoadIdentity();
pmv.glTranslatef(dx, dy, z0);
- textRenderUtil.drawString3D(gl, renderer, font, fontSize, text, null, sampleCount);
+ {
+ final float sxy = fontSize / font.getMetrics().getUnitsPerEM();
+ pmv.glScalef(sxy, sxy, 1.0f);
+ }
+ textRenderUtil.drawString3D(gl, renderer, font, text, null, sampleCount);
lastRow = row;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java b/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java
index 1ee8a464d..866a522ac 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java
@@ -40,6 +40,7 @@ import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.curve.opengl.TextRegionUtil;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
+import com.jogamp.graph.font.FontScale;
import com.jogamp.graph.font.FontSet;
import com.jogamp.graph.geom.SVertex;
import com.jogamp.newt.Window;
@@ -145,8 +146,8 @@ public abstract class TextRendererGLELBase implements GLEventListener {
final Object upObj = drawable.getUpstreamWidget();
if( upObj instanceof Window ) {
- final float[] pixelsPerMM = ((Window)upObj).getPixelsPerMM(new float[2]);
- dpiH = pixelsPerMM[1]*25.4f;
+ final float[] dpi = FontScale.perMMToPerInch( ((Window)upObj).getPixelsPerMM(new float[2]) );
+ dpiH = dpi[1];
}
}
@@ -183,7 +184,7 @@ public abstract class TextRendererGLELBase implements GLEventListener {
*
* @param drawable
* @param font
- * @param pixelSize Use {@link Font#getPixelSize(float, float)} for resolution correct pixel-size.
+ * @param pixelSize Use {@link Font#toPixels(float, float)} for resolution correct pixel-size.
* @param text
* @param column
* @param tx
@@ -209,7 +210,7 @@ public abstract class TextRendererGLELBase implements GLEventListener {
*
* @param drawable
* @param font
- * @param pixelSize Use {@link Font#getPixelSize(float, float)} for resolution correct pixel-size.
+ * @param pixelSize Use {@link Font#toPixels(float, float)} for resolution correct pixel-size.
* @param text
* @param column
* @param row
@@ -261,19 +262,20 @@ public abstract class TextRendererGLELBase implements GLEventListener {
pmvMatrix.glLoadIdentity();
}
pmvMatrix.glTranslatef(dx, dy, tz);
+ final float sxy = ( pixelScale * pixelSize ) / font.getMetrics().getUnitsPerEM();
if( flipVerticalInGLOrientation && drawable.isGLOriented() ) {
- pmvMatrix.glScalef(pixelScale, -1f*pixelScale, 1f);
- } else if( 1f != pixelScale ) {
- pmvMatrix.glScalef(pixelScale, pixelScale, 1f);
+ pmvMatrix.glScalef(sxy, -1f*sxy, 1.0f);
+ } else {
+ pmvMatrix.glScalef(sxy, sxy, 1.0f);
}
renderer.enable(gl, true);
if( cacheRegion ) {
- textRenderUtil.drawString3D(gl, renderer, font, pixelSize, text, null, vbaaSampleCount);
+ textRenderUtil.drawString3D(gl, renderer, font, text, null, vbaaSampleCount);
} else if( null != region ) {
- TextRegionUtil.drawString3D(gl, region, renderer, font, pixelSize, text, null, vbaaSampleCount,
+ TextRegionUtil.drawString3D(gl, region, renderer, font, text, null, vbaaSampleCount,
textRenderUtil.tempT1, textRenderUtil.tempT2);
} else {
- TextRegionUtil.drawString3D(gl, renderModes, renderer, font, pixelSize, text, null, vbaaSampleCount,
+ TextRegionUtil.drawString3D(gl, renderModes, renderer, font, text, null, vbaaSampleCount,
textRenderUtil.tempT1, textRenderUtil.tempT2);
}
renderer.enable(gl, false);
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java
index 2d3b0664e..311abbcc3 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java
@@ -47,6 +47,7 @@ import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.GLRegion;
import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.curve.opengl.RenderState;
+import com.jogamp.graph.font.FontScale;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
@@ -125,9 +126,7 @@ public abstract class GPURendererListenerBase01 implements GLEventListener {
final Object upObj = drawable.getUpstreamWidget();
if( upObj instanceof Window ) {
final Window window = (Window) upObj;
- final float[] sDPI = window.getPixelsPerMM(new float[2]);
- sDPI[0] *= 25.4f;
- sDPI[1] *= 25.4f;
+ final float[] sDPI = FontScale.perMMToPerInch( window.getPixelsPerMM(new float[2]) );
System.err.println("DPI "+sDPI[0]+" x "+sDPI[1]);
final float[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new float[2]);
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo.java
index fff3bc291..c3b1d1473 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo.java
@@ -29,9 +29,12 @@ package com.jogamp.opengl.test.junit.graph.demos;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLProfile;
-
+import com.jogamp.opengl.math.geom.AABBox;
+import com.jogamp.common.util.InterruptSource;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.RenderState;
+import com.jogamp.graph.font.Font;
+import com.jogamp.graph.font.FontScale;
import com.jogamp.graph.geom.SVertex;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
@@ -130,19 +133,38 @@ public class GPUTextNewtDemo {
// ((TextRenderer)textGLListener.getRenderer()).setCacheLimit(32);
window.addGLEventListener(textGLListener);
window.setVisible(true);
+
+ {
+ final Font font = textGLListener.getFont();
+ final float[] sDPI = FontScale.perMMToPerInch( window.getPixelsPerMM(new float[2]) );
+ final float font_ptpi = 12f;
+ final float font_ppi = FontScale.toPixels(font_ptpi, sDPI[1]);
+ final AABBox fontNameBox = font.getMetricBounds(GPUTextRendererListenerBase01.textX2, font_ppi);
+ System.err.println("GPU Text Newt Demo: "+font.fullString());
+ System.err.println("GPU Text Newt Demo: screen-dpi: "+sDPI[0]+"x"+sDPI[1]+", font "+font_ptpi+" pt, "+font_ppi+" pixel");
+ System.err.println("GPU Text Newt Demo: textX2: "+fontNameBox+" pixel");
+ window.setSurfaceSize((int)(fontNameBox.getWidth()*1.1f), (int)(fontNameBox.getHeight()*2f));
+ }
+
// FPSAnimator animator = new FPSAnimator(60);
final Animator animator = new Animator();
animator.setUpdateFPSFrames(60, System.err);
animator.add(window);
window.addKeyListener(new KeyAdapter() {
+ @Override
public void keyPressed(final KeyEvent arg0) {
if(arg0.getKeyCode() == KeyEvent.VK_F4) {
- window.destroy();
+ new InterruptSource.Thread() {
+ @Override
+ public void run() {
+ window.destroy();
+ } }.start();
}
}
});
window.addWindowListener(new WindowAdapter() {
+ @Override
public void windowDestroyed(final WindowEvent e) {
animator.stop();
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java
index 85d1b5290..e0097bd74 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java
@@ -43,6 +43,9 @@ import com.jogamp.graph.curve.opengl.RenderState;
import com.jogamp.graph.curve.opengl.TextRegionUtil;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
+import com.jogamp.graph.font.FontScale;
+import com.jogamp.graph.font.FontSet;
+import com.jogamp.graph.font.Font.Glyph;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
@@ -68,13 +71,13 @@ import com.jogamp.opengl.util.PMVMatrix;
*/
public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerBase01 {
public final TextRegionUtil textRegionUtil;
- private final GLRegion regionFPS, regionBottom;
+ private final GLRegion regionFPS, regionHead, regionBottom;
int fontSet = FontFactory.UBUNTU;
Font font;
int headType = 0;
boolean drawFPS = true;
- final float fontSizeFName = 8f;
+ final float fontSizeFName = 10f;
final float fontSizeFPS = 10f;
final int[] sampleCountFPS = new int[] { 8 };
float fontSizeHead = 12f;
@@ -88,28 +91,54 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
static final String text1 = "abcdefghijklmnopqrstuvwxyz\nABCDEFGHIJKLMNOPQRSTUVWXYZ\n0123456789.:,;(*!?/\\\")$%^&-+@~#<>{}[]";
static final String text2 = "The quick brown fox jumps over the lazy dog";
- static final String textX =
+ public static final String textX =
"JOGAMP graph demo using Resolution Independent NURBS\n"+
"JOGAMP JOGL - OpenGL ES2 profile\n"+
"Press 1/2 to zoom in/out the below text\n"+
"Press 3/4 to incr/decs font size (alt: head, w/o bottom)\n"+
"Press 6/7 to edit texture size if using VBAA\n"+
"Press 0/9 to rotate the below string\n"+
+ "Press s to screenshot\n"+
"Press v to toggle vsync\n"+
"Press i for live input text input (CR ends it, backspace supported)\n"+
"Press f to toggle fps. H for different text, space for font type\n";
- static final String textX2 =
+ public static final String textX2 =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec nec sapien tellus. \n"+
"Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel urna. Mauris ultricies \n"+
"quam iaculis urna cursus ornare. Nullam ut felis a ante ultrices ultricies nec a elit. \n"+
- "In hac habitasse platea dictumst. Vivamus et mi a quam lacinia pharetra at venenatis est.\n"+
- "Morbi quis bibendum nibh. Donec lectus orci, sagittis in consequat nec, volutpat nec nisi.\n"+
+ "In hac habitasse platea dictumst. Vivamus et mi a quam lacinia pharetra at venenatis est. \n"+
+ "Morbi quis bibendum nibh. Donec lectus orci, sagittis in consequat nec, volutpat nec nisi. \n"+
"Donec ut dolor et nulla tristique varius. In nulla magna, fermentum id tempus quis, semper \n"+
- "in lorem. Maecenas in ipsum ac justo scelerisque sollicitudin. Quisque sit amet neque lorem,\n" +
+ "in lorem. Maecenas in ipsum ac justo scelerisque sollicitudin. Quisque sit amet neque lorem, \n" +
"-------Press H to change text---------";
- StringBuilder userString = new StringBuilder();
+ public static final String textX3 =
+ "I “Ask Jeff” or ‘Ask Jeff’. Take the chef d’œuvre! Two of [of] (of) ‘of’ “of” of? of! of*.\n"+
+ "Les Woëvres, the Fôret de Wœvres, the Voire and Vauvise. Yves is in heaven; D’Amboise is in jail.\n"+
+ "Lyford’s in Texas & L’Anse-aux-Griffons in Québec; the Łyna in Poland. Yriarte, Yciar and Ysaÿe are at Yale.\n"+
+ "Kyoto and Ryotsu are both in Japan, Kwikpak on the Yukon delta, Kvæven in Norway, Kyulu in Kenya, not in Rwanda.…\n"+
+ "Miłosz and Wū Wŭ all in the library? 1510–1620, 11:00 pm, and the 1980s are over.\n"+
+ "Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel urna. Mauris ultricies \n"+
+ "-------Press H to change text---------";
+
+ public static final String textX30 =
+ "I “Ask Jeff” or ‘Ask Jeff’. Take the chef d’œuvre! Two of [of] (of) ‘of’ “of” of? of! of*.\n"+
+ "Two of [of] (of) ‘of’ “of” of? of! of*. Ydes, Yffignac and Ygrande are in France: so are Ypres,\n"+
+ "Les Woëvres, the Fôret de Wœvres, the Voire and Vauvise. Yves is in heaven; D’Amboise is in jail.\n"+
+ "Lyford’s in Texas & L’Anse-aux-Griffons in Québec; the Łyna in Poland. Yriarte, Yciar and Ysaÿe are at Yale.\n"+
+ "Kyoto and Ryotsu are both in Japan, Kwikpak on the Yukon delta, Kvæven in Norway, Kyulu in Kenya, not in Rwanda.…\n"+
+ "Walton’s in West Virginia, but «Wren» is in Oregon. Tlálpan is near Xochimilco in México.\n"+
+ "The Zygos & Xylophagou are in Cyprus, Zwettl in Austria, Fænø in Denmark, the Vøringsfossen and Værøy in Norway.\n"+
+ "Tchula is in Mississippi, the Tittabawassee in Michigan. Twodot is here in Montana, Ywamun in Burma.\n"+
+ "Yggdrasil and Ymir, Yngvi and Vóden, Vídrið and Skeggjöld and Týr are all in the Eddas.\n"+
+ "Tørberget and Våg, of course, are in Norway, Ktipas and Tmolos in Greece, but Vázquez is in Argentina, Vreden in Germany,\n"+
+ "Von-Vincke-Straße in Münster, Vdovino in Russia, Ytterbium in the periodic table. Are Toussaint L’Ouverture, Wölfflin, Wolfe,\n"+
+ "Miłosz and Wū Wŭ all in the library? 1510–1620, 11:00 pm, and the 1980s are over.\n"+
+ "Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel urna. Mauris ultricies \n"+
+ "-------Press H to change text---------";
+
+ StringBuilder userString = new StringBuilder(textX2);
boolean userInput = false;
public GPUTextRendererListenerBase01(final RenderState rs, final int renderModes, final int sampleCount, final boolean blending, final boolean debug, final boolean trace) {
// NOTE_ALPHA_BLENDING: We use alpha-blending
@@ -119,9 +148,11 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
rs.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED);
this.textRegionUtil = new TextRegionUtil(renderModes);
this.regionFPS = GLRegion.create(renderModes, null);
+ this.regionHead = GLRegion.create(renderModes, null);
this.regionBottom = GLRegion.create(renderModes, null);
try {
- this.font = FontFactory.get(fontSet).getDefault();
+ // this.font = FontFactory.get(fontSet).getDefault();
+ this.font = FontFactory.get(fontSet).get(FontSet.FAMILY_LIGHT, FontSet.STYLE_NONE);
dumpFontNames();
this.fontName = font.toString();
@@ -139,7 +170,7 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
}
void switchHeadBox() {
- headType = ( headType + 1 ) % 4 ;
+ headType = ( headType + 1 ) % 5 ;
switch(headType) {
case 0:
headtext = null;
@@ -151,12 +182,15 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
case 2:
headtext= textX;
break;
+ case 3:
+ headtext= textX3;
+ break;
default:
headtext = text1;
}
if(null != headtext) {
- headbox = font.getMetricBounds(headtext, font.getPixelSize(fontSizeHead, dpiH));
+ headbox = font.getMetricBounds(headtext, FontScale.toPixels(fontSizeHead, dpiH));
}
}
@@ -166,15 +200,13 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
final Object upObj = drawable.getUpstreamWidget();
if( upObj instanceof Window ) {
final Window window = (Window) upObj;
- final float[] sDPI = window.getPixelsPerMM(new float[2]);
- sDPI[0] *= 25.4f;
- sDPI[1] *= 25.4f;
+ final float[] sDPI = FontScale.perMMToPerInch( window.getPixelsPerMM(new float[2]) );
dpiH = sDPI[1];
System.err.println("Using screen DPI of "+dpiH);
} else {
System.err.println("Using default DPI of "+dpiH);
}
- fontNameBox = font.getMetricBounds(fontName, font.getPixelSize(fontSizeFName, dpiH));
+ fontNameBox = font.getMetricBounds(fontName, FontScale.toPixels(fontSizeFName, dpiH));
switchHeadBox();
}
@@ -198,6 +230,7 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
@Override
public void dispose(final GLAutoDrawable drawable) {
regionFPS.destroy(drawable.getGL().getGL2ES2());
+ regionHead.destroy(drawable.getGL().getGL2ES2());
regionBottom.destroy(drawable.getGL().getGL2ES2());
super.dispose(drawable);
}
@@ -223,14 +256,14 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmv.glLoadIdentity();
rs.setColorStatic(0.1f, 0.1f, 0.1f, 1.0f);
- final float pixelSizeFName = font.getPixelSize(fontSizeFName, dpiH);
- final float pixelSizeHead = font.getPixelSize(fontSizeHead, dpiH);
- final float pixelSizeBottom = font.getPixelSize(fontSizeBottom, dpiH);
+ final float pixelSizeFName = FontScale.toPixels(fontSizeFName, dpiH);
+ final float pixelSizeHead = FontScale.toPixels(fontSizeHead, dpiH);
+ final float pixelSizeBottom = FontScale.toPixels(fontSizeBottom, dpiH);
renderer.enable(gl, true);
if( drawFPS ) {
- final float pixelSizeFPS = font.getPixelSize(fontSizeFPS, dpiH);
+ final float pixelSizeFPS = FontScale.toPixels(fontSizeFPS, dpiH);
final float lfps, tfps, td;
final GLAnimatorControl animator = drawable.getAnimator();
if( null != animator ) {
@@ -250,20 +283,27 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
// bottom, half line up
pmv.glTranslatef(nearPlaneX0, nearPlaneY0+(nearPlaneS * pixelSizeFPS / 2f), nearPlaneZ0);
-
+ {
+ final float sxy = ( nearPlaneS * pixelSizeFPS ) / font.getMetrics().getUnitsPerEM();
+ pmv.glScalef(sxy, sxy, 1.0f);
+ }
// No cache, keep region alive!
- TextRegionUtil.drawString3D(gl, regionFPS, renderer, font, nearPlaneS * pixelSizeFPS, text, null, sampleCountFPS,
- textRegionUtil.tempT1, textRegionUtil.tempT2);
+ TextRegionUtil.drawString3D(gl, regionFPS, renderer, font, text, null, sampleCountFPS, textRegionUtil.tempT1,
+ textRegionUtil.tempT2);
}
- float dx = width-fontNameBox.getWidth()-2f;
- float dy = height - 10f;
+ float dx = width-fontNameBox.getWidth()-font.getAdvanceWidth(Glyph.ID_SPACE, pixelSizeFName);
+ float dy = height-fontNameBox.getHeight();
pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmv.glLoadIdentity();
pmv.glTranslatef(nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy), nearPlaneZ0);
+ {
+ final float sxy = ( nearPlaneS * pixelSizeFName ) / font.getMetrics().getUnitsPerEM();
+ pmv.glScalef(sxy, sxy, 1.0f);
+ }
// System.err.printf("FontN: [%f %f] -> [%f %f]%n", dx, dy, nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy));
- textRegionUtil.drawString3D(gl, renderer, font, nearPlaneS * pixelSizeFName, fontName, null, getSampleCount());
+ textRegionUtil.drawString3D(gl, renderer, font, fontName, null, getSampleCount());
dx = 10f;
dy += -fontNameBox.getHeight() - 10f;
@@ -273,8 +313,12 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
pmv.glLoadIdentity();
// System.err.printf("Head: [%f %f] -> [%f %f]%n", dx, dy, nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy));
pmv.glTranslatef(nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy), nearPlaneZ0);
+ {
+ final float sxy = ( nearPlaneS * pixelSizeHead ) / font.getMetrics().getUnitsPerEM();
+ pmv.glScalef(sxy, sxy, 1.0f);
+ }
// pmv.glTranslatef(x0, y1, z0);
- textRegionUtil.drawString3D(gl, renderer, font, nearPlaneS * pixelSizeHead, headtext, null, getSampleCount());
+ textRegionUtil.drawString3D(gl, renderer, font, headtext, null, getSampleCount());
}
dy += -headbox.getHeight() - font.getLineHeight(pixelSizeBottom);
@@ -285,6 +329,10 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
// System.err.printf("Bottom: [%f %f] -> [%f %f]%n", dx, dy, nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy));
pmv.glTranslatef(getXTran(), getYTran(), getZTran());
pmv.glRotatef(getAngle(), 0, 1, 0);
+ {
+ final float sxy = ( nearPlaneS * pixelSizeBottom ) / font.getMetrics().getUnitsPerEM();
+ pmv.glScalef(sxy, sxy, 1.0f);
+ }
rs.setColorStatic(0.9f, 0.0f, 0.0f, 1.0f);
if( bottomTextUseFrustum ) {
@@ -292,23 +340,26 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
}
if(!userInput) {
if( bottomTextUseFrustum ) {
- TextRegionUtil.drawString3D(gl, regionBottom, renderer, font, nearPlaneS * pixelSizeBottom, text2, null, getSampleCount(),
- textRegionUtil.tempT1, textRegionUtil.tempT2);
+ TextRegionUtil.drawString3D(gl, regionBottom, renderer, font, text2, null, getSampleCount(), textRegionUtil.tempT1,
+ textRegionUtil.tempT2);
} else {
- textRegionUtil.drawString3D(gl, renderer, font, nearPlaneS * pixelSizeBottom, text2, null, getSampleCount());
+ textRegionUtil.drawString3D(gl, renderer, font, text2, null, getSampleCount());
}
} else {
if( bottomTextUseFrustum ) {
- TextRegionUtil.drawString3D(gl, regionBottom, renderer, font, nearPlaneS * pixelSizeBottom, userString.toString(), null, getSampleCount(),
- textRegionUtil.tempT1, textRegionUtil.tempT2);
+ TextRegionUtil.drawString3D(gl, regionBottom, renderer, font, userString.toString(), null, getSampleCount(), textRegionUtil.tempT1,
+ textRegionUtil.tempT2);
} else {
- textRegionUtil.drawString3D(gl, renderer, font, nearPlaneS * pixelSizeBottom, userString.toString(), null, getSampleCount());
+ textRegionUtil.drawString3D(gl, renderer, font, userString.toString(), null, getSampleCount());
}
}
renderer.enable(gl, false);
}
final boolean bottomTextUseFrustum = true;
+ public Font getFont() { return font; }
+ public float getFontSizeHead() { return fontSizeHead; }
+
public void fontBottomIncr(final int v) {
fontSizeBottom = Math.abs((fontSizeBottom + v) % fontSizeModulo) ;
dumpMatrix(true);
@@ -317,7 +368,7 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
public void fontHeadIncr(final int v) {
fontSizeHead = Math.abs((fontSizeHead + v) % fontSizeModulo) ;
if(null != headtext) {
- headbox = font.getMetricBounds(headtext, font.getPixelSize(fontSizeHead, dpiH));
+ headbox = font.getMetricBounds(headtext, FontScale.toPixels(fontSizeHead, dpiH));
}
}
@@ -329,7 +380,7 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
fontSet = set;
font = _font;
fontName = font.getFullFamilyName(null).toString();
- fontNameBox = font.getMetricBounds(fontName, font.getPixelSize(fontSizeFName, dpiH));
+ fontNameBox = font.getMetricBounds(fontName, FontScale.toPixels(fontSizeFName, dpiH));
dumpFontNames();
return true;
}
@@ -346,7 +397,7 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
fontSet = set;
font = _font;
fontName = font.getFullFamilyName(null).toString();
- fontNameBox = font.getMetricBounds(fontName, font.getPixelSize(fontSizeFName, dpiH));
+ fontNameBox = font.getMetricBounds(fontName, FontScale.toPixels(fontSizeFName, dpiH));
dumpFontNames();
return true;
}
@@ -361,7 +412,7 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
void dumpMatrix(final boolean bbox) {
System.err.println("Matrix: " + getXTran() + "/" + getYTran() + " x"+getZTran() + " @"+getAngle() +" fontSize "+fontSizeBottom);
if(bbox) {
- System.err.println("bbox: "+font.getMetricBounds(text2, nearPlaneS * font.getPixelSize(fontSizeBottom, dpiH)));
+ System.err.println("bbox: "+font.getMetricBounds(text2, nearPlaneS * FontScale.toPixels(fontSizeBottom, dpiH)));
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java
index a55ed26c0..e92f18995 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java
@@ -23,6 +23,7 @@ import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.curve.opengl.RenderState;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
+import com.jogamp.graph.font.FontScale;
import com.jogamp.graph.geom.SVertex;
import com.jogamp.newt.MonitorDevice;
import com.jogamp.newt.Window;
@@ -357,6 +358,7 @@ public class GPUUISceneGLListener0A implements GLEventListener {
@Override
public void mouseClicked(final MouseEvent e) {
new InterruptSource.Thread() {
+ @Override
public void run() {
if( null != cDrawable ) {
final GLAnimatorControl actrl = cDrawable.getAnimator();
@@ -668,12 +670,8 @@ public class GPUUISceneGLListener0A implements GLEventListener {
if( upObj instanceof Window ) {
final Window upWin = (Window)upObj;
final MonitorDevice mm = upWin.getMainMonitor();
- final float[] monitorDPI = mm.getPixelsPerMM(new float[2]);
- monitorDPI[0] *= 25.4f;
- monitorDPI[1] *= 25.4f;
- final float[] sDPI = upWin.getPixelsPerMM(new float[2]);
- sDPI[0] *= 25.4f;
- sDPI[1] *= 25.4f;
+ final float[] monitorDPI = FontScale.perMMToPerInch( mm.getPixelsPerMM(new float[2]) );
+ final float[] sDPI = FontScale.perMMToPerInch( upWin.getPixelsPerMM(new float[2]) );
dpiH = sDPI[1];
System.err.println("Monitor detected: "+mm);
System.err.println("Monitor dpi: "+monitorDPI[0]+" x "+monitorDPI[1]);
@@ -731,7 +729,7 @@ public class GPUUISceneGLListener0A implements GLEventListener {
sceneUIController.addShape(jogampLabel);
jogampLabel.setEnabled(enableOthers);
- final float pixelSize10Pt = font.getPixelSize(fontSizePt, dpiH);
+ final float pixelSize10Pt = FontScale.toPixels(fontSizePt, dpiH);
System.err.println("10Pt PixelSize: Display "+dpiH+" dpi, fontSize "+fontSizePt+" ppi -> "+pixelSize10Pt+" pixel-size");
truePtSizeLabel = new Label(renderer.getRenderState().getVertexFactory(), renderModes, font, pixelSize10Pt, truePtSize);
sceneUIController.addShape(truePtSizeLabel);
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 a6b2e03bd..39eab26e2 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
@@ -107,7 +107,7 @@ public class LabelButton extends RoundButton {
}
// Setting pixelSize based on actual text-box size
- final AABBox lbox1 = label.font.getPointsBounds(null, label.text, lPixelSize1, tempT1, tempT2);
+ final AABBox lbox1 = label.font.getPointsBounds(null, label.text, lPixelSize1);
// Center text .. (share same center w/ button)
final float[] lctr = lbox1.getCenter();
final float[] ctr = box.getCenter();
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java
index 163f5736d..66655dadd 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java
@@ -44,6 +44,7 @@ import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.GLRegion;
import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.font.Font;
+import com.jogamp.graph.font.FontScale;
import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase;
import com.jogamp.opengl.test.junit.util.UITestCase;
@@ -93,7 +94,7 @@ public abstract class GLReadBuffer00Base extends UITestCase {
final String text = String.format("Frame %04d (%03d): %04dx%04d", frameNo, userCounter, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
System.err.println("TextRendererGLEL.display: "+text);
if( null != renderer ) {
- final float pixelSize = font.getPixelSize(14f, dpiH);
+ final float pixelSize = FontScale.toPixels(14f, dpiH);
drawable.getGL().glClearColor(1f, 1f, 1f, 0f);
renderString(drawable, font, pixelSize, text, 0 /* col */, 0 /* row */, 0, 0, -1, regionFPS);
} else {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java
index a8dede526..134503520 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java
@@ -47,6 +47,7 @@ import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.GLRegion;
import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.font.Font;
+import com.jogamp.graph.font.FontScale;
import com.jogamp.junit.util.JunitTracer;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.KeyAdapter;
@@ -118,6 +119,7 @@ public class MovieCube implements GLEventListener {
}
if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
new InterruptSource.Thread() {
+ @Override
public void run() {
// loop for-ever ..
mPlayer.seek(0);
@@ -196,8 +198,8 @@ public class MovieCube implements GLEventListener {
this.setSharedPMVMatrix(cube.pmvMatrix);
super.init(drawable);
- pixelSize1 = font.getPixelSize(fontSize1, dpiH);
- pixelSize2 = font.getPixelSize(fontSize2, dpiH);
+ pixelSize1 = FontScale.toPixels(fontSize1, dpiH);
+ pixelSize2 = FontScale.toPixels(fontSize2, dpiH);
pixelScale = 1.0f / ( pixelSize1 * 20f );
// underlineSize: 'underline' amount of pixel below 0/0 (Note: lineGap is negative)
final Font.Metrics metrics = font.getMetrics();
@@ -270,6 +272,7 @@ public class MovieCube implements GLEventListener {
private boolean displayOSD = true;
private final KeyListener keyAction = new KeyAdapter() {
+ @Override
public void keyReleased(final KeyEvent e) {
if( e.isAutoRepeat() ) {
return;
@@ -562,6 +565,7 @@ public class MovieCube implements GLEventListener {
final GLWindow window = GLWindow.create(caps);
final Animator anim = new Animator(window);
window.addWindowListener(new WindowAdapter() {
+ @Override
public void windowDestroyed(final WindowEvent e) {
anim.stop();
}
@@ -601,6 +605,7 @@ public class MovieCube implements GLEventListener {
se.printStackTrace();
}
new InterruptSource.Thread() {
+ @Override
public void run() {
window.destroy();
} }.start();
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java
index 9b9073721..af0aaa775 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java
@@ -47,6 +47,7 @@ import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.GLRegion;
import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.font.Font;
+import com.jogamp.graph.font.FontScale;
import com.jogamp.junit.util.JunitTracer;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.KeyAdapter;
@@ -194,7 +195,7 @@ public class MovieSBSStereo implements StereoGLEventListener {
final String text4 = mPlayer.getUri().path.decode();
if( displayOSD && null != renderer ) {
// We share ClearColor w/ MovieSimple's init !
- final float pixelSize = font.getPixelSize(fontSize, dpiH);
+ final float pixelSize = FontScale.toPixels(fontSize, dpiH);
if( null != regionFPS ) {
renderString(drawable, font, pixelSize, text1, 1 /* col */, 1 /* row */, 0, 0, -1, regionFPS); // no-cache
} else {
@@ -210,6 +211,7 @@ public class MovieSBSStereo implements StereoGLEventListener {
private boolean displayOSD = false;
private final MouseListener mouseAction = new MouseAdapter() {
+ @Override
public void mousePressed(final MouseEvent e) {
if(e.getY()<=surfHeight/2 && null!=mPlayer && 1 == e.getClickCount()) {
if(GLMediaPlayer.State.Playing == mPlayer.getState()) {
@@ -219,6 +221,7 @@ public class MovieSBSStereo implements StereoGLEventListener {
}
}
}
+ @Override
public void mouseReleased(final MouseEvent e) {
if(e.getY()<=surfHeight/2) {
rotate = -1;
@@ -226,10 +229,12 @@ public class MovieSBSStereo implements StereoGLEventListener {
System.err.println("zoom: "+zoom);
}
}
+ @Override
public void mouseMoved(final MouseEvent e) {
prevMouseX = e.getX();
// prevMouseY = e.getY();
}
+ @Override
public void mouseDragged(final MouseEvent e) {
final int x = e.getX();
final int y = e.getY();
@@ -247,6 +252,7 @@ public class MovieSBSStereo implements StereoGLEventListener {
prevMouseX = x;
// prevMouseY = y;
}
+ @Override
public void mouseWheelMoved(final MouseEvent e) {
if( !e.isShiftDown() ) {
zoom += e.getRotation()[1]/10f; // vertical: wheel
@@ -255,6 +261,7 @@ public class MovieSBSStereo implements StereoGLEventListener {
} };
private final KeyListener keyAction = new KeyAdapter() {
+ @Override
public void keyReleased(final KeyEvent e) {
if( e.isAutoRepeat() ) {
return;
@@ -802,6 +809,7 @@ public class MovieSBSStereo implements StereoGLEventListener {
static class StereoGLMediaEventListener implements GLMediaEventListener {
void destroyWindow(final Window window) {
new InterruptSource.Thread() {
+ @Override
public void run() {
window.destroy();
} }.start();
@@ -848,6 +856,7 @@ public class MovieSBSStereo implements StereoGLEventListener {
} else {
System.err.println("MovieSimple State: EOS");
new InterruptSource.Thread() {
+ @Override
public void run() {
mp.setPlaySpeed(1f);
mp.seek(0);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
index 25ce93597..4ba3372eb 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
@@ -52,6 +52,7 @@ import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.GLRegion;
import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.font.Font;
+import com.jogamp.graph.font.FontScale;
import com.jogamp.junit.util.JunitTracer;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.KeyAdapter;
@@ -197,7 +198,7 @@ public class MovieSimple implements GLEventListener {
final String text4 = mPlayer.getUri().path.decode();
if( displayOSD && null != renderer ) {
// We share ClearColor w/ MovieSimple's init !
- final float pixelSize = font.getPixelSize(fontSize, dpiH);
+ final float pixelSize = FontScale.toPixels(fontSize, dpiH);
if( null != regionFPS ) {
renderString(drawable, font, pixelSize, text1, 1 /* col */, 1 /* row */, 0, 0, -1, regionFPS); // no-cache
} else {
@@ -212,6 +213,7 @@ public class MovieSimple implements GLEventListener {
private boolean displayOSD = true;
private final MouseListener mouseAction = new MouseAdapter() {
+ @Override
public void mousePressed(final MouseEvent e) {
if(e.getY()<=surfHeight/2 && null!=mPlayer && 1 == e.getClickCount()) {
if(GLMediaPlayer.State.Playing == mPlayer.getState()) {
@@ -221,6 +223,7 @@ public class MovieSimple implements GLEventListener {
}
}
}
+ @Override
public void mouseReleased(final MouseEvent e) {
if(e.getY()<=surfHeight/2) {
rotate = -1;
@@ -228,10 +231,12 @@ public class MovieSimple implements GLEventListener {
System.err.println("zoom: "+zoom);
}
}
+ @Override
public void mouseMoved(final MouseEvent e) {
prevMouseX = e.getX();
// prevMouseY = e.getY();
}
+ @Override
public void mouseDragged(final MouseEvent e) {
final int x = e.getX();
final int y = e.getY();
@@ -249,6 +254,7 @@ public class MovieSimple implements GLEventListener {
prevMouseX = x;
// prevMouseY = y;
}
+ @Override
public void mouseWheelMoved(final MouseEvent e) {
if( !e.isShiftDown() ) {
zoom += e.getRotation()[1]/10f; // vertical: wheel
@@ -257,6 +263,7 @@ public class MovieSimple implements GLEventListener {
} };
private final KeyListener keyAction = new KeyAdapter() {
+ @Override
public void keyReleased(final KeyEvent e) {
if( e.isAutoRepeat() ) {
return;
@@ -357,6 +364,7 @@ public class MovieSimple implements GLEventListener {
}
if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
new InterruptSource.Thread() {
+ @Override
public void run() {
// loop for-ever ..
mPlayer.seek(0);
@@ -809,6 +817,7 @@ public class MovieSimple implements GLEventListener {
static class MyGLMediaEventListener implements GLMediaEventListener {
void destroyWindow(final Window window) {
new InterruptSource.Thread() {
+ @Override
public void run() {
window.destroy();
} }.start();
@@ -875,6 +884,7 @@ public class MovieSimple implements GLEventListener {
System.err.println("MovieSimple State: EOS");
if( loopEOS ) {
new InterruptSource.Thread() {
+ @Override
public void run() {
mp.setPlaySpeed(1f);
mp.seek(0);
@@ -1038,6 +1048,7 @@ public class MovieSimple implements GLEventListener {
anim.start();
windows[i] = GLWindow.create(caps);
windows[i].addWindowListener(new WindowAdapter() {
+ @Override
public void windowDestroyed(final WindowEvent e) {
anim.stop();
}
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtReparentingKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtReparentingKeyAdapter.java
index cd4edddb1..5d1ceba36 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtReparentingKeyAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtReparentingKeyAdapter.java
@@ -27,6 +27,7 @@
*/
package com.jogamp.opengl.test.junit.newt.parenting;
+import com.jogamp.graph.font.FontScale;
import com.jogamp.nativewindow.CapabilitiesImmutable;
import com.jogamp.nativewindow.NativeWindow;
import com.jogamp.nativewindow.NativeWindowHolder;
@@ -69,6 +70,7 @@ public class NewtReparentingKeyAdapter extends NEWTDemoListener {
e.setConsumed(true);
quitAdapterOff();
glWindow.invokeOnNewThread(null, false, new Runnable() {
+ @Override
public void run() {
final java.lang.Thread t = glWindow.setExclusiveContextThread(null);
if(glWindow.getParent()==null) {
@@ -103,9 +105,7 @@ public class NewtReparentingKeyAdapter extends NEWTDemoListener {
final CapabilitiesImmutable reqCaps = win.getRequestedCapabilities();
final CapabilitiesImmutable caps = null != chosenCaps ? chosenCaps : reqCaps;
final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl";
- final float[] sDPI = win.getPixelsPerMM(new float[2]);
- sDPI[0] *= 25.4f;
- sDPI[1] *= 25.4f;
+ final float[] sDPI = FontScale.perMMToPerInch( win.getPixelsPerMM(new float[2]) );
win.setTitle("GLWindow["+capsA+"], win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()+", sDPI "+sDPI[0]+" x "+sDPI[1]);
}
}