Replaced AnnotatedSource by ImageSpanEx

This commit is contained in:
M66B
2022-04-07 12:17:34 +02:00
parent b0e0169f7e
commit 1dfac120dd
9 changed files with 211 additions and 173 deletions

View File

@@ -59,6 +59,8 @@ import androidx.preference.PreferenceManager;
import com.caverock.androidsvg.SVG;
import org.jsoup.nodes.Element;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
@@ -302,6 +304,20 @@ class ImageHelper {
}
static Drawable decodeImage(final Context context, final long id, String source, boolean show, int zoom, final float scale, final TextView view) {
return decodeImage(context, id, source, 0, 0, false, show, zoom, scale, view);
}
static Drawable decodeImage(final Context context, final long id, Element img, boolean show, int zoom, final float scale, final TextView view) {
String source = img.attr("src");
Integer w = Helper.parseInt(img.attr("width"));
Integer h = Helper.parseInt(img.attr("height"));
boolean tracking = !TextUtils.isEmpty(img.attr("x-tracking"));
return decodeImage(context, id, source, w == null ? 0 : w, h == null ? 0 : h, tracking, show, zoom, scale, view);
}
private static Drawable decodeImage(final Context context, final long id,
String source, final int aw, final int ah, boolean tracking,
boolean show, int zoom, final float scale, final TextView view) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean inline = prefs.getBoolean("inline_images", false);
@@ -309,24 +325,22 @@ class ImageHelper {
final Resources res = context.getResources();
try {
final AnnotatedSource a = new AnnotatedSource(source);
if (TextUtils.isEmpty(a.source)) {
if (TextUtils.isEmpty(source)) {
Drawable d = context.getDrawable(R.drawable.twotone_broken_image_24);
d.setBounds(0, 0, px, px);
return d;
}
boolean embedded = a.source.startsWith("cid:");
boolean data = a.source.startsWith("data:");
boolean content = a.source.startsWith("content:");
boolean embedded = source.startsWith("cid:");
boolean data = source.startsWith("data:");
boolean content = source.startsWith("content:");
Log.d("Image show=" + show + " inline=" + inline + " source=" + a.source);
Log.d("Image show=" + show + " inline=" + inline + " source=" + source);
// Embedded images
if (embedded && (show || inline)) {
DB db = DB.getInstance(context);
String cid = "<" + a.source.substring(4) + ">";
String cid = "<" + source.substring(4) + ">";
EntityAttachment attachment = db.attachment().getAttachment(id, cid);
if (attachment == null) {
Log.i("Image not found CID=" + cid);
@@ -347,7 +361,7 @@ class ImageHelper {
attachment.getMimeType(),
scaleToPixels);
if (view != null)
fitDrawable(d, a, scale, view);
fitDrawable(d, aw, ah, scale, view);
return d;
} catch (IOException ex) {
Log.w(ex);
@@ -369,7 +383,7 @@ class ImageHelper {
Drawable d = new BitmapDrawable(res, bm);
d.setBounds(0, 0, bm.getWidth(), bm.getHeight());
if (view != null)
fitDrawable(d, a, scale, view);
fitDrawable(d, aw, ah, scale, view);
return d;
}
}
@@ -377,11 +391,11 @@ class ImageHelper {
}
// Data URI
if (data && (show || inline || a.tracking))
if (data && (show || inline || tracking))
try {
int scaleToPixels = res.getDisplayMetrics().widthPixels;
String mimeType = getDataUriType(a.source);
ByteArrayInputStream bis = getDataUriStream(a.source);
String mimeType = getDataUriType(source);
ByteArrayInputStream bis = getDataUriStream(source);
Bitmap bm = getScaledBitmap(bis, "data:" + mimeType, mimeType, scaleToPixels);
if (bm == null)
throw new IllegalArgumentException("decode byte array failed");
@@ -390,7 +404,7 @@ class ImageHelper {
d.setBounds(0, 0, bm.getWidth(), bm.getHeight());
if (view != null)
fitDrawable(d, a, scale, view);
fitDrawable(d, aw, ah, scale, view);
return d;
} catch (IllegalArgumentException ex) {
Log.i(ex);
@@ -401,7 +415,7 @@ class ImageHelper {
if (content && (show || inline))
try {
Uri uri = Uri.parse(a.source);
Uri uri = Uri.parse(source);
Log.i("Loading image source=" + uri);
Bitmap bm;
@@ -409,16 +423,16 @@ class ImageHelper {
try (InputStream is = context.getContentResolver().openInputStream(uri)) {
if (is == null)
throw new FileNotFoundException(uri.toString());
bm = getScaledBitmap(is, a.source, null, scaleToPixels);
bm = getScaledBitmap(is, source, null, scaleToPixels);
if (bm == null)
throw new FileNotFoundException(a.source);
throw new FileNotFoundException(source);
}
Drawable d = new BitmapDrawable(res, bm);
d.setBounds(0, 0, bm.getWidth(), bm.getHeight());
if (view != null)
fitDrawable(d, a, scale, view);
fitDrawable(d, aw, ah, scale, view);
return d;
} catch (Throwable ex) {
// FileNotFound, Security
@@ -437,7 +451,7 @@ class ImageHelper {
}
// Check cache
Drawable cached = getCachedImage(context, id, a.source);
Drawable cached = getCachedImage(context, id, source);
if (cached != null || view == null) {
if (view == null)
if (cached == null) {
@@ -447,7 +461,7 @@ class ImageHelper {
} else
return cached;
else
fitDrawable(cached, a, scale, view);
fitDrawable(cached, aw, ah, scale, view);
return cached;
}
@@ -486,17 +500,17 @@ class ImageHelper {
public void run() {
try {
// Check cache again
Drawable cached = getCachedImage(context, id, a.source);
Drawable cached = getCachedImage(context, id, source);
if (cached != null) {
fitDrawable(cached, a, scale, view);
post(cached, a.source);
fitDrawable(cached, aw, ah, scale, view);
post(cached, source);
return;
}
// Download image
Drawable d = downloadImage(context, id, a.source, null);
fitDrawable(d, a, scale, view);
post(d, a.source);
Drawable d = downloadImage(context, id, source, null);
fitDrawable(d, aw, ah, scale, view);
post(d, source);
} catch (Throwable ex) {
// Show broken icon
Log.i(ex);
@@ -505,7 +519,7 @@ class ImageHelper {
: R.drawable.twotone_broken_image_24);
Drawable d = context.getDrawable(resid);
d.setBounds(0, 0, px, px);
post(d, a.source);
post(d, source);
}
}
@@ -547,7 +561,7 @@ class ImageHelper {
private static Map<Drawable, Rect> drawableBounds = new WeakHashMap<>();
static void fitDrawable(final Drawable d, final AnnotatedSource a, float scale, final View view) {
static void fitDrawable(final Drawable d, int aw, int ah, float scale, final View view) {
synchronized (drawableBounds) {
if (drawableBounds.containsKey(d))
d.setBounds(drawableBounds.get(d));
@@ -559,15 +573,15 @@ class ImageHelper {
int w = Math.round(Helper.dp2pixels(view.getContext(), bounds.width()) * scale);
int h = Math.round(Helper.dp2pixels(view.getContext(), bounds.height()) * scale);
if (a.width == 0 && a.height != 0)
a.width = Math.round(a.height * w / (float) h);
if (a.height == 0 && a.width != 0)
a.height = Math.round(a.width * h / (float) w);
if (aw == 0 && ah != 0)
aw = Math.round(ah * w / (float) h);
if (ah == 0 && aw != 0)
ah = Math.round(aw * h / (float) w);
if (a.width != 0 && a.height != 0) {
boolean swap = ((w > h) != (a.width > a.height)) && false;
w = Math.round(Helper.dp2pixels(view.getContext(), swap ? a.height : a.width) * scale);
h = Math.round(Helper.dp2pixels(view.getContext(), swap ? a.width : a.height) * scale);
if (aw != 0 && ah != 0) {
boolean swap = ((w > h) != (aw > ah)) && false;
w = Math.round(Helper.dp2pixels(view.getContext(), swap ? ah : aw) * scale);
h = Math.round(Helper.dp2pixels(view.getContext(), swap ? aw : ah) * scale);
}
float width = view.getContext().getResources().getDisplayMetrics().widthPixels;
@@ -931,55 +945,4 @@ class ImageHelper {
return (lum / n);
}
static class AnnotatedSource {
private String source;
private int width = 0;
private int height = 0;
private boolean tracking = false;
// Encapsulate some ugliness
AnnotatedSource(String source) {
this.source = source;
if (source != null && source.endsWith("###")) {
int pos = source.substring(0, source.length() - 3).lastIndexOf("###");
if (pos > 0) {
int x = source.indexOf("x", pos + 3);
int s = source.indexOf(":", pos + 3);
if (x > 0 && s > x)
try {
this.width = Integer.parseInt(source.substring(pos + 3, x));
this.height = Integer.parseInt(source.substring(x + 1, s));
this.tracking = Boolean.parseBoolean(source.substring(s + 1, source.length() - 3));
this.source = source.substring(0, pos);
} catch (NumberFormatException ex) {
Log.e(ex);
}
}
}
}
AnnotatedSource(String source, int width, int height, boolean tracking) {
this.source = source;
this.width = width;
this.height = height;
this.tracking = tracking;
}
public String getSource() {
return this.source;
}
public boolean isTracking() {
return this.tracking;
}
String getAnnotated() {
return (width == 0 && height == 0
? source
: source + "###" + width + "x" + height + ":" + tracking + "###");
}
}
}