package org.andengine.entity.text.vbo; 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.HighPerformanceVertexBufferObject; 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:43 - 29.03.2012 */ public class HighPerformanceTextVertexBufferObject extends HighPerformanceVertexBufferObject implements ITextVertexBufferObject { // =========================================================== // Constants // =========================================================== // =========================================================== // Fields // =========================================================== // =========================================================== // Constructors // =========================================================== public HighPerformanceTextVertexBufferObject(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 float[] bufferData = this.mBufferData; final float packedColor = pText.getColor().getABGRPackedFloat(); int bufferDataOffset = 0; final int charactersMaximum = pText.getCharactersMaximum(); for(int i = 0; i < charactersMaximum; i++) { bufferData[bufferDataOffset + 0 * Text.VERTEX_SIZE + Text.COLOR_INDEX] = packedColor; bufferData[bufferDataOffset + 1 * Text.VERTEX_SIZE + Text.COLOR_INDEX] = packedColor; bufferData[bufferDataOffset + 2 * Text.VERTEX_SIZE + Text.COLOR_INDEX] = packedColor; bufferData[bufferDataOffset + 3 * Text.VERTEX_SIZE + Text.COLOR_INDEX] = packedColor; bufferData[bufferDataOffset + 4 * Text.VERTEX_SIZE + Text.COLOR_INDEX] = packedColor; bufferData[bufferDataOffset + 5 * Text.VERTEX_SIZE + Text.COLOR_INDEX] = packedColor; bufferDataOffset += Text.LETTER_SIZE; } this.setDirtyOnHardware(); } @Override public void onUpdateVertices(final Text pText) { final float[] bufferData = this.mBufferData; // 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 row = 0; row < lineCount; row++) { final CharSequence line = lines.get(row); float xBase; switch(pText.getHorizontalAlign()) { case RIGHT: xBase = lineAlignmentWidth - lineWidths.get(row); break; case CENTER: xBase = (lineAlignmentWidth - lineWidths.get(row)) * 0.5f; break; case LEFT: default: xBase = 0; } final float yBase = row * (lineHeight + pText.getLeading()); final int lineLength = line.length(); Letter previousLetter = null; for(int i = 0; i < lineLength; i++) { final Letter letter = font.getLetter(line.charAt(i)); 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[bufferDataOffset + 0 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_X] = x; bufferData[bufferDataOffset + 0 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_Y] = y; bufferData[bufferDataOffset + 0 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_U] = u; bufferData[bufferDataOffset + 0 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_V] = v; bufferData[bufferDataOffset + 1 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_X] = x; bufferData[bufferDataOffset + 1 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_Y] = y2; bufferData[bufferDataOffset + 1 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_U] = u; bufferData[bufferDataOffset + 1 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_V] = v2; bufferData[bufferDataOffset + 2 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_X] = x2; bufferData[bufferDataOffset + 2 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_Y] = y2; bufferData[bufferDataOffset + 2 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_U] = u2; bufferData[bufferDataOffset + 2 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_V] = v2; bufferData[bufferDataOffset + 3 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_X] = x2; bufferData[bufferDataOffset + 3 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_Y] = y2; bufferData[bufferDataOffset + 3 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_U] = u2; bufferData[bufferDataOffset + 3 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_V] = v2; bufferData[bufferDataOffset + 4 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_X] = x2; bufferData[bufferDataOffset + 4 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_Y] = y; bufferData[bufferDataOffset + 4 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_U] = u2; bufferData[bufferDataOffset + 4 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_V] = v; bufferData[bufferDataOffset + 5 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_X] = x; bufferData[bufferDataOffset + 5 * Text.VERTEX_SIZE + Text.VERTEX_INDEX_Y] = y; bufferData[bufferDataOffset + 5 * Text.VERTEX_SIZE + Text.TEXTURECOORDINATES_INDEX_U] = u; bufferData[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 // =========================================================== }