summaryrefslogtreecommitdiffstats
path: root/src/jogamp
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2011-03-25 03:48:01 +0100
committerSven Gothel <[email protected]>2011-03-25 03:48:01 +0100
commit49379f06ceefeaa795af05b1c890047176fe19ef (patch)
treeab69e049d49028f0ca9fe915101416fa9170ae4b /src/jogamp
parent524a7d61a4fc4a4d38aeb543b9887e787555bb71 (diff)
Add generic Font and impl TypecastFont.
Diffstat (limited to 'src/jogamp')
-rw-r--r--src/jogamp/graph/font/JavaFontLoader.java111
-rw-r--r--src/jogamp/graph/font/typecast/TypecastFont.java178
-rw-r--r--src/jogamp/graph/font/typecast/TypecastFontFactory.java65
-rw-r--r--src/jogamp/graph/font/typecast/TypecastGlyph.java269
-rw-r--r--src/jogamp/graph/font/typecast/TypecastMetrics.java87
-rw-r--r--src/jogamp/graph/font/typecast/TypecastRenderer.java162
6 files changed, 872 insertions, 0 deletions
diff --git a/src/jogamp/graph/font/JavaFontLoader.java b/src/jogamp/graph/font/JavaFontLoader.java
new file mode 100644
index 000000000..f6954944d
--- /dev/null
+++ b/src/jogamp/graph/font/JavaFontLoader.java
@@ -0,0 +1,111 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.graph.font;
+
+public class JavaFontLoader {
+
+ static String javaFontPath;
+ static
+ {
+ javaFontPath = System.getProperty("java.home") + "/lib/fonts/";
+ }
+
+ public static final int MAX_BITMAP_FONT_SIZE = 120;
+
+ public static final int MONOSPACED = 1;
+ public static final int SERIF = 2;
+ public static final int SANSERIF = 3;
+ public static final int CURSIVE = 4;
+ public static final int FANTASY = 5;
+
+ final static String availableJavaFontNames[] =
+ {
+ "Lucida Bright Regular",
+ "Lucida Bright Italic",
+ "Lucida Bright Demibold",
+ "Lucida Bright Demibold Italic",
+ "Lucida Sans Regular",
+ "Lucida Sans Demibold",
+ "Lucida Sans Typewriter Regular",
+ "Lucida Sans Typewriter Bold",
+ };
+ static public String[] getAvailableNames()
+ {
+ return availableJavaFontNames;
+ }
+
+ final static String availableJavaFontFileNames[] =
+ {
+ "LucidaBrightRegular.ttf",
+ "LucidaBrightItalic.ttf",
+ "LucidaBrightDemiBold.ttf",
+ "LucidaBrightDemiItalic.ttf",
+ "LucidaSansRegular.ttf",
+ "LucidaSansDemiBold.ttf",
+ "LucidaTypewriterRegular.ttf",
+ "LucidaTypewriterBold.ttf",
+ };
+
+ static public String get(int type)
+ {
+ String font = null;
+
+ switch (type)
+ {
+ case MONOSPACED:
+ font = getByName("Lucida Sans Typewriter Regular");
+ break;
+ case SERIF:
+ font = getByName("Lucida Bright Regular");
+ break;
+ case SANSERIF:
+ font = getByName("Lucida Sans Regular");
+ break;
+ case CURSIVE:
+ font = getByName("Lucida Bright Regular");
+ break;
+ case FANTASY:
+ font = getByName("Lucida Sans Regular");
+ break;
+ }
+
+ return font;
+ }
+
+ static public String getByName(String name)
+ {
+ for (int i=0; i<availableJavaFontNames.length; i++)
+ {
+ if (name.equals(availableJavaFontNames[i]) == true)
+ {
+ return javaFontPath+availableJavaFontFileNames[i];
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/jogamp/graph/font/typecast/TypecastFont.java b/src/jogamp/graph/font/typecast/TypecastFont.java
new file mode 100644
index 000000000..7cc80cc13
--- /dev/null
+++ b/src/jogamp/graph/font/typecast/TypecastFont.java
@@ -0,0 +1,178 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.graph.font.typecast;
+
+import java.io.File;
+import java.io.IOException;
+
+import jogamp.graph.font.JavaFontLoader;
+
+import net.java.dev.typecast.ot.OTFont;
+import net.java.dev.typecast.ot.OTFontCollection;
+import net.java.dev.typecast.ot.table.CmapFormat;
+import net.java.dev.typecast.ot.table.CmapTable;
+import net.java.dev.typecast.ot.table.ID;
+
+import com.jogamp.common.util.IntObjectHashMap;
+import com.jogamp.graph.font.Font;
+import com.jogamp.graph.geom.AABBox;
+import com.jogamp.graph.geom.plane.AffineTransform;
+import com.jogamp.graph.geom.plane.Path2D;
+import com.jogamp.graph.geom.PointTex;
+import com.jogamp.graph.geom.Point;
+
+class TypecastFont implements Font {
+ static final boolean DEBUG = false;
+
+ final Point.Factory<? extends PointTex> pointFactory;
+ final OTFontCollection fontset;
+ final OTFont font;
+ final int size;
+ Metrics metrics;
+ final CmapFormat cmapFormat;
+ int cmapentries;
+ // final IntIntHashMap char2Code;
+ IntObjectHashMap char2Glyph;
+
+ public static TypecastFont create(Point.Factory<? extends PointTex> factory, String name, int size) {
+ String path = JavaFontLoader.getByName(name);
+ OTFontCollection fontset;
+ try {
+ fontset = OTFontCollection.create(new File(path));
+ return new TypecastFont(factory, fontset, size);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public TypecastFont(Point.Factory<? extends PointTex> factory, OTFontCollection fontset, int size) {
+ this.pointFactory = factory;
+ this.fontset = fontset;
+ this.font = fontset.getFont(0);
+ this.size = size;
+
+ CmapTable cmapTable = font.getCmapTable();
+ CmapFormat _cmapFormat = null;
+ /*
+ if(null == _cmapFormat) {
+ _cmapFormat = cmapTable.getCmapFormat(ID.platformMacintosh, ID.encodingASCII);
+ } */
+ if(null == _cmapFormat) {
+ // default unicode
+ _cmapFormat = cmapTable.getCmapFormat(ID.platformMicrosoft, ID.encodingUnicode);
+ }
+ if(null == _cmapFormat) {
+ // maybe a symbol font ?
+ _cmapFormat = cmapTable.getCmapFormat(ID.platformMicrosoft, ID.encodingSymbol);
+ }
+ if(null == _cmapFormat) {
+ throw new RuntimeException("Cannot find a suitable cmap table for font "+font);
+ }
+ cmapFormat = _cmapFormat;
+
+ cmapentries = 0;
+ for (int i = 0; i < cmapFormat.getRangeCount(); ++i) {
+ CmapFormat.Range range = cmapFormat.getRange(i);
+ cmapentries += range.getEndCode() - range.getStartCode() + 1; // end included
+ }
+ if(DEBUG) {
+ System.err.println("num glyphs: "+font.getNumGlyphs());
+ System.err.println("num cmap entries: "+cmapentries);
+ }
+
+ /*
+ char2Code = new IntIntHashMap(cmapentries + cmapentries/4);
+ for (int i = 0; i < cmapFormat.getRangeCount(); ++i) {
+ CmapFormat.Range range = cmapFormat.getRange(i);
+ for (int j = range.getStartCode(); j <= range.getEndCode(); ++j) {
+ final int code = cmapFormat.mapCharCode(j);
+ char2Code.put(j, code);
+ if(code < 50) {
+ System.err.println(" char: " + (int)j + " ( " + (char)j +" ) -> " + code);
+ }
+ }
+ }
+ */
+ char2Glyph = new IntObjectHashMap(cmapentries + cmapentries/4);
+ }
+
+ public String getName() {
+ return fontset.getFileName();
+ }
+
+ public float getSize() {
+ return size;
+ }
+
+ public Metrics getMetrics() {
+ if (metrics == null) {
+ metrics = new TypecastMetrics(this);
+ }
+ return metrics;
+ }
+
+ public Glyph getGlyph(char symbol) {
+ TypecastGlyph result = (TypecastGlyph) char2Glyph.get(symbol);
+ if (null == result) {
+ // final short code = (short) char2Code.get(symbol);
+ final short code = (short) cmapFormat.mapCharCode(symbol);
+ net.java.dev.typecast.ot.OTGlyph glyph = font.getGlyph(code);
+ final Path2D path = TypecastRenderer.buildPath(glyph);
+ result = new TypecastGlyph(this, symbol, code, glyph.getBBox(), glyph.getAdvanceWidth(), path);
+ if(DEBUG) {
+ System.err.println("New glyph: " + (int)symbol + " ( " + (char)symbol +" ) -> " + code + ", contours " + glyph.getPointCount() + ": " + path);
+ }
+ char2Glyph.put(symbol, result);
+ }
+ return result;
+ }
+
+ public void getOutline(String string, AffineTransform transform, Path2D[] result) {
+ TypecastRenderer.getOutline(pointFactory, this, string, transform, result);
+ }
+
+ public float getStringWidth(String string) {
+ // return 0f; // FIXME font.getStringWidthForPixelSize(string, size);
+ throw new RuntimeException("n/a");
+ }
+
+ public float getStringHeight(String string) {
+ // return 0f; // FIXME font.getStringHeightForPixelSize(string, size);
+ throw new RuntimeException("n/a");
+ }
+
+ public AABBox getStringBounds(CharSequence string) {
+ // return null; // FIXME font.getStringBoundsForPixelSize(string, size);
+ throw new RuntimeException("n/a");
+ }
+
+ final public int getNumGlyphs() {
+ return font.getNumGlyphs();
+ }
+} \ No newline at end of file
diff --git a/src/jogamp/graph/font/typecast/TypecastFontFactory.java b/src/jogamp/graph/font/typecast/TypecastFontFactory.java
new file mode 100644
index 000000000..f66772029
--- /dev/null
+++ b/src/jogamp/graph/font/typecast/TypecastFontFactory.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.graph.font.typecast;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.jogamp.graph.font.Font;
+import com.jogamp.graph.font.FontFactory;
+import com.jogamp.graph.geom.Point.Factory;
+import com.jogamp.graph.geom.PointTex;
+
+
+public class TypecastFontFactory implements FontFactory {
+
+ Map<String, Font> fonts = new HashMap<String, Font>();
+
+ public Font createFont(Factory<? extends PointTex> factory, String name, int size) {
+ Font result = fonts.get(name + ":"+size);
+ if (result == null) {
+ result = TypecastFont.create(factory, name, size);
+ if(result != null) {
+ fonts.put(name+":"+size, result);
+ }
+ }
+ return result;
+ }
+
+
+ public Font createFont(Factory<? extends PointTex> factory,
+ String[] families,
+ String style,
+ String variant,
+ String weight,
+ String size) {
+ throw new Error("not implemented");
+ }
+
+
+} \ No newline at end of file
diff --git a/src/jogamp/graph/font/typecast/TypecastGlyph.java b/src/jogamp/graph/font/typecast/TypecastGlyph.java
new file mode 100644
index 000000000..faca8c779
--- /dev/null
+++ b/src/jogamp/graph/font/typecast/TypecastGlyph.java
@@ -0,0 +1,269 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.graph.font.typecast;
+
+import com.jogamp.graph.font.Font;
+import com.jogamp.graph.geom.AABBox;
+import com.jogamp.graph.geom.plane.AffineTransform;
+import com.jogamp.graph.geom.plane.Path2D;
+
+public class TypecastGlyph implements Font.Glyph {
+ public class Advance
+ {
+ Font font;
+ float advance;
+ float advances[]; // in pixels
+ float sizes[];
+ float advanceCached = -1; // in pixels
+ float sizeCached = -1;
+
+ public Advance(Font font, float advance)
+ {
+ this.font = font;
+ this.advance = advance;
+
+ this.advances = new float[0];
+ this.sizes = new float[0];
+ }
+
+ public float getScaleForPixelSize(float pixelSize)
+ {
+ return this.font.getMetrics().getScaleForPixelSize(pixelSize);
+ }
+
+ public void add(float advance, float size)
+ {
+ float advancesNew[] = new float[this.advances.length+1];
+ float sizesNew[] = new float[this.sizes.length+1];
+
+ for (int i=0; i<this.advances.length; i++) {
+ advancesNew[i] = this.advances[i];
+ sizesNew[i] = this.sizes[i];
+ }
+
+ advancesNew[advancesNew.length-1] = advance;
+ sizesNew[sizesNew.length-1] = size;
+
+ this.advances = advancesNew;
+ this.sizes = sizesNew;
+ }
+
+ public float get(float size, boolean useFrationalMetrics)
+ {
+ if (this.sizeCached != size) {
+ this.sizeCached = size;
+
+ float value = (this.advance * getScaleForPixelSize(size));
+ if (useFrationalMetrics == false) {
+ //value = (float)Math.ceil(value);
+ // value = (int)value;
+ value = (int) ( value + 0.5f ) ; // TODO: check
+ }
+
+ if (true)
+ {
+ for (int i=0; i<this.advances.length; i++)
+ {
+ if (this.sizes[i] == size)
+ {
+ value = this.advances[i];
+ break;
+ }
+ }
+ }
+
+ this.advanceCached = value;
+ }
+ return this.advanceCached;
+ }
+
+ public String toString()
+ {
+ String string = "";
+ for (int i=0; i<this.advances.length; i++) {
+ string += " size: "+this.sizes[i]+" advance: "+this.advances[i]+"\n";
+ }
+ if (string.length() > 0) {
+ string = "\n advances: \n"+string;
+ }
+ return "\nAdvance:"+
+ "\n advance: "+this.advance+
+ string;
+ }
+ }
+
+ public class Metrics
+ {
+ AABBox bbox;
+ AABBox bbox_sized;
+ Advance advance;
+
+ public Metrics(Font font, AABBox bbox, float advance)
+ {
+ this.bbox = bbox;
+ this.advance = new Advance(font, advance);
+ }
+
+ public float getScaleForPixelSize(float pixelSize)
+ {
+ return this.advance.getScaleForPixelSize(pixelSize);
+ }
+
+ public AABBox getBBox()
+ {
+ return this.bbox;
+ }
+
+ public void addAdvance(float advance, float size)
+ {
+ this.advance.add(advance, size);
+ }
+
+ public float getAdvanceForPixelSize(float size, boolean useFrationalMetrics)
+ {
+ return this.advance.get(size, useFrationalMetrics);
+ }
+
+ public String toString()
+ {
+ return "\nMetrics:"+
+ "\n bbox: "+this.bbox+
+ this.advance;
+ }
+ }
+
+ public static final short INVALID_ID = (short)((1 << 16) - 1);
+ public static final short MAX_ID = (short)((1 << 16) - 2);
+
+ private final Font font;
+
+ char symbol;
+ short id;
+ int advance;
+ Metrics metrics;
+
+ protected Path2D path; // in EM units
+ protected Path2D pathSized;
+ protected float numberSized;
+
+ protected TypecastGlyph(Font font, char symbol) {
+ this.font = font;
+ this.symbol = symbol;
+ }
+
+ protected TypecastGlyph(Font font,
+ char symbol, short id, AABBox bbox, int advance, Path2D path) {
+ this.font = font;
+ this.symbol = symbol;
+ this.advance = advance;
+
+ init(id, bbox, advance);
+
+ this.path = path;
+ this.pathSized = null;
+ this.numberSized = 0.0f;
+ }
+
+ void init(short id, AABBox bbox, int advance) {
+ this.id = id;
+ this.advance = advance;
+ this.metrics = new Metrics(this.font, bbox, this.advance);
+ }
+
+ public Font getFont() {
+ return this.font;
+ }
+
+ public char getSymbol() {
+ return this.symbol;
+ }
+
+ AABBox getBBoxUnsized() {
+ return this.metrics.getBBox();
+ }
+
+ public AABBox getBBox() {
+ return this.metrics.getBBox();
+ }
+
+ public Metrics getMetrics() {
+ return this.metrics;
+ }
+
+ public short getID() {
+ return this.id;
+ }
+
+ public float getScaleForPixelSize(float pixelSize) {
+ return this.metrics.getScaleForPixelSize(pixelSize);
+ }
+
+ public AABBox getBBox(float size) {
+ AABBox newBox = getBBox().clone();
+ newBox.scale(size);
+ return newBox;
+ }
+
+ public AABBox getBBoxForPixelSize(float pixelSize) {
+ return getBBox(getScaleForPixelSize(pixelSize));
+ }
+
+ protected void addAdvance(float advance, float size) {
+ this.metrics.addAdvance(advance, size);
+ }
+
+ public float getAdvanceForPixelSize(float size, boolean useFrationalMetrics) {
+ return this.metrics.getAdvanceForPixelSize(size, useFrationalMetrics);
+ }
+
+ public float getAdvance() {
+ return getAdvanceForPixelSize(font.getSize(), false);
+ }
+
+ public Path2D getPath() {
+ return getPath(getScaleForPixelSize(font.getSize()));
+ }
+
+ private Path2D getPath(float size)
+ {
+ if (this.numberSized != size) {
+ this.numberSized = size;
+ this.pathSized = AffineTransform.getScaleInstance(null, size, size).createTransformedShape(getPath());
+ }
+ return this.pathSized;
+ }
+
+ public Path2D getPathForPixelSize(float pixelSize) {
+ return getPath(getScaleForPixelSize(pixelSize));
+ }
+
+ public Path2D getNormalPath() {
+ return this.path;
+ }
+
+}
diff --git a/src/jogamp/graph/font/typecast/TypecastMetrics.java b/src/jogamp/graph/font/typecast/TypecastMetrics.java
new file mode 100644
index 000000000..541ed90d8
--- /dev/null
+++ b/src/jogamp/graph/font/typecast/TypecastMetrics.java
@@ -0,0 +1,87 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.graph.font.typecast;
+
+import net.java.dev.typecast.ot.table.HeadTable;
+import net.java.dev.typecast.ot.table.HheaTable;
+
+import com.jogamp.graph.font.Font.Metrics;
+import com.jogamp.graph.geom.AABBox;
+
+class TypecastMetrics implements Metrics {
+ private final TypecastFont fontImpl;
+
+ // HeadTable
+ private final float unitsPerEM_Inv;
+ private final float unitsPerEM_Inv_sized;
+ private final AABBox bbox_sized;
+
+ // HheaTable
+ private final float ascend_sized;
+ private final float descent_sized;
+ private final float linegap_sized;
+
+ public TypecastMetrics(TypecastFont fontImpl) {
+ this.fontImpl = fontImpl;
+ final HeadTable headTable = this.fontImpl.font.getHeadTable();
+ unitsPerEM_Inv = 1.0f / ( (float) headTable.getUnitsPerEm() );
+ unitsPerEM_Inv_sized = this.fontImpl.size * unitsPerEM_Inv;
+ int maxWidth = headTable.getXMax() - headTable.getXMin();
+ int maxHeight = headTable.getYMax() - headTable.getYMin();
+ float lowx= headTable.getXMin();
+ float lowy = -(headTable.getYMin()+maxHeight);
+ float highx = lowx + maxWidth;
+ float highy = lowy + maxHeight;
+ bbox_sized = new AABBox(lowx, lowy, 0, highx, highy, 0); // invert
+ bbox_sized.scale(unitsPerEM_Inv_sized);
+
+ final HheaTable hheaTable = this.fontImpl.font.getHheaTable();
+ ascend_sized = unitsPerEM_Inv_sized * -hheaTable.getAscender(); // invert
+ descent_sized = unitsPerEM_Inv_sized * -hheaTable.getDescender(); // invert
+ linegap_sized = unitsPerEM_Inv_sized * -hheaTable.getLineGap(); // invert
+ }
+
+ public final float getAscent() {
+ return ascend_sized;
+ }
+ public final float getDescent() {
+ return descent_sized;
+ }
+ public final float getLineGap() {
+ return linegap_sized;
+ }
+ public final float getScale() {
+ return unitsPerEM_Inv_sized;
+ }
+ public float getScaleForPixelSize(float pixelSize) {
+ return pixelSize * unitsPerEM_Inv;
+ }
+ public final AABBox getBBox() {
+ return bbox_sized;
+ }
+} \ No newline at end of file
diff --git a/src/jogamp/graph/font/typecast/TypecastRenderer.java b/src/jogamp/graph/font/typecast/TypecastRenderer.java
new file mode 100644
index 000000000..7b36d22b5
--- /dev/null
+++ b/src/jogamp/graph/font/typecast/TypecastRenderer.java
@@ -0,0 +1,162 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.graph.font.typecast;
+
+import com.jogamp.graph.font.Font;
+import com.jogamp.graph.geom.plane.AffineTransform;
+import com.jogamp.graph.geom.plane.Path2D;
+import com.jogamp.graph.geom.PointTex;
+import com.jogamp.graph.geom.Point.Factory;
+
+import net.java.dev.typecast.ot.Point;
+import net.java.dev.typecast.ot.OTGlyph;
+
+/**
+ * Factory to build a {@link com.jogamp.graph.geom.Path2D Path2D} from
+ * {@link net.java.dev.typecast.ot.OTGlyph Glyph}s.
+ */
+public class TypecastRenderer {
+
+ public static void getOutline(Factory<? extends PointTex> factory, TypecastFont font,
+ String string, AffineTransform transform, Path2D[] p)
+ {
+ if (string == null) {
+ return;
+ }
+ Font.Metrics metrics = font.getMetrics();
+ float advanceTotal = 0;
+ float lineGap = metrics.getLineGap() ;
+ float ascent = metrics.getAscent() ;
+ float descent = metrics.getDescent() ;
+ if (transform == null) {
+ transform = new AffineTransform(factory);
+ }
+ AffineTransform t = new AffineTransform(factory);
+
+ float advanceY = lineGap - descent + ascent;
+ float y = 0;
+ for (int i=0; i<string.length(); i++)
+ {
+ p[i] = new Path2D();
+ p[i].reset();
+ t.setTransform(transform);
+ char character = string.charAt(i);
+ if (character == '\n') {
+ y -= advanceY;
+ advanceTotal = 0;
+ continue;
+ }
+ TypecastGlyph glyph = (TypecastGlyph) font.getGlyph(character);
+ Path2D gp = glyph.getNormalPath();
+ float scale = metrics.getScale();
+ t.translate(advanceTotal, y);
+ t.scale(scale, scale);
+ p[i].append(gp.iterator(t), false);
+ advanceTotal += glyph.getAdvanceForPixelSize(font.getSize(), true);
+ }
+ }
+
+ /**
+ * Build a {@link com.jogamp.graph.geom.Path2D Path2D} from a
+ * {@link net.java.dev.typecast.ot.OTGlyph Glyph}. This glyph path can then
+ * be transformed and rendered.
+ */
+ public static Path2D buildPath(OTGlyph glyph) {
+
+ if (glyph == null) {
+ return null;
+ }
+
+ Path2D glyphPath = new Path2D();
+
+ // Iterate through all of the points in the glyph. Each time we find a
+ // contour end point, add the point range to the path.
+ int firstIndex = 0;
+ int count = 0;
+ for (int i = 0; i < glyph.getPointCount(); i++) {
+ count++;
+ if (glyph.getPoint(i).endOfContour) {
+ addContourToPath(glyphPath, glyph, firstIndex, count);
+ firstIndex = i + 1;
+ count = 0;
+ }
+ }
+ return glyphPath;
+ }
+
+ private static void addContourToPath(Path2D gp, OTGlyph glyph, int startIndex, int count) {
+ int offset = 0;
+ while (offset < count) {
+ Point point = glyph.getPoint(startIndex + offset%count);
+ Point point_plus1 = glyph.getPoint(startIndex + (offset+1)%count);
+ Point point_plus2 = glyph.getPoint(startIndex + (offset+2)%count);
+ if(offset == 0)
+ {
+ gp.moveTo(point.x, -point.y);
+ }
+
+ if (point.onCurve) {
+ if (point_plus1.onCurve) {
+ // s = new Line2D.Float(point.x, -point.y, point_plus1.x, -point_plus1.y);
+ gp.lineTo( point_plus1.x, -point_plus1.y );
+ offset++;
+ } else {
+ if (point_plus2.onCurve) {
+ // s = new QuadCurve2D.Float( point.x, -point.y, point_plus1.x, -point_plus1.y, point_plus2.x, -point_plus2.y);
+ gp.quadTo(point_plus1.x, -point_plus1.y, point_plus2.x, -point_plus2.y);
+ offset+=2;
+ } else {
+ // s = new QuadCurve2D.Float(point.x,-point.y,point_plus1.x,-point_plus1.y,
+ // midValue(point_plus1.x, point_plus2.x), -midValue(point_plus1.y, point_plus2.y));
+ gp.quadTo(point_plus1.x, -point_plus1.y, midValue(point_plus1.x, point_plus2.x), -midValue(point_plus1.y, point_plus2.y));
+ offset+=2;
+ }
+ }
+ } else {
+ if (point_plus1.onCurve) {
+ // s = new QuadCurve2D.Float(midValue(point_minus1.x, point.x), -midValue(point_minus1.y, point.y),
+ // point.x, -point.y, point_plus1.x, -point_plus1.y);
+ //gp.curve3(point_plus1.x, -point_plus1.y, point.x, -point.y);
+ gp.quadTo(point.x, -point.y, point_plus1.x, -point_plus1.y);
+ offset++;
+
+ } else {
+ // s = new QuadCurve2D.Float(midValue(point_minus1.x, point.x), -midValue(point_minus1.y, point.y), point.x, -point.y,
+ // midValue(point.x, point_plus1.x), -midValue(point.y, point_plus1.y));
+ //gp.curve3(midValue(point.x, point_plus1.x), -midValue(point.y, point_plus1.y), point.x, -point.y);
+ gp.quadTo(point.x, -point.y, midValue(point.x, point_plus1.x), -midValue(point.y, point_plus1.y));
+ offset++;
+ }
+ }
+ }
+ }
+
+ private static int midValue(int a, int b) {
+ return a + (b - a)/2;
+ }
+}