Add animated image support
This commit is contained in:
1 parent
c32ffb8bbb
commit
41a383c1ac
7 files changed
+324
-129
No files matched your search
@@ -148,7 +148,7 @@ public class DirGalleryProvider extends GalleryProvider implements Runnable {
|
||||
|
||||
try {
|
||||
InputStream is = new FileInputStream(new File(mDir, files[index]));
|
||||
Image image = Image.decode(is, false);
|
||||
Image image = Image.decode(is, true);
|
||||
mDecodingIndex.lazySet(GalleryPageView.INVALID_INDEX);
|
||||
if (image != null) {
|
||||
notifyPageSucceed(index, image);
|
||||
|
||||
@@ -175,7 +175,7 @@ public class ZipGalleryProvider extends GalleryProvider implements Runnable {
|
||||
ZipEntry zipEntry = zipFile.getEntry(filenames.get(index));
|
||||
if (zipEntry != null) {
|
||||
InputStream is = zipFile.getInputStream(zipEntry);
|
||||
Image image = Image.decode(is, false);
|
||||
Image image = Image.decode(is, true);
|
||||
mDecodingIndex.lazySet(GalleryPageView.INVALID_INDEX);
|
||||
if (image != null) {
|
||||
notifyPageSucceed(index, image);
|
||||
|
||||
@@ -126,19 +126,17 @@ public class GalleryPageView extends GLFrameLayout {
|
||||
}
|
||||
|
||||
private void unbindImage() {
|
||||
Texture texture = mImage.getTexture();
|
||||
ImageTexture texture = mImage.getImageTexture();
|
||||
if (texture != null) {
|
||||
mImage.setTexture(null);
|
||||
if (texture instanceof ImageTexture) {
|
||||
((ImageTexture) texture).recycle();
|
||||
}
|
||||
mImage.setImageTexture(null);
|
||||
texture.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
public void setImage(ImageTexture imageTexture) {
|
||||
unbindImage();
|
||||
if (imageTexture != null) {
|
||||
mImage.setTexture(imageTexture);
|
||||
mImage.setImageTexture(imageTexture);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.support.annotation.IntDef;
|
||||
|
||||
import com.hippo.gl.anim.AlphaAnimation;
|
||||
import com.hippo.gl.glrenderer.GLCanvas;
|
||||
import com.hippo.gl.glrenderer.ImageTexture;
|
||||
import com.hippo.gl.glrenderer.Texture;
|
||||
import com.hippo.gl.view.GLView;
|
||||
import com.hippo.yorozuya.AnimationUtils;
|
||||
@@ -31,7 +32,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ImageView extends GLView {
|
||||
public class ImageView extends GLView implements ImageTexture.Callback {
|
||||
|
||||
@IntDef({SCALE_ORIGIN, SCALE_FIT_WIDTH, SCALE_FIT_HEIGHT, SCALE_FIT, SCALE_FIXED})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@@ -60,7 +61,7 @@ public class ImageView extends GLView {
|
||||
|
||||
private static final long ALPHA_ANIMATION_DURING = 300L;
|
||||
|
||||
private Texture mTexture;
|
||||
private ImageTexture mImageTexture;
|
||||
private int mTextureWidth;
|
||||
private int mTextureHeight;
|
||||
|
||||
@@ -115,18 +116,18 @@ public class ImageView extends GLView {
|
||||
@Override
|
||||
protected int getSuggestedMinimumWidth() {
|
||||
return Math.max(super.getSuggestedMinimumWidth(),
|
||||
mTexture == null ? 0 : mTextureWidth);
|
||||
mImageTexture == null ? 0 : mTextureWidth);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSuggestedMinimumHeight() {
|
||||
return Math.max(super.getSuggestedMinimumHeight(),
|
||||
mTexture == null ? 0 : mTextureHeight);
|
||||
mImageTexture == null ? 0 : mTextureHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthSpec, int heightSpec) {
|
||||
if (mTexture == null) {
|
||||
if (mImageTexture == null) {
|
||||
super.onMeasure(widthSpec, heightSpec);
|
||||
} else {
|
||||
float ratio = (float) mTextureWidth / mTextureHeight;
|
||||
@@ -172,10 +173,19 @@ public class ImageView extends GLView {
|
||||
@Override
|
||||
protected void onPositionInRootChanged(int x, int y, int oldX, int oldY) {
|
||||
mPositionInRootDirty = true;
|
||||
|
||||
if (mImageTexture != null) {
|
||||
getValidRect(mValidRect);
|
||||
if (!mValidRect.isEmpty()) {
|
||||
mImageTexture.start();
|
||||
} else {
|
||||
mImageTexture.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void getScaleDefault(float[] scaleDefault) {
|
||||
if (mTexture == null) {
|
||||
if (mImageTexture == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -192,12 +202,18 @@ public class ImageView extends GLView {
|
||||
Arrays.sort(scaleDefault);
|
||||
}
|
||||
|
||||
public void setTexture(Texture texture) {
|
||||
mTexture = texture;
|
||||
public void setImageTexture(ImageTexture imageTexture) {
|
||||
// Remove callback
|
||||
if (mImageTexture != null) {
|
||||
mImageTexture.setCallback(null);
|
||||
}
|
||||
|
||||
if (texture != null) {
|
||||
mTextureWidth = texture.getWidth();
|
||||
mTextureHeight = texture.getHeight();
|
||||
mImageTexture = imageTexture;
|
||||
|
||||
if (imageTexture != null) {
|
||||
imageTexture.setCallback(this);
|
||||
mTextureWidth = imageTexture.getWidth();
|
||||
mTextureHeight = imageTexture.getHeight();
|
||||
// Avoid zero and negative
|
||||
if (mTextureWidth <= 0) {
|
||||
mTextureWidth = 1;
|
||||
@@ -219,12 +235,12 @@ public class ImageView extends GLView {
|
||||
mPositionInRootDirty = true;
|
||||
}
|
||||
|
||||
public Texture getTexture() {
|
||||
return mTexture;
|
||||
public ImageTexture getImageTexture() {
|
||||
return mImageTexture;
|
||||
}
|
||||
|
||||
public boolean isLoaded() {
|
||||
return mTexture != null;
|
||||
return mImageTexture != null;
|
||||
}
|
||||
|
||||
public boolean canFlingVertically() {
|
||||
@@ -351,7 +367,7 @@ public class ImageView extends GLView {
|
||||
int screenWidth = getWidth();
|
||||
int screenHeight = getHeight();
|
||||
|
||||
if (mTexture == null || screenWidth == 0 || screenHeight == 0) {
|
||||
if (mImageTexture == null || screenWidth == 0 || screenHeight == 0) {
|
||||
mScaleOffsetDirty = true;
|
||||
return;
|
||||
}
|
||||
@@ -530,8 +546,8 @@ public class ImageView extends GLView {
|
||||
float left = (focusX - ((focusX - dst.left) * scale));
|
||||
float top = (focusY - ((focusY - dst.top) * scale));
|
||||
dst.set(left, top,
|
||||
(left + (mTexture.getWidth() * newScale)),
|
||||
(top + (mTexture.getHeight() * newScale)));
|
||||
(left + (mImageTexture.getWidth() * newScale)),
|
||||
(top + (mImageTexture.getHeight() * newScale)));
|
||||
|
||||
// adjust position
|
||||
adjustPosition();
|
||||
@@ -541,8 +557,8 @@ public class ImageView extends GLView {
|
||||
}
|
||||
|
||||
private void applyPositionInRoot() {
|
||||
int width = mTexture.getWidth();
|
||||
int height = mTexture.getHeight();
|
||||
int width = mImageTexture.getWidth();
|
||||
int height = mImageTexture.getHeight();
|
||||
RectF dst = mDst;
|
||||
RectF dstActual = mDstActual;
|
||||
RectF srcActual = mSrcActual;
|
||||
@@ -569,7 +585,7 @@ public class ImageView extends GLView {
|
||||
|
||||
@Override
|
||||
public void onRender(GLCanvas canvas) {
|
||||
Texture texture = mTexture;
|
||||
Texture texture = mImageTexture;
|
||||
if (texture == null) {
|
||||
return;
|
||||
}
|
||||
@@ -586,4 +602,9 @@ public class ImageView extends GLView {
|
||||
texture.draw(canvas, mSrcActual, mDstActual);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateImageTexture(ImageTexture who) {
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
@@ -1176,6 +1176,7 @@ public class SpiderQueen implements Runnable {
|
||||
|
||||
try {
|
||||
pipe.obtain();
|
||||
// TODO how to keep stream open
|
||||
Image image = Image.decode(pipe.open(), false);
|
||||
if (image != null) {
|
||||
mDecodingIndex.lazySet(GalleryPageView.INVALID_INDEX);
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.hippo.gl.glrenderer;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.NonNull;
|
||||
@@ -26,17 +27,18 @@ import android.support.annotation.NonNull;
|
||||
import com.hippo.gl.annotation.RenderThread;
|
||||
import com.hippo.gl.view.GLRoot;
|
||||
import com.hippo.image.Image;
|
||||
import com.hippo.yorozuya.InfiniteThreadExecutor;
|
||||
import com.hippo.yorozuya.PVLock;
|
||||
import com.hippo.yorozuya.PriorityThreadFactory;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class ImageTexture implements Texture {
|
||||
public class ImageTexture implements Texture, Animatable {
|
||||
|
||||
@IntDef({TILE_SMALL, TILE_LARGE})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@@ -61,7 +63,7 @@ public class ImageTexture implements Texture {
|
||||
|
||||
private static final Bitmap sSmallUploadBitmap;
|
||||
private static final Bitmap sLargeUploadBitmap;
|
||||
private static final InfiniteThreadExecutor sThreadExecutor;
|
||||
private static final PriorityThreadFactory sThreadFactory;
|
||||
private static final PVLock sPVLock;
|
||||
|
||||
private static Tile sSmallFreeTileHead = null;
|
||||
@@ -79,15 +81,18 @@ public class ImageTexture implements Texture {
|
||||
private final RectF mSrcRect = new RectF();
|
||||
private final RectF mDestRect = new RectF();
|
||||
|
||||
private volatile boolean mFrameDirty = false;
|
||||
private final AtomicBoolean mFrameDirty = new AtomicBoolean();
|
||||
private boolean mImageBusy = false;
|
||||
private final AtomicBoolean mNeedRecycle = new AtomicBoolean();
|
||||
|
||||
private final AtomicReference<Thread> mAnimateThread = new AtomicReference<>();
|
||||
|
||||
private WeakReference<Callback> mCallback;
|
||||
|
||||
static {
|
||||
sSmallUploadBitmap = Bitmap.createBitmap(SMALL_TILE_SIZE, SMALL_TILE_SIZE, Bitmap.Config.ARGB_8888);
|
||||
sLargeUploadBitmap = Bitmap.createBitmap(LARGE_TILE_SIZE, LARGE_TILE_SIZE, Bitmap.Config.ARGB_8888);
|
||||
sThreadExecutor = new InfiniteThreadExecutor(3000, new LinkedBlockingQueue<Runnable>(),
|
||||
new PriorityThreadFactory(ImageTexture.class.getSimpleName(),
|
||||
android.os.Process.THREAD_PRIORITY_BACKGROUND));
|
||||
sThreadFactory = new PriorityThreadFactory("ImageTexture$AnimateTask", android.os.Process.THREAD_PRIORITY_BACKGROUND);
|
||||
sPVLock = new PVLock(3);
|
||||
}
|
||||
|
||||
@@ -177,31 +182,29 @@ public class ImageTexture implements Texture {
|
||||
protected Bitmap onGetBitmap() {
|
||||
final Image image = this.image;
|
||||
if (image != null) {
|
||||
synchronized (image) {
|
||||
int srcX;
|
||||
int dstX;
|
||||
if (offsetX - borderSize < 0) {
|
||||
srcX = 0;
|
||||
dstX = borderSize - offsetX;
|
||||
} else {
|
||||
srcX = offsetX - borderSize;
|
||||
dstX = 0;
|
||||
}
|
||||
int srcY;
|
||||
int dstY;
|
||||
if (offsetY - borderSize < 0) {
|
||||
srcY = 0;
|
||||
dstY = borderSize - offsetY;
|
||||
} else {
|
||||
srcY = offsetY - borderSize;
|
||||
dstY = 0;
|
||||
}
|
||||
|
||||
image.render(srcX, srcY, uploadBitmap, dstX, dstY,
|
||||
Math.min(image.getWidth() - srcX, tileSize - dstX),
|
||||
Math.min(image.getHeight() - srcY, tileSize - dstY),
|
||||
true, Color.TRANSPARENT);
|
||||
int srcX;
|
||||
int dstX;
|
||||
if (offsetX - borderSize < 0) {
|
||||
srcX = 0;
|
||||
dstX = borderSize - offsetX;
|
||||
} else {
|
||||
srcX = offsetX - borderSize;
|
||||
dstX = 0;
|
||||
}
|
||||
int srcY;
|
||||
int dstY;
|
||||
if (offsetY - borderSize < 0) {
|
||||
srcY = 0;
|
||||
dstY = borderSize - offsetY;
|
||||
} else {
|
||||
srcY = offsetY - borderSize;
|
||||
dstY = 0;
|
||||
}
|
||||
|
||||
image.render(srcX, srcY, uploadBitmap, dstX, dstY,
|
||||
Math.min(image.getWidth() - srcX, tileSize - dstX),
|
||||
Math.min(image.getHeight() - srcY, tileSize - dstY),
|
||||
true, Color.TRANSPARENT);
|
||||
}
|
||||
return uploadBitmap;
|
||||
}
|
||||
@@ -216,24 +219,12 @@ public class ImageTexture implements Texture {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void invalidateInternal() {
|
||||
private void invalidate() {
|
||||
invalidateContent();
|
||||
image = null;
|
||||
uploadBitmap = null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
|
||||
public void invalidate() {
|
||||
final Image image = this.image;
|
||||
if (image != null) {
|
||||
synchronized (image) {
|
||||
invalidateInternal();
|
||||
}
|
||||
} else {
|
||||
invalidateInternal();
|
||||
}
|
||||
}
|
||||
|
||||
public void free() {
|
||||
switch (mTileType) {
|
||||
case TILE_SMALL:
|
||||
@@ -290,6 +281,131 @@ public class ImageTexture implements Texture {
|
||||
}
|
||||
}
|
||||
|
||||
private class AnimateRunnable implements Runnable {
|
||||
|
||||
public void doRun() {
|
||||
long lastTime = SystemClock.currentThreadTimeMillis();
|
||||
|
||||
synchronized (mImage) {
|
||||
// Check recycled
|
||||
if (mImage.isRecycled()) {
|
||||
return;
|
||||
}
|
||||
// Check image busy
|
||||
if (mImageBusy) {
|
||||
// Image is busy, means it is recycling
|
||||
return;
|
||||
}
|
||||
if (mNeedRecycle.get()) {
|
||||
// Need recycle
|
||||
return;
|
||||
}
|
||||
// Obtain image
|
||||
mImageBusy = true;
|
||||
}
|
||||
|
||||
boolean interrupted = Thread.currentThread().isInterrupted();
|
||||
|
||||
if (!mImage.isCompleted()) {
|
||||
if (!interrupted) {
|
||||
try {
|
||||
sPVLock.p();
|
||||
} catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
}
|
||||
if (!interrupted && !mNeedRecycle.get()) {
|
||||
mImage.complete();
|
||||
}
|
||||
sPVLock.v();
|
||||
}
|
||||
}
|
||||
|
||||
int frameCount = mImage.getFrameCount();
|
||||
|
||||
synchronized (mImage) {
|
||||
// Release image
|
||||
mImageBusy = false;
|
||||
}
|
||||
|
||||
if (interrupted || mNeedRecycle.get() || frameCount < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
// Obtain
|
||||
synchronized (mImage) {
|
||||
// Check recycled
|
||||
if (mImage.isRecycled()) {
|
||||
return;
|
||||
}
|
||||
// Check image busy
|
||||
if (mImageBusy) {
|
||||
// Image is busy, means it is recycling
|
||||
return;
|
||||
}
|
||||
if (mNeedRecycle.get()) {
|
||||
// Need recycle
|
||||
return;
|
||||
}
|
||||
// Obtain image
|
||||
mImageBusy = true;
|
||||
}
|
||||
|
||||
mImage.advance();
|
||||
long delay = mImage.getDelay();
|
||||
long time = System.currentTimeMillis();
|
||||
delay -= time - lastTime;
|
||||
lastTime = time;
|
||||
mFrameDirty.lazySet(true);
|
||||
invalidateSelf();
|
||||
|
||||
synchronized (mImage) {
|
||||
// Release image
|
||||
mImageBusy = false;
|
||||
}
|
||||
|
||||
if (delay > 0) {
|
||||
try {
|
||||
Thread.sleep(delay);
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
doRun();
|
||||
|
||||
while (mNeedRecycle.get()) {
|
||||
// Obtain
|
||||
synchronized (mImage) {
|
||||
// Check recycled
|
||||
if (mImage.isRecycled()) {
|
||||
break;
|
||||
}
|
||||
// Check image busy
|
||||
if (mImageBusy) {
|
||||
// Image is busy, means it is recycling
|
||||
break;
|
||||
}
|
||||
// Obtain image
|
||||
mImageBusy = true;
|
||||
}
|
||||
|
||||
mImage.recycle();
|
||||
|
||||
synchronized (mImage) {
|
||||
// Release image
|
||||
mImageBusy = false;
|
||||
}
|
||||
}
|
||||
|
||||
mAnimateThread.lazySet(null);
|
||||
}
|
||||
}
|
||||
|
||||
public ImageTexture(@NonNull Image image) {
|
||||
mImage = image;
|
||||
int width = mWidth = image.getWidth();
|
||||
@@ -354,13 +470,61 @@ public class ImageTexture implements Texture {
|
||||
|
||||
mTiles = list.toArray(new Tile[list.size()]);
|
||||
|
||||
/*
|
||||
if (image instanceof AnimatedImage) {
|
||||
sThreadExecutor.execute(new DecodeTask());
|
||||
if (!mImage.isCompleted() || mImage.getFrameCount() >= 1) {
|
||||
Thread thread = sThreadFactory.newThread(new AnimateRunnable());
|
||||
mAnimateThread.lazySet(thread);
|
||||
thread.start();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
public final void setCallback(Callback cb) {
|
||||
mCallback = new WeakReference<>(cb);
|
||||
}
|
||||
|
||||
public Callback getCallback() {
|
||||
if (mCallback != null) {
|
||||
return mCallback.get();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void invalidateSelf() {
|
||||
final Callback callback = getCallback();
|
||||
if (callback != null) {
|
||||
callback.invalidateImageTexture(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (mImage.isRecycled() || (mImage.isCompleted() && mImage.getFrameCount() < 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Thread thread = mAnimateThread.get();
|
||||
if (thread == null) {
|
||||
thread = sThreadFactory.newThread(new AnimateRunnable());
|
||||
mAnimateThread.set(thread);
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
if (!mImage.isRecycled() && (mImage.isCompleted() && mImage.getFrameCount() >= 1)) {
|
||||
Thread thread = mAnimateThread.getAndSet(null);
|
||||
if (null != thread) {
|
||||
thread.interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private boolean uploadNextTile(GLCanvas canvas) {
|
||||
if (mUploadIndex == mTiles.length) return true;
|
||||
|
||||
@@ -417,12 +581,9 @@ public class ImageTexture implements Texture {
|
||||
|
||||
@RenderThread
|
||||
private void syncFrame() {
|
||||
if (mFrameDirty) {
|
||||
mFrameDirty = false;
|
||||
|
||||
if (mFrameDirty.getAndSet(false)) {
|
||||
// invalid tiles
|
||||
for (int i = 0, n = mTiles.length; i < n; i++) {
|
||||
Tile tile = mTiles[i];
|
||||
for (Tile tile : mTiles) {
|
||||
int width = tile.mWidth;
|
||||
int height = tile.mHeight;
|
||||
tile.invalidateContent();
|
||||
@@ -445,16 +606,13 @@ public class ImageTexture implements Texture {
|
||||
float scaleX = (float) w / mWidth;
|
||||
float scaleY = (float) h / mHeight;
|
||||
|
||||
synchronized (mImage) {
|
||||
syncFrame();
|
||||
for (int i = 0, n = mTiles.length; i < n; ++i) {
|
||||
Tile t = mTiles[i];
|
||||
src.set(0, 0, t.contentWidth, t.contentHeight);
|
||||
src.offset(t.offsetX, t.offsetY);
|
||||
mapRect(dest, src, 0, 0, x, y, scaleX, scaleY);
|
||||
src.offset(t.borderSize - t.offsetX, t.borderSize - t.offsetY);
|
||||
canvas.drawTexture(t, src, dest);
|
||||
}
|
||||
syncFrame();
|
||||
for (Tile t : mTiles) {
|
||||
src.set(0, 0, t.contentWidth, t.contentHeight);
|
||||
src.offset(t.offsetX, t.offsetY);
|
||||
mapRect(dest, src, 0, 0, x, y, scaleX, scaleY);
|
||||
src.offset(t.borderSize - t.offsetX, t.borderSize - t.offsetY);
|
||||
canvas.drawTexture(t, src, dest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -470,19 +628,16 @@ public class ImageTexture implements Texture {
|
||||
float scaleX = target.width() / source.width();
|
||||
float scaleY = target.height() / source.height();
|
||||
|
||||
synchronized (mImage) {
|
||||
syncFrame();
|
||||
for (int i = 0, n = mTiles.length; i < n; ++i) {
|
||||
Tile t = mTiles[i];
|
||||
src.set(0, 0, t.contentWidth, t.contentHeight);
|
||||
src.offset(t.offsetX, t.offsetY);
|
||||
if (!src.intersect(source)) {
|
||||
continue;
|
||||
}
|
||||
mapRect(dest, src, x0, y0, x, y, scaleX, scaleY);
|
||||
src.offset(t.borderSize - t.offsetX, t.borderSize - t.offsetY);
|
||||
canvas.drawTexture(t, src, dest);
|
||||
syncFrame();
|
||||
for (Tile t : mTiles) {
|
||||
src.set(0, 0, t.contentWidth, t.contentHeight);
|
||||
src.offset(t.offsetX, t.offsetY);
|
||||
if (!src.intersect(source)) {
|
||||
continue;
|
||||
}
|
||||
mapRect(dest, src, x0, y0, x, y, scaleX, scaleY);
|
||||
src.offset(t.borderSize - t.offsetX, t.borderSize - t.offsetY);
|
||||
canvas.drawTexture(t, src, dest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,16 +650,13 @@ public class ImageTexture implements Texture {
|
||||
float scaleX = (float) width / mWidth;
|
||||
float scaleY = (float) height / mHeight;
|
||||
|
||||
synchronized (mImage) {
|
||||
syncFrame();
|
||||
for (int i = 0, n = mTiles.length; i < n; ++i) {
|
||||
Tile t = mTiles[i];
|
||||
src.set(0, 0, t.contentWidth, t.contentHeight);
|
||||
src.offset(t.offsetX, t.offsetY);
|
||||
mapRect(dest, src, 0, 0, x, y, scaleX, scaleY);
|
||||
src.offset(t.borderSize - t.offsetX, t.borderSize - t.offsetY);
|
||||
canvas.drawMixed(t, color, ratio, src, dest);
|
||||
}
|
||||
syncFrame();
|
||||
for (Tile t : mTiles) {
|
||||
src.set(0, 0, t.contentWidth, t.contentHeight);
|
||||
src.offset(t.offsetX, t.offsetY);
|
||||
mapRect(dest, src, 0, 0, x, y, scaleX, scaleY);
|
||||
src.offset(t.borderSize - t.offsetX, t.borderSize - t.offsetY);
|
||||
canvas.drawMixed(t, color, ratio, src, dest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,19 +671,16 @@ public class ImageTexture implements Texture {
|
||||
float scaleX = target.width() / source.width();
|
||||
float scaleY = target.height() / source.height();
|
||||
|
||||
synchronized (mImage) {
|
||||
syncFrame();
|
||||
for (int i = 0, n = mTiles.length; i < n; ++i) {
|
||||
Tile t = mTiles[i];
|
||||
src.set(0, 0, t.contentWidth, t.contentHeight);
|
||||
src.offset(t.offsetX, t.offsetY);
|
||||
if (!src.intersect(source)) {
|
||||
continue;
|
||||
}
|
||||
mapRect(dest, src, x0, y0, x, y, scaleX, scaleY);
|
||||
src.offset(t.borderSize - t.offsetX, t.borderSize - t.offsetY);
|
||||
canvas.drawMixed(t, color, ratio, src, dest);
|
||||
syncFrame();
|
||||
for (Tile t : mTiles) {
|
||||
src.set(0, 0, t.contentWidth, t.contentHeight);
|
||||
src.offset(t.offsetX, t.offsetY);
|
||||
if (!src.intersect(source)) {
|
||||
continue;
|
||||
}
|
||||
mapRect(dest, src, x0, y0, x, y, scaleX, scaleY);
|
||||
src.offset(t.borderSize - t.offsetX, t.borderSize - t.offsetY);
|
||||
canvas.drawMixed(t, color, ratio, src, dest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,11 +694,37 @@ public class ImageTexture implements Texture {
|
||||
}
|
||||
|
||||
public void recycle() {
|
||||
for (int i = 0, n = mTiles.length; i < n; ++i) {
|
||||
mTiles[i].free();
|
||||
for (Tile mTile : mTiles) {
|
||||
mTile.free();
|
||||
}
|
||||
|
||||
boolean recycleNow;
|
||||
|
||||
synchronized (mImage) {
|
||||
if (!mImageBusy) {
|
||||
recycleNow = true;
|
||||
mImageBusy = true;
|
||||
} else {
|
||||
recycleNow = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (recycleNow) {
|
||||
mImage.recycle();
|
||||
synchronized (mImage) {
|
||||
mImageBusy = false;
|
||||
}
|
||||
} else {
|
||||
mNeedRecycle.set(true);
|
||||
}
|
||||
|
||||
Thread thread = mAnimateThread.getAndSet(null);
|
||||
if (null != thread) {
|
||||
thread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
public interface Callback {
|
||||
void invalidateImageTexture(ImageTexture who);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user