package org.anddev.andengine.entity.text;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.entity.shape.RectangularShape;
import org.anddev.andengine.opengl.font.Font;
import org.anddev.andengine.opengl.texture.buffer.TextTextureBuffer;
import org.anddev.andengine.opengl.util.GLHelper;
import org.anddev.andengine.opengl.vertex.TextVertexBuffer;
import org.anddev.andengine.util.HorizontalAlign;
import org.anddev.andengine.util.StringUtils;
/**
* (c) 2010 Nicolas Gramlich
* (c) 2011 Zynga Inc.
*
* @author Nicolas Gramlich
* @since 10:54:59 - 03.04.2010
*/
public class Text extends RectangularShape {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
private final TextTextureBuffer mTextTextureBuffer;
private String mText;
private String[] mLines;
private int[] mWidths;
private final Font mFont;
private int mMaximumLineWidth;
protected final int mCharactersMaximum;
protected final int mVertexCount;
// ===========================================================
// Constructors
// ===========================================================
public Text(final float pX, final float pY, final Font pFont, final String pText) {
this(pX, pY, pFont, pText, HorizontalAlign.LEFT);
}
public Text(final float pX, final float pY, final Font pFont, final String pText, final HorizontalAlign pHorizontalAlign) {
this(pX, pY, pFont, pText, pHorizontalAlign, pText.length() - StringUtils.countOccurrences(pText, '\n'));
}
protected Text(final float pX, final float pY, final Font pFont, final String pText, final HorizontalAlign pHorizontalAlign, final int pCharactersMaximum) {
super(pX, pY, 0, 0, new TextVertexBuffer(pCharactersMaximum, pHorizontalAlign, GL11.GL_STATIC_DRAW, true));
this.mCharactersMaximum = pCharactersMaximum;
this.mVertexCount = TextVertexBuffer.VERTICES_PER_CHARACTER * this.mCharactersMaximum;
this.mTextTextureBuffer = new TextTextureBuffer(2 * this.mVertexCount, GL11.GL_STATIC_DRAW, true);
this.mFont = pFont;
this.updateText(pText);
this.initBlendFunction();
}
protected void updateText(final String pText) {
this.mText = pText;
final Font font = this.mFont;
this.mLines = StringUtils.split(this.mText, '\n', this.mLines);
final String[] lines = this.mLines;
final int lineCount = lines.length;
final boolean widthsReusable = this.mWidths != null && this.mWidths.length == lineCount;
if(!widthsReusable) {
this.mWidths = new int[lineCount];
}
final int[] widths = this.mWidths;
int maximumLineWidth = 0;
for (int i = lineCount - 1; i >= 0; i--) {
widths[i] = font.getStringWidth(lines[i]);
maximumLineWidth = Math.max(maximumLineWidth, widths[i]);
}
this.mMaximumLineWidth = maximumLineWidth;
super.mWidth = this.mMaximumLineWidth;
final float width = super.mWidth;
super.mBaseWidth = width;
super.mHeight = lineCount * font.getLineHeight() + (lineCount - 1) * font.getLineGap();
final float height = super.mHeight;
super.mBaseHeight = height;
this.mRotationCenterX = width * 0.5f;
this.mRotationCenterY = height * 0.5f;
this.mScaleCenterX = this.mRotationCenterX;
this.mScaleCenterY = this.mRotationCenterY;
this.mTextTextureBuffer.update(font, lines);
this.updateVertexBuffer();
}
// ===========================================================
// Getter & Setter
// ===========================================================
public String getText() {
return this.mText;
}
public int getCharactersMaximum() {
return this.mCharactersMaximum;
}
@Override
public TextVertexBuffer getVertexBuffer() {
return (TextVertexBuffer)this.mVertexBuffer;
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
@Override
protected void onInitDraw(final GL10 pGL) {
super.onInitDraw(pGL);
GLHelper.enableTextures(pGL);
GLHelper.enableTexCoordArray(pGL);
}
@Override
protected void drawVertices(final GL10 pGL, final Camera pCamera) {
pGL.glDrawArrays(GL10.GL_TRIANGLES, 0, this.mVertexCount);
}
@Override
protected void onUpdateVertexBuffer() {
final Font font = this.mFont;
if(font != null) {
this.getVertexBuffer().update(font, this.mMaximumLineWidth, this.mWidths, this.mLines);
}
}
@Override
protected void onApplyTransformations(final GL10 pGL) {
super.onApplyTransformations(pGL);
this.applyTexture(pGL);
}
@Override
protected void finalize() throws Throwable {
super.finalize();
if(this.mTextTextureBuffer.isManaged()) {
this.mTextTextureBuffer.unloadFromActiveBufferObjectManager();
}
}
// ===========================================================
// Methods
// ===========================================================
private void initBlendFunction() {
if(this.mFont.getTexture().getTextureOptions().mPreMultipyAlpha) {
this.setBlendFunction(BLENDFUNCTION_SOURCE_PREMULTIPLYALPHA_DEFAULT, BLENDFUNCTION_DESTINATION_PREMULTIPLYALPHA_DEFAULT);
}
}
private void applyTexture(final GL10 pGL) {
if(GLHelper.EXTENSIONS_VERTEXBUFFEROBJECTS) {
final GL11 gl11 = (GL11)pGL;
this.mTextTextureBuffer.selectOnHardware(gl11);
this.mFont.getTexture().bind(pGL);
GLHelper.texCoordZeroPointer(gl11);
} else {
this.mFont.getTexture().bind(pGL);
GLHelper.texCoordPointer(pGL, this.mTextTextureBuffer.getFloatBuffer());
}
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}