diff --git a/app/src/main/java/com/hippo/gl/glrenderer/TextTexture.java b/app/src/main/java/com/hippo/gl/glrenderer/MovableTextTexture.java similarity index 91% rename from app/src/main/java/com/hippo/gl/glrenderer/TextTexture.java rename to app/src/main/java/com/hippo/gl/glrenderer/MovableTextTexture.java index 22b6848ad..f67593e3e 100644 --- a/app/src/main/java/com/hippo/gl/glrenderer/TextTexture.java +++ b/app/src/main/java/com/hippo/gl/glrenderer/MovableTextTexture.java @@ -9,18 +9,20 @@ import java.util.Arrays; // TODO support multiline /** - * Only support single line + * Works like movable type.
+ *
+ * Only support single line now */ -public class TextTexture extends SpriteTexture { +public class MovableTextTexture extends SpriteTexture { private char[] mCharacters; private float[] mWidths; private float mHeight; private float mMaxWidth; - private TextTexture(Bitmap bitmap, int count, int[] rects, char[] characters, + private MovableTextTexture(Bitmap bitmap, int count, int[] rects, char[] characters, float[] widths, float height, float maxWidth) { - super(bitmap, count, rects); + super(bitmap, false, count, rects); mCharacters = characters; mWidths = widths; mHeight = height; @@ -120,7 +122,7 @@ public class TextTexture extends SpriteTexture { * @param characters all Characters * @return the TextTexture */ - public static TextTexture create(Typeface typeface, int size, int color, char[] characters) { + public static MovableTextTexture create(Typeface typeface, int size, int color, char[] characters) { Paint paint = new Paint(); paint.setAntiAlias(true); paint.setTextSize(size); @@ -176,6 +178,6 @@ public class TextTexture extends SpriteTexture { } } - return new TextTexture(bitmap, length, rects, characters, widths, height, maxWidth); + return new MovableTextTexture(bitmap, length, rects, characters, widths, height, maxWidth); } } diff --git a/app/src/main/java/com/hippo/gl/glrenderer/SpriteTexture.java b/app/src/main/java/com/hippo/gl/glrenderer/SpriteTexture.java index fcfeac8ec..2c64ac226 100644 --- a/app/src/main/java/com/hippo/gl/glrenderer/SpriteTexture.java +++ b/app/src/main/java/com/hippo/gl/glrenderer/SpriteTexture.java @@ -13,8 +13,8 @@ public class SpriteTexture extends TiledTexture { private RectF mTempSource = new RectF(); private RectF mTempTarget = new RectF(); - public SpriteTexture(Bitmap bitmap, int count, int[] rects) { - super(bitmap); + public SpriteTexture(Bitmap bitmap, boolean isOpaque, int count, int[] rects) { + super(bitmap, isOpaque); AssertUtils.assertEquals("rects.length must be count * 4", count * 4, rects.length); mCount = count; diff --git a/app/src/main/java/com/hippo/gl/glrenderer/TiledTexture.java b/app/src/main/java/com/hippo/gl/glrenderer/TiledTexture.java index c926ea785..b7c156a48 100644 --- a/app/src/main/java/com/hippo/gl/glrenderer/TiledTexture.java +++ b/app/src/main/java/com/hippo/gl/glrenderer/TiledTexture.java @@ -17,11 +17,10 @@ package com.hippo.gl.glrenderer; import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import android.graphics.PorterDuff.Mode; +import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.os.SystemClock; @@ -62,6 +61,16 @@ public class TiledTexture implements Texture { private final RectF mSrcRect = new RectF(); private final RectF mDestRect = new RectF(); + static { + sUploadBitmap = Bitmap.createBitmap(TILE_SIZE, TILE_SIZE, Bitmap.Config.ARGB_8888); + sCanvas = new Canvas(sUploadBitmap); + sBitmapPaint = new Paint(Paint.FILTER_BITMAP_FLAG); + sBitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); + sPaint = new Paint(); + sPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); + sPaint.setColor(Color.TRANSPARENT); + } + public static class Uploader implements GLRoot.OnGLIdleListener { private final ArrayDeque mTextures = new ArrayDeque<>(INIT_CAPACITY); @@ -198,10 +207,10 @@ public class TiledTexture implements Texture { return mUploadIndex == mTiles.length; } - public TiledTexture(Bitmap bitmap) { + public TiledTexture(Bitmap bitmap, boolean isOpaque) { mWidth = bitmap.getWidth(); mHeight = bitmap.getHeight(); - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList<>(); for (int x = 0, w = mWidth; x < w; x += CONTENT_SIZE) { for (int y = 0, h = mHeight; y < h; y += CONTENT_SIZE) { @@ -212,6 +221,7 @@ public class TiledTexture implements Texture { tile.setSize( Math.min(CONTENT_SIZE, mWidth - x), Math.min(CONTENT_SIZE, mHeight - y)); + tile.setOpaque(isOpaque); list.add(tile); } } @@ -231,23 +241,6 @@ public class TiledTexture implements Texture { } } - public static void freeResources() { - sUploadBitmap = null; - sCanvas = null; - sBitmapPaint = null; - sPaint = null; - } - - public static void prepareResources() { - sUploadBitmap = Bitmap.createBitmap(TILE_SIZE, TILE_SIZE, Config.ARGB_8888); - sCanvas = new Canvas(sUploadBitmap); - sBitmapPaint = new Paint(Paint.FILTER_BITMAP_FLAG); - sBitmapPaint.setXfermode(new PorterDuffXfermode(Mode.SRC)); - sPaint = new Paint(); - sPaint.setXfermode(new PorterDuffXfermode(Mode.SRC)); - sPaint.setColor(Color.TRANSPARENT); - } - // We want to draw the "source" on the "target". // This method is to find the "output" rectangle which is // the corresponding area of the "src". @@ -334,6 +327,7 @@ public class TiledTexture implements Texture { } // Draws a sub region of this texture on to the specified rectangle. + @Override public void draw(GLCanvas canvas, RectF source, RectF target) { RectF src = mSrcRect; RectF dest = mDestRect; diff --git a/app/src/main/java/com/hippo/gl/view/GLView.java b/app/src/main/java/com/hippo/gl/view/GLView.java index f5673bc13..b4a6eac03 100644 --- a/app/src/main/java/com/hippo/gl/view/GLView.java +++ b/app/src/main/java/com/hippo/gl/view/GLView.java @@ -20,6 +20,7 @@ import android.graphics.Color; import android.graphics.Rect; import android.os.Parcelable; import android.os.SystemClock; +import android.support.annotation.IntDef; import android.util.Log; import android.util.SparseArray; import android.view.MotionEvent; @@ -29,6 +30,8 @@ import com.hippo.gl.glrenderer.GLCanvas; import com.hippo.gl.glrenderer.GLPaint; import com.hippo.yorozuya.AssertUtils; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; // GLView is a UI component. It can render to a GLCanvas and accept touch @@ -49,14 +52,20 @@ import java.util.ArrayList; public class GLView implements TouchOwner { private static final String TAG = "GLView"; - private static final boolean DEBUG_DRAW_BOUNDS = true; + private static final boolean DEBUG_DRAW_BOUNDS = false; - public static final int VISIBLE = 0; - public static final int INVISIBLE = 1; + @IntDef({VISIBLE, INVISIBLE, GONE}) + @Retention(RetentionPolicy.SOURCE) + public @interface Visibility {} - private static final int FLAG_INVISIBLE = 1; - private static final int FLAG_SET_MEASURED_SIZE = 2; - private static final int FLAG_LAYOUT_REQUESTED = 4; + public static final int VISIBLE = 0b00000000; + public static final int INVISIBLE = 0b00000001; + public static final int GONE = 0b00000010; + public static final int VISIBILITY_INVALID = 0b00000011; + + private static final int FLAG_INVISIBLE = 0b00000011; + private static final int FLAG_SET_MEASURED_SIZE = 0b00000100; + private static final int FLAG_LAYOUT_REQUESTED = 0b00001000; /** * Used to mark a GlView that has no ID. @@ -143,22 +152,47 @@ public class GLView implements TouchOwner { private OnClickListener mOnClickListener; private OnLongClickListener mOnLongClickListener; - // Sets the visibility of this GLView (either GLView.VISIBLE or - // GLView.INVISIBLE). - public void setVisibility(int visibility) { - if (visibility == getVisibility()) return; - if (visibility == VISIBLE) { - mViewFlags &= ~FLAG_INVISIBLE; + /** + * Set the enabled state of this view. + * + * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. + */ + public void setVisibility(@Visibility int visibility) { + @Visibility + int oldVisibility = getVisibility(); + if (visibility == oldVisibility) { + return; + } + + mViewFlags &= ~FLAG_INVISIBLE; + mViewFlags |= visibility; + + onVisibilityChanged(this, visibility); + + if (oldVisibility == GLView.GONE || visibility == GLView.GONE) { + requestLayout(); } else { - mViewFlags |= FLAG_INVISIBLE; + invalidate(); } - onVisibilityChanged(visibility); - invalidate(); } - // Returns GLView.VISIBLE or GLView.INVISIBLE + /** + * Returns the visibility status for this view. + * + * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. + */ + @Visibility + @SuppressWarnings("WrongConstant") public int getVisibility() { - return (mViewFlags & FLAG_INVISIBLE) == 0 ? VISIBLE : INVISIBLE; + int visibility = mViewFlags & FLAG_INVISIBLE; + + if (visibility == VISIBILITY_INVALID) { + visibility = VISIBLE; + mViewFlags &= ~FLAG_INVISIBLE; + mViewFlags |= visibility; + } + + return visibility; } // This should only be called on the content pane (the topmost GLView). @@ -979,6 +1013,9 @@ public class GLView implements TouchOwner { public static void measureAllComponents(GLView parent, int widthSpec, int heightSpec) { for (int i = 0, n = parent.getComponentCount(); i < n; i++) { GLView component = parent.getComponent(i); + if (component.getVisibility() == GONE) { + continue; + } measureComponent(component, widthSpec, heightSpec); } } @@ -1030,12 +1067,9 @@ public class GLView implements TouchOwner { return true; } - protected void onVisibilityChanged(int visibility) { + protected void onVisibilityChanged(GLView changedView, @Visibility int visibility) { for (int i = 0, n = getComponentCount(); i < n; ++i) { - GLView child = getComponent(i); - if (child.getVisibility() == GLView.VISIBLE) { - child.onVisibilityChanged(visibility); - } + getComponent(i).onVisibilityChanged(changedView, visibility); } } diff --git a/app/src/main/java/com/hippo/gl/widget/GLFrameLayout.java b/app/src/main/java/com/hippo/gl/widget/GLFrameLayout.java index 202cdfa04..f37584292 100644 --- a/app/src/main/java/com/hippo/gl/widget/GLFrameLayout.java +++ b/app/src/main/java/com/hippo/gl/widget/GLFrameLayout.java @@ -27,6 +27,9 @@ public class GLFrameLayout extends GLView { int maxHeight = 0; for (int i = 0, n = getComponentCount(); i < n; i++) { GLView component = getComponent(i); + if (component.getVisibility() == GONE) { + continue; + } measureComponent(component, widthSpec, heightSpec); maxWidth = Math.max(maxWidth, component.getMeasuredWidth()); maxHeight = Math.max(maxHeight, component.getMeasuredHeight()); @@ -57,6 +60,9 @@ public class GLFrameLayout extends GLView { for (int i = 0, n = getComponentCount(); i < n; i++) { GLView component = getComponent(i); + if (component.getVisibility() == GONE) { + continue; + } int measureWidth = component.getMeasuredWidth(); int measureHeight = component.getMeasuredHeight(); int componentLeft; diff --git a/app/src/main/java/com/hippo/gl/widget/GLLinearLayout.java b/app/src/main/java/com/hippo/gl/widget/GLLinearLayout.java index d3920c7ca..73f8c3164 100644 --- a/app/src/main/java/com/hippo/gl/widget/GLLinearLayout.java +++ b/app/src/main/java/com/hippo/gl/widget/GLLinearLayout.java @@ -73,6 +73,9 @@ public class GLLinearLayout extends GLView { for (int i = 0, n = getComponentCount(); i < n; i++) { final GLView component = getComponent(i); + if (component.getVisibility() == GONE) { + continue; + } final LayoutParams lp = (LayoutParams) component.getLayoutParams(); if (lp.weight > 0.0f) { @@ -99,6 +102,9 @@ public class GLLinearLayout extends GLView { for (int i = 0, n = getComponentCount(); i < n; i++) { final GLView component = getComponent(i); + if (component.getVisibility() == GONE) { + continue; + } final LayoutParams lp = (LayoutParams) component.getLayoutParams(); if (lp.weight > 0.0f) { @@ -127,6 +133,9 @@ public class GLLinearLayout extends GLView { int maxHeight = 0; for (int i = 0, n = getComponentCount(); i < n; i++) { GLView component = getComponent(i); + if (component.getVisibility() == GONE) { + continue; + } if (mOrientation == VERTICAL) { maxWidth = Math.max(maxWidth, component.getMeasuredWidth()); @@ -163,6 +172,9 @@ public class GLLinearLayout extends GLView { for (int i = 0, n = getComponentCount(); i < n; i++) { GLView component = getComponent(i); + if (component.getVisibility() == GONE) { + continue; + } int measureWidth = component.getMeasuredWidth(); int measureHeight = component.getMeasuredHeight(); @@ -179,6 +191,9 @@ public class GLLinearLayout extends GLView { for (int i = 0, n = getComponentCount(); i < n; i++) { GLView component = getComponent(i); + if (component.getVisibility() == GONE) { + continue; + } int measureWidth = component.getMeasuredWidth(); int measureHeight = component.getMeasuredHeight(); diff --git a/app/src/main/java/com/hippo/gl/widget/GLTextView.java b/app/src/main/java/com/hippo/gl/widget/GLMovableTextView.java similarity index 93% rename from app/src/main/java/com/hippo/gl/widget/GLTextView.java rename to app/src/main/java/com/hippo/gl/widget/GLMovableTextView.java index 70addee1f..fd3004975 100644 --- a/app/src/main/java/com/hippo/gl/widget/GLTextView.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.TextTexture; +import com.hippo.gl.glrenderer.MovableTextTexture; import com.hippo.gl.view.GLView; import com.hippo.gl.view.Gravity; import com.hippo.yorozuya.ArrayUtils; -public class GLTextView extends GLView { +public class GLMovableTextView extends GLView { - TextTexture mTextTexture; + MovableTextTexture mTextTexture; private String mText = ""; private int[] mIndexes = ArrayUtils.EMPTY_INT_ARRAY; @@ -42,7 +42,7 @@ public class GLTextView extends GLView { } } - public void setTextTexture(TextTexture textTexture) { + public void setTextTexture(MovableTextTexture textTexture) { if (mTextTexture == textTexture) { return; }