202 lines
4.8 KiB
Java
202 lines
4.8 KiB
Java
package ru.noties.markwon.spans;
|
|
|
|
import android.graphics.Canvas;
|
|
import android.graphics.ColorFilter;
|
|
import android.graphics.PixelFormat;
|
|
import android.graphics.Rect;
|
|
import android.graphics.drawable.Animatable;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.support.annotation.IntRange;
|
|
import android.support.annotation.NonNull;
|
|
import android.support.annotation.Nullable;
|
|
|
|
import ru.noties.markwon.renderer.html.ImageSize;
|
|
import ru.noties.markwon.renderer.html.ImageSizeResolver;
|
|
|
|
public class AsyncDrawable extends Drawable {
|
|
|
|
public interface Loader {
|
|
|
|
void load(@NonNull String destination, @NonNull AsyncDrawable drawable);
|
|
|
|
void cancel(@NonNull String destination);
|
|
}
|
|
|
|
private final String destination;
|
|
private final Loader loader;
|
|
private final ImageSize imageSize;
|
|
private final ImageSizeResolver imageSizeResolver;
|
|
|
|
private Drawable result;
|
|
private Callback callback;
|
|
|
|
private int canvasWidth;
|
|
private float textSize;
|
|
|
|
public AsyncDrawable(@NonNull String destination, @NonNull Loader loader) {
|
|
this(destination, loader, null, null);
|
|
}
|
|
|
|
/**
|
|
* @since 1.0.1
|
|
*/
|
|
public AsyncDrawable(
|
|
@NonNull String destination,
|
|
@NonNull Loader loader,
|
|
@Nullable ImageSizeResolver imageSizeResolver,
|
|
@Nullable ImageSize imageSize
|
|
) {
|
|
this.destination = destination;
|
|
this.loader = loader;
|
|
this.imageSizeResolver = imageSizeResolver;
|
|
this.imageSize = imageSize;
|
|
}
|
|
|
|
@NonNull
|
|
public String getDestination() {
|
|
return destination;
|
|
}
|
|
|
|
public Drawable getResult() {
|
|
return result;
|
|
}
|
|
|
|
public boolean hasResult() {
|
|
return result != null;
|
|
}
|
|
|
|
public boolean isAttached() {
|
|
return getCallback() != null;
|
|
}
|
|
|
|
// yeah
|
|
public void setCallback2(@Nullable Callback callback) {
|
|
|
|
this.callback = callback;
|
|
super.setCallback(callback);
|
|
|
|
// if not null -> means we are attached
|
|
if (callback != null) {
|
|
loader.load(destination, this);
|
|
} else {
|
|
if (result != null) {
|
|
|
|
result.setCallback(null);
|
|
|
|
// let's additionally stop if it Animatable
|
|
if (result instanceof Animatable) {
|
|
((Animatable) result).stop();
|
|
}
|
|
}
|
|
loader.cancel(destination);
|
|
}
|
|
}
|
|
|
|
public void setResult(@NonNull Drawable result) {
|
|
|
|
// if we have previous one, detach it
|
|
if (this.result != null) {
|
|
this.result.setCallback(null);
|
|
}
|
|
|
|
this.result = result;
|
|
this.result.setCallback(callback);
|
|
|
|
final Rect bounds = resolveBounds();
|
|
result.setBounds(bounds);
|
|
setBounds(bounds);
|
|
|
|
invalidateSelf();
|
|
}
|
|
|
|
/**
|
|
* @since 1.0.1
|
|
*/
|
|
@SuppressWarnings("WeakerAccess")
|
|
public void initWithKnownDimensions(int width, float textSize) {
|
|
this.canvasWidth = width;
|
|
this.textSize = textSize;
|
|
}
|
|
|
|
@Override
|
|
public void draw(@NonNull Canvas canvas) {
|
|
if (hasResult()) {
|
|
result.draw(canvas);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public int getOpacity() {
|
|
final int opacity;
|
|
if (hasResult()) {
|
|
opacity = result.getOpacity();
|
|
} else {
|
|
opacity = PixelFormat.TRANSPARENT;
|
|
}
|
|
return opacity;
|
|
}
|
|
|
|
@Override
|
|
public int getIntrinsicWidth() {
|
|
final int out;
|
|
if (hasResult()) {
|
|
out = result.getIntrinsicWidth();
|
|
} else {
|
|
out = 0;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
@Override
|
|
public int getIntrinsicHeight() {
|
|
final int out;
|
|
if (hasResult()) {
|
|
out = result.getIntrinsicHeight();
|
|
} else {
|
|
out = 0;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
/**
|
|
* @since 1.0.1
|
|
*/
|
|
@NonNull
|
|
private Rect resolveBounds() {
|
|
|
|
final Rect rect;
|
|
|
|
if (imageSizeResolver == null
|
|
|| imageSize == null) {
|
|
|
|
// @since 1.0.5
|
|
final Rect bounds = result.getBounds();
|
|
if (bounds.width() > canvasWidth) {
|
|
|
|
// let's scale image down, as we do not want to expand beyond canvas width
|
|
final float ratio = (float) bounds.width() / bounds.height();
|
|
final int height = (int) (canvasWidth / ratio + .5F);
|
|
rect = new Rect(0, 0, canvasWidth, height);
|
|
|
|
} else {
|
|
rect = bounds;
|
|
}
|
|
|
|
} else {
|
|
rect = imageSizeResolver.resolveImageSize(imageSize, result.getBounds(), canvasWidth, textSize);
|
|
}
|
|
|
|
return rect;
|
|
}
|
|
}
|