/***********************************************************************
* mt4j Copyright (c) 2008 - 2009, C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
***********************************************************************/
package org.mt4j.components.visibleComponents.font.fontFactories;
import java.awt.Toolkit;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import org.apache.batik.svggen.font.Font;
import org.apache.batik.svggen.font.Glyph;
import org.apache.batik.svggen.font.Point;
import org.apache.batik.svggen.font.table.CmapFormat;
import org.apache.batik.svggen.font.table.Table;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.SimpleLayout;
import org.mt4j.components.visibleComponents.font.VectorFont;
import org.mt4j.components.visibleComponents.font.VectorFontCharacter;
import org.mt4j.util.MT4jSettings;
import org.mt4j.util.MTColor;
import org.mt4j.util.UnitTranslator;
import org.mt4j.util.math.Vector3D;
import org.mt4j.util.math.Vertex;
import org.mt4j.util.xml.svg.CustomPathHandler;
import processing.core.PApplet;
/**
* A factory for creating vector font objects.
* @author Christopher Ruff
*/
public class TTFontFactory implements IFontFactory{
/** The Constant logger. */
private static final Logger logger = Logger.getLogger(TTFontFactory.class.getName());
static{
// logger.setLevel(Level.ERROR);
logger.setLevel(Level.WARN);
// logger.setLevel(Level.DEBUG);
SimpleLayout l = new SimpleLayout();
ConsoleAppender ca = new ConsoleAppender(l);
logger.addAppender(ca);
}
public static String defaultCharacters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜabcdefghijklmnopqrstuvwxyzäöü<>|,;.:-_#'+*!\"§$%&/()=?´{[]}\\@";
// //Register the factory
// static{
// //FIXME not working!!? never gets called
// FontManager.getInstance().registerFontFactory(".ttf", new TTFontFactory());
// }
private PApplet pa;
private Font f;
private float scaleFactor;
private short unitsPerEm;
private int fontDefaultXAdvancing;
private int fontSize;
private String fontPath;
private boolean antiAliasing;
public TTFontFactory(){
// this.fontPath = fontPath;
// this.f = Font.create(fontPath);
// this.setSize(50);
// this.fontDefaultXAdvancing = 500;
// this.fontSize = 50;
// this.unitsPerEm = f.getHeadTable().getUnitsPerEm();
}
public VectorFont createFont(PApplet pa, String fontFileName){
return this.createFont(pa, fontFileName, 50, new MTColor(0,0,0,255), new MTColor(0,0,0,255));
}
public VectorFont createFont(
PApplet pa,
String fontFileName,
int fontSize,
MTColor fillColor,
MTColor strokeColor)
{
return this.createFont(pa, fontFileName, fontSize, fillColor, strokeColor, true);
}
/* (non-Javadoc)
* @see mTouch.components.visibleComponents.font.IFontFactory#loadFont(processing.core.PApplet, java.lang.String, int, float, float, float, float, float, float, float, float)
*/
public VectorFont createFont(
PApplet pa,
String fontFileName,
int fontSize,
MTColor fillColor,
MTColor strokeColor,
boolean antiAliasing
){
// //INITIAL SETTINGS
// this.pa = pa;
// this.fontPath = svgFontFileName;
// this.f = Font.create(fontPath);
// this.setSize(fontSize);
// this.fontDefaultXAdvancing = 500; //TODO can we get this from somewhere?
// this.fontSize = fontSize;
// this.unitsPerEm = f.getHeadTable().getUnitsPerEm();
// ///
//
// //Get the desired fontsize scaling factor
// short unitsPerEm = f.getHeadTable().getUnitsPerEm();
// int resolution = Toolkit.getDefaultToolkit().getScreenResolution();
// //logger.info("Screen resolution: " + resolution);
//
// //This calculates the font in "pt" point size (used in windows)
// this.scaleFactor = ((float)fontSize * (float)resolution) / (72F * (float)unitsPerEm); //original
//
// //FIXME TEST
// float test = UnitTranslator.pointsToPixels(scaleFactor*fontSize, Math.round(resolution));
//// test = Math.round((float)fontSize/(float)unitsPerEm);
// //This calculates the font size in..pixels? at least same as in svg
// test = (float)(1.0/(float)this.unitsPerEm) * fontSize;
// this.scaleFactor = test;
//
// //System.out.println("->Scalefactor: " + this.scaleFactor);
//
// //CREATE FONT CHARACTERS
// VectorFontCharacter[] chars = this.getTTFCharacters(f, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ���abcdefghijklmnopqrstuvwxyz���<>|,;.:-_#'+*!\"�$%&/()=?�~��{[]}\\^�@�"
// ,fillColor, strokeColor, scaleFactor);
VectorFontCharacter[] chars = this.getTTFCharacters(
pa,
defaultCharacters,
fillColor,
strokeColor,
fontFileName,
fontSize,
antiAliasing);
VectorFontCharacter[] newArray = new VectorFontCharacter[chars.length+3];
System.arraycopy(chars, 0, newArray, 0, chars.length);
//Manually add a NEWLINE character to the font
Vertex[] nlVerts = new Vertex[]{new Vertex(0,0,0), new Vertex(200,0,0),new Vertex(200,100,0),/*new Vertex(0,100,0)*/};
ArrayList<Vertex[]> nlContours = new ArrayList<Vertex[]>();
nlContours.add(nlVerts);
VectorFontCharacter newLine = new VectorFontCharacter(nlContours, pa);
newLine.setPickable(false);
newLine.setVisible(false);
newLine.setNoFill(true);
newLine.setNoStroke(true);
newLine.setHorizontalDist(0);
newLine.setUnicode("\n");
newLine.setName("newline");
newArray[newArray.length-3] = newLine;
//Manually add a SPACE character to the font
// int charIndex = this.getCmapFormat(f).mapCharCode(32);
int charIndex = this.getCmapFormat(f).mapCharCode('i');
// int charIndex = this.getCmapFormat(f).mapCharCode('-');
int default_advance_x = f.getHmtxTable().getAdvanceWidth(charIndex);
Glyph glyph = f.getGlyph(charIndex);
int xadvance = 0;
if (glyph != null){
// xadvance = Math.round((default_advance_x * (float)(1.0/(float)this.unitsPerEm)) * fontSize);
xadvance = Math.round(default_advance_x * this.scaleFactor);
}else{
// xadvance = Math.round((fontDefaultXAdvancing * (float)(1.0/(float)this.unitsPerEm)) * fontSize);
xadvance = Math.round(fontDefaultXAdvancing * this.scaleFactor);
}
Vertex[] spaceVerts = new Vertex[]{new Vertex(0,0,0), new Vertex(xadvance,0,0),new Vertex(xadvance,100,0), /*new Vertex(0,100,0)*/};
ArrayList<Vertex[]> spaceContours = new ArrayList<Vertex[]>();
spaceContours.add(spaceVerts);
VectorFontCharacter space = new VectorFontCharacter(spaceContours, pa);
space.setPickable(false);
space.setVisible(false);
space.setNoFill(true);
space.setNoStroke(true);
space.setHorizontalDist(xadvance);
space.setUnicode(" ");
space.setName("space");
newArray[newArray.length-2] = space;
//Manually add a TAB character to the font
int defaultTabWidth = fontDefaultXAdvancing*4;
Vertex[] tabVerts = new Vertex[]{new Vertex(0,0,0), new Vertex(200,0,0),new Vertex(200,100,0),/*new Vertex(0,100,0)*/};
ArrayList<Vertex[]> tabContours = new ArrayList<Vertex[]>();
tabContours.add(tabVerts);
VectorFontCharacter tab = new VectorFontCharacter(tabContours, pa);
tab.setPickable(false);
try {
int tabWidth = 4 * space.getHorizontalDist();
tab.setHorizontalDist(tabWidth);
tab.setVertices(new Vertex[]{new Vertex(0,0,0), new Vertex(tabWidth,0,0),new Vertex(tabWidth,100,0),/*new Vertex(0,100,0)*/} );
} catch (Exception e) {
tab.setHorizontalDist(defaultTabWidth);
}
tab.setUnicode("\t");
tab.setName("tab");
tab.setVisible(false);
tab.setNoFill(true);
tab.setNoStroke(true);
newArray[newArray.length-1] = tab;
////////
int fontMaxAscent = f.getAscent();
int fontMaxDescent = f.getDescent();
//Set font max descent and ascent according to font size
// float tmp = fontMaxAscent * (float)(1.0/(float)this.unitsPerEm);
// fontMaxAscent = Math.round(tmp * fontSize);
// float tmp2 = fontMaxDescent * (float)(1.0/(float)this.unitsPerEm);
// fontMaxDescent = Math.round(tmp2 * fontSize);
fontMaxAscent = Math.round(fontMaxAscent * this.scaleFactor);
fontMaxDescent = Math.round(fontMaxDescent * this.scaleFactor);
//Create Font
VectorFont vectorFont = new VectorFont(newArray, fontDefaultXAdvancing, this.getFamily(f), fontMaxAscent, fontMaxDescent, this.unitsPerEm, fontSize,
fillColor,
strokeColor,
antiAliasing);
vectorFont.setFontFileName(fontPath);
vectorFont.setFontId("-1");
return vectorFont;
}
/*
public SvgFont getFont(){
SvgFontCharacter[] chars = this.getTTFCharacters("123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ���abcdefghijklmnopqrstuvwxyz���<>|,;.:-_#'+*!\"�$%&/()=?��~#��456{[]}\\^�@�");
SvgFontCharacter[] newArray = new SvgFontCharacter[chars.length+3];
System.arraycopy(chars, 0, newArray, 0, chars.length);
//Manually add a NEWLINE character to the font
SvgFontCharacter newLine = new SvgFontCharacter(new Vertex[]{new Vertex(0,0,0), new Vertex(200,0,0),new Vertex(200,100,0),new Vertex(0,100,0)}, new ArrayList<Vertex[]>(), pa);
newLine.setPickable(false);
newLine.setVisible(false);
newLine.setHorizontalDist(0);
newLine.setUnicode("\n");
newLine.setName("newline");
newArray[newArray.length-3] = newLine;
//Manually add a SPACE character to the font
int charIndex = this.getCmapFormat(f).mapCharCode(32);
int default_advance_x = f.getHmtxTable().getAdvanceWidth(charIndex);
Glyph glyph = f.getGlyph(charIndex);
int xadvance = 0;
if (glyph != null){
xadvance = Math.round((default_advance_x * (float)(1.0/(float)this.unitsPerEm)) * fontSize);
}else{
xadvance = Math.round((fontDefaultXAdvancing * (float)(1.0/(float)this.unitsPerEm)) * fontSize);
}
SvgFontCharacter space = new SvgFontCharacter(new Vertex[]{new Vertex(0,0,0), new Vertex(xadvance,0,0),new Vertex(xadvance,100,0),new Vertex(0,100,0)}, new ArrayList<Vertex[]>(), pa);
space.setPickable(false);
space.setVisible(false);
space.setHorizontalDist(xadvance);
space.setUnicode(" ");
space.setName("space");
newArray[newArray.length-2] = space;
logger.info("Advance of character space " + charIndex + " :" + default_advance_x);
//Manually add a TAB character to the font
int defaultTabWidth = fontDefaultXAdvancing*4;
SvgFontCharacter tab = new SvgFontCharacter(new Vertex[]{new Vertex(0,0,0), new Vertex(defaultTabWidth,0,0),new Vertex(defaultTabWidth,100,0),new Vertex(0,100,0)}, new ArrayList<Vertex[]>(), pa);
tab.setPickable(false);
try {
int tabWidth = 4*space.getHorizontalDist();
tab.setHorizontalDist(tabWidth);
tab.setVerticesLocal(new Vertex[]{new Vertex(0,0,0), new Vertex(tabWidth,0,0),new Vertex(tabWidth,100,0),new Vertex(0,100,0)} );
tab.setUseBoundingPickRect();
} catch (Exception e) {
tab.setHorizontalDist(defaultTabWidth);
}
tab.setUnicode("tab");
tab.setName("tab");
tab.setVisible(false);
newArray[newArray.length-1] = tab;
////////
int fontMaxAscent = f.getAscent();
int fontMaxDescent = f.getDescent();
//Set font max descent and ascent according to font size
float tmp = fontMaxAscent * (float)(1.0/(float)this.unitsPerEm);
fontMaxAscent = Math.round(tmp * fontSize);
float tmp2 = fontMaxDescent * (float)(1.0/(float)this.unitsPerEm);
fontMaxDescent = Math.round(tmp2 * fontSize);
//Create Font
SvgFont svgFont = new SvgFont(newArray, fontDefaultXAdvancing, this.getFamily(), fontMaxAscent, fontMaxDescent,this.unitsPerEm, fontSize);
svgFont.setFontFileName(fontPath);
svgFont.setFontId("-1");
return svgFont;
}
*/
/**
* Gets the tTF characters.
*
* @param pa the pa
* @param text the text
* @param fillColor the fill color
* @param strokeColor the stroke color
* @param fontFileName the font file name
* @param fontSize the font size
* @return the tTF characters
*/
public VectorFontCharacter[] getTTFCharacters(
PApplet pa,
String text,
MTColor fillColor,
MTColor strokeColor,
String fontFileName,
int fontSize
) {
return this.getTTFCharacters(pa, text, fillColor, strokeColor, fontFileName, fontSize, true);
}
/**
* Gets the TTFont characters.
* This does essentially the same as createFont()
* but you can specify the characters to create in the string parameter.
*
* @param pa the pa
* @param text the text
* @param fillColor the fill color
* @param strokeColor the stroke color
* @param fontFileName the font file name
* @param fontSize the font size
* @param antiAliasing the anti aliasing
* @return the tTF characters
*/
public VectorFontCharacter[] getTTFCharacters(
PApplet pa,
String text,
MTColor fillColor,
MTColor strokeColor,
String fontFileName,
int fontSize,
boolean antiAliasing
) {
this.pa = pa;
this.fontPath = fontFileName;
this.antiAliasing = antiAliasing;
File fontFile = new File(fontPath);
if (fontFile.exists()){
//do it as usual
this.f = Font.create(fontPath);
}else{
logger.debug("Couldnt find font file: " + fontPath + " - trying to load from classpath by extracting .ttf file to a temporary directory.");
InputStream in = null;
in = Thread.currentThread().getContextClassLoader().getResourceAsStream(fontFileName);
if (in == null){
in = getClass().getResourceAsStream(fontFileName);
}
if (in == null)
logger.error("Couldnt load the font: " + fontPath + " from the classpath.");
//Need to create a tmp file since Font.create() needs a File! :(
try {
File tmpFile = File.createTempFile("tmpFont", ".ttf"); //TODO get font name !? //TODO works from JNLP/JAR?
tmpFile.deleteOnExit();
FileOutputStream fo = new FileOutputStream(tmpFile);
byte[] buffer = new byte[2048];
int tmp = 0;
while ((tmp = in.read(buffer)) != -1){
fo.write(buffer, 0, tmp);
}
fo.flush();
fo.close();
//FileOutputStream fo = new FileOutputStream(new File(""));
this.f = Font.create(tmpFile.getPath());
} catch (IOException e) {
e.printStackTrace();
}
}
//TODO Load directly from stream?
// File f = new FileCacheImageInputStream(arg0, arg1)
if (f == null || f.getHeadTable() == null){
logger.error("Couldnt load font: " + fontPath);
return new VectorFontCharacter[]{};
}
this.setSize(fontSize);
this.fontDefaultXAdvancing = 500; //TODO can we get this from somewhere?
this.fontSize = fontSize;
this.unitsPerEm = f.getHeadTable().getUnitsPerEm();
///
//Get the desired fontsize scaling factor
short unitsPerEm = f.getHeadTable().getUnitsPerEm();
int resolution = Toolkit.getDefaultToolkit().getScreenResolution();
//System.out.println("Screen resolution: " + resolution);
//This calculates the font in "pt" point size (used in windows)
this.scaleFactor = ((float)fontSize * (float)resolution) / (72F * (float)unitsPerEm); //original
//FIXME TEST
float test = UnitTranslator.pointsToPixels(scaleFactor*fontSize, Math.round(resolution));
// test = Math.round((float)fontSize/(float)unitsPerEm);
//This calculates the font size in..pixels? at least same as in svg
test = (float)(1.0/(float)this.unitsPerEm) * fontSize;
this.scaleFactor = test;
//logger.info("->Scalefactor: " + this.scaleFactor);
//CREATE FONT CHARACTERS
VectorFontCharacter[] chars = this.createTTFCharacters(f, text, fillColor, strokeColor, scaleFactor);
return chars;
}
/**
* Creates new TTFont characters.
*
* @param f the f
* @param text the text
* @param fillColor the fill color
* @param strokeColor the stroke color
* @param scaleFactor the scale factor
* @return the vector font character[]
* @throws RuntimeException the runtime exception
*/
private VectorFontCharacter[] createTTFCharacters(Font f, String text,
MTColor fillColor,
MTColor strokeColor,
float scaleFactor
)throws RuntimeException{
// Decide upon a cmap table to use for our character to glyph look-up
CmapFormat cmapFmt = this.getCmapFormat(f);
if (cmapFmt == null) {
// throw new RuntimeException("Cannot find a suitable cmap table");
logger.error("Cannot find a suitable cmap table");
return new VectorFontCharacter[]{};
}
// If this font includes arabic script, we want to specify
// substitutions for initial, medial, terminal & isolated
// cases.
/*
GsubTable gsub = (GsubTable) f.getTable(Table.GSUB);
SingleSubst initialSubst = null;
SingleSubst medialSubst = null;
SingleSubst terminalSubst = null;
if (gsub != null) {
Script s = gsub.getScriptList().findScript(ScriptTags.SCRIPT_TAG_ARAB);
if (s != null) {
LangSys ls = s.getDefaultLangSys();
if (ls != null) {
Feature init = gsub.getFeatureList().findFeature(ls, FeatureTags.FEATURE_TAG_INIT);
Feature medi = gsub.getFeatureList().findFeature(ls, FeatureTags.FEATURE_TAG_MEDI);
Feature fina = gsub.getFeatureList().findFeature(ls, FeatureTags.FEATURE_TAG_FINA);
initialSubst = (SingleSubst)
gsub.getLookupList().getLookup(init, 0).getSubtable(0);
medialSubst = (SingleSubst)
gsub.getLookupList().getLookup(medi, 0).getSubtable(0);
terminalSubst = (SingleSubst)
gsub.getLookupList().getLookup(fina, 0).getSubtable(0);
}
}
}*/
ArrayList<VectorFontCharacter> characters = new ArrayList<VectorFontCharacter>();
int x = 0;
for (short i = 0; i < text.length(); i++) {
int glyphIndex = cmapFmt.mapCharCode(text.charAt(i));
Glyph glyph = f.getGlyph(glyphIndex);
int default_advance_x = f.getHmtxTable().getAdvanceWidth(glyphIndex);
if (glyph != null) {
// glyph.scale(Math.round(scaleFactor)); //Scaling has changed to int!?
// Add the Glyph to the Shape with an horizontal offset of x
VectorFontCharacter fontChar = getGlyphAsShape(f, glyph, glyphIndex, x, fillColor, strokeColor);
if (fontChar != null){
//Sets characters horizontal advancement and unicode value
fontChar.setHorizontalDist(default_advance_x);
// float tmp = fontChar.getHorizontalDist() * (float)(1.0/(float)this.unitsPerEm);
// fontChar.setHorizontalDist(Math.round(tmp * fontSize));
fontChar.setHorizontalDist(Math.round(fontChar.getHorizontalDist() * scaleFactor)); //FIXME TRIAL
fontChar.setUnicode(Character.toString(text.charAt(i)));
fontChar.setName(Character.toString(text.charAt(i)));
characters.add(fontChar);
}
x += glyph.getAdvanceWidth();
}else{
logger.error("Couldnt find character: \"" + text.charAt(i) + "\" in " + fontPath);
x += (int)((float)default_advance_x /* *scaleFactor */);
}
}
VectorFontCharacter[] chars = characters.toArray(new VectorFontCharacter[characters.size()]);
return chars;
}
/**
*
* @param font
* @param glyph
* @param glyphIndex
* @param xadv
* @return
*/
private VectorFontCharacter getGlyphAsShape(
Font font,
Glyph glyph,
int glyphIndex,
float xadv,
MTColor fillColor,
MTColor strokeColor
) {
int firstIndex = 0;
int count = 0;
int i;
ArrayList<Vertex[]> allContours = new ArrayList<Vertex[]>();
if (glyph != null) {
for (i = 0; i < glyph.getPointCount(); i++) {
count++;
if (glyph.getPoint(i).endOfContour) {
Vertex[] contour = getContourAsShape(glyph, firstIndex, count, xadv);
if (contour != null){
allContours.add(contour);
}
firstIndex = i + 1;
count = 0;
}
}
}
if (!allContours.isEmpty()){
for(Vertex[] contour: allContours){
Vertex.xRotateVectorArray(contour, new Vector3D((float)(xadv/2.0),0,0), 180);
// Vertex.scaleVectorArray(contour, new Vector3D(0,0,0), (float)(1.0/(float)this.unitsPerEm));
// Vertex.scaleVectorArray(contour, new Vector3D(0,0,0), fontSize);
Vertex.scaleVectorArray(contour, new Vector3D(0,0,0), this.scaleFactor);
}
VectorFontCharacter character = new VectorFontCharacter(allContours, pa);
if (MT4jSettings.getInstance().isOpenGlMode())
character.setUseDirectGL(true);
character.setStrokeWeight(0.7f);
character.setPickable(false);
// //FIXME TEST -> dont use a font outline if we use multi-sampling and outlineColor=fillcolor
if (!this.antiAliasing){
character.setNoStroke(true);
}else{
if (MT4jSettings.getInstance().isMultiSampling() && fillColor.equals(strokeColor)){
character.setNoStroke(true);
}else{
character.setNoStroke(false);
}
}
// for(Vertex[] contour: character.getContours()){
// Vertex.xRotateVectorArray(contour, new Vector3D((float)(xadv/2.0),0,0), 180);
// Vertex.scaleVectorArray(contour, new Vector3D(0,0,0), (float)(1.0/(float)this.unitsPerEm));
// Vertex.scaleVectorArray(contour, new Vector3D(0,0,0), fontSize);
// }
// Vertex[] v = character.getGeometryInfo().getVertices();
// Vertex.xRotateVectorArray(v, new Vector3D((float)(xadv/2.0),0,0), 180);
// Vertex.scaleVectorArray(v, new Vector3D(0,0,0), (float)(1.0/(float)this.unitsPerEm));
// Vertex.scaleVectorArray(v, new Vector3D(0,0,0), fontSize);
// character.setVertices(v);
/*
character.xRotate(new Vector3D((float)(xadv/2.0),0,0), 180);
character.scale((float)(1.0/(float)this.unitsPerEm), new Vector3D(0,0,0));
character.scale(fontSize , new Vector3D(0,0,0));
*/
character.setStrokeColor(new MTColor(strokeColor));
character.setFillColor(new MTColor(fillColor));
if (MT4jSettings.getInstance().isOpenGlMode())
character.generateAndUseDisplayLists();
return character;
}else{
return null;
}
}
/**
*
* @param glyph
* @param startIndex
* @param count
* @param xadv
* @return
*/
private Vertex[] getContourAsShape(Glyph glyph, int startIndex, int count, float xadv) {
// If this is a single point on it's own, welogger.info("Value of pointx: "+pointx); can't do anything with it
if (glyph.getPoint(startIndex).endOfContour) {
return null;
}
//logger.info("Leftsidebear " + glyph.getLeftSideBearing());
//logger.info("Advx " + glyph.getAdvanceWidth());
int offset = 0;
//float originx = 0F,originy = 0F;
CustomPathHandler pathHandler = new CustomPathHandler();
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);
float pointx = ((float)point.x);
float pointy = ((float)point.y);
float point_plus1x = ((float)point_plus1.x);
float point_plus1y = ((float)point_plus1.y);
float point_plus2x = ((float)point_plus2.x);
float point_plus2y = ((float)point_plus2.y);
if (offset == 0) {
pathHandler.movetoAbs(pointx,pointy);
}
if (point.onCurve && point_plus1.onCurve) {
// line command
pathHandler.linetoAbs(point_plus1x,point_plus1y);
offset++;
} else if (point.onCurve && !point_plus1.onCurve && point_plus2.onCurve) {
// This is a curve with no implied points
// quadratic bezier command
pathHandler.curvetoQuadraticAbs(point_plus1x, point_plus1y, point_plus2x, point_plus2y);
offset+=2;
} else if (point.onCurve && !point_plus1.onCurve && !point_plus2.onCurve) {
// This is a curve with one implied point
pathHandler.curvetoQuadraticAbs(point_plus1x, point_plus1y, midValue(point_plus1x, point_plus2x), midValue(point_plus1y, point_plus2y));
offset+=2;
} else if (!point.onCurve && !point_plus1.onCurve) {
// This is a curve with two implied points
// quadratic bezier with
pathHandler.curvetoQuadraticAbs(pointx, pointy, midValue(pointx, point_plus1x), midValue(pointy, point_plus1y));
offset++;
} else if (!point.onCurve && point_plus1.onCurve) {
// This is a curve with no implied points
pathHandler.curvetoQuadraticAbs(pointx, pointy, point_plus1x, point_plus1y);
offset++;
} else {
logger.info("drawGlyph case not catered for!!");
break;
}
}
pathHandler.closePath();
Vertex[] p = pathHandler.getPathPointsArray();
/*
//Get Sub-Paths
ArrayList<Vertex[]> subPaths = pathHandler.getContours();
logger.info("Pathpoints array:");
for (int i = 0; i < p.length; i++) {
Vertex vertex = p[i];
logger.info(vertex);
}
logger.info("Subpaths");
for(Vertex[] subPath : subPaths)
for (int i = 0; i < subPath.length; i++) {
Vertex vertex = subPath[i];
logger.info(vertex);
}
*/
return p;
}
/**
* Gets the vectorFontCharacter by charcode.
*
* @param charCodeMapIndex the char code map index
* @param pa the pa
* @param fontFile the font file
*
* @return the char charcode
*/
public VectorFontCharacter getCharCharcode(PApplet pa, String fontFile, int charCodeMapIndex){
this.pa = pa;
this.fontPath = fontFile;
this.f = Font.create(fontPath);
this.setSize(fontSize);
this.fontDefaultXAdvancing = 500;
this.fontSize = 50;
this.unitsPerEm = f.getHeadTable().getUnitsPerEm();
CmapFormat cmapFmt = this.getCmapFormat(f);
int charIndex = cmapFmt.mapCharCode(charCodeMapIndex);
int default_advance_x = f.getHmtxTable().getAdvanceWidth(charIndex);
Glyph glyph = f.getGlyph(charIndex);
if (glyph != null){
VectorFontCharacter character = this.getGlyphAsShape(f, glyph, charIndex, 0, new MTColor(0,0,0,255), new MTColor(0,0,0,255));
if (character != null){
character.setHorizontalDist(default_advance_x);
return character;
}else{
return null;
}
}else{
return null;
}
}
/**
*
* @param f
* @return
*/
private CmapFormat getCmapFormat(Font f){
//Decide upon a cmap table to use for our character to glyph look-up
CmapFormat cmapFmt = null;
boolean forceAscii = false;
if (forceAscii) {
// We've been asked to use the ASCII/Macintosh cmap format
cmapFmt = f.getCmapTable().getCmapFormat(
Table.platformMacintosh,
Table.encodingRoman );
//logger.info("Forced ASCII. Loading ASCII/Macintosh cmap format...");
} else {
// The default behaviour is to use the Unicode cmap encoding
cmapFmt = f.getCmapTable().getCmapFormat(
Table.platformMicrosoft,
Table.encodingUGL );
if(cmapFmt != null) {
// logger.info("Loading Unicode cmap format...");
}
if (cmapFmt == null){
cmapFmt = f.getCmapTable().getCmapFormat(
Table.platformMicrosoft,
Table.encodingKorean );
if(cmapFmt != null) {
// logger.info("Loading Microsoft/Korean cmap format...");
}
}
if (cmapFmt == null){
cmapFmt = f.getCmapTable().getCmapFormat(
Table.platformMicrosoft,
Table.encodingHebrew );
if(cmapFmt != null) {
// logger.info("Loading Microsoft/Hebrew cmap format...");
}
}
if (cmapFmt == null) {
// This might be a symbol font, so we'll look for an "undefined" encoding
cmapFmt = f.getCmapTable().getCmapFormat(
Table.platformMicrosoft,
Table.encodingUndefined );
if(cmapFmt != null) {
// logger.info("Loading Undefined cmap format...");
}
}
}
return cmapFmt;
}
private static float midValue(float a, float b) {
return a + (b - a)/2;
}
/**
* Use this method to reset the point size of the font.
* @eexample setSize
* @param size int, the point size of the font in points.
* @related size
* @related RFont
*/
private void setSize(int size){
int resolution = Toolkit.getDefaultToolkit().getScreenResolution();
this.scaleFactor = ((float)size * (float)resolution) / (72F * (float)unitsPerEm);
//this.scaleFactorFixed = (int)(this.scaleFactor * 65536F);
//logger.info(scaleFactor);
//logger.info(scaleFactorFixed);
}
/**
* @invisible
**/
private String getFamily(Font f){
return f.getNameTable().getRecord(Table.nameFontFamilyName);
}
}