Package processing.core

Source Code of processing.core.BitmapFontFactoryProxy

/***********************************************************************
* mt4j Copyright (c) 2008 - 2010 Christopher 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 processing.core;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.SimpleLayout;
import org.mt4j.MTApplication;
import org.mt4j.components.visibleComponents.font.BitmapFont;
import org.mt4j.components.visibleComponents.font.BitmapFontCharacter;
import org.mt4j.components.visibleComponents.font.IFont;
import org.mt4j.components.visibleComponents.font.fontFactories.IFontFactory;
import org.mt4j.util.MT4jSettings;
import org.mt4j.util.MTColor;

import processing.core.PFont.Glyph;

/**
* A factory for creating BitmapFont objects.
* @author Christopher Ruff
*/
public class BitmapFontFactoryProxy implements IFontFactory {
  /** The Constant logger. */
  private static final Logger logger = Logger.getLogger(BitmapFontFactoryProxy.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äöü<>|,;.:-_#'+*!\"§$%&/()=?ยด{[]}\\@";
 
//  static{
//    FontManager.getInstance().registerFontFactory("", new BitmapFontFactory());
  //  }

  /* (non-Javadoc)
   * @see org.mt4j.components.visibleComponents.font.fontFactories.IFontFactory#createFont(processing.core.PApplet, java.lang.String, int, org.mt4j.util.MTColor, org.mt4j.util.MTColor)
   */
  public IFont createFont(
      PApplet pa,
      String fontFileName,
      int fontSize,
      MTColor fillColor,
      MTColor strokeColor
  ) {
    return this.createFont(pa, fontFileName, fontSize, fillColor, strokeColor, true);
  }
 
  /* (non-Javadoc)
   * @see org.mt4j.components.visibleComponents.font.fontFactories.IFontFactory#createFont(processing.core.PApplet, java.lang.String, int, org.mt4j.util.MTColor, org.mt4j.util.MTColor)
   */
  public IFont createFont(
      PApplet pa,
      String fontFileName,
      int fontSize,
      MTColor fillColor,
      MTColor strokeColor,
      boolean antiAliased
  ) {
    PFont p5Font = null;
    try {
      p5Font = this.getProcessingFont(pa, fontFileName, fontSize, antiAliased);
    } catch (FileNotFoundException e1) {
      e1.printStackTrace();
    }
    List<BitmapFontCharacter> bitMapCharacters = this.createCharacters(pa, p5Font, defaultCharacters, fillColor, strokeColor);
 
    //font is null sometimes (vlw)
    /*
    Font f = p5Font.getFont();
    FontMetrics fm = pa.getFontMetrics(f);
    Map<TextAttribute, ?> atts = f.getAttributes();
    Set<TextAttribute> attKeys = atts.keySet();
    for (Iterator iterator = attKeys.iterator(); iterator.hasNext();) {
      TextAttribute textAttribute = (TextAttribute) iterator.next();
      Object value = atts.get(textAttribute);
      logger.debug("Key: " + textAttribute + " Value: " + value);
    }
//    FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(f);
     */
   
    int defaultHorizontalAdvX = (!bitMapCharacters.isEmpty())? bitMapCharacters.get(0).getHorizontalDist() : Math.round(p5Font.descent() * fontSize); //FIXME HACK!
    String fontFamily = p5Font.getPostScriptName();
//    String fontFamily = f.getFamily();
    //FIXME ascent() and descent() return to small values! wheres the difference??
    int fontMaxAscent = Math.round(p5Font.ascent()* (fontSize));
    fontMaxAscent +=(float)fontSize/5.5f; //FIXME HACK! because the same ttf fonts seem to have bigger ascents
//    int fontMaxAscent = p5Font.lazyMetrics.getAscent();
    int fontMaxDescent = Math.round(p5Font.descent() * fontSize);
    /*
    //TODO INFO: because in vector font this is a negative value, too
    Font f = p5Font.getFont();
    if (f != null){
      FontMetrics fm = pa.getFontMetrics(f);
      fontMaxDescent = fm.getDescent();
    }
    */
    fontMaxDescent *= -1; //We use negative descent values
   
    //logger.debug("Bitmapfont max descent: " + fontMaxDescent);
   
//    int fontMaxAscent = Math.round(p5Font.ascent()*fontSize);
//    int fontMaxDescent = Math.round(p5Font.descent()*fontSize);
//    int fontMaxAscent = fm.getMaxAscent();
//    int fontMaxDescent = fm.getMaxDescent();
    int unitsPerEm = 1000; //FIXME HACK!
    int originalFontSize = fontSize; //important for font cache
   
    PImage dummy = new PImage(1,1);
//    /*
    //Manually add a newLine character to the font
    BitmapFontCharacter newLine = new BitmapFontCharacter(dummy, pa, "\n", 0, 0, 0);
    newLine.setPickable(false);                   
    newLine.setVisible(false);
    newLine.setNoFill(true);
    newLine.setNoStroke(true);
    newLine.setName("newline");
    bitMapCharacters.add(newLine);
   
    //Manually add a SPACE character to the font
//    int spaceAdvancex = defaultHorizontalAdvX;
//    int spaceAdvancex = fm.charWidth(' ');
    //TODO hack, we use the dash character's width for the space width, because dont know how to get it
//    int spaceIndex = p5Font.index('-');
//    int spaceAdvancex = p5Font.width[spaceIndex];
//    int spaceAdvancex = p5Font.getGlyph('-').width;
    int spaceAdvancex = Math.round(((float) p5Font.width('i') * (float) fontSize));
//    int spaceAdvancex = Math.round(pa.textWidth(' '));
//    int spaceAdvancex = Math.round(p5Font.width(' ') * p5Font.size);
    BitmapFontCharacter space = new BitmapFontCharacter(dummy, pa, " ", 0, 0, spaceAdvancex);
    space.setPickable(false);                   
    space.setVisible(false);
    space.setNoFill(true);
    space.setNoStroke(true);
    space.setName("space");
    bitMapCharacters.add(space);
   
    //Manually add a TAB character to the font
    int defaultTabWidth = spaceAdvancex*4;
    BitmapFontCharacter tab = new BitmapFontCharacter(dummy, pa, "\t", 0, 0, defaultTabWidth);
    try {
      int tabWidth = 4 * space.getHorizontalDist();
      tab.setHorizontalDist(tabWidth);
    } catch (Exception e) {
      tab.setHorizontalDist(defaultTabWidth);
    }
    tab.setPickable(false);
    tab.setName("tab");
    tab.setVisible(false);
    tab.setNoFill(true);
    tab.setNoStroke(true);
    bitMapCharacters.add(tab);
//    */
   
    //TODO bitmap font size seems different to same size vector font, we must have check descent -> textarea -> res*em*etc
    //TODO eureka font -  numbers baseline wrong?
   
    //Create the bitmap font
    BitmapFontCharacter[] characters = bitMapCharacters.toArray(new BitmapFontCharacter[bitMapCharacters.size()]);
    BitmapFont bitmapFont = new BitmapFont(characters, defaultHorizontalAdvX, fontFamily, fontMaxAscent, fontMaxDescent, unitsPerEm, originalFontSize,
        fillColor,
        strokeColor,
        antiAliased
    );
    bitmapFont.setFontFileName(fontFileName);
    return bitmapFont;
  }
 
 
//  /**
//   * Gets the processing font.
//   *
//   * @param pa the pa
//   * @param fontFileName the font file name
//   * @param fontSize the font size
//   * @return the processing font
//   */
//  private PFont getProcessingFont(PApplet pa, String fontFileName, int fontSize){
//    return this.getProcessingFont(pa, fontFileName, fontSize, true);
//  }

  /**
   * Gets the processing font.
   *
   * @param pa the pa
   * @param fontFileName the font file name
   * @param fontSize the font size
   * @param antiAliased the anti aliased
   * @return the processing font
   * @throws FileNotFoundException
   */
  private PFont getProcessingFont(PApplet pa, String fontFileName, int fontSize, boolean antiAliased) throws FileNotFoundException{
    PFont p5Font;
    //When loading the vlw font the font size and anti aliasing is already determined with the file
    //and our parameter isnt honored
    if (fontFileName.endsWith(".vlw")){
      p5Font = pa.loadFont(fontFileName);
      //If not found try to load from the "/data" directory
      if (p5Font == null){
        int lastDirFileSeparator = fontFileName.lastIndexOf(java.io.File.separator);
        int lastDirSeparator = fontFileName.lastIndexOf(MTApplication.separator);
        if (lastDirFileSeparator != -1){
          p5Font = pa.loadFont(fontFileName.substring(lastDirFileSeparator+1, fontFileName.length()));
        }else if (lastDirSeparator != -1){
          p5Font = pa.loadFont(fontFileName.substring(lastDirSeparator+1, fontFileName.length()));
        }
      }
    }
    else if (fontFileName.endsWith(".ttf") || fontFileName.endsWith(".otf")){
      p5Font = pa.createFont(fontFileName, fontSize, antiAliased);
      //If not found try to load from the "/data" directory
      if (p5Font == null){
        int lastDirFileSeparator = fontFileName.lastIndexOf(java.io.File.separator);
        int lastDirSeparator = fontFileName.lastIndexOf(MTApplication.separator);
        if (lastDirFileSeparator != -1){
          p5Font = pa.createFont(fontFileName.substring(lastDirFileSeparator+1, fontFileName.length()), fontSize, antiAliased);
        }else if (lastDirSeparator != -1){
          p5Font = pa.createFont(fontFileName.substring(lastDirSeparator+1, fontFileName.length()), fontSize, antiAliased);
        }else{
          p5Font = pa.loadFont(fontFileName);
        }
      }
    }
    else{
      //No file suffix -> Create font from a java/system font
      int lastDirFileSeparator = fontFileName.lastIndexOf(java.io.File.separator);
      int lastDirSeparator = fontFileName.lastIndexOf(MTApplication.separator);
      if (lastDirFileSeparator != -1){
        p5Font = pa.createFont(fontFileName.substring(lastDirFileSeparator+1, fontFileName.length()), fontSize, antiAliased); //Creats the font
      }
      else if (lastDirSeparator != -1){
        p5Font = pa.createFont(fontFileName.substring(lastDirSeparator+1, fontFileName.length()), fontSize, antiAliased); //Creats the font 
      }
      else{
        p5Font = pa.loadFont(fontFileName);
      }
    }
   
    if (p5Font == null){
      throw new NullPointerException("Couldnt load the font: " + fontFileName);
    }
    return p5Font;
  }
 
 
 
  public List<BitmapFontCharacter> getCharacters(PApplet pa,
      String chars,
      MTColor fillColor,
      MTColor strokeColor,
      String fontFileName,
      int fontSize
  ){
    return this.getCharacters(pa, chars, fillColor, strokeColor, fontFileName, fontSize, true);
  }
 
  /**
   * Creates the specified characters.
   *
   * @param pa the pa
   * @param chars the chars
   * @param fillColor the fill color
   * @param strokeColor the stroke color
   * @param fontFileName the font file name
   * @param fontSize the font size
   * @param antiAliased the anti aliased
   * @return the characters
   */
  public List<BitmapFontCharacter> getCharacters(PApplet pa,
      String chars,
      MTColor fillColor,
      MTColor strokeColor,
      String fontFileName,
      int fontSize,
      boolean antiAliased
  ){
    PFont p5Font = null;
    try {
      p5Font = this.getProcessingFont(pa, fontFileName, fontSize, antiAliased);
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
    return createCharacters(pa, p5Font, chars, fillColor, strokeColor);
  }
 
 
  private List<BitmapFontCharacter> createCharacters(PApplet pa, PFont p5Font, String chars, MTColor fillColor, MTColor strokeColor){
    List<BitmapFontCharacter> bitMapCharacters = new ArrayList<BitmapFontCharacter>();
   
    for (int i = 0; i < chars.length(); i++) {
      char c = chars.charAt(i);
//      int charIndex = p5Font.index(c);
      Glyph glyph = p5Font.getGlyph(c);
      if (glyph != null){
        PImage charImage = glyph.image;
        int charWidth = glyph.width;
        int charHeight = glyph.height;
        int topExtend = glyph.topExtent;
        int leftExtend = glyph.leftExtent;
        int widthDisplacement = glyph.setWidth;
       

        //int topOffset = p5Font.descent + (-charHeight - (topExtend-charHeight)); //ORIGINAL
        int topOffset =  (-charHeight - (topExtend-charHeight));
       
        //Copy the actual font data on the image from the upper left corner 1 pixel
        //into the middle of the image to avoid anti aliasing artefacts at the corners
//        PImage copy = new PImage(charImage.width, charImage.height, PImage.ARGB); //ORG

//        for (int j = 0; j < charImage.pixels.length; j++) { //ORG
//          int d = charImage.pixels[j];
//          /*
//            int a = d >> 24 & 0xFF;
//            int r = d >> 16 & 0xFF;
//            int g = d >> 8 & 0xFF;
//            int b = d & 0xFF;
//            logger.debug("R: " + r + " G:" + g + " B:" + " A:" + a);
//           */
//          charImage.pixels[j] = (d << 24) | 0x00FFFFFF; //ORIGINAL! //make it white
////          charImage.pixels[j] = (d << 24) | pa.color(fillColor.getR(), fillColor.getG(), fillColor.getB(), 0);
////          charImage.pixels[j] = (charImage.pixels[j] << 24) | 0x00FFFFFF;
//          //charImage.format = PConstants.ARGB;
//         
//          //Clear the copy image in the same loop
//          copy.pixels[j] = (copy.pixels[j] << 24) | 0x00FFFFFF; //Original! //make it white
////          copy.pixels[j] = (d << 24) | 0x00FFFFFF; //Original! //make it white
//        }
       
        for (int j = 0; j < charImage.pixels.length; j++) { //ORG
          charImage.pixels[j] = (charImage.pixels[j] << 24) | 0x00FFFFFF; //ORIGINAL! //make it white
        }
       
        //Shift character image data down and right in the image because of aliasing artifacts at the border
        //we need to compensate for this when displaying the char
        //FIXME this creates far to big images..but because of artefacts needed..?
        int topShiftAmount = 4;
        int leftShiftAmount = 4;
       
//        PImage copy = new PImage(ToolsMath.nearestPowerOfTwo(charWidth + shiftAmount), ToolsMath.nearestPowerOfTwo(charHeight + shiftAmount), PImage.ARGB);
//       
        PImage copy = new PImage(nextPowerOfTwo(charImage.width + leftShiftAmount + 1), nextPowerOfTwo(charImage.height + topShiftAmount), PImage.ARGB);
//        PImage copy = new PImage(charImage.width + leftShiftAmount + 1, charImage.height + topShiftAmount, PImage.ARGB);
       
        copy.copy(charImage, 0, 0, charWidth, charHeight, leftShiftAmount, topShiftAmount, charWidth, charHeight);
       
//        copy.copy(charImage, 0, 0, charImage.width, charImage.height, leftShiftAmount, topShiftAmount, charImage.width, charImage.height);
       
//        copy.copy(charImage, 0, 0, charWidth, charHeight, shiftAmount, shiftAmount, charWidth, charHeight);
//        copy.copy(charImage, 0, 0, charImage.width, charImage.height, shiftAmount, shiftAmount, charImage.width, charImage.height);
//        copy.copy(charImage, 0, 0, charImage.width, charImage.height, shiftAmount, shiftAmount, charImage.width, charImage.height);
//        copy.copy(charImage, 0, 0, charWidth, charHeight, shiftAmount, shiftAmount, charWidth, charHeight);
       
        charImage = copy;
       
        //FIXME the topoffset is smaller than with the vector font! check that!
        //FIXME anti aliasing artefacts may also stem from using a perspective and not ortho camera!!
        //FIXME space character too wide..
       
        //Move the character to compensate for the shifting of the image
        topOffset -= topShiftAmount; //org shiftamount
        leftExtend -= leftShiftAmount;
       
        //FIXME TEST
//        if (c == 'i'){
//          copy.save(MT4jSettings.DEFAULT_IMAGES_PATH + "i.png");
//        }
       
        //Create bitmap font character
        String StringChar = new Character(c).toString();
        BitmapFontCharacter character = new BitmapFontCharacter(charImage, pa, StringChar, leftExtend, topOffset, widthDisplacement);
        character.setName(StringChar);
        character.setFillColor(new MTColor(fillColor));
        if (MT4jSettings.getInstance().isOpenGlMode()){
          character.generateAndUseDisplayLists();
        }
        bitMapCharacters.add(character);
        //logger.debug("Char: " + c + " charWidth: " + charWidth +  " leftExtend: " + leftExtend + " widthDisplacement: " + widthDisplacement + " imageHeight: " + charImage.height + " charHeight: " + charHeight +  " topExtent: " + topExtend);
      }else{
        logger.warn("Couldnt create bitmap character : " + c + " -> not found!");
      }
    }
    return bitMapCharacters;
  }
 
  private int nextPowerOfTwo(int val) {
        int ret = 1;
        while (ret < val) {
          ret <<= 1;
        }
        return ret;
      }

// 
//    /**
//     * Create a .vlw font on the fly from either a font name that's
//     * installed on the system, or from a .ttf or .otf that's inside
//     * the data folder of this sketch.
//     * <P/>
//     * Many .otf fonts don't seem to be supported by Java, perhaps because
//     * they're CFF based?
//     * <P/>
//     * Font names are inconsistent across platforms and Java versions.
//     * On Mac OS X, Java 1.3 uses the font menu name of the font,
//     * whereas Java 1.4 uses the PostScript name of the font. Java 1.4
//     * on OS X will also accept the font menu name as well. On Windows,
//     * it appears that only the menu names are used, no matter what
//     * Java version is in use. Naming system unknown/untested for 1.5.
//     * <P/>
//     * Use 'null' for the charset if you want to dynamically create
//     * character bitmaps only as they're needed. (Version 1.0.9 and
//     * earlier would interpret null as all unicode characters.)
//     */
//    public PFont createFont(PApplet app, String name, float size,
//                            boolean smooth, char charset[]) {
//      String lowerName = name.toLowerCase();
//      Font baseFont = null;
//
//      try {
//        InputStream stream = null;
//        if (lowerName.endsWith(".otf") || lowerName.endsWith(".ttf")) {
//          stream = app.createInput(name);
//          if (stream == null) {
//            System.err.println("The font \"" + name + "\" " +
//                               "is missing or inaccessible, make sure " +
//                               "the URL is valid or that the file has been " +
//                               "added to your sketch and is readable.");
//            return null;
//          }
//          baseFont = Font.createFont(Font.TRUETYPE_FONT, app.createInput(name));
//
//        } else {
//          baseFont = PFont.findFont(name);
//        }
//        return new PFont(baseFont.deriveFont(size), smooth, charset,
//                         stream != null);
//
//      } catch (Exception e) {
//        System.err.println("Problem createFont(" + name + ")");
//        e.printStackTrace();
//        return null;
//      }
//    }
//   
//   private class MYPFont extends PFont{
//    
//     public void getGlyphImage(){
//       getGlyph('a');
//     }
//    
//     public class bla extends PFont.Glyph{
//      
//     }
//    
//   }


}
TOP

Related Classes of processing.core.BitmapFontFactoryProxy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.