package com.glview.hwui.font;
import android.opengl.Matrix;
import com.glview.graphics.shader.BaseShader;
import com.glview.graphics.shader.DefaultTextureShader;
import com.glview.hwui.Caches;
import com.glview.hwui.GLPaint;
import com.glview.libgdx.graphics.Mesh;
import com.glview.libgdx.graphics.VertexAttribute;
import com.glview.libgdx.graphics.VertexAttributes.Usage;
import com.glview.libgdx.graphics.glutils.ShaderProgram;
import com.glview.libgdx.graphics.math.NumberUtils;
import com.glview.libgdx.graphics.opengl.GL20;
import com.glview.libgdx.graphics.utils.Disposable;
import com.glview.util.MatrixUtil;
class FontBatch implements Disposable {
private Mesh mMesh;
final float[] mVertices;
int mIndex = 0;
final CacheTexture mTexture;
float mInvTexWidth, mInvTexHeight;
final FontRenderer mFontRenderer;
DefaultTextureShader mDefaultShader;
BaseShader mCustomShader;
Caches mCaches;
float[] mIdentityMatrix = new float[16];
float[] mTmpPoint = new float[2];
float mPackedColor;
float mCachedAlpha;
int mCachedColor;
public FontBatch(FontRenderer fontRenderer, CacheTexture texture) {
this(fontRenderer, texture, 2048);
}
public FontBatch(FontRenderer fontRenderer, CacheTexture texture, int size) {
// 32767 is max index, so 32767 / 6 - (32767 / 6 % 3) = 5460.
if (size > 5460) throw new IllegalArgumentException("Can't have more than 5460 sprites per batch: " + size);
mFontRenderer = fontRenderer;
mTexture = texture;
mInvTexWidth = 1.0f / texture.getWidth();
mInvTexHeight = 1.0f / texture.getHeight();
Matrix.setIdentityM(mIdentityMatrix, 0);
mCaches = Caches.getInstance();
mMesh = new Mesh(false, size * 4, size * 6, new VertexAttribute(
Usage.Position, 2, ShaderProgram.POSITION_ATTRIBUTE), // position
new VertexAttribute(Usage.ColorPacked, 4,
ShaderProgram.COLOR_ATTRIBUTE),
new VertexAttribute(Usage.TextureCoordinates, 2,
ShaderProgram.TEXCOORD_ATTRIBUTE));// texture position
mVertices = new float[size * 20];
int len = size * 6;
short[] indices = new short[len];
short j = 0;
for (int i = 0; i < len; i += 6, j += 4) {
indices[i] = j;
indices[i + 1] = (short)(j + 1);
indices[i + 2] = (short)(j + 2);
indices[i + 3] = (short)(j + 2);
indices[i + 4] = (short)(j + 3);
indices[i + 5] = j;
}
mMesh.setIndices(indices);
mDefaultShader = new DefaultTextureShader();
mDefaultShader.setHasTexcoordsAttr(true);
mDefaultShader.setHasColorAttr(true);
mDefaultShader.setHasTotalColor(false);
mDefaultShader.setA8Format(true);
}
@Override
public void dispose() {
mMesh.dispose();
}
public boolean full() {
return this.mIndex == this.mVertices.length;
}
public void draw(float x, float y, float width, float height, float srcX, float srcY, float srcWidth, float srcHeight, float[] transformation, float alpha, int color, GLPaint paint) {
float[] vertices = this.mVertices;
if (this.mIndex == vertices.length) //
flush();
final float u = srcX * mInvTexWidth;
final float v = srcY * mInvTexHeight;
final float u2 = (srcX + srcWidth) * mInvTexWidth;
final float v2 = (srcY + srcHeight) * mInvTexHeight;
final float fx2 = x + width;
final float fy2 = y + height;
float[] pt = MatrixUtil.mapPoint(transformation, mTmpPoint, x, y);
float x1 = pt[0], y1 = pt[1];
pt = MatrixUtil.mapPoint(transformation, mTmpPoint, x, fy2);
float x2 = pt[0], y2 = pt[1];
pt = MatrixUtil.mapPoint(transformation, mTmpPoint, fx2, fy2);
float x3 = pt[0], y3 = pt[1];
pt = MatrixUtil.mapPoint(transformation, mTmpPoint, fx2, y);
float x4 = pt[0], y4 = pt[1];
if (alpha != mCachedAlpha || color != mCachedColor) {
mCachedAlpha = alpha;
mCachedColor = color;
mPackedColor = NumberUtils.intToFloatColor(packColor(alpha, color));
}
float c = mPackedColor;
int idx = this.mIndex;
vertices[idx++] = x1;
vertices[idx++] = y1;
vertices[idx++] = c;
vertices[idx++] = u;
vertices[idx++] = v;
vertices[idx++] = x2;
vertices[idx++] = y2;
vertices[idx++] = c;
vertices[idx++] = u;
vertices[idx++] = v2;
vertices[idx++] = x3;
vertices[idx++] = y3;
vertices[idx++] = c;
vertices[idx++] = u2;
vertices[idx++] = v2;
vertices[idx++] = x4;
vertices[idx++] = y4;
vertices[idx++] = c;
vertices[idx++] = u2;
vertices[idx++] = v;
this.mIndex = idx;
}
public void draw(float x, float y, float width, float height, float srcX, float srcY, float srcWidth, float srcHeight, float alpha, int color, GLPaint paint) {
float[] vertices = this.mVertices;
if (this.mIndex == vertices.length) //
flush();
final float u = srcX * mInvTexWidth;
final float v = srcY * mInvTexHeight;
final float u2 = (srcX + srcWidth) * mInvTexWidth;
final float v2 = (srcY + srcHeight) * mInvTexHeight;
final float fx2 = x + width;
final float fy2 = y + height;
float c = NumberUtils.intToFloatColor(packColor(alpha, color));
int idx = this.mIndex;
vertices[idx++] = x;
vertices[idx++] = y;
vertices[idx++] = c;
vertices[idx++] = u;
vertices[idx++] = v;
vertices[idx++] = x;
vertices[idx++] = fy2;
vertices[idx++] = c;
vertices[idx++] = u;
vertices[idx++] = v2;
vertices[idx++] = fx2;
vertices[idx++] = fy2;
vertices[idx++] = c;
vertices[idx++] = u2;
vertices[idx++] = v2;
vertices[idx++] = fx2;
vertices[idx++] = y;
vertices[idx++] = c;
vertices[idx++] = u2;
vertices[idx++] = v;
this.mIndex = idx;
}
public void flush() {
if (mIndex == 0) return;
mTexture.upload();
int count = mIndex / 20 * 6;
mCaches.bindTexture(mTexture.mTexture);
Mesh mesh = this.mMesh;
mesh.setVertices(mVertices, 0, mIndex);
mesh.getIndicesBuffer().position(0);
mesh.getIndicesBuffer().limit(count);
ShaderProgram program = mDefaultShader.getShaderProgram();
mCaches.useProgram(program);
mDefaultShader.setupColor(1, 1, 1, 1);
if (mFontRenderer.getGLCanvas() != null) {
mFontRenderer.getGLCanvas().applyMatrix(mDefaultShader, mIdentityMatrix);
}
mDefaultShader.setupCustomValues();
mesh.render(program, GL20.GL_TRIANGLES, 0, count);
mIndex = 0;
}
int packColor(float alpha, int color) {
float prealpha = ((color >>> 24) & 0xFF) * alpha / 255;
float colorR = Math.round(((color >> 16) & 0xFF)) * prealpha / 255;
float colorG = Math.round(((color >> 8) & 0xFF)) * prealpha / 255;
float colorB = Math.round((color & 0xFF)) * prealpha / 255;
float colorA = Math.round(255 * prealpha) * 1.0f / 255;
int intBits = (int)(255 * colorA) << 24 | (int)(255 * colorB) << 16 | (int)(255 * colorG) << 8 | (int)(255 * colorR);
return intBits;
}
}