package master.flame.danmaku.danmaku.model.android; import android.annotation.SuppressLint; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import tv.cjump.jni.NativeBitmapFactory; public class DrawingCacheHolder { public Canvas canvas; public Bitmap bitmap; public Bitmap[][] bitmapArray; public Object extra; public int width; public int height; public boolean drawn; private int mDensity; public DrawingCacheHolder() { } public DrawingCacheHolder(int w, int h) { buildCache(w, h, 0, true); } public DrawingCacheHolder(int w, int h, int density) { mDensity = density; buildCache(w, h, density, true); } public void buildCache(int w, int h, int density, boolean checkSizeEquals) { boolean reuse = checkSizeEquals ? (w == width && h == height) : (w <= width && h <= height); if (reuse && bitmap != null && !bitmap.isRecycled()) { // canvas.drawColor(Color.TRANSPARENT); canvas.setBitmap(null); bitmap.eraseColor(Color.TRANSPARENT); canvas.setBitmap(bitmap); recycleBitmapArray(); return; } if (bitmap != null) { recycle(); } width = w; height = h; bitmap = NativeBitmapFactory.createBitmap(w, h, Bitmap.Config.ARGB_8888); if (density > 0) { mDensity = density; bitmap.setDensity(density); } if (canvas == null){ canvas = new Canvas(bitmap); canvas.setDensity(density); }else canvas.setBitmap(bitmap); } public void erase() { eraseBitmap(bitmap); eraseBitmapArray(); } public void recycle() { width = height = 0; // if (canvas != null) { // canvas = null; // } if (bitmap != null) { bitmap.recycle(); bitmap = null; } recycleBitmapArray(); extra = null; } @SuppressLint("NewApi") public void splitWith(int dispWidth, int dispHeight, int maximumCacheWidth, int maximumCacheHeight) { recycleBitmapArray(); if (width <= 0 || height <= 0 || bitmap == null || bitmap.isRecycled()) { return; } if (width <= maximumCacheWidth && height <= maximumCacheHeight) { return; } maximumCacheWidth = Math.min(maximumCacheWidth, dispWidth); maximumCacheHeight = Math.min(maximumCacheHeight, dispHeight); int xCount = width / maximumCacheWidth + (width % maximumCacheWidth == 0 ? 0 : 1); int yCount = height / maximumCacheHeight + (height % maximumCacheHeight == 0 ? 0 : 1); int averageWidth = width / xCount; int averageHeight = height / yCount; final Bitmap[][] bmpArray = new Bitmap[yCount][xCount]; if (canvas == null){ canvas = new Canvas(); if (mDensity > 0) { canvas.setDensity(mDensity); } } Rect rectSrc = new Rect(); Rect rectDst = new Rect(); for (int yIndex = 0; yIndex < yCount; yIndex++) { for (int xIndex = 0; xIndex < xCount; xIndex++) { Bitmap bmp = bmpArray[yIndex][xIndex] = NativeBitmapFactory.createBitmap( averageWidth, averageHeight, Bitmap.Config.ARGB_8888); if (mDensity > 0) { bmp.setDensity(mDensity); } canvas.setBitmap(bmp); int left = xIndex * averageWidth, top = yIndex * averageHeight; rectSrc.set(left, top, left + averageWidth, top + averageHeight); rectDst.set(0, 0, bmp.getWidth(), bmp.getHeight()); canvas.drawBitmap(bitmap, rectSrc, rectDst, null); } } canvas.setBitmap(bitmap); bitmapArray = bmpArray; } private void eraseBitmap(Bitmap bmp) { if (bmp != null && !bmp.isRecycled()) { bmp.eraseColor(Color.TRANSPARENT); } } private void eraseBitmapArray() { if (bitmapArray != null) { for (int i = 0; i < bitmapArray.length; i++) { for (int j = 0; j < bitmapArray[i].length; j++) { eraseBitmap(bitmapArray[i][j]); } } } } private void recycleBitmapArray() { if (bitmapArray != null) { for (int i = 0; i < bitmapArray.length; i++) { for (int j = 0; j < bitmapArray[i].length; j++) { if (bitmapArray[i][j] != null) { bitmapArray[i][j].recycle(); bitmapArray[i][j] = null; } } } bitmapArray = null; } } public final boolean draw(Canvas canvas, float left, float top, Paint paint) { if (bitmapArray != null) { for (int i = 0; i < bitmapArray.length; i++) { for (int j = 0; j < bitmapArray[i].length; j++) { Bitmap bmp = bitmapArray[i][j]; if (bmp != null && !bmp.isRecycled()) { float dleft = left + j * bmp.getWidth(); if (dleft > canvas.getWidth() || dleft + bmp.getWidth() < 0) { continue; } float dtop = top + i * bmp.getHeight(); if (dtop > canvas.getHeight() || dtop + bmp.getHeight() < 0) { continue; } canvas.drawBitmap(bmp, dleft, dtop, paint); } } } return true; } else if (bitmap != null && !bitmap.isRecycled()) { canvas.drawBitmap(bitmap, left, top, paint); return true; } return false; } }