Replaced AnnotatedSource by ImageSpanEx

pull/207/head
M66B 2 years ago
parent b0e0169f7e
commit 1dfac120dd

@ -54,6 +54,7 @@ import androidx.preference.PreferenceManager;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import java.util.Objects;
@ -272,12 +273,14 @@ public class ActivitySignature extends ActivityBase {
else if (etText.isRaw())
etText.setText(html);
else
etText.setText(HtmlHelper.fromHtml(html, new Html.ImageGetter() {
etText.setText(HtmlHelper.fromHtml(html, new HtmlHelper.ImageGetterEx() {
@Override
public Drawable getDrawable(String source) {
if (source != null && source.startsWith("cid:"))
source = null;
return ImageHelper.decodeImage(ActivitySignature.this, -1, source, true, 0, 1.0f, etText);
public Drawable getDrawable(Element element) {
String source = element.attr("src");
if (source.startsWith("cid:"))
element.attr("src", "cid:");
return ImageHelper.decodeImage(ActivitySignature.this,
-1, element, true, 0, 1.0f, etText);
}
}, null, this));
loaded = true;

@ -528,8 +528,13 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
Spanned spanned = (Spanned) tvBody.getText();
for (ImageSpan img : spanned.getSpans(0, spanned.length(), ImageSpan.class)) {
Drawable d = img.getDrawable();
ImageHelper.AnnotatedSource a = new ImageHelper.AnnotatedSource(img.getSource());
ImageHelper.fitDrawable(d, a, scale, tvBody);
int w = 0;
int h = 0;
if (img instanceof ImageSpanEx) {
w = ((ImageSpanEx) img).getWidth();
h = ((ImageSpanEx) img).getHeight();
}
ImageHelper.fitDrawable(d, w, h, scale, tvBody);
}
// Feedback
@ -584,8 +589,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
if (!show_images) {
ImageSpan[] image = buffer.getSpans(off, off, ImageSpan.class);
if (image.length > 0 && image[0].getSource() != null) {
ImageHelper.AnnotatedSource a = new ImageHelper.AnnotatedSource(image[0].getSource());
Uri uri = Uri.parse(a.getSource());
Uri uri = Uri.parse(image[0].getSource());
if ("http".equals(uri.getScheme()) || "https".equals(uri.getScheme())) {
ripple(event);
if (onOpenLink(uri, null, false))
@ -613,15 +617,13 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
ImageSpan[] image = buffer.getSpans(off, off, ImageSpan.class);
if (image.length > 0) {
ImageHelper.AnnotatedSource a = new ImageHelper.AnnotatedSource(image[0].getSource());
String source = a.getSource();
if (!TextUtils.isEmpty(source)) {
if (!a.isTracking()) {
ripple(event);
onOpenImage(message.id, source);
}
if (image[0] instanceof ImageSpanEx &&
((ImageSpanEx) image[0]).getTracking())
return true;
}
ripple(event);
onOpenImage(message.id, image[0].getSource());
return true;
}
DynamicDrawableSpan[] ddss = buffer.getSpans(off, off, DynamicDrawableSpan.class);
@ -2815,10 +2817,11 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
HtmlHelper.collapseQuotes(document);
// Draw images
SpannableStringBuilder ssb = HtmlHelper.fromDocument(context, document, new Html.ImageGetter() {
SpannableStringBuilder ssb = HtmlHelper.fromDocument(context, document, new HtmlHelper.ImageGetterEx() {
@Override
public Drawable getDrawable(String source) {
Drawable drawable = ImageHelper.decodeImage(context, message.id, source, show_images, zoom, scale, tvBody);
public Drawable getDrawable(Element element) {
Drawable drawable = ImageHelper.decodeImage(context,
message.id, element, show_images, zoom, scale, tvBody);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
if (drawable instanceof AnimatedImageDrawable)
@ -5664,13 +5667,12 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
private void onOpenImage(long id, @NonNull String source) {
Log.i("Viewing image source=" + source);
ImageHelper.AnnotatedSource annotated = new ImageHelper.AnnotatedSource(source);
Uri uri = Uri.parse(annotated.getSource());
Uri uri = Uri.parse(source);
String scheme = uri.getScheme();
Bundle args = new Bundle();
args.putLong("id", id);
args.putString("source", annotated.getSource());
args.putString("source", source);
args.putInt("zoom", zoom);
if ("cid".equals(scheme))

@ -55,6 +55,7 @@ import androidx.preference.PreferenceManager;
import androidx.room.EntityInsertionAdapter;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import java.util.List;
import java.util.concurrent.ExecutorService;
@ -460,11 +461,11 @@ public class EditTextCompose extends FixedEditText {
private SpannableStringBuilder getSpanned(Context context, String html) {
Document document = HtmlHelper.sanitizeCompose(context, html, false);
Spanned paste = HtmlHelper.fromDocument(context, document, new Html.ImageGetter() {
Spanned paste = HtmlHelper.fromDocument(context, document, new HtmlHelper.ImageGetterEx() {
@Override
public Drawable getDrawable(String source) {
public Drawable getDrawable(Element element) {
return ImageHelper.decodeImage(context,
-1, source, true, 0, 1.0f, EditTextCompose.this);
-1, element, true, 0, 1.0f, EditTextCompose.this);
}
}, null);

@ -56,6 +56,7 @@ import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.snackbar.Snackbar;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
public class FragmentAnswer extends FragmentBase {
private ViewGroup view;
@ -247,12 +248,14 @@ public class FragmentAnswer extends FragmentBase {
if (html == null)
etText.setText(null);
else
etText.setText(HtmlHelper.fromHtml(html, new Html.ImageGetter() {
etText.setText(HtmlHelper.fromHtml(html, new HtmlHelper.ImageGetterEx() {
@Override
public Drawable getDrawable(String source) {
if (source != null && source.startsWith("cid:"))
source = null;
return ImageHelper.decodeImage(context, -1, source, true, 0, 1.0f, etText);
public Drawable getDrawable(Element element) {
String source = element.attr("src");
if (source.startsWith("cid:"))
element.attr("src", "cid:");
return ImageHelper.decodeImage(context,
-1, element, true, 0, 1.0f, etText);
}
}, null, context));
}

@ -2018,12 +2018,14 @@ public class FragmentCompose extends FragmentBase {
String html = EntityAnswer.replacePlaceholders(answer.text, to);
Spanned spanned = HtmlHelper.fromHtml(html, new Html.ImageGetter() {
Spanned spanned = HtmlHelper.fromHtml(html, new HtmlHelper.ImageGetterEx() {
@Override
public Drawable getDrawable(String source) {
if (source != null && source.startsWith("cid:"))
source = null;
return ImageHelper.decodeImage(getContext(), working, source, true, zoom, 1.0f, etBody);
public Drawable getDrawable(Element element) {
String source = element.attr("src");
if (source.startsWith("cid:"))
element.attr("src", "cid:");
return ImageHelper.decodeImage(getContext(),
working, element, true, zoom, 1.0f, etBody);
}
}, null, getContext());
@ -2886,10 +2888,11 @@ public class FragmentCompose extends FragmentBase {
Helper.writeText(file, doc.html());
}
return HtmlHelper.fromHtml(html, new Html.ImageGetter() {
return HtmlHelper.fromHtml(html, new HtmlHelper.ImageGetterEx() {
@Override
public Drawable getDrawable(String source) {
return ImageHelper.decodeImage(context, id, source, true, zoom, 1.0f, etBody);
public Drawable getDrawable(Element element) {
return ImageHelper.decodeImage(context,
id, element, true, zoom, 1.0f, etBody);
}
}, null, getContext());
}
@ -6382,10 +6385,11 @@ public class FragmentCompose extends FragmentBase {
doc = HtmlHelper.sanitizeCompose(context, doc.html(), true);
Spanned spannedBody = HtmlHelper.fromDocument(context, doc, new Html.ImageGetter() {
Spanned spannedBody = HtmlHelper.fromDocument(context, doc, new HtmlHelper.ImageGetterEx() {
@Override
public Drawable getDrawable(String source) {
return ImageHelper.decodeImage(context, id, source, true, zoom, 1.0f, etBody);
public Drawable getDrawable(Element element) {
return ImageHelper.decodeImage(context,
id, element, true, zoom, 1.0f, etBody);
}
}, null);
@ -6412,10 +6416,11 @@ public class FragmentCompose extends FragmentBase {
HtmlHelper.autoLink(dref);
Document quote = HtmlHelper.sanitizeView(context, dref, show_images);
spannedRef = HtmlHelper.fromDocument(context, quote,
new Html.ImageGetter() {
new HtmlHelper.ImageGetterEx() {
@Override
public Drawable getDrawable(String source) {
return ImageHelper.decodeImage(context, id, source, show_images, zoom, 1.0f, tvReference);
public Drawable getDrawable(Element element) {
return ImageHelper.decodeImage(context,
id, element, show_images, zoom, 1.0f, tvReference);
}
},
null);
@ -6616,10 +6621,11 @@ public class FragmentCompose extends FragmentBase {
Spanned signature = null;
if (identity != null && !TextUtils.isEmpty(identity.signature))
signature = HtmlHelper.fromHtml(identity.signature, new Html.ImageGetter() {
signature = HtmlHelper.fromHtml(identity.signature, new HtmlHelper.ImageGetterEx() {
@Override
public Drawable getDrawable(String source) {
return ImageHelper.decodeImage(getContext(), working, source, true, 0, 1.0f, tvSignature);
public Drawable getDrawable(Element element) {
return ImageHelper.decodeImage(getContext(),
working, element, true, 0, 1.0f, tvSignature);
}
}, null, getContext());
tvSignature.setText(signature);

@ -406,7 +406,19 @@ public class HtmlEx {
if (style[j] instanceof ImageSpan) {
out.append("<img src=\"");
out.append(((ImageSpan) style[j]).getSource());
out.append("\">");
out.append("\"");
if (style[j] instanceof ImageSpanEx) {
ImageSpanEx img = (ImageSpanEx) style[j];
int w = img.getWidth();
if (w > 0)
out.append(" width=\"").append(w).append("\"");
int h = img.getHeight();
if (h > 0)
out.append(" height=\"").append(h).append("\"");
}
out.append(">");
// Don't output the dummy character underlying the image.
i = next;

@ -110,7 +110,6 @@ import java.net.URI;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -1371,38 +1370,6 @@ public class HtmlHelper {
.attr("x-font-size-abs", Integer.toString(textSizeSmall));
img.appendChild(a);
}
// Annotate source with width and height
if (!TextUtils.isEmpty(src)) {
int width = 0;
int height = 0;
// Relative sizes (%) = use image size
String awidth = img.attr("width").replace(" ", "");
for (int i = 0; i < awidth.length(); i++)
if (Character.isDigit(awidth.charAt(i)))
width = width * 10 + (byte) awidth.charAt(i) - (byte) '0';
else {
width = 0;
break;
}
String aheight = img.attr("height").replace(" ", "");
for (int i = 0; i < aheight.length(); i++)
if (Character.isDigit(aheight.charAt(i)))
height = height * 10 + (byte) aheight.charAt(i) - (byte) '0';
else {
height = 0;
break;
}
if (width != 0 || height != 0) {
ImageHelper.AnnotatedSource a = new ImageHelper.AnnotatedSource(
src, width, height, !TextUtils.isEmpty(tracking));
img.attr("src", a.getAnnotated());
}
}
}
// Selective new lines
@ -2928,7 +2895,7 @@ public class HtmlHelper {
static SpannableStringBuilder fromDocument(
Context context, @NonNull Document document,
@Nullable Html.ImageGetter imageGetter, @Nullable Html.TagHandler tagHandler) {
@Nullable ImageGetterEx imageGetter, @Nullable Html.TagHandler tagHandler) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean debug = prefs.getBoolean("debug", false);
boolean monospaced_pre = prefs.getBoolean("monospaced_pre", false);
@ -3350,9 +3317,9 @@ public class HtmlHelper {
if (!TextUtils.isEmpty(src)) {
Drawable d = (imageGetter == null
? context.getDrawable(R.drawable.twotone_broken_image_24)
: imageGetter.getDrawable(src));
: imageGetter.getDrawable(element));
ssb.insert(start, "\uFFFC"); // Object replacement character
setSpan(ssb, new ImageSpan(d, src), start, start + 1);
setSpan(ssb, new ImageSpanEx(d, element), start, start + 1);
}
break;
case "li":
@ -3608,7 +3575,7 @@ public class HtmlHelper {
return fromHtml(html, null, null, context);
}
static Spanned fromHtml(@NonNull String html, @Nullable Html.ImageGetter imageGetter, @Nullable Html.TagHandler tagHandler, Context context) {
static Spanned fromHtml(@NonNull String html, @Nullable ImageGetterEx imageGetter, @Nullable Html.TagHandler tagHandler, Context context) {
Document document = JsoupEx.parse(html);
return fromDocument(context, document, imageGetter, tagHandler);
}
@ -3716,4 +3683,8 @@ public class HtmlHelper {
spanned.getSpanFlags(spans[i]));
return reverse;
}
interface ImageGetterEx {
Drawable getDrawable(Element element);
}
}

@ -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 + "###");
}
}
}

@ -0,0 +1,77 @@
package eu.faircode.email;
/*
This file is part of FairEmail.
FairEmail is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
FairEmail is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FairEmail. If not, see <http://www.gnu.org/licenses/>.
Copyright 2018-2022 by Marcel Bokhorst (M66B)
*/
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.text.style.ImageSpan;
import androidx.annotation.NonNull;
import org.jsoup.nodes.Element;
public class ImageSpanEx extends ImageSpan {
private final int width;
private final int height;
private final boolean tracking;
public ImageSpanEx(@NonNull Drawable drawable, @NonNull Element img) {
super(drawable, img.attr("src"));
int _width = 0;
int _height = 0;
// Relative sizes (%) = use image size
String awidth = img.attr("width").replace(" ", "");
for (int i = 0; i < awidth.length(); i++)
if (Character.isDigit(awidth.charAt(i)))
_width = _width * 10 + (byte) awidth.charAt(i) - (byte) '0';
else {
_width = 0;
break;
}
String aheight = img.attr("height").replace(" ", "");
for (int i = 0; i < aheight.length(); i++)
if (Character.isDigit(aheight.charAt(i)))
_height = _height * 10 + (byte) aheight.charAt(i) - (byte) '0';
else {
_height = 0;
break;
}
this.width = _width;
this.height = _height;
this.tracking = !TextUtils.isEmpty(img.attr("x-tracking"));
}
public int getWidth() {
return this.width;
}
public int getHeight() {
return this.height;
}
public boolean getTracking() {
return this.tracking;
}
}
Loading…
Cancel
Save