/*
* Copyright (C) 2016 Google Inc. All Rights Reserved.
*
* 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.google.android.apps.santatracker.games.simpleengine;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.WindowManager;
import java.util.ArrayList;
class BitmapTextureMaker implements Runnable {
private boolean mStartedLoading = false;
private boolean mFinishedLoading = false;
static final int DIM_WIDTH = 0;
static final int DIM_HEIGHT = 1;
private Context mContext = null;
private int mScreenWidth = 0;
private int mScreenHeight = 0;
private ArrayList<BitmapEntry> mEntries = new ArrayList<BitmapEntry>();
BitmapTextureMaker() {
}
public void request(int tag, int resId, String name, int dimType, float maxDim) {
if (mStartedLoading) {
Logger.e("Can't request a new bitmap after loading has started.");
return;
}
BitmapEntry e = new BitmapEntry();
e.tag = tag;
e.resId = resId;
e.dimType = dimType;
e.maxDim = maxDim;
e.name = name;
mEntries.add(e);
Logger.d("Bitmap requested: " + e.toString() + ", #" + (mEntries.size() - 1));
}
public void startLoading(Context ctx) {
mStartedLoading = true;
mContext = ctx.getApplicationContext();
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mScreenWidth = wm.getDefaultDisplay().getWidth();
mScreenHeight = wm.getDefaultDisplay().getHeight();
Logger.d("Starting async load of bitmaps. Screen dimensions " + mScreenWidth + "screenX" +
mScreenHeight);
Thread t = new Thread(this);
t.start();
}
class BitmapEntry {
int tag;
int dimType;
float maxDim;
int resId;
Bitmap bitmap = null;
String name = "";
@Override
public String toString() {
return "[BitmapEntry name=" + name + ", " +
((dimType == DIM_HEIGHT) ? "maxH=" : "maxW=") + maxDim +
", resId=" + resId + ", bitmap=" + (bitmap == null ? "(null)" : "loaded!" +
"]");
}
}
@Override
public void run() {
for (BitmapEntry e : mEntries) {
loadBitmapEntry(e);
}
mContext = null;
mFinishedLoading = true;
Logger.d("Finished loading bitmaps.");
}
void loadBitmapEntry(BitmapEntry e) {
Logger.d("Loading bitmap entry " + e.toString());
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(mContext.getResources(), e.resId, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
float imageAspect = imageWidth / (float) imageHeight;
float screenUnit = (float) mScreenHeight;
Logger.d(e.name + " dimensions " + imageWidth + "screenX" + imageHeight);
int reqWidth = 0, reqHeight = 0;
if (e.dimType == DIM_HEIGHT) {
reqHeight = (int) (e.maxDim * screenUnit);
reqWidth = (int) (imageAspect * reqHeight);
} else if (e.dimType == DIM_WIDTH) {
reqWidth = (int) (e.maxDim * screenUnit);
reqHeight = (int) (reqWidth / imageAspect);
}
Logger.d(e.name + " requested dimensions " + reqWidth + "screenX" + reqHeight);
int inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
Logger.d(e.name + " in sample size " + inSampleSize);
options.inSampleSize = inSampleSize;
options.inJustDecodeBounds = false;
e.bitmap = BitmapFactory.decodeResource(mContext.getResources(), e.resId, options);
Logger.d("Loaded bitmap for " + e.name + ", " + e.bitmap.getWidth() + "x" +
e.bitmap.getHeight());
}
// From http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
private static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
public boolean isFinishedLoading() {
return mFinishedLoading;
}
public boolean hasStartedLoading() {
return mStartedLoading;
}
public Bitmap getBitmap(int index) {
if (!mFinishedLoading) {
Logger.e("Can't call getBitmap before BitmapTextureMaker is finished loading.");
return null;
}
if (index < 0 || index >= mEntries.size()) {
return null;
}
return mEntries.get(index).bitmap;
}
public int getBitmapCount() {
return mEntries.size();
}
public int getTag(int index) {
return (index >= 0 && index < mEntries.size()) ? mEntries.get(index).tag : 0;
}
public void dispose() {
mFinishedLoading = mStartedLoading = false;
for (BitmapEntry e : mEntries) {
if (e.bitmap != null) {
e.bitmap.recycle();
e.bitmap = null;
}
}
}
}