Add image editor sample app.

fork-5.53.8
Alex Hart 2021-09-16 11:18:54 -03:00
rodzic c43fe44e3e
commit bcfe8909e5
40 zmienionych plików z 1404 dodań i 1 usunięć

1
image-editor/app/.gitignore vendored 100644
Wyświetl plik

@ -0,0 +1 @@
/build

Wyświetl plik

@ -0,0 +1,49 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id 'witness'
}
apply from: 'witness-verifications.gradle'
android {
compileSdk COMPILE_SDK
defaultConfig {
applicationId "org.signal.imageeditor.app"
versionCode 1
versionName "1.0"
minSdk MINIMUM_SDK
targetSdk TARGET_SDK
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JAVA_VERSION
targetCompatibility JAVA_VERSION
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencyVerification {
configuration = '(debug|release)RuntimeClasspath'
}
dependencies {
implementation libs.androidx.core.ktx
implementation libs.androidx.appcompat
implementation libs.material.material
implementation project(':image-editor')
implementation libs.glide.glide
kapt libs.glide.compiler
}

Wyświetl plik

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

Wyświetl plik

@ -0,0 +1,24 @@
package com.example.imageeditor.app
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.example.imageeditor.app", appContext.packageName)
}
}

Wyświetl plik

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.signal.imageeditor.app">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Signal">
<activity
android:name="org.signal.imageeditor.app.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

Wyświetl plik

@ -0,0 +1,275 @@
package org.signal.imageeditor.app;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import org.signal.imageeditor.app.renderers.UriRenderer;
import org.signal.imageeditor.app.renderers.UrlRenderer;
import org.signal.imageeditor.core.ImageEditorView;
import org.signal.imageeditor.core.UndoRedoStackListener;
import org.signal.imageeditor.core.model.EditorElement;
import org.signal.imageeditor.core.model.EditorModel;
import org.signal.imageeditor.core.renderers.MultiLineTextRenderer;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Locale;
public final class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private ImageEditorView imageEditorView;
private Menu menu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
toolbar.setTitle(R.string.app_name_short);
setSupportActionBar(toolbar);
imageEditorView = findViewById(R.id.image_editor);
imageEditorView.setUndoRedoStackListener((undoAvailable, redoAvailable) -> {
Log.d("ALAN", String.format("Undo/Redo available: %s, %s", undoAvailable ? "Y" : "N", redoAvailable ? "Y" : "N"));
if (menu == null) return;
MenuItem undo = menu.findItem(R.id.action_undo);
MenuItem redo = menu.findItem(R.id.action_redo);
if (undo != null) undo.setVisible(undoAvailable);
if (redo != null) redo.setVisible(redoAvailable);
});
EditorModel model = null;
if (savedInstanceState != null) {
model = savedInstanceState.getParcelable("MODEL");
Log.d("ALAN", "Restoring instance " + (model != null ? model.hashCode() : 0));
}
if (model == null) {
model = initialModel();
Log.d("ALAN", "New instance created " + model.hashCode());
}
imageEditorView.setModel(model);
imageEditorView.setTapListener(new ImageEditorView.TapListener() {
@Override
public void onEntityDown(@Nullable EditorElement editorElement) {
Log.d("ALAN", "Entity down " + editorElement);
}
@Override
public void onEntitySingleTap(@Nullable EditorElement editorElement) {
Log.d("ALAN", "Entity single tapped " + editorElement);
}
@Override
public void onEntityDoubleTap(@NonNull EditorElement editorElement) {
Log.d("ALAN", "Entity double tapped " + editorElement);
if (editorElement.getRenderer() instanceof MultiLineTextRenderer) {
imageEditorView.startTextEditing(editorElement);
} else {
imageEditorView.deleteElement(editorElement);
}
}
});
}
private static EditorModel initialModel() {
EditorModel model = EditorModel.create();
EditorElement image = new EditorElement(new UrlRenderer("https://cdn.aarp.net/content/dam/aarp/home-and-family/your-home/2018/06/1140-house-inheriting.imgcache.rev68c065601779c5d76b913cf9ec3a977e.jpg"));
image.getFlags().setSelectable(false).persist();
model.addElement(image);
EditorElement elementC = new EditorElement(new UrlRenderer("https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/SNice.svg/220px-SNice.svg.png"));
elementC.getLocalMatrix().postScale(0.2f, 0.2f);
//elementC.getLocalMatrix().postRotate(30);
model.addElement(elementC);
EditorElement elementE = new EditorElement(new UrlRenderer("https://www.vitalessentialsraw.com/assets/images/background-images/laying-grey-cat.png"));
elementE.getLocalMatrix().postScale(0.2f, 0.2f);
//elementE.getLocalMatrix().postRotate(60);
model.addElement(elementE);
EditorElement elementD = new EditorElement(new UrlRenderer("https://petspluslubbocktx.com/files/2016/11/DC-Cat-Weight-Management.png"));
elementD.getLocalMatrix().postScale(0.2f, 0.2f);
//elementD.getLocalMatrix().postRotate(60);
model.addElement(elementD);
EditorElement elementF = new EditorElement(new UrlRenderer("https://purepng.com/public/uploads/large/purepng.com-black-top-hathatsstandard-sizeblacktop-14215263591972x0zh.png"));
elementF.getLocalMatrix().postScale(0.2f, 0.2f);
//elementF.getLocalMatrix().postRotatF(60);
model.addElement(elementF);
EditorElement elementG = new EditorElement(new UriRenderer(Uri.parse("file:///android_asset/food/apple.png")));
elementG.getLocalMatrix().postScale(0.2f, 0.2f);
//elementG.getLocalMatrix().postRotatG(60);
model.addElement(elementG);
EditorElement elementH = new EditorElement(new MultiLineTextRenderer("Hello, World!", 0xff0000ff, MultiLineTextRenderer.Mode.REGULAR));
//elementH.getLocalMatrix().postScale(0.2f, 0.2f);
model.addElement(elementH);
EditorElement elementH2 = new EditorElement(new MultiLineTextRenderer("Hello, World 2!", 0xff0000ff, MultiLineTextRenderer.Mode.REGULAR));
//elementH.getLocalMatrix().postScale(0.2f, 0.2f);
model.addElement(elementH2);
return model;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("MODEL", imageEditorView.getModel());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.action_menu, menu);
this.menu = menu;
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_undo:
imageEditorView.getModel().undo();
Log.d(TAG, String.format("Model is %s", imageEditorView.getModel().isChanged() ? "changed" : "unchanged"));
return true;
case R.id.action_redo:
imageEditorView.getModel().redo();
return true;
case R.id.action_crop:
imageEditorView.setMode(ImageEditorView.Mode.MoveAndResize);
imageEditorView.getModel().startCrop();
return true;
case R.id.action_done:
imageEditorView.setMode(ImageEditorView.Mode.MoveAndResize);
imageEditorView.getModel().doneCrop();
return true;
case R.id.action_draw:
imageEditorView.setDrawingBrushColor(0xffffff00);
imageEditorView.startDrawing(0.02f, Paint.Cap.ROUND, false);
return true;
case R.id.action_rotate_right_90:
imageEditorView.getModel().rotate90clockwise();
return true;
case R.id.action_rotate_left_90:
imageEditorView.getModel().rotate90anticlockwise();
return true;
case R.id.action_flip_horizontal:
imageEditorView.getModel().flipHorizontal();
return true;
case R.id.action_flip_vertical:
imageEditorView.getModel().flipVertical();
return true;
case R.id.action_edit_text:
editText();
return true;
case R.id.action_lock_crop_aspect:
imageEditorView.getModel().setCropAspectLock(!imageEditorView.getModel().isCropAspectLocked());
return true;
case R.id.action_save:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE },
0);
} else {
Bitmap bitmap = imageEditorView.getModel().render(this);
try {
Uri uri = saveBmp(bitmap);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "image/*");
startActivity(intent);
} finally {
bitmap.recycle();
}
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void editText() {
imageEditorView.getModel().getRoot().findElement(new Matrix(), new Matrix(), (element, inverseMatrix) -> {
if (element.getRenderer() instanceof MultiLineTextRenderer) {
imageEditorView.startTextEditing(element);
return true;
}
return false;
}
);
}
private Uri saveBmp(Bitmap bitmap) {
String path = Environment.getExternalStorageDirectory().toString();
File filePath = new File(path);
File imageEditor = new File(filePath, "ImageEditor");
if (!imageEditor.exists()) {
imageEditor.mkdir();
}
int counter = 0;
File file;
do {
counter++;
file = new File(imageEditor, String.format(Locale.US, "ImageEditor_%03d.jpg", counter));
} while (file.exists());
try {
try (OutputStream stream = new FileOutputStream(file)) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream);
}
return Uri.parse(MediaStore.Images.Media.insertImage(getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName()));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

Wyświetl plik

@ -0,0 +1,10 @@
package org.signal.imageeditor.app;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.AppGlideModule;
@GlideModule
public class TheAppGlideModule extends AppGlideModule {
}

Wyświetl plik

@ -0,0 +1,12 @@
package org.signal.imageeditor.app.renderers;
import org.signal.imageeditor.core.Bounds;
import org.signal.imageeditor.core.Renderer;
public abstract class StandardHitTestRenderer implements Renderer {
@Override
public boolean hitTest(float x, float y) {
return Bounds.contains(x, y);
}
}

Wyświetl plik

@ -0,0 +1,138 @@
package org.signal.imageeditor.app.renderers;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import org.signal.imageeditor.app.GlideApp;
import org.signal.imageeditor.core.Bounds;
import org.signal.imageeditor.core.Renderer;
import org.signal.imageeditor.core.RendererContext;
public final class UriRenderer implements Renderer, Parcelable {
private final Uri imageUri;
private final Paint paint = new Paint();
private final Matrix temp1 = new Matrix();
private final Matrix temp2 = new Matrix();
@Nullable
private Bitmap bitmap;
public UriRenderer(Uri imageUri) {
this.imageUri = imageUri;
paint.setAntiAlias(true);
}
private UriRenderer(Parcel in) {
this(Uri.parse(in.readString()));
}
@Override
public void render(@NonNull RendererContext rendererContext) {
if (bitmap != null && bitmap.isRecycled()) bitmap = null;
if (bitmap == null) {
GlideApp.with(rendererContext.context)
.asBitmap()
.load(imageUri)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
setBitmap(resource);
rendererContext.rendererReady.onReady(UriRenderer.this, cropMatrix(resource), new Point(resource.getWidth(), resource.getHeight()));
}
});
}
if (bitmap != null) {
rendererContext.save();
rendererContext.canvasMatrix.concat(temp1);
// FYI units are pixels at this point.
paint.setAlpha(rendererContext.getAlpha(255));
rendererContext.canvas.drawBitmap(bitmap, 0, 0, paint);
rendererContext.restore();
} else {
rendererContext.canvas.drawRect(-0.5f, -0.5f, 0.5f, 0.5f, paint);
}
}
@Override
public boolean hitTest(float x, float y) {
return pixelNotAlpha(x, y);
}
private boolean pixelNotAlpha(float x, float y) {
if (bitmap == null) return false;
temp1.invert(temp2);
float[] onBmp = new float[2];
temp2.mapPoints(onBmp, new float[]{ x, y });
int xInt = (int) onBmp[0];
int yInt = (int) onBmp[1];
if (xInt >= 0 && xInt < bitmap.getWidth() && yInt >= 0 && yInt < bitmap.getHeight()) {
return (bitmap.getPixel(xInt, yInt) & 0xff000000) != 0;
} else {
return false;
}
}
private void setBitmap(Bitmap bitmap) {
if (bitmap != null) {
this.bitmap = bitmap;
RectF from = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());
temp1.setRectToRect(from, Bounds.FULL_BOUNDS, Matrix.ScaleToFit.CENTER);
}
}
private static Matrix cropMatrix(Bitmap bitmap) {
Matrix matrix = new Matrix();
if (bitmap.getWidth() > bitmap.getHeight()) {
matrix.preScale(1, ((float) bitmap.getHeight()) / bitmap.getWidth());
} else {
matrix.preScale(((float) bitmap.getWidth()) / bitmap.getHeight(), 1);
}
return matrix;
}
public static final Creator<UriRenderer> CREATOR = new Creator<UriRenderer>() {
@Override
public UriRenderer createFromParcel(Parcel in) {
return new UriRenderer(in);
}
@Override
public UriRenderer[] newArray(int size) {
return new UriRenderer[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(imageUri.toString());
}
}

Wyświetl plik

@ -0,0 +1,263 @@
package org.signal.imageeditor.app.renderers;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.os.Parcel;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import org.signal.imageeditor.app.GlideApp;
import org.signal.imageeditor.core.Bounds;
import org.signal.imageeditor.core.RendererContext;
import java.util.concurrent.ExecutionException;
public final class UrlRenderer extends StandardHitTestRenderer {
private static final String TAG = "UrlRenderer";
private final String url;
private final Paint paint = new Paint();
private final Matrix temp1 = new Matrix();
private final Matrix temp2 = new Matrix();
private Bitmap bitmap;
public UrlRenderer(@Nullable String url) {
this.url = url;
paint.setAntiAlias(true);
}
private UrlRenderer(Parcel in) {
this(in.readString());
}
public static final Creator<UrlRenderer> CREATOR = new Creator<UrlRenderer>() {
@Override
public UrlRenderer createFromParcel(Parcel in) {
return new UrlRenderer(in);
}
@Override
public UrlRenderer[] newArray(int size) {
return new UrlRenderer[size];
}
};
@Override
public void render(@NonNull RendererContext rendererContext) {
if (bitmap != null && bitmap.isRecycled()) bitmap = null;
if (bitmap == null) {
if (rendererContext.isBlockingLoad()) {
try {
setBitmap(rendererContext, GlideApp.with(rendererContext.context)
.asBitmap()
.load(url)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.submit()
.get());
} catch (ExecutionException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} else {
GlideApp.with(rendererContext.context)
.asBitmap()
.load(url)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
setBitmap(rendererContext, resource);
}
});
}
}
if (bitmap != null) {
rendererContext.save();
rendererContext.getCurrent(temp2);
temp2.preConcat(temp1);
rendererContext.canvas.concat(temp1);
// FYI units are pixels at this point.
paint.setAlpha(rendererContext.getAlpha(255));
rendererContext.canvas.drawBitmap(bitmap, 0, 0, paint);
rendererContext.restore();
} else {
if (rendererContext.isBlockingLoad()) {
Log.e(TAG, "blocking but drawing null :(");
}
rendererContext.canvas.drawRect(Bounds.FULL_BOUNDS, paint);
}
drawDebugInfo(rendererContext);
}
private void drawDebugInfo(RendererContext rendererContext) {
// float width = bitmap.getWidth();
// float height = bitmap.getWidth();
//RectF bounds = new RectF(Bounds.LEFT, Bounds.TOP/2f, Bounds.RIGHT,Bounds.BOTTOM/2f );//Bounds.FULL_BOUNDS;
RectF bounds = Bounds.FULL_BOUNDS;
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(0xffffff00);
rendererContext.canvas.drawRect(bounds, paint);
RectF fullBounds = new RectF();
rendererContext.mapRect(fullBounds, bounds);
rendererContext.save();
RectF dst = new RectF();
rendererContext.mapRect(dst, bounds);
paint.setColor(0xffff00ff);
rendererContext.canvasMatrix.setToIdentity();
rendererContext.canvas.drawRect(dst, paint);
rendererContext.restore();
rendererContext.save();
Matrix unrotated = new Matrix();
rendererContext.getCurrent(unrotated);
findUnrotateMatrix(unrotated);
Matrix rotated = new Matrix();
rendererContext.getCurrent(rotated);
findRotateMatrix(rotated);
RectF dst2 = new RectF();
unrotated.mapRect(dst2, Bounds.FULL_BOUNDS); // works because square, do we need rotated here?
float scaleX = Bounds.FULL_BOUNDS.width() / dst2.width();
float scaleY = Bounds.FULL_BOUNDS.height() / dst2.height();
rendererContext.canvasMatrix.concat(unrotated);
Matrix matrix = new Matrix();
matrix.setScale(scaleX, scaleY);
rendererContext.canvasMatrix.concat(matrix);
paint.setColor(0xff0000ff);
rendererContext.canvas.drawRect(bounds, paint);
rendererContext.restore();
}
/**
* Given a scaled/rotated and transformed matrix, extract just the rotate and reverse it.
*/
private void findUnrotateMatrix(@NonNull Matrix matrix) {
float[] values = new float[9];
matrix.getValues(values);
float xScale = (float) Math.sqrt(values[0] * values[0] + values[3] * values[3]);
float yScale = (float) Math.sqrt(values[1] * values[1] + values[4] * values[4]);
values[0] /= xScale;
values[1] /= -yScale;
values[2] = 0;
values[3] /= -xScale;
values[4] /= yScale;
values[5] = 0;
matrix.setValues(values);
}
/**
* Given a scaled/rotated and transformed matrix, extract just the rotate and reverse it.
*/
private void findRotateMatrix(@NonNull Matrix matrix) {
float[] values = new float[9];
matrix.getValues(values);
float xScale = (float) Math.sqrt(values[0] * values[0] + values[3] * values[3]);
float yScale = (float) Math.sqrt(values[1] * values[1] + values[4] * values[4]);
values[0] /= xScale;
values[1] /= yScale;
values[2] = 0;
values[3] /= xScale;
values[4] /= yScale;
values[5] = 0;
matrix.setValues(values);
}
@Override
public boolean hitTest(float x, float y) {
return super.hitTest(x, y) && pixelNotAlpha(x, y);
}
private boolean pixelNotAlpha(float x, float y) {
if (bitmap == null) return false;
temp1.invert(temp2);
float[] onBmp = new float[2];
temp2.mapPoints(onBmp, new float[]{ x, y });
int xInt = (int) onBmp[0];
int yInt = (int) onBmp[1];
if (xInt >= 0 && xInt < bitmap.getWidth() && yInt >= 0 && yInt < bitmap.getHeight()) {
return (bitmap.getPixel(xInt, yInt) & 0xff000000) != 0;
} else {
return xInt >= 0 && xInt <= bitmap.getWidth() && yInt >= 0 && yInt <= bitmap.getHeight();
}
}
private void setBitmap(@NonNull RendererContext rendererContext, @Nullable Bitmap bitmap) {
this.bitmap = bitmap;
if (bitmap != null) {
RectF from = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());
temp1.setRectToRect(from, Bounds.FULL_BOUNDS, Matrix.ScaleToFit.CENTER);
rendererContext.rendererReady.onReady(this, cropMatrix(bitmap), new Point(bitmap.getWidth(), bitmap.getHeight()));
}
}
private void setBitmap(Bitmap bitmap) {
if (bitmap != null) {
this.bitmap = bitmap;
RectF from = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());
temp1.setRectToRect(from, Bounds.FULL_BOUNDS, Matrix.ScaleToFit.CENTER);
}
}
private static Matrix cropMatrix(Bitmap bitmap) {
Matrix matrix = new Matrix();
if (bitmap.getWidth() > bitmap.getHeight()) {
matrix.preScale(1, ((float) bitmap.getHeight()) / bitmap.getWidth());
} else {
matrix.preScale(((float) bitmap.getWidth()) / bitmap.getHeight(), 1);
}
return matrix;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(url);
}
}

Wyświetl plik

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

Wyświetl plik

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
</vector>

Wyświetl plik

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M17,15h2V7c0,-1.1 -0.9,-2 -2,-2H9v2h8v8zM7,17V1H5v4H1v2h4v10c0,1.1 0.9,2 2,2h10v4h2v-4h4v-2H7z"/>
</vector>

Wyświetl plik

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M15,21h2v-2h-2v2zM19,9h2L21,7h-2v2zM3,5v14c0,1.1 0.9,2 2,2h4v-2L5,19L5,5h4L9,3L5,3c-1.1,0 -2,0.9 -2,2zM19,3v2h2c0,-1.1 -0.9,-2 -2,-2zM11,23h2L13,1h-2v22zM19,17h2v-2h-2v2zM15,5h2L17,3h-2v2zM19,13h2v-2h-2v2zM19,21c1.1,0 2,-0.9 2,-2h-2v2z"/>
</vector>

Wyświetl plik

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

Wyświetl plik

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M18.4,10.6C16.55,8.99 14.15,8 11.5,8c-4.65,0 -8.58,3.03 -9.96,7.22L3.9,16c1.05,-3.19 4.05,-5.5 7.6,-5.5 1.95,0 3.73,0.72 5.12,1.88L13,16h9V7l-3.6,3.6z"/>
</vector>

Wyświetl plik

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M7.11,8.53L5.7,7.11C4.8,8.27 4.24,9.61 4.07,11h2.02c0.14,-0.87 0.49,-1.72 1.02,-2.47zM6.09,13L4.07,13c0.17,1.39 0.72,2.73 1.62,3.89l1.41,-1.42c-0.52,-0.75 -0.87,-1.59 -1.01,-2.47zM7.1,18.32c1.16,0.9 2.51,1.44 3.9,1.61L11,17.9c-0.87,-0.15 -1.71,-0.49 -2.46,-1.03L7.1,18.32zM13,4.07L13,1L8.45,5.55 13,10L13,6.09c2.84,0.48 5,2.94 5,5.91s-2.16,5.43 -5,5.91v2.02c3.95,-0.49 7,-3.85 7,-7.93s-3.05,-7.44 -7,-7.93z"/>
</vector>

Wyświetl plik

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M15.55,5.55L11,1v3.07C7.06,4.56 4,7.92 4,12s3.05,7.44 7,7.93v-2.02c-2.84,-0.48 -5,-2.94 -5,-5.91s2.16,-5.43 5,-5.91L11,10l4.55,-4.45zM19.93,11c-0.17,-1.39 -0.72,-2.73 -1.62,-3.89l-1.42,1.42c0.54,0.75 0.88,1.6 1.02,2.47h2.02zM13,17.9v2.02c1.39,-0.17 2.74,-0.71 3.9,-1.61l-1.44,-1.44c-0.75,0.54 -1.59,0.89 -2.46,1.03zM16.89,15.48l1.42,1.41c0.9,-1.16 1.45,-2.5 1.62,-3.89h-2.02c-0.14,0.87 -0.48,1.72 -1.02,2.48z"/>
</vector>

Wyświetl plik

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z"/>
</vector>

Wyświetl plik

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12.5,8c-2.65,0 -5.05,0.99 -6.9,2.6L2,7v9h9l-3.62,-3.62c1.39,-1.16 3.16,-1.88 5.12,-1.88 3.54,0 6.55,2.31 7.6,5.5l2.37,-0.78C21.08,11.03 17.15,8 12.5,8z"/>
</vector>

Wyświetl plik

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<org.signal.imageeditor.core.ImageEditorView
android:id="@+id/image_editor"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toolbar" />
</androidx.constraintlayout.widget.ConstraintLayout>

Wyświetl plik

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_crop"
android:icon="@drawable/ic_crop_black_24dp"
android:title="@string/crop"
app:showAsAction="always" />
<item
android:id="@+id/action_done"
android:icon="@drawable/ic_check_black_24dp"
android:title="@string/done"
app:showAsAction="always" />
<item
android:id="@+id/action_undo"
android:icon="@drawable/ic_undo_black_24dp"
android:title="@string/undo"
app:showAsAction="always" />
<item
android:id="@+id/action_redo"
android:icon="@drawable/ic_redo_black_24dp"
android:title="@string/redo"
app:showAsAction="always" />
<item
android:id="@+id/action_save"
android:icon="@drawable/ic_save_black_24dp"
android:title="@string/save"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_draw"
android:title="@string/draw"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_rotate_right_90"
android:icon="@drawable/ic_rotate_right_black_24dp"
android:title="@string/rotate_90_right"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_rotate_left_90"
android:icon="@drawable/ic_rotate_left_black_24dp"
android:title="@string/rotate_90_left"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_flip_horizontal"
android:icon="@drawable/ic_flip_black_24dp"
android:title="@string/flip_horizontal"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_flip_vertical"
android:title="@string/flip_vertical"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_edit_text"
android:title="@string/edit_text"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_lock_crop_aspect"
android:title="@string/lock_crop_aspect"
app:showAsAction="ifRoom" />
</menu>

Wyświetl plik

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Wyświetl plik

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 1.4 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 2.8 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 982 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 1.7 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 1.9 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 3.8 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 2.8 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 5.8 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 3.8 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 7.6 KiB

Wyświetl plik

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<color name="colorAccent">#D81B60</color>
</resources>

Wyświetl plik

@ -0,0 +1,17 @@
<resources>
<string name="app_name">Image Editor Sample App</string>
<string name="app_name_short">Image Editor</string>
<string name="undo">Undo</string>
<string name="redo">Redo</string>
<string name="crop">Crop</string>
<string name="done">Done</string>
<string name="save">Save</string>
<string name="draw">Draw</string>
<string name="rotate_90_right">Rotate 90 right</string>
<string name="rotate_90_left">Rotate 90 left</string>
<string name="flip_horizontal">Flip horizontal</string>
<string name="flip_vertical">Flip vertical</string>
<string name="edit_text">Edit Text</string>
<string name="lock_crop_aspect">Lock crop aspect</string>
</resources>

Wyświetl plik

@ -0,0 +1,9 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Signal" parent="Theme.MaterialComponents.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>

Wyświetl plik

@ -0,0 +1,17 @@
package com.example.imageeditor.app
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

Wyświetl plik

@ -0,0 +1,150 @@
// Auto-generated, use ./gradlew calculateChecksums to regenerate
dependencyVerification {
verify = [
['androidx.activity:activity:1.0.0',
'd1bc9842455c2e534415d88c44df4d52413b478db9093a1ba36324f705f44c3d'],
['androidx.annotation:annotation-experimental:1.0.0',
'b219d2b568e7e4ba534e09f8c2fd242343df6ccbdfbbe938846f5d740e6b0b11'],
['androidx.annotation:annotation:1.2.0',
'9029262bddce116e6d02be499e4afdba21f24c239087b76b3b57d7e98b490a36'],
['androidx.appcompat:appcompat-resources:1.2.0',
'c470297c03ff3de1c3d15dacf0be0cae63abc10b52f021dd07ae28daa3100fe5'],
['androidx.appcompat:appcompat:1.2.0',
'3d2131a55a61a777322e2126e0018011efa6339e53b44153eb651b16020cca70'],
['androidx.arch.core:core-common:2.1.0',
'fe1237bf029d063e7f29fe39aeaf73ef74c8b0a3658486fc29d3c54326653889'],
['androidx.arch.core:core-runtime:2.0.0',
'87e65fc767c712b437649c7cee2431ebb4bed6daef82e501d4125b3ed3f65f8e'],
['androidx.cardview:cardview:1.0.0',
'1193c04c22a3d6b5946dae9f4e8c59d6adde6a71b6bd5d87fb99d82dda1afec7'],
['androidx.collection:collection:1.1.0',
'632a0e5407461de774409352940e292a291037724207a787820c77daf7d33b72'],
['androidx.constraintlayout:constraintlayout-solver:2.0.1',
'b23732edbb3511d937fea1ffef047b0e6c001b50c1921f0d959fc384d706ec6a'],
['androidx.constraintlayout:constraintlayout:2.0.1',
'ec15b5d4a2eff07888bc1499ce2e2c6efe24c0ed60cc57b08c9dc4b6fd3c2189'],
['androidx.coordinatorlayout:coordinatorlayout:1.1.0',
'44a9e30abf56af1025c52a0af506fee9c4131aa55efda52f9fd9451211c5e8cb'],
['androidx.core:core-ktx:1.5.0',
'5964cfe7a4882da2a00fb6ca3d3a072d04139208186f7bc4b3cb66022764fc42'],
['androidx.core:core:1.5.0',
'2b279712795689069cfb63e48b3ab63c32a5649bdda44c482eb8f81ca1a72161'],
['androidx.cursoradapter:cursoradapter:1.0.0',
'a81c8fe78815fa47df5b749deb52727ad11f9397da58b16017f4eb2c11e28564'],
['androidx.customview:customview:1.0.0',
'20e5b8f6526a34595a604f56718da81167c0b40a7a94a57daa355663f2594df2'],
['androidx.documentfile:documentfile:1.0.0',
'865a061ef2fad16522f8433536b8d47208c46ff7c7745197dfa1eeb481869487'],
['androidx.drawerlayout:drawerlayout:1.0.0',
'9402442cdc5a43cf62fb14f8cf98c63342d4d9d9b805c8033c6cf7e802749ac1'],
['androidx.dynamicanimation:dynamicanimation:1.0.0',
'ce005162c229bf308d2d5b12fb6cad0874069cbbeaccee63a8193bd08d40de04'],
['androidx.exifinterface:exifinterface:1.0.0',
'ee48be10aab8f54efff4c14b77d11e10b9eeee4379d5ef6bf297a2923c55cc11'],
['androidx.fragment:fragment:1.1.0',
'a14c8b8f2153f128e800fbd266a6beab1c283982a29ec570d2cc05d307d81496'],
['androidx.interpolator:interpolator:1.0.0',
'33193135a64fe21fa2c35eec6688f1a76e512606c0fc83dc1b689e37add7732a'],
['androidx.legacy:legacy-support-core-utils:1.0.0',
'a7edcf01d5b52b3034073027bc4775b78a4764bb6202bb91d61c829add8dd1c7'],
['androidx.lifecycle:lifecycle-common:2.1.0',
'76db6be533bd730fb361c2feb12a2c26d9952824746847da82601ef81f082643'],
['androidx.lifecycle:lifecycle-livedata-core:2.0.0',
'fde334ec7e22744c0f5bfe7caf1a84c9d717327044400577bdf9bd921ec4f7bc'],
['androidx.lifecycle:lifecycle-livedata:2.0.0',
'c82609ced8c498f0a701a30fb6771bb7480860daee84d82e0a81ee86edf7ba39'],
['androidx.lifecycle:lifecycle-runtime:2.1.0',
'e5173897b965e870651e83d9d5af1742d3f532d58863223a390ce3a194c8312b'],
['androidx.lifecycle:lifecycle-viewmodel:2.1.0',
'ba55fb7ac1b2828d5327cda8acf7085d990b2b4c43ef336caa67686249b8523d'],
['androidx.loader:loader:1.0.0',
'11f735cb3b55c458d470bed9e25254375b518b4b1bad6926783a7026db0f5025'],
['androidx.localbroadcastmanager:localbroadcastmanager:1.0.0',
'e71c328ceef5c4a7d76f2d86df1b65d65fe2acf868b1a4efd84a3f34336186d8'],
['androidx.print:print:1.0.0',
'1d5c7f3135a1bba661fc373fd72e11eb0a4adbb3396787826dd8e4190d5d9edd'],
['androidx.recyclerview:recyclerview:1.1.0',
'f0d2b5a67d0a91ee1b1c73ef2b636a81f3563925ddd15a1d4e1c41ec28de7a4f'],
['androidx.savedstate:savedstate:1.0.0',
'2510a5619c37579c9ce1a04574faaf323cd0ffe2fc4e20fa8f8f01e5bb402e83'],
['androidx.transition:transition:1.2.0',
'a1e059b3bc0b43a58dec0efecdcaa89c82d2bca552ea5bacf6656c46e853157e'],
['androidx.vectordrawable:vectordrawable-animated:1.1.0',
'76da2c502371d9c38054df5e2b248d00da87809ed058f3363eae87ce5e2403f8'],
['androidx.vectordrawable:vectordrawable:1.1.0',
'46fd633ac01b49b7fcabc263bf098c5a8b9e9a69774d234edcca04fb02df8e26'],
['androidx.versionedparcelable:versionedparcelable:1.1.1',
'57e8d93260d18d5b9007c9eed3c64ad159de90c8609ebfc74a347cbd514535a4'],
['androidx.viewpager2:viewpager2:1.0.0',
'e95c0031d4cc247cd48196c6287e58d2cee54d9c79b85afea7c90920330275af'],
['androidx.viewpager:viewpager:1.0.0',
'147af4e14a1984010d8f155e5e19d781f03c1d70dfed02a8e0d18428b8fc8682'],
['com.github.bumptech.glide:annotations:4.11.0',
'd219d238006d824962176229d4708abcdddcfe342c6a18a5d0fa48d6f0479b3e'],
['com.github.bumptech.glide:disklrucache:4.11.0',
'd06775a5171b777aa3db031eb0dd4a1dbe3f00dda35b5574dfd953f6b0d5ef18'],
['com.github.bumptech.glide:gifdecoder:4.11.0',
'197a1cd5b76855aa02b230c13974e293229b901dc2b96fab4315201e78baa804'],
['com.github.bumptech.glide:glide:4.11.0',
'5c294e6a5f0f812cef876b8412954c1822da184af38e082a5b766e3c4f4fcd95'],
['com.google.android.material:material:1.3.0',
'cbf1e7d69fc236cdadcbd1ec5f6c0a1a41aca6ad1ef7f8481058956270ab1f0a'],
['com.google.protobuf:protobuf-javalite:3.10.0',
'215a94dbe100130295906b531bb72a26965c7ac8fcd9a75bf8054a8ac2abf4b4'],
['org.jetbrains.kotlin:kotlin-stdlib-common:1.4.32',
'e1ff6f55ee9e7591dcc633f7757bac25a7edb1cc7f738b37ec652f10f66a4145'],
['org.jetbrains.kotlin:kotlin-stdlib:1.4.32',
'13e9fd3e69dc7230ce0fc873a92a4e5d521d179bcf1bef75a6705baac3bfecba'],
['org.jetbrains:annotations:13.0',
'ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478'],
]
}

Wyświetl plik

@ -10,6 +10,7 @@ include ':video'
include ':device-transfer'
include ':device-transfer-app'
include ':image-editor'
include ':image-editor-app'
project(':app').name = 'Signal-Android'
project(':paging').projectDir = file('paging/lib')
@ -21,7 +22,8 @@ project(':device-transfer-app').projectDir = file('device-transfer/app')
project(':libsignal-service').projectDir = file('libsignal/service')
project(':image-editor').projectDir = file('image-editor/lib')
project(':image-editor-app').projectDir = file('image-editor/app')
rootProject.name='Signal'
apply from: 'dependencies.gradle'
apply from: 'dependencies.gradle'