package org.andengine.entity.text.vbo;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import org.andengine.entity.text.Text;
import org.andengine.opengl.font.IFont;
import org.andengine.opengl.font.Letter;
import org.andengine.opengl.vbo.DrawType;
import org.andengine.opengl.vbo.LowMemoryVertexBufferObject;
import org.andengine.opengl.vbo.VertexBufferObjectManager;
import org.andengine.opengl.vbo.attribute.VertexBufferObjectAttributes;
import org.andengine.util.adt.list.IFloatList;
/**
* (c) Zynga 2012
*
* @author Nicolas Gramlich <ngramlich@zynga.com>
* @since 12:38:22 - 29.03.2012
*/
public class LowMemoryTextVertexBufferObject extends LowMemoryVertexBufferObject implements ITextVertexBufferObject {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
// ===========================================================
// Constructors
// ===========================================================
public LowMemoryTextVertexBufferObject(final VertexBufferObjectManager pVertexBufferObjectManager, final int pCapacity, final DrawType pDrawType, final boolean pAutoDispose, final VertexBufferObjectAttributes pVertexBufferObjectAttributes) {
super(pVertexBufferObjectManager, pCapacity, pDrawType, pAutoDispose, pVertexBufferObjectAttributes);
}
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
@Override
public void onUpdateColor(final Text pText) {
final FloatBuffer bufferData = this.mFloatBuffer;
final float packedColor = pText.getColor().getABGRPackedFloat();
int bufferDataOffset = 0;
final int charactersMaximum = pText.getCharactersMaximum();
for(int i = 0; i < charactersMaximum; i++) {
bufferData.put(bufferDataOffset + 0 * Text.VERTEX_SIZE + Text.COLOR_INDEX, packedColor);
bufferData.put(bufferDataOffset + 1 * Text.VERTEX_SIZE + Text.COLOR_INDEX, packedColor);
bufferData.put(bufferDataOffset + 2 * Text.VERTEX_SIZE + Text.COLOR_INDEX, packedColor);
bufferData.put(bufferDataOffset + 3 * Text.VERTEX_SIZE + Text.COLOR_INDEX, packedColor);
bufferData.put(bufferDataOffset + 4 * Text.VERTEX_SIZE + Text.COLOR_INDEX, packedColor);
bufferData.put(bufferDataOffset + 5 * Text.VERTEX_SIZE + Text.COLOR_INDEX, packedColor);
bufferDataOffset += Text.LETTER_SIZE;
}
this.setDirtyOnHardware();
}
@Override
public void onUpdateVertices(final Text pText) {
final FloatBuffer bufferData = this.mFloatBuffer;
// TODO Optimize with field access?
final IFont font = pText.getFont();
final ArrayList<CharSequence> lines = pText.getLines();
final float lineHeight = font.getLineHeight();
final IFloatList lineWidths = pText.getLineWidths();
final float lineAlignmentWidth = pText.getLineAlignmentWidth();
int charactersToDraw = 0;
int bufferDataOffset = 0;
final int lineCount = lines.size();
for (int i = 0; i < lineCount; i++) {
final CharSequence line = lines.get(i);
float xBase;
switch(pText.getHorizontalAlign()) {
case RIGHT:
xBase = lineAlignmentWidth - lineWidths.get(i);
break;
case CENTER:
xBase = (lineAlignmentWidth - lineWidths.get(i)) * 0.5f;
break;
case LEFT:
default:
xBase = 0;
}
final float yBase = i * (lineHeight + pText.getLeading());
final int lineLength = line.length();
Letter previousLetter = null;
for(int j = 0; j < lineLength; j++) {
final Letter letter = font.getLetter(line.charAt(j));
if(previousLetter != null) {
xBase += previousLetter.getKerning(letter.mCharacter);
}
if(!letter.isWhitespace()) {
final float x = xBase + letter.mOffsetX;
final float y = yBase + letter.mOffsetY;
final float y2 = y + letter.mHeight;
final float x2 = x + letter.mWidth;
final float u = letter.mU;
final float v = letter.mV;
final float u2 = letter.mU2;
final float v2 = letter.mV2;
bufferData.put(bufferDataOffset + 0 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_X, x);
bufferData.put(bufferDataOffset + 0 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_Y, y);
bufferData.put(bufferDataOffset + 0 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_U, u);
bufferData.put(bufferDataOffset + 0 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_V, v);
bufferData.put(bufferDataOffset + 1 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_X, x);
bufferData.put(bufferDataOffset + 1 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_Y, y2);
bufferData.put(bufferDataOffset + 1 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_U, u);
bufferData.put(bufferDataOffset + 1 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_V, v2);
bufferData.put(bufferDataOffset + 2 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_X, x2);
bufferData.put(bufferDataOffset + 2 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_Y, y2);
bufferData.put(bufferDataOffset + 2 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_U, u2);
bufferData.put(bufferDataOffset + 2 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_V, v2);
bufferData.put(bufferDataOffset + 3 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_X, x2);
bufferData.put(bufferDataOffset + 3 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_Y, y2);
bufferData.put(bufferDataOffset + 3 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_U, u2);
bufferData.put(bufferDataOffset + 3 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_V, v2);
bufferData.put(bufferDataOffset + 4 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_X, x2);
bufferData.put(bufferDataOffset + 4 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_Y, y);
bufferData.put(bufferDataOffset + 4 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_U, u2);
bufferData.put(bufferDataOffset + 4 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_V, v);
bufferData.put(bufferDataOffset + 5 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_X, x);
bufferData.put(bufferDataOffset + 5 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_Y, y);
bufferData.put(bufferDataOffset + 5 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_U, u);
bufferData.put(bufferDataOffset + 5 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_V, v);
bufferDataOffset += Text.LETTER_SIZE;
charactersToDraw++;
}
xBase += letter.mAdvance;
previousLetter = letter;
}
}
pText.setCharactersToDraw(charactersToDraw);
this.setDirtyOnHardware();
}
// ===========================================================
// Methods
// ===========================================================
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}