package org.thoughtcrime.securesms.imageeditor.renderers; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.os.Parcel; import androidx.annotation.ColorRes; import androidx.annotation.NonNull; import androidx.core.content.res.ResourcesCompat; import network.loki.messenger.R; import org.thoughtcrime.securesms.imageeditor.Bounds; import org.thoughtcrime.securesms.imageeditor.Renderer; import org.thoughtcrime.securesms.imageeditor.RendererContext; /** * Renders a box outside of the current crop area using {@link R.color#crop_area_renderer_outer_color} * and around the edge it renders the markers for the thumbs using {@link R.color#crop_area_renderer_edge_color}, * {@link R.dimen#crop_area_renderer_edge_thickness} and {@link R.dimen#crop_area_renderer_edge_size}. *
* Hit tests outside of the bounds.
*/
public final class CropAreaRenderer implements Renderer {
@ColorRes
private final int color;
private final Path cropClipPath = new Path();
private final Path screenClipPath = new Path();
private final RectF dst = new RectF();
private final Paint paint = new Paint();
@Override
public void render(@NonNull RendererContext rendererContext) {
rendererContext.save();
Canvas canvas = rendererContext.canvas;
Resources resources = rendererContext.context.getResources();
canvas.clipPath(cropClipPath);
canvas.drawColor(ResourcesCompat.getColor(resources, color, null));
rendererContext.mapRect(dst, Bounds.FULL_BOUNDS);
final int thickness = resources.getDimensionPixelSize(R.dimen.crop_area_renderer_edge_thickness);
final int size = (int) Math.min(resources.getDimensionPixelSize(R.dimen.crop_area_renderer_edge_size), Math.min(dst.width(), dst.height()) / 3f - 10);
paint.setColor(ResourcesCompat.getColor(resources, R.color.crop_area_renderer_edge_color, null));
rendererContext.canvasMatrix.setToIdentity();
screenClipPath.reset();
screenClipPath.moveTo(dst.left, dst.top);
screenClipPath.lineTo(dst.right, dst.top);
screenClipPath.lineTo(dst.right, dst.bottom);
screenClipPath.lineTo(dst.left, dst.bottom);
screenClipPath.close();
canvas.clipPath(screenClipPath);
canvas.translate(dst.left, dst.top);
float halfDx = (dst.right - dst.left - size + thickness) / 2;
float halfDy = (dst.bottom - dst.top - size + thickness) / 2;
canvas.drawRect(-thickness, -thickness, size, size, paint);
canvas.translate(0, halfDy);
canvas.drawRect(-thickness, -thickness, size, size, paint);
canvas.translate(0, halfDy);
canvas.drawRect(-thickness, -thickness, size, size, paint);
canvas.translate(halfDx, 0);
canvas.drawRect(-thickness, -thickness, size, size, paint);
canvas.translate(halfDx, 0);
canvas.drawRect(-thickness, -thickness, size, size, paint);
canvas.translate(0, -halfDy);
canvas.drawRect(-thickness, -thickness, size, size, paint);
canvas.translate(0, -halfDy);
canvas.drawRect(-thickness, -thickness, size, size, paint);
canvas.translate(-halfDx, 0);
canvas.drawRect(-thickness, -thickness, size, size, paint);
rendererContext.restore();
}
public CropAreaRenderer(@ColorRes int color) {
this.color = color;
cropClipPath.toggleInverseFillType();
cropClipPath.moveTo(Bounds.LEFT, Bounds.TOP);
cropClipPath.lineTo(Bounds.RIGHT, Bounds.TOP);
cropClipPath.lineTo(Bounds.RIGHT, Bounds.BOTTOM);
cropClipPath.lineTo(Bounds.LEFT, Bounds.BOTTOM);
cropClipPath.close();
screenClipPath.toggleInverseFillType();
}
private CropAreaRenderer(Parcel in) {
this(in.readInt());
}
@Override
public boolean hitTest(float x, float y) {
return !Bounds.contains(x, y);
}
public static final Creator