Package de.lessvoid.nifty.renderer.lwjgl.render.font

Source Code of de.lessvoid.nifty.renderer.lwjgl.render.font.Font

package de.lessvoid.nifty.renderer.lwjgl.render.font;

import java.util.Hashtable;
import java.util.Map;

import org.lwjgl.opengl.GL11;

import de.lessvoid.nifty.elements.tools.FontHelper;
import de.lessvoid.nifty.renderer.lwjgl.render.LwjglRenderFont;
import de.lessvoid.nifty.renderer.lwjgl.render.LwjglRenderImage;
import de.lessvoid.nifty.renderer.lwjgl.render.font.ColorValueParser.Result;
import de.lessvoid.nifty.spi.render.RenderDevice;
import de.lessvoid.nifty.tools.Color;


/**
* OpenGL display list based Font.
* @author void
*/
public class Font {
  /**
   * the font reader.
   */
  private AngelCodeFont font;

  /**
   * display list id.
   */
  private int listId;

  /**
   * textures.
   */
  private LwjglRenderImage[] textures;

  private int selectionStart;
 
  private int selectionEnd;
 
  private float selectionBackgroundR;
  private float selectionBackgroundG;
  private float selectionBackgroundB;
  private float selectionBackgroundA;

  private float selectionR;
  private float selectionG;
  private float selectionB;
  private float selectionA;
 
  private Map<Character, Integer> displayListMap = new Hashtable<Character, Integer>();
  private ColorValueParser colorValueParser = new ColorValueParser();

  /**
   * construct the font.
   */
  public Font(final RenderDevice device) {
    selectionStart = -1;
    selectionEnd = -1;
    selectionR = 1.0f;
    selectionG = 0.0f;
    selectionB = 0.0f;
    selectionA = 1.0f;
    selectionBackgroundR = 0.0f;
    selectionBackgroundG = 1.0f;
    selectionBackgroundB = 0.0f;
    selectionBackgroundA = 1.0f;
  }
 
  /**
   * has selection.
   * @return true or false
   */
  private boolean isSelection() {
    return !(selectionStart == -1 && selectionEnd == -1);
  }

  /**
   * init the font with the given filename.
   * @param filename the filename
   * @return true, when success or false on error
   */
  public final boolean init(final String filename) {
    // get the angel code font from file
    font = new AngelCodeFont();
    if (!font.load(filename)) {
      return false;
    }

    // load textures of font into array
    textures = new LwjglRenderImage[font.getTextures().length];
    for (int i = 0; i < font.getTextures().length; i++) {
      textures[i] = new LwjglRenderImage(extractPath(filename) + font.getTextures()[i], true);
    }

    // now build open gl display lists for every character in the font
    initDisplayList();
    return true;
  }

  /**
   * extract the path from the given filename.
   * @param filename file
   * @return path
   */
  private String extractPath(final String filename) {
    int idx = filename.lastIndexOf("/");
    if (idx == -1) {
      return "";
    } else {
      return filename.substring(0, idx) + "/";
    }
  }

  /**
   *
   */
  private void initDisplayList()
  {
    displayListMap.clear();

    // create new list
    listId = GL11.glGenLists(font.getChars().size());
    Tools.checkGLError("glGenLists");
   
    // create the list
    int i = 0;
    for (Map.Entry<Character, CharacterInfo> entry : font.getChars().entrySet()) {
      displayListMap.put(entry.getKey(), listId + i);
      GL11.glNewList(listId + i, GL11.GL_COMPILE);
      Tools.checkGLError("glNewList");
      CharacterInfo charInfo = entry.getValue();
      if (charInfo != null) {
        GL11.glBegin( GL11.GL_QUADS );
        Tools.checkGLError( "glBegin" );
   
          float u0 = charInfo.getX() / (float)font.getWidth();
          float v0 = charInfo.getY() / (float)font.getHeight();
          float u1 = ( charInfo.getX() + charInfo.getWidth() ) / (float)font.getWidth();
          float v1 = ( charInfo.getY() + charInfo.getHeight() ) / (float)font.getHeight();
   
          GL11.glTexCoord2f( u0, v0 );
          GL11.glVertex2f( charInfo.getXoffset(), charInfo.getYoffset() );
         
          GL11.glTexCoord2f( u0, v1 );
          GL11.glVertex2f( charInfo.getXoffset(), charInfo.getYoffset() + charInfo.getHeight() );
   
          GL11.glTexCoord2f( u1, v1 );
          GL11.glVertex2f( charInfo.getXoffset() + charInfo.getWidth(), charInfo.getYoffset() + charInfo.getHeight() );
   
          GL11.glTexCoord2f( u1, v0 );
          GL11.glVertex2f( charInfo.getXoffset() + charInfo.getWidth(), charInfo.getYoffset() );
     
        GL11.glEnd();
        Tools.checkGLError( "glEnd" );
      }

      // end list
      GL11.glEndList();
      Tools.checkGLError( "glEndList" );
      i++;
    }
  }

  /**
   *
   * @param x
   * @param y
   * @param text
   */
  public void drawString( int x, int y, String text ) {
//    enableBlend();
    internalRenderText(x, y, text, 1.0f, false, 1.0f);
//    disableBlend();
  }

  public void drawStringWithSize( int x, int y, String text, float size ) {
//    enableBlend();
    internalRenderText(x, y, text, size, false, 1.0f);
//    disableBlend();
  }

  public void renderWithSizeAndColor( int x, int y, String text, float size, float r, float g, float b, float a ) {
//    enableBlend();
    GL11.glColor4f(r, g, b, a);
    internalRenderText( x, y, text, size, false, a);
//    disableBlend();
  }
 
  /**
   * @param xPos x
   * @param yPos y
   * @param text text
   * @param size size
   * @param useAlphaTexture use alpha
   * @param a
   */
  private void internalRenderText(
      final int xPos,
      final int yPos,
      final String text,
      final float size,
      final boolean useAlphaTexture,
      final float alpha) {
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
      GL11.glPushMatrix();
      GL11.glLoadIdentity();

//      GL11.glEnable(GL11.GL_TEXTURE_2D);

      int originalWidth = getStringWidthInternal(text, 1.0f);
      int sizedWidth = getStringWidthInternal(text, size);
      int x = xPos - (sizedWidth - originalWidth) / 2;

      int activeTextureIdx = -1;

      for (int i = 0; i < text.length(); i++) {
        Result result = colorValueParser.isColor(text, i);
        while (result.isColor()) {
          Color color = result.getColor();
          GL11.glColor4f(color.getRed(), color.getGreen(), color.getBlue(), alpha);
          i = result.getNextIndex();
          if (i >= text.length()) {
            break;
          }
          result = colorValueParser.isColor(text, i);
        }
        if (i >= text.length()) {
          break;
        }

        char currentc = text.charAt(i);
        char nextc = FontHelper.getNextCharacter(text, i);
        CharacterInfo charInfoC = font.getChar((char) currentc);
        int kerning = 0;
        float characterWidth = 0;
        if (charInfoC != null) {
          int texId = charInfoC.getPage();
          if (activeTextureIdx != texId) {
            activeTextureIdx = texId;
            textures[activeTextureIdx].bind();
          }

          kerning = LwjglRenderFont.getKerning(charInfoC, nextc);
          characterWidth = (float) (charInfoC.getXadvance() * size + kerning);

          GL11.glLoadIdentity();
          GL11.glTranslatef(x, yPos, 0.0f);
 
          GL11.glTranslatef(0.0f, getHeight() / 2, 0.0f);
          GL11.glScalef(size, size, 1.0f);
          GL11.glTranslatef(0.0f, -getHeight() / 2, 0.0f);
 
          boolean characterDone = false;
            if (isSelection()) {
              if (i >= selectionStart && i < selectionEnd) {
                GL11.glPushAttrib(GL11.GL_CURRENT_BIT);
 
                disableBlend();
                GL11.glDisable(GL11.GL_TEXTURE_2D);
 
                GL11.glColor4f(selectionBackgroundR, selectionBackgroundG, selectionBackgroundB, selectionBackgroundA);
                GL11.glBegin(GL11.GL_QUADS);
 
                  GL11.glVertex2i(0, 0);
                  GL11.glVertex2i((int) characterWidth, 0);
                  GL11.glVertex2i((int) characterWidth, 0 + getHeight());
                  GL11.glVertex2i(0, 0 + getHeight());
 
                GL11.glEnd();
                GL11.glEnable(GL11.GL_TEXTURE_2D);
                enableBlend();
 
                GL11.glColor4f(selectionR, selectionG, selectionB, selectionA);
                GL11.glCallList(displayListMap.get(currentc));
                Tools.checkGLError("glCallList");
                GL11.glPopAttrib();
 
                characterDone = true;
              }
            }
 
          if (!characterDone) {
            GL11.glCallList(displayListMap.get(currentc));
            Tools.checkGLError("glCallList");
          }
 
          x += characterWidth;
        }
      }

      GL11.glPopMatrix();
  }

  /**
   *
   */
  private void disableBlend() {
    GL11.glDisable( GL11.GL_BLEND );
  }

  /**
   *
   */
  private void enableBlend() {
    GL11.glEnable( GL11.GL_BLEND );
    GL11.glBlendFunc( GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA );
  }
 
  public int getStringWidth( String text ) {
    return getStringWidthInternal( text, 1.0f );
  }

  /**
   * @param text text
   * @param size size
   * @return length
   */
  private int getStringWidthInternal(final String text, final float size) {
    int length = 0;

    for (int i=0; i<text.length(); i++) {
      Result result = colorValueParser.isColor(text, i);
      if (result.isColor()) {
        i = result.getNextIndex();
        if (i >= text.length()) {
          break;
        }
      }
      char currentCharacter = text.charAt(i);
      char nextCharacter = FontHelper.getNextCharacter(text, i);

      Integer w = getCharacterWidth(currentCharacter, nextCharacter, size);
      if (w != null) {
        length += w;
      }
    }
    return length;
  }

  public int getHeight()
  {
    return font.getLineHeight();
  }

  public void setSelectionStart(int selectionStart) {
    this.selectionStart = selectionStart;
  }

  public void setSelectionEnd(int selectionEnd) {
    this.selectionEnd = selectionEnd;
  }

  public void setSelectionColor(final float selectionR, final float selectionG, final float selectionB, final float selectionA) {
    this.selectionR = selectionR;
    this.selectionG = selectionG;
    this.selectionB = selectionB;
    this.selectionA = selectionA;
  }
 
  public void setSelectionBackgroundColor(final float selectionR, final float selectionG, final float selectionB, final float selectionA) {
    this.selectionBackgroundR = selectionR;
    this.selectionBackgroundG = selectionG;
    this.selectionBackgroundB = selectionB;
    this.selectionBackgroundA = selectionA;
  }

  /**
   * get character information.
   * @param character char
   * @return CharacterInfo
   */
  public CharacterInfo getChar(final char character) {
    return font.getChar(character);
  }

  /**
   * Return the width of the given character including kerning information.
   * @param currentCharacter current character
   * @param nextCharacter next character
   * @param size font size
   * @return width of the character or null when no information for the character is available
   */
  public Integer getCharacterWidth(final char currentCharacter, final char nextCharacter, final float size) {
    CharacterInfo currentCharacterInfo = font.getChar(currentCharacter);
    if (currentCharacterInfo == null) {
      return null;
    } else {
      return new Integer((int)(currentCharacterInfo.getXadvance() * size + getKerning(currentCharacterInfo, nextCharacter)));
    }
  }

  /**
   * @param charInfoC
   * @param nextc
   * @return
   */
  public static int getKerning(final CharacterInfo charInfoC, final char nextc) {
    Integer kern = charInfoC.getKerning().get(Character.valueOf(nextc));
    if (kern != null) {
      return kern.intValue();
    }
    return 0;
  }
}
TOP

Related Classes of de.lessvoid.nifty.renderer.lwjgl.render.font.Font

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.