diff --git a/app/build.gradle b/app/build.gradle index 34b67a7c8..003125677 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -63,7 +63,7 @@ dependencies { compile 'com.github.seven332:conaco:0.1.3-eh' compile 'com.github.seven332:easyrecyclerview:0.1.0' compile 'com.github.seven332:drawerLayout:0.1.0' - compile 'com.github.seven332:image:0.1.3' + compile 'com.github.seven332:image:0.1.4' compile 'com.github.seven332:okhttp:3.2.0-eh' compile 'com.github.seven332:refreshlayout:0.1.0' compile 'com.github.seven332:ripple:0.1.1' diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/gl/GalleryPageView.java b/app/src/main/java/com/hippo/ehviewer/gallery/gl/GalleryPageView.java index 90d971e99..ac20b6471 100644 --- a/app/src/main/java/com/hippo/ehviewer/gallery/gl/GalleryPageView.java +++ b/app/src/main/java/com/hippo/ehviewer/gallery/gl/GalleryPageView.java @@ -19,8 +19,8 @@ package com.hippo.ehviewer.gallery.gl; import android.content.Context; import com.hippo.gl.glrenderer.BasicTexture; +import com.hippo.gl.glrenderer.ImageMovableTextTexture; import com.hippo.gl.glrenderer.ImageTexture; -import com.hippo.gl.glrenderer.MovableTextTexture; import com.hippo.gl.glrenderer.Texture; import com.hippo.gl.view.Gravity; import com.hippo.gl.widget.GLFrameLayout; @@ -49,7 +49,7 @@ public class GalleryPageView extends GLFrameLayout { private int mIndex = INVALID_INDEX; - public GalleryPageView(Context context, MovableTextTexture pageTextTexture, + public GalleryPageView(Context context, ImageMovableTextTexture pageTextTexture, int progressColor, int progressSize) { // Add image mImage = new ImageView(); diff --git a/app/src/main/java/com/hippo/ehviewer/gallery/gl/GalleryView.java b/app/src/main/java/com/hippo/ehviewer/gallery/gl/GalleryView.java index 4a9bde080..abc0454af 100644 --- a/app/src/main/java/com/hippo/ehviewer/gallery/gl/GalleryView.java +++ b/app/src/main/java/com/hippo/ehviewer/gallery/gl/GalleryView.java @@ -28,7 +28,7 @@ import com.hippo.ehviewer.R; import com.hippo.gl.annotation.RenderThread; import com.hippo.gl.glrenderer.BasicTexture; import com.hippo.gl.glrenderer.GLCanvas; -import com.hippo.gl.glrenderer.MovableTextTexture; +import com.hippo.gl.glrenderer.ImageMovableTextTexture; import com.hippo.gl.glrenderer.StringTexture; import com.hippo.gl.glrenderer.Texture; import com.hippo.gl.util.GalleryUtils; @@ -90,7 +90,7 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener { private static final int METHOD_ON_ATTACH_TO_ROOT = 20; private final Context mContext; - private MovableTextTexture mPageTextTexture; + private ImageMovableTextTexture mPageTextTexture; private final GestureRecognizer mGestureRecognizer; private Adapter mAdapter; @@ -228,7 +228,7 @@ public class GalleryView extends GLView implements GestureRecognizer.Listener { @SuppressWarnings("deprecation") private void onAttachToRootInternal() { if (null == mPageTextTexture) { - mPageTextTexture = MovableTextTexture.create(Typeface.DEFAULT, + mPageTextTexture = ImageMovableTextTexture.create(Typeface.DEFAULT, mContext.getResources().getDimensionPixelSize(R.dimen.gallery_page_text), mContext.getResources().getColor(R.color.secondary_text_dark), new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}); diff --git a/app/src/main/java/com/hippo/gl/glrenderer/ImageMovableTextTexture.java b/app/src/main/java/com/hippo/gl/glrenderer/ImageMovableTextTexture.java new file mode 100644 index 000000000..c169cf102 --- /dev/null +++ b/app/src/main/java/com/hippo/gl/glrenderer/ImageMovableTextTexture.java @@ -0,0 +1,210 @@ +/* + * Copyright 2016 Hippo Seven + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.gl.glrenderer; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Typeface; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.hippo.image.Image; +import com.hippo.image.ImageWrapper; + +import java.util.Arrays; + +public class ImageMovableTextTexture extends ImageSpriteTexture { + + private final char[] mCharacters; + private final float[] mWidths; + private final float mHeight; + private final float mMaxWidth; + + public ImageMovableTextTexture(@NonNull ImageWrapper image, int count, int[] rects, + char[] characters, float[] widths, float height, float maxWidth) { + super(image, count, rects); + + mCharacters = characters; + mWidths = widths; + mHeight = height; + mMaxWidth = maxWidth; + } + + public int[] getTextIndexes(String text) { + char[] characters = mCharacters; + + int length = text.length(); + int[] indexes = new int[length]; + for (int i = 0; i < length; i++) { + char ch = text.charAt(i); + indexes[i] = Arrays.binarySearch(characters, ch); + } + + return indexes; + } + + 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 float getTextWidth(int[] indexes) { + float[] widths = mWidths; + float width = 0.0f; + int length = indexes.length; + for (int i = 0; i < length; i++) { + int index = indexes[i]; + if (index >= 0) { + width += widths[index]; + } else { + width += mMaxWidth; + } + } + + return width; + } + + public float getMaxWidth() { + return mMaxWidth; + } + + public float getTextHeight() { + return mHeight; + } + + 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; + } + } + } + + public void drawText(GLCanvas canvas, int[] indexes, int x, int y) { + float[] widths = mWidths; + + for (int i = 0, n = indexes.length; i < n; i++) { + int index = indexes[i]; + 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 + */ + @Nullable + public static ImageMovableTextTexture 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); + + Paint.FontMetricsInt fmi = paint.getFontMetricsInt(); + int fixed = fmi.bottom; + int height = fmi.bottom - fmi.top; + + int length = characters.length; + float[] widths = new float[length]; + paint.getTextWidths(characters, 0, length, widths); + + // Calculate 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); + canvas.translate(0, height - fixed); + + // 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; + } + } + + Image image = Image.create(bitmap); + bitmap.recycle(); + if (image == null) { + return null; + } + ImageWrapper imageWrapper = new ImageWrapper(image); + if (imageWrapper.obtain()) { + return new ImageMovableTextTexture(imageWrapper, length, rects, characters, widths, height, maxWidth); + } else { + return null; + } + } +} diff --git a/app/src/main/java/com/hippo/gl/glrenderer/ImageSpriteTexture.java b/app/src/main/java/com/hippo/gl/glrenderer/ImageSpriteTexture.java new file mode 100644 index 000000000..d7a2e237f --- /dev/null +++ b/app/src/main/java/com/hippo/gl/glrenderer/ImageSpriteTexture.java @@ -0,0 +1,90 @@ +/* + * Copyright 2016 Hippo Seven + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.gl.glrenderer; + +import android.graphics.RectF; +import android.support.annotation.NonNull; + +import com.hippo.image.ImageWrapper; +import com.hippo.yorozuya.AssertUtils; + +public class ImageSpriteTexture extends ImageTexture { + + private final int mCount; + private final int[] mRects; + + private final RectF mTempSource = new RectF(); + private final RectF mTempTarget = new RectF(); + + public ImageSpriteTexture(@NonNull ImageWrapper image, int count, int[] rects) { + super(image); + + 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/gl/glrenderer/ImageTexture.java b/app/src/main/java/com/hippo/gl/glrenderer/ImageTexture.java index b0ef3673a..3f09ca893 100644 --- a/app/src/main/java/com/hippo/gl/glrenderer/ImageTexture.java +++ b/app/src/main/java/com/hippo/gl/glrenderer/ImageTexture.java @@ -368,6 +368,9 @@ public class ImageTexture implements Texture, Animatable { } } + /** + * Call {@link ImageWrapper#obtain()} first + */ public ImageTexture(@NonNull ImageWrapper image) { mImage = image; int width = mWidth = image.getWidth(); diff --git a/app/src/main/java/com/hippo/gl/widget/GLMovableTextView.java b/app/src/main/java/com/hippo/gl/widget/GLMovableTextView.java index ffe11e93a..1132b5059 100644 --- a/app/src/main/java/com/hippo/gl/widget/GLMovableTextView.java +++ b/app/src/main/java/com/hippo/gl/widget/GLMovableTextView.java @@ -20,14 +20,14 @@ import android.graphics.Rect; import android.text.TextUtils; import com.hippo.gl.glrenderer.GLCanvas; -import com.hippo.gl.glrenderer.MovableTextTexture; +import com.hippo.gl.glrenderer.ImageMovableTextTexture; import com.hippo.gl.view.GLView; import com.hippo.gl.view.Gravity; import com.hippo.yorozuya.collect.CollectionUtils; public class GLMovableTextView extends GLView { - MovableTextTexture mTextTexture; + ImageMovableTextTexture mTextTexture; private String mText = ""; private int[] mIndexes = CollectionUtils.EMPTY_INT_ARRAY; @@ -42,7 +42,7 @@ public class GLMovableTextView extends GLView { } } - public void setTextTexture(MovableTextTexture textTexture) { + public void setTextTexture(ImageMovableTextTexture textTexture) { if (mTextTexture == textTexture) { return; }