mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-06 07:48:38 +09:00
pt 1 in reviving the android build (copied from pm 28a1, wish me luck)
This commit is contained in:
parent
efa9662725
commit
d7788a6d6d
4249 changed files with 468189 additions and 0 deletions
357
mobile/android/thirdparty/com/squareup/picasso/BitmapHunter.java
vendored
Normal file
357
mobile/android/thirdparty/com/squareup/picasso/BitmapHunter.java
vendored
Normal file
|
|
@ -0,0 +1,357 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Square, Inc.
|
||||
*
|
||||
* 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.squareup.picasso;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Matrix;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.Uri;
|
||||
import android.provider.MediaStore;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import static android.content.ContentResolver.SCHEME_ANDROID_RESOURCE;
|
||||
import static android.content.ContentResolver.SCHEME_CONTENT;
|
||||
import static android.content.ContentResolver.SCHEME_FILE;
|
||||
import static android.provider.ContactsContract.Contacts;
|
||||
import static com.squareup.picasso.Picasso.LoadedFrom.MEMORY;
|
||||
|
||||
abstract class BitmapHunter implements Runnable {
|
||||
|
||||
/**
|
||||
* Global lock for bitmap decoding to ensure that we are only are decoding one at a time. Since
|
||||
* this will only ever happen in background threads we help avoid excessive memory thrashing as
|
||||
* well as potential OOMs. Shamelessly stolen from Volley.
|
||||
*/
|
||||
private static final Object DECODE_LOCK = new Object();
|
||||
private static final String ANDROID_ASSET = "android_asset";
|
||||
protected static final int ASSET_PREFIX_LENGTH =
|
||||
(SCHEME_FILE + ":///" + ANDROID_ASSET + "/").length();
|
||||
|
||||
final Picasso picasso;
|
||||
final Dispatcher dispatcher;
|
||||
final Cache cache;
|
||||
final Stats stats;
|
||||
final String key;
|
||||
final Request data;
|
||||
final List<Action> actions;
|
||||
final boolean skipMemoryCache;
|
||||
|
||||
Bitmap result;
|
||||
Future<?> future;
|
||||
Picasso.LoadedFrom loadedFrom;
|
||||
Exception exception;
|
||||
int exifRotation; // Determined during decoding of original resource.
|
||||
|
||||
BitmapHunter(Picasso picasso, Dispatcher dispatcher, Cache cache, Stats stats, Action action) {
|
||||
this.picasso = picasso;
|
||||
this.dispatcher = dispatcher;
|
||||
this.cache = cache;
|
||||
this.stats = stats;
|
||||
this.key = action.getKey();
|
||||
this.data = action.getData();
|
||||
this.skipMemoryCache = action.skipCache;
|
||||
this.actions = new ArrayList<Action>(4);
|
||||
attach(action);
|
||||
}
|
||||
|
||||
protected void setExifRotation(int exifRotation) {
|
||||
this.exifRotation = exifRotation;
|
||||
}
|
||||
|
||||
@Override public void run() {
|
||||
try {
|
||||
Thread.currentThread().setName(Utils.THREAD_PREFIX + data.getName());
|
||||
|
||||
result = hunt();
|
||||
|
||||
if (result == null) {
|
||||
dispatcher.dispatchFailed(this);
|
||||
} else {
|
||||
dispatcher.dispatchComplete(this);
|
||||
}
|
||||
} catch (Downloader.ResponseException e) {
|
||||
exception = e;
|
||||
dispatcher.dispatchFailed(this);
|
||||
} catch (IOException e) {
|
||||
exception = e;
|
||||
dispatcher.dispatchRetry(this);
|
||||
} catch (OutOfMemoryError e) {
|
||||
StringWriter writer = new StringWriter();
|
||||
stats.createSnapshot().dump(new PrintWriter(writer));
|
||||
exception = new RuntimeException(writer.toString(), e);
|
||||
dispatcher.dispatchFailed(this);
|
||||
} catch (Exception e) {
|
||||
exception = e;
|
||||
dispatcher.dispatchFailed(this);
|
||||
} finally {
|
||||
Thread.currentThread().setName(Utils.THREAD_IDLE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
abstract Bitmap decode(Request data) throws IOException;
|
||||
|
||||
Bitmap hunt() throws IOException {
|
||||
Bitmap bitmap;
|
||||
|
||||
if (!skipMemoryCache) {
|
||||
bitmap = cache.get(key);
|
||||
if (bitmap != null) {
|
||||
stats.dispatchCacheHit();
|
||||
loadedFrom = MEMORY;
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
bitmap = decode(data);
|
||||
|
||||
if (bitmap != null) {
|
||||
stats.dispatchBitmapDecoded(bitmap);
|
||||
if (data.needsTransformation() || exifRotation != 0) {
|
||||
synchronized (DECODE_LOCK) {
|
||||
if (data.needsMatrixTransform() || exifRotation != 0) {
|
||||
bitmap = transformResult(data, bitmap, exifRotation);
|
||||
}
|
||||
if (data.hasCustomTransformations()) {
|
||||
bitmap = applyCustomTransformations(data.transformations, bitmap);
|
||||
}
|
||||
}
|
||||
stats.dispatchBitmapTransformed(bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
void attach(Action action) {
|
||||
actions.add(action);
|
||||
}
|
||||
|
||||
void detach(Action action) {
|
||||
actions.remove(action);
|
||||
}
|
||||
|
||||
boolean cancel() {
|
||||
return actions.isEmpty() && future != null && future.cancel(false);
|
||||
}
|
||||
|
||||
boolean isCancelled() {
|
||||
return future != null && future.isCancelled();
|
||||
}
|
||||
|
||||
boolean shouldSkipMemoryCache() {
|
||||
return skipMemoryCache;
|
||||
}
|
||||
|
||||
boolean shouldRetry(boolean airplaneMode, NetworkInfo info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Bitmap getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
Request getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
List<Action> getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
Exception getException() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
Picasso.LoadedFrom getLoadedFrom() {
|
||||
return loadedFrom;
|
||||
}
|
||||
|
||||
static BitmapHunter forRequest(Context context, Picasso picasso, Dispatcher dispatcher,
|
||||
Cache cache, Stats stats, Action action, Downloader downloader) {
|
||||
if (action.getData().resourceId != 0) {
|
||||
return new ResourceBitmapHunter(context, picasso, dispatcher, cache, stats, action);
|
||||
}
|
||||
Uri uri = action.getData().uri;
|
||||
String scheme = uri.getScheme();
|
||||
if (SCHEME_CONTENT.equals(scheme)) {
|
||||
if (Contacts.CONTENT_URI.getHost().equals(uri.getHost()) //
|
||||
&& !uri.getPathSegments().contains(Contacts.Photo.CONTENT_DIRECTORY)) {
|
||||
return new ContactsPhotoBitmapHunter(context, picasso, dispatcher, cache, stats, action);
|
||||
} else if (MediaStore.AUTHORITY.equals(uri.getAuthority())) {
|
||||
return new MediaStoreBitmapHunter(context, picasso, dispatcher, cache, stats, action);
|
||||
} else {
|
||||
return new ContentStreamBitmapHunter(context, picasso, dispatcher, cache, stats, action);
|
||||
}
|
||||
} else if (SCHEME_FILE.equals(scheme)) {
|
||||
if (!uri.getPathSegments().isEmpty() && ANDROID_ASSET.equals(uri.getPathSegments().get(0))) {
|
||||
return new AssetBitmapHunter(context, picasso, dispatcher, cache, stats, action);
|
||||
}
|
||||
return new FileBitmapHunter(context, picasso, dispatcher, cache, stats, action);
|
||||
} else if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
|
||||
return new ResourceBitmapHunter(context, picasso, dispatcher, cache, stats, action);
|
||||
} else {
|
||||
return new NetworkBitmapHunter(picasso, dispatcher, cache, stats, action, downloader);
|
||||
}
|
||||
}
|
||||
|
||||
static void calculateInSampleSize(int reqWidth, int reqHeight, BitmapFactory.Options options) {
|
||||
calculateInSampleSize(reqWidth, reqHeight, options.outWidth, options.outHeight, options);
|
||||
}
|
||||
|
||||
static void calculateInSampleSize(int reqWidth, int reqHeight, int width, int height,
|
||||
BitmapFactory.Options options) {
|
||||
int sampleSize = 1;
|
||||
if (height > reqHeight || width > reqWidth) {
|
||||
final int heightRatio = Math.round((float) height / (float) reqHeight);
|
||||
final int widthRatio = Math.round((float) width / (float) reqWidth);
|
||||
sampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
|
||||
}
|
||||
|
||||
options.inSampleSize = sampleSize;
|
||||
options.inJustDecodeBounds = false;
|
||||
}
|
||||
|
||||
static Bitmap applyCustomTransformations(List<Transformation> transformations, Bitmap result) {
|
||||
for (int i = 0, count = transformations.size(); i < count; i++) {
|
||||
final Transformation transformation = transformations.get(i);
|
||||
Bitmap newResult = transformation.transform(result);
|
||||
|
||||
if (newResult == null) {
|
||||
final StringBuilder builder = new StringBuilder() //
|
||||
.append("Transformation ")
|
||||
.append(transformation.key())
|
||||
.append(" returned null after ")
|
||||
.append(i)
|
||||
.append(" previous transformation(s).\n\nTransformation list:\n");
|
||||
for (Transformation t : transformations) {
|
||||
builder.append(t.key()).append('\n');
|
||||
}
|
||||
Picasso.HANDLER.post(new Runnable() {
|
||||
@Override public void run() {
|
||||
throw new NullPointerException(builder.toString());
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
if (newResult == result && result.isRecycled()) {
|
||||
Picasso.HANDLER.post(new Runnable() {
|
||||
@Override public void run() {
|
||||
throw new IllegalStateException("Transformation "
|
||||
+ transformation.key()
|
||||
+ " returned input Bitmap but recycled it.");
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the transformation returned a new bitmap ensure they recycled the original.
|
||||
if (newResult != result && !result.isRecycled()) {
|
||||
Picasso.HANDLER.post(new Runnable() {
|
||||
@Override public void run() {
|
||||
throw new IllegalStateException("Transformation "
|
||||
+ transformation.key()
|
||||
+ " mutated input Bitmap but failed to recycle the original.");
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
result = newResult;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static Bitmap transformResult(Request data, Bitmap result, int exifRotation) {
|
||||
int inWidth = result.getWidth();
|
||||
int inHeight = result.getHeight();
|
||||
|
||||
int drawX = 0;
|
||||
int drawY = 0;
|
||||
int drawWidth = inWidth;
|
||||
int drawHeight = inHeight;
|
||||
|
||||
Matrix matrix = new Matrix();
|
||||
|
||||
if (data.needsMatrixTransform()) {
|
||||
int targetWidth = data.targetWidth;
|
||||
int targetHeight = data.targetHeight;
|
||||
|
||||
float targetRotation = data.rotationDegrees;
|
||||
if (targetRotation != 0) {
|
||||
if (data.hasRotationPivot) {
|
||||
matrix.setRotate(targetRotation, data.rotationPivotX, data.rotationPivotY);
|
||||
} else {
|
||||
matrix.setRotate(targetRotation);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.centerCrop) {
|
||||
float widthRatio = targetWidth / (float) inWidth;
|
||||
float heightRatio = targetHeight / (float) inHeight;
|
||||
float scale;
|
||||
if (widthRatio > heightRatio) {
|
||||
scale = widthRatio;
|
||||
int newSize = (int) Math.ceil(inHeight * (heightRatio / widthRatio));
|
||||
drawY = (inHeight - newSize) / 2;
|
||||
drawHeight = newSize;
|
||||
} else {
|
||||
scale = heightRatio;
|
||||
int newSize = (int) Math.ceil(inWidth * (widthRatio / heightRatio));
|
||||
drawX = (inWidth - newSize) / 2;
|
||||
drawWidth = newSize;
|
||||
}
|
||||
matrix.preScale(scale, scale);
|
||||
} else if (data.centerInside) {
|
||||
float widthRatio = targetWidth / (float) inWidth;
|
||||
float heightRatio = targetHeight / (float) inHeight;
|
||||
float scale = widthRatio < heightRatio ? widthRatio : heightRatio;
|
||||
matrix.preScale(scale, scale);
|
||||
} else if (targetWidth != 0 && targetHeight != 0 //
|
||||
&& (targetWidth != inWidth || targetHeight != inHeight)) {
|
||||
// If an explicit target size has been specified and they do not match the results bounds,
|
||||
// pre-scale the existing matrix appropriately.
|
||||
float sx = targetWidth / (float) inWidth;
|
||||
float sy = targetHeight / (float) inHeight;
|
||||
matrix.preScale(sx, sy);
|
||||
}
|
||||
}
|
||||
|
||||
if (exifRotation != 0) {
|
||||
matrix.preRotate(exifRotation);
|
||||
}
|
||||
|
||||
Bitmap newResult =
|
||||
Bitmap.createBitmap(result, drawX, drawY, drawWidth, drawHeight, matrix, true);
|
||||
if (newResult != result) {
|
||||
result.recycle();
|
||||
result = newResult;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue