From 8dd939f4dcc524c7998b6e737676944644a079f7 Mon Sep 17 00:00:00 2001 From: seven332 Date: Fri, 24 Jul 2015 16:40:35 +0800 Subject: [PATCH] Add SpriteTexture and TextTexture --- .../gallery/glrenderer/SpriteTexture.java | 73 ++++++++++ .../gallery/glrenderer/TextTexture.java | 129 ++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/SpriteTexture.java create mode 100644 app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/TextTexture.java diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/SpriteTexture.java b/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/SpriteTexture.java new file mode 100644 index 000000000..07339789e --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/SpriteTexture.java @@ -0,0 +1,73 @@ +package com.hippo.ehviewer.gallery.glrenderer; + +import android.graphics.Bitmap; +import android.graphics.RectF; + +import com.hippo.yorozuya.AssertUtils; + +public class SpriteTexture extends TiledTexture { + + private int mCount; + private int[] mRects; + + private RectF mTempSource = new RectF(); + private RectF mTempTarget = new RectF(); + + public SpriteTexture(Bitmap bitmap, int count, int[] rects) { + super(bitmap); + + AssertUtils.assertEquals("rects.length must be count * 4", count * 4, rects.length); + mCount = count; + mRects = rects; + } + + public int getCount() { + return mCount; + } + + public void drawSprite(GLCanvas canvas, int index, int x, int y) { + int[] rects = mRects; + int offset = index * 4; + int sourceX = rects[offset]; + int sourceY = rects[offset + 1]; + int sourceWidth = rects[offset + 2]; + int sourceHeight = rects[offset + 3]; + mTempSource.set(sourceX, sourceY, sourceX + sourceWidth, sourceY + sourceHeight); + mTempTarget.set(x, y, x + sourceWidth, y + sourceHeight); + draw(canvas, mTempSource, mTempTarget); + } + + public void drawSprite(GLCanvas canvas, int index, int x, int y, int width, int height) { + int[] rects = mRects; + int offset = index * 4; + int sourceX = rects[offset]; + int sourceY = rects[offset + 1]; + mTempSource.set(sourceX, sourceY, sourceX + rects[offset + 2], sourceY + rects[offset + 3]); + mTempTarget.set(x, y, x + width, y + height); + draw(canvas, mTempSource, mTempTarget); + } + + public void drawSpriteMixed(GLCanvas canvas, int index, int color, float ratio, int x, int y) { + int[] rects = mRects; + int offset = index * 4; + int sourceX = rects[offset]; + int sourceY = rects[offset + 1]; + int sourceWidth = rects[offset + 2]; + int sourceHeight = rects[offset + 3]; + mTempSource.set(sourceX, sourceY, sourceX + sourceWidth, sourceY + sourceHeight); + mTempTarget.set(x, y, x + sourceWidth, y + sourceHeight); + drawMixed(canvas, color, ratio, mTempSource, mTempTarget); + } + + public void drawSpriteMixed(GLCanvas canvas, int index, int color, float ratio, + int x, int y, int width, int height) { + int[] rects = mRects; + int offset = index * 4; + int sourceX = rects[offset]; + int sourceY = rects[offset + 1]; + mTempSource.set(sourceX, sourceY, sourceX + rects[offset + 2], + sourceY + rects[offset + 3]); + mTempTarget.set(x, y, x + width, y + height); + drawMixed(canvas, color, ratio, mTempSource, mTempTarget); + } +} diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/TextTexture.java b/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/TextTexture.java new file mode 100644 index 000000000..978645682 --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/gallery/glrenderer/TextTexture.java @@ -0,0 +1,129 @@ +package com.hippo.ehviewer.gallery.glrenderer; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.Typeface; + +import java.util.Arrays; + +public class TextTexture extends SpriteTexture { + + private char[] mCharacters; + private float[] mWidths; + private float mHeight; + private float mMaxWidth; + + private TextTexture(Bitmap bitmap, int count, int[] rects, char[] characters, + float[] widths, float height, float maxWidth) { + super(bitmap, count, rects); + mCharacters = characters; + mWidths = widths; + mHeight = height; + mMaxWidth = maxWidth; + } + + public float getTextWidth(String text) { + char[] characters = mCharacters; + float[] widths = mWidths; + float width = 0.0f; + + for (int i = 0, n = text.length(); i < n; i++) { + char ch = text.charAt(i); + int index = Arrays.binarySearch(characters, ch); + if (index >= 0) { + width += widths[index]; + } else { + width += mMaxWidth; + } + } + + return width; + } + + public void drawText(GLCanvas canvas, String text, int x, int y) { + char[] characters = mCharacters; + float[] widths = mWidths; + + for (int i = 0, n = text.length(); i < n; i++) { + char ch = text.charAt(i); + int index = Arrays.binarySearch(characters, ch); + if (index >= 0) { + drawSprite(canvas, index, x, y); + x += widths[index]; + } else { + x += mMaxWidth; + } + } + } + + /** + * Create a TextTexture to draw text + * + * @param typeface the typeface + * @param size text size + * @param characters all Characters + * @return the TextTexture + */ + public static TextTexture create(Typeface typeface, int size, int color, char[] characters) { + Paint paint = new Paint(); + paint.setAntiAlias(true); + paint.setTextSize(size); + paint.setColor(color); + paint.setTypeface(typeface); + + Rect rect = new Rect(); + paint.getTextBounds(characters, 0, Math.min(5, characters.length), rect); + int height = rect.height(); + + int length = characters.length; + float[] widths = new float[length]; + paint.getTextWidths(characters, 0, length, widths); + + // Caculate bitmap size + float maxWidth = 0.0f; + for (float f : widths) { + maxWidth = Math.max(maxWidth, f); + } + int hCount = (int) Math.ceil(Math.sqrt(height / maxWidth * length)); + int vCount = (int) Math.ceil(Math.sqrt(maxWidth / height * length)); + if (hCount * (vCount - 1) > length) { + vCount--; + } + if ((hCount - 1) * vCount > length) { + hCount--; + } + + Bitmap bitmap = Bitmap.createBitmap((int) Math.ceil(hCount * maxWidth), + (int) Math.ceil(vCount * height), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + // TODO draw text do not precisely start from X, how to get the fix + int fix = size / 96 + 1; + canvas.translate(0, height - fix); + + // Draw + int[] rects = new int[length * 4]; + int x = 0; + int y = 0; + for (int i = 0; i < length; i++) { + int offset = i * 4; + rects[offset + 0] = x; + rects[offset + 1] = y; + rects[offset + 2] = (int) widths[i]; + rects[offset + 3] = height; + + canvas.drawText(characters, i, 1, x, y, paint); + + if (i % hCount == hCount - 1) { + // The end of row + x = 0; + y += height; + } else { + x += maxWidth; + } + } + + return new TextTexture(bitmap, length, rects, characters, widths, height, maxWidth); + } +}