mirror of
https://github.com/oxen-io/session-android.git
synced 2025-10-24 15:02:02 +00:00
107
src/org/thoughtcrime/securesms/components/ShapeScrim.java
Normal file
107
src/org/thoughtcrime/securesms/components/ShapeScrim.java
Normal file
@@ -0,0 +1,107 @@
|
||||
package org.thoughtcrime.securesms.components;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.RectF;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
public class ShapeScrim extends View {
|
||||
|
||||
private enum ShapeType {
|
||||
CIRCLE, SQUARE
|
||||
}
|
||||
|
||||
private final Paint eraser;
|
||||
private final ShapeType shape;
|
||||
private final float radius;
|
||||
|
||||
private Bitmap scrim;
|
||||
private Canvas scrimCanvas;
|
||||
|
||||
public ShapeScrim(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public ShapeScrim(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public ShapeScrim(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
if (attrs != null) {
|
||||
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ShapeScrim, 0, 0);
|
||||
String shapeName = typedArray.getString(R.styleable.ShapeScrim_shape);
|
||||
|
||||
if ("square".equalsIgnoreCase(shapeName)) this.shape = ShapeType.SQUARE;
|
||||
else if ("circle".equalsIgnoreCase(shapeName)) this.shape = ShapeType.CIRCLE;
|
||||
else this.shape = ShapeType.SQUARE;
|
||||
|
||||
this.radius = typedArray.getFloat(R.styleable.ShapeScrim_radius, 0.4f);
|
||||
|
||||
typedArray.recycle();
|
||||
} else {
|
||||
this.shape = ShapeType.SQUARE;
|
||||
this.radius = 0.4f;
|
||||
}
|
||||
|
||||
this.eraser = new Paint();
|
||||
this.eraser.setColor(0xFFFFFFFF);
|
||||
this.eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
int shortDimension = getWidth() < getHeight() ? getWidth() : getHeight();
|
||||
float drawRadius = shortDimension * radius;
|
||||
|
||||
if (scrimCanvas == null) {
|
||||
scrim = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
|
||||
scrimCanvas = new Canvas(scrim);
|
||||
}
|
||||
|
||||
scrim.eraseColor(Color.TRANSPARENT);
|
||||
scrimCanvas.drawColor(Color.parseColor("#55BDBDBD"));
|
||||
|
||||
if (shape == ShapeType.CIRCLE) drawCircle(scrimCanvas, drawRadius, eraser);
|
||||
else drawSquare(scrimCanvas, drawRadius, eraser);
|
||||
|
||||
canvas.drawBitmap(scrim, 0, 0, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
|
||||
super.onSizeChanged(width, height, oldHeight, oldHeight);
|
||||
|
||||
if (width != oldWidth || height != oldHeight) {
|
||||
scrim = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
scrimCanvas = new Canvas(scrim);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawCircle(Canvas canvas, float radius, Paint eraser) {
|
||||
canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, eraser);
|
||||
}
|
||||
|
||||
private void drawSquare(Canvas canvas, float radius, Paint eraser) {
|
||||
float left = (getWidth() / 2 ) - radius;
|
||||
float top = (getHeight() / 2) - radius;
|
||||
float right = left + (radius * 2);
|
||||
float bottom = top + (radius * 2);
|
||||
|
||||
RectF square = new RectF(left, top, right, bottom);
|
||||
|
||||
canvas.drawRoundRect(square, 25, 25, eraser);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import android.hardware.Camera.Size;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -22,6 +23,7 @@ public class CameraUtils {
|
||||
int width,
|
||||
int height,
|
||||
@NonNull Camera camera) {
|
||||
Log.w("CameraUtils", String.format("getPreferredPreviewSize(%d, %d, %d)", displayOrientation, width, height));
|
||||
double targetRatio = (double)width / height;
|
||||
Size optimalSize = null;
|
||||
double minDiff = Double.MAX_VALUE;
|
||||
|
||||
@@ -19,6 +19,7 @@ import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.Camera;
|
||||
@@ -39,6 +40,7 @@ import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
@@ -73,7 +75,15 @@ public class CameraView extends FrameLayout {
|
||||
super(context, attrs, defStyle);
|
||||
setBackgroundColor(Color.BLACK);
|
||||
|
||||
if (isMultiCamera()) cameraId = TextSecurePreferences.getDirectCaptureCameraId(context);
|
||||
if (attrs != null) {
|
||||
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CameraView);
|
||||
int camera = typedArray.getInt(R.styleable.CameraView_camera, -1);
|
||||
|
||||
if (camera != -1) cameraId = camera;
|
||||
else if (isMultiCamera()) cameraId = TextSecurePreferences.getDirectCaptureCameraId(context);
|
||||
|
||||
typedArray.recycle();
|
||||
}
|
||||
|
||||
surface = new CameraSurfaceView(getContext());
|
||||
onOrientationChange = new OnOrientationChange(context.getApplicationContext());
|
||||
@@ -87,7 +97,9 @@ public class CameraView extends FrameLayout {
|
||||
Log.w(TAG, "onResume() queued");
|
||||
enqueueTask(new SerialAsyncTask<Camera>() {
|
||||
@Override
|
||||
protected @Nullable Camera onRunBackground() {
|
||||
protected
|
||||
@Nullable
|
||||
Camera onRunBackground() {
|
||||
try {
|
||||
return Camera.open(cameraId);
|
||||
} catch (Exception e) {
|
||||
@@ -131,15 +143,19 @@ public class CameraView extends FrameLayout {
|
||||
|
||||
enqueueTask(new SerialAsyncTask<Void>() {
|
||||
private Optional<Camera> cameraToDestroy;
|
||||
@Override protected void onPreMain() {
|
||||
|
||||
@Override
|
||||
protected void onPreMain() {
|
||||
cameraToDestroy = camera;
|
||||
camera = Optional.absent();
|
||||
}
|
||||
|
||||
@Override protected Void onRunBackground() {
|
||||
@Override
|
||||
protected Void onRunBackground() {
|
||||
if (cameraToDestroy.isPresent()) {
|
||||
try {
|
||||
stopPreview();
|
||||
cameraToDestroy.get().setPreviewCallback(null);
|
||||
cameraToDestroy.get().release();
|
||||
Log.w(TAG, "released old camera instance");
|
||||
} catch (Exception e) {
|
||||
@@ -224,6 +240,30 @@ public class CameraView extends FrameLayout {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void setPreviewCallback(final PreviewCallback previewCallback) {
|
||||
enqueueTask(new PostInitializationTask<Void>() {
|
||||
@Override
|
||||
protected void onPostMain(Void avoid) {
|
||||
if (camera.isPresent()) {
|
||||
camera.get().setPreviewCallback(new Camera.PreviewCallback() {
|
||||
@Override
|
||||
public void onPreviewFrame(byte[] data, Camera camera) {
|
||||
if (!CameraView.this.camera.isPresent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int rotation = getCameraPictureOrientation();
|
||||
final Size previewSize = camera.getParameters().getPreviewSize();
|
||||
if (data != null) {
|
||||
previewCallback.onPreviewFrame(new PreviewFrame(data, previewSize.width, previewSize.height, rotation));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isMultiCamera() {
|
||||
return Camera.getNumberOfCameras() > 1;
|
||||
}
|
||||
@@ -515,4 +555,38 @@ public class CameraView extends FrameLayout {
|
||||
void onImageCapture(@NonNull final byte[] imageBytes);
|
||||
void onCameraFail();
|
||||
}
|
||||
|
||||
public interface PreviewCallback {
|
||||
void onPreviewFrame(@NonNull PreviewFrame frame);
|
||||
}
|
||||
|
||||
public static class PreviewFrame {
|
||||
private final @NonNull byte[] data;
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final int orientation;
|
||||
|
||||
private PreviewFrame(@NonNull byte[] data, int width, int height, int orientation) {
|
||||
this.data = data;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.orientation = orientation;
|
||||
}
|
||||
|
||||
public @NonNull byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public int getOrientation() {
|
||||
return orientation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user