From 93e6ccb9e479aaa9a7cf3ea8561d1724364ee3ce Mon Sep 17 00:00:00 2001 From: Alan Evans Date: Thu, 9 May 2019 14:11:11 -0300 Subject: [PATCH] Replace image editor. --- res/drawable-hdpi/ic_brush_highlight_32.png | Bin 0 -> 1222 bytes res/drawable-hdpi/ic_brush_marker_32.png | Bin 0 -> 1198 bytes res/drawable-hdpi/ic_camera_emoji_36.png | Bin 3605 -> 0 bytes res/drawable-hdpi/ic_check_circle_32.png | Bin 0 -> 1513 bytes .../ic_check_circle_filled_36.png | Bin 1508 -> 0 bytes res/drawable-hdpi/ic_crop_32.png | Bin 0 -> 1579 bytes res/drawable-hdpi/ic_crop_lock_32.png | Bin 0 -> 1989 bytes res/drawable-hdpi/ic_crop_unlock_32.png | Bin 0 -> 1995 bytes res/drawable-hdpi/ic_emoji_32.png | Bin 0 -> 2993 bytes res/drawable-hdpi/ic_flip_32.png | Bin 0 -> 1893 bytes res/drawable-hdpi/ic_highlighter_36.png | Bin 1226 -> 0 bytes res/drawable-hdpi/ic_marker_36.png | Bin 1332 -> 0 bytes res/drawable-hdpi/ic_rotate_32.png | Bin 0 -> 2111 bytes res/drawable-hdpi/ic_text_32.png | Bin 0 -> 2201 bytes res/drawable-hdpi/ic_text_36.png | Bin 2508 -> 0 bytes res/drawable-hdpi/ic_trash_filled_32.png | Bin 0 -> 1492 bytes res/drawable-hdpi/ic_trash_outline_36.png | Bin 1800 -> 0 bytes res/drawable-hdpi/ic_undo_32.png | Bin 0 -> 2075 bytes res/drawable-hdpi/ic_undo_36.png | Bin 2330 -> 0 bytes res/drawable-mdpi/ic_brush_highlight_32.png | Bin 0 -> 709 bytes res/drawable-mdpi/ic_brush_marker_32.png | Bin 0 -> 744 bytes res/drawable-mdpi/ic_camera_emoji_36.png | Bin 1919 -> 0 bytes res/drawable-mdpi/ic_check_circle_32.png | Bin 0 -> 809 bytes .../ic_check_circle_filled_36.png | Bin 949 -> 0 bytes res/drawable-mdpi/ic_crop_32.png | Bin 0 -> 867 bytes res/drawable-mdpi/ic_crop_lock_32.png | Bin 0 -> 1039 bytes res/drawable-mdpi/ic_crop_unlock_32.png | Bin 0 -> 1063 bytes res/drawable-mdpi/ic_emoji_32.png | Bin 0 -> 1591 bytes res/drawable-mdpi/ic_flip_32.png | Bin 0 -> 1109 bytes res/drawable-mdpi/ic_highlighter_36.png | Bin 782 -> 0 bytes res/drawable-mdpi/ic_marker_36.png | Bin 830 -> 0 bytes res/drawable-mdpi/ic_rotate_32.png | Bin 0 -> 1203 bytes res/drawable-mdpi/ic_text_32.png | Bin 0 -> 1298 bytes res/drawable-mdpi/ic_text_36.png | Bin 1423 -> 0 bytes res/drawable-mdpi/ic_trash_filled_32.png | Bin 0 -> 835 bytes res/drawable-mdpi/ic_trash_outline_36.png | Bin 993 -> 0 bytes res/drawable-mdpi/ic_undo_32.png | Bin 0 -> 1204 bytes res/drawable-mdpi/ic_undo_36.png | Bin 1357 -> 0 bytes res/drawable-xhdpi/ic_brush_highlight_32.png | Bin 0 -> 1676 bytes res/drawable-xhdpi/ic_brush_marker_32.png | Bin 0 -> 1700 bytes res/drawable-xhdpi/ic_camera_emoji_36.png | Bin 5501 -> 0 bytes res/drawable-xhdpi/ic_check_circle_32.png | Bin 0 -> 2222 bytes .../ic_check_circle_filled_36.png | Bin 2455 -> 0 bytes res/drawable-xhdpi/ic_crop_32.png | Bin 0 -> 1928 bytes res/drawable-xhdpi/ic_crop_lock_32.png | Bin 0 -> 2420 bytes res/drawable-xhdpi/ic_crop_unlock_32.png | Bin 0 -> 2566 bytes res/drawable-xhdpi/ic_emoji_32.png | Bin 0 -> 4457 bytes res/drawable-xhdpi/ic_flip_32.png | Bin 0 -> 2672 bytes res/drawable-xhdpi/ic_highlighter_36.png | Bin 1783 -> 0 bytes res/drawable-xhdpi/ic_marker_36.png | Bin 1882 -> 0 bytes res/drawable-xhdpi/ic_rotate_32.png | Bin 0 -> 3013 bytes res/drawable-xhdpi/ic_text_32.png | Bin 0 -> 3288 bytes res/drawable-xhdpi/ic_text_36.png | Bin 3582 -> 0 bytes res/drawable-xhdpi/ic_trash_filled_32.png | Bin 0 -> 1782 bytes res/drawable-xhdpi/ic_trash_outline_36.png | Bin 2145 -> 0 bytes res/drawable-xhdpi/ic_undo_32.png | Bin 0 -> 3173 bytes res/drawable-xhdpi/ic_undo_36.png | Bin 3365 -> 0 bytes res/drawable-xxhdpi/ic_brush_highlight_32.png | Bin 0 -> 2761 bytes res/drawable-xxhdpi/ic_brush_marker_32.png | Bin 0 -> 2956 bytes res/drawable-xxhdpi/ic_camera_emoji_36.png | Bin 9888 -> 0 bytes res/drawable-xxhdpi/ic_check_circle_32.png | Bin 0 -> 4550 bytes .../ic_check_circle_filled_36.png | Bin 5046 -> 0 bytes res/drawable-xxhdpi/ic_crop_32.png | Bin 0 -> 3461 bytes res/drawable-xxhdpi/ic_crop_lock_32.png | Bin 0 -> 4276 bytes res/drawable-xxhdpi/ic_crop_unlock_32.png | Bin 0 -> 4494 bytes res/drawable-xxhdpi/ic_emoji_32.png | Bin 0 -> 8155 bytes res/drawable-xxhdpi/ic_flip_32.png | Bin 0 -> 4329 bytes res/drawable-xxhdpi/ic_highlighter_36.png | Bin 3128 -> 0 bytes res/drawable-xxhdpi/ic_marker_36.png | Bin 3360 -> 0 bytes res/drawable-xxhdpi/ic_rotate_32.png | Bin 0 -> 5358 bytes res/drawable-xxhdpi/ic_text_32.png | Bin 0 -> 5592 bytes res/drawable-xxhdpi/ic_text_36.png | Bin 6266 -> 0 bytes res/drawable-xxhdpi/ic_trash_filled_32.png | Bin 0 -> 3146 bytes res/drawable-xxhdpi/ic_trash_outline_36.png | Bin 3861 -> 0 bytes res/drawable-xxhdpi/ic_undo_32.png | Bin 0 -> 5730 bytes res/drawable-xxhdpi/ic_undo_36.png | Bin 6136 -> 0 bytes .../ic_brush_highlight_32.png | Bin 0 -> 4435 bytes res/drawable-xxxhdpi/ic_brush_marker_32.png | Bin 0 -> 4548 bytes res/drawable-xxxhdpi/ic_camera_emoji_36.png | Bin 14964 -> 0 bytes res/drawable-xxxhdpi/ic_check_circle_32.png | Bin 0 -> 7187 bytes .../ic_check_circle_filled_36.png | Bin 7994 -> 0 bytes res/drawable-xxxhdpi/ic_crop_32.png | Bin 0 -> 4865 bytes res/drawable-xxxhdpi/ic_crop_lock_32.png | Bin 0 -> 6181 bytes res/drawable-xxxhdpi/ic_crop_unlock_32.png | Bin 0 -> 6579 bytes res/drawable-xxxhdpi/ic_emoji_32.png | Bin 0 -> 12431 bytes res/drawable-xxxhdpi/ic_flip_32.png | Bin 0 -> 6175 bytes res/drawable-xxxhdpi/ic_highlighter_36.png | Bin 4996 -> 0 bytes res/drawable-xxxhdpi/ic_marker_36.png | Bin 5176 -> 0 bytes res/drawable-xxxhdpi/ic_rotate_32.png | Bin 0 -> 7824 bytes res/drawable-xxxhdpi/ic_text_32.png | Bin 0 -> 8162 bytes res/drawable-xxxhdpi/ic_text_36.png | Bin 9036 -> 0 bytes res/drawable-xxxhdpi/ic_trash_filled_32.png | Bin 0 -> 4373 bytes res/drawable-xxxhdpi/ic_trash_outline_36.png | Bin 5086 -> 0 bytes res/drawable-xxxhdpi/ic_undo_32.png | Bin 0 -> 8522 bytes res/drawable-xxxhdpi/ic_undo_36.png | Bin 8989 -> 0 bytes ...fragment.xml => image_editor_fragment.xml} | 14 +- ...{scribble_hud.xml => image_editor_hud.xml} | 80 +- res/layout/mediasend_fragment.xml | 1 + res/layout/scribble_activity.xml | 11 - res/layout/scribble_view.xml | 23 - res/values/crop_area_renderer.xml | 10 + res/values/strings.xml | 2 + .../securesms/imageeditor/Bounds.java | 29 + .../securesms/imageeditor/CanvasMatrix.java | 78 ++ .../imageeditor/ColorableRenderer.java | 16 + .../securesms/imageeditor/DrawingSession.java | 45 + .../securesms/imageeditor/EditSession.java | 30 + .../imageeditor/ElementDragEditSession.java | 42 + .../imageeditor/ElementEditSession.java | 69 ++ .../imageeditor/ElementScaleEditSession.java | 97 ++ .../securesms/imageeditor/HiddenEditText.java | 136 +++ .../imageeditor/ImageEditorView.java | 426 +++++++++ .../securesms/imageeditor/Renderer.java | 26 + .../imageeditor/RendererContext.java | 114 +++ .../imageeditor/ThumbDragEditSession.java | 68 ++ .../imageeditor/model/AlphaAnimation.java | 63 ++ .../imageeditor/model/AnimationMatrix.java | 136 +++ .../imageeditor/model/CropThumbRenderer.java | 83 ++ .../imageeditor/model/EditorElement.java | 333 +++++++ .../model/EditorElementHierarchy.java | 325 +++++++ .../imageeditor/model/EditorFlags.java | 116 +++ .../imageeditor/model/EditorModel.java | 435 +++++++++ .../imageeditor/model/ElementStack.java | 118 +++ .../imageeditor/model/ParcelUtils.java | 34 + .../imageeditor/model/ThumbRenderer.java | 73 ++ .../AutomaticControlPointBezierLine.java | 224 +++++ .../renderers/BezierDrawingRenderer.java | 144 +++ .../renderers/CropAreaRenderer.java | 133 +++ .../renderers/InvalidateableRenderer.java | 34 + .../renderers/InverseFillRenderer.java | 71 ++ .../imageeditor/renderers/TextRenderer.java | 204 ++++ .../mediasend/MediaSendActivity.java | 12 +- .../mediasend/MediaSendFragment.java | 29 +- .../MediaSendFragmentPagerAdapter.java | 7 +- .../scribbles/ImageEditorFragment.java | 376 ++++++++ .../securesms/scribbles/ImageEditorHud.java | 274 ++++++ .../securesms/scribbles/ScribbleFragment.java | 318 ------- .../securesms/scribbles/ScribbleHud.java | 264 ------ .../securesms/scribbles/UriGlideRenderer.java | 186 ++++ .../multitouch/BaseGestureDetector.java | 149 --- .../multitouch/MoveGestureDetector.java | 170 ---- .../multitouch/RotateGestureDetector.java | 170 ---- .../multitouch/ShoveGestureDetector.java | 201 ---- .../multitouch/TwoFingerGestureDetector.java | 189 ---- .../securesms/scribbles/viewmodel/Font.java | 83 -- .../securesms/scribbles/viewmodel/Layer.java | 141 --- .../scribbles/viewmodel/TextLayer.java | 94 -- .../scribbles/widget/CanvasView.java | 881 ------------------ .../scribbles/widget/MotionView.java | 526 ----------- .../scribbles/widget/ScribbleView.java | 270 ------ .../widget/VerticalSlideColorPicker.java | 2 + .../scribbles/widget/entity/ImageEntity.java | 83 -- .../scribbles/widget/entity/MotionEntity.java | 290 ------ .../scribbles/widget/entity/TextEntity.java | 189 ---- 154 files changed, 4655 insertions(+), 4092 deletions(-) create mode 100755 res/drawable-hdpi/ic_brush_highlight_32.png create mode 100755 res/drawable-hdpi/ic_brush_marker_32.png delete mode 100644 res/drawable-hdpi/ic_camera_emoji_36.png create mode 100755 res/drawable-hdpi/ic_check_circle_32.png delete mode 100644 res/drawable-hdpi/ic_check_circle_filled_36.png create mode 100755 res/drawable-hdpi/ic_crop_32.png create mode 100755 res/drawable-hdpi/ic_crop_lock_32.png create mode 100755 res/drawable-hdpi/ic_crop_unlock_32.png create mode 100755 res/drawable-hdpi/ic_emoji_32.png create mode 100755 res/drawable-hdpi/ic_flip_32.png delete mode 100644 res/drawable-hdpi/ic_highlighter_36.png delete mode 100644 res/drawable-hdpi/ic_marker_36.png create mode 100755 res/drawable-hdpi/ic_rotate_32.png create mode 100755 res/drawable-hdpi/ic_text_32.png delete mode 100644 res/drawable-hdpi/ic_text_36.png create mode 100755 res/drawable-hdpi/ic_trash_filled_32.png delete mode 100644 res/drawable-hdpi/ic_trash_outline_36.png create mode 100755 res/drawable-hdpi/ic_undo_32.png delete mode 100644 res/drawable-hdpi/ic_undo_36.png create mode 100755 res/drawable-mdpi/ic_brush_highlight_32.png create mode 100755 res/drawable-mdpi/ic_brush_marker_32.png delete mode 100644 res/drawable-mdpi/ic_camera_emoji_36.png create mode 100755 res/drawable-mdpi/ic_check_circle_32.png delete mode 100644 res/drawable-mdpi/ic_check_circle_filled_36.png create mode 100755 res/drawable-mdpi/ic_crop_32.png create mode 100755 res/drawable-mdpi/ic_crop_lock_32.png create mode 100755 res/drawable-mdpi/ic_crop_unlock_32.png create mode 100755 res/drawable-mdpi/ic_emoji_32.png create mode 100755 res/drawable-mdpi/ic_flip_32.png delete mode 100644 res/drawable-mdpi/ic_highlighter_36.png delete mode 100644 res/drawable-mdpi/ic_marker_36.png create mode 100755 res/drawable-mdpi/ic_rotate_32.png create mode 100755 res/drawable-mdpi/ic_text_32.png delete mode 100644 res/drawable-mdpi/ic_text_36.png create mode 100755 res/drawable-mdpi/ic_trash_filled_32.png delete mode 100644 res/drawable-mdpi/ic_trash_outline_36.png create mode 100755 res/drawable-mdpi/ic_undo_32.png delete mode 100644 res/drawable-mdpi/ic_undo_36.png create mode 100755 res/drawable-xhdpi/ic_brush_highlight_32.png create mode 100755 res/drawable-xhdpi/ic_brush_marker_32.png delete mode 100644 res/drawable-xhdpi/ic_camera_emoji_36.png create mode 100755 res/drawable-xhdpi/ic_check_circle_32.png delete mode 100644 res/drawable-xhdpi/ic_check_circle_filled_36.png create mode 100755 res/drawable-xhdpi/ic_crop_32.png create mode 100755 res/drawable-xhdpi/ic_crop_lock_32.png create mode 100755 res/drawable-xhdpi/ic_crop_unlock_32.png create mode 100755 res/drawable-xhdpi/ic_emoji_32.png create mode 100755 res/drawable-xhdpi/ic_flip_32.png delete mode 100644 res/drawable-xhdpi/ic_highlighter_36.png delete mode 100644 res/drawable-xhdpi/ic_marker_36.png create mode 100755 res/drawable-xhdpi/ic_rotate_32.png create mode 100755 res/drawable-xhdpi/ic_text_32.png delete mode 100644 res/drawable-xhdpi/ic_text_36.png create mode 100755 res/drawable-xhdpi/ic_trash_filled_32.png delete mode 100644 res/drawable-xhdpi/ic_trash_outline_36.png create mode 100755 res/drawable-xhdpi/ic_undo_32.png delete mode 100644 res/drawable-xhdpi/ic_undo_36.png create mode 100755 res/drawable-xxhdpi/ic_brush_highlight_32.png create mode 100755 res/drawable-xxhdpi/ic_brush_marker_32.png delete mode 100644 res/drawable-xxhdpi/ic_camera_emoji_36.png create mode 100755 res/drawable-xxhdpi/ic_check_circle_32.png delete mode 100644 res/drawable-xxhdpi/ic_check_circle_filled_36.png create mode 100755 res/drawable-xxhdpi/ic_crop_32.png create mode 100755 res/drawable-xxhdpi/ic_crop_lock_32.png create mode 100755 res/drawable-xxhdpi/ic_crop_unlock_32.png create mode 100755 res/drawable-xxhdpi/ic_emoji_32.png create mode 100755 res/drawable-xxhdpi/ic_flip_32.png delete mode 100644 res/drawable-xxhdpi/ic_highlighter_36.png delete mode 100644 res/drawable-xxhdpi/ic_marker_36.png create mode 100755 res/drawable-xxhdpi/ic_rotate_32.png create mode 100755 res/drawable-xxhdpi/ic_text_32.png delete mode 100644 res/drawable-xxhdpi/ic_text_36.png create mode 100755 res/drawable-xxhdpi/ic_trash_filled_32.png delete mode 100644 res/drawable-xxhdpi/ic_trash_outline_36.png create mode 100755 res/drawable-xxhdpi/ic_undo_32.png delete mode 100644 res/drawable-xxhdpi/ic_undo_36.png create mode 100755 res/drawable-xxxhdpi/ic_brush_highlight_32.png create mode 100755 res/drawable-xxxhdpi/ic_brush_marker_32.png delete mode 100644 res/drawable-xxxhdpi/ic_camera_emoji_36.png create mode 100755 res/drawable-xxxhdpi/ic_check_circle_32.png delete mode 100644 res/drawable-xxxhdpi/ic_check_circle_filled_36.png create mode 100755 res/drawable-xxxhdpi/ic_crop_32.png create mode 100755 res/drawable-xxxhdpi/ic_crop_lock_32.png create mode 100755 res/drawable-xxxhdpi/ic_crop_unlock_32.png create mode 100755 res/drawable-xxxhdpi/ic_emoji_32.png create mode 100755 res/drawable-xxxhdpi/ic_flip_32.png delete mode 100644 res/drawable-xxxhdpi/ic_highlighter_36.png delete mode 100644 res/drawable-xxxhdpi/ic_marker_36.png create mode 100755 res/drawable-xxxhdpi/ic_rotate_32.png create mode 100755 res/drawable-xxxhdpi/ic_text_32.png delete mode 100644 res/drawable-xxxhdpi/ic_text_36.png create mode 100755 res/drawable-xxxhdpi/ic_trash_filled_32.png delete mode 100644 res/drawable-xxxhdpi/ic_trash_outline_36.png create mode 100755 res/drawable-xxxhdpi/ic_undo_32.png delete mode 100644 res/drawable-xxxhdpi/ic_undo_36.png rename res/layout/{scribble_fragment.xml => image_editor_fragment.xml} (50%) rename res/layout/{scribble_hud.xml => image_editor_hud.xml} (68%) delete mode 100644 res/layout/scribble_activity.xml delete mode 100644 res/layout/scribble_view.xml create mode 100644 res/values/crop_area_renderer.xml create mode 100644 src/org/thoughtcrime/securesms/imageeditor/Bounds.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/CanvasMatrix.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/ColorableRenderer.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/DrawingSession.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/EditSession.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/ElementDragEditSession.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/ElementEditSession.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/ElementScaleEditSession.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/HiddenEditText.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/ImageEditorView.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/Renderer.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/RendererContext.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/ThumbDragEditSession.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/model/AlphaAnimation.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/model/AnimationMatrix.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/model/CropThumbRenderer.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/model/EditorElement.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/model/EditorElementHierarchy.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/model/EditorFlags.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/model/EditorModel.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/model/ElementStack.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/model/ParcelUtils.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/model/ThumbRenderer.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/renderers/AutomaticControlPointBezierLine.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/renderers/BezierDrawingRenderer.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/renderers/CropAreaRenderer.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/renderers/InvalidateableRenderer.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/renderers/InverseFillRenderer.java create mode 100644 src/org/thoughtcrime/securesms/imageeditor/renderers/TextRenderer.java create mode 100644 src/org/thoughtcrime/securesms/scribbles/ImageEditorFragment.java create mode 100644 src/org/thoughtcrime/securesms/scribbles/ImageEditorHud.java delete mode 100644 src/org/thoughtcrime/securesms/scribbles/ScribbleFragment.java delete mode 100644 src/org/thoughtcrime/securesms/scribbles/ScribbleHud.java create mode 100644 src/org/thoughtcrime/securesms/scribbles/UriGlideRenderer.java delete mode 100644 src/org/thoughtcrime/securesms/scribbles/multitouch/BaseGestureDetector.java delete mode 100644 src/org/thoughtcrime/securesms/scribbles/multitouch/MoveGestureDetector.java delete mode 100644 src/org/thoughtcrime/securesms/scribbles/multitouch/RotateGestureDetector.java delete mode 100644 src/org/thoughtcrime/securesms/scribbles/multitouch/ShoveGestureDetector.java delete mode 100644 src/org/thoughtcrime/securesms/scribbles/multitouch/TwoFingerGestureDetector.java delete mode 100644 src/org/thoughtcrime/securesms/scribbles/viewmodel/Font.java delete mode 100644 src/org/thoughtcrime/securesms/scribbles/viewmodel/Layer.java delete mode 100644 src/org/thoughtcrime/securesms/scribbles/viewmodel/TextLayer.java delete mode 100644 src/org/thoughtcrime/securesms/scribbles/widget/CanvasView.java delete mode 100644 src/org/thoughtcrime/securesms/scribbles/widget/MotionView.java delete mode 100644 src/org/thoughtcrime/securesms/scribbles/widget/ScribbleView.java delete mode 100644 src/org/thoughtcrime/securesms/scribbles/widget/entity/ImageEntity.java delete mode 100644 src/org/thoughtcrime/securesms/scribbles/widget/entity/MotionEntity.java delete mode 100644 src/org/thoughtcrime/securesms/scribbles/widget/entity/TextEntity.java diff --git a/res/drawable-hdpi/ic_brush_highlight_32.png b/res/drawable-hdpi/ic_brush_highlight_32.png new file mode 100755 index 0000000000000000000000000000000000000000..96b0c5fbe68cfa017d3a0c06eadd583fa6108f0c GIT binary patch literal 1222 zcmV;%1UdVOP)Px(fJsC_RA>e5nOjI4R~X0BCTY?(*fyzln~-$FipCf(wXDWQ6QNK_lcyG9tC$D# z>{AqM(i`+mAC}fU2E?fK`r-wIkU~N5F-Y^0Ze0M#bwM zOOdEHXxPelz)b`GW$6{^H7O-3e&Y}Z{I@-!Fhe(vhyNuFFeHOLxY{$8Q!C z6nNG4mh`HGGj6i#_0Jmc^!`EVZ7H*-r{}AUjg3c7q81K^f6K|qIj?Icr8gydDIuKr z3%nwK-M}v{E>6jZ2!71W%-oMU;T8NFiQq(B_}SUnKeDs4ziex33)r2=&CM+p{Bem? zb8Xzlg`b<73;O;3PXzdZbhf*@yTLd?I;Ewh<*NONL@GIMapC9Z=YKCQF8)YV8PW+U zQ@YUG+k1;t!utC9uBpuV~SzYFgZRhsmUlv!9NrM@SUBVH`JakF_4*d9kG7}Us_svVPRq6fq`#tZ~sQLrzLua^l@Y= zeV*`V1Wj78Ix_?Dw|CW^H#`IPbtwtIQ@14}A04pdd@^lzN*8nef1NfDqU8ZA?B*i1 z%{-rQY4hKLXQ?;!ysAo5m?dQ7$$ge`3Mxw5%#MzZukG+fMMWR0ow_CA(nd_yGEOl? zQI&3w{Pgs6C@(MXGqsb??@Bn}CFfO`#nv{C=e$@fV>zcLIaXg^Uv45#;Waoo*r)bS zr5x!!$(JYtRxFk=WfJ|v(&@3Wv0nkVo1AFXwKB<1DkW0n#bo6^TO3DgYiqv{xb@*} zcYxpea{4(dE2~Q1w?WS7CAU^spzX%sr7HAJOicU&+;*nDoq4VSuMhNZ^^9vdZyW%g z^hrrgO-)~0TbtYt-n0YX+S>Y^+wkN)@azN}l9*Z2tE;O&Us+iR8`#(*@GUJZ-|Jpi zBX8;)@}7Zvyt1Seap$o$$K7;r%c!0uc@iII6OT3gUxA9q8}x59q#A68ran8)(NPu6I9UCWWYX z*htFIs(X24WaPHCz5m1!ZF%2Qd%i@$W(KK#x?@{KjA%0Wh%99@&Y%Mg4GkGnQ&ZtU zAP~~|lJroDNIU*BPWSAJZRG%MMmT~+^KD&vBmvL=uw1jP9I(R}M>x_m#(*a3 kuEHCbb%7 literal 0 HcmV?d00001 diff --git a/res/drawable-hdpi/ic_brush_marker_32.png b/res/drawable-hdpi/ic_brush_marker_32.png new file mode 100755 index 0000000000000000000000000000000000000000..8c01ce8868fe6c2a71253acc3c6e0e04f4ae1b6b GIT binary patch literal 1198 zcmV;f1X25mP)Px(Xh}ptRA>e5SzAj~Q55c~)pVH|3)4(=6dN+A7flH%aA1T2%L|1_;zNUI4-yF( z7(_!aDhPsaLSzUbh<_l(4D&(7)E>;PRcYM z{u5Xyd)Bp-X^_}%AjAW~fkY|1w%1dV@UjO^l$3Qwa4;o>^O5iYKpPtyd$OUSA*;N+ z`~uo1fJl~&jg2>YdU_tVw6qk2goK1ccL<=tfr=P!xR8Vvh{?~-&zPH=`?&U7T&=CG z&$L=?*3i&UheziwMn*W+pc3*lucS zDo4MQ09Q`YRgjUlSS(i;78b@y3`W?xy1HJo?oYbAyPtq~44?rNGeD3J#iVY}7Z(?2 zEiNujk}Qn)o|&0>-(WD@L;Z(81DczgA7BhcS70M~LuqMg4#-cFD9YKKoSeJy@$n_2 zqobewk)N2D7}RJq=U~7wfX+~41(MAJWuizZZzI-BK!OMtC9B$j7DR@`1rWE>vBH~7U%)Y^OuU;GSK@IhW|exot*xyIdb7!7x?Ejd zeN(5?ok5$YW_%A&^z;Dp`4n%;#7oJg<>h6Y)Bx6ddwc8A^Ax}%aXr9LQ|#OZb9qI4 zT<|JT5i6jntE;nwhKAC!UYVbt|Jv8r_Y#VE;0M4D4=%vx7Zm6f7kW~ko}Qkxy1Hr? z-bdZh(b4fVDk|zct}|r#_7xDXV_v`FHUJy8#6x~{czE~)K1gJvS0cc$A$bw+T(N+O zuMi@cm4ShQZoOXrxW2yrRZUIJ7wGK30X?ZHNK|Z4)ev{H-^7nE12@qv_?Msuwv7jV0mN1+c-J|_bN~PV M07*qoM6N<$g1GTO1^@s6 literal 0 HcmV?d00001 diff --git a/res/drawable-hdpi/ic_camera_emoji_36.png b/res/drawable-hdpi/ic_camera_emoji_36.png deleted file mode 100644 index 2be395fcc1a5cd1003653493493778796729e1c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3605 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 P00000NkvXXu0mjfdO_tj literal 0 HcmV?d00001 diff --git a/res/drawable-hdpi/ic_check_circle_filled_36.png b/res/drawable-hdpi/ic_check_circle_filled_36.png deleted file mode 100644 index e00b6b5674a616aa5c555f29abaf4c38e2a67765..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1508 zcmVPx)o=HSORA>e5n$J%iRTRfjs#ShO?NeeGw9&Fb)0mjX=)zcRf!K{9VJUINo&^4b zZY5R}HDXhKiG&0QA&?Lup$UmBWMgH+LRUpYq6YH73e2P551Eq;!<+YJ=FOwzg_E4T znLGEM^Znj)@45HRo3gSqIqQK_(F0Ev0R=WqG5>UckBnP>pkLE~s?m#+B4$J&ftE|p zxxZFsz90c9)RFGHzgCtANpmLKv4r+sBG2glyhoqaHDwT`9%6*{biFJ6-=mayi9#}# z#3e>Ml&ApwIcbHoN?O_3+4*KmOUw0|nwrPlZ2U1fIl0)~-My+u+tM^uq>rRVGLZ<%US6T+A@scTg7lK~YFAg+Co3x}6I)wb ze;z~>+Rzpo*m7-R8z19Cfd$yaHa_s>`owplXDNY!<8bhO2pM|oKURKOQLg`v(zPPg#|Qa1dq z;9z%mHywbXXvO$+$q_lGf(^@9%ou`XBqr}=hQvum%HK=)c84W%4oqN+l}v~h>GmR% z_$20(pN#(=3~oXpBZCc$k%XQg+$4*7GL+xRlez~Bm|SdNj1)DtK$X%2W&- zEbcnT#sG|94J8(>lxkmP!Hf%{Sna?BHYpfGM~!jIzOR-oP7*tcqzQt_-G0@&SVPS< zvds(9diHNgg9>5KSz229S@m*m(ZB{q7b}=^iVedW)w=cs(!0~w*Y}NlxApY&3@9?0 zppF0=7^Pr6HXQvSgcy_YJV%e}>grc@eNvJc8XEely}f-}4%6l3<(%6B1#Dnc1$ISX z&Y2ylz~Wb@;czdgw~A2i3=R%{A-|2%W)b{aK5`C4Fn|%PQZVPtjyz<`^2XZQ+WjIB z$Y#<=-IU+P(b3UfRmw{WLtq4}i#aDT&OI#3Z)uhPEgOo2%ZwC}Y8)FIBT|9$%I_PD zV0AHrJy3Y~vh?lE&CPYcp)B{IGFX;&6dfToK0f}f%0iREfG|D;tBW}=u~$^_+TPyY ze>4sfG8UOjb=$~fsuybbxb}{anwXgQPUVqEVF!$0m4Z1mu^ksg)*p!V_V(VD!4~N) zCci3%A$Nq-)YR1XSsjEZ6fs`>geGP~@nHztPJe&@monZYy{T+=Cl5IAN9( z1XhVU6fJo?2()%|yRb@^~Oyp^}F;-7iLP^Yl6 zJ+{D-;h4lh)6x5h`#SCZk`rN!hgw2o9W-q?a_latR|7{xOyb0B6>W3eu&*Kd%s z)L&9BOd&?p$dD}9_KN$j7;`<5CP}{H7N5hYv958dE}1_iAcim`OYUzZh%qF+65EyNIu97k{xN=f{=4lxskCE1c4HS64|{2YQP#1Yz|5F~;@AF#Zh=L44C zi}e9ZTw>yKD6}VnY{85q8Pt?H32~lN58>6dBR!R$90AZP7D2#!i5elwtP>A(4LKv| z{dS5no}&ecIV;GBud$Id+ZHKbwL@Z*8Igj?_#K?xpY^~g=z+)C29D9^xBdA50000< KMNUMnLSTZ4OVio_ diff --git a/res/drawable-hdpi/ic_crop_32.png b/res/drawable-hdpi/ic_crop_32.png new file mode 100755 index 0000000000000000000000000000000000000000..f0b4e36b6dc307db6cc7f3de96a42ff5fa276893 GIT binary patch literal 1579 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 literal 0 HcmV?d00001 diff --git a/res/drawable-hdpi/ic_flip_32.png b/res/drawable-hdpi/ic_flip_32.png new file mode 100755 index 0000000000000000000000000000000000000000..dec80d99818e712142b1989a41f709a3acf7d95b GIT binary patch literal 1893 zcmV-r2b%baP)Px+A4x<(RA>e5Sba!UXBgM(=lxQ%(j0!x>6GdE03}hjB&TgoqM6K3@Uom{%4S4= z)E`105ER&qH9@nLUjx~~_D?K=*#42yLK%!r7?_hmMa@>~Rj;<+?{MD3QLcLKIa)A$ z;JNoX?|Gm1`F`K$JziexuR#ckVcnl9IylYy(<$ z?AWn!U|_&eUS9qdo`ZpbKpI58*A7DY4bUWhe0==Zmw>*$zD7L14UC2I4IF#$;K5IL z-U^HWnt_HLXm|lx38sy$x3{-2I5;>3G$9Pg2$=o+{GvG!9Uc9_kt0XaL56S~XgCT+ z4WRd_MBoNMc6N3xXbEO!W<)*s&(6+@S~Jzv)zx4^D9{R|;f8cD#4HP^qPCu%o^qSb z771E{xw$zSCV3dyqvU#QZ0z>ar%%6!cdUf~F$e#;z=#3lrGn<<`ApbuBtqEYL_l+AjMg|85Z;>Gt5QQG{V)rWAxpU_mAVn=uC(TB9VgMKAw#hywsHUc-9twHF4>k$d$i1kpuD*n# z9!FZ)E?&Ioz!;-o0n$NhW&jtroIig)Gb$=76SPMlM}S@E)V+K69%4gk;{s^*_U_xa z?@f?)pht(BRu8JZA6!~mT2H|`frlBRFi}!c(mpvk`M1er3OIA-OeMy+BXLL590jcg za2^ZH+R@SRQCL{myP)*~4>c(YV`F3gpdP;ALWzlqIfo7%N(RX&Xl}Q)7(nlHUZB6f ze{g<&ejR9|KqF>>6FAU*c=qhsFw)EC=+UFq7-JMz3z}LCEe3E7w@TZ!YuAcGLPD6U zMnOcui9&vU{rdGLE{H}iz$kEAWfWdCH8p*OMsF5%7T4X~y%%HZD7e+t?I0MbJoC>| zSXdahZQHgY&}#*v7A6}T8-E`j9`2=}yu3We=FOW$yG=(5r!LULodKN4afZ%*;>3wM zgp)hMS^*6pN-f6m196a1aEi5o%u>r#S3|Y|O!-wl}%+r`x0ZJ4O9z58J z^WiD#E~KTUr5wU(fZImTodFD$6}?GXTwGih=vM`d0$U7ce}Df&eBHZ5!D(q}g}J%8 zQ6R;ohdL`!P#eHOZkzPJ9fu1WHf17c!ysSuDU))DjIJ8_PBLQu{{7!gOiYZS{>k$M~+A z2vXDnjhA4t0n*lq2I~tkLGQoZ`!g*RkPVB*BPPa`8Ey>NYfA78#>aC>`*d2S6L|2#f-FuaBVpHQ4wWD4jE2ngU7 z>4mWn+`e{`)&bt}@$uA+j!{4z0d8Y1+_t`NYisj^AxYEI(|+)Tl5YyvG6X%3d#(!~ z;eNrie}OY2BO^bP1-Gw&`T2R1oL(GS5f}|d>d~V|e_&hh0|VO*#R#REG03n`S>_lm z6`whjaA8afi2YndfN8?o;(9D#%23P2=300000NkvXXu0mjfMlg3) literal 0 HcmV?d00001 diff --git a/res/drawable-hdpi/ic_highlighter_36.png b/res/drawable-hdpi/ic_highlighter_36.png deleted file mode 100644 index 586aa32d0ba27ec6494fedd954c425b76530cdfc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1226 zcmV;*1U37KP)Px(gh@m}RA>e5nM+7iQ5eUqw9?+uQ%y|}$4nh%Gzv8EhF(*_k%y@cigxLUhWjdd5=J)uxpT*}%5KRVr8&{qsOB z$gS3Y3vL@;mc(0*t)v>oCz0#cjG=y(XU4~hy43riaq7^t70pa0z3+xrY{ z3D8j}3?jU2nFg1Zn-(fMG&Ju`EbRg$P}$MZ@f1Mu&;dw{Jyhi}e<;(~*w|YY#@*W5+Aupi z`(*{VGGIhNOiBJ9X>3)f`uh4u@bt3TY%T}{=X5$9cpd}of|!m{*s4&7R4KenhE745 zIXO9Z{o%&P$6w>w35Z})L~K>4wzjtWaMS>WLrk?K=xTFwbCXC(o6R<0GMO^aei+&T zZ8+Gkpi1E+Cxv6sAt(wm)zs8H29%p%gfbe9=h04Rk%k-kJzFbOBpgp^Y;1fepr)p# zKB`bmL9R;pG2hT=trd#VNN#FsD)WOnhjs%0J5Z^qsb_U4^uT)BUr9ebQtKHa^?&P; zLPrFg{q*$H)9=rE;J+AC>Dv7i7PO`4EA85EQ;aDtJh@i$ZRbZvN8fRw3Ujx#v^>Bw z9=?bL?WTZ&zsly0tLq4yQDkTiUfi{{wU5!B260`-RXWRMYd_g$KlrGusJRc~ekiHC zySw3MpuFDc>FLSD#Kdg06D&qmivNOEMkuBrx8hu3$L8kdnmrzmOMtP&p2-5oui<$* zlpr@z#Uq<|kn(C{4k^!I%2```-kDvs$g4IHQmV#qnax6(RIlvd61xg)}QY;w_LUMLv$u>9SRP`ODlsEZ-z~HOTw2)#P@gd>7 o8nI0`y$AFj(0f4d0cm^S2N~sXO%NhGsQ>@~07*qoM6N<$f;S*W5&!@I diff --git a/res/drawable-hdpi/ic_marker_36.png b/res/drawable-hdpi/ic_marker_36.png deleted file mode 100644 index dde1357bcb29747c95c151e5baf4c96a47c9cde9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmV-41Px(?ny*JRA>e5np;R5R~X0BYuc`^HmgliXlk*T;n8q}uM) dseMtrfL76}ctNdHijXIXR`Jp*QG&OsyRN(a|HnD*x`xcA zQ08Qr5B|>CnKLur?|kPn=Nu0lFw7_cqXdi+FiOB(0?)XUQm4HAbZL3(eS=p1|LZ#a zpq^DF-Xj2>Q?K(p&uyz>TI4~}ZO^-tx}^lr3-I7YRRnZG1YnxiD4HGGfHolqMB4|) zlF-u#MIR1A0gxp-J3A&LBjdf%(NWvN!oo{9XHH2;IbKmw@kv@*+PQ#$fPaRDhSqRi zGiu1AixG-7#snRKPW1NnmN}hHhYPl{vND^Llw{4%&;P<^v#s(R&EartR904|A^#id zy?O@+Zn(`GDjHC?cU*V>1>8fs-EMQA*-0%eEluE2??6G249!U)^M*Rv*VlJTI6pBl zasN>;;<|d=4h{~E#nWDeMB7syuGgQ(LZMy#fi`rty1M!oFOWSymzS5P0T2mE5wXWY zjg5^B2L=XS%FN6x(TLb~RaMnBK)ngEed^lA2t@}(M-lB={Rm|?n=fQ#Wqq}^wY9k? zJbQm^*VotIz;hU_LlB1t4hOm!U(T-kH7M#)P&qj{g<4Q`b#+C!KN>m=y$rFiSZKN! zU(5#1_7FZeI9MivAR^@p6e3lO`%glIdIi!I3h!5{3J2g&j6WX%%1N;C@$uhT{d|FH zXlVEv_Y;caofJ^;LjhB&;mF9ybwW)}PW}d{^FBa18yg#M;u+FG5sX!ljr>q?aq$PU zv$MZq3`)w)%`MPqQ-t~k_r*X`MGF2X#*Twv98BMa&gSLieW?Z2)YSAX@=6OOx_S0s zEcMvJ!onOMph`WU#8{n(63$>X zX?KN|6G(6C>FN3DX@Fv+SOvLuaSUJT7rj9|e`CQ$dMI%0PVYHcJeHiCe9mIAypK(T zKRsbY8c;tYpVZY)K#3V}IM&z;*4NkP0e3krF7EQ;;^MRb;&EVLp!#Wm5|c%xvq(=* zPvLF{0ajO67ZMW_uf)g4e~iVM!L_xuzW~iO3a>BVrk=;OccCaK4C2_vB{J!{bojJu>@dtwcx`QMfdKM6&dkiT;`&<0XhW49NABEn*M8s5J*tW diff --git a/res/drawable-hdpi/ic_rotate_32.png b/res/drawable-hdpi/ic_rotate_32.png new file mode 100755 index 0000000000000000000000000000000000000000..e01fe3696721a0fe62ff9f0d57234294caf00eb5 GIT binary patch literal 2111 zcmV-F2*CG=P)Px+`AI}URA>e5nR`gpXBfwi*EGvkY8T6uUA*P299_oNA8pxcjmRh>WbKbA|5>}x z8nGf8+bS3Y)z+$k2nz!Hqc#Y-U@dCJLSvI)W+S_(m8It0bM)B0pC9LqqdPb4U=DiV z>-+n?m*;)1@B93YHrxN4LIyy7_dT8ldp~#P!Q>5J5GsVZo)O+Dbi1JD`3dI1CL?^f z7)J{+uGZ{@0zvZx778XA;UmNp!AGuNzdoa(q2buBUAwaM9wnd{^9CK6kQpM$MhcTx zuU@^RwYBx`Q&C4p$KA}#%p~>Wm0%lAET5kcDpElBDJxg5e80K5xeDRCy1Lp63k%n& zKT#Men7q*A;2^9|*o+V+uUN5SSyNL}HNtmxc6RLCx$_J4zb@bb=9o}I=|K@r2tsI# zCv1%H_wV1ow`$d@?ds1J<_noZvM^S7MZg;<{=yX@B!&x9pFDX|f#nT39FC60#>Scl z4<3}2mzSSVD1DZclr&p&Q-$#YA&2rLH;TLvLV?)C#Kbha-Cl2m_tq+`S}Q6lep$0- z&0?)f5%35GAcy+o4K@x2v1yo+He%ekaaGyb+3$pghK4JIs(0+zQF!s<#p3Gf>XL|v zh{oZ=hmVSkjEs$oi%ZST&0VQ{i9dJlTzOqx9hV#k>OB#tawvfHMhU5V_U!qDlLrs9 zx3@RxF8EyiIl>!KV%~uR2R@a+e;W_g*VmWl<>f8WIQcG>(&qH7Z8%L$u24?`by!{>{7ID_wLRBCAeG zNtrBB@Df($PDtOlapM|=-aV9%qIK)mty`-8R|Rq+Xty@PS#hqGV-H{VmGt0vgWCOoNLZ=g_02*f!Q!t zz=CW%S{UO22#N3$1&+!Y5@@d46oIi}0{pNp7aIJgZQ8UckJAZHT)%$3NPVnjjJe3+ zk$jy(MtH2ng@f?KChn)j%AUYHfS_1=$is&Z)$}MIs75($04LAWD_5>G&6zXDp)h+h zAt529wzl@Sl9G}~8grOAY6B*OH%W=Lr*7G@CHLC3YlW&TD-;sV-QC>|tmTiKPNzcK z-uU?OBsFX#CKjLuV_5D&cwi_U*IkOB0yq(+e8^4-t1* z-g57$Q>VU>ARYdM4P;!()E_;1^keZ(7VseZARt~%J#ys8cKB#NhdeT0eS{r~ddvkZ z?TL)_M;$zP@V)%}{O>g>Or`MydEr!5RaK>uu0@{c(uL*q<3wHx(WMnWOf+G_gk)WC zi(_J9#!5bi3cR)3wr#s4z6}Clf)a5mGm>xJx^+4{JUsfui4)s(+5N13LaALKB&(V!=rPfO*WH$$I#}ucoHvcUM1_XFohaxXw`cTx3pV zWo5D6NoG9dD_=F-lW^JC<;$19BR=w`)4p`+(iQ4U7dUy`laxdyhI@m4Kr$l$p^yO| z_zCSwSc*C>KKC$6JAeNCk0>BzZ)%JR)|^Iq>`5NuN>k{M(DgoxXC>f`lP6E!(Q~8F zEVK%30&WEz9$?0p*CI3tjpB0`ehR&)&6_u8sSoS3pE;2_Ra#ibmXbQoHRerDkBJeY zMIcOZh$n1qZEeILLfVB+fuqkHgMqfJW4+zQ&o)A&cS6Gm2w#U3tWj%I{)`wsn(M~< zj{s&NlibNtA}lP-8kf5f-U#hAY26w0dS;C|`^C=UXN!u8;&L5rgCbjT`9h4_Q2PIw7b{VTARqJzUJ#r+x3_a5XkgnG;zm=_}~yP#QFBN#vp77}biZM3<-JjjM`}`OzKGw!Q z70^XyZKmshc{~SYbDjT&k9*Sg*%B=9r+_uC4b9ISy!%|^LkfiE;tF%|v*||mdc*qQ z(__fnF^XlLox9P|(Nu%fMO2LlVU9TF`6J^w_G0}I6={^sHhlxTmnd}gnLJt32;X(# z!i6$8#>dB}PM+nnl+Ji1P*C$wR>$fCKLLJvb`}&Al&ZxG7%LECXj))|rKrPr*MH?JQ1PToR@ z5TW#Kxpe8$PdPa`U+Rb3?5kI=?mu(p%rX7!@sEBrXx1ktHHuA1?$LUZGeqGMIcCh5 zVfydP)J2OHtx|c60i4H=AOAru-xU;U&%#yDK_Nnmm?u`#OG`@&B#aZwJufM7?Pt%P z{aSpd2v{F)dkSTB`zI388(~%8Jbd_YNo;IvseW0utA>x!@fty?E%LSA;;Xx)Q$n}t zpB{Jg|AAlk@8AFJh7B7|Yw(G{R~ugJw+A>Oyb)tq1`FX05|?D;nb2d**Ln>Px-Q%OWYRA>e5msw1eM-;~|JD1`DrKo@kidI>zN{tE%*j-bjOC+6No8 z#-vtFZJR!rSRYKPaf#7tU801>Hd^aaca5na2yWGgA_%gt{r^7in2*H^Pqa<$N&a`{ zJLk;IIcLtCnd@+P$P)oi1UwP&M8Fe)|8WGox@kLl2HvhdLtBLwS4$uCD0RmHbTHaa z@E3dq9|39>nuG?SQ83P^+cShQT@emoe6Y|_^`IQ5?)V|-s(6kAqS zcCob`RaRE!OEydh5pc9SyDGJwAyOw$h{zPRw6ru~|E*iM@*X{U^tbV4&YU?@r4uPQ z1;+Fkb+s7LB+Z=J+1Z(1US3x2A3uKlg6OibQVzUT@=5fHCgU2pKvAgWxd603Nc=z&LmFO5B!ECVd8khK7!BXlSS+ zWgb6%TrA$ZK0ZG0)zs9K!)t14svj|8M7sD90%I_sGlGxN=ui|mTQ3V?La5MN2ojJ3 zb`{X?G&nC>NcxtyL?m$4s#W9s{QQWpqoAOG$UkXrZmzg_^X55ta>jr8^5qlNWg!e~ zA1S_#@fg%cctsc>M7h8j>M!6Ba-5+s0GuTgtQ1!JoZLBp46g%IQ&T6I5l4<3`CWa= zX2tpQ=l?MLv17-gL-b6fj0ocae1Z@f78Vwjo144f?%lhawTnj-j5AeLRlnT0apU_n zYt~Gb4vq{cEG%3n-q%Nu9{oVy%#8!g)g_^X$NhvcPoF-$PpZ__)s<-{UKek$5JTE% z@p@!31X+ssEFK`3g$M+55y_$2sgElvD(*0*Gg75%*t2KPH`1MI_mrM z5U&HVC>{@5ym;{^W}>{jyj<}Tgm3}plJDHPbKb}my-&r97Kk)+-~=f}Iz+Ety?TCQ zV`GicS3oL@ii%Du!kaH&zPzurv@{PHr10|<;sC>l))CiXx!*POh(LW&}VM29v^+TguTwHu+!h{La zB^xUw3dussrcIlcO0U%D(O$fGaj#?}1=j7-0iwp1QyE4*c<|saCLvXnGUO+fhJ#3y z2hN%`YX)*iH+7MCqXiBqbFdiCkDv{{1=X zTO=D;w^QoO0eCF#OiD^(n=RU~VFOPG(uQinF0kdCgCJE6WERO-?gJBj9Pmj?OY3I> zp`9SjFx0$Ud4fY22^xhuoi`4&k%`qganS5U^jS0@JUqPjph1JkXNPKZMS6OA{IqG) z20NY3I$vMkX85{+eQIlK110aHexvw)QBhF|Ix8V6eWj=f-VqTIoCAyW2z;Op<1wy% zWch~QeEat8S`Kq?aB#S{w|9FzsXU_>IS{yVZi{t=y;TSDoOoy~WU~b>Jri7K0 zl-v+MQ{b{0Dnz$KjK1T9Nms94J!;0SUAuOHc<6I)jMSOPF*4n(hs8?~1_~4ciUZFC z%4&>KCspef82z(n&mItejKJ=N)~q14O_%W5$fhmQ+7_P@PfpNO<@HAhRGN z(Y0vGlqt+XG>KI0`t|F7ltCP7M`B{)JKMHx`%qn+!zij6=%?Z_Kn8!V)+)Q=IRXL# za1sXr>Bnw#Ahz4ObmYBt`w{`$`-Z{xZNzy1kDZH}IdkUwCTiv7<;CKS61bRnJH4vg zc%zZ4ZPDB6Hx-Mln3$M1b$@)cYuB!?^nc?zI=Z}m)hpl@eJ(%o^G=>TxkB^cD7!$w z+Yp|GO`kqJO=GP8zV-F><;rD@zyPAzVUUYwja5HMFHLJv7GAh;;oIU7VX6sjqS97 z5sYClPx;hDk(0RA>e5m}zWO*A>Udjy*OQgYkkLykG*D&4#cTS{f+E1zJiALaGS#LyJU3 zg=j?yAOsQul_ClVs33^4s|uTns(wHyVvP$pB__r|*j&nHzyX6X;N6Vf|L?`e8V1Ho zRV7h1NBYmb@7{CIJ=;C+zHzw%6!1X60|5^NJP`0ezykpfd|e(0YU4)mgSUj>M)2Iw zhUoz%u*REad(xppJ-@SXcM33bH(ZjfJJz+qEko@Gyld}zPpdCAQe4zPWLX ziSjo>mPW1F9A5YM@#Ej_+`02$7F1VPmmfHA;IFoL=+L2K)bAvarcNYn?%Uepd6Z2! zeE9GZ3sylv!KWiejQGHwU%Yrh8fFRIg$_bn94Gew9kq623?l;V`uFcoR2({e`t;|y zxw&^sOH1!C(4j+z*g13Nq^sLb@GdM&H%G`v7r;IS8)M!dH1#^Mur&mqJ1HqCvTN6_ z!&#sxc{Xp}{HeO7H*enjj4^2PHg~UDwd%c)kPtR>J$Ue-@XD1d57jL@d-iOOiOtB!$W$NYNL@DfXPC)F zN%$!^F+#lXwvZrn5jqQz0z7~e?DDzewZ%^{WL1sC2#c-g;<-V#bUa zvoyweN)&n)6%~DAbE=ddYK+PmC!oByN6jcap3tjTuXh#s16o^e>%H5ms;Vbz)~uN) z-cjeyo!f15hYlTDsxN%Nn z?+Hl)=fpeZ=`$9;eEISpOV&+W=dZ1=uYb96<;p)CJ9g}E#(zE%RO* z5R*5Vcf+%@v&Y)R_3PI^SHDu=`cx|f@7c5GlQCn)EK%Rpty{PB#Kgp?`}gl-0DHg# zHOY&KiHTNfZRpssBhG;u&YwSjJTEWrtPHr)vuDo;y-NBF8#e5RO7DJ3)!%+8`ifO~ zSyO|&scW%(!yMoDAw{?UUP$+ix?AhZ? zU|n5ZWn5g`1daC;$ZsM-WRg`-J~BQjb5vvB6}k!-k5TYO&73)Nq{ri_GG3+mN{xR{ zz#tT*@&V2^>j&Jqb0^pMX(;F=N=ize>zSLpeWGyL ztyL8MVSH(6X@k|LKzNsZ_H$34K7Dj>a4_Spd-v{LTd-ikNp(wvQh`caC6MYB0u{0J zPa?IgzErnl7#F{z^ zpoUGGHeFI{=ZZ5HE08{&bnAEDzI~f{hbB&(NO}=94mw65^DTYiu*M;k`kU%t5C)h* z&YXTw9s}!y>Zebi!rLk$B5xu~L-+jo^Rwk0Jnqt+@JZjkeUpX{A081I8CmXjyX)|r zC`e~7q@tptz20YKs%VbP^z`(h>R38Dk<@drUcj6mhjMk-RL7$9rYJB5JaXKf!eL>ZEe+w6DN*^hlkgYf~souz6V%0gkVxquY**j>@YSS zGGqwtN5~U6D<0i8iu9$RuFExU+_-_;wr$H(mvc)cvc!diCl-4iI$d(xuNd_EX_I0@bdM(Ax+7^gLLfF4MkR)zF|SS)(fW z6OE?{6r1>i2M_+*=5=l#=)6wUI5N8k>`k#D!Whe~zlScpO)qrTZr!?dqsB9Zcmb!O zce6y;Nsrzt249*2yLa#2q%n-@CZHfZzUZtmJ~=X|V77MS#*Hg9Hc&wE7#Z467wTf0 z*DK^>jsHNvI6`TaHbMO!Q>RY-kuv6m@zZYEvgOa38zrO)9R&3DON13~#p>GhGcQ3N z-P_*RcwYhKt$ZWQ8+e&bQuKcMi>=pR2*)*sQxXLt&{YMc=`RNO^s$=XxCdvF_Z*HG zqL10%aKqP4rS8$AM@1&{+O=y1ix)5cohmTAI0Bvg65%BL3A!F_F(LXMD%99WAz2_* z{Ds{d6SsZ)_Fvd~MZQ#Ll`@?oP}wl<9T{`TcxV-s3cUvl&YU@OQ2QT#{P;2VQx9`G z-+OfVSVP~N7A{;kMY6bdaS`xKO@`@@nJXqBH#c{;Rtyl#GtC`X4tpnkFs7-Hl$i`= zz%Mn9V~8k9MC*p%r?9ZF=~KjbeOpE6WBs3!rNT9`xVSjadw$81C6gqJ^nb-Ll<=j7 zDO09|s3hNb{`@(i4?1$>$lt~ERHzm_0u{?2aZ{+3x1UMrt*T_Clxx6%0c3*RE_jbs z>V;dPJLLlXA9-ZLgbBaW>m|c31FX>%>cOc~r}k-XpB|qJb*ZVTKi8K-rap~Q!@|Nm z`qbez!o8J!o5dUkAnd^uMR5b7LtN*qhe{XByd@XY@cW4rdOBIfQU;;u)|Q18E@?0W2h1 z%|%Spjx%tG$v~#B4EVhFGG$rATJ~T+q73L`2y?8Xg&0FN{7nvr!Iv1bacj*GTI>6+ z^L;isEy*xG6g8!74T>6k_cb2&ZHr#;2PoiyfCmB|2zVgifq(}B9te0K;DP@?5Bvws WUA?9VN$Fw$0000Px)j!8s8RA>e5SxZbLRTS<2&qgOW&J4%`re`EEf!W{!a6w1KS@GGrFfk!)W@n6H z!`cO50fxj+T$t#>G*J>*8i5c#MrjwcnFI_18`^1Ln4ad-Up%L#UUg4()pS>PK}_tM z9O~7p`|i8HcdP4SvDB#MfvP-Ut!j0CG35x@lmQv=_KJGBWb+;o;#Qxm+%Np+kIjaBvVA9Uc7uYwiH`0F4!ChoN~Syi4I!R1HSY z16*%uX}On3B=&UlE}A|+KR;@3Z+{1CZv(FYG(s(3+;e|*G%@vz_&|$<@)SZvc~uMH zJyYk}%F4>eot>S-7+-t|ibkXVxLmH3&1Pe2NR-KB95+BiLqiX&R;z7wbv4x0)isWX zkASBDQ%R6G6HK{6DDniOo&i+Y3DCpLZC+`J;OCW|@eB+M+zEw3-#Q!)&-(iMT1Q96 zSD23jX8<=Rk)QH>^Yil`_4M?-pUq~|So>gZZtfxG$uG_Vh7xft4?5-WtZ-atByRHx zNjC+5sH}HkVc~vbV`K32^wgb9CY{J(8}h+QU~GjF_CO%e-qh68%C$>NOTWhB@k6)U zowD2QS$JA_(!#arblQPAe{XMZ5bV~yy}iG-wzf8$PG=epQ1}@+-g`Wr6r%gn@bK_& z;OC)d0Z?ROtV{IPwcXv_iJ}C);t4qMQ|NLFV6hMxfZ;Qur}ZeugL!;>9ESH@KA*3l zuCDG?J!UiKQO%;MRO*P4#QrhJW;&JSd7%f-04=@_+y&l7?uM?)`ID2AUt`bvz&+q~ z;AMbWQABzXptU?OeBnq3klrX-eMuA8i@AOb909CQ=YS{(80JaO0P$v|A*=#tIB5I{ za3v(~CGCq1sXX`AOd&l3s3;c@v|OnW7#Gpn+FCdki#=*!m zqhK)D<@fuU2A1vZ?Y|?D$Yw)BL;YJI&Z$YRUUVY&=C!E)i#4p}RnzqJ^kQFM-}jrF zn-L)lWivB4IQRqSPfkuAi}{D3{{H^&W@cu77IW2HUlf6|9jWUq$F3ur=sq_f2RaE6T=z)Dsf( z>VDE52<;CHlQJjO*->JZa< zdLpyDyu4nt`VuDK{q)q-)b9|@HV!}PtBL?sqz9M^tw@pBWrtvAXNSsn05<_fUtJh5 zm8Vh>ASXRQZzRwX|AG^jML1{4v9YnwA)iexo;gOKYLYs0kisYg!r|~Yh(gxvNFch8 zk^7%uk2itW0JikYaWL3Q69qAx{Fl(}@$vBwH#RnYMDsVwoUOzldK=a2$^QQSpZFia zWOsM>dyw4<+yGe3n7S`aA3QJ3Kqe3c(Fm4Z@lTJJFy=<$-$O>d#p1veVe5tI!agi} zMI19_MH$6VpGsO-u#~(6JwvctOoKS4@GlUo?VspN8-%DoPx*!bwCyRA>e5noUStR}{zJ%&0MA{7TdsB{c~FEu?`a3mYUPkb;|Tnnfvu&_Whn zwA(_dkX=Zj%eKp4kxHQ@3+qBivT@^q+ZBwwxWh7y z2}f(l8fnI?iMJ|D3!y>#o5<}!l!lp66;i2ExL3GG7&J~(AIzwKHG3{x7N&%e8HZP+ z0wRS``-F9UeSPOUIyz3qQ_|kLcLU z%*^<+XV0E2E-p?RE-Wm}%+Jq1U0z;ZsH&=}Z)$3Ky|S|MkKy6rDebXnahAzuv^l!0 zi@xTYLYPHn5Z=T9jDi;gcvZrN>FMd~jg5^R8vi_W=+LLBRBB#)s~`5Tw?a@oIXU^c z40}}$xTo>5_)mq4LK;dCs6BWqLQ7Y3LU3J{#vAznrD+7!LeiyPSSPG?2n`ltHm|kzZY1-J?32?e6YAt;jVTK74q7U|@i#5&0U2oB@r~ zXhg`c#=}@NAczjv@bKZoFGCg04lY6mba6W6%(jgwr9GQMO#0>&wCS#hnNEjLdXQ$h zfCnZaU%7GP#&@l)t)prNdsX-q>2x}wREnFyj7B4nmJUL11-bUHSC5Ldva+&OHJ4OP zP0jPik00NYEKBX2vcp(U9nv(YGxDE&=UD|!LkUx-T2?U79B33vLY{Fn6=)vl7?-no z#0&vgpP8`}@zdx3`~B$17J8kYnRHy@!xOfrzPduIM5D%f*WqZ)!ir@rFWo z%zIuK!>pqr5HH1!A3uKj#EBE{i{5c4FE8iZpM;zZjXseWCOKI_q;C1j%8Kt0jZ1n4 zO;8IU3%3i@EvRQWX0r(hnv^siAx#@*g4jZ_yR$Lr@8; z=goL5hL2oow_c6ni8 zrm&ypn$wv4j;PVIv!Dxsq71VGoMG0r7*W(dRZ!GgGpR%e1*jAFthHA(*76Bsj@aj9 zi&Y$$7mM5dVi!t*z@Cwjkq;g`c<|ZK(9n6!F{VPFCe83bXyda69(%;YAwW>x3r-RL zZYyGe^GGLTC663A@@`#S-AO$PnEx(JH#ax896fsUBhjAdA2sk|T&DNKv*Ld^J3Bj~ z`42)OX{jl)c!<(4YO9hr64c@CM1!A}ysf|k91XwBt?}F*OW~KwFmxuZ6ZTpa=w=zw z)=)f0GtYKcw+AOjQ5q5xp&(zH(#Q;Rqwjq^m$Fd^&>Pn}5z!2hc_*4af(IL-5{it4k4$e`>p7o42QC8q|yiql+n z!UG%)-@gcj=l1wKO|vh|{H<6h$}o$HJJh0%$Ct*($G@+wt^MuMqes7L&OON5)YQ~p zx_AGY_0SspYXq(NS$Bu&xw*MX@$6R?bjlhRILl9K{Vj6f8;W0Cj@`X`_ZxkdWTfPn z=BI?MLVg+HmzYy*}~JhxI_GMPM}fmAOn9l~P{Lg(YN4jE0zM7C(pokhL+wF@r{1U;E= zJ!|nc5o%I>eAU+0_7TKF>y;5J|9bv-CGj5&`~Qy z0a7R_Y(97H+?zW1CUvkAfNaj-EO(}*ucrB-kcc78qDDOsx!S8&ufEaQ*?Ce|Zls$h zBMX(uHhY%&HAVXM^z@91Jtw5I@+c@MTE!?qUE)2`(*C0gS8dD-tyyhZ2RzgaFXp?87SfRk`#yT&Cm@yb+e-9;$MTIJ`mEfS9AidT4 q&GPx+)k#D_RA>e5nORI!R~W|!kjNrE_bi3G<~q;p=w+j9&8YZF)mf4Xown3rXrhEU_b`?|6S&o0R(1% z)_LGd{&Vg<=iKjn+d22U-`H#uG+}`;Ss-LgPxpT~)O!n0!@#?YNLxXdttJ zLNGpXaWe8V^b zjvdSOcsy-D!YxzZ%R-!xC^&cR+V%eJ+qX}5b#=A$`cIz5#>T(SoH~? zRls|M9v=3KhVlSRB3fHpr-g=wVr5%XQ(jo;}->l9JxhE#827TUuJ` z?%%(E{qf_+^%AmCmhXs-jde_)K3z@hoP>mg%<%B=sSbxDb`;*vGL*|>4z zdm3LZqzfqmmR%?$3u(d<3I67hBS$`$*UstrZo}i@!-top5XN9WhGKmTOgCBbr@x;f+e|q7Xt*vii@98`TJ4EEvCI;% z8vBA6<}~s>g|MOl{Ro9(%%3kTKY8+GNl#Bt7reFC+=mVw`b_Rw z4>**tRJ`vVfcYcQ*|TTQRaaM6D2~rRc<|s{d3pIx%_TgrzQ5LD-Xwto0&k@4-@pG8 zJit25&CR#d($ZF_pOC|t{_@q-KEgt=2M!#_h2d~iS6BC~=FSuXjajUUH+T*u7U_T} zG;3YGdi7`e1oqUBUKq+XSO?ARRaI5n?RNVTojfdN3keD7)zR9kmy{KBbQh%zyNpK6iMExRPrnqsT zkR~_TC9DZ-Fe(%5ihJi#F_XRS!aYR3~bH8sDfZ$vLVkGWxrW$*+i2NvQu zG~k{^2?2yh>7hKTp<#*VSc`CR>Y(@$1>}XNt5>hiQ6ENRoq+ZNOnCqhK7h~y=APCF zK3d_$!Xo(K$vJwdt&{v7lqfANEl}S=0b{XV&=Ll~3xwpW4Gj%9Q9y@8neGW)-U}G7 zAE9-y5Sb{Ov`cU+bFDrHqUWUT7#V zC`^M*0c6Gt9_2~(+(6mc*@PAGAM^^~0m}=QE?s)0Yl~7-Q&9lngI<9?iS?@&8|hbivKuPoAr#v8^v-rl|@*c3o2Vm)l`+_~ge7Aavw0rmz;^rK)?01u!* zq|@mng|O*+yYf_FBng7R>$ny zw=ZMIjvYG_6BDy_Z-|OoonHOd)jramX;i`19Tyj;vXb2@uWRotr@U?+P#LkQqN3u5 z{QUf%TrO9=`u`F5Q27T3&N3@_V9YGZzq2EQB(I))aF0y?gh*m6@5jQr6}#CVNy=lwB3P z2(n52&(W+HZ@6>k&K3Q=biSyls9Mjpd4a`Eu0vHXkjkF_nu@U@V<9}k$-*WFD1>74 zp=4-GOiZZ$twA7id6F?I4hU<&J>g<<{eVLz5D#dbe#En8f1nINa9X1za}Ww3BtYPS zLI*6kcvv(R1$=oJK1M0VOrH_XDB{~19uw_^1zwZ|{smsh@dLq60UZDU002ovPDHLk FV1nN=)V}}# literal 0 HcmV?d00001 diff --git a/res/drawable-hdpi/ic_undo_36.png b/res/drawable-hdpi/ic_undo_36.png deleted file mode 100644 index 6b5ff3ee6990f71f36f856f8bb3b5b97d8973e5f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2330 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 AGynhq diff --git a/res/drawable-mdpi/ic_brush_highlight_32.png b/res/drawable-mdpi/ic_brush_highlight_32.png new file mode 100755 index 0000000000000000000000000000000000000000..723199fb185385b16a2bf7f1e9269ccb9d643dce GIT binary patch literal 709 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 FV1ly2r9=P# diff --git a/res/drawable-mdpi/ic_check_circle_32.png b/res/drawable-mdpi/ic_check_circle_32.png new file mode 100755 index 0000000000000000000000000000000000000000..bfb3eb03356a02c01cfb2d2aeca83be042fc4c95 GIT binary patch literal 809 zcmV+^1J?YBP)Px%<4Ht8R9FekSHF)EK^Q%M8xcG&R8mQDiLo*kmc}cD1nKp9{{zC`KtW+;VWM8d zs6-%v1SAj&Y7?*!EolhYm>dLABe^}_^JX@;vpekW$%$X`Wp-x2dGF0PKX!I)ZN+xN z2R~!!ClC4I?glE-_wh`3H7^1r=^3D%hhGroS(K;Xv_1GQ_)qwEQO;3P&_W?@0!TpO zi}1_oboyp8nT$oF(Obb_FdPU3*3rH;o6W}4>GW&A-+y1NR-4&uwu|On_%}F(P@pfP zu+#7m{AwnXc{m!4dix%YvFyXX0)tp?gGI=JF_5F)h(sbcdcEE|kG!@p_9X_f1g0ku zRJ)N#ByM9QpKYi<8;C(HA%fTojVnAv)yp84T8Skx!6_w&qcJ^P<g43L9daB`Y<4o}y{YN~O{cBI8Ui>k6_Y zkJoCo7s@+ZRVQH46#N0<$RHx7h%m|P_4-R2n?r+c3Op@BkmM+$TrNKb_8v=SrqO7; za^P}o(k(*I+pyVez6R-?R4TQNa;w#9y>VpHH0rjYuY(ArZ$W+!WkJKEZPpz`zK`O` zWHQ#WXkIuS#qv1hy^U9=-CQpB2&JoqLZM5pK}vwY=2eYcw!5Ot!pc6!)XR*l>_S2T zH13F%UCAhbQ?b%ZsT9FX9Q(E0aw{RTV#oet;wFH47{kTMY2iofpZ=PG&ol~=Vkk(S nAu>Szn9Bb_+dh|p|5f=LvcK5{*am+D00000NkvXXu0mjfNN0H7 literal 0 HcmV?d00001 diff --git a/res/drawable-mdpi/ic_check_circle_filled_36.png b/res/drawable-mdpi/ic_check_circle_filled_36.png deleted file mode 100644 index 0063fcdf6e5fb83812ebad38e4e94491eba12981..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 949 zcmV;m14{gfP)Px&Z%IT!R9Fe^SWRnFK@_c@X`2dZT$I{H11>6VbY2N)wSbnvgutu`}t*dy{lt3?++RIJ`IW?%Z>7=gz!& z85%mZ?io1K{ju^X#}Mbl^{mCKiM9bW#Fh8j=0p&Qi3`9mFe1P<#nC9D4paqxi#A0P z$C{2H`cQ}qxCD4Yq0p_lxw(MP=es#NI_e!88yhzaV`zVWzkG0T@MC*>`(vR{$Sy7} zet>@k_yzm{WcF~|n^DL`zzfVoqtVCZa``LBwT!+T!?7X;V=-n=#(|ug$%Tc52c=T! zior$Q%*&(W|-PZ252-IHAl={oEb}q zVy4KUQ^WsOjF&0yM`o=07*k9i>r$>x+^UUJj%)5Xr=rKP1=kH^E6&<`_^iIwH$ ztUv>&XE^-3owi#1*tx~C!Is{PGg2J~YCY4G>6wg~-sH1P> z1jubOc3!X7>($nXqnl+7$T3M`$qTJ2atU8hXe1&Z~VMN~`7#>Pg}!rQTV+?44Qb(3O{DSsl7cq&B6 zzCbpcecO>;@nCm%w`)=J@5DY7 zTPHQCKyjrHv*iN#DLsx2ZPxGi&reTJ-*CI#mjMs@`6*oizVGbpe9GtZIebdLM|T;} z{*=}cL@pXd5!~ikUp(m%Y|9hhiTv3BzBc2JASgm+&+H)oP@p)Tqub8XX2;X}UNZ0( Xort_B^A@bT00000NkvXXu0mjfSkA%T diff --git a/res/drawable-mdpi/ic_crop_32.png b/res/drawable-mdpi/ic_crop_32.png new file mode 100755 index 0000000000000000000000000000000000000000..1b57301a1f4bf1f239b90d55dc7364ee595fe6f8 GIT binary patch literal 867 zcmV-p1DyPcP)Px&9Z5t%R9Fe^mc4EhK@i9N5gQu}I8vfSfFmJ;aD@<5l#CX5A)z?e&+sCG$BMAd5bgWk6Uo3SeygqyvHc{~tkwOVlv z7-Zvx?ZUL-N}8B+N;YCs5Eu@J@WfmgewJ)Rm}c{4Vd#uPbK*@2o6UFFq1)}U`CZ|L zKrSpJHXjK+p(V84Zw#?gL@T?*d{uHBXCR}0)a&(6#bWWL^l}hF==sN)Nj$Nsgxe?P z>GX5nOQq85LZNUd!DGSdK|+A5$@V+Kp72O` zDm)g_LP{VMi*Qft$Yyf6+}pum&~7vupY@F_US3ETK@!49yzdi^N~N-|_icfCz}hn4 z?wdm9=;-L6*X#Y%`$K^P{y`=QSujb0n=k}LfljBx#u&#u$>oO#SEt=>e~(6^3BAwm zb50(`USxjD0Qn#WlPg}lwmC<#BjpYrL*7$|%>bLyznLd_mnQBy4e({`l>t{CSgQwA z&OLv<+3d6#!0$sL9EQVT3KE5Bsj^wc$V+y%xOx7P)(RyBqkg}Cl1wJ)4U}doB1U*B z()=u8uoH{L2JR%IDf1YG4r83la(Se zGr`Dm7#bdZVd{OGTe0?*`gvAe?W1Dp)M~Xa)OO0N)|QgO7o?>#(#`=PQLFA|GMV>M z@Jq1j!Z2dL!=*x=IMmhbM9Rj($|SwJ0$yI2Sh$EBA^vnUu4;ah5x!)(Tz;3$W?!ix zz0mhJq3eRvcZBhxBqT|O0yi1%b|{5xVLM$teWG_e9*=V`gxLJ6fC1>GwKLlLG>am# z6=r}jehK&XB9VxRu{pUh=uD5T4xBMu@P*S2NH|v>cTZ0|ug{M==VknSb1-u?BXnHN tr!k)wUY7yvgAsr|I6d%F#Kd-q^cyZ+ftwpf?X&;@002ovPDHLkV1ftGoiYFb literal 0 HcmV?d00001 diff --git a/res/drawable-mdpi/ic_crop_lock_32.png b/res/drawable-mdpi/ic_crop_lock_32.png new file mode 100755 index 0000000000000000000000000000000000000000..4170c434ebf3d50fb757bf85488bd30163953e3e GIT binary patch literal 1039 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 literal 0 HcmV?d00001 diff --git a/res/drawable-mdpi/ic_flip_32.png b/res/drawable-mdpi/ic_flip_32.png new file mode 100755 index 0000000000000000000000000000000000000000..53d441235df12b26c2c7cbf8784d4605a61c1c14 GIT binary patch literal 1109 zcmV-b1giUqP)Px(4@pEpR9Fe^R$WMwVHEanZn`<=PnpBY%{9mo{g_fIh(cn)sO+jlAp*Nh62V(< z!>cX?FA^088eJuk6qJ(AD|HunVTj_zbb;p2ru%cV=lR+vYwep`8C}$YXWu#JJ@5OT zbKY~_cS%YA>0i%4@-HMH1#{8>euKb%i03yDrUQF8agjub_VW7rdTn1{UnTf#AZvJd z_*zv}RS|e4km#D25+5;JGN5p2Y3Wrk81#Za2N(l^!0znqY(IECkOBM=C%CA(v$OLK zHV^EBAXfop;vO3t8!0I%sYIPzg-Q*ia_o1A z(JRzywE-z!3Xh&V#&`sm$&ZhZ59@R~v)k=nTUl9|fu0>gCt?N}b1*bniRha(8ci`| zNlHsg3!pt6larIr3kwS`qF%1Um=3Tb7)ZjzNf`!%!Q^tezA(y2!uUZ3rlzI_A(!Un z=9a>Kd3}BTvrHyC4;?Qn$v`CsFp1}<>h0})q*N-|+wqX^D+sml433-`92~rhNpyf6 zkx&-sn6jp(rp)8FMct2${z~$70q3 z9m;BNZ@-BL#~&@~a2;%;WkB47Dc7PkUn7&Qy1F{HFwhHJDUP@sy z6s-JwTw?EYa&q{T#zo1=$<;7)AxqP!8yvH33b&>^H8qugRu2f#%eJ?-GaDKj8u3us zbUGdH20I{lEgA;!r20f5&hIAdJhav8^%sc4=B1~n^Pe-@R3I?}JPKYQOd%n*64+Px%$Vo&&R9Fe^m(Pn*Q5?mm%xcVXqDgC_nr5N6sEL_U1Z^|Bh&Ht;2nrXjX5-2~ zV4_88o;v&pYT$n)`sDlX#f|%oI=RAGGqZycBe6OJQg`@A?_v3y% z-+RCJIyR<;>cH+C*t5IGcYK=f-#Zj<-hlc;@q9~YwzQ0{fgoDwFmx2sK@1UUaHh~F zVfI5NtyX&}l}bHpwOVVTQ0NZY2)7TCJ3HuN5KdfjffBSLjLon{~qxQ-{7Lc+@yQfKC~+3ZWgtgNg&@%em90Qo6G zwcG77C?+7;fVPE+$K&_WsTp#5z21kSQ#9o^a#UXCDub1 z;L4`~%jRbfV<|y6rC>OAxT~8m7z}f@TJ8HLisXQ6lbp)|`WHf6qqxPdmt1ic4v8RnjR62EX5b698)>48IG7 zLKxSWLe4tYCEm*)F!GS@{DpyRG#WK}y}ql_XvQ(1k755?bGzMlG1Gpa_YS1!|0@1^ zrh`@3;&eLa;g}7_hag$ggZB&ZyX`!u=p4mkI?{!DkQ%B3|GWdg0A+p?C(2cI0{{R3 M07*qoM6N<$f>I-PWdHyG diff --git a/res/drawable-mdpi/ic_marker_36.png b/res/drawable-mdpi/ic_marker_36.png deleted file mode 100644 index 89fe303da42c645e01c3bb596ac50cd46e588f07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 830 zcmV-E1Ht@>P)Px%_(?=TR9Fe^ms@DkQ5?tZ=9ERXEW@yp5i)9Yeek7+`68hZj6qMm`<&2v3Mz=6 zvMGcRHIs0Qw!DlDr@1jipA0JY;6NDkI#bz;Zp};I-{1ck|Ji?3=y7}Sz}IvApY!p1 zE}WxKbVJvH)*Lv{+UNiD^}(iAY|J{!YfW_uR@q$Mjy!=Vp&p3RRp<~zWfaPywuGGc z(@Za|Yb8wst4$`;xnwfw@Or)XkT-ffp1Z57tNv6f^;E0X8c@~?@nS&NjX*F*&1UoE zd_MoJE{5ghFEeorexLKI8K%zzhuy4d!yW@3mTOYjJTgE(KvgnM@`L zgp1G-DM~x-5~c|-hN-D3zec0EGrxovO6iZ2g5o;p<;u>VSEJZ>~Un5SR5s zM~6C_%|0g>x7+<<7ia2$K!6tVRS682V~09bt*oq!`u+Y#1SB&}1T)?V7>psT0X1TS z&*ytA2NMhi-=UtnGZ>?>eh{C50}pA+*tTYIC=~LEFeeeyn&C1{=yw}N3kOE!V8Y?> z{(+g9nRyTBYtY_1Gdnvgg`typ@1|*PZq6@pX3t?J_6WMpKZQmK^KVaMWFEcUU}&Zw+b>jj-o zce7L~{bV2%E1%qLa$DG70~P8mzbs}Ft@N95Dh4u7A{W}ZvU#=aVH)44cHfJpOkPhl>h($07*qo IM6N<$g2E<_82|tP diff --git a/res/drawable-mdpi/ic_rotate_32.png b/res/drawable-mdpi/ic_rotate_32.png new file mode 100755 index 0000000000000000000000000000000000000000..8c92376b0308e0be5461be51474a2788f24bf380 GIT binary patch literal 1203 zcmV;k1WfyhP)Px(ZAnByR9Fe^R$WMwVHD2&HJz=DiMD$2HwKc=Ur-@y}i z3knKOV2=u*r{W$GCYrjft?kar%8C!Mw{>-Oz3l7jdu2A8N5RSO@pyh=-khGEo{7B* zfZm9k@Qro>IqmK3O^pA-!ov6b{QRrXohmCUyFNNPY5)=6{QUgK($Z2b^vOV6N$@Zx zTuw(v$32p;+wDe`O0^HVbU@SE+FA`y*sNCTx5C20qtG!gHWdzT=0%J-V@dE30eq`8 zAh)x#v%0sp_ZG(d40i$~ceu8;_NLG0bI;Aqy~muy7`~Vilb7>CCQ=4)1jqsSCc!v{ z`6+;30QK|$V@}c}lcU$`A23%9216z04Ba2SK!$wFgXQJrSI5T23{I!h3^#jtP$WSz zdXS8!k&%&SI-Tw$Z0Q}6P)ViIvq;Xb2+=s^BuFoW2n$EB(Cx~Sk`gWA_*5hkNyf*= zKj1SnGwXvl3S+TYEKw*Fsi=h4U~@SsDd|c}OUoCmJMoDw_Vo0;DlRUr!k441sHk`g zy;rb}^rY*L3=9msKoVIS8X8J4&jJnt`y=20beX{Ms;a7+w1L+iW6nIF7u0!qdDq}M z|M2keL(J)&sKVH3mzI{Mj7H;gjOjL#qU$ySFJcAM_V@SeVQa)V6$pd@&vVPm%Zrnf zlX{Hz03mr0GQlE4AeG5vi72yE7&`zDK(}oKt~&ucYJv&2DHsc(<(d@)7Lt>bsb|{` z5n-dCWD*jhgoFe)p6v1KjGzk_?(yTZ^CEBf<~)P43|IyS2OojhBE}>Xa$YzAtZ!L@ z4<-T5`2xR?2OVqUZ6$y^)`{RjUQ7ul8BoO21Azl0{6zhm7M_F=?6+4HPXa>XZHjR? zfk2Fq$s!aFHWseOaxnLZP!*-H6XG5dk?SXQDtT2Y0TM5S=rbfBY|yMjXxjwtEjnz_S=g&Ye>}O z!+Jo%-OF;Ts;Q~D)Y#bg1kJ>OE@wb_{Ykg1*@Qe$uw+W5G7XnsmPjO`rlzKX`uh4I zY+?~w_t}LQN0`tf?CBYGb#*r;CMMpv-EK>?cFZ-D?RnJtPBgCzuw~z8NsmdwJwPKG zvz)SX34bu6B_mzU&;|MdoX9XY RCpiEB002ovPDHLkV1md%HVOa$ literal 0 HcmV?d00001 diff --git a/res/drawable-mdpi/ic_text_32.png b/res/drawable-mdpi/ic_text_32.png new file mode 100755 index 0000000000000000000000000000000000000000..17b40ed2c51cc589e3b0e3f07f63d4fdea9fb13b GIT binary patch literal 1298 zcmV+t1?~EYP)Px(%t=H+R9Fe^R$WNjR}@b)SsJGQ)AQ(>j(2IEylzO^E1jU(HN6-zn|tWMzif< z-P3a5=e_6L^S|eu-#zylktiY&2LA61i2sIwD6B;T9O)MT{J_)T9K*ktze<2XWq<;R z1DMD@@CWb&H~^T)eotDJB&zF3d-pGV?2|tE)4ty12NQw5JUZ4}VKW1_lP2pmSpe zq;NBSqpqo`DYo0~Kkx4Dy8M2>$K`U_Iy*b7u$H~Hwq~81n`^{85g;33g`36a<>lQB z1Ok3k{RlcKPp+@8zsm$xR#s-AUj-PHEU+R~dwY91`o%+^t*tF5j?S{Zz3qS+XliP@ zPy6!n@~`mK2EV~@R!G0nY&L(!4@O2t+Mr(qNNu{??cQW!OfYDpe|$+v$=kdssCpka z<#X6x1yX@)ZEbCzdcEGmTjX>)AHa4QVA5fQ3ztBng$b}~=obJs-KCkCnJ(IyAao_b zUQmsWjyBVdUNJ&vU?xn4IO_WQ`@i9OxCBl%1L>3|B_$~|8qEzy*(IQfE(}xM;DIZd(1^*vG~m6b+Q?lj2u-Pq*7_j z;^LycyuAF)goK1wBoc{#Z*NbA3dAVHuhnXABqk;*Ha9o7@r^_-m$S=7t*xy#416(# zKzzQvCX?wgj=~)-0jwVjtI2Cm}9%+WtTKmQ%*Oh#aqtj2=T zZ1j$AX=!N;dPoll4A7DDSe;JyIz|z$+mAAt%pDaK#VQU3O%{!6FJ@(B8FF%RZo&8y z;O7ISR4UU73kzTC?(Uw4Z4dAPY|@z0($edwJ{mbP4wDlS#PmpLIFCo>4l4n*PUvp{ zF9Rt-@HSk|%*=e3)gb5!bUsQN-1QoMhkNf(tJOKMsR2GZF9O$WHroK#(cF{J*)MF) zkR({W%4)TKMaQwRF%xtx!0zYK2w*d&uCK4#=vQ4`eH*$8Or_!&exnU<$6`Z6!^e8P z{ucV_eTTy_h{TrgIPG{mo+snun^$ZaNUM(vtyW7>(^(7X3T!cSaZu#@X4~9|i{pzrdrVhn)d6xw*O5 ztE#H9F=wMP=5YXSOiH*BgL(n}=s0db%qd)>Fa7AxUr6+&AJ=H-u`zl2ag7bhkwP1V z4SM+N>U4#IF5Kfo?=XJ^KQ5j26@t)*YXaySkq8432F@_>CxI?cT*hiV_y7O^07*qo IM6N<$f(9mGx&QzG literal 0 HcmV?d00001 diff --git a/res/drawable-mdpi/ic_text_36.png b/res/drawable-mdpi/ic_text_36.png deleted file mode 100644 index 5f04230da207e8eebecbcbd527a9119d90b318b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1423 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 P00000NkvXXu0mjf2u$eF diff --git a/res/drawable-mdpi/ic_undo_32.png b/res/drawable-mdpi/ic_undo_32.png new file mode 100755 index 0000000000000000000000000000000000000000..badf4d708f0b3199513e8af5bb26cdec33d9eac8 GIT binary patch literal 1204 zcmV;l1WWsgP)Px(Zb?KzR9Fe^ms?2WWf;bFn{j5H8C}zMb%H5d>0qX8wjQWxDp{h7zze zh|mk!u7bStDiC5XR4_5U2t_L!B*Ih{(qU0Np{s%;V(F-3y3W}18|FWaGLECm?oGY$ z%y)PX-}C>D@1&&s*Cq9o2{8JPPUtVGjm{`z?XV3+aMDlR@x=%bt9?d|G=V`L35No9 zX2Bv{j+C^qL4v}8@VBrRspAKcgk(%Ih!p}_hlYl3t*@_#YHDhR)eZ=j%*@Oy&CSj3 z($dlooK9!4)oRU7OG|Sc92{&10)anQR#qMi4-fxZUtj;*?(Xhi^6?9hfgCfFl<@UA z+uPeytE;OF{)WY3Dd_9#`@-+{FC0mN!Qg?<=bM_+1Vf0*4D=9N58qb z`LLs-<4ch%lK)k~Di|}RYGQ#vu7XT2EG*nFEG(>9US9s4z#_2R)z$S?adGjxvUyd= z7hJ*%!u7JUvbTDBd+&<;681|=OC#mwI6;h68qQ^1kg8yFb)JTEWrJ?(Cb{8LRPQ!qU}eP23` z8M``>u;V$tn^jd+-!3jLRu&Z%eN=Qog+k-AzBHW z|NFxfG1Y(@&8X9#@Me=fR-nwXgQgE$2R z1>70OPQsHWz_>>vBO^X4*%B2jXH=dBf#_iIDo=wzYDGl_Cn-fY>xK&UQ&gTb0pgoW zN=j}p;@sTaLlxW+=h?`(URcgNh8K>Ugd<;n;fsj)1TZe4^DY&a74LylS8;zR6gt#Z zd|Pc^MULT_!hn}^b90|l33z}YlgurMZ_NQ-{YZ&x+Johp(GRmdlCd(2MCM2Vyqeeoqa^8d_Ji31P zN?Ubxb&2x55#DrVNh>ia*=y3jBtYmz;rdNUY)YmF=ze8o<%iO-?hq#CxrFJoXJuu% zNGz1;u0n*TRSBzidV2b2l2VdWl2rQ9@9gaOdU|@kw%KgO^5;2EDiu488LSDAou8lo zN_Thn9S!({GNwg6uYQdeq9hZZoSf`yZEbB(B2y}Rmyjv2;}d>)yv-z^V}cDq2*y+b zNST#-UlIXsHC{dbnD9RUko6?>$0Qj7iWL@Y0ZU_$3M(Q%kT3u#@V}fn1OEUpN)n^p S3Mjt-0000Px)2T4RhR9Fe^S8GV*RTOt;8?{z*ba&F3YJET{X@Sko5Ir_9*j@39TM?8Z>Qd@} zl(gZiXWsvQ7~aGTJc*-`Nk*Gnu_*CA#}~h_#9_))EQ^&_cO1}=bmzTekl$7*hL_~xgwta=KKll12oVp!!X~0=z)l#p`p85TU-73R$fZf@?Uwzjq}3kwU=5)u+rN~JP6Cnx7-V`Jl|)6>&!CX;C$qPB&Fh2E^JtT&G-{b`WG%iM~)xN9O>*wKF6OQl$@ObpDVi&{biHffd4-bFGBZFrSySux)`uqFu zPfblVR#jEKf^qKjQAFct7%xDSTCKjmy}kWAJ(Zc6`8s%^0N3!CI9cA+)%6t(I!o>C z?YA(_cyLG5LvKap=H}i$I5^Pb77n2QJm55*T%9F%7mk38gNOJXAeBn3;o;#XcxkSu zr$-MK^Nu?@HL9bdLz|kKdbh5wF0-JZ;714=0h>DoVw{S&i>CnQ9RV8W?G@(n$-=_I zREWtxmY0_Y(Pt`gb?g{+P9k9KTjw($&7~|aLF~xL$hWw;`zn>{W%Q3dZ!bnKxFeBa z?OS&;XU8ear^M9R**PGQNP^1B%C4jDQwlh%+}A!gFN=(fd<~bxh8$OoK2v~$QyeA|#rh{~8@`8u=a@iviBo{y_SJg#eN zYvbs%ilknzHpt1`nS5+)>~qx5Df|Yghzq$Q%JP^PBMOusZ?pVBv8FF6DY*e2i@I|; z2t1cWrNKo-Mc455?6P#Iudn|Eyl8+5X)Kk}IL;;bO`a&wV)OI!-(!KsYO|@S>0^vt z0lf7zME+iYf{~S#l^H1NbyVtM2^$O2AXdI%2}{qM7{f}F8=>(&5qHcZQl_V;zk`B( zn8g~4{Mp&rpIcj7OIhT{$H!lj%jL=0+1a-m8X7)By(EhKBRmzq78e)agbp4zjd6F} znBtnKfQtAKzJT)e&f?Px*MoC0LRCodHnoCTSR}{y!Qd(Qu!PdSXFdz>_l!&NQS{{~yK82D7E$;-=oRb?LGF@ZKH#tao@ohy*Xth(99`7l;Y`uI(ji^3Bc7C&dPrFFAMa+&7_0 zsHmtopt?k1lR#j!y#k^pf9cYt&qXLl*ePTS`JqafoSgi%prBy4>WBw;0m0O^5;gg@ zwzkj2Vuz3nYyD<#tBT)1%Igw^#~6WBcn{#Wt@wqzmu;>C+!hLR5~h)|9#r@^%# zZ(R-AY9aK$l0SIx;9Ih~m3*we`JV*KdoC_{nZWGo!ftFB%Yk{`M0*qPmL2o1iud?fp9DAKa1eRfw@SCg^4NvEc!?o?M-f1vu;glz)Ew+cDoPI8<= z-UPmlBEoo1PfkuQ71?n^+?q~LPfs2{e*B2qk`f?aT3TA7_O?B`R^NhR$Q!E@^jO5C2s>r+5SZN`SaLqcJ@_y+C!_1ui!6AbykI_Qw&Wwh}Ym+2mj)tmR*~A3l8eeJyu? zHv~!N=jW$tYip0G4MSmrMq=rZZkF_yoSm16xjW>X%;(dE9jK(W6KA%H{iw zr6Z+^30KuVU0}FiX=V%*h>~q%arI?IS)u?D`&MrMM@vznm!G1-Q9! zaefatM(8XSW1sJTni>}ux4p5k@t7VQU7eYknFv*eE;DP?Hci0#<~5e1NUPsLq2pK& z_r;Z2@3Z5B;I8=i_=5WS`kJAkp`QtSBO@bSD&H!wKHzM?SYKKDOC&29C7=k#Fr)zE z8u&?iz1|IpiHW}J*RS7J8NrX|>T`k#bjsRWA}N4gQ)g8K!vf$LCa4k3iSCdF*2u3< z`^$0)Fuga5FezSP0vv73)Ml(s>KKVe0ah|b3Dz=`xAoj^I_aja23!re8gMmW(ZJvB W_|}k39324w0000Px*UP(kjRCodHTWd@lRTRdz_(IfLg=(O-LZMseZo|VuOxskY@dwJE28$Sl7L7y+ z0aJ=?NaPV-B1$5U5ac02f`1Gl0V41dNgyQtA;v@_ukeakC6r|szi-&H4%6MX7!zl@ zbCQoc_c6o$&N=toJ9F>)`I%yBz|?@L0Uy@D9XjXE{z)GtWtX>9{gyWBdZ(+6w3AeI z+xF$%*Olm};7)Xfq?q32x@Mka)Pz_sU_Hq@fK68_Z6!tVKcZI!2qE_G9u>sOBuJvn zQ#ouSTv&I_g$<;3Ks*AMJB2svNk~Y@laxR3An*tfV6)lw%+1Z+>ndm61FVAtmX?;r zXJ=<8golUw4-E}nMLC65CwW5mBIIdFl6wqz7O>>x}(om-}-r-zf0l8&Q37@+c~G%8lNBIL#DkE5p{Ky*PtK?X^?*|{zT z2M51RPfx$JzP|p4wvKry;d|U420Q`W59rO?(WPxslc!6&$rlwBT>$y3o(QtcZnt0a zR>yMO{~Deb1aKJXQUO}>v{oo^w4|iuT@d_J2reuvOwZ5H&r1GQ(!RdFi+I*P;2}VQ zBrf$K-pE_a%geJteoaU&E-wBS85x<60CxqkU|Gs02QDs4^We*dy3_) z)z#G>Y;JD4$%F5&QBhIvqfHiEy2aseY~GAG>(|!S<}DVB4fpK@7*utm08ixiql4Dk z+S*)@Ul)QTZ?#%4pzf`*va&C4mAupGv^O<1QE7Z`AaEa`n^}MzVYFw!qvhF2TU}jU zJ_u^bpGRFl@Z@-NDEP!?m!2kWf3#~wRd=%g!C#t2T$|SIDas zz_s~4SU+9JudJ;6f@q(K@?DR4m)q;w@+42;5D*Ut!W#cH6|lOx`g2T7%$ul7-EF`# z5_wSoX8=x1PXY(W$HzZQOiWC{bxKuL)#tm3_C_NQj*16}0`?$(0Ehw3)YQ~`>I>vK z1@gU|F@SGqk-&>s09E)3d5(W^|L1Z2LVbOGsjrb2*N?;MuSC5DkQu>K%63K_^K^T$ zyqkPuV`H&N-jk^{Wv1n~*Y<{3B#LYx`!RIj_57`G#920Sz1 z`I*rkF+-PMa?r0G;?q+dHNkmazU=a|_H#gtFGPFrRNm?NVUu5Wx#1839K$BWC%60B z9y}GH`^!g-r*M6^wYBxKFOipz8UY|5lAN5Jq~65bF|lhhMxEysv*Qnm)AiM_wqbZj z|475rW7g>8>GmYg&skjKb4!c6I!ACk&>_W1wm>gwY0 zl*0gzs2Gks`m6*#j(bLYj(J;mcXy?bmvm%gqziRtfRkBSS!Y2!H#If&1oBka(*W<+ z-9{z)bVCvA%T8`Ye0+SewCk@W8NpksYpXv9{p8>R^yz{F>INdn)*&_bt+_Xa<1VqIb^t0HY{=U zT@jL?8wWv-s*kNv5i>J0<9T^`+|uU!&M{9GrfdXADD*cl7%@ArS_#K!1P#V9fDv=jZ32Mm_>K2=E*ZU0#BnVcp(a zfT9~y33O>rVma>8(OBL%Qd6d~ipaYihvMfT;l=*TCP0Px~H%UZ6RCodHn+c3oRhGxA*g+6wX?CoQq86$smO>p+SsIjd+nsI{hmN9V8ju;| zgmE&4X$Qf$Vx}|Wnh7&RRJ7YIgCh|mDh6oRkwpi^W>uirl(nFMTITn-;*$v` zZ8nH*$Fo_exd2K944|}4aC<%5k-qD$yK={j8B@}~fB&3r-MVFU=+L1{n>KAaw{G3~ z0+l1Ds=B(m60WGIIB@jn(cK3Q9N4*O)29D>4?HmKi!Z)-?bxwndup0U<>lpNYuB#*-M#nTdy8Zb73Ycj zi@S?26f+R$;`pZIpN~+2X@a+O6n7J&Y`(bkl~-Q5=itGEo0^D8z0J$Y%08YyfBtm! z1yBRUeZ^hHcq2NY8v}UObheFY2Lli>hN*=208*#B@4ma_jyvv{)xCT7BE83{>f3L> z{o|G`TR!>x^UpVY`Q?|pR<2yR=bLZ7sZjo@9`|A_4W$qD6}q%$_~_V-*}t@Nqqvdc>(_k4=(UFBuq5sf$&!pSWQB z`0*1omHtOVUKtL%;>oG6zWQqU3opEI&*hh2evRsuic7?WVn%*|I6KDVQN}bKEG`vL zV_$mdrF#YD>Z+=$lVKmEw{6?@){r4Xu2Nm5T^}*JF>nmx4>ILKa5|_{-1!o5@q-UO zIQ_(l69+=20Y)CO^ro9`x?XhvWsn%dY13Q$BQY{C;w=mV1l=)DRTpohi`x}N|y65HUw$V^y$-o#iC(-wdHtCbqLzn0+>zmB08p1;s}8- zpEH#^6FBZaFnd^V#EsI69Zzci(*r1rT{@Iv*D65dBjn0UOYfZ=IEF9044iGE(dxhL!2$ z>`~Ab{~6^C5y$5;9nqFip)GM~z~sr3$GrLGo4?V4a)!SB5U-HQ2xBxr+BhYXL>^_- zp)PF-9)0xDsoI?Wiw>qg(>qgzpbTiCvDSh7NPmtz)}Jp7%EyZ+L(dRky?#H@0VBi8 zl{;_Vyjv}tL*j@LBd#VtQ68=aHVUsHZsq9%*UWHBuyg0mRXUXqR~gFT2^dCyaSDy> zrw?j_b$t16>!D}0fSRvH0M0<*O&Cf$^uRL!m$O{{jW^ynnX{qW>+JYzD88IpA)?07=xxhK@wtnhl|GLTtiM=O@dyx$^&;{?m z|Na8E51!ReKmGJ9$;lC8D1&9NLx3}sKY}j`Zp#Nei}RGnsNo@uP$-ymheTP?x^?Sbal7!Tk*u6HZQ3tXFH?*c#RFxi!zH=7xmRc( zb10PIw1Vz>wI3{IFl{L9VGlF|QM7pR;<;|e*G=USQ_pys8F}XY0G+KSTPWV3Z!%+) zpDo5q;)dY~xH_?^RNs^jx^4XV!3Q5KRGmCA(>NS?y+&SuC!#~H47)qtK77|#gKJeU zLmZDM_Gr8-_p-|_o2YilZ&ms}exvg7zErj-`%mr|y##+i9%EZioH((>`I=rID-Imi z`$;jYLbaGx1M;Y$R4aYB>fE+%Tf8tO>4SZS3h-3=qHUbWi}dKzrw^lCFX{Z1sY2?; zWuY57qU%WwiauI?`$wfC8as9@o`(+Dir#f7RVIp&PiL*=-i2||WnqW*TA^ptE+p#|4IICqxR4(#l{Pqb3>QbwQ~h6$dDrFcc04jg}`R5mu=J zXJ1mNPo9rRMzxn^?LW$9%$UKlj2v7%+==ToNyzf1Goz%WWF!Yo%i$@|mdFd(>=7ru z#M3TLY)9B{<+N|#epDz!d6$Ya#BQ%-!xRT7DNn-xN=-4WK7jB#f;)y$2gUOjELbpI zJJ;tw{q)l(IhQFfTg=MD#*Y3{8HFqYC>u}qN|}X)g{7Jz4{NLOyQNE)&K5YVu>Hh@ zf%bhn z)TmKCRAvR^?fmZcJW+sA1|UX zY;vottSmlsVYHR8;V1<24j=?nf+9@7=be1lQSyw*eEFk9

hb&q`c~NeDA&Y ze)7m8j}$A9<-U^`187H|23E;Nk^3JktxM50tuvK=MIEI)yus5ZE~CZ%{riuqJS{yvz3sKv zUOQhK#qoM&GY9B^=+X9+K!yP`D9(#UKhXw&*zk3chyGf->%Uc+`sq3np%ZD7b#<@__YlYI`UJRSDy-|d6bjXMdy#N0Dr=P|>@`_Var%t_&d@-Zx5o5GSlb55N zGe5ON#Hn7_Q}854ELYrDjBKWf;|E4CMc~MwL>ZtW6Avs9U#4G3xN?&`zR;KQv&Ago z=#4I+K6%5351$y`N=sY<%~3tPn*Ol4(L`lWvrCjN<)@N_y*2!VqP(HveqxNoC={Y2 z3?jd1!-fqnxQ(7wGGvK7aGc5pivbGREV}@JaVQG|-jBqTWr*{{L#IrcGD#cN4+5Dr z^r14Qd>?VB3p$|-zz*X!n%kA>CoJWK`eSS8eR^$}sEonPUt&#x=5O+Yw_=OE2*ojk zdUOJl#=uN*i9mVLit*GX&3y`v|2lf~=xbDtM{(H97Y`H<5Ca@(yagajZ@A%xU#?!g z`oH9f$r~le5;(tCd5Jhf46t~x^}sXHJ)c`>@}3j4ff6@k>4Slx4YsBPC}pN9LwFJM zAA_0q-F2G&PkxzHI!!0(W%__WN6G!-gJO2J>?x3ml5|YWxKQ_V#!s3w>7Vp%2{0p) zo|U@C^Qk^|t=hVEE1xs=tXQ#Pug*s40=j*qw zx0HWad_+wD?5ZITE_!#0uUp}s50I1HMOqNDg4#2z0zk&RmeaVG83}t!yZiE=zuQtTk_ar zkNsoVN#X~?MtP6ge=p%h;anc7DZ@42h`3skxN^sI=p|;qLw$pU7ojZ6Y__;a0sg1@ z5%8%)hYoGAobP*5mo~IThB!-%Ok~ps17dK9L&UB^uHst)&n}+gQA^t|o=5D<*)yl;zpLSWi5Jdp4ofw07 zwwpV5Zod9+qf|fZWM6Q>1>Gf+KGJkR);6VlpMIv^{O-H&eyn;Mlkt58ARXf+ z1>A{Nz)W8I<+_`0eq5olyhI&F2M}myfOtm+Q-aa&FU}D&Rq%=u@sI>F$`0Ptp)PIM zOCckbY`h82$(JryhW8YuYkA`CH2M)P7zlK0(0f$gCu7`1Dx-hL8{U?LJ$Trawx<8r9?mNuwhFQ_Z1UY@`_cSDQ49|A;$>= zWw1Q$FdjogCXfE8V^C;kV35gx;SpKl5`F8QA{}bQw!~d&JQ6Qt(2$9oW&=mEA_8%g zLoqgW05CLuSDK*6rEZm#ig9U1*1Klf#tjZZt1nHzfP@DD9KhgR7@aR3!HUYFksK{~ z_uHrMNHcXa#0)I`pA&E-HzGhnQIt$>2618Ld7xYkSM;<&o1}U}#RJ6{!)T)@UWK^JNx7nJ9OaMZ{lt=o89V;=a-AX)=O;rCPjr@m%e?m&buoUzPHt*CtGuFkW@>E&?*Tp`$(L zjKMkM2I>r=oq?irPX(6Xj=C;fddn@hOw)2p9I8bEtAcAZVr_~yex;+vF7bCdYaP}! ztH6T-nqN@#BSBAnBJDM3(4YdoX7a&K!iXWYNS}q*KmPdRztstSoeGYK%f;+- zPKw#gGiT1s;MSV{GpO+5i!biev17-c+#unSgxIkn`oWUl z#x7&*s;2*(ybn;jVS5m9pk6v{PNj#Kt5KylhngJXRF1_C6E=LtXt z%YeAd-r{zu+B{^1nnzk)DV86CMcN({=GSfgr;|2@1CqVUPXpp-Dj7}6vjI&Kat4hJ z2u<8~{AqDEI@Qy8u6zD@9)a@+oJZg<5`q5*f!*0~JO&o|00000NkvXXu0mjfv%YZ8 diff --git a/res/drawable-xhdpi/ic_check_circle_32.png b/res/drawable-xhdpi/ic_check_circle_32.png new file mode 100755 index 0000000000000000000000000000000000000000..cb4f9bd360d9336c522ed23291e96dcdc55fa5f7 GIT binary patch literal 2222 zcmV;f2vPTmP)Px-Xh}ptRCodHn_p~HMHI#>wnZw{hSW600yQW}2@ylIkti|PvP%Ml2Ocne08KC< zO)9TwcrpQNh&9y|3Z)bxO&|m!hL*qf#Rp$Z2sQBmjXXdIBEHy`(z3hw{kHeiVY~nL zZYfz#@^xnC&OLL!Gc#vq?!7H4dMbtOfoGhO8z)|_UteF_U-#!mq#7kSAI;uDU1$toH;{9(<6{K(vW>Ycu80!EEVc^?b`M6 zl`B`i9~l|>=V6w@z34y}Iz8RAL0hy*+cvFo=}f6fUucLSOm9Cg%o7#}bwd5_-Md?E z-@g4@mYfsbhE8Dc?R z8QVP$aIt`>?EivST){&&{L7TD(EfYXh7B7yj66|NQBhH&6X&l30|Pf@__)APn$u%a z!2!${=FLK(J|730*xt(5Z)}Hy$Hij7Bhw&udEg?Wg5fep$I#_fRaMNR86(VZkd8sv z4hPjG2Eb`b97yVbO`A5YOQ)gfssr)8d-on{ZEfvI*9jhngbr|RcZYwiF09PuVTRws zT7)08x3{;+uFb+$#ip)sI2=mV4jkYj)CyCkfja_l0Ej-?;xSfPSs5FN$1WlnI&k1X z+m0POev~mI!u^txl9T}r!{GoIWtjqSGoH#mDma5(6YJ)({{H@NQh9eeuG90Kot>?+ zDIhco>pD6*+Et#i_su@Iz)64`9NmuB&j}$wu=G_6Zww9&_M3vol{)0t$fngou)Dka zYn5m8@C7b#65s~M*yUeE6NPh?zAU_T>(;HoOo%fd)0va$>Wo7^aOB95jLFj;T;Sw! zgJWC=Fh4j#vi`r#BkFXGg*ZV;(YezPC&VLv?AWn(*^^PvoBeQslgAB?aGfF)5+&LG zt{fX1`_~jCOO3ql*(z)%QbQowJ;|;)>JI=~GE zL`Q^lmc6uymZbQjE$2g3;ibhrA~g|P?egLxBjKKd2M>O=ef#zS-N^kV$B!T1*wob2 zth{S$MtVIi-0yOnqQkbpwYu_-dN%D|RIh~;sfn~~oEn87kvo%-5U1yZCr_T-FQ-I= zoCGd#5^4q83n=@jWHklMG7$(XNVQ94P+;h;N!JPS$e%iOs#CgiCXao|rhw}L9FSEI zG$$wxGhd|#C#)6%nhswk8wn11b6oKB>C;`( z1QLyec;wHVIn!;5{7TbZ2L0R!MHs@a6EqUOa7O}p%5ad-Agt9J;U2$8yL!^y2oWXy z+zLn3n}?*+hIT_wPtWHN2jo5CjFPq5t{!!b_A}qt*GFthxfR9%92n*aOLTzP;)fCR zs`TN6_k?#9**^v3y|T6E&YkC%T%#ES|JBVg|3 z%a=b21OiRU=S@5gqiO(7aDyXUqY^t5xG?De1+qS`Ud~BlV`J0Bix;;^Q6-Q=wly>~ ze2}x^6bd{Jt^+2?$Gg>?1`Ace_lKf4Zru12_%Xaw>B#1xC{AIBuytf_KYaM`VU{!B zL?24M0(?`LM3J5y?APUC0WNTYTS~Fjpden1#Kr);HK%i$1%1fE>OOpUXJ1jf+1UDc7|*o3hwo|I8VMKWbLjJ3hDz19Ka~B zfXFdyq}+`|1y({1H>;X<^)n! z3cxu6XSkruKppDiIK-aP@GypBtARs|3(BbjIM^7J%})GqfVJ#8!j?^Q2&02Msa>=B z+;2o6hBHC}c}tD7Im+s*N^at(1I!ZBX#^omp432H@~+s!3Q_|^UDDL2%r`M(eNz}m wkvW1()}E!Y)s38+T0XY!)89`$;DZPL1D8ZxwWGu@GXMYp07*qoM6N<$f}&d|UjP6A literal 0 HcmV?d00001 diff --git a/res/drawable-xhdpi/ic_check_circle_filled_36.png b/res/drawable-xhdpi/ic_check_circle_filled_36.png deleted file mode 100644 index 625c7e901192ec7ea64fc2e486d0720571d473e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2455 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 VIBTQ<&FTOE002ovPDHLkV1kKYtV;j@ diff --git a/res/drawable-xhdpi/ic_crop_32.png b/res/drawable-xhdpi/ic_crop_32.png new file mode 100755 index 0000000000000000000000000000000000000000..ebddc2d9bb754f9069c313e088ed409fced944f2 GIT binary patch literal 1928 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 literal 0 HcmV?d00001 diff --git a/res/drawable-xhdpi/ic_highlighter_36.png b/res/drawable-xhdpi/ic_highlighter_36.png deleted file mode 100644 index 40bc10a95df0f700cee9bc8fd0cb3f533ca33dd5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1783 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 Hu0mjfp{30o literal 0 HcmV?d00001 diff --git a/res/drawable-xhdpi/ic_text_32.png b/res/drawable-xhdpi/ic_text_32.png new file mode 100755 index 0000000000000000000000000000000000000000..368f7282a2b8cdee84789ead0eb52eafbfc64989 GIT binary patch literal 3288 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 diff --git a/res/drawable-xhdpi/ic_trash_filled_32.png b/res/drawable-xhdpi/ic_trash_filled_32.png new file mode 100755 index 0000000000000000000000000000000000000000..3d9e02a1f10d97ce68db51e0343cbde775a90642 GIT binary patch literal 1782 zcmVPx*ut`KgRCodHnoUexRTRhhwn(vJMH?D4w3UUiE`+ojj4KySG+h`MuH2c_7~`T6 zHZ^HNVu(A43;bvkH!fU}5HxWC3lbwXU1>;*N|jm~S}NZk12g#l4Re~u`yeTvB zo#b%uyZ4@R&-tHo?|sa>6%{eX2*e2dpAo1mvh${&(y#6}{f-)8$X(xUjqqYOGQ%mAFl4~&K1J}?&xi=rrkyi~Yo)L*!_*Copn1&kEe%MB zDPh_HB2o~FkpUKY9DPh&FMd43hg32r;P`=$b2y2^8{&2GYNiAXbKXidl^)?7kv=Sb zR{X-m#KdPyOH04+?Chk(xhS=`xHv7DFKcUSJ0yQf{EWCkj9&DYED=>APt=>mr>-Zj4Arr}(7!s2IKI_sbqN7l)Y4)-#in!bHN4S?i=b#W!WbI^7HBGiJ&~6*1mF}?_kzJ%7KDa7o6lj9DZDu$J6KUFvd8WNl+;sKo)i=7j zy53PeO_wiU{(5wDbXE^I&xVE*P6N|GC@ZSx=H_P3pFjUvWo2bmLqo&S*4EaAp`oGM z8gBsG=4x}BZEUjG>Ru)Wj=J`eUleTweNN}iaV8_mq?*Z7!WdYms2{m`^XBJ`jg9OB z6~Bs3pFaJSsziTH%nt9)0OZk$6Ng7eM&3Sm?%eCDS14;9w70ikynFZVydII~l)x!t zRnuUi6L1;hoQv_kSzr#R-$OX_&>%(TAJ2#qZCF`ZnH2bM$~;>#fI_x;2q$w9Adv}W zLkgDJjNMs%%-Wgpm^AZ6uT&Ay-eES|9usIPDIP>9VcoEs&F>jH!_VLA+vH^eqf&jp#W%~tL!%kZ=l!-VS-;#JCQ*vCg z_6g#?06+*PjjXO}dSm3sD;cV)s=`SeUd}Lef@Vu#UjRrxjUJIV1t4nYIQ=C-nG7J^ zvCZsr9TJ!+|M2+byB_a#Vww#eS!}B=>Y;5RKk@-k`LHxd3czk^PXSIJI ze(%baE8n{N)gCD89$UzBJ{eGmetR3U4fLU|nwlC?loypmeSJMUwwnTF-2)4GE;a!6 zgN7&5^iL0IO8-V(T^)Oin*wFs0}FXBHULDK&B+5mX6L3ap=NYyjAp zvYo@}%}VRtP8p{!xn!MV_g(iyX5X61R4@jhOam90*>MI$24$HliZh^00~eXuaRx*N zWtl39GoVZZ7n#{{21EvBnJS7ipiBc7nb~m$LwU?J<^qi0{37VOi`As&xDn20wRA125?jg_G z^o-csK=eU*YhhvGkG)+7_oPcze`Ax_GQqMnr%_=5Fz1;hF*P;yQ%>!VXu!2=*M8Ad zcJYdD4cM9&g#iGCC}x7q;o;#il?P61Yikd>ySv9^2%pmIGF09Ggmr+On|=X zx4u8%O&~QeFmOq>aFeuE{DheGA2zTO$&XOX1YCw}>Fn%0ql?Xd9ux>;V`JaQjB9D?LIb<`FKq1dwEN!6e0=;$~*Jw5%yqXc1fb@l$>;2@DdBR(bOWa1)cQKK*Y zX(9_a!#TUTyiDr7*w@$h?&Rd;kWPocbjEM!J%LNo$wGlamuNw^MQ5e|$Nv8Qk9D7* zOLM*~ZWH4??+m<5VOyx^hZ-#95Hhdc?esI=WK_*f`vCy01_C8Z0*9SUTa;_jK9w5?>7!V4P|{{^fT5h1T)1>Wz(ocG zkv2BRd4~22GO|vG%t>?DKnWdn6dM&{oavx6Agpd>RQjDx8Ys>-=8GvtAVwfYAT$F1 Y0fFwsuOsDrQ~&?~07*qoM6N<$f;+cT3;+NC literal 0 HcmV?d00001 diff --git a/res/drawable-xhdpi/ic_trash_outline_36.png b/res/drawable-xhdpi/ic_trash_outline_36.png deleted file mode 100644 index 1721c329a43d8f2176813d4585d16fcc242d0ca7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2145 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 LNkvXXu0mjfm#YI$ literal 0 HcmV?d00001 diff --git a/res/drawable-xhdpi/ic_undo_36.png b/res/drawable-xhdpi/ic_undo_36.png deleted file mode 100644 index 8d173d16eadbeb1da4ada06a4508febff7f04495..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3365 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 P00000NkvXXu0mjfmSI-b literal 0 HcmV?d00001 diff --git a/res/drawable-xxhdpi/ic_brush_marker_32.png b/res/drawable-xxhdpi/ic_brush_marker_32.png new file mode 100755 index 0000000000000000000000000000000000000000..8e90632c390f65c0c140d1fd986de245488f92f1 GIT binary patch literal 2956 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 literal 0 HcmV?d00001 diff --git a/res/drawable-xxhdpi/ic_check_circle_filled_36.png b/res/drawable-xxhdpi/ic_check_circle_filled_36.png deleted file mode 100644 index 69c728f056dc626a25f1598d320f4a73f81df7a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5046 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 JY89J^{{z;ys~!LV diff --git a/res/drawable-xxhdpi/ic_crop_32.png b/res/drawable-xxhdpi/ic_crop_32.png new file mode 100755 index 0000000000000000000000000000000000000000..c69c5c049c61b50dbb65034389b09797f35c2382 GIT binary patch literal 3461 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 literal 0 HcmV?d00001 diff --git a/res/drawable-xxhdpi/ic_crop_lock_32.png b/res/drawable-xxhdpi/ic_crop_lock_32.png new file mode 100755 index 0000000000000000000000000000000000000000..a86488e13c6509a8b6db31f315a77514461cc12e GIT binary patch literal 4276 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 LG|;G2vyb{8k+&(t literal 0 HcmV?d00001 diff --git a/res/drawable-xxhdpi/ic_highlighter_36.png b/res/drawable-xxhdpi/ic_highlighter_36.png deleted file mode 100644 index c67056bc47fd511d3b07caa2830d60f84a38dd2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3128 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 bfY>>XA1LKXs}+~$wmbkcV=F?H5h?zEe;Gsw diff --git a/res/drawable-xxhdpi/ic_rotate_32.png b/res/drawable-xxhdpi/ic_rotate_32.png new file mode 100755 index 0000000000000000000000000000000000000000..d13035a146a8a109b668d5d0dd866c5df317a49f GIT binary patch literal 5358 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 M07*qoM6N<$g4bSLCjbBd literal 0 HcmV?d00001 diff --git a/res/drawable-xxhdpi/ic_text_32.png b/res/drawable-xxhdpi/ic_text_32.png new file mode 100755 index 0000000000000000000000000000000000000000..4dd242e401ba52b6109b0bb5eb5498934bd432c8 GIT binary patch literal 5592 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 literal 0 HcmV?d00001 diff --git a/res/drawable-xxhdpi/ic_text_36.png b/res/drawable-xxhdpi/ic_text_36.png deleted file mode 100644 index 22cbfb82ec1c45c3af40d59665a366e10e70b2ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6266 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 B4{rbf diff --git a/res/drawable-xxhdpi/ic_trash_filled_32.png b/res/drawable-xxhdpi/ic_trash_filled_32.png new file mode 100755 index 0000000000000000000000000000000000000000..6a4ccab1b61c95ba2cd9e20ac4bf9b16d841902a GIT binary patch literal 3146 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 U4qd(Wr{@9;;byREU8fiS0lIy2djJ3c diff --git a/res/drawable-xxhdpi/ic_undo_32.png b/res/drawable-xxhdpi/ic_undo_32.png new file mode 100755 index 0000000000000000000000000000000000000000..372fe355d0a2decff5268224cfcfa16cc6028c97 GIT binary patch literal 5730 zcmV-o7MPy097#k$RCodHoe7YXMV7~Dxe)=y0p)0_Y2;d@xuFM8L=ezX#zolJb-Cfn) zRgJUtB3@^H`Q`EQ|6ab#FYEiVn>EW*9)Uapc?9wZ{Tu!r$20RSIIQgR2F59GGv?J*V6P5|%VOe*Uv@jm# zaoI3DLK(OYIhsZtE<@b)6PgbO@i5K#!!o2b8HF85M+gH$UY8Bi+*$62opd}b<2np5 zVaUyOO@61j9j>F~b^+c@+JWFYOt*rl$FeyjEoamsgO&_{Lx3Vn!R+c#BR1ujdzybn*!7*s0LGF}0PMSMp z-~iI)2$8|uvMTO$=d&WHgE&OobrZU6hsXf%=KWQ1(urF}LYH@aN=npCJZqGR0zv>o zzyQgh(0Mvc2gy(8NQ1aGpp*yfnz#itXU?4B;lqc=diCnnNMIioueBb3_V3@n>#MK6`t!PV>sCDd^wV!X{P4r;R1IJw7hE31EjJAtB^0d?6T3^6L%3GE$&zqQl^`@NZemsA|7>?=&iTj zdhpwCzy0)37K!?4=gc$DoKCyqA>sjIP2!R7127fc};t?OZ$>z zj2J~=5HT^b9wTPt(N~Y|tSJGPkS<{bFv1{MEBW7Q<#+Gi-B$Nt@{$j-+iG+E`R5ni ze*5j06&4nbS2}spp#yvO?)_@#&YfG;=5Fymjk=1KEn8|jXvLh+zC(u&$F*zMj!|cK zn6lm@jyR%apFVx2X^xnxIcCXix83%@lTSXmPMMJvIdM&8V*2TM0+(cJRCiPjK(~@2 z3>6Uf=cyD>R#t}Pv=fsD!Q+Y;IB;MG`Ql#;88T#+K){vNNUCG|mMvRWe)7pDD_?x^ z#Z?OyELgv7+cvWty@W(Hf^xzR8$}%IO(y+ z9vgGT6<7RD<(~NHqmQ;L<32I6Q)j$hh4g{Gxa~$&g6d6+un_zszPw00%TRNHIVHEOQ2J#l(f;o?<3U7;s?Xq;o$eCO>l!<*8?cxU_%&{!?g&_S|+fL{3fA zziHdHEpkw{kC^%o3nhdKK(OI2yzs)k(N2sSHR^KR`@8PlyU*4V@ZIQrUt^Jr7cahF zZsSztFBN0CefOZhm>2_i!cIFotcVKoJ_sNHwq#Q~Cw60>5*;|a;iYwxjQ%;$#Ip&3^ zY`)f<^YLk?o%S>3$1tn}j|Aqh=Hi^XqiPCRv}n;h3rwhqbHj)cBmP-y?v%s4yu5tZ zgAYD9SAw4=27EdPC^0chR)ELC0TDpyDDAco)8UZme0WWqeB`Gbia{YPDN!aP1536d zXnWk_k3arT8Vx(cemJgqVe_n6voMsX5|A(FN{A|8#PiQTf1iaVT(M%sDh=O_VVdI_ z5v#R2xkQ4WAwEUSL^((dAoy~u3$P44U;;8+P{j&rB*1!(UjfkVc9Jii^a!9jvsmEGtxoM+O#aMWAfjjERw9WKmJka{Oo{|^qI*BxK z57Y|kHYMWHV1W0slzt$4D*2UMJ5>X$_U!Sy?${wsxOA{aTC!xxvWXKX{!SBK=W*l4 z_0eu-rIw}@dN?W>)$PRmMp;WEx{vH}Yp)9F2QG>IAG@U8a+f<~>9^|XeT&i)q!HixmRoMQ^{Atc@+ytK zc_Oy_iTvqAGF5=V2lxsJ_;oss9EN%5hm{dGCS6+zdllcK72Vf&-g)O-jRNM41a<7# zvH00%pJg$D)x%8gjHU+71u9=B(EyF1eI9Un%1;i~1IyCrP|fsOb@di|ID2`QiE*fS zy~r+!zS$k|EK(?DiCp^XtFJy3?GI1Un%mCQeO5(9;-83dW#D5)C|WmVGTZ@#%F#9r zAuwRI(=S;?u~@8&{Cx{8MVm|D0$9W!EG^Ge{b;9Q-=z|YF`2C3|o_MDcc2+SXht*X^ zvS+FQ@>>b`K9m5X5Uy()iU}nskAVef*glxh;NuqTA{5O!SqbhNePX%EgJFj|?zm&j z%{SltYsC|IF(FTyG-;+b8#gNbJMnHYMnpd>f7ov&SEodU)o)cxv5<@e7_iNri0ACuH_0r$6|2Mggmw4r|t|nX8Af35q93zX(1xdi3ZA zl(0k0^8};7qu6~=Qq2Tl>5@S;D1^3VgJ_G!3Q{q`!M^8F;PPn+t@7C*`UlZ3_tgq% zF1Pumwo=Zjx<|fddT}83=%bG=)bj)ViH=_CF;--66hbhBvS5q=yCN(G-x;456#A(# z8afa8L-*y;L)`{L(VUX|N1u?J=Yv8q6Y@Cib5+}_c^<@=3Y$zNB%mFM*W8xBRot&aA_3h!ZRFm;O{dj{C*jZ(?Flrd(D5FjTuQP)x zNtbLr^$F8$BNzEBzej;bYlVD$nKtX*4296Ly3MuMUOQB2jDn0uKw~N(loO)gZJ``0#<$d?vw^A+$g(OH1p@VgS?>A%EFz&2Y z%8!7W;W79g1@Xm(o(J}B-@biySnTMdk3K=m)QrKWj=TawB$MMPz#J;!fVQgFgjv}o zJ?ETr*vqmKZ21nu>`C#w0+QfJc~Na7=&kFG(VY6hsZePs0MNk|&MQD5G?cK`)$r^L_FUfA!NU8+W#PK(7^e zm(05$BT;*31uy~*=`9I1-I7S#);xScRs!)lm5^5eFx5^T1<>QyqYfVyFeT6KZGJFvS+l-4&5jEao4kXJwg!dfFJ0S2!EeX+?_ zbrMx6fVB8LQFXIUh2#~G1Y@-eTfY?$SAw=4*da|Ky&=LcVg?`J>ja+)@(KWj+R5O9 zRh;$HWcO&1&p!KXi_!qyN^q816_HnfVX8TdTfJ_BReY;KKSlP8X4jWB8%0O|!V*ukTr-1O5;Zw*b1oA{Y2}@Uw@B)fd}v()sOOj zNeZ+Q?0R_Rq}APb-#tq2wDKucf;Mc}u=LYUKjpQ=a0Foe=0x69k-Q5^Mg`zgg0J+} zI@sl}le0H#_Qo4;{6T5_V9)zQc^4D~D1++|c;4FMBRqa)WXU=Fnrp84hwyzM;(ASe zhnA!hbU%D2h;0hoSKhbQSf1g%FKhu3a(uj%K zA3|}qe(KB_xdU_p#sWfiI{9)cnA)q0EIVs^yPmF!_ZAP)FI^||pcR5o{QdXee^&Rg z{{CW=h0-WbJ@hv%N_wD3t3>ro1~nRnIlUrq$UWjsO`*&f40zyz{DDSW9mnvu(XV6l zCD87xuDa@R<@4+IOu|gS-v7y2-)uby&(OmHn1pymn;)rR;-qnpJmkefDBF}2%5J~U zi?uz(SoNq|Z@u+W?ekPSQcdS1&DZ^rVq6r~kMGBIWn}%z-(Uhr0Hp&60NAXP@rQi4 z#{2TbNn=%kBFJk&ZGlS4DH(iQJiZ(7*=Fu59{CSwDH7c zR?BgD^`UkreHA}fubN=p31Zh%6Y|_$yLRnSB0oXmf^a`gvi(3O+yMl~%2_uTY3NSW zd-R+2MaggV|v;WyskW@;z43u4`t~$@>_OAb4OMH zlPeb8RbQ5m!}3GHiErM#`G554-l@tnQan&xB<8^d3&IK+4UOrVkS!JPv;%0g%V>>> zk>^KwT#e*TCizG@U5)e_N2xyPyk7?+;fAn06b2BU8&Dz&uuHN<8AQUAbt~QEJj_Qf zM?En0Qa{#;5*PurkMcVp*Sqh&JHJPd9=Mkz(pjY&rca-Ko!$rCt{bU*KTA$?QrT=@ z&`CN+$LI`0GN#XUrtI6dFXgFO91W&(I&V`xRuOzzi1ihV@xizyua;0us1&;>14;m1J)^%(zi<;SNE6%P;>i}A;}hH&YMasd*{1ymSIHapFhjVz2Xo=llwd8$P&fTx`y z;xQcBha8qE8uIje`st@nS6&p=SB&!LBl3iP9~_#5Jj}5=K#0!+3X8;ph7KKis@|ht z9_^T~Iq>48mtJ}x#j%xiHYNr%l!4`<5IPU2xUeXbj+FyA`6);FnD_)S7LTISI<`{B z)%;1%0h6oB7<}qB`1IMXPSN@kAU1?7goi(tfikezcKURu<7=qK3GMVb|HVS1_RH-7U0_`LPKaU_z2Qa1-OpT0#O3YXg~>ZMaZ8X zKY#xG%k@^-X-ccLT@LTo(v`!zSIJGST(DrlhT!mSuQ&*80P*(a&RU*(?ztS^U819q z2kZ3S+79nl@i-ll;$Ob<$}8`e^0z1j(9Kvq;D<)w_LbalsuhR~stRDl!&KJ5`JB)oZsQ-Z8z2x}%FJ-AU9bey7TL-M9Xg@8IoB8yihaUR%O*h^2ClxU0 zga8lY3IU&ySJUXzt;2)jRwz*bfDr)jECHE3j~5q-S%nOhXDEH*i6?H-mnQFfQqE;a zyR@0n356ZWMT2h7AUX^|woY>5dZ)H07*qoM6N<$f=eU>J^%m! literal 0 HcmV?d00001 diff --git a/res/drawable-xxhdpi/ic_undo_36.png b/res/drawable-xxhdpi/ic_undo_36.png deleted file mode 100644 index b5877cfcb5401c72287f313b9a7f340ef64774db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6136 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 G$o~LXu+2yS diff --git a/res/drawable-xxxhdpi/ic_brush_highlight_32.png b/res/drawable-xxxhdpi/ic_brush_highlight_32.png new file mode 100755 index 0000000000000000000000000000000000000000..331b5615d7cdae65875c2ddf8cb4d88ccf911770 GIT binary patch literal 4435 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 literal 0 HcmV?d00001 diff --git a/res/drawable-xxxhdpi/ic_camera_emoji_36.png b/res/drawable-xxxhdpi/ic_camera_emoji_36.png deleted file mode 100644 index 5bdb14b6eaa2141c1f2996a610cbc2c8f223400d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14964 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 S?)x@UfQ*Eqc=dOqp#KBzcxO5Q diff --git a/res/drawable-xxxhdpi/ic_check_circle_32.png b/res/drawable-xxxhdpi/ic_check_circle_32.png new file mode 100755 index 0000000000000000000000000000000000000000..8241bd663c81104f5d9e001ee3f27682aae7e1ad GIT binary patch literal 7187 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 literal 0 HcmV?d00001 diff --git a/res/drawable-xxxhdpi/ic_check_circle_filled_36.png b/res/drawable-xxxhdpi/ic_check_circle_filled_36.png deleted file mode 100644 index 2edd336b38c57e1cb6051014a81c77b567853757..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7994 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�_dHoLL>q!l^g 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 literal 0 HcmV?d00001 diff --git a/res/drawable-xxxhdpi/ic_crop_unlock_32.png b/res/drawable-xxxhdpi/ic_crop_unlock_32.png new file mode 100755 index 0000000000000000000000000000000000000000..6a3e084b35215b2dcee00f43250ea9cd079ae363 GIT binary patch literal 6579 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 b`S(IQG=V6a&@S%lC=7tmFi@|2V2A!cs#%!h literal 0 HcmV?d00001 diff --git a/res/drawable-xxxhdpi/ic_emoji_32.png b/res/drawable-xxxhdpi/ic_emoji_32.png new file mode 100755 index 0000000000000000000000000000000000000000..2d5d626fe492e338f3947816a7928f06c151239d GIT binary patch literal 12431 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 CcT`3I literal 0 HcmV?d00001 diff --git a/res/drawable-xxxhdpi/ic_flip_32.png b/res/drawable-xxxhdpi/ic_flip_32.png new file mode 100755 index 0000000000000000000000000000000000000000..8e86977d6a423fa2c2fd0abda663e5b66cd08cbb GIT binary patch literal 6175 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 Mwy{=?ro+?!1C6D8w*UYD literal 0 HcmV?d00001 diff --git a/res/drawable-xxxhdpi/ic_highlighter_36.png b/res/drawable-xxxhdpi/ic_highlighter_36.png deleted file mode 100644 index 296e2b93e0bd7a78b4d68d26f4dd9a3031204824..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4996 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 diff --git a/res/drawable-xxxhdpi/ic_rotate_32.png b/res/drawable-xxxhdpi/ic_rotate_32.png new file mode 100755 index 0000000000000000000000000000000000000000..c66cf2b23588a65b4c7b2b19d84f6a882b4a2f7b GIT binary patch literal 7824 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 literal 0 HcmV?d00001 diff --git a/res/drawable-xxxhdpi/ic_text_36.png b/res/drawable-xxxhdpi/ic_text_36.png deleted file mode 100644 index b1f4eed53251e4254aa1d0fab261989d14c5a233..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9036 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 O08KSr#5WbI7ykpOp+9T@ literal 0 HcmV?d00001 diff --git a/res/drawable-xxxhdpi/ic_trash_outline_36.png b/res/drawable-xxxhdpi/ic_trash_outline_36.png deleted file mode 100644 index 2fccd17e7a7282b4f19f13c890651487b49ce893..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5086 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 diff --git a/res/drawable-xxxhdpi/ic_undo_32.png b/res/drawable-xxxhdpi/ic_undo_32.png new file mode 100755 index 0000000000000000000000000000000000000000..656c45b39f9b34acfa6e7835980f93f8f303bab4 GIT binary patch literal 8522 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 literal 0 HcmV?d00001 diff --git a/res/drawable-xxxhdpi/ic_undo_36.png b/res/drawable-xxxhdpi/ic_undo_36.png deleted file mode 100644 index 44300d0f547fd5b3e47190b7c8a1d29644530721..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8989 zcmbta1ydYNw8er2mq3su*y8T6xVr}@5Oi_Z0NG$6!C5@G2Dji6+=4Ccy0~kA0B^td z6W*(?nXajtn(Cgu_w+gEc9fQeA}%%sHWCsNuCkJx4x*3$@4`e!-1ii=nh_ncr;efw zQq?%s0TL43yt16Mo*(i_7FN7|f6HJvvJokXH3o*X)+g*zW>r%p0heY17U?O&_W+3k zf~)8Zs6;uxw%!&6!)^<(*|NX+yLMl5UNHe$C^K>>9bGQ7f)oUD_hPmyIqP|ve&MmV z)^c|_Zg4X;zgnWn_40f-ACw~ETarbjOrZ3CZbKX>xE>~^!>Moj=_%GJ4lMZrBJJCX z1xP2Q;&_kuL7V4(&VEwa@luv)S3Q2@Rh54d#Zp)di{@%;KDcj2BvW7VIFXMRb^%`r zQs8ZKj)MDoYvNK11?+ET|29ALGzeR4!?u)|D?r*i*PVA%py(;~rDokF*#TnxhW z({R-#IBMC(F;S1%j$aK__G9l8XQ&D$edF>+`R69>?BziV!yX9jarce;at6|^ zyGg3zicNUoI~*gmH2a0Y)iv8x{Lo_%lI^Qcs7`KCfl|)m`@qo3VVM`I*m_Ho6^RP{Zhm*lRSA@ENUGiHs_!SzD}48p%9qD0Knvet2|Tl zp(~g}L-e4~1%t{>s;SDX&1canPFz&Td8xs>Kp`gMr2T4qtj5O1MxB+FRnTRv-M_b3 zJ#$XAEBVvY{ay~&i(H*W_ZJ&Y&_!R}V!d5RWxz@>FChb`$iO zLauAIbsg`4Sz?LBea`|JoGL40#dY9_&@C5;% zrNf2oiIM-!q;Qx}IIXt+D#OL4;9p>^cKa5K%78sYFjAk;4h3JPv2%)%N^VEME@IIw2K`-Lf46Wq0Qeig;|Nf&lv zTH{Ztb%e>OzuNuM3~=1Qe=oX&)r}^+^sTr(+KCk6(s{p&su%|dO1Tw4WxE=hF>18m z{#V()qaX;=S;}H-Z*=Ioo}2lpd-ek73K7wSw^mODC*dU=$EX1VX#yE-SfY2ZwV(2o93F6_XsNA61 zobG97J5KU>XVrK8X=hAm-L$e}RMa2)@J{NakgX2ABjCoN@op`!i5%qT7P;0DSiZz* zw$$i6I&0#3QZ4Fa_w@7FuQ2E3-(HjC^WW_pmhPtr;jr4Rlp{5=U+Q+WM zrMn@S>^HDox=E)+enLnD%ajxfAeXj5;Md(0qwj08gCE|L(ikz$3pKRawDg3Q60px> z*?e~6?P6!`p3fCV^_{RN01kUtZP6cA6c(q7n)jNC5hYnZ#(`Dmx67_woq?w`YUSp!P1@g^POp*guaArG;W@Sa9n9cPV8a_A3|H!OV{ z8B#d>08Er$1dz3FJDT$Hx!WX|(x}{Fmm>|PH#9;nE2J40Svo)0uk4;4ZrIjCUY@$Z zR}Wk2LaW!BHg`x18B%?{-KAiu-_ea>Zzj?la-7nKrtP=-qMi^x_V4Cuo3CWM`}RN^ z>r)_n9kD0Cj;h*DGaRcsQpyFBhLW&ct>gL%^E+NKX?J3w)i95yV$JASVqQl$Wqg%l zVk68&iZa4b5(8_Emm z&WLCeK@3W>8T5Ci-0wu-9Lo*h=^gx#zr8gDv7!!M67!Y6k(2 zrMxl#;^Db$OcOVvSqz8_KAQiz42OKKQ5~2LB}OM7gR%{tW)-_=Mmes!{L67(@+9mK ziawP>MI@x(YT#X?KW7Ky24Gu-QS*V5x z9LjU3DB16r94GOx57*Tczj zLj2%{i_Pxa2CYd!ivsheSNJxcK~w5J-O41(=Tr z(H-Id>-{;GZNeT z@ID~S99tFzNSyjF^5A*8E@dMH;ueD2SGp zWK6{r9iFGnD{Y)o8n1*CAOzMt2-ayIu@GM)pGc&dcZKaF2p#$_^^Z^{mYTYM9hS?h zo*}zUx=k*0B7-!{g*Z=78>9C=- z3S`OVJg#0&5F&zCT6l*I@KNICnu*q1lObQ1ISpL?2X6j+7pH$;|SB0{@A=N9_c zkW{oD15IhRIwRh|cyoab%6OY^{gOTpQj}xhkh>)Snmd19^G|WatO7N&LCVC~T((=5 z7hVLseMnpXeSIfWiuQBEkLC_31@S4yhwlLl+-B+On8btDJQjwL1q`E zHGB1G5wVqVV>V`F zcJ3sqR?P;(S7)ZEo)c6{IME>wAa27MqKK^b%#@8W+;Y6{C`FGw{SFJB)z%;w4xm1kSKPCbs01{_tRlq({aN8nLEL?2?f{l3#rOVz|r#3M}( z^W#|<_yY*1taWP0Tn{|!kev|O`*E~oTy6E@iJ%jmrB)7(=>i;|t5X@QIMnvtTZ{4&C`kKhoWx3L&k^50kEW`_&6AjsI)bumEGoY}!#_FQ! zwD(`aM_p%}V<1x+`#eLD0aq8MMVV5DGsM`S{jORq?m)|$L)Coi8=S8Q*@BWpJC34~ zw(bsVj}Gs1&$^l2Yn`)_(Z;g`epK-`>M{(>C%o*N9jH-G0=9XduJ|WZt)#G2*9xEm z)yIKaURwHg8vRHM6iA{mTi#T=Kf=?fn{bcVv!gzp=Rb z#09u)ICjS}eG?>b+*@H~QJh-4N52-aRIIV;>!6FT-119%>2M*Vg zbq}xrqS_^Pukv@08Rm;Dlrfv-YdtfR^^0F@9t~e8g?JCcy^Pk)AG;S@RXbGRY3#Q$ zw1BW9hAD-)pEVR3KGf)+ojyyg%nfc`CUya_?6gS8lYki|$Qt;A~@y?`@r zyE7!fF1r*Cct5f(YoGSjbl+c|&5CHV^yjC5@LQP@)??7mq?_Z4B!HY`G1+-@ATHqc z&%i=+$z|#Y%>-+xMJ9@D7G`Djh(o<)aHLsrH4phRA z$AghB9=T5p_vIXUfBFiwvlcJJgj(5*BcUNx} zs%pme&EkaVEWB~K_3Zeu9mjd@ab{vr-)}!J63;-C;evs|36>_@=q}Fy7DGaDH~*Tt zFQyu({CKxNWtEmvcf(_DU;j++Q+P?m3Lg$`Y3P6&d~D9J`VdY$oFR8}0-2eUYa~Vv zq%moC5YR02?VmsTa(t8KF&g|Zodd}C3IwoQ0TO|Zms%fW-f1yYN6~9Lc!C_~D$?Co zHymkI@UciZExqaRZy3?O$#(pOsZmwj1>DLkj5VzXKdy{e%^Fv?!JHaoQFwN5<$&?d zzdZS(7|=%0infNW=!z1QUNoCh_AI7~FRLb_n6ihKqqK>nDIBjGqPMXiyb)y^Z)x#~ z6!S^)t``sem+SOi%FobiqIu@tf0Y%cjhFiS!T`jdGshg|ZIoZf{ubK1^g-q@8lSM*-aM)_zo77SX22*zs-raX2(X8 z*_zBPYX(g&HNQFiHE-UILUbcDp7D!G1=AW+bxn{CehP?1GtoFOh(GFaAxTR7&2APGOv8t&s-t6T0G3t zi%1L|~HA1@`vrW5aJ3~Q}XG$%E3mdPOm^d z8;&hSCFysw>X^im%#|sL1*wy+Jl`u!P*i7~ZYmnx&M0Q%#w20H-Kh<;EU~dBMzKND zowDY2uhGv|+?-Lpe89&s&($P$&h^*CL@8P`t-x8Pv{47Js$imF7txw$sL>IZ9@^ZG zy!=)=8v9RWWD}{ACzWdSxiexxqUFE~6vG8~LB zg|i8mtxB;oruw>z{Q*VEW^UcDp4j5_9rs6)*~s=;*&l510t@1mX2(bQ5euhV_>Dd% zs;}AqKqW|6y6c>ezbfis4EK3kE$qBc$3JM2yV?qV&I$jo(fZnN(t5Iujpcxj?0@wzV z>LNI+nF5A+qh!vKj2rbH#~&C6eI8^Sk1vbPUWr$N{Ib=PDa?9~{hg9I5~z`plQ3X4 zrWX+RcKn=Q+xoce_;Kv$9arOG(_8HmzUx6v#fWekWS*dfJr%-X`z0smPBZ#U${?+* zjnU;{+9-1SuX=EQk~RO8X7|;bDNjY2YrS!r}d7A?3=@U4LlFFoK{5r3KTm-Hxbs50?)g^^>R`{}L|qq=*o$aEy; zcj&|I$)l|J^0y~s^QZSqdk7{kqH&+UW+zls8;9M2?>%RPeEP}-Z?1AdH%2p`e%&suN>r;H;LN6nfiYG zmVxA(l=dVJ)keCK;dimqObefW!$Lh}YbvJ$KC6$Hg-Qj&fqBIf2yLzWfShcJT@n?% zbwGo#Iv>jMoN#8)KB77w!^SIBW%4k01Sy-{z~4Bvcf#KxS-f)+u_Yo@7&1AQ=_0(N zp-e2vn4hWz5(CxtgN|zlH8u)M?fJ}jz_3D-WPl<7L_qFOw50HTnDsQ)+S?f^fMCk@ArnmNk$|X|_)upC8ZS=G{5Pr%2N3kiI+K zp^F{Xg17<9HXIaK%e$SK!q-eOpjHM~&zGk=&9W#^PSEY*@Q6^v5I70kr6W;g41v~imr3!*+o?Ym0Cjha)Takd#@EXSDGKi3lAKv9a%%vY;rF> zeJPxnLmw43dJ03+2Eu%x?P*e8e~>&fI|~{VOB_#kZy|L>^INMF9pZXcqZ6lS~J(u(Qt{mN*}s z!huVSBVuwRXsE=%H^hXXd?DP|;gF0(lRSEyDy%*=2wK)Jrz`@-ILLH)`m{-ti?|*_ z@!&&m6L?LKvym;{k;j(`v7#mH(;vdq1*IH@aEEEdLZdPIlMsl-XyZYZe;24RIY{ul z**S>Nb3wOn;7^e2cP!a0rYc6AdscDBf|J?QGW%b#`q;yy0;z(orvkr&*tUOrWJthY zQfzlGM)2L*i+?-4@h z^5F581YPu#eZOADmwf+BU&!u=G=X#-Ul-X!iOj$UQYmx;zmAg2tRo$lmxVQl+zJCV z9N`7k@mX+NSC&WW_8|hZZ<>>Q!yYVXF2)~AB-Z(!(m+TGNOIE|^? zwhUEN1OXCvE1qP|i*-fsi4YY8a8{KXkoAR|B@oFrzeBsF2TICF6uK`?nh|T%=CqJna)(5+-n!cKy+jyCWPMGYqbQt}P{wb-Y;9$Z4ST&XNDf1FA zETZ!;njO_yhm3zGejVe}(t&*{EK{;im4#+6WxI;Latf2ULtxgu@pvbXn}E^Sz+S-Z zv53sx0_BZ?pCk)ko2dhxv=({-Jn@0tbV%+AM;MicFMqF+IAk^hcj)TUWX0}9(c)Y4`|p!I<*7F;qUmsl^jOR_X_d@|_9BIa zP96(&-K%%0a&=q-gQybWr3&5f|19wq$K!=sF4k#ZSaVx#CbZMYSo^1mb)^X@p8ix> z+hSql$95Ujh0t*MRW2v0MV~o4-^}vWlB1WFft2LrO=?GI(^`OI+4I#kr_JB@t$8{J z<&Q_t{Wr>smrPzYo&7sM#{?0;yh}0m$EY_FpN5@iQ{V#;uQX4F0&NdAuH#~Cqy`vyCr%?D^a2tb98luP;77Ez^ftbQ6N4S2C} zL&vR{#GmXeL(cF)m|&bb!R>_EgM1{f7j6|kyPRJL_MOC#R9wo1#Uyjc(L42|e+H&R zDRk+`>9(QAQi*t|wfUSZ{GDgbz;Qf96rhec+s}K1poCjt*pU72kHojMPF;071~>}A zj>=qF0kVh^86c}8{^#OCh!xCw=t*E7$Q}e93=9{bV0NCQ$?fa@bgM z!f5MgJ#_A>h7GI0cqSPE6!1?6k3ni*oN4E8(D0}DN&|&9T;HM+t5|FUR(@-?}~fxjq70KY$IA^ z&}2l*M+E!51NiSG+#S*NghBYH7|WT5WS3v7ziWc{aAO*x_qj-3E3oh$#I()fgU)}q z1n{})6|X75i{ym%C16B%w<`#@`l#ye)05VTfhZDKMj%0$Ni<0o);8AA)EyUmU2t2V z7sN@S4jmZfgG+>9mxGk^kWwXbB&+ zptZydZ26WL>9c6k8q>JQPk-bI`fNlNUqGz>?%S1z1zos-C{R0j7X9%nA-%#syOqJ@ z!-Yod6haq=L*BM1DBI5;oBGXBL)cKsDxBF55a!nXHOT?;OhOE?Pg=I(l?L>f!`dsPnTLoOb+@C4nE<(VHYJY! zZz}@XcUZ8eJX+-9*s@`gXcCVXgEZ9!1@Casc-&=RH4{Ak?eiCjMY8?U0E#VSdQwrhoW=4&Nw-lBG>;9}dqhxsl*vF1A7yhM~D)enQ}{E#lAZl?Fe8d;*-zFm*2 zk!4gmQg}&B3^8&3NyqS!J}hyKZt*zCwS|benjiy#WgvahFd|+PQ-zmFrmlGdOq^RW z9JZG=g%}_`aRI7GMkq z_*LphAi+j+P@X`-yVzkgZ8Zks*F=lDiyjqf_}t4eZ~2N{eU+CRo!j>1e~tg+7wmGW z*j{H_sh)Z&n(#8QXffw9>ipRM&E}Je!3SBh!s;*5L`g`LoQil>m6qn1Rxl}&@-O;m zbf)}U5S9$|*-3&XVoFxDy5ga{W-Mz*k44d(;k_%$L-pTgeLquL*ZzqtoScSLWq<_q_u>i(!ybxj`b zC5&{YRUmy!BBABr-?G}Y0!(1v zjByZkin@q_aA#j~$}(jLZZc@ImizR|v9xh1mv1t@M-V3xtid#P0M#UqT5|r$curR1 zgXS)|Re@#MBODu}iW+AxQYep+?pLav==KNv1MwQ0-EsoaKgV2^ngapB#h^MydP_(C z(@#^|JKvMyk*2sW>?v%*z?{?ISj2G(KgPwsI26>kT%1&i5nDZ=b%RezNIkL351$5| zvpQuLPLQ1<_iIE6Z$)t0LfpX;wv>ty_Qw3Dp2V5&;{P8_>ov*?##e?Wf4-B~7>M&O ONXqgWa#b=GU;YPLWNK*u diff --git a/res/layout/scribble_fragment.xml b/res/layout/image_editor_fragment.xml similarity index 50% rename from res/layout/scribble_fragment.xml rename to res/layout/image_editor_fragment.xml index 2f42b4893..f3935cadc 100644 --- a/res/layout/scribble_fragment.xml +++ b/res/layout/image_editor_fragment.xml @@ -1,20 +1,18 @@ + android:layout_height="match_parent"> - - diff --git a/res/layout/scribble_hud.xml b/res/layout/image_editor_hud.xml similarity index 68% rename from res/layout/scribble_hud.xml rename to res/layout/image_editor_hud.xml index e77a2f5e4..b522492a1 100644 --- a/res/layout/scribble_hud.xml +++ b/res/layout/image_editor_hud.xml @@ -34,7 +34,7 @@ android:layout_height="wrap_content" android:background="?attr/selectableItemBackgroundBorderless" android:padding="8dp" - android:src="@drawable/ic_trash_outline_36" /> + android:src="@drawable/ic_trash_filled_32" /> - - - - + android:src="@drawable/ic_undo_32" /> + android:src="@drawable/ic_text_32" /> + + + + + android:src="@drawable/ic_emoji_32" /> + + + android:src="@drawable/ic_check_circle_32" /> @@ -113,6 +121,36 @@ app:layout_constraintTop_toBottomOf="@+id/scribble_color_picker" app:layout_constraintVertical_bias="0.0" /> + + + + + + \ No newline at end of file diff --git a/res/layout/mediasend_fragment.xml b/res/layout/mediasend_fragment.xml index 7037fb199..97c63cb4b 100644 --- a/res/layout/mediasend_fragment.xml +++ b/res/layout/mediasend_fragment.xml @@ -25,6 +25,7 @@ android:layout_height="match_parent"> - - - diff --git a/res/layout/scribble_view.xml b/res/layout/scribble_view.xml deleted file mode 100644 index 29abcf442..000000000 --- a/res/layout/scribble_view.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/res/values/crop_area_renderer.xml b/res/values/crop_area_renderer.xml new file mode 100644 index 000000000..953c9c04c --- /dev/null +++ b/res/values/crop_area_renderer.xml @@ -0,0 +1,10 @@ + + + + 32dp + 2dp + + #ffffffff + #7f000000 + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 19dc61e60..8ae1ebe47 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -623,6 +623,8 @@ Failed to save image changes + Signal + No results found for \'%s\' Conversations diff --git a/src/org/thoughtcrime/securesms/imageeditor/Bounds.java b/src/org/thoughtcrime/securesms/imageeditor/Bounds.java new file mode 100644 index 000000000..0b8faf663 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/Bounds.java @@ -0,0 +1,29 @@ +package org.thoughtcrime.securesms.imageeditor; + +import android.graphics.RectF; + +/** + * The local extent of a {@link org.thoughtcrime.securesms.imageeditor.model.EditorElement}. + * i.e. all {@link org.thoughtcrime.securesms.imageeditor.model.EditorElement}s have a bounding rectangle from: + *

+ * {@link #LEFT} to {@link #RIGHT} and from {@link #TOP} to {@link #BOTTOM}. + */ +public final class Bounds { + + public static final float LEFT = -1000f; + public static final float RIGHT = 1000f; + + public static final float TOP = -1000f; + public static final float BOTTOM = 1000f; + + public static final float CENTRE_X = (LEFT + RIGHT) / 2f; + public static final float CENTRE_Y = (TOP + BOTTOM) / 2f; + + public static final float[] CENTRE = new float[]{ CENTRE_X, CENTRE_Y }; + + static RectF newFullBounds() { + return new RectF(LEFT, TOP, RIGHT, BOTTOM); + } + + public static RectF FULL_BOUNDS = newFullBounds(); +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/CanvasMatrix.java b/src/org/thoughtcrime/securesms/imageeditor/CanvasMatrix.java new file mode 100644 index 000000000..b3fd5bbd9 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/CanvasMatrix.java @@ -0,0 +1,78 @@ +package org.thoughtcrime.securesms.imageeditor; + +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.RectF; +import android.support.annotation.NonNull; + +/** + * Tracks the current matrix for a canvas. + *

+ * This is because you cannot reliably call {@link Canvas#setMatrix(Matrix)}. + * {@link Canvas#getMatrix()} provides this hint in its documentation: + * "track relevant transform state outside of the canvas." + *

+ * To achieve this, any changes to the canvas matrix must be done via this class, including save and + * restore operations where the matrix was altered in between. + */ +public final class CanvasMatrix { + + private final static int STACK_HEIGHT_LIMIT = 16; + + private final Canvas canvas; + private final Matrix canvasMatrix = new Matrix(); + private final Matrix temp = new Matrix(); + private final Matrix[] stack = new Matrix[STACK_HEIGHT_LIMIT]; + private int stackHeight; + + CanvasMatrix(Canvas canvas) { + this.canvas = canvas; + for (int i = 0; i < stack.length; i++) { + stack[i] = new Matrix(); + } + } + + public void concat(@NonNull Matrix matrix) { + canvas.concat(matrix); + canvasMatrix.preConcat(matrix); + } + + void save() { + canvas.save(); + if (stackHeight == STACK_HEIGHT_LIMIT) { + throw new AssertionError("Not enough space on stack"); + } + stack[stackHeight++].set(canvasMatrix); + } + + void restore() { + canvas.restore(); + canvasMatrix.set(stack[--stackHeight]); + } + + void getCurrent(@NonNull Matrix into) { + into.set(canvasMatrix); + } + + public void setToIdentity() { + if (canvasMatrix.invert(temp)) { + concat(temp); + } + } + + public void initial(Matrix viewMatrix) { + concat(viewMatrix); + } + + boolean mapRect(@NonNull RectF dst, @NonNull RectF src) { + return canvasMatrix.mapRect(dst, src); + } + + public void mapPoints(float[] dst, float[] src) { + canvasMatrix.mapPoints(dst, src); + } + + public void copyTo(@NonNull Matrix matrix) { + matrix.set(canvasMatrix); + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/ColorableRenderer.java b/src/org/thoughtcrime/securesms/imageeditor/ColorableRenderer.java new file mode 100644 index 000000000..71a159711 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/ColorableRenderer.java @@ -0,0 +1,16 @@ +package org.thoughtcrime.securesms.imageeditor; + +import android.support.annotation.ColorInt; + +/** + * A renderer that can have its color changed. + *

+ * For example, Lines and Text can change color. + */ +public interface ColorableRenderer extends Renderer { + + @ColorInt + int getColor(); + + void setColor(@ColorInt int color); +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/DrawingSession.java b/src/org/thoughtcrime/securesms/imageeditor/DrawingSession.java new file mode 100644 index 000000000..72dcaa27b --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/DrawingSession.java @@ -0,0 +1,45 @@ +package org.thoughtcrime.securesms.imageeditor; + +import android.graphics.Matrix; +import android.graphics.PointF; +import android.support.annotation.NonNull; + +import org.thoughtcrime.securesms.imageeditor.model.EditorElement; +import org.thoughtcrime.securesms.imageeditor.renderers.BezierDrawingRenderer; + +/** + * Passes touch events into a {@link BezierDrawingRenderer}. + */ +class DrawingSession extends ElementEditSession { + + private final BezierDrawingRenderer renderer; + + private DrawingSession(@NonNull EditorElement selected, @NonNull Matrix inverseMatrix, @NonNull BezierDrawingRenderer renderer) { + super(selected, inverseMatrix); + this.renderer = renderer; + } + + public static EditSession start(EditorElement element, BezierDrawingRenderer renderer, Matrix inverseMatrix, PointF point) { + DrawingSession drawingSession = new DrawingSession(element, inverseMatrix, renderer); + drawingSession.setScreenStartPoint(0, point); + renderer.setFirstPoint(drawingSession.startPointElement[0]); + return drawingSession; + } + + @Override + public void movePoint(int p, @NonNull PointF point) { + if (p != 0) return; + setScreenEndPoint(p, point); + renderer.addNewPoint(endPointElement[0]); + } + + @Override + public EditSession newPoint(Matrix newInverse, PointF point, int p) { + return this; + } + + @Override + public EditSession removePoint(Matrix newInverse, int p) { + return this; + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/EditSession.java b/src/org/thoughtcrime/securesms/imageeditor/EditSession.java new file mode 100644 index 000000000..3c79c07b4 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/EditSession.java @@ -0,0 +1,30 @@ +package org.thoughtcrime.securesms.imageeditor; + +import android.graphics.Matrix; +import android.graphics.PointF; + +import org.thoughtcrime.securesms.imageeditor.model.EditorElement; + +/** + * Represents an underway edit of the image. + *

+ * Accepts new touch positions, new touch points, released touch points and when complete can commit the edit. + *

+ * Examples of edit session implementations are, Drag, Draw, Resize: + *

+ * {@link ElementDragEditSession} for dragging with a single finger. + * {@link ElementScaleEditSession} for resize/dragging with two fingers. + * {@link DrawingSession} for drawing with a single finger. + */ +interface EditSession { + + void movePoint(int p, PointF point); + + EditorElement getSelected(); + + EditSession newPoint(Matrix newInverse, PointF point, int p); + + EditSession removePoint(Matrix newInverse, int p); + + void commit(); +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/ElementDragEditSession.java b/src/org/thoughtcrime/securesms/imageeditor/ElementDragEditSession.java new file mode 100644 index 000000000..732175104 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/ElementDragEditSession.java @@ -0,0 +1,42 @@ +package org.thoughtcrime.securesms.imageeditor; + +import android.graphics.Matrix; +import android.graphics.PointF; +import android.support.annotation.NonNull; + +import org.thoughtcrime.securesms.imageeditor.model.EditorElement; + +final class ElementDragEditSession extends ElementEditSession { + + private ElementDragEditSession(@NonNull EditorElement selected, @NonNull Matrix inverseMatrix) { + super(selected, inverseMatrix); + } + + static ElementDragEditSession startDrag(@NonNull EditorElement selected, @NonNull Matrix inverseViewModelMatrix, @NonNull PointF point) { + if (!selected.getFlags().isEditable()) return null; + + ElementDragEditSession elementDragEditSession = new ElementDragEditSession(selected, inverseViewModelMatrix); + elementDragEditSession.setScreenStartPoint(0, point); + elementDragEditSession.setScreenEndPoint(0, point); + + return elementDragEditSession; + } + + @Override + public void movePoint(int p, @NonNull PointF point) { + setScreenEndPoint(p, point); + + selected.getEditorMatrix() + .setTranslate(endPointElement[0].x - startPointElement[0].x, endPointElement[0].y - startPointElement[0].y); + } + + @Override + public EditSession newPoint(Matrix newInverse, PointF point, int p) { + return ElementScaleEditSession.startScale(this, newInverse, point, p); + } + + @Override + public EditSession removePoint(Matrix newInverse, int p) { + return this; + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/ElementEditSession.java b/src/org/thoughtcrime/securesms/imageeditor/ElementEditSession.java new file mode 100644 index 000000000..cc37ddb58 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/ElementEditSession.java @@ -0,0 +1,69 @@ +package org.thoughtcrime.securesms.imageeditor; + +import android.graphics.Matrix; +import android.graphics.PointF; +import android.support.annotation.NonNull; + +import org.thoughtcrime.securesms.imageeditor.model.EditorElement; + +abstract class ElementEditSession implements EditSession { + + private final Matrix inverseMatrix; + + final EditorElement selected; + + final PointF[] startPointElement = newTwoPointArray(); + final PointF[] endPointElement = newTwoPointArray(); + final PointF[] startPointScreen = newTwoPointArray(); + final PointF[] endPointScreen = newTwoPointArray(); + + ElementEditSession(@NonNull EditorElement selected, @NonNull Matrix inverseMatrix) { + this.selected = selected; + this.inverseMatrix = inverseMatrix; + } + + void setScreenStartPoint(int p, @NonNull PointF point) { + startPointScreen[p] = point; + mapPoint(startPointElement[p], inverseMatrix, point); + } + + void setScreenEndPoint(int p, @NonNull PointF point) { + endPointScreen[p] = point; + mapPoint(endPointElement[p], inverseMatrix, point); + } + + @Override + public abstract void movePoint(int p, @NonNull PointF point); + + @Override + public void commit() { + selected.commitEditorMatrix(); + } + + @Override + public EditorElement getSelected() { + return selected; + } + + private static PointF[] newTwoPointArray() { + PointF[] array = new PointF[2]; + for (int i = 0; i < array.length; i++) { + array[i] = new PointF(); + } + return array; + } + + /** + * Map src to dst using the matrix. + * + * @param dst Output point. + * @param matrix Matrix to transform point with. + * @param src Input point. + */ + static void mapPoint(@NonNull PointF dst, @NonNull Matrix matrix, @NonNull PointF src) { + float[] in = { src.x, src.y }; + float[] out = new float[2]; + matrix.mapPoints(out, in); + dst.set(out[0], out[1]); + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/ElementScaleEditSession.java b/src/org/thoughtcrime/securesms/imageeditor/ElementScaleEditSession.java new file mode 100644 index 000000000..95197c1fb --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/ElementScaleEditSession.java @@ -0,0 +1,97 @@ +package org.thoughtcrime.securesms.imageeditor; + +import android.graphics.Matrix; +import android.graphics.PointF; +import android.support.annotation.NonNull; + +import org.thoughtcrime.securesms.imageeditor.model.EditorElement; + +final class ElementScaleEditSession extends ElementEditSession { + + private ElementScaleEditSession(EditorElement selected, Matrix inverseMatrix) { + super(selected, inverseMatrix); + } + + static ElementScaleEditSession startScale(@NonNull ElementDragEditSession session, @NonNull Matrix inverseMatrix, @NonNull PointF point, int p) { + session.commit(); + ElementScaleEditSession newSession = new ElementScaleEditSession(session.selected, inverseMatrix); + newSession.setScreenStartPoint(1 - p, session.endPointScreen[0]); + newSession.setScreenEndPoint(1 - p, session.endPointScreen[0]); + newSession.setScreenStartPoint(p, point); + newSession.setScreenEndPoint(p, point); + return newSession; + } + + @Override + public void movePoint(int p, @NonNull PointF point) { + setScreenEndPoint(p, point); + Matrix editorMatrix = selected.getEditorMatrix(); + + editorMatrix.reset(); + + if (selected.getFlags().isAspectLocked()) { + + float scale = (float) findScale(startPointElement, endPointElement); + + editorMatrix.postTranslate(-startPointElement[0].x, -startPointElement[0].y); + editorMatrix.postScale(scale, scale); + + double angle = angle(endPointElement[0], endPointElement[1]) - angle(startPointElement[0], startPointElement[1]); + + if (!selected.getFlags().isRotateLocked()) { + editorMatrix.postRotate((float) Math.toDegrees(angle)); + } + + editorMatrix.postTranslate(endPointElement[0].x, endPointElement[0].y); + } else { + editorMatrix.postTranslate(-startPointElement[0].x, -startPointElement[0].y); + + float scaleX = (endPointElement[1].x - endPointElement[0].x) / (startPointElement[1].x - startPointElement[0].x); + float scaleY = (endPointElement[1].y - endPointElement[0].y) / (startPointElement[1].y - startPointElement[0].y); + + editorMatrix.postScale(scaleX, scaleY); + + editorMatrix.postTranslate(endPointElement[0].x, endPointElement[0].y); + } + } + + @Override + public EditSession newPoint(Matrix newInverse, PointF point, int p) { + return this; + } + + @Override + public EditSession removePoint(Matrix newInverse, int p) { + return convertToDrag(p, newInverse); + } + + private static double angle(PointF a, PointF b) { + return Math.atan2(a.y - b.y, a.x - b.x); + } + + private ElementDragEditSession convertToDrag(int p, Matrix inverse) { + return ElementDragEditSession.startDrag(selected, inverse, endPointScreen[1 - p]); + } + + /** + * Find relative distance between an old and new set of Points. + * + * @param from Pair of points. + * @param to New pair of points. + * @return Scale + */ + private static double findScale(@NonNull PointF[] from, @NonNull PointF[] to) { + float originalD2 = getDistanceSquared(from[0], from[1]); + float newD2 = getDistanceSquared(to[0], to[1]); + return Math.sqrt(newD2 / originalD2); + } + + /** + * Distance between two points squared. + */ + private static float getDistanceSquared(@NonNull PointF a, @NonNull PointF b) { + float dx = a.x - b.x; + float dy = a.y - b.y; + return dx * dx + dy * dy; + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/HiddenEditText.java b/src/org/thoughtcrime/securesms/imageeditor/HiddenEditText.java new file mode 100644 index 000000000..03e252ab3 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/HiddenEditText.java @@ -0,0 +1,136 @@ +package org.thoughtcrime.securesms.imageeditor; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Color; +import android.graphics.Rect; +import android.support.annotation.Nullable; +import android.text.InputType; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.FrameLayout; + +import org.thoughtcrime.securesms.imageeditor.renderers.TextRenderer; + +/** + * Invisible {@link android.widget.EditText} that is used during in-image text editing. + */ +final class HiddenEditText extends android.support.v7.widget.AppCompatEditText { + + @SuppressLint("InlinedApi") + private static final int INCOGNITO_KEYBOARD_IME = EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING; + + @Nullable + private TextRenderer currentTextEntity; + + @Nullable + private Runnable onEndEdit; + + public HiddenEditText(Context context) { + super(context); + setAlpha(0); + setLayoutParams(new FrameLayout.LayoutParams(1, 1, Gravity.TOP | Gravity.START)); + setClickable(false); + setFocusable(true); + setFocusableInTouchMode(true); + setBackgroundColor(Color.TRANSPARENT); + setTextSize(TypedValue.COMPLEX_UNIT_SP, 1); + setInputType(InputType.TYPE_CLASS_TEXT); + setImeOptions(EditorInfo.IME_ACTION_DONE); + clearFocus(); + } + + @Override + protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { + super.onTextChanged(text, start, lengthBefore, lengthAfter); + if (currentTextEntity != null) { + currentTextEntity.setText(text.toString()); + } + } + + @Override + public void onEditorAction(int actionCode) { + super.onEditorAction(actionCode); + if (actionCode == EditorInfo.IME_ACTION_DONE && currentTextEntity != null) { + currentTextEntity.setFocused(false); + endEdit(); + } + } + + @Override + protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { + super.onFocusChanged(focused, direction, previouslyFocusedRect); + if (currentTextEntity != null) { + currentTextEntity.setFocused(focused); + if (!focused) { + endEdit(); + } + } + } + + private void endEdit() { + if (onEndEdit != null) { + onEndEdit.run(); + } + } + + @Nullable TextRenderer getCurrentTextEntity() { + return currentTextEntity; + } + + void setCurrentTextEntity(@Nullable TextRenderer currentTextEntity) { + if (this.currentTextEntity != currentTextEntity) { + if (this.currentTextEntity != null) { + this.currentTextEntity.setFocused(false); + } + this.currentTextEntity = currentTextEntity; + if (currentTextEntity != null) { + String text = currentTextEntity.getText(); + setText(text); + setSelection(text.length()); + } else { + setText(""); + } + } + } + + @Override + protected void onSelectionChanged(int selStart, int selEnd) { + super.onSelectionChanged(selStart, selEnd); + if (currentTextEntity != null) { + currentTextEntity.setSelection(selStart, selEnd); + } + } + + @Override + public boolean requestFocus(int direction, Rect previouslyFocusedRect) { + boolean focus = super.requestFocus(direction, previouslyFocusedRect); + + if (currentTextEntity != null && focus) { + currentTextEntity.setFocused(true); + InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT); + if (!imm.isAcceptingText()) { + imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_IMPLICIT_ONLY); + } + } + + return focus; + } + + public void hideKeyboard() { + InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY); + } + + public void setIncognitoKeyboardEnabled(boolean incognitoKeyboardEnabled) { + setImeOptions(incognitoKeyboardEnabled ? getImeOptions() | INCOGNITO_KEYBOARD_IME + : getImeOptions() & ~INCOGNITO_KEYBOARD_IME); + } + + public void setOnEndEdit(@Nullable Runnable onEndEdit) { + this.onEndEdit = onEndEdit; + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/ImageEditorView.java b/src/org/thoughtcrime/securesms/imageeditor/ImageEditorView.java new file mode 100644 index 000000000..7b746667f --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/ImageEditorView.java @@ -0,0 +1,426 @@ +package org.thoughtcrime.securesms.imageeditor; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Point; +import android.graphics.PointF; +import android.graphics.RectF; +import android.support.annotation.ColorInt; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.view.GestureDetectorCompat; +import android.util.AttributeSet; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.widget.FrameLayout; + +import org.thoughtcrime.securesms.imageeditor.model.EditorElement; +import org.thoughtcrime.securesms.imageeditor.model.EditorModel; +import org.thoughtcrime.securesms.imageeditor.model.ThumbRenderer; +import org.thoughtcrime.securesms.imageeditor.renderers.BezierDrawingRenderer; +import org.thoughtcrime.securesms.imageeditor.renderers.TextRenderer; + +/** + * ImageEditorView + *

+ * Android {@link android.view.View} that allows manipulation of a base image, rotate/flip/crop and + * addition and manipulation of text/drawing/and other image layers that move with the base image. + *

+ * Drawing + *

+ * Drawing is achieved by setting the {@link #color} and putting the view in {@link Mode#Draw}. + * Touch events are then passed to a new {@link BezierDrawingRenderer} on a new {@link EditorElement}. + *

+ * New images + *

+ * To add new images to the base image add via the {@link EditorModel#addElementCentered(EditorElement, float)} + * which centers the new item in the current crop area. + */ +public final class ImageEditorView extends FrameLayout { + + private HiddenEditText editText; + + @NonNull + private Mode mode = Mode.MoveAndResize; + + @ColorInt + private int color = 0xff000000; + + private float thickness = 0.02f; + + @NonNull + private Paint.Cap cap = Paint.Cap.ROUND; + + private EditorModel model; + + private GestureDetectorCompat doubleTap; + + @Nullable + private DrawingChangedListener drawingChangedListener; + + private final Matrix viewMatrix = new Matrix(); + private final RectF viewPort = Bounds.newFullBounds(); + private final RectF visibleViewPort = Bounds.newFullBounds(); + private final RectF screen = new RectF(); + + private TapListener tapListener; + private RendererContext rendererContext; + + @Nullable + private EditSession editSession; + + public ImageEditorView(Context context) { + super(context); + init(); + } + + public ImageEditorView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + init(); + } + + public ImageEditorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + setWillNotDraw(false); + setModel(new EditorModel()); + + editText = createAHiddenTextEntryField(); + + doubleTap = new GestureDetectorCompat(getContext(), new DoubleTapGestureListener()); + + setOnTouchListener((v, event) -> doubleTap.onTouchEvent(event)); + } + + private HiddenEditText createAHiddenTextEntryField() { + HiddenEditText editText = new HiddenEditText(getContext()); + addView(editText); + editText.clearFocus(); + editText.setOnEndEdit(this::doneTextEditing); + return editText; + } + + public void startTextEditing(@NonNull EditorElement editorElement, boolean incognitoKeyboardEnabled, boolean selectAll) { + Renderer renderer = editorElement.getRenderer(); + if (renderer instanceof TextRenderer) { + TextRenderer textRenderer = (TextRenderer) renderer; + + editText.setIncognitoKeyboardEnabled(incognitoKeyboardEnabled); + editText.setCurrentTextEntity(textRenderer); + if (selectAll) { + editText.selectAll(); + } + editText.requestFocus(); + + getModel().zoomTo(editorElement, Bounds.TOP / 2, true); + } + } + + public boolean isTextEditing() { + return editText.getCurrentTextEntity() != null; + } + + public void doneTextEditing() { + getModel().zoomOut(); + if (editText.getCurrentTextEntity() != null) { + editText.setCurrentTextEntity(null); + editText.hideKeyboard(); + if (tapListener != null) { + tapListener.onEntityDown(null); + } + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (rendererContext == null || rendererContext.canvas != canvas) { + rendererContext = new RendererContext(getContext(), canvas, rendererReady, rendererInvalidate); + } + rendererContext.save(); + try { + rendererContext.canvasMatrix.initial(viewMatrix); + model.draw(rendererContext); + } finally { + rendererContext.restore(); + } + } + + private final RendererContext.Ready rendererReady = new RendererContext.Ready() { + @Override + public void onReady(@NonNull Renderer renderer, @Nullable Matrix cropMatrix, @Nullable Point size) { + model.onReady(renderer, cropMatrix, size); + invalidate(); + } + }; + + private final RendererContext.Invalidate rendererInvalidate = renderer -> invalidate(); + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + updateViewMatrix(); + } + + private void updateViewMatrix() { + screen.right = getWidth(); + screen.bottom = getHeight(); + + viewMatrix.setRectToRect(viewPort, screen, Matrix.ScaleToFit.FILL); + + float[] values = new float[9]; + viewMatrix.getValues(values); + + float scale = values[0] / values[4]; + + RectF tempViewPort = Bounds.newFullBounds(); + if (scale < 1) { + tempViewPort.top /= scale; + tempViewPort.bottom /= scale; + } else { + tempViewPort.left *= scale; + tempViewPort.right *= scale; + } + + visibleViewPort.set(tempViewPort); + + viewMatrix.setRectToRect(visibleViewPort, screen, Matrix.ScaleToFit.CENTER); + + model.setVisibleViewPort(visibleViewPort); + + invalidate(); + } + + public void setModel(@NonNull EditorModel model) { + if (this.model != model) { + if (this.model != null) { + this.model.setInvalidate(null); + } + this.model = model; + this.model.setInvalidate(this::invalidate); + this.model.setVisibleViewPort(visibleViewPort); + invalidate(); + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: { + Matrix inverse = new Matrix(); + PointF point = getPoint(event); + EditorElement selected = model.findElementAtPoint(point, viewMatrix, inverse); + + model.pushUndoPoint(); + editSession = startEdit(inverse, point, selected); + + if (tapListener != null && allowTaps()) { + if (editSession != null) { + tapListener.onEntityDown(editSession.getSelected()); + } else { + tapListener.onEntityDown(null); + } + } + + return true; + } + case MotionEvent.ACTION_MOVE: { + if (editSession != null) { + for (int p = 0; p < Math.min(2, event.getPointerCount()); p++) { + editSession.movePoint(p, getPoint(event, p)); + } + invalidate(); + return true; + } + break; + } + case MotionEvent.ACTION_POINTER_DOWN: { + if (editSession != null && event.getPointerCount() == 2) { + editSession.commit(); + model.pushUndoPoint(); + + Matrix newInverse = model.findElementInverseMatrix(editSession.getSelected(), viewMatrix); + editSession = editSession.newPoint(newInverse, getPoint(event, event.getActionIndex()), event.getActionIndex()); + if (editSession == null) { + dragDropRelease(); + } + return true; + } + break; + } + case MotionEvent.ACTION_POINTER_UP: { + if (editSession != null && event.getActionIndex() < 2) { + editSession.commit(); + model.pushUndoPoint(); + dragDropRelease(); + + Matrix newInverse = model.findElementInverseMatrix(editSession.getSelected(), viewMatrix); + editSession = editSession.removePoint(newInverse, event.getActionIndex()); + return true; + } + break; + } + case MotionEvent.ACTION_UP: { + if (editSession != null) { + editSession.commit(); + dragDropRelease(); + + editSession = null; + invalidate(); + return true; + } + break; + } + } + + return super.onTouchEvent(event); + } + + private @Nullable EditSession startEdit(@NonNull Matrix inverse, @NonNull PointF point, @Nullable EditorElement selected) { + if (mode == Mode.Draw) { + return startADrawingSession(point); + } else { + return startAMoveAndResizeSession(inverse, point, selected); + } + } + + private EditSession startADrawingSession(@NonNull PointF point) { + BezierDrawingRenderer renderer = new BezierDrawingRenderer(color, thickness * Bounds.FULL_BOUNDS.width(), cap, model.findCropRelativeToRoot()); + EditorElement element = new EditorElement(renderer); + model.addElementCentered(element, 1); + + Matrix elementInverseMatrix = model.findElementInverseMatrix(element, viewMatrix); + + return DrawingSession.start(element, renderer, elementInverseMatrix, point); + } + + private EditSession startAMoveAndResizeSession(@NonNull Matrix inverse, @NonNull PointF point, @Nullable EditorElement selected) { + Matrix elementInverseMatrix; + if (selected == null) return null; + + if (selected.getRenderer() instanceof ThumbRenderer) { + ThumbRenderer thumb = (ThumbRenderer) selected.getRenderer(); + + selected = getModel().findById(thumb.getElementToControl()); + + if (selected == null) return null; + + elementInverseMatrix = model.findElementInverseMatrix(selected, viewMatrix); + if (elementInverseMatrix != null) { + return ThumbDragEditSession.startDrag(selected, elementInverseMatrix, thumb.getControlPoint(), point); + } else { + return null; + } + } + + return ElementDragEditSession.startDrag(selected, inverse, point); + } + + public void setMode(@NonNull Mode mode) { + this.mode = mode; + } + + public void startDrawing(float thickness, @NonNull Paint.Cap cap) { + this.thickness = thickness; + this.cap = cap; + setMode(Mode.Draw); + } + + public void setDrawingBrushColor(int color) { + this.color = color; + } + + private void dragDropRelease() { + model.dragDropRelease(); + if (drawingChangedListener != null) { + drawingChangedListener.onDrawingChanged(); + } + } + + private static PointF getPoint(MotionEvent event) { + return getPoint(event, 0); + } + + private static PointF getPoint(MotionEvent event, int p) { + return new PointF(event.getX(p), event.getY(p)); + } + + public EditorModel getModel() { + return model; + } + + public void setDrawingChangedListener(@Nullable DrawingChangedListener drawingChangedListener) { + this.drawingChangedListener = drawingChangedListener; + } + + public void setTapListener(TapListener tapListener) { + this.tapListener = tapListener; + } + + public void deleteElement(@Nullable EditorElement editorElement) { + if (editorElement != null) { + model.pushUndoPoint(); + model.delete(editorElement); + invalidate(); + } + } + + private final class DoubleTapGestureListener extends GestureDetector.SimpleOnGestureListener { + + @Override + public boolean onDoubleTap(MotionEvent e) { + if (tapListener != null && editSession != null && allowTaps()) { + tapListener.onEntityDoubleTap(editSession.getSelected()); + } + return true; + } + + @Override + public void onLongPress(MotionEvent e) {} + + @Override + public boolean onSingleTapUp(MotionEvent e) { + if (tapListener != null && allowTaps()) { + if (editSession != null) { + EditorElement selected = editSession.getSelected(); + model.indicateSelected(selected); + tapListener.onEntitySingleTap(selected); + } else { + tapListener.onEntitySingleTap(null); + } + } + return true; + } + + @Override + public boolean onDown(MotionEvent e) { + return false; + } + } + + private boolean allowTaps() { + return !model.isCropping() && mode != Mode.Draw; + } + + public enum Mode { + MoveAndResize, + Draw + } + + public interface DrawingChangedListener { + void onDrawingChanged(); + } + + public interface TapListener { + + void onEntityDown(@Nullable EditorElement editorElement); + + void onEntitySingleTap(@Nullable EditorElement editorElement); + + void onEntityDoubleTap(@NonNull EditorElement editorElement); + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/Renderer.java b/src/org/thoughtcrime/securesms/imageeditor/Renderer.java new file mode 100644 index 000000000..0b4ff672b --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/Renderer.java @@ -0,0 +1,26 @@ +package org.thoughtcrime.securesms.imageeditor; + +import android.os.Parcelable; +import android.support.annotation.NonNull; + +/** + * Responsible for rendering a single {@link org.thoughtcrime.securesms.imageeditor.model.EditorElement} to the canvas. + *

+ * Because it knows the most about the whereabouts of the image it is also responsible for hit detection. + */ +public interface Renderer extends Parcelable { + + /** + * Draw self to the context. + * + * @param rendererContext The context to draw to. + */ + void render(@NonNull RendererContext rendererContext); + + /** + * @param x Local coordinate X + * @param y Local coordinate Y + * @return true iff hit. + */ + boolean hitTest(float x, float y); +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/RendererContext.java b/src/org/thoughtcrime/securesms/imageeditor/RendererContext.java new file mode 100644 index 000000000..9ca600f39 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/RendererContext.java @@ -0,0 +1,114 @@ +package org.thoughtcrime.securesms.imageeditor; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Point; +import android.graphics.RectF; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +/** + * Contains all of the information required for a {@link Renderer} to do its job. + *

+ * Includes a {@link #canvas}, preconfigured with the correct matrix. + *

+ * The {@link #canvasMatrix} should further matrix manipulation be required. + */ +public final class RendererContext { + + @NonNull + public final Context context; + + @NonNull + public final Canvas canvas; + + @NonNull + public final CanvasMatrix canvasMatrix; + + @NonNull + public final Ready rendererReady; + + @NonNull + public final Invalidate invalidate; + + private boolean blockingLoad; + + private float fade = 1f; + + private boolean isEditing = true; + + public RendererContext(@NonNull Context context, @NonNull Canvas canvas, @NonNull Ready rendererReady, @NonNull Invalidate invalidate) { + this.context = context; + this.canvas = canvas; + this.canvasMatrix = new CanvasMatrix(canvas); + this.rendererReady = rendererReady; + this.invalidate = invalidate; + } + + public void setBlockingLoad(boolean blockingLoad) { + this.blockingLoad = blockingLoad; + } + + /** + * {@link Renderer}s generally run in the foreground but can load any data they require in the background. + *

+ * If they do so, they can use the {@link #invalidate} callback when ready to inform the view it needs to be redrawn. + *

+ * However, when isBlockingLoad is true, the renderer is running in the background for the final render + * and must load the data immediately and block the render until done so. + */ + public boolean isBlockingLoad() { + return blockingLoad; + } + + public boolean mapRect(@NonNull RectF dst, @NonNull RectF src) { + return canvasMatrix.mapRect(dst, src); + } + + public void setIsEditing(boolean isEditing) { + this.isEditing = isEditing; + } + + public boolean isEditing() { + return isEditing; + } + + public void setFade(float fade) { + this.fade = fade; + } + + public int getAlpha(int alpha) { + return Math.max(0, Math.min(255, (int) (fade * alpha))); + } + + /** + * Persist the current state on to a stack, must be complimented by a call to {@link #restore()}. + */ + public void save() { + canvasMatrix.save(); + } + + /** + * Restore the current state from the stack, must match a call to {@link #save()}. + */ + public void restore() { + canvasMatrix.restore(); + } + + public interface Ready { + + Ready NULL = (renderer, cropMatrix, size) -> { + }; + + void onReady(@NonNull Renderer renderer, @Nullable Matrix cropMatrix, @Nullable Point size); + } + + public interface Invalidate { + + Invalidate NULL = (renderer) -> { + }; + + void onInvalidate(@NonNull Renderer renderer); + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/ThumbDragEditSession.java b/src/org/thoughtcrime/securesms/imageeditor/ThumbDragEditSession.java new file mode 100644 index 000000000..591e16afe --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/ThumbDragEditSession.java @@ -0,0 +1,68 @@ +package org.thoughtcrime.securesms.imageeditor; + +import android.graphics.Matrix; +import android.graphics.PointF; +import android.support.annotation.NonNull; + +import org.thoughtcrime.securesms.imageeditor.model.EditorElement; +import org.thoughtcrime.securesms.imageeditor.model.ThumbRenderer; + +class ThumbDragEditSession extends ElementEditSession { + + @NonNull + private final ThumbRenderer.ControlPoint controlPoint; + + private ThumbDragEditSession(@NonNull EditorElement selected, @NonNull ThumbRenderer.ControlPoint controlPoint, @NonNull Matrix inverseMatrix) { + super(selected, inverseMatrix); + this.controlPoint = controlPoint; + } + + static EditSession startDrag(@NonNull EditorElement selected, @NonNull Matrix inverseViewModelMatrix, @NonNull ThumbRenderer.ControlPoint controlPoint, @NonNull PointF point) { + if (!selected.getFlags().isEditable()) return null; + + ElementEditSession elementDragEditSession = new ThumbDragEditSession(selected, controlPoint, inverseViewModelMatrix); + elementDragEditSession.setScreenStartPoint(0, point); + elementDragEditSession.setScreenEndPoint(0, point); + return elementDragEditSession; + } + + @Override + public void movePoint(int p, @NonNull PointF point) { + setScreenEndPoint(p, point); + + Matrix editorMatrix = selected.getEditorMatrix(); + + editorMatrix.reset(); + + float x = controlPoint.opposite().getX(); + float y = controlPoint.opposite().getY(); + + editorMatrix.postTranslate(-x, -y); + + boolean aspectLocked = selected.getFlags().isAspectLocked(); + + float defaultScale = aspectLocked ? 2 : 1; + + float scaleX = controlPoint.isVerticalCenter() ? defaultScale : (endPointElement[0].x - x) / (startPointElement[0].x - x); + float scaleY = controlPoint.isHorizontalCenter() ? defaultScale : (endPointElement[0].y - y) / (startPointElement[0].y - y); + + if (aspectLocked) { + float minScale = Math.min(scaleX, scaleY); + editorMatrix.postScale(minScale, minScale); + } else { + editorMatrix.postScale(scaleX, scaleY); + } + + editorMatrix.postTranslate(x, y); + } + + @Override + public EditSession newPoint(Matrix newInverse, PointF point, int p) { + return null; + } + + @Override + public EditSession removePoint(Matrix newInverse, int p) { + return null; + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/model/AlphaAnimation.java b/src/org/thoughtcrime/securesms/imageeditor/model/AlphaAnimation.java new file mode 100644 index 000000000..0a2c24d32 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/model/AlphaAnimation.java @@ -0,0 +1,63 @@ +package org.thoughtcrime.securesms.imageeditor.model; + +import android.animation.ValueAnimator; +import android.support.annotation.Nullable; +import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; + +final class AlphaAnimation { + + private final static Interpolator interpolator = new LinearInterpolator(); + + final static AlphaAnimation NULL_1 = new AlphaAnimation(1); + + private final float from; + private final float to; + private final Runnable invalidate; + private final boolean canAnimate; + private float animatedFraction; + + private AlphaAnimation(float from, float to, @Nullable Runnable invalidate) { + this.from = from; + this.to = to; + this.invalidate = invalidate; + this.canAnimate = invalidate != null; + } + + private AlphaAnimation(float fixed) { + this(fixed, fixed, null); + } + + static AlphaAnimation animate(float from, float to, @Nullable Runnable invalidate) { + if (invalidate == null) { + return new AlphaAnimation(to); + } + + if (from != to) { + AlphaAnimation animationMatrix = new AlphaAnimation(from, to, invalidate); + animationMatrix.start(); + return animationMatrix; + } else { + return new AlphaAnimation(to); + } + } + + private void start() { + if (canAnimate && invalidate != null) { + ValueAnimator animator = ValueAnimator.ofFloat(from, to); + animator.setDuration(200); + animator.setInterpolator(interpolator); + animator.addUpdateListener(animation -> { + animatedFraction = (float) animation.getAnimatedValue(); + invalidate.run(); + }); + animator.start(); + } + } + + float getValue() { + if (!canAnimate) return to; + + return animatedFraction; + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/model/AnimationMatrix.java b/src/org/thoughtcrime/securesms/imageeditor/model/AnimationMatrix.java new file mode 100644 index 000000000..712f52d11 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/model/AnimationMatrix.java @@ -0,0 +1,136 @@ +package org.thoughtcrime.securesms.imageeditor.model; + +import android.animation.ValueAnimator; +import android.graphics.Matrix; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.animation.CycleInterpolator; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.Interpolator; + +import org.thoughtcrime.securesms.imageeditor.CanvasMatrix; + +/** + * Animation Matrix provides a matrix that animates over time down to the identity matrix. + */ +final class AnimationMatrix { + + private final static float[] iValues = new float[9]; + private final static Interpolator interpolator = new DecelerateInterpolator(); + private final static Interpolator pulseInterpolator = inverse(new CycleInterpolator(0.5f)); + + static AnimationMatrix NULL = new AnimationMatrix(); + + static { + new Matrix().getValues(iValues); + } + + private final Runnable invalidate; + private final boolean canAnimate; + private final float[] undoValues = new float[9]; + + private final Matrix temp = new Matrix(); + private final float[] tempValues = new float[9]; + + private ValueAnimator animator; + private float animatedFraction; + + private AnimationMatrix(@NonNull Matrix undo, @NonNull Runnable invalidate) { + this.invalidate = invalidate; + this.canAnimate = true; + undo.getValues(undoValues); + } + + private AnimationMatrix() { + canAnimate = false; + invalidate = null; + } + + static @NonNull AnimationMatrix animate(@NonNull Matrix from, @NonNull Matrix to, @Nullable Runnable invalidate) { + if (invalidate == null) { + return NULL; + } + + Matrix undo = new Matrix(); + boolean inverted = to.invert(undo); + if (inverted) { + undo.preConcat(from); + } + if (inverted && !undo.isIdentity()) { + AnimationMatrix animationMatrix = new AnimationMatrix(undo, invalidate); + animationMatrix.start(interpolator); + return animationMatrix; + } else { + return NULL; + } + } + + /** + * Animate applying a matrix and then animate removing. + */ + static @NonNull AnimationMatrix singlePulse(@NonNull Matrix pulse, @Nullable Runnable invalidate) { + if (invalidate == null) { + return NULL; + } + + AnimationMatrix animationMatrix = new AnimationMatrix(pulse, invalidate); + animationMatrix.start(pulseInterpolator); + + return animationMatrix; + } + + private void start(@NonNull Interpolator interpolator) { + if (canAnimate) { + animator = ValueAnimator.ofFloat(1, 0); + animator.setDuration(250); + animator.setInterpolator(interpolator); + animator.addUpdateListener(animation -> { + animatedFraction = (float) animation.getAnimatedValue(); + invalidate.run(); + }); + animator.start(); + } + } + + void stop() { + ValueAnimator animator = this.animator; + if (animator != null) animator.cancel(); + } + + /** + * Append the current animation value. + */ + void preConcatValueTo(@NonNull Matrix onTo) { + if (!canAnimate) return; + + onTo.preConcat(buildTemp()); + } + + /** + * Append the current animation value. + */ + void preConcatValueTo(@NonNull CanvasMatrix canvasMatrix) { + if (!canAnimate) return; + + canvasMatrix.concat(buildTemp()); + } + + private Matrix buildTemp() { + if (!canAnimate) { + temp.reset(); + return temp; + } + + final float fractionCompliment = 1f - animatedFraction; + for (int i = 0; i < 9; i++) { + tempValues[i] = fractionCompliment * iValues[i] + animatedFraction * undoValues[i]; + } + + temp.setValues(tempValues); + return temp; + } + + private static Interpolator inverse(@NonNull Interpolator interpolator) { + return input -> 1f - interpolator.getInterpolation(input); + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/model/CropThumbRenderer.java b/src/org/thoughtcrime/securesms/imageeditor/model/CropThumbRenderer.java new file mode 100644 index 000000000..ffac880e8 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/model/CropThumbRenderer.java @@ -0,0 +1,83 @@ +package org.thoughtcrime.securesms.imageeditor.model; + +import android.graphics.Matrix; +import android.os.Parcel; +import android.support.annotation.NonNull; + +import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.imageeditor.Bounds; +import org.thoughtcrime.securesms.imageeditor.Renderer; +import org.thoughtcrime.securesms.imageeditor.RendererContext; + +import java.util.UUID; + +/** + * Hit tests a circle that is {@link R.dimen#crop_area_renderer_edge_size} in radius on the screen. + *

+ * Does not draw anything. + */ +class CropThumbRenderer implements Renderer, ThumbRenderer { + + private final ControlPoint controlPoint; + private final UUID toControl; + + private final float[] centreOnScreen = new float[2]; + private final Matrix matrix = new Matrix(); + private int size; + + CropThumbRenderer(@NonNull ControlPoint controlPoint, @NonNull UUID toControl) { + this.controlPoint = controlPoint; + this.toControl = toControl; + } + + @Override + public ControlPoint getControlPoint() { + return controlPoint; + } + + @Override + public UUID getElementToControl() { + return toControl; + } + + @Override + public void render(@NonNull RendererContext rendererContext) { + rendererContext.canvasMatrix.mapPoints(centreOnScreen, Bounds.CENTRE); + rendererContext.canvasMatrix.copyTo(matrix); + size = rendererContext.context.getResources().getDimensionPixelSize(R.dimen.crop_area_renderer_edge_size); + } + + @Override + public boolean hitTest(float x, float y) { + float[] hitPointOnScreen = new float[2]; + matrix.mapPoints(hitPointOnScreen, new float[]{ x, y }); + + float dx = centreOnScreen[0] - hitPointOnScreen[0]; + float dy = centreOnScreen[1] - hitPointOnScreen[1]; + + return dx * dx + dy * dy < size * size; + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator CREATOR = new Creator() { + @Override + public CropThumbRenderer createFromParcel(Parcel in) { + return new CropThumbRenderer(ControlPoint.values()[in.readInt()], ParcelUtils.readUUID(in)); + } + + @Override + public CropThumbRenderer[] newArray(int size) { + return new CropThumbRenderer[size]; + } + }; + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(controlPoint.ordinal()); + ParcelUtils.writeUUID(dest, toControl); + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/model/EditorElement.java b/src/org/thoughtcrime/securesms/imageeditor/model/EditorElement.java new file mode 100644 index 000000000..f8b7f3de2 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/model/EditorElement.java @@ -0,0 +1,333 @@ +package org.thoughtcrime.securesms.imageeditor.model; + +import android.graphics.Matrix; +import android.os.Parcel; +import android.os.Parcelable; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import org.thoughtcrime.securesms.imageeditor.Renderer; +import org.thoughtcrime.securesms.imageeditor.RendererContext; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** + * An image consists of a tree of {@link EditorElement}s. + *

+ * Each element has some persisted state: + * - An optional {@link Renderer} so that it can draw itself. + * - A list of child elements that make the tree possible. + * - Its own transformation matrix, which applies to itself and all its children. + * - A set of flags controlling visibility, selectablity etc. + *

+ * Then some temporary state. + * - A editor matrix for displaying as yet uncommitted edits. + * - An animation matrix for animating from one matrix to another. + * - Deleted children to allow them to fade out on delete. + * - Temporary flags, for temporary visibility, selectablity etc. + */ +public final class EditorElement implements Parcelable { + + private final UUID id; + private final EditorFlags flags; + private final Matrix localMatrix = new Matrix(); + private final Matrix editorMatrix = new Matrix(); + + @Nullable + private final Renderer renderer; + + private final Matrix temp = new Matrix(); + + private final Matrix tempMatrix = new Matrix(); + + private final List children = new LinkedList<>(); + private final List deletedChildren = new LinkedList<>(); + + @NonNull + private AnimationMatrix animationMatrix = AnimationMatrix.NULL; + + @NonNull + private AlphaAnimation alphaAnimation = AlphaAnimation.NULL_1; + + public EditorElement(@Nullable Renderer renderer) { + this.id = UUID.randomUUID(); + this.flags = new EditorFlags(); + this.renderer = renderer; + } + + private EditorElement(Parcel in) { + id = ParcelUtils.readUUID(in); + flags = new EditorFlags(in.readInt()); + ParcelUtils.readMatrix(localMatrix, in); + renderer = in.readParcelable(Renderer.class.getClassLoader()); + in.readTypedList(children, EditorElement.CREATOR); + } + + UUID getId() { + return id; + } + + public @Nullable Renderer getRenderer() { + return renderer; + } + + /** + * Iff Visible, + * Renders tree with the following localMatrix: + *

+ * viewModelMatrix * localMatrix * editorMatrix * animationMatrix + *

+ * Child nodes are supplied with a viewModelMatrix' = viewModelMatrix * localMatrix * editorMatrix * animationMatrix + * + * @param rendererContext Canvas to draw on to. + */ + void draw(@NonNull RendererContext rendererContext) { + if (!flags.isVisible() && !flags.isChildrenVisible()) return; + + rendererContext.save(); + + rendererContext.canvasMatrix.concat(localMatrix); + + if (rendererContext.isEditing()) { + rendererContext.canvasMatrix.concat(editorMatrix); + animationMatrix.preConcatValueTo(rendererContext.canvasMatrix); + } + + if (flags.isVisible()) { + float alpha = alphaAnimation.getValue(); + if (alpha > 0) { + rendererContext.setFade(alpha); + drawSelf(rendererContext); + rendererContext.setFade(1f); + } + } + + if (flags.isChildrenVisible()) { + drawChildren(children, rendererContext); + drawChildren(deletedChildren, rendererContext); + } + + rendererContext.restore(); + } + + private void drawSelf(@NonNull RendererContext rendererContext) { + if (renderer == null) return; + renderer.render(rendererContext); + } + + private static void drawChildren(@NonNull List children, @NonNull RendererContext rendererContext) { + for (EditorElement element : children) { + element.draw(rendererContext); + } + } + + public void addElement(@NonNull EditorElement element) { + children.add(element); + } + + public Matrix getLocalMatrix() { + return localMatrix; + } + + public Matrix getEditorMatrix() { + return editorMatrix; + } + + EditorElement findElement(@NonNull EditorElement toFind, @NonNull Matrix viewMatrix, @NonNull Matrix outInverseModelMatrix) { + return findElement(viewMatrix, outInverseModelMatrix, (element, inverseMatrix) -> toFind == element); + } + + EditorElement findElementAt(float x, float y, @NonNull Matrix viewModelMatrix, @NonNull Matrix outInverseModelMatrix) { + final float[] dst = new float[2]; + final float[] src = { x, y }; + + return findElement(viewModelMatrix, outInverseModelMatrix, (element, inverseMatrix) -> { + Renderer renderer = element.renderer; + if (renderer == null) return false; + inverseMatrix.mapPoints(dst, src); + return element.flags.isSelectable() && renderer.hitTest(dst[0], dst[1]); + }); + } + + public EditorElement findElement(@NonNull Matrix viewModelMatrix, @NonNull Matrix outInverseModelMatrix, @NonNull FindElementPredicate predicate) { + temp.set(viewModelMatrix); + + temp.preConcat(localMatrix); + temp.preConcat(editorMatrix); + + if (temp.invert(tempMatrix)) { + + for (int i = children.size() - 1; i >= 0; i--) { + EditorElement elementAt = children.get(i).findElement(temp, outInverseModelMatrix, predicate); + if (elementAt != null) { + return elementAt; + } + } + + if (predicate.test(this, tempMatrix)) { + outInverseModelMatrix.set(tempMatrix); + return this; + } + } + + return null; + } + + public EditorFlags getFlags() { + return flags; + } + + int getChildCount() { + return children.size(); + } + + EditorElement getChild(int i) { + return children.get(i); + } + + void forAllInTree(@NonNull PerElementFunction function) { + function.apply(this); + for (EditorElement child : children) { + child.forAllInTree(function); + } + } + + void deleteChild(@NonNull EditorElement editorElement, @Nullable Runnable invalidate) { + Iterator iterator = children.iterator(); + while (iterator.hasNext()) { + if (iterator.next() == editorElement) { + iterator.remove(); + addDeletedChildFadingOut(editorElement, invalidate); + } + } + } + + void addDeletedChildFadingOut(@NonNull EditorElement fromElement, @Nullable Runnable invalidate) { + deletedChildren.add(fromElement); + fromElement.animateFadeOut(invalidate); + } + + private void animateFadeOut(@Nullable Runnable invalidate) { + alphaAnimation = AlphaAnimation.animate(1, 0, invalidate); + } + + void animateFadeIn(@Nullable Runnable invalidate) { + alphaAnimation = AlphaAnimation.animate(0, 1, invalidate); + } + + @Nullable EditorElement parentOf(@NonNull EditorElement element) { + if (children.contains(element)) { + return this; + } + for (EditorElement child : children) { + EditorElement parent = child.parentOf(element); + if (parent != null) { + return parent; + } + } + return null; + } + + public void singleScalePulse(@Nullable Runnable invalidate) { + Matrix scale = new Matrix(); + scale.setScale(1.2f, 1.2f); + + animationMatrix = AnimationMatrix.singlePulse(scale, invalidate); + } + + public interface PerElementFunction { + void apply(EditorElement element); + } + + public interface FindElementPredicate { + boolean test(EditorElement element, Matrix inverseMatrix); + } + + public void commitEditorMatrix() { + if (flags.isEditable()) { + localMatrix.preConcat(editorMatrix); + editorMatrix.reset(); + } else { + rollbackEditorMatrix(null); + } + } + + void rollbackEditorMatrix(@Nullable Runnable invalidate) { + animateEditorTo(new Matrix(), invalidate); + } + + void buildMap(Map map) { + map.put(id, this); + for (EditorElement child : children) { + child.buildMap(map); + } + } + + void animateFrom(@NonNull Matrix oldMatrix, @Nullable Runnable invalidate) { + Matrix oldMatrixCopy = new Matrix(oldMatrix); + animationMatrix.stop(); + animationMatrix.preConcatValueTo(oldMatrixCopy); + animationMatrix = AnimationMatrix.animate(oldMatrixCopy, localMatrix, invalidate); + } + + void animateEditorTo(@NonNull Matrix newEditorMatrix, @Nullable Runnable invalidate) { + setMatrixWithAnimation(editorMatrix, newEditorMatrix, invalidate); + } + + void animateLocalTo(@NonNull Matrix newLocalMatrix, @Nullable Runnable invalidate) { + setMatrixWithAnimation(localMatrix, newLocalMatrix, invalidate); + } + + /** + * @param destination Matrix to change + * @param source Matrix value to set + * @param invalidate Callback to allow animation + */ + private void setMatrixWithAnimation(@NonNull Matrix destination, @NonNull Matrix source, @Nullable Runnable invalidate) { + Matrix old = new Matrix(destination); + animationMatrix.stop(); + animationMatrix.preConcatValueTo(old); + destination.set(source); + animationMatrix = AnimationMatrix.animate(old, destination, invalidate); + } + + Matrix getLocalMatrixAnimating() { + Matrix matrix = new Matrix(localMatrix); + animationMatrix.preConcatValueTo(matrix); + return matrix; + } + + void stopAnimation() { + animationMatrix.stop(); + } + + public static final Creator CREATOR = new Creator() { + @Override + public EditorElement createFromParcel(Parcel in) { + return new EditorElement(in); + } + + @Override + public EditorElement[] newArray(int size) { + return new EditorElement[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + ParcelUtils.writeUUID(dest, id); + dest.writeInt(this.flags.asInt()); + ParcelUtils.writeMatrix(dest, localMatrix); + dest.writeParcelable(renderer, flags); + dest.writeTypedList(children); + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/model/EditorElementHierarchy.java b/src/org/thoughtcrime/securesms/imageeditor/model/EditorElementHierarchy.java new file mode 100644 index 000000000..d16c677bf --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/model/EditorElementHierarchy.java @@ -0,0 +1,325 @@ +package org.thoughtcrime.securesms.imageeditor.model; + +import android.graphics.Matrix; +import android.graphics.Point; +import android.graphics.PointF; +import android.graphics.RectF; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.imageeditor.Bounds; +import org.thoughtcrime.securesms.imageeditor.renderers.CropAreaRenderer; +import org.thoughtcrime.securesms.imageeditor.renderers.InverseFillRenderer; + +/** + * Creates and handles a strict EditorElement Hierarchy. + *

+ * root - always square, contains only temporary zooms for editing. e.g. when the whole editor zooms out for cropping + * | + * |- view - contains persisted adjustments for crops + * | | + * | |- flipRotate - contains persisted adjustments for flip and rotate operations, ensures operations are centered within the current view + * | | + * | |- imageRoot + * | | |- mainImage + * | | |- stickers/drawings/text + * | | + * | |- overlay - always square + * | | |- imageCrop - a crop to match the aspect of the main image + * | | | |- cropEditorElement - user crop, not always square, but upright, the area of the view + * | | | | | All children do not move/scale or rotate. + * | | | | |- blackout + * | | | | |- thumbs + * | | | | | |- Center left thumb + * | | | | | |- Center right thumb + * | | | | | |- Top center thumb + * | | | | | |- Bottom center thumb + * | | | | | |- Top left thumb + * | | | | | |- Top right thumb + * | | | | | |- Bottom left thumb + * | | | | | |- Bottom right thumb + */ +final class EditorElementHierarchy { + + static @NonNull EditorElementHierarchy create() { + return new EditorElementHierarchy(createRoot()); + } + + static @NonNull EditorElementHierarchy create(@Nullable EditorElement root) { + if (root == null) { + return create(); + } else { + return new EditorElementHierarchy(root); + } + } + + private final EditorElement root; + private final EditorElement view; + private final EditorElement flipRotate; + private final EditorElement imageRoot; + private final EditorElement overlay; + private final EditorElement imageCrop; + private final EditorElement cropEditorElement; + private final EditorElement blackout; + private final EditorElement thumbs; + + private EditorElementHierarchy(@NonNull EditorElement root) { + this.root = root; + this.view = this.root.getChild(0); + this.flipRotate = this.view.getChild(0); + this.imageRoot = this.flipRotate.getChild(0); + this.overlay = this.flipRotate.getChild(1); + this.imageCrop = this.overlay.getChild(0); + this.cropEditorElement = this.imageCrop.getChild(0); + this.blackout = this.cropEditorElement.getChild(0); + this.thumbs = this.cropEditorElement.getChild(1); + } + + private static @NonNull EditorElement createRoot() { + EditorElement root = new EditorElement(null); + + EditorElement imageRoot = new EditorElement(null); + root.addElement(imageRoot); + + EditorElement flipRotate = new EditorElement(null); + imageRoot.addElement(flipRotate); + + EditorElement image = new EditorElement(null); + flipRotate.addElement(image); + + EditorElement overlay = new EditorElement(null); + flipRotate.addElement(overlay); + + EditorElement imageCrop = new EditorElement(null); + overlay.addElement(imageCrop); + + EditorElement cropEditorElement = new EditorElement(new CropAreaRenderer(R.color.crop_area_renderer_outer_color)); + + cropEditorElement.getFlags() + .setRotateLocked(true) + .setAspectLocked(true) + .setSelectable(false) + .setVisible(false) + .persist(); + + imageCrop.addElement(cropEditorElement); + + EditorElement blackout = new EditorElement(new InverseFillRenderer(0xff000000)); + + blackout.getFlags() + .setSelectable(false) + .setEditable(false) + .persist(); + + cropEditorElement.addElement(blackout); + + cropEditorElement.addElement(createThumbs(cropEditorElement)); + return root; + } + + private static @NonNull EditorElement createThumbs(EditorElement cropEditorElement) { + EditorElement thumbs = new EditorElement(null); + + thumbs.getFlags() + .setChildrenVisible(false) + .setSelectable(false) + .setVisible(false) + .persist(); + + thumbs.addElement(newThumb(cropEditorElement, ThumbRenderer.ControlPoint.CENTER_LEFT)); + thumbs.addElement(newThumb(cropEditorElement, ThumbRenderer.ControlPoint.CENTER_RIGHT)); + + thumbs.addElement(newThumb(cropEditorElement, ThumbRenderer.ControlPoint.TOP_CENTER)); + thumbs.addElement(newThumb(cropEditorElement, ThumbRenderer.ControlPoint.BOTTOM_CENTER)); + + thumbs.addElement(newThumb(cropEditorElement, ThumbRenderer.ControlPoint.TOP_LEFT)); + thumbs.addElement(newThumb(cropEditorElement, ThumbRenderer.ControlPoint.TOP_RIGHT)); + thumbs.addElement(newThumb(cropEditorElement, ThumbRenderer.ControlPoint.BOTTOM_LEFT)); + thumbs.addElement(newThumb(cropEditorElement, ThumbRenderer.ControlPoint.BOTTOM_RIGHT)); + + return thumbs; + } + + private static @NonNull EditorElement newThumb(@NonNull EditorElement toControl, @NonNull ThumbRenderer.ControlPoint controlPoint) { + EditorElement element = new EditorElement(new CropThumbRenderer(controlPoint, toControl.getId())); + + element.getFlags() + .setSelectable(false) + .persist(); + + element.getLocalMatrix().preTranslate(controlPoint.getX(), controlPoint.getY()); + + return element; + } + + EditorElement getRoot() { + return root; + } + + EditorElement getImageRoot() { + return imageRoot; + } + + /** + * The main image, null if not yet set. + */ + @Nullable EditorElement getMainImage() { + return imageRoot.getChildCount() > 0 ? imageRoot.getChild(0) : null; + } + + EditorElement getCropEditorElement() { + return cropEditorElement; + } + + EditorElement getImageCrop() { + return imageCrop; + } + + EditorElement getOverlay() { + return overlay; + } + + EditorElement getFlipRotate() { + return flipRotate; + } + + void startCrop(@NonNull Runnable invalidate) { + Matrix editor = new Matrix(); + float scaleInForCrop = 0.8f; + + editor.postScale(scaleInForCrop, scaleInForCrop); + root.animateEditorTo(editor, invalidate); + + cropEditorElement.getFlags() + .setVisible(true); + + blackout.getFlags() + .setVisible(false); + + thumbs.getFlags() + .setChildrenVisible(true); + + thumbs.forAllInTree(element -> element.getFlags().setSelectable(true)); + + imageRoot.forAllInTree(element -> element.getFlags().setSelectable(false)); + + EditorElement mainImage = getMainImage(); + if (mainImage != null) { + mainImage.getFlags().setSelectable(true); + } + + invalidate.run(); + } + + void doneCrop(@NonNull RectF visibleViewPort, @Nullable Runnable invalidate) { + updateViewToCrop(visibleViewPort, invalidate); + + root.rollbackEditorMatrix(invalidate); + + root.forAllInTree(element -> element.getFlags().reset()); + } + + void updateViewToCrop(@NonNull RectF visibleViewPort, @Nullable Runnable invalidate) { + RectF dst = new RectF(); + + getCropFinalMatrix().mapRect(dst, Bounds.FULL_BOUNDS); + + Matrix temp = new Matrix(); + temp.setRectToRect(dst, visibleViewPort, Matrix.ScaleToFit.CENTER); + view.animateLocalTo(temp, invalidate); + } + + private @NonNull Matrix getCropFinalMatrix() { + Matrix matrix = new Matrix(flipRotate.getLocalMatrix()); + matrix.preConcat(imageCrop.getLocalMatrix()); + matrix.preConcat(cropEditorElement.getLocalMatrix()); + return matrix; + } + + void dragDropRelease(@NonNull RectF visibleViewPort, @NonNull Runnable invalidate) { + if (cropEditorElement.getFlags().isVisible()) { + updateViewToCrop(visibleViewPort, invalidate); + } + } + + RectF getCropRect() { + RectF dst = new RectF(); + getCropFinalMatrix().mapRect(dst, Bounds.FULL_BOUNDS); + return dst; + } + + void flipRotate(int degrees, int scaleX, int scaleY, @NonNull RectF visibleViewPort, @Nullable Runnable invalidate) { + Matrix newLocal = new Matrix(flipRotate.getLocalMatrix()); + if (degrees != 0) { + newLocal.postRotate(degrees); + } + newLocal.postScale(scaleX, scaleY); + flipRotate.animateLocalTo(newLocal, invalidate); + updateViewToCrop(visibleViewPort, invalidate); + } + + /** + * The full matrix for the {@link #getMainImage()} from {@link #root} down. + */ + Matrix getMainImageFullMatrix() { + Matrix matrix = new Matrix(); + + matrix.preConcat(view.getLocalMatrix()); + matrix.preConcat(getMainImageFullMatrixFromFlipRotate()); + + return matrix; + } + + /** + * The full matrix for the {@link #getMainImage()} from {@link #flipRotate} down. + */ + Matrix getMainImageFullMatrixFromFlipRotate() { + Matrix matrix = new Matrix(); + + matrix.preConcat(flipRotate.getLocalMatrix()); + matrix.preConcat(imageRoot.getLocalMatrix()); + + EditorElement mainImage = getMainImage(); + if (mainImage != null) { + matrix.preConcat(mainImage.getLocalMatrix()); + } + + return matrix; + } + + /** + * Calculates the exact output size based upon the crops/rotates and zooms in the hierarchy. + * + * @param inputSize Main image size + * @return Size after applying all zooms/rotates and crops + */ + PointF getOutputSize(@NonNull Point inputSize) { + Matrix matrix = new Matrix(); + + matrix.preConcat(flipRotate.getLocalMatrix()); + matrix.preConcat(cropEditorElement.getLocalMatrix()); + EditorElement mainImage = getMainImage(); + if (mainImage != null) { + float xScale = 1f / xScale(mainImage.getLocalMatrix()); + matrix.preScale(xScale, xScale); + } + + float[] dst = new float[4]; + matrix.mapPoints(dst, new float[]{ 0, 0, inputSize.x, inputSize.y }); + + float widthF = Math.abs(dst[0] - dst[2]); + float heightF = Math.abs(dst[1] - dst[3]); + + return new PointF(widthF, heightF); + } + + /** + * Extract the x scale from a matrix, which is the length of the first column. + */ + static float xScale(@NonNull Matrix matrix) { + float[] values = new float[9]; + matrix.getValues(values); + return (float) Math.sqrt(values[0] * values[0] + values[3] * values[3]); + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/model/EditorFlags.java b/src/org/thoughtcrime/securesms/imageeditor/model/EditorFlags.java new file mode 100644 index 000000000..700ddaa86 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/model/EditorFlags.java @@ -0,0 +1,116 @@ +package org.thoughtcrime.securesms.imageeditor.model; + +/** + * Flags for an {@link EditorElement}. + *

+ * Values you set are not persisted unless you call {@link #persist()}. + *

+ * This allows temporary state for editing and an easy way to revert to the persisted state via {@link #reset()}. + */ +public final class EditorFlags { + + private static final int ASPECT_LOCK = 1; + private static final int ROTATE_LOCK = 2; + private static final int SELECTABLE = 4; + private static final int VISIBLE = 8; + private static final int CHILDREN_VISIBLE = 16; + private static final int EDITABLE = 32; + + private int flags; + private int persistedFlags; + + EditorFlags() { + this(ASPECT_LOCK | SELECTABLE | VISIBLE | CHILDREN_VISIBLE | EDITABLE); + } + + EditorFlags(int flags) { + this.flags = flags; + this.persistedFlags = flags; + } + + public EditorFlags setRotateLocked(boolean rotateLocked) { + setFlag(ROTATE_LOCK, rotateLocked); + return this; + } + + public boolean isRotateLocked() { + return isFlagSet(ROTATE_LOCK); + } + + public EditorFlags setAspectLocked(boolean aspectLocked) { + setFlag(ASPECT_LOCK, aspectLocked); + return this; + } + + public boolean isAspectLocked() { + return isFlagSet(ASPECT_LOCK); + } + + public EditorFlags setSelectable(boolean selectable) { + setFlag(SELECTABLE, selectable); + return this; + } + + public boolean isSelectable() { + return isFlagSet(SELECTABLE); + } + + public EditorFlags setEditable(boolean canEdit) { + setFlag(EDITABLE, canEdit); + return this; + } + + public boolean isEditable() { + return isFlagSet(EDITABLE); + } + + public EditorFlags setVisible(boolean visible) { + setFlag(VISIBLE, visible); + return this; + } + + public boolean isVisible() { + return isFlagSet(VISIBLE); + } + + public EditorFlags setChildrenVisible(boolean childrenVisible) { + setFlag(CHILDREN_VISIBLE, childrenVisible); + return this; + } + + public boolean isChildrenVisible() { + return isFlagSet(CHILDREN_VISIBLE); + } + + private void setFlag(int flag, boolean set) { + if (set) { + this.flags |= flag; + } else { + this.flags &= ~flag; + } + } + + private boolean isFlagSet(int flag) { + return (flags & flag) != 0; + } + + int asInt() { + return persistedFlags; + } + + int getCurrentState() { + return flags; + } + + public void persist() { + persistedFlags = flags; + } + + void reset() { + restoreState(persistedFlags); + } + + void restoreState(int flags) { + this.flags = flags; + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/model/EditorModel.java b/src/org/thoughtcrime/securesms/imageeditor/model/EditorModel.java new file mode 100644 index 000000000..1a1b6644d --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/model/EditorModel.java @@ -0,0 +1,435 @@ +package org.thoughtcrime.securesms.imageeditor.model; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Point; +import android.graphics.PointF; +import android.graphics.RectF; +import android.os.Parcel; +import android.os.Parcelable; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.WorkerThread; + +import org.thoughtcrime.securesms.imageeditor.Bounds; +import org.thoughtcrime.securesms.imageeditor.ColorableRenderer; +import org.thoughtcrime.securesms.imageeditor.Renderer; +import org.thoughtcrime.securesms.imageeditor.RendererContext; + +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +/** + * Contains a reference to the root {@link EditorElement}, maintains undo and redo stacks and has a + * reference to the {@link EditorElementHierarchy}. + *

+ * As such it is the entry point for all operations that change the image. + */ +public final class EditorModel implements Parcelable, RendererContext.Ready { + + private static final Runnable NULL_RUNNABLE = () -> { + }; + + private static final int MINIMUM_OUTPUT_WIDTH = 0; + + @NonNull + private Runnable invalidate = NULL_RUNNABLE; + + private final ElementStack undoStack; + private final ElementStack redoStack; + + private EditorElementHierarchy editorElementHierarchy; + + private final RectF visibleViewPort = new RectF(); + private final Point size; + + public EditorModel() { + this.size = new Point(1024, 1024); + this.editorElementHierarchy = EditorElementHierarchy.create(); + this.undoStack = new ElementStack(50); + this.redoStack = new ElementStack(50); + } + + private EditorModel(Parcel in) { + ClassLoader classLoader = getClass().getClassLoader(); + this.size = new Point(in.readInt(), in.readInt()); + this.editorElementHierarchy = EditorElementHierarchy.create(in.readParcelable(classLoader)); + this.undoStack = in.readParcelable(classLoader); + this.redoStack = in.readParcelable(classLoader); + } + + public void setInvalidate(@Nullable Runnable invalidate) { + this.invalidate = invalidate != null ? invalidate : NULL_RUNNABLE; + } + + /** + * Renders tree with the following matrix: + *

+ * viewModelMatrix * matrix * editorMatrix + *

+ * Child nodes are supplied with a viewModelMatrix' = viewModelMatrix * matrix * editorMatrix + * + * @param rendererContext Canvas to draw on to. + */ + public void draw(@NonNull RendererContext rendererContext) { + editorElementHierarchy.getRoot().draw(rendererContext); + } + + public @Nullable Matrix findElementInverseMatrix(@NonNull EditorElement element, @NonNull Matrix viewMatrix) { + Matrix inverse = new Matrix(); + if (findElement(element, viewMatrix, inverse)) { + return inverse; + } + return null; + } + + private @Nullable Matrix findElementMatrix(@NonNull EditorElement element, @NonNull Matrix viewMatrix) { + Matrix inverse = findElementInverseMatrix(element, viewMatrix); + if (inverse != null) { + Matrix regular = new Matrix(); + inverse.invert(regular); + return regular; + } + return null; + } + + public EditorElement findElementAtPoint(@NonNull PointF point, @NonNull Matrix viewMatrix, @NonNull Matrix outInverseModelMatrix) { + return editorElementHierarchy.getRoot().findElementAt(point.x, point.y, viewMatrix, outInverseModelMatrix); + } + + private boolean findElement(@NonNull EditorElement element, @NonNull Matrix viewMatrix, @NonNull Matrix outInverseModelMatrix) { + return editorElementHierarchy.getRoot().findElement(element, viewMatrix, outInverseModelMatrix) == element; + } + + public void pushUndoPoint() { + if (undoStack.tryPush(editorElementHierarchy.getRoot())) { + redoStack.clear(); + } + } + + public void undo() { + undoRedo(undoStack, redoStack); + } + + public void redo() { + undoRedo(redoStack, undoStack); + } + + private void undoRedo(@NonNull ElementStack fromStack, @NonNull ElementStack toStack) { + final EditorElement popped = fromStack.pop(); + + if (popped != null) { + EditorElement oldRootElement = editorElementHierarchy.getRoot(); + editorElementHierarchy = EditorElementHierarchy.create(popped); + toStack.tryPush(oldRootElement); + + restoreStateWithAnimations(oldRootElement, editorElementHierarchy.getRoot(), invalidate); + invalidate.run(); + + // re-zoom image root as the view port might be different now + editorElementHierarchy.updateViewToCrop(visibleViewPort, invalidate); + } + } + + private static void restoreStateWithAnimations(@NonNull EditorElement fromRootElement, @NonNull EditorElement toRootElement, @NonNull Runnable onInvalidate) { + Map fromMap = getElementMap(fromRootElement); + Map toMap = getElementMap(toRootElement); + + for (EditorElement fromElement : fromMap.values()) { + fromElement.stopAnimation(); + EditorElement toElement = toMap.get(fromElement.getId()); + if (toElement != null) { + toElement.animateFrom(fromElement.getLocalMatrixAnimating(), onInvalidate); + } else { + // element is removed + EditorElement parentFrom = fromRootElement.parentOf(fromElement); + if (parentFrom != null) { + EditorElement toParent = toMap.get(parentFrom.getId()); + if (toParent != null) { + toParent.addDeletedChildFadingOut(fromElement, onInvalidate); + } + } + } + } + + for (EditorElement toElement : toMap.values()) { + if (!fromMap.containsKey(toElement.getId())) { + // new item + toElement.animateFadeIn(onInvalidate); + } + } + } + + private static Map getElementMap(@NonNull EditorElement element) { + final Map result = new HashMap<>(); + element.buildMap(result); + return result; + } + + public void startCrop() { + pushUndoPoint(); + editorElementHierarchy.startCrop(invalidate); + } + + public void doneCrop() { + editorElementHierarchy.doneCrop(visibleViewPort, invalidate); + } + + public void setCropAspectLock(boolean locked) { + EditorFlags flags = editorElementHierarchy.getCropEditorElement().getFlags(); + int currentState = flags.setAspectLocked(locked).getCurrentState(); + flags.reset(); + flags.setAspectLocked(locked).persist(); + flags.restoreState(currentState); + } + + public boolean isCropAspectLocked() { + return editorElementHierarchy.getCropEditorElement().getFlags().isAspectLocked(); + } + + public void dragDropRelease() { + editorElementHierarchy.dragDropRelease(visibleViewPort, invalidate); + } + + public void setVisibleViewPort(@NonNull RectF visibleViewPort) { + this.visibleViewPort.set(visibleViewPort); + this.editorElementHierarchy.updateViewToCrop(visibleViewPort, invalidate); + } + + public Set getUniqueColorsIgnoringAlpha() { + final Set colors = new LinkedHashSet<>(); + + editorElementHierarchy.getRoot().forAllInTree(element -> { + Renderer renderer = element.getRenderer(); + if (renderer instanceof ColorableRenderer) { + colors.add(((ColorableRenderer) renderer).getColor() | 0xff000000); + } + }); + + return colors; + } + + public static final Creator CREATOR = new Creator() { + @Override + public EditorModel createFromParcel(Parcel in) { + return new EditorModel(in); + } + + @Override + public EditorModel[] newArray(int size) { + return new EditorModel[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(size.x); + dest.writeInt(size.y); + dest.writeParcelable(editorElementHierarchy.getRoot(), flags); + dest.writeParcelable(undoStack, flags); + dest.writeParcelable(redoStack, flags); + } + + /** + * Blocking render of the model. + */ + @WorkerThread + public Bitmap render(@NonNull Context context) { + EditorElement image = editorElementHierarchy.getFlipRotate(); + RectF cropRect = editorElementHierarchy.getCropRect(); + Point outputSize = getOutputSize(); + + Bitmap bitmap = Bitmap.createBitmap(outputSize.x, outputSize.y, Bitmap.Config.ARGB_8888); + try { + Canvas canvas = new Canvas(bitmap); + RendererContext rendererContext = new RendererContext(context, canvas, RendererContext.Ready.NULL, RendererContext.Invalidate.NULL); + + RectF bitmapArea = new RectF(); + bitmapArea.right = bitmap.getWidth(); + bitmapArea.bottom = bitmap.getHeight(); + + Matrix viewMatrix = new Matrix(); + viewMatrix.setRectToRect(cropRect, bitmapArea, Matrix.ScaleToFit.FILL); + + rendererContext.setIsEditing(false); + rendererContext.setBlockingLoad(true); + + EditorElement overlay = editorElementHierarchy.getOverlay(); + overlay.getFlags().setVisible(false).setChildrenVisible(false); + + try { + rendererContext.canvasMatrix.initial(viewMatrix); + image.draw(rendererContext); + } finally { + overlay.getFlags().reset(); + } + } catch (Exception e) { + bitmap.recycle(); + throw e; + } + return bitmap; + } + + @NonNull + private Point getOutputSize() { + PointF outputSize = editorElementHierarchy.getOutputSize(size); + + int width = (int) Math.max(MINIMUM_OUTPUT_WIDTH, outputSize.x); + int height = (int) (width * outputSize.y / outputSize.x); + + return new Point(width, height); + } + + @Override + public void onReady(@NonNull Renderer renderer, @Nullable Matrix cropMatrix, @Nullable Point size) { + if (cropMatrix != null && size != null && isRendererOfMainImage(renderer)) { + Matrix imageCropMatrix = editorElementHierarchy.getImageCrop().getLocalMatrix(); + this.size.set(size.x, size.y); + if (imageCropMatrix.isIdentity()) { + imageCropMatrix.set(cropMatrix); + editorElementHierarchy.doneCrop(visibleViewPort, null); + } + } + } + + private boolean isRendererOfMainImage(@NonNull Renderer renderer) { + EditorElement mainImage = editorElementHierarchy.getMainImage(); + Renderer mainImageRenderer = mainImage != null ? mainImage.getRenderer() : null; + return mainImageRenderer == renderer; + } + + /** + * Add a new {@link EditorElement} centered in the current visible crop area. + * + * @param element New element to add. + * @param scale Initial scale for new element. + */ + public void addElementCentered(@NonNull EditorElement element, float scale) { + Matrix localMatrix = element.getLocalMatrix(); + + editorElementHierarchy.getMainImageFullMatrix().invert(localMatrix); + + localMatrix.preScale(scale, scale); + addElement(element); + } + + /** + * Add an element to the main image, or if there is no main image, make the new element the main image. + * + * @param element New element to add. + */ + public void addElement(@NonNull EditorElement element) { + pushUndoPoint(); + + EditorElement mainImage = editorElementHierarchy.getMainImage(); + EditorElement parent = mainImage != null ? mainImage : editorElementHierarchy.getImageRoot(); + + parent.addElement(element); + + if (parent != mainImage) { + undoStack.clear(); + } + } + + public boolean isChanged() { + return !undoStack.isEmpty() || undoStack.isOverflowed(); + } + + public RectF findCropRelativeToRoot() { + return findCropRelativeTo(editorElementHierarchy.getRoot()); + } + + private RectF findCropRelativeTo(EditorElement element) { + return findRelativeBounds(editorElementHierarchy.getCropEditorElement(), element); + } + + private RectF findRelativeBounds(EditorElement from, EditorElement to) { + Matrix matrix1 = findElementMatrix(from, new Matrix()); + Matrix matrix2 = findElementInverseMatrix(to, new Matrix()); + + RectF dst = new RectF(Bounds.FULL_BOUNDS); + if (matrix1 != null) { + matrix1.preConcat(matrix2); + + matrix1.mapRect(dst, Bounds.FULL_BOUNDS); + } + return dst; + } + + public void rotate90clockwise() { + pushUndoPoint(); + editorElementHierarchy.flipRotate(90, 1, 1, visibleViewPort, invalidate); + } + + public void rotate90anticlockwise() { + pushUndoPoint(); + editorElementHierarchy.flipRotate(-90, 1, 1, visibleViewPort, invalidate); + } + + public void flipHorizontal() { + pushUndoPoint(); + editorElementHierarchy.flipRotate(0, -1, 1, visibleViewPort, invalidate); + } + + public void flipVerticle() { + pushUndoPoint(); + editorElementHierarchy.flipRotate(0, 1, -1, visibleViewPort, invalidate); + } + + public EditorElement getRoot() { + return editorElementHierarchy.getRoot(); + } + + public void delete(@NonNull EditorElement editorElement) { + editorElementHierarchy.getImageRoot().forAllInTree(element -> element.deleteChild(editorElement, invalidate)); + } + + public @Nullable EditorElement findById(@NonNull UUID uuid) { + return getElementMap(getRoot()).get(uuid); + } + + /** + * Changes the temporary view so that the element is centered in it. + * + * @param entity Entity to center on. + * @param y An optional extra value to translate the view by to leave space for the keyboard for example. + * @param doNotZoomOut Iff true, undoes any zoom out + */ + public void zoomTo(@NonNull EditorElement entity, float y, boolean doNotZoomOut) { + Matrix elementInverseMatrix = findElementInverseMatrix(entity, new Matrix()); + if (elementInverseMatrix != null) { + elementInverseMatrix.preConcat(editorElementHierarchy.getRoot().getEditorMatrix()); + + float xScale = EditorElementHierarchy.xScale(elementInverseMatrix); + if (doNotZoomOut && xScale < 1) { + elementInverseMatrix.postScale(1 / xScale, 1 / xScale); + } + + elementInverseMatrix.postTranslate(0, y); + + editorElementHierarchy.getRoot().animateEditorTo(elementInverseMatrix, invalidate); + } + } + + public void zoomOut() { + editorElementHierarchy.getRoot().rollbackEditorMatrix(invalidate); + } + + public void indicateSelected(@NonNull EditorElement selected) { + selected.singleScalePulse(invalidate); + } + + public boolean isCropping() { + return editorElementHierarchy.getCropEditorElement().getFlags().isVisible(); + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/model/ElementStack.java b/src/org/thoughtcrime/securesms/imageeditor/model/ElementStack.java new file mode 100644 index 000000000..3b0a1b588 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/model/ElementStack.java @@ -0,0 +1,118 @@ +package org.thoughtcrime.securesms.imageeditor.model; + +import android.os.Parcel; +import android.os.Parcelable; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import java.util.Arrays; +import java.util.Stack; + +/** + * Contains a stack of elements for undo and redo stacks. + *

+ * Elements are mutable, so this stack serializes the element and keeps a stack of serialized data. + *

+ * The stack has a {@link #limit} and if it exceeds that limit the {@link #overflowed} flag is set. + * So that when used as an undo stack, {@link #isEmpty()} and {@link #isOverflowed()} tell you if the image has ever changed. + */ +final class ElementStack implements Parcelable { + + private final int limit; + private final Stack stack = new Stack<>(); + private boolean overflowed; + + ElementStack(int limit) { + this.limit = limit; + } + + private ElementStack(@NonNull Parcel in) { + this(in.readInt()); + overflowed = in.readInt() != 0; + final int count = in.readInt(); + for (int i = 0; i < count; i++) { + stack.add(i, in.createByteArray()); + } + } + + /** + * Pushes an element to the stack iff the element's serialized value is different to any found at + * the top of the stack. + * + * @param element new editor element state. + * @return true iff the pushed item was different to the top item. + */ + boolean tryPush(@NonNull EditorElement element) { + Parcel parcel = Parcel.obtain(); + byte[] bytes; + try { + parcel.writeParcelable(element, 0); + bytes = parcel.marshall(); + } finally { + parcel.recycle(); + } + boolean push = stack.isEmpty() || !Arrays.equals(bytes, stack.peek()); + if (push) { + stack.push(bytes); + if (stack.size() > limit) { + stack.remove(0); + overflowed = true; + } + } + return push; + } + + @Nullable EditorElement pop() { + if (stack.empty()) return null; + + byte[] data = stack.pop(); + Parcel parcel = Parcel.obtain(); + try { + parcel.unmarshall(data, 0, data.length); + parcel.setDataPosition(0); + return parcel.readParcelable(EditorElement.class.getClassLoader()); + } finally { + parcel.recycle(); + } + } + + void clear() { + stack.clear(); + } + + public static final Creator CREATOR = new Creator() { + @Override + public ElementStack createFromParcel(Parcel in) { + return new ElementStack(in); + } + + @Override + public ElementStack[] newArray(int size) { + return new ElementStack[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(limit); + dest.writeInt(overflowed ? 1 : 0); + final int count = stack.size(); + dest.writeInt(count); + for (int i = 0; i < count; i++) { + dest.writeByteArray(stack.get(i)); + } + } + + boolean isEmpty() { + return stack.isEmpty(); + } + + boolean isOverflowed() { + return overflowed; + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/model/ParcelUtils.java b/src/org/thoughtcrime/securesms/imageeditor/model/ParcelUtils.java new file mode 100644 index 000000000..8ef74329d --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/model/ParcelUtils.java @@ -0,0 +1,34 @@ +package org.thoughtcrime.securesms.imageeditor.model; + +import android.graphics.Matrix; +import android.os.Parcel; +import android.support.annotation.NonNull; + +import java.util.UUID; + +final class ParcelUtils { + + private ParcelUtils() { + } + + static void writeMatrix(@NonNull Parcel dest, @NonNull Matrix matrix) { + float[] values = new float[9]; + matrix.getValues(values); + dest.writeFloatArray(values); + } + + static void readMatrix(@NonNull Matrix matrix, @NonNull Parcel in) { + float[] values = new float[9]; + in.readFloatArray(values); + matrix.setValues(values); + } + + static UUID readUUID(@NonNull Parcel in) { + return new UUID(in.readLong(), in.readLong()); + } + + static void writeUUID(@NonNull Parcel dest, @NonNull UUID uuid) { + dest.writeLong(uuid.getMostSignificantBits()); + dest.writeLong(uuid.getLeastSignificantBits()); + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/model/ThumbRenderer.java b/src/org/thoughtcrime/securesms/imageeditor/model/ThumbRenderer.java new file mode 100644 index 000000000..21020b525 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/model/ThumbRenderer.java @@ -0,0 +1,73 @@ +package org.thoughtcrime.securesms.imageeditor.model; + +import org.thoughtcrime.securesms.imageeditor.Bounds; +import org.thoughtcrime.securesms.imageeditor.Renderer; + +import java.util.UUID; + +/** + * A special {@link Renderer} that controls another {@link EditorElement}. + *

+ * It has a reference to the {@link EditorElement#getId()} and a {@link ControlPoint} which it is in control of. + *

+ * The presence of this interface on the selected element is used to launch a ThumbDragEditSession. + */ +public interface ThumbRenderer extends Renderer { + + enum ControlPoint { + + CENTER_LEFT (Bounds.LEFT, Bounds.CENTRE_Y), + CENTER_RIGHT (Bounds.RIGHT, Bounds.CENTRE_Y), + + TOP_CENTER (Bounds.CENTRE_X, Bounds.TOP), + BOTTOM_CENTER (Bounds.CENTRE_X, Bounds.BOTTOM), + + TOP_LEFT (Bounds.LEFT, Bounds.TOP), + TOP_RIGHT (Bounds.RIGHT, Bounds.TOP), + BOTTOM_LEFT (Bounds.LEFT, Bounds.BOTTOM), + BOTTOM_RIGHT (Bounds.RIGHT, Bounds.BOTTOM); + + private final float x; + private final float y; + + ControlPoint(float x, float y) { + this.x = x; + this.y = y; + } + + public float getX() { + return x; + } + + public float getY() { + return y; + } + + public ControlPoint opposite() { + switch (this) { + case CENTER_LEFT: return CENTER_RIGHT; + case CENTER_RIGHT: return CENTER_LEFT; + case TOP_CENTER: return BOTTOM_CENTER; + case BOTTOM_CENTER: return TOP_CENTER; + case TOP_LEFT: return BOTTOM_RIGHT; + case TOP_RIGHT: return BOTTOM_LEFT; + case BOTTOM_LEFT: return TOP_RIGHT; + case BOTTOM_RIGHT: return TOP_LEFT; + default: + throw new RuntimeException(); + } + } + + public boolean isHorizontalCenter() { + return this == ControlPoint.CENTER_LEFT || this == ControlPoint.CENTER_RIGHT; + } + + public boolean isVerticalCenter() { + return this == ControlPoint.TOP_CENTER || this == ControlPoint.BOTTOM_CENTER; + } + } + + ControlPoint getControlPoint(); + + UUID getElementToControl(); +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/renderers/AutomaticControlPointBezierLine.java b/src/org/thoughtcrime/securesms/imageeditor/renderers/AutomaticControlPointBezierLine.java new file mode 100644 index 000000000..22d5a4b8c --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/renderers/AutomaticControlPointBezierLine.java @@ -0,0 +1,224 @@ +package org.thoughtcrime.securesms.imageeditor.renderers; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.os.Parcel; +import android.os.Parcelable; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import java.util.Arrays; + +/** + * Given points for a line to go though, automatically finds control points. + *

+ * Based on http://www.particleincell.com/2012/bezier-splines/ + *

+ * Can then draw that line to a {@link Canvas} given a {@link Paint}. + *

+ * Allocation efficient so that adding new points does not result in lots of array allocations. + */ +final class AutomaticControlPointBezierLine implements Parcelable { + + private static final int INITIAL_CAPACITY = 256; + + private float[] x; + private float[] y; + + // control points + private float[] p1x; + private float[] p1y; + private float[] p2x; + private float[] p2y; + + private int count; + + private final Path path = new Path(); + + private AutomaticControlPointBezierLine(@Nullable float[] x, @Nullable float[] y, int count) { + this.count = count; + this.x = x != null ? x : new float[INITIAL_CAPACITY]; + this.y = y != null ? y : new float[INITIAL_CAPACITY]; + allocControlPointsAndWorkingMemory(this.x.length); + recalculateControlPoints(); + } + + AutomaticControlPointBezierLine() { + this(null, null, 0); + } + + void reset() { + count = 0; + path.reset(); + } + + /** + * Adds a new point to the end of the line but ignores points that are too close to the last. + * + * @param x new x point + * @param y new y point + * @param thickness the maximum distance to allow, line thickness is recommended. + */ + void addPointFiltered(float x, float y, float thickness) { + if (count > 0) { + float dx = this.x[count - 1] - x; + float dy = this.y[count - 1] - y; + if (dx * dx + dy * dy < thickness * thickness) { + return; + } + } + addPoint(x, y); + } + + /** + * Adds a new point to the end of the line. + * + * @param x new x point + * @param y new y point + */ + void addPoint(float x, float y) { + if (this.x == null || count == this.x.length) { + resize(this.x != null ? this.x.length << 1 : INITIAL_CAPACITY); + } + + this.x[count] = x; + this.y[count] = y; + count++; + + recalculateControlPoints(); + } + + private void resize(int newCapacity) { + x = Arrays.copyOf(x, newCapacity); + y = Arrays.copyOf(y, newCapacity); + allocControlPointsAndWorkingMemory(newCapacity - 1); + } + + private void allocControlPointsAndWorkingMemory(int max) { + p1x = new float[max]; + p1y = new float[max]; + p2x = new float[max]; + p2y = new float[max]; + + a = new float[max]; + b = new float[max]; + c = new float[max]; + r = new float[max]; + } + + private void recalculateControlPoints() { + path.reset(); + + if (count > 2) { + computeControlPoints(x, p1x, p2x, count); + computeControlPoints(y, p1y, p2y, count); + } + + path.moveTo(x[0], y[0]); + switch (count) { + case 1: + path.lineTo(x[0], y[0]); + break; + case 2: + path.lineTo(x[1], y[1]); + break; + default: + for (int i = 1; i < count - 1; i++) { + path.cubicTo(p1x[i], p1y[i], p2x[i], p2y[i], x[i + 1], y[i + 1]); + } + } + } + + /** + * Draw the line. + * + * @param canvas The canvas to draw on. + * @param paint The paint to use. + */ + void draw(@NonNull Canvas canvas, @NonNull Paint paint) { + canvas.drawPath(path, paint); + } + + // rhs vector for computeControlPoints method + private float[] a; + private float[] b; + private float[] c; + private float[] r; + + /** + * Based on http://www.particleincell.com/2012/bezier-splines/ + * + * @param k knots x or y, must be at least 2 entries + * @param p1 corresponding first control point x or y + * @param p2 corresponding second control point x or y + * @param count number of k to process + */ + private void computeControlPoints(float[] k, float[] p1, float[] p2, int count) { + final int n = count - 1; + + // left most segment + a[0] = 0; + b[0] = 2; + c[0] = 1; + r[0] = k[0] + 2 * k[1]; + + // internal segments + for (int i = 1; i < n - 1; i++) { + a[i] = 1; + b[i] = 4; + c[i] = 1; + r[i] = 4 * k[i] + 2 * k[i + 1]; + } + + // right segment + a[n - 1] = 2; + b[n - 1] = 7; + c[n - 1] = 0; + r[n - 1] = 8 * k[n - 1] + k[n]; + + // solves Ax=b with the Thomas algorithm + for (int i = 1; i < n; i++) { + float m = a[i] / b[i - 1]; + b[i] = b[i] - m * c[i - 1]; + r[i] = r[i] - m * r[i - 1]; + } + + p1[n - 1] = r[n - 1] / b[n - 1]; + for (int i = n - 2; i >= 0; --i) { + p1[i] = (r[i] - c[i] * p1[i + 1]) / b[i]; + } + + // we have p1, now compute p2 + for (int i = 0; i < n - 1; i++) { + p2[i] = 2 * k[i + 1] - p1[i + 1]; + } + + p2[n - 1] = 0.5f * (k[n] + p1[n - 1]); + } + + public static final Creator CREATOR = new Creator() { + @Override + public AutomaticControlPointBezierLine createFromParcel(Parcel in) { + float[] x = in.createFloatArray(); + float[] y = in.createFloatArray(); + return new AutomaticControlPointBezierLine(x, y, x != null ? x.length : 0); + } + + @Override + public AutomaticControlPointBezierLine[] newArray(int size) { + return new AutomaticControlPointBezierLine[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeFloatArray(Arrays.copyOfRange(x, 0, count)); + dest.writeFloatArray(Arrays.copyOfRange(y, 0, count)); + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/renderers/BezierDrawingRenderer.java b/src/org/thoughtcrime/securesms/imageeditor/renderers/BezierDrawingRenderer.java new file mode 100644 index 000000000..6259e794b --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/renderers/BezierDrawingRenderer.java @@ -0,0 +1,144 @@ +package org.thoughtcrime.securesms.imageeditor.renderers; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PointF; +import android.graphics.RectF; +import android.os.Parcel; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import org.thoughtcrime.securesms.imageeditor.ColorableRenderer; +import org.thoughtcrime.securesms.imageeditor.RendererContext; + +/** + * Renders a {@link AutomaticControlPointBezierLine} with {@link #thickness}, {@link #color} and {@link #cap} end type. + */ +public final class BezierDrawingRenderer extends InvalidateableRenderer implements ColorableRenderer { + + private final Paint paint; + private final AutomaticControlPointBezierLine bezierLine; + private final Paint.Cap cap; + + @Nullable + private final RectF clipRect; + + private int color; + private float thickness; + + private BezierDrawingRenderer(int color, float thickness, @NonNull Paint.Cap cap, @Nullable AutomaticControlPointBezierLine bezierLine, @Nullable RectF clipRect) { + this.paint = new Paint(); + this.color = color; + this.thickness = thickness; + this.cap = cap; + this.clipRect = clipRect; + this.bezierLine = bezierLine != null ? bezierLine : new AutomaticControlPointBezierLine(); + + updatePaint(); + } + + public BezierDrawingRenderer(int color, float thickness, @NonNull Paint.Cap cap, @Nullable RectF clipRect) { + this(color, thickness, cap,null, clipRect != null ? new RectF(clipRect) : null); + } + + @Override + public int getColor() { + return color; + } + + @Override + public void setColor(int color) { + if (this.color != color) { + this.color = color; + updatePaint(); + invalidate(); + } + } + + public void setThickness(float thickness) { + if (this.thickness != thickness) { + this.thickness = thickness; + updatePaint(); + invalidate(); + } + } + + private void updatePaint() { + paint.setColor(color); + paint.setStrokeWidth(thickness); + paint.setStyle(Paint.Style.STROKE); + paint.setAntiAlias(true); + paint.setStrokeCap(cap); + } + + public void setFirstPoint(PointF point) { + bezierLine.reset(); + bezierLine.addPoint(point.x, point.y); + invalidate(); + } + + public void addNewPoint(PointF point) { + if (cap != Paint.Cap.ROUND) { + bezierLine.addPointFiltered(point.x, point.y, thickness * 0.5f); + } else { + bezierLine.addPoint(point.x, point.y); + } + invalidate(); + } + + @Override + public void render(@NonNull RendererContext rendererContext) { + super.render(rendererContext); + Canvas canvas = rendererContext.canvas; + canvas.save(); + if (clipRect != null) { + canvas.clipRect(clipRect); + } + + int alpha = paint.getAlpha(); + paint.setAlpha(rendererContext.getAlpha(alpha)); + + bezierLine.draw(canvas, paint); + + paint.setAlpha(alpha); + rendererContext.canvas.restore(); + } + + @Override + public boolean hitTest(float x, float y) { + return false; + } + + public static final Creator CREATOR = new Creator() { + @Override + public BezierDrawingRenderer createFromParcel(Parcel in) { + int color = in.readInt(); + float thickness = in.readFloat(); + Paint.Cap cap = Paint.Cap.values()[in.readInt()]; + AutomaticControlPointBezierLine bezierLine = in.readParcelable(AutomaticControlPointBezierLine.class.getClassLoader()); + RectF clipRect = in.readParcelable(RectF.class.getClassLoader()); + + return new BezierDrawingRenderer(color, thickness, cap, bezierLine, clipRect); + } + + @Override + public BezierDrawingRenderer[] newArray(int size) { + return new BezierDrawingRenderer[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(color); + dest.writeFloat(thickness); + dest.writeInt(cap.ordinal()); + dest.writeParcelable(bezierLine, flags); + dest.writeParcelable(clipRect, flags); + } + +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/renderers/CropAreaRenderer.java b/src/org/thoughtcrime/securesms/imageeditor/renderers/CropAreaRenderer.java new file mode 100644 index 000000000..67f26354f --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/renderers/CropAreaRenderer.java @@ -0,0 +1,133 @@ +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 android.support.annotation.ColorRes; +import android.support.annotation.NonNull; +import android.support.v4.content.res.ResourcesCompat; + +import org.thoughtcrime.securesms.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.FULL_BOUNDS.contains(x, y); + } + + public static final Creator CREATOR = new Creator() { + @Override + public CropAreaRenderer createFromParcel(Parcel in) { + return new CropAreaRenderer(in); + } + + @Override + public CropAreaRenderer[] newArray(int size) { + return new CropAreaRenderer[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(color); + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/renderers/InvalidateableRenderer.java b/src/org/thoughtcrime/securesms/imageeditor/renderers/InvalidateableRenderer.java new file mode 100644 index 000000000..88c5549d0 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/renderers/InvalidateableRenderer.java @@ -0,0 +1,34 @@ +package org.thoughtcrime.securesms.imageeditor.renderers; + +import android.support.annotation.NonNull; + +import org.thoughtcrime.securesms.imageeditor.Renderer; +import org.thoughtcrime.securesms.imageeditor.RendererContext; + +import java.lang.ref.WeakReference; + +/** + * Maintains a weak reference to the an invalidate callback allowing future invalidation without memory leak risk. + */ +abstract class InvalidateableRenderer implements Renderer { + + private WeakReference invalidate = new WeakReference<>(null); + + @Override + public void render(@NonNull RendererContext rendererContext) { + setInvalidate(rendererContext.invalidate); + } + + private void setInvalidate(RendererContext.Invalidate invalidate) { + if (invalidate != this.invalidate.get()) { + this.invalidate = new WeakReference<>(invalidate); + } + } + + protected void invalidate() { + RendererContext.Invalidate invalidate = this.invalidate.get(); + if (invalidate != null) { + invalidate.onInvalidate(this); + } + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/renderers/InverseFillRenderer.java b/src/org/thoughtcrime/securesms/imageeditor/renderers/InverseFillRenderer.java new file mode 100644 index 000000000..71f42c687 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/renderers/InverseFillRenderer.java @@ -0,0 +1,71 @@ +package org.thoughtcrime.securesms.imageeditor.renderers; + +import android.graphics.Path; +import android.os.Parcel; +import android.support.annotation.ColorInt; +import android.support.annotation.NonNull; + +import org.thoughtcrime.securesms.imageeditor.Bounds; +import org.thoughtcrime.securesms.imageeditor.Renderer; +import org.thoughtcrime.securesms.imageeditor.RendererContext; + +/** + * Renders the {@link color} outside of the {@link Bounds}. + *

+ * Hit tests outside of the bounds. + */ +public final class InverseFillRenderer implements Renderer { + + private final int color; + + private final Path path = new Path(); + + @Override + public void render(@NonNull RendererContext rendererContext) { + rendererContext.canvas.save(); + rendererContext.canvas.clipPath(path); + rendererContext.canvas.drawColor(color); + rendererContext.canvas.restore(); + } + + public InverseFillRenderer(@ColorInt int color) { + this.color = color; + path.toggleInverseFillType(); + path.moveTo(Bounds.LEFT, Bounds.TOP); + path.lineTo(Bounds.RIGHT, Bounds.TOP); + path.lineTo(Bounds.RIGHT, Bounds.BOTTOM); + path.lineTo(Bounds.LEFT, Bounds.BOTTOM); + path.close(); + } + + private InverseFillRenderer(Parcel in) { + this(in.readInt()); + } + + @Override + public boolean hitTest(float x, float y) { + return !Bounds.FULL_BOUNDS.contains(x, y); + } + + public static final Creator CREATOR = new Creator() { + @Override + public InverseFillRenderer createFromParcel(Parcel in) { + return new InverseFillRenderer(in); + } + + @Override + public InverseFillRenderer[] newArray(int size) { + return new InverseFillRenderer[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(color); + } +} diff --git a/src/org/thoughtcrime/securesms/imageeditor/renderers/TextRenderer.java b/src/org/thoughtcrime/securesms/imageeditor/renderers/TextRenderer.java new file mode 100644 index 000000000..182f459c4 --- /dev/null +++ b/src/org/thoughtcrime/securesms/imageeditor/renderers/TextRenderer.java @@ -0,0 +1,204 @@ +package org.thoughtcrime.securesms.imageeditor.renderers; + +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Typeface; +import android.os.Parcel; +import android.support.annotation.ColorInt; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import org.thoughtcrime.securesms.imageeditor.Bounds; +import org.thoughtcrime.securesms.imageeditor.ColorableRenderer; +import org.thoughtcrime.securesms.imageeditor.RendererContext; + +/** + * Renders a single line of {@link #text} in ths specified {@link #color}. + *

+ * Scales down the text size to fit inside the {@link Bounds} width. + */ +public final class TextRenderer extends InvalidateableRenderer implements ColorableRenderer { + + @NonNull + private String text = ""; + + @ColorInt + private int color; + + private final Paint paint = new Paint(); + private final Paint selectionPaint = new Paint(); + private final RectF textBounds = new RectF(); + private final RectF selectionBounds = new RectF(); + private final RectF maxTextBounds = new RectF(); + private final Matrix projectionMatrix = new Matrix(); + private final Matrix inverseProjectionMatrix = new Matrix(); + + private final float textScale; + + private float xForCentre; + private int selStart; + private int selEnd; + private boolean hasFocus; + + public TextRenderer(@Nullable String text, @ColorInt int color) { + setColor(color); + float regularTextSize = paint.getTextSize(); + paint.setAntiAlias(true); + paint.setTextSize(100); + paint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + textScale = paint.getTextSize() / regularTextSize; + selectionPaint.setAntiAlias(true); + setText(text != null ? text : ""); + } + + private TextRenderer(Parcel in) { + this(in.readString(), in.readInt()); + } + + public static final Creator CREATOR = new Creator() { + @Override + public TextRenderer createFromParcel(Parcel in) { + return new TextRenderer(in); + } + + @Override + public TextRenderer[] newArray(int size) { + return new TextRenderer[size]; + } + }; + + @Override + public void render(@NonNull RendererContext rendererContext) { + super.render(rendererContext); + rendererContext.save(); + Canvas canvas = rendererContext.canvas; + + rendererContext.canvasMatrix.concat(projectionMatrix); + + canvas.clipRect(textBounds); + + if (hasFocus) { + canvas.drawRect(selectionBounds, selectionPaint); + } + + int alpha = paint.getAlpha(); + paint.setAlpha(rendererContext.getAlpha(alpha)); + + canvas.drawText(text, xForCentre, 0, paint); + + paint.setAlpha(alpha); + + rendererContext.restore(); + } + + @NonNull + public String getText() { + return text; + } + + public void setText(@NonNull String text) { + if (!this.text.equals(text)) { + this.text = text; + recalculate(); + } + } + + private void recalculate() { + Rect temp = new Rect(); + + getTextBoundsWithoutTrim(text, 0, text.length(), temp); + textBounds.set(temp); + + maxTextBounds.set(textBounds); + maxTextBounds.right = Math.max(150 * textScale, maxTextBounds.right); + + xForCentre = maxTextBounds.centerX() - textBounds.centerX(); + + textBounds.left += xForCentre; + textBounds.right += xForCentre; + + if (selStart != selEnd) { + getTextBoundsWithoutTrim(text, Math.min(text.length(), selStart), Math.min(text.length(), selEnd), temp); + } else { + Rect startTemp = new Rect(); + int start = Math.min(text.length(), selStart); + String text = this.text.substring(0, start); + + getTextBoundsWithoutTrim(text, 0, start, startTemp); + paint.getTextBounds("|", 0, 1, temp); + + int width = temp.width(); + + temp.left -= width; + temp.right -= width; + temp.left += startTemp.right; + temp.right += startTemp.right; + } + selectionBounds.set(temp); + selectionBounds.left += xForCentre; + selectionBounds.right += xForCentre; + + projectionMatrix.setRectToRect(new RectF(maxTextBounds), Bounds.FULL_BOUNDS, Matrix.ScaleToFit.CENTER); + projectionMatrix.invert(inverseProjectionMatrix); + invalidate(); + } + + private void getTextBoundsWithoutTrim(String text, int start, int end, Rect result) { + Rect extra = new Rect(); + Rect xBounds = new Rect(); + String cannotBeTrimmed = "x" + text.substring(start, end) + "x"; + paint.getTextBounds(cannotBeTrimmed, 0, cannotBeTrimmed.length(), extra); + paint.getTextBounds("x", 0, 1, xBounds); + result.set(extra); + result.right -= 2 * xBounds.width(); + } + + @Override + public int getColor() { + return color; + } + + @Override + public void setColor(@ColorInt int color) { + if (this.color != color) { + this.color = color; + paint.setColor(color); + selectionPaint.setColor(color & ~0xff000000 | 0x7f000000); + invalidate(); + } + } + + @Override + public boolean hitTest(float x, float y) { + float[] dst = new float[2]; + inverseProjectionMatrix.mapPoints(dst, new float[]{ x, y }); + return textBounds.contains(dst[0], dst[1]); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(text); + dest.writeInt(color); + } + + public void setSelection(int selStart, int selEnd) { + this.selStart = selStart; + this.selEnd = selEnd; + recalculate(); + } + + public void setFocused(boolean hasFocus) { + if (this.hasFocus != hasFocus) { + this.hasFocus = hasFocus; + invalidate(); + } + } +} diff --git a/src/org/thoughtcrime/securesms/mediasend/MediaSendActivity.java b/src/org/thoughtcrime/securesms/mediasend/MediaSendActivity.java index 289fd2332..41edfe10e 100644 --- a/src/org/thoughtcrime/securesms/mediasend/MediaSendActivity.java +++ b/src/org/thoughtcrime/securesms/mediasend/MediaSendActivity.java @@ -27,7 +27,7 @@ import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.providers.BlobProvider; import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.scribbles.ScribbleFragment; +import org.thoughtcrime.securesms.scribbles.ImageEditorFragment; import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.MediaUtil; import org.thoughtcrime.securesms.util.Util; @@ -49,7 +49,7 @@ import java.util.Locale; public class MediaSendActivity extends PassphraseRequiredActionBarActivity implements MediaPickerFolderFragment.Controller, MediaPickerItemFragment.Controller, MediaSendFragment.Controller, - ScribbleFragment.Controller, + ImageEditorFragment.Controller, Camera1Fragment.Controller { private static final String TAG = MediaSendActivity.class.getSimpleName(); @@ -446,4 +446,12 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple button.startAnimation(grow); } + + @Override + public void onRequestFullScreen(boolean fullScreen) { + MediaSendFragment sendFragment = (MediaSendFragment) getSupportFragmentManager().findFragmentByTag(TAG_SEND); + if (sendFragment != null && sendFragment.isVisible()) { + sendFragment.onRequestFullScreen(fullScreen); + } + } } diff --git a/src/org/thoughtcrime/securesms/mediasend/MediaSendFragment.java b/src/org/thoughtcrime/securesms/mediasend/MediaSendFragment.java index 496158ac3..071771b9f 100644 --- a/src/org/thoughtcrime/securesms/mediasend/MediaSendFragment.java +++ b/src/org/thoughtcrime/securesms/mediasend/MediaSendFragment.java @@ -28,6 +28,7 @@ import android.view.WindowManager; import android.view.inputmethod.EditorInfo; import android.widget.TextView; +import org.thoughtcrime.securesms.imageeditor.model.EditorModel; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.TransportOption; import org.thoughtcrime.securesms.components.ComposeText; @@ -43,7 +44,7 @@ import org.thoughtcrime.securesms.mediapreview.MediaRailAdapter; import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.providers.BlobProvider; import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.scribbles.widget.ScribbleView; +import org.thoughtcrime.securesms.scribbles.ImageEditorFragment; import org.thoughtcrime.securesms.util.CharacterCalculator.CharacterState; import org.thoughtcrime.securesms.util.MediaUtil; import org.thoughtcrime.securesms.util.Stopwatch; @@ -51,6 +52,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.ThemeUtil; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; +import org.thoughtcrime.securesms.util.concurrent.SettableFuture; import org.thoughtcrime.securesms.util.views.Stub; import org.whispersystems.libsignal.util.guava.Optional; @@ -79,6 +81,7 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl private static final String KEY_LOCALE = "locale"; private InputAwareLayout hud; + private View captionAndRail; private SendButton sendButton; private ComposeText composeText; private ViewGroup composeContainer; @@ -140,6 +143,7 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { hud = view.findViewById(R.id.mediasend_hud); + captionAndRail = view.findViewById(R.id.mediasend_caption_and_rail); sendButton = view.findViewById(R.id.mediasend_send_button); composeText = view.findViewById(R.id.mediasend_compose_text); composeContainer = view.findViewById(R.id.mediasend_compose_container); @@ -313,7 +317,9 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl } public void onTouchEventsNeeded(boolean needed) { - fragmentPager.setEnabled(!needed); + if (fragmentPager != null) { + fragmentPager.setEnabled(!needed); + } } public boolean handleBackPress() { @@ -423,8 +429,11 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl for (Media media : mediaList) { Object state = savedState.get(media.getUri()); - if (state instanceof ScribbleView.SavedState && !((ScribbleView.SavedState) state).isEmpty()) { - futures.put(media, ScribbleView.renderImage(requireContext(), media.getUri(), (ScribbleView.SavedState) state, GlideApp.with(this))); + if (state instanceof ImageEditorFragment.Data) { + EditorModel model = ((ImageEditorFragment.Data) state).readModel(); + if (model != null && model.isChanged()) { + futures.put(media, render(requireContext(), model)); + } } } @@ -493,6 +502,18 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl }.execute(); } + private static ListenableFuture render(@NonNull Context context, @NonNull EditorModel model) { + SettableFuture future = new SettableFuture<>(); + + AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> future.set(model.render(context))); + + return future; + } + + public void onRequestFullScreen(boolean fullScreen) { + captionAndRail.setVisibility(fullScreen ? View.GONE : View.VISIBLE); + } + private class FragmentPageChangeListener extends ViewPager.SimpleOnPageChangeListener { @Override public void onPageSelected(int position) { diff --git a/src/org/thoughtcrime/securesms/mediasend/MediaSendFragmentPagerAdapter.java b/src/org/thoughtcrime/securesms/mediasend/MediaSendFragmentPagerAdapter.java index 8830027c7..31e718d12 100644 --- a/src/org/thoughtcrime/securesms/mediasend/MediaSendFragmentPagerAdapter.java +++ b/src/org/thoughtcrime/securesms/mediasend/MediaSendFragmentPagerAdapter.java @@ -9,15 +9,12 @@ import android.support.v4.app.FragmentStatePagerAdapter; import android.view.View; import android.view.ViewGroup; -import org.thoughtcrime.securesms.logging.Log; -import org.thoughtcrime.securesms.scribbles.ScribbleFragment; +import org.thoughtcrime.securesms.scribbles.ImageEditorFragment; import org.thoughtcrime.securesms.util.MediaUtil; -import org.whispersystems.libsignal.util.guava.Optional; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Locale; import java.util.Map; class MediaSendFragmentPagerAdapter extends FragmentStatePagerAdapter { @@ -40,7 +37,7 @@ class MediaSendFragmentPagerAdapter extends FragmentStatePagerAdapter { if (MediaUtil.isGif(mediaItem.getMimeType())) { return MediaSendGifFragment.newInstance(mediaItem.getUri()); } else if (MediaUtil.isImageType(mediaItem.getMimeType())) { - return ScribbleFragment.newInstance(mediaItem.getUri()); + return ImageEditorFragment.newInstance(mediaItem.getUri()); } else if (MediaUtil.isVideoType(mediaItem.getMimeType())) { return MediaSendVideoFragment.newInstance(mediaItem.getUri()); } else { diff --git a/src/org/thoughtcrime/securesms/scribbles/ImageEditorFragment.java b/src/org/thoughtcrime/securesms/scribbles/ImageEditorFragment.java new file mode 100644 index 000000000..2c2e37e45 --- /dev/null +++ b/src/org/thoughtcrime/securesms/scribbles/ImageEditorFragment.java @@ -0,0 +1,376 @@ +package org.thoughtcrime.securesms.scribbles; + +import android.content.Intent; +import android.graphics.Paint; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.imageeditor.ColorableRenderer; +import org.thoughtcrime.securesms.imageeditor.ImageEditorView; +import org.thoughtcrime.securesms.imageeditor.Renderer; +import org.thoughtcrime.securesms.imageeditor.model.EditorElement; +import org.thoughtcrime.securesms.imageeditor.model.EditorModel; +import org.thoughtcrime.securesms.imageeditor.renderers.TextRenderer; +import org.thoughtcrime.securesms.logging.Log; +import org.thoughtcrime.securesms.mediasend.MediaSendPageFragment; +import org.thoughtcrime.securesms.mms.MediaConstraints; +import org.thoughtcrime.securesms.mms.PushMediaConstraints; +import org.thoughtcrime.securesms.scribbles.widget.VerticalSlideColorPicker; +import org.thoughtcrime.securesms.util.ParcelUtil; +import org.thoughtcrime.securesms.util.TextSecurePreferences; + +import static android.app.Activity.RESULT_OK; + +public final class ImageEditorFragment extends Fragment implements ImageEditorHud.EventListener, + VerticalSlideColorPicker.OnColorChangeListener, + MediaSendPageFragment { + + private static final String TAG = Log.tag(ImageEditorFragment.class); + + private static final String KEY_IMAGE_URI = "image_uri"; + + public static final int SELECT_STICKER_REQUEST_CODE = 123; + + private EditorModel restoredModel; + + @Nullable + private EditorElement currentSelection; + private int imageMaxHeight; + private int imageMaxWidth; + + public static class Data { + private final Bundle bundle; + + Data(Bundle bundle) { + this.bundle = bundle; + } + + public Data() { + this(new Bundle()); + } + + void writeModel(@NonNull EditorModel model) { + byte[] bytes = ParcelUtil.serialize(model); + bundle.putByteArray("MODEL", bytes); + } + + @Nullable + public EditorModel readModel() { + byte[] bytes = bundle.getByteArray("MODEL"); + if (bytes == null) { + return null; + } + return ParcelUtil.deserialize(bytes, EditorModel.CREATOR); + } + } + + private Uri imageUri; + private Controller controller; + private ImageEditorHud imageEditorHud; + private ImageEditorView imageEditorView; + + public static ImageEditorFragment newInstance(@NonNull Uri imageUri) { + Bundle args = new Bundle(); + args.putParcelable(KEY_IMAGE_URI, imageUri); + + ImageEditorFragment fragment = new ImageEditorFragment(); + fragment.setArguments(args); + fragment.setUri(imageUri); + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (!(getActivity() instanceof Controller)) { + throw new IllegalStateException("Parent activity must implement Controller interface."); + } + controller = (Controller) getActivity(); + Bundle arguments = getArguments(); + if (arguments != null) { + imageUri = arguments.getParcelable(KEY_IMAGE_URI); + } + + if (imageUri == null) { + throw new AssertionError("No KEY_IMAGE_URI supplied"); + } + + MediaConstraints mediaConstraints = new PushMediaConstraints(); + + imageMaxWidth = mediaConstraints.getImageMaxWidth(requireContext()); + imageMaxHeight = mediaConstraints.getImageMaxHeight(requireContext()); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.image_editor_fragment, container, false); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + imageEditorHud = view.findViewById(R.id.scribble_hud); + imageEditorView = view.findViewById(R.id.image_editor_view); + + imageEditorHud.setEventListener(this); + + imageEditorView.setTapListener(selectionListener); + imageEditorView.setDrawingChangedListener(this::refreshUniqueColors); + + EditorModel editorModel = null; + + if (restoredModel != null) { + editorModel = restoredModel; + restoredModel = null; + } else if (savedInstanceState != null) { + editorModel = new Data(savedInstanceState).readModel(); + } + + if (editorModel == null) { + editorModel = new EditorModel(); + EditorElement image = new EditorElement(new UriGlideRenderer(imageUri, true, imageMaxWidth, imageMaxHeight)); + image.getFlags().setSelectable(false).persist(); + editorModel.addElement(image); + } + + imageEditorView.setModel(editorModel); + + refreshUniqueColors(); + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + new Data(outState).writeModel(imageEditorView.getModel()); + } + + @Override + public void setUri(@NonNull Uri uri) { + this.imageUri = uri; + } + + @NonNull + @Override + public Uri getUri() { + return imageUri; + } + + @Nullable + @Override + public View getPlaybackControls() { + return null; + } + + @Override + public Object saveState() { + Data data = new Data(); + data.writeModel(imageEditorView.getModel()); + return data; + } + + @Override + public void restoreState(@NonNull Object state) { + if (state instanceof Data) { + + Data data = (Data) state; + EditorModel model = data.readModel(); + + if (model != null) { + if (imageEditorView != null) { + imageEditorView.setModel(model); + refreshUniqueColors(); + } else { + this.restoredModel = model; + } + } + } else { + Log.w(TAG, "Received a bad saved state. Received class: " + state.getClass().getName()); + } + } + + private void changeEntityColor(int selectedColor) { + if (currentSelection != null) { + Renderer renderer = currentSelection.getRenderer(); + if (renderer instanceof ColorableRenderer) { + ((ColorableRenderer) renderer).setColor(selectedColor); + refreshUniqueColors(); + } + } + } + + private void startTextEntityEditing(@NonNull EditorElement textElement, boolean selectAll) { + imageEditorView.startTextEditing(textElement, TextSecurePreferences.isIncognitoKeyboardEnabled(requireContext()), selectAll); + } + + protected void addText() { + String initialText = requireContext().getString(R.string.ImageEditorFragment_initial_text); + int color = imageEditorHud.getActiveColor(); + TextRenderer renderer = new TextRenderer(initialText, color); + EditorElement element = new EditorElement(renderer); + + imageEditorView.getModel().addElementCentered(element, 1); + imageEditorView.invalidate(); + + currentSelection = element; + + startTextEntityEditing(element, true); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK && requestCode == SELECT_STICKER_REQUEST_CODE && data != null) { + final String stickerFile = data.getStringExtra(StickerSelectActivity.EXTRA_STICKER_FILE); + + UriGlideRenderer renderer = new UriGlideRenderer(Uri.parse("file:///android_asset/" + stickerFile), false, imageMaxWidth, imageMaxHeight); + EditorElement element = new EditorElement(renderer); + imageEditorView.getModel().addElementCentered(element, 0.2f); + currentSelection = element; + } + } + + @Override + public void onModeStarted(@NonNull ImageEditorHud.Mode mode) { + imageEditorView.setMode(ImageEditorView.Mode.MoveAndResize); + imageEditorView.doneTextEditing(); + + controller.onTouchEventsNeeded(mode != ImageEditorHud.Mode.NONE); + + switch (mode) { + case CROP: + imageEditorView.getModel().startCrop(); + break; + + case DRAW: + imageEditorView.startDrawing(0.01f, Paint.Cap.ROUND); + break; + + case HIGHLIGHT: + imageEditorView.startDrawing(0.03f, Paint.Cap.SQUARE); + break; + + case TEXT: + addText(); + break; + + case MOVE_DELETE: + Intent intent = new Intent(getContext(), StickerSelectActivity.class); + startActivityForResult(intent, SELECT_STICKER_REQUEST_CODE); + break; + + case NONE: + imageEditorView.getModel().doneCrop(); + currentSelection = null; + break; + } + } + + @Override + public void onColorChange(int color) { + imageEditorView.setDrawingBrushColor(color); + changeEntityColor(color); + } + + @Override + public void onUndo() { + imageEditorView.getModel().undo(); + refreshUniqueColors(); + } + + @Override + public void onDelete() { + imageEditorView.deleteElement(currentSelection); + refreshUniqueColors(); + } + + @Override + public void onFlipHorizontal() { + imageEditorView.getModel().flipHorizontal(); + } + + @Override + public void onRotate90AntiClockwise() { + imageEditorView.getModel().rotate90anticlockwise(); + } + + @Override + public void onCropAspectLock(boolean locked) { + imageEditorView.getModel().setCropAspectLock(locked); + } + + @Override + public boolean isCropAspectLocked() { + return imageEditorView.getModel().isCropAspectLocked(); + } + + @Override + public void onRequestFullScreen(boolean fullScreen) { + controller.onRequestFullScreen(fullScreen); + } + + private void refreshUniqueColors() { + imageEditorHud.setColorPalette(imageEditorView.getModel().getUniqueColorsIgnoringAlpha()); + } + + private final ImageEditorView.TapListener selectionListener = new ImageEditorView.TapListener() { + + @Override + public void onEntityDown(@Nullable EditorElement editorElement) { + if (editorElement != null) { + controller.onTouchEventsNeeded(true); + } else { + currentSelection = null; + controller.onTouchEventsNeeded(false); + imageEditorHud.enterMode(ImageEditorHud.Mode.NONE); + imageEditorView.doneTextEditing(); + } + } + + @Override + public void onEntitySingleTap(@Nullable EditorElement editorElement) { + currentSelection = editorElement; + if (currentSelection != null) { + if (editorElement.getRenderer() instanceof TextRenderer) { + setTextElement(editorElement, (ColorableRenderer) editorElement.getRenderer(), imageEditorView.isTextEditing()); + } else { + imageEditorHud.enterMode(ImageEditorHud.Mode.MOVE_DELETE); + } + } + } + + @Override + public void onEntityDoubleTap(@NonNull EditorElement editorElement) { + currentSelection = editorElement; + if (editorElement.getRenderer() instanceof TextRenderer) { + setTextElement(editorElement, (ColorableRenderer) editorElement.getRenderer(), true); + } + } + + private void setTextElement(@NonNull EditorElement editorElement, + @NonNull ColorableRenderer colorableRenderer, + boolean startEditing) + { + int color = colorableRenderer.getColor(); + imageEditorHud.enterMode(ImageEditorHud.Mode.TEXT); + imageEditorHud.setActiveColor(color); + if (startEditing) { + startTextEntityEditing(editorElement, false); + } + } + }; + + public interface Controller { + void onTouchEventsNeeded(boolean needed); + + void onRequestFullScreen(boolean fullScreen); + } +} diff --git a/src/org/thoughtcrime/securesms/scribbles/ImageEditorHud.java b/src/org/thoughtcrime/securesms/scribbles/ImageEditorHud.java new file mode 100644 index 000000000..7b36e82dd --- /dev/null +++ b/src/org/thoughtcrime/securesms/scribbles/ImageEditorHud.java @@ -0,0 +1,274 @@ +package org.thoughtcrime.securesms.scribbles; + +import android.content.Context; +import android.graphics.Color; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.scribbles.widget.ColorPaletteAdapter; +import org.thoughtcrime.securesms.scribbles.widget.VerticalSlideColorPicker; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * The HUD (heads-up display) that contains all of the tools for interacting with + * {@link org.thoughtcrime.securesms.imageeditor.ImageEditorView} + */ +public final class ImageEditorHud extends LinearLayout { + + private View cropButton; + private View cropFlipButton; + private View cropRotateButton; + private ImageView cropAspectLock; + private View drawButton; + private View highlightButton; + private View textButton; + private View stickerButton; + private View undoButton; + private View deleteButton; + private View confirmButton; + private VerticalSlideColorPicker colorPicker; + private RecyclerView colorPalette; + + @NonNull + private EventListener eventListener = NULL_EVENT_LISTENER; + @Nullable + private ColorPaletteAdapter colorPaletteAdapter; + + private final Map> visibilityModeMap = new HashMap<>(); + private final Set allViews = new HashSet<>(); + + public ImageEditorHud(@NonNull Context context) { + super(context); + initialize(); + } + + public ImageEditorHud(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + initialize(); + } + + public ImageEditorHud(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(); + } + + private void initialize() { + inflate(getContext(), R.layout.image_editor_hud, this); + setOrientation(VERTICAL); + + cropButton = findViewById(R.id.scribble_crop_button); + cropFlipButton = findViewById(R.id.scribble_crop_flip); + cropRotateButton = findViewById(R.id.scribble_crop_rotate); + cropAspectLock = findViewById(R.id.scribble_crop_aspect_lock); + colorPalette = findViewById(R.id.scribble_color_palette); + drawButton = findViewById(R.id.scribble_draw_button); + highlightButton = findViewById(R.id.scribble_highlight_button); + textButton = findViewById(R.id.scribble_text_button); + stickerButton = findViewById(R.id.scribble_sticker_button); + undoButton = findViewById(R.id.scribble_undo_button); + deleteButton = findViewById(R.id.scribble_delete_button); + confirmButton = findViewById(R.id.scribble_confirm_button); + colorPicker = findViewById(R.id.scribble_color_picker); + + cropAspectLock.setOnClickListener(v -> { + eventListener.onCropAspectLock(!eventListener.isCropAspectLocked()); + updateCropAspectLockImage(eventListener.isCropAspectLocked()); + }); + + initializeViews(); + initializeVisibilityMap(); + setMode(Mode.NONE); + } + + private void updateCropAspectLockImage(boolean cropAspectLocked) { + cropAspectLock.setImageDrawable(getResources().getDrawable(cropAspectLocked ? R.drawable.ic_crop_lock_32 : R.drawable.ic_crop_unlock_32)); + } + + private void initializeVisibilityMap() { + setVisibleViewsWhenInMode(Mode.NONE, drawButton, highlightButton, textButton, stickerButton, cropButton, undoButton); + + setVisibleViewsWhenInMode(Mode.DRAW, confirmButton, undoButton, colorPicker, colorPalette); + + setVisibleViewsWhenInMode(Mode.HIGHLIGHT, confirmButton, undoButton, colorPicker, colorPalette); + + setVisibleViewsWhenInMode(Mode.TEXT, confirmButton, deleteButton, colorPicker, colorPalette); + + setVisibleViewsWhenInMode(Mode.MOVE_DELETE, confirmButton, deleteButton); + + setVisibleViewsWhenInMode(Mode.CROP, confirmButton, cropFlipButton, cropRotateButton, cropAspectLock); + + for (Set views : visibilityModeMap.values()) { + allViews.addAll(views); + } + } + + private void setVisibleViewsWhenInMode(Mode mode, View... views) { + visibilityModeMap.put(mode, new HashSet<>(Arrays.asList(views))); + } + + private void initializeViews() { + undoButton.setOnClickListener(v -> eventListener.onUndo()); + + deleteButton.setOnClickListener(v -> { + eventListener.onDelete(); + setMode(Mode.NONE); + }); + + cropButton.setOnClickListener(v -> setMode(Mode.CROP)); + cropFlipButton.setOnClickListener(v -> eventListener.onFlipHorizontal()); + cropRotateButton.setOnClickListener(v -> eventListener.onRotate90AntiClockwise()); + + confirmButton.setOnClickListener(v -> setMode(Mode.NONE)); + + colorPaletteAdapter = new ColorPaletteAdapter(); + colorPaletteAdapter.setEventListener(colorPicker::setActiveColor); + + colorPalette.setLayoutManager(new LinearLayoutManager(getContext())); + colorPalette.setAdapter(colorPaletteAdapter); + + drawButton.setOnClickListener(v -> setMode(Mode.DRAW)); + highlightButton.setOnClickListener(v -> setMode(Mode.HIGHLIGHT)); + textButton.setOnClickListener(v -> setMode(Mode.TEXT)); + stickerButton.setOnClickListener(v -> setMode(Mode.MOVE_DELETE)); + } + + public void setColorPalette(@NonNull Set colors) { + if (colorPaletteAdapter != null) { + colorPaletteAdapter.setColors(colors); + } + } + + public int getActiveColor() { + return colorPicker.getActiveColor(); + } + + public void setActiveColor(int color) { + colorPicker.setActiveColor(color); + } + + public void setEventListener(@Nullable EventListener eventListener) { + this.eventListener = eventListener != null ? eventListener : NULL_EVENT_LISTENER; + } + + public void enterMode(@NonNull Mode mode) { + setMode(mode, false); + } + + private void setMode(@NonNull Mode mode) { + setMode(mode, true); + } + + private void setMode(@NonNull Mode mode, boolean notify) { + Set visibleButtons = visibilityModeMap.get(mode); + for (View button : allViews) { + button.setVisibility(visibleButtons != null && visibleButtons.contains(button) ? VISIBLE : GONE); + } + + switch (mode) { + case CROP: presentModeCrop(); break; + case DRAW: presentModeDraw(); break; + case HIGHLIGHT: presentModeHighlight(); break; + case TEXT: presentModeText(); break; + } + + if (notify) { + eventListener.onModeStarted(mode); + } + eventListener.onRequestFullScreen(mode != Mode.NONE); + } + + private void presentModeCrop() { + updateCropAspectLockImage(eventListener.isCropAspectLocked()); + } + + private void presentModeDraw() { + colorPicker.setOnColorChangeListener(standardOnColorChangeListener); + colorPicker.setActiveColor(Color.RED); + } + + private void presentModeHighlight() { + colorPicker.setOnColorChangeListener(highlightOnColorChangeListener); + colorPicker.setActiveColor(Color.YELLOW); + } + + private void presentModeText() { + colorPicker.setOnColorChangeListener(standardOnColorChangeListener); + colorPicker.setActiveColor(Color.WHITE); + } + + private final VerticalSlideColorPicker.OnColorChangeListener standardOnColorChangeListener = selectedColor -> eventListener.onColorChange(selectedColor); + + private final VerticalSlideColorPicker.OnColorChangeListener highlightOnColorChangeListener = selectedColor -> eventListener.onColorChange(replaceAlphaWith128(selectedColor)); + + private static int replaceAlphaWith128(int color) { + return color & ~0xff000000 | 0x80000000; + } + + public enum Mode { + NONE, DRAW, HIGHLIGHT, TEXT, MOVE_DELETE, CROP + } + + public interface EventListener { + void onModeStarted(@NonNull Mode mode); + void onColorChange(int color); + void onUndo(); + void onDelete(); + void onFlipHorizontal(); + void onRotate90AntiClockwise(); + void onCropAspectLock(boolean locked); + boolean isCropAspectLocked(); + void onRequestFullScreen(boolean fullScreen); + } + + private static final EventListener NULL_EVENT_LISTENER = new EventListener() { + + @Override + public void onModeStarted(@NonNull Mode mode) { + } + + @Override + public void onColorChange(int color) { + } + + @Override + public void onUndo() { + } + + @Override + public void onDelete() { + } + + @Override + public void onFlipHorizontal() { + } + + @Override + public void onRotate90AntiClockwise() { + } + + @Override + public void onCropAspectLock(boolean locked) { + } + + @Override + public boolean isCropAspectLocked() { + return false; + } + + @Override + public void onRequestFullScreen(boolean fullScreen) { + } + }; +} diff --git a/src/org/thoughtcrime/securesms/scribbles/ScribbleFragment.java b/src/org/thoughtcrime/securesms/scribbles/ScribbleFragment.java deleted file mode 100644 index f7dfa9e63..000000000 --- a/src/org/thoughtcrime/securesms/scribbles/ScribbleFragment.java +++ /dev/null @@ -1,318 +0,0 @@ -package org.thoughtcrime.securesms.scribbles; - -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.PointF; -import android.net.Uri; -import android.os.AsyncTask; -import android.os.Build; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.WindowManager; - -import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.TransportOption; -import org.thoughtcrime.securesms.logging.Log; -import org.thoughtcrime.securesms.mediasend.MediaSendPageFragment; -import org.thoughtcrime.securesms.mms.GlideApp; -import org.thoughtcrime.securesms.mms.GlideRequests; -import org.thoughtcrime.securesms.providers.BlobProvider; -import org.thoughtcrime.securesms.providers.DeprecatedPersistentBlobProvider; -import org.thoughtcrime.securesms.scribbles.viewmodel.Font; -import org.thoughtcrime.securesms.scribbles.viewmodel.Layer; -import org.thoughtcrime.securesms.scribbles.viewmodel.TextLayer; -import org.thoughtcrime.securesms.scribbles.widget.MotionView; -import org.thoughtcrime.securesms.scribbles.widget.ScribbleView; -import org.thoughtcrime.securesms.scribbles.widget.VerticalSlideColorPicker; -import org.thoughtcrime.securesms.scribbles.widget.entity.ImageEntity; -import org.thoughtcrime.securesms.scribbles.widget.entity.MotionEntity; -import org.thoughtcrime.securesms.scribbles.widget.entity.TextEntity; -import org.thoughtcrime.securesms.util.MediaUtil; -import org.thoughtcrime.securesms.util.Util; -import org.thoughtcrime.securesms.util.concurrent.SimpleTask; -import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; -import org.whispersystems.libsignal.util.guava.Optional; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.Locale; -import java.util.concurrent.ExecutionException; - -import static android.app.Activity.RESULT_OK; - -@TargetApi(Build.VERSION_CODES.JELLY_BEAN) -public class ScribbleFragment extends Fragment implements ScribbleHud.EventListener, - VerticalSlideColorPicker.OnColorChangeListener, - MediaSendPageFragment -{ - - private static final String TAG = ScribbleFragment.class.getSimpleName(); - - private static final String KEY_IMAGE_URI = "image_uri"; - - public static final int SELECT_STICKER_REQUEST_CODE = 123; - - private Controller controller; - private ScribbleHud scribbleHud; - private ScribbleView scribbleView; - private GlideRequests glideRequests; - private Uri imageUri; - - private ScribbleView.SavedState savedState; - - public static ScribbleFragment newInstance(@NonNull Uri imageUri) { - Bundle args = new Bundle(); - args.putParcelable(KEY_IMAGE_URI, imageUri); - - ScribbleFragment fragment = new ScribbleFragment(); - fragment.setArguments(args); - fragment.setUri(imageUri); - return fragment; - } - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (!(getActivity() instanceof Controller)) { - throw new IllegalStateException("Parent activity must implement Controller interface."); - } - controller = (Controller) getActivity(); - imageUri = getArguments().getParcelable(KEY_IMAGE_URI); - } - - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.scribble_fragment, container, false); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - this.glideRequests = GlideApp.with(this); - this.scribbleHud = view.findViewById(R.id.scribble_hud); - this.scribbleView = view.findViewById(R.id.scribble_view); - - scribbleHud.setEventListener(this); - - scribbleView.setMotionViewCallback(motionViewCallback); - scribbleView.setDrawingChangedListener(() -> scribbleHud.setColorPalette(scribbleView.getUniqueColors())); - scribbleView.setDrawingMode(false); - scribbleView.setImage(glideRequests, imageUri); - - if (savedState != null) { - scribbleView.restoreState(savedState); - } - } - - @Override - public void setUri(@NonNull Uri uri) { - this.imageUri = uri; - } - - @Override - public @NonNull Uri getUri() { - return imageUri; - } - - @Override - public @Nullable View getPlaybackControls() { - return null; - } - - @Override - public @Nullable Object saveState() { - return scribbleView.saveState(); - } - - @Override - public void restoreState(@NonNull Object state) { - if (state instanceof ScribbleView.SavedState) { - savedState = (ScribbleView.SavedState) state; - - if (scribbleView != null) { - scribbleView.restoreState(savedState); - } - } else { - Log.w(TAG, "Received a bad saved state. Received class: " + state.getClass().getName()); - } - } - - private void addSticker(final Bitmap pica) { - Util.runOnMain(() -> { - Layer layer = new Layer(); - ImageEntity entity = new ImageEntity(layer, pica, scribbleView.getWidth(), scribbleView.getHeight()); - - scribbleView.addEntityAndPosition(entity); - }); - } - - private void changeTextEntityColor(int selectedColor) { - TextEntity textEntity = currentTextEntity(); - - if (textEntity == null) { - return; - } - - textEntity.getLayer().getFont().setColor(selectedColor); - textEntity.updateEntity(); - scribbleView.invalidate(); - scribbleHud.setColorPalette(scribbleView.getUniqueColors()); - } - - private void startTextEntityEditing() { - TextEntity textEntity = currentTextEntity(); - if (textEntity != null) { - scribbleView.startEditing(textEntity); - } - } - - @Nullable - private TextEntity currentTextEntity() { - if (scribbleView != null && scribbleView.getSelectedEntity() instanceof TextEntity) { - return ((TextEntity) scribbleView.getSelectedEntity()); - } else { - return null; - } - } - - protected void addTextSticker() { - TextLayer textLayer = createTextLayer(); - TextEntity textEntity = new TextEntity(textLayer, scribbleView.getWidth(), scribbleView.getHeight()); - scribbleView.addEntityAndPosition(textEntity); - - PointF center = textEntity.absoluteCenter(); - center.y = center.y * 0.5F; - textEntity.moveCenterTo(center); - - scribbleView.invalidate(); - - startTextEntityEditing(); - changeTextEntityColor(scribbleHud.getActiveColor()); - } - - private TextLayer createTextLayer() { - TextLayer textLayer = new TextLayer(); - Font font = new Font(); - - font.setColor(scribbleHud.getActiveColor()); - font.setSize(TextLayer.Limits.INITIAL_FONT_SIZE); - - textLayer.setFont(font); - - return textLayer; - } - - @SuppressLint("StaticFieldLeak") - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == RESULT_OK && requestCode == SELECT_STICKER_REQUEST_CODE && data != null) { - final String stickerFile = data.getStringExtra(StickerSelectActivity.EXTRA_STICKER_FILE); - - SimpleTask.run(getLifecycle(), () -> { - try { - return BitmapFactory.decodeStream(getContext().getAssets().open(stickerFile)); - } catch (IOException e) { - Log.w(TAG, e); - return null; - } - }, bitmap -> { - if (bitmap != null) { - addSticker(bitmap); - } - }); - } - } - - @Override - public void onModeStarted(@NonNull ScribbleHud.Mode mode) { - switch (mode) { - case DRAW: - controller.onTouchEventsNeeded(true); - scribbleView.setDrawingMode(true); - scribbleView.setDrawingBrushWidth(ScribbleView.DEFAULT_BRUSH_WIDTH); - break; - - case HIGHLIGHT: - controller.onTouchEventsNeeded(true); - scribbleView.setDrawingMode(true); - scribbleView.setDrawingBrushWidth(ScribbleView.DEFAULT_BRUSH_WIDTH * 3); - break; - - case TEXT: - controller.onTouchEventsNeeded(true); - scribbleView.setDrawingMode(false); - addTextSticker(); - break; - - case STICKER: - controller.onTouchEventsNeeded(true); - scribbleView.setDrawingMode(false); - Intent intent = new Intent(getContext(), StickerSelectActivity.class); - startActivityForResult(intent, SELECT_STICKER_REQUEST_CODE); - break; - - case NONE: - controller.onTouchEventsNeeded(false); - scribbleView.clearSelection(); - scribbleView.setDrawingMode(false); - break; - } - } - - @Override - public void onColorChange(int color) { - scribbleView.setDrawingBrushColor(color); - changeTextEntityColor(color); - } - - @Override - public void onUndo() { - scribbleView.undoDrawing(); - scribbleHud.setColorPalette(scribbleView.getUniqueColors()); - } - - @Override - public void onDelete() { - scribbleView.deleteSelected(); - scribbleHud.setColorPalette(scribbleView.getUniqueColors()); - } - - private final MotionView.MotionViewCallback motionViewCallback = new MotionView.MotionViewCallback() { - @Override - public void onEntitySelected(@Nullable MotionEntity entity) { - if (entity == null) { - scribbleHud.enterMode(ScribbleHud.Mode.NONE); - controller.onTouchEventsNeeded(false); - } else if (entity instanceof TextEntity) { - int textColor = ((TextEntity) entity).getLayer().getFont().getColor(); - - scribbleHud.enterMode(ScribbleHud.Mode.TEXT); - scribbleHud.setActiveColor(textColor); - controller.onTouchEventsNeeded(true); - } else { - scribbleHud.enterMode(ScribbleHud.Mode.STICKER); - controller.onTouchEventsNeeded(true); - } - } - - @Override - public void onEntityDoubleTap(@NonNull MotionEntity entity) { - startTextEntityEditing(); - } - }; - - public interface Controller { - void onTouchEventsNeeded(boolean needed); - } -} diff --git a/src/org/thoughtcrime/securesms/scribbles/ScribbleHud.java b/src/org/thoughtcrime/securesms/scribbles/ScribbleHud.java deleted file mode 100644 index 64e4f17d2..000000000 --- a/src/org/thoughtcrime/securesms/scribbles/ScribbleHud.java +++ /dev/null @@ -1,264 +0,0 @@ -package org.thoughtcrime.securesms.scribbles; - -import android.content.Context; -import android.graphics.Color; -import android.graphics.PorterDuff; -import android.graphics.Rect; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.text.Editable; -import android.text.TextWatcher; -import android.util.AttributeSet; -import android.view.KeyEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.widget.LinearLayout; -import android.widget.TextView; - -import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.TransportOption; -import org.thoughtcrime.securesms.components.ComposeText; -import org.thoughtcrime.securesms.components.InputAwareLayout; -import org.thoughtcrime.securesms.components.SendButton; -import org.thoughtcrime.securesms.components.emoji.EmojiDrawer; -import org.thoughtcrime.securesms.components.emoji.EmojiToggle; -import org.thoughtcrime.securesms.scribbles.widget.ColorPaletteAdapter; -import org.thoughtcrime.securesms.scribbles.widget.VerticalSlideColorPicker; -import org.thoughtcrime.securesms.util.CharacterCalculator.CharacterState; -import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.thoughtcrime.securesms.util.views.Stub; -import org.whispersystems.libsignal.util.guava.Optional; - -import java.util.Locale; -import java.util.Set; - -/** - * The HUD (heads-up display) that contains all of the tools for interacting with - * {@link org.thoughtcrime.securesms.scribbles.widget.ScribbleView} - */ -public class ScribbleHud extends LinearLayout { - - private View drawButton; - private View highlightButton; - private View textButton; - private View stickerButton; - private View undoButton; - private View deleteButton; - private View confirmButton; - private VerticalSlideColorPicker colorPicker; - private RecyclerView colorPalette; - - private EventListener eventListener; - private ColorPaletteAdapter colorPaletteAdapter; - - public ScribbleHud(@NonNull Context context) { - super(context); - initialize(); - } - - public ScribbleHud(@NonNull Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - initialize(); - } - - public ScribbleHud(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - initialize(); - } - - private void initialize() { - inflate(getContext(), R.layout.scribble_hud, this); - setOrientation(VERTICAL); - - drawButton = findViewById(R.id.scribble_draw_button); - highlightButton = findViewById(R.id.scribble_highlight_button); - textButton = findViewById(R.id.scribble_text_button); - stickerButton = findViewById(R.id.scribble_sticker_button); - undoButton = findViewById(R.id.scribble_undo_button); - deleteButton = findViewById(R.id.scribble_delete_button); - confirmButton = findViewById(R.id.scribble_confirm_button); - colorPicker = findViewById(R.id.scribble_color_picker); - colorPalette = findViewById(R.id.scribble_color_palette); - - initializeViews(); - setMode(Mode.NONE); - } - - private void initializeViews() { - undoButton.setOnClickListener(v -> { - if (eventListener != null) { - eventListener.onUndo(); - } - }); - - deleteButton.setOnClickListener(v -> { - if (eventListener != null) { - eventListener.onDelete(); - } - setMode(Mode.NONE); - }); - - confirmButton.setOnClickListener(v -> setMode(Mode.NONE)); - - colorPaletteAdapter = new ColorPaletteAdapter(); - colorPaletteAdapter.setEventListener(colorPicker::setActiveColor); - - colorPalette.setLayoutManager(new LinearLayoutManager(getContext())); - colorPalette.setAdapter(colorPaletteAdapter); - } - - public void setColorPalette(@NonNull Set colors) { - colorPaletteAdapter.setColors(colors); - } - - public int getActiveColor() { - return colorPicker.getActiveColor(); - } - - public void setActiveColor(int color) { - colorPicker.setActiveColor(color); - } - - public void setEventListener(@Nullable EventListener eventListener) { - this.eventListener = eventListener; - } - - public void enterMode(@NonNull Mode mode) { - setMode(mode, false); - } - - private void setMode(@NonNull Mode mode) { - setMode(mode, true); - } - - private void setMode(@NonNull Mode mode, boolean notify) { - switch (mode) { - case NONE: presentModeNone(); break; - case DRAW: presentModeDraw(); break; - case HIGHLIGHT: presentModeHighlight(); break; - case TEXT: presentModeText(); break; - case STICKER: presentModeSticker(); break; - } - - if (notify && eventListener != null) { - eventListener.onModeStarted(mode); - } - } - - private void presentModeNone() { - drawButton.setVisibility(VISIBLE); - highlightButton.setVisibility(VISIBLE); - textButton.setVisibility(VISIBLE); - stickerButton.setVisibility(VISIBLE); - - undoButton.setVisibility(GONE); - deleteButton.setVisibility(GONE); - confirmButton.setVisibility(GONE); - colorPicker.setVisibility(GONE); - colorPalette.setVisibility(GONE); - - drawButton.setOnClickListener(v -> setMode(Mode.DRAW)); - highlightButton.setOnClickListener(v -> setMode(Mode.HIGHLIGHT)); - textButton.setOnClickListener(v -> setMode(Mode.TEXT)); - stickerButton.setOnClickListener(v -> setMode(Mode.STICKER)); - } - - private void presentModeDraw() { - confirmButton.setVisibility(VISIBLE); - undoButton.setVisibility(VISIBLE); - colorPicker.setVisibility(VISIBLE); - colorPalette.setVisibility(VISIBLE); - - drawButton.setVisibility(GONE); - highlightButton.setVisibility(GONE); - textButton.setVisibility(GONE); - stickerButton.setVisibility(GONE); - deleteButton.setVisibility(GONE); - - - colorPicker.setOnColorChangeListener(standardOnColorChangeListener); - colorPicker.setActiveColor(Color.RED); - } - - private void presentModeHighlight() { - confirmButton.setVisibility(VISIBLE); - undoButton.setVisibility(VISIBLE); - colorPicker.setVisibility(VISIBLE); - colorPalette.setVisibility(VISIBLE); - - drawButton.setVisibility(GONE); - highlightButton.setVisibility(GONE); - textButton.setVisibility(GONE); - deleteButton.setVisibility(GONE); - stickerButton.setVisibility(GONE); - - colorPicker.setOnColorChangeListener(highlightOnColorChangeListener); - colorPicker.setActiveColor(Color.YELLOW); - } - - private void presentModeText() { - confirmButton.setVisibility(VISIBLE); - deleteButton.setVisibility(VISIBLE); - colorPicker.setVisibility(VISIBLE); - colorPalette.setVisibility(VISIBLE); - - textButton.setVisibility(GONE); - drawButton.setVisibility(GONE); - highlightButton.setVisibility(GONE); - stickerButton.setVisibility(GONE); - undoButton.setVisibility(GONE); - - colorPicker.setOnColorChangeListener(standardOnColorChangeListener); - colorPicker.setActiveColor(Color.WHITE); - } - - private void presentModeSticker() { - deleteButton.setVisibility(VISIBLE); - confirmButton.setVisibility(VISIBLE); - - drawButton.setVisibility(GONE); - highlightButton.setVisibility(GONE); - textButton.setVisibility(GONE); - stickerButton.setVisibility(GONE); - undoButton.setVisibility(GONE); - colorPicker.setVisibility(GONE); - colorPalette.setVisibility(GONE); - } - - private final VerticalSlideColorPicker.OnColorChangeListener standardOnColorChangeListener = new VerticalSlideColorPicker.OnColorChangeListener() { - @Override - public void onColorChange(int selectedColor) { - if (eventListener != null) { - eventListener.onColorChange(selectedColor); - } - } - }; - - private final VerticalSlideColorPicker.OnColorChangeListener highlightOnColorChangeListener = new VerticalSlideColorPicker.OnColorChangeListener() { - @Override - public void onColorChange(int selectedColor) { - if (eventListener != null) { - int r = Color.red(selectedColor); - int g = Color.green(selectedColor); - int b = Color.blue(selectedColor); - int a = 128; - - eventListener.onColorChange(Color.argb(a, r, g, b)); - } - } - }; - - public enum Mode { - NONE, DRAW, HIGHLIGHT, TEXT, STICKER - } - - public interface EventListener { - void onModeStarted(@NonNull Mode mode); - void onColorChange(int color); - void onUndo(); - void onDelete(); - } -} diff --git a/src/org/thoughtcrime/securesms/scribbles/UriGlideRenderer.java b/src/org/thoughtcrime/securesms/scribbles/UriGlideRenderer.java new file mode 100644 index 000000000..01a897986 --- /dev/null +++ b/src/org/thoughtcrime/securesms/scribbles/UriGlideRenderer.java @@ -0,0 +1,186 @@ +package org.thoughtcrime.securesms.scribbles; + +import android.content.Context; +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.support.annotation.NonNull; +import android.support.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.thoughtcrime.securesms.imageeditor.Bounds; +import org.thoughtcrime.securesms.imageeditor.Renderer; +import org.thoughtcrime.securesms.imageeditor.RendererContext; +import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader; +import org.thoughtcrime.securesms.mms.GlideApp; +import org.thoughtcrime.securesms.mms.GlideRequest; + +import java.util.concurrent.ExecutionException; + +/** + * Uses Glide to load an image and implements a {@link Renderer}. + * + * The image can be encrypted. + */ +final class UriGlideRenderer implements Renderer { + + private final Uri imageUri; + private final Paint paint = new Paint(); + private final Matrix imageProjectionMatrix = new Matrix(); + private final Matrix temp = new Matrix(); + private final boolean decryptable; + private final int maxWidth; + private final int maxHeight; + + @Nullable + private Bitmap bitmap; + + UriGlideRenderer(@NonNull Uri imageUri, boolean decryptable, int maxWidth, int maxHeight) { + this.imageUri = imageUri; + this.decryptable = decryptable; + this.maxWidth = maxWidth; + this.maxHeight = maxHeight; + paint.setAntiAlias(true); + } + + @Override + public void render(@NonNull RendererContext rendererContext) { + if (getBitmap() == null) { + if (rendererContext.isBlockingLoad()) { + try { + Bitmap bitmap = getBitmapGlideRequest(rendererContext.context).submit().get(); + setBitmap(rendererContext, bitmap); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } else { + getBitmapGlideRequest(rendererContext.context).into(new SimpleTarget() { + @Override + public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition transition) { + setBitmap(rendererContext, resource); + } + }); + } + } + + final Bitmap bitmap = getBitmap(); + if (bitmap != null) { + rendererContext.save(); + + rendererContext.canvasMatrix.concat(imageProjectionMatrix); + + // Units are image level pixels at this point. + + int alpha = paint.getAlpha(); + paint.setAlpha(rendererContext.getAlpha(alpha)); + + rendererContext.canvas.drawBitmap(bitmap, 0, 0, paint); + + paint.setAlpha(alpha); + + rendererContext.restore(); + } else { + // If failed to load, we draw a black out, in case image was sticker positioned to cover private info. + rendererContext.canvas.drawRect(Bounds.FULL_BOUNDS, paint); + } + } + + private GlideRequest getBitmapGlideRequest(@NonNull Context context) { + return GlideApp.with(context) + .asBitmap() + .diskCacheStrategy(DiskCacheStrategy.NONE) + .override(maxWidth, maxHeight) + .centerInside() + .load(decryptable ? new DecryptableStreamUriLoader.DecryptableUri(imageUri) : imageUri); + } + + @Override + public boolean hitTest(float x, float y) { + return pixelAlphaNotZero(x, y); + } + + private boolean pixelAlphaNotZero(float x, float y) { + Bitmap bitmap = getBitmap(); + + if (bitmap == null) return false; + + imageProjectionMatrix.invert(temp); + + float[] onBmp = new float[2]; + temp.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; + } + } + + @Nullable + private Bitmap getBitmap() { + if (bitmap != null && bitmap.isRecycled()) { + bitmap = null; + } + return bitmap; + } + + 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()); + imageProjectionMatrix.setRectToRect(from, Bounds.FULL_BOUNDS, Matrix.ScaleToFit.CENTER); + rendererContext.rendererReady.onReady(UriGlideRenderer.this, cropMatrix(bitmap), new Point(bitmap.getWidth(), bitmap.getHeight())); + } + } + + 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 CREATOR = new Creator() { + @Override + public UriGlideRenderer createFromParcel(Parcel in) { + return new UriGlideRenderer(Uri.parse(in.readString()), + in.readInt() == 1, + in.readInt(), + in.readInt() + ); + } + + @Override + public UriGlideRenderer[] newArray(int size) { + return new UriGlideRenderer[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(imageUri.toString()); + dest.writeInt(decryptable ? 1 : 0); + dest.writeInt(maxWidth); + dest.writeInt(maxHeight); + } +} diff --git a/src/org/thoughtcrime/securesms/scribbles/multitouch/BaseGestureDetector.java b/src/org/thoughtcrime/securesms/scribbles/multitouch/BaseGestureDetector.java deleted file mode 100644 index 0d3930b00..000000000 --- a/src/org/thoughtcrime/securesms/scribbles/multitouch/BaseGestureDetector.java +++ /dev/null @@ -1,149 +0,0 @@ -package org.thoughtcrime.securesms.scribbles.multitouch; - -import android.content.Context; -import android.view.MotionEvent; - -/** - * @author Almer Thie (code.almeros.com) - * Copyright (c) 2013, Almer Thie (code.almeros.com) - *

- * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - *

- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - */ -public abstract class BaseGestureDetector { - /** - * This value is the threshold ratio between the previous combined pressure - * and the current combined pressure. When pressure decreases rapidly - * between events the position values can often be imprecise, as it usually - * indicates that the user is in the process of lifting a pointer off of the - * device. This value was tuned experimentally. - */ - protected static final float PRESSURE_THRESHOLD = 0.67f; - protected final Context mContext; - protected boolean mGestureInProgress; - protected MotionEvent mPrevEvent; - protected MotionEvent mCurrEvent; - protected float mCurrPressure; - protected float mPrevPressure; - protected long mTimeDelta; - - - public BaseGestureDetector(Context context) { - mContext = context; - } - - /** - * All gesture detectors need to be called through this method to be able to - * detect gestures. This method delegates work to handler methods - * (handleStartProgressEvent, handleInProgressEvent) implemented in - * extending classes. - * - * @param event - * @return - */ - public boolean onTouchEvent(MotionEvent event) { - final int actionCode = event.getAction() & MotionEvent.ACTION_MASK; - if (!mGestureInProgress) { - handleStartProgressEvent(actionCode, event); - } else { - handleInProgressEvent(actionCode, event); - } - return true; - } - - /** - * Called when the current event occurred when NO gesture is in progress - * yet. The handling in this implementation may set the gesture in progress - * (via mGestureInProgress) or out of progress - * - * @param actionCode - * @param event - */ - protected abstract void handleStartProgressEvent(int actionCode, MotionEvent event); - - /** - * Called when the current event occurred when a gesture IS in progress. The - * handling in this implementation may set the gesture out of progress (via - * mGestureInProgress). - * - * @param actionCode - * @param event - */ - protected abstract void handleInProgressEvent(int actionCode, MotionEvent event); - - - protected void updateStateByEvent(MotionEvent curr) { - final MotionEvent prev = mPrevEvent; - - // Reset mCurrEvent - if (mCurrEvent != null) { - mCurrEvent.recycle(); - mCurrEvent = null; - } - mCurrEvent = MotionEvent.obtain(curr); - - - // Delta time - mTimeDelta = curr.getEventTime() - prev.getEventTime(); - - // Pressure - mCurrPressure = curr.getPressure(curr.getActionIndex()); - mPrevPressure = prev.getPressure(prev.getActionIndex()); - } - - protected void resetState() { - if (mPrevEvent != null) { - mPrevEvent.recycle(); - mPrevEvent = null; - } - if (mCurrEvent != null) { - mCurrEvent.recycle(); - mCurrEvent = null; - } - mGestureInProgress = false; - } - - - /** - * Returns {@code true} if a gesture is currently in progress. - * - * @return {@code true} if a gesture is currently in progress, {@code false} otherwise. - */ - public boolean isInProgress() { - return mGestureInProgress; - } - - /** - * Return the time difference in milliseconds between the previous accepted - * GestureDetector event and the current GestureDetector event. - * - * @return Time difference since the last move event in milliseconds. - */ - public long getTimeDelta() { - return mTimeDelta; - } - - /** - * Return the event time of the current GestureDetector event being - * processed. - * - * @return Current GestureDetector event time in milliseconds. - */ - public long getEventTime() { - return mCurrEvent.getEventTime(); - } - -} diff --git a/src/org/thoughtcrime/securesms/scribbles/multitouch/MoveGestureDetector.java b/src/org/thoughtcrime/securesms/scribbles/multitouch/MoveGestureDetector.java deleted file mode 100644 index f623a202a..000000000 --- a/src/org/thoughtcrime/securesms/scribbles/multitouch/MoveGestureDetector.java +++ /dev/null @@ -1,170 +0,0 @@ -package org.thoughtcrime.securesms.scribbles.multitouch; - -import android.content.Context; -import android.graphics.PointF; -import android.view.MotionEvent; - -/** - * @author Almer Thie (code.almeros.com) - * Copyright (c) 2013, Almer Thie (code.almeros.com) - *

- * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - *

- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - */ -public class MoveGestureDetector extends BaseGestureDetector { - - private static final PointF FOCUS_DELTA_ZERO = new PointF(); - private final OnMoveGestureListener mListener; - private PointF mCurrFocusInternal; - private PointF mPrevFocusInternal; - private PointF mFocusExternal = new PointF(); - private PointF mFocusDeltaExternal = new PointF(); - public MoveGestureDetector(Context context, OnMoveGestureListener listener) { - super(context); - mListener = listener; - } - - @Override - protected void handleStartProgressEvent(int actionCode, MotionEvent event) { - switch (actionCode) { - case MotionEvent.ACTION_DOWN: - resetState(); // In case we missed an UP/CANCEL event - - mPrevEvent = MotionEvent.obtain(event); - mTimeDelta = 0; - - updateStateByEvent(event); - break; - - case MotionEvent.ACTION_MOVE: - mGestureInProgress = mListener.onMoveBegin(this); - break; - } - } - - @Override - protected void handleInProgressEvent(int actionCode, MotionEvent event) { - switch (actionCode) { - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - mListener.onMoveEnd(this); - resetState(); - break; - - case MotionEvent.ACTION_MOVE: - updateStateByEvent(event); - - // Only accept the event if our relative pressure is within - // a certain limit. This can help filter shaky data as a - // finger is lifted. - if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD) { - final boolean updatePrevious = mListener.onMove(this); - if (updatePrevious) { - mPrevEvent.recycle(); - mPrevEvent = MotionEvent.obtain(event); - } - } - break; - } - } - - protected void updateStateByEvent(MotionEvent curr) { - super.updateStateByEvent(curr); - - final MotionEvent prev = mPrevEvent; - - // Focus intenal - mCurrFocusInternal = determineFocalPoint(curr); - mPrevFocusInternal = determineFocalPoint(prev); - - // Focus external - // - Prevent skipping of focus delta when a finger is added or removed - boolean mSkipNextMoveEvent = prev.getPointerCount() != curr.getPointerCount(); - mFocusDeltaExternal = mSkipNextMoveEvent ? FOCUS_DELTA_ZERO : new PointF(mCurrFocusInternal.x - mPrevFocusInternal.x, mCurrFocusInternal.y - mPrevFocusInternal.y); - - // - Don't directly use mFocusInternal (or skipping will occur). Add - // unskipped delta values to mFocusExternal instead. - mFocusExternal.x += mFocusDeltaExternal.x; - mFocusExternal.y += mFocusDeltaExternal.y; - } - - /** - * Determine (multi)finger focal point (a.k.a. center point between all - * fingers) - * - * @return PointF focal point - */ - private PointF determineFocalPoint(MotionEvent e) { - // Number of fingers on screen - final int pCount = e.getPointerCount(); - float x = 0f; - float y = 0f; - - for (int i = 0; i < pCount; i++) { - x += e.getX(i); - y += e.getY(i); - } - - return new PointF(x / pCount, y / pCount); - } - - public float getFocusX() { - return mFocusExternal.x; - } - - public float getFocusY() { - return mFocusExternal.y; - } - - public PointF getFocusDelta() { - return mFocusDeltaExternal; - } - - /** - * Listener which must be implemented which is used by MoveGestureDetector - * to perform callbacks to any implementing class which is registered to a - * MoveGestureDetector via the constructor. - * - * @see MoveGestureDetector.SimpleOnMoveGestureListener - */ - public interface OnMoveGestureListener { - public boolean onMove(MoveGestureDetector detector); - - public boolean onMoveBegin(MoveGestureDetector detector); - - public void onMoveEnd(MoveGestureDetector detector); - } - - /** - * Helper class which may be extended and where the methods may be - * implemented. This way it is not necessary to implement all methods - * of OnMoveGestureListener. - */ - public static class SimpleOnMoveGestureListener implements OnMoveGestureListener { - public boolean onMove(MoveGestureDetector detector) { - return false; - } - - public boolean onMoveBegin(MoveGestureDetector detector) { - return true; - } - - public void onMoveEnd(MoveGestureDetector detector) { - // Do nothing, overridden implementation may be used - } - } - -} diff --git a/src/org/thoughtcrime/securesms/scribbles/multitouch/RotateGestureDetector.java b/src/org/thoughtcrime/securesms/scribbles/multitouch/RotateGestureDetector.java deleted file mode 100644 index 2032af2e5..000000000 --- a/src/org/thoughtcrime/securesms/scribbles/multitouch/RotateGestureDetector.java +++ /dev/null @@ -1,170 +0,0 @@ -package org.thoughtcrime.securesms.scribbles.multitouch; - -import android.content.Context; -import android.view.MotionEvent; - -/** - * @author Almer Thie (code.almeros.com) - * Copyright (c) 2013, Almer Thie (code.almeros.com) - *

- * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - *

- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - */ -public class RotateGestureDetector extends TwoFingerGestureDetector { - - private static final String TAG = RotateGestureDetector.class.getSimpleName(); - private final OnRotateGestureListener mListener; - private boolean mSloppyGesture; - - - public RotateGestureDetector(Context context, OnRotateGestureListener listener) { - super(context); - mListener = listener; - } - - @Override - protected void handleStartProgressEvent(int actionCode, MotionEvent event) { - switch (actionCode) { - case MotionEvent.ACTION_POINTER_DOWN: - // At least the second finger is on screen now - - resetState(); // In case we missed an UP/CANCEL event - mPrevEvent = MotionEvent.obtain(event); - mTimeDelta = 0; - - updateStateByEvent(event); - - // See if we have a sloppy gesture - mSloppyGesture = isSloppyGesture(event); - if (!mSloppyGesture) { - // No, start gesture now - mGestureInProgress = mListener.onRotateBegin(this); - } - break; - - case MotionEvent.ACTION_MOVE: - if (!mSloppyGesture) { - break; - } - - // See if we still have a sloppy gesture - mSloppyGesture = isSloppyGesture(event); - if (!mSloppyGesture) { - // No, start normal gesture now - mGestureInProgress = mListener.onRotateBegin(this); - } - - break; - - case MotionEvent.ACTION_POINTER_UP: - if (!mSloppyGesture) { - break; - } - - break; - } - } - - @Override - protected void handleInProgressEvent(int actionCode, MotionEvent event) { - switch (actionCode) { - case MotionEvent.ACTION_POINTER_UP: - // Gesture ended but - updateStateByEvent(event); - - if (!mSloppyGesture) { - mListener.onRotateEnd(this); - } - - resetState(); - break; - - case MotionEvent.ACTION_CANCEL: - if (!mSloppyGesture) { - mListener.onRotateEnd(this); - } - - resetState(); - break; - - case MotionEvent.ACTION_MOVE: - updateStateByEvent(event); - - // Only accept the event if our relative pressure is within - // a certain limit. This can help filter shaky data as a - // finger is lifted. - if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD) { - final boolean updatePrevious = mListener.onRotate(this); - if (updatePrevious) { - mPrevEvent.recycle(); - mPrevEvent = MotionEvent.obtain(event); - } - } - break; - } - } - - @Override - protected void resetState() { - super.resetState(); - mSloppyGesture = false; - } - - /** - * Return the rotation difference from the previous rotate event to the current - * event. - * - * @return The current rotation //difference in degrees. - */ - public float getRotationDegreesDelta() { - double diffRadians = Math.atan2(mPrevFingerDiffY, mPrevFingerDiffX) - Math.atan2(mCurrFingerDiffY, mCurrFingerDiffX); - return (float) (diffRadians * 180 / Math.PI); - } - - /** - * Listener which must be implemented which is used by RotateGestureDetector - * to perform callbacks to any implementing class which is registered to a - * RotateGestureDetector via the constructor. - * - * @see RotateGestureDetector.SimpleOnRotateGestureListener - */ - public interface OnRotateGestureListener { - public boolean onRotate(RotateGestureDetector detector); - - public boolean onRotateBegin(RotateGestureDetector detector); - - public void onRotateEnd(RotateGestureDetector detector); - } - - /** - * Helper class which may be extended and where the methods may be - * implemented. This way it is not necessary to implement all methods - * of OnRotateGestureListener. - */ - public static class SimpleOnRotateGestureListener implements OnRotateGestureListener { - public boolean onRotate(RotateGestureDetector detector) { - return false; - } - - public boolean onRotateBegin(RotateGestureDetector detector) { - return true; - } - - public void onRotateEnd(RotateGestureDetector detector) { - // Do nothing, overridden implementation may be used - } - } -} diff --git a/src/org/thoughtcrime/securesms/scribbles/multitouch/ShoveGestureDetector.java b/src/org/thoughtcrime/securesms/scribbles/multitouch/ShoveGestureDetector.java deleted file mode 100644 index cb4eb339e..000000000 --- a/src/org/thoughtcrime/securesms/scribbles/multitouch/ShoveGestureDetector.java +++ /dev/null @@ -1,201 +0,0 @@ -package org.thoughtcrime.securesms.scribbles.multitouch; - -import android.content.Context; -import android.view.MotionEvent; - -/** - * @author Robert Nordan (robert.nordan@norkart.no) - *

- * Copyright (c) 2013, Norkart AS - *

- * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - *

- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - */ -public class ShoveGestureDetector extends TwoFingerGestureDetector { - - private final OnShoveGestureListener mListener; - private float mPrevAverageY; - private float mCurrAverageY; - private boolean mSloppyGesture; - - public ShoveGestureDetector(Context context, OnShoveGestureListener listener) { - super(context); - mListener = listener; - } - - @Override - protected void handleStartProgressEvent(int actionCode, MotionEvent event) { - switch (actionCode) { - case MotionEvent.ACTION_POINTER_DOWN: - // At least the second finger is on screen now - - resetState(); // In case we missed an UP/CANCEL event - mPrevEvent = MotionEvent.obtain(event); - mTimeDelta = 0; - - updateStateByEvent(event); - - // See if we have a sloppy gesture - mSloppyGesture = isSloppyGesture(event); - if (!mSloppyGesture) { - // No, start gesture now - mGestureInProgress = mListener.onShoveBegin(this); - } - break; - - case MotionEvent.ACTION_MOVE: - if (!mSloppyGesture) { - break; - } - - // See if we still have a sloppy gesture - mSloppyGesture = isSloppyGesture(event); - if (!mSloppyGesture) { - // No, start normal gesture now - mGestureInProgress = mListener.onShoveBegin(this); - } - - break; - - case MotionEvent.ACTION_POINTER_UP: - if (!mSloppyGesture) { - break; - } - - break; - } - } - - @Override - protected void handleInProgressEvent(int actionCode, MotionEvent event) { - switch (actionCode) { - case MotionEvent.ACTION_POINTER_UP: - // Gesture ended but - updateStateByEvent(event); - - if (!mSloppyGesture) { - mListener.onShoveEnd(this); - } - - resetState(); - break; - - case MotionEvent.ACTION_CANCEL: - if (!mSloppyGesture) { - mListener.onShoveEnd(this); - } - - resetState(); - break; - - case MotionEvent.ACTION_MOVE: - updateStateByEvent(event); - - // Only accept the event if our relative pressure is within - // a certain limit. This can help filter shaky data as a - // finger is lifted. Also check that shove is meaningful. - if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD - && Math.abs(getShovePixelsDelta()) > 0.5f) { - final boolean updatePrevious = mListener.onShove(this); - if (updatePrevious) { - mPrevEvent.recycle(); - mPrevEvent = MotionEvent.obtain(event); - } - } - break; - } - } - - @Override - protected void updateStateByEvent(MotionEvent curr) { - super.updateStateByEvent(curr); - - final MotionEvent prev = mPrevEvent; - float py0 = prev.getY(0); - float py1 = prev.getY(1); - mPrevAverageY = (py0 + py1) / 2.0f; - - float cy0 = curr.getY(0); - float cy1 = curr.getY(1); - mCurrAverageY = (cy0 + cy1) / 2.0f; - } - - @Override - protected boolean isSloppyGesture(MotionEvent event) { - boolean sloppy = super.isSloppyGesture(event); - if (sloppy) - return true; - - // If it's not traditionally sloppy, we check if the angle between fingers - // is acceptable. - double angle = Math.abs(Math.atan2(mCurrFingerDiffY, mCurrFingerDiffX)); - //about 20 degrees, left or right - return !((0.0f < angle && angle < 0.35f) - || 2.79f < angle && angle < Math.PI); - } - - /** - * Return the distance in pixels from the previous shove event to the current - * event. - * - * @return The current distance in pixels. - */ - public float getShovePixelsDelta() { - return mCurrAverageY - mPrevAverageY; - } - - @Override - protected void resetState() { - super.resetState(); - mSloppyGesture = false; - mPrevAverageY = 0.0f; - mCurrAverageY = 0.0f; - } - - /** - * Listener which must be implemented which is used by ShoveGestureDetector - * to perform callbacks to any implementing class which is registered to a - * ShoveGestureDetector via the constructor. - * - * @see ShoveGestureDetector.SimpleOnShoveGestureListener - */ - public interface OnShoveGestureListener { - public boolean onShove(ShoveGestureDetector detector); - - public boolean onShoveBegin(ShoveGestureDetector detector); - - public void onShoveEnd(ShoveGestureDetector detector); - } - - /** - * Helper class which may be extended and where the methods may be - * implemented. This way it is not necessary to implement all methods - * of OnShoveGestureListener. - */ - public static class SimpleOnShoveGestureListener implements OnShoveGestureListener { - public boolean onShove(ShoveGestureDetector detector) { - return false; - } - - public boolean onShoveBegin(ShoveGestureDetector detector) { - return true; - } - - public void onShoveEnd(ShoveGestureDetector detector) { - // Do nothing, overridden implementation may be used - } - } -} diff --git a/src/org/thoughtcrime/securesms/scribbles/multitouch/TwoFingerGestureDetector.java b/src/org/thoughtcrime/securesms/scribbles/multitouch/TwoFingerGestureDetector.java deleted file mode 100644 index 5ae6cd635..000000000 --- a/src/org/thoughtcrime/securesms/scribbles/multitouch/TwoFingerGestureDetector.java +++ /dev/null @@ -1,189 +0,0 @@ -package org.thoughtcrime.securesms.scribbles.multitouch; - -import android.content.Context; -import android.util.DisplayMetrics; -import android.view.MotionEvent; -import android.view.ViewConfiguration; - -import org.thoughtcrime.securesms.logging.Log; - -/** - * @author Almer Thie (code.almeros.com) - * Copyright (c) 2013, Almer Thie (code.almeros.com) - *

- * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - *

- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - */ -public abstract class TwoFingerGestureDetector extends BaseGestureDetector { - - private static final String TAG = TwoFingerGestureDetector.class.getSimpleName(); - - private final float mEdgeSlop; - protected float mPrevFingerDiffX; - protected float mPrevFingerDiffY; - protected float mCurrFingerDiffX; - protected float mCurrFingerDiffY; - private float mRightSlopEdge; - private float mBottomSlopEdge; - private float mCurrLen; - private float mPrevLen; - - public TwoFingerGestureDetector(Context context) { - super(context); - - ViewConfiguration config = ViewConfiguration.get(context); - mEdgeSlop = config.getScaledEdgeSlop(); - } - - @Override - protected abstract void handleStartProgressEvent(int actionCode, MotionEvent event); - - @Override - protected abstract void handleInProgressEvent(int actionCode, MotionEvent event); - - protected void updateStateByEvent(MotionEvent curr) { - super.updateStateByEvent(curr); - - final MotionEvent prev = mPrevEvent; - - mCurrLen = -1; - mPrevLen = -1; - - // Previous - final float px0 = prev.getX(0); - final float py0 = prev.getY(0); - final float px1 = prev.getX(1); - final float py1 = prev.getY(1); - final float pvx = px1 - px0; - final float pvy = py1 - py0; - mPrevFingerDiffX = pvx; - mPrevFingerDiffY = pvy; - - // Current - final float cx0 = curr.getX(0); - final float cy0 = curr.getY(0); - final float cx1 = curr.getX(1); - final float cy1 = curr.getY(1); - final float cvx = cx1 - cx0; - final float cvy = cy1 - cy0; - mCurrFingerDiffX = cvx; - mCurrFingerDiffY = cvy; - } - - /** - * Return the current distance between the two pointers forming the - * gesture in progress. - * - * @return Distance between pointers in pixels. - */ - public float getCurrentSpan() { - if (mCurrLen == -1) { - final float cvx = mCurrFingerDiffX; - final float cvy = mCurrFingerDiffY; - mCurrLen = (float) Math.sqrt(cvx * cvx + cvy * cvy); - } - return mCurrLen; - } - - /** - * Return the previous distance between the two pointers forming the - * gesture in progress. - * - * @return Previous distance between pointers in pixels. - */ - public float getPreviousSpan() { - if (mPrevLen == -1) { - final float pvx = mPrevFingerDiffX; - final float pvy = mPrevFingerDiffY; - mPrevLen = (float) Math.sqrt(pvx * pvx + pvy * pvy); - } - return mPrevLen; - } - - /** - * Check if we have a sloppy gesture. Sloppy gestures can happen if the edge - * of the user's hand is touching the screen, for example. - * - * @param event - * @return - */ - protected boolean isSloppyGesture(MotionEvent event) { - // As orientation can change, query the metrics in touch down - DisplayMetrics metrics = mContext.getResources().getDisplayMetrics(); - mRightSlopEdge = metrics.widthPixels - mEdgeSlop; - mBottomSlopEdge = metrics.heightPixels - mEdgeSlop; - - final float edgeSlop = mEdgeSlop; - final float rightSlop = mRightSlopEdge; - final float bottomSlop = mBottomSlopEdge; - - final float x0 = event.getRawX(); - final float y0 = event.getRawY(); - final float x1 = getRawX(event, 1); - final float y1 = getRawY(event, 1); - - - Log.d(TAG, - String.format("x0: %f, y0: %f, x1: %f, y1: %f, EdgeSlop: %f, RightSlop: %f, BottomSlop: %f", - x0, y0, x1, y1, edgeSlop, rightSlop, bottomSlop)); - - - boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop - || x0 > rightSlop || y0 > bottomSlop; - boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop - || x1 > rightSlop || y1 > bottomSlop; - - if (p0sloppy && p1sloppy) { - return true; - } else if (p0sloppy) { - return true; - } else if (p1sloppy) { - return true; - } - return false; - } - - /** - * MotionEvent has no getRawX(int) method; simulate it pending future API approval. - * - * @param event - * @param pointerIndex - * @return - */ - protected static float getRawX(MotionEvent event, int pointerIndex) { - float offset = event.getX() - event.getRawX(); - if (pointerIndex < event.getPointerCount()) { - return event.getX(pointerIndex) + offset; - } - return 0f; - } - - /** - * MotionEvent has no getRawY(int) method; simulate it pending future API approval. - * - * @param event - * @param pointerIndex - * @return - */ - protected static float getRawY(MotionEvent event, int pointerIndex) { - float offset = Math.abs(event.getY() - event.getRawY()); - if (pointerIndex < event.getPointerCount()) { - return event.getY(pointerIndex) + offset; - } - return 0f; - } - -} diff --git a/src/org/thoughtcrime/securesms/scribbles/viewmodel/Font.java b/src/org/thoughtcrime/securesms/scribbles/viewmodel/Font.java deleted file mode 100644 index 2de6decf4..000000000 --- a/src/org/thoughtcrime/securesms/scribbles/viewmodel/Font.java +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright (c) 2016 UPTech - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package org.thoughtcrime.securesms.scribbles.viewmodel; - - -public class Font { - - /** - * color value (ex: 0xFF00FF) - */ - private int color; - /** - * name of the font - */ - private String typeface; - /** - * size of the font, relative to parent - */ - private float size; - - public Font() { - } - - public void increaseSize(float diff) { - if (size + diff <= Limits.MAX_FONT_SIZE) { - size = size + diff; - } - } - - public void decreaseSize(float diff) { - if (size - diff >= Limits.MIN_FONT_SIZE) { - size = size - diff; - } - } - - public int getColor() { - return color; - } - - public void setColor(int color) { - this.color = color; - } - - public String getTypeface() { - return typeface; - } - - public void setTypeface(String typeface) { - this.typeface = typeface; - } - - public float getSize() { - return size; - } - - public void setSize(float size) { - this.size = size; - } - - private interface Limits { - float MIN_FONT_SIZE = 0.01F; - float MAX_FONT_SIZE = 0.46F; - } -} \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/scribbles/viewmodel/Layer.java b/src/org/thoughtcrime/securesms/scribbles/viewmodel/Layer.java deleted file mode 100644 index 06d99941d..000000000 --- a/src/org/thoughtcrime/securesms/scribbles/viewmodel/Layer.java +++ /dev/null @@ -1,141 +0,0 @@ -/** - * Copyright (c) 2016 UPTech - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.thoughtcrime.securesms.scribbles.viewmodel; - -import android.support.annotation.FloatRange; -import org.thoughtcrime.securesms.logging.Log; - -public class Layer { - - /** - * rotation relative to the layer center, in degrees - */ - @FloatRange(from = 0.0F, to = 360.0F) - private float rotationInDegrees; - - private float scale; - /** - * top left X coordinate, relative to parent canvas - */ - private float x; - /** - * top left Y coordinate, relative to parent canvas - */ - private float y; - /** - * is layer flipped horizontally (by X-coordinate) - */ - private boolean isFlipped; - - public Layer() { - reset(); - } - - protected void reset() { - this.rotationInDegrees = 0.0F; - this.scale = 1.0F; - this.isFlipped = false; - this.x = 0.0F; - this.y = 0.0F; - } - - public void postScale(float scaleDiff) { - Log.i("Layer", "ScaleDiff: " + scaleDiff); - float newVal = scale + scaleDiff; - if (newVal >= getMinScale() && newVal <= getMaxScale()) { - scale = newVal; - } - } - - protected float getMaxScale() { - return Limits.MAX_SCALE; - } - - protected float getMinScale() { - return Limits.MIN_SCALE; - } - - public void postRotate(float rotationInDegreesDiff) { - this.rotationInDegrees += rotationInDegreesDiff; - this.rotationInDegrees %= 360.0F; - } - - public void postTranslate(float dx, float dy) { - this.x += dx; - this.y += dy; - } - - public void flip() { - this.isFlipped = !isFlipped; - } - - public float initialScale() { - return Limits.INITIAL_ENTITY_SCALE; - } - - public float getRotationInDegrees() { - return rotationInDegrees; - } - - public void setRotationInDegrees(@FloatRange(from = 0.0, to = 360.0) float rotationInDegrees) { - this.rotationInDegrees = rotationInDegrees; - } - - public float getScale() { - return scale; - } - - public void setScale(float scale) { - this.scale = scale; - } - - public float getX() { - return x; - } - - public void setX(float x) { - this.x = x; - } - - public float getY() { - return y; - } - - public void setY(float y) { - this.y = y; - } - - public boolean isFlipped() { - return isFlipped; - } - - public void setFlipped(boolean flipped) { - isFlipped = flipped; - } - - interface Limits { - float MIN_SCALE = 0.06F; - float MAX_SCALE = 4.0F; - float INITIAL_ENTITY_SCALE = 0.4F; - } -} diff --git a/src/org/thoughtcrime/securesms/scribbles/viewmodel/TextLayer.java b/src/org/thoughtcrime/securesms/scribbles/viewmodel/TextLayer.java deleted file mode 100644 index 4d9e77a3b..000000000 --- a/src/org/thoughtcrime/securesms/scribbles/viewmodel/TextLayer.java +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright (c) 2016 UPTech - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.thoughtcrime.securesms.scribbles.viewmodel; - -public class TextLayer extends Layer { - - private String text; - private Font font; - - public TextLayer() { - } - - @Override - protected void reset() { - super.reset(); - this.text = ""; - this.font = new Font(); - } - - @Override - protected float getMaxScale() { - return Limits.MAX_SCALE; - } - - @Override - protected float getMinScale() { - return Limits.MIN_SCALE; - } - - @Override - public float initialScale() { - return Limits.INITIAL_SCALE; - } - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - public Font getFont() { - return font; - } - - public void setFont(Font font) { - this.font = font; - } - - @Override - public void postScale(float scaleDiff) { - if (scaleDiff > 0) font.increaseSize(scaleDiff); - else if (scaleDiff < 0) font.decreaseSize(Math.abs(scaleDiff)); - } - - public interface Limits { - /** - * limit text size to view bounds - * so that users don't put small font size and scale it 100+ times - */ - float MAX_SCALE = 1.0F; - float MIN_SCALE = 0.2F; - - float MIN_BITMAP_HEIGHT = 0.13F; - - float FONT_SIZE_STEP = 0.008F; - - float INITIAL_FONT_SIZE = 0.1F; - int INITIAL_FONT_COLOR = 0xff000000; - - float INITIAL_SCALE = 0.8F; // set the same to avoid text scaling - } -} \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/scribbles/widget/CanvasView.java b/src/org/thoughtcrime/securesms/scribbles/widget/CanvasView.java deleted file mode 100644 index d58b7b919..000000000 --- a/src/org/thoughtcrime/securesms/scribbles/widget/CanvasView.java +++ /dev/null @@ -1,881 +0,0 @@ -/** - * CanvasView.java - * - * Copyright (c) 2014 Tomohiro IKEDA (Korilakkuma) - * Released under the MIT license - */ - -package org.thoughtcrime.securesms.scribbles.widget; - - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Bitmap.CompressFormat; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; -import android.graphics.RectF; -import android.support.annotation.NonNull; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; - -import java.io.ByteArrayOutputStream; -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -/** - * This class defines fields and methods for drawing. - */ -public class CanvasView extends View { - - private static final String TAG = CanvasView.class.getSimpleName(); - - public static final int DEFAULT_STROKE_WIDTH = 15; - - // Enumeration for Mode - public enum Mode { - DRAW, - TEXT, - ERASER; - } - - // Enumeration for Drawer - public enum Drawer { - PEN, - LINE, - RECTANGLE, - CIRCLE, - ELLIPSE, - QUADRATIC_BEZIER, - QUBIC_BEZIER; - } - - private int initialWidth = 0; - private int initialHeight = 0; - private int canvasWidth = 1; - private int canvasHeight = 1; - private Bitmap bitmap = null; - - private List pathLists = new ArrayList(); - private List paintLists = new ArrayList(); - - // for Eraser -// private int baseColor = Color.WHITE; - private int baseColor = Color.TRANSPARENT; - - // for Undo, Redo - private int historyPointer = 0; - - // Flags - private Mode mode = Mode.DRAW; - private Drawer drawer = Drawer.PEN; - private boolean isDown = false; - - // for Paint - private Paint.Style paintStyle = Paint.Style.STROKE; - private int paintStrokeColor = Color.BLACK; - private int paintFillColor = Color.BLACK; - private float paintStrokeWidth = DEFAULT_STROKE_WIDTH; - private int opacity = 255; - private float blur = 0F; - private Paint.Cap lineCap = Paint.Cap.ROUND; - - // for Drawer - private float startX = 0F; - private float startY = 0F; - private float controlX = 0F; - private float controlY = 0F; - - private boolean active = false; - - /** - * Copy Constructor - * - * @param context - * @param attrs - * @param defStyle - */ - public CanvasView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - this.setup(); - } - - /** - * Copy Constructor - * - * @param context - * @param attrs - */ - public CanvasView(Context context, AttributeSet attrs) { - super(context, attrs); - this.setup(); - } - - /** - * Copy Constructor - * - * @param context - */ - public CanvasView(Context context) { - super(context); - } - - - private void setup() { - this.pathLists.add(new Path()); - this.paintLists.add(this.createPaint()); - this.historyPointer++; - } - - /** - * This method creates the instance of Paint. - * In addition, this method sets styles for Paint. - * - * @return paint This is returned as the instance of Paint - */ - private Paint createPaint() { - Paint paint = new Paint(); - - paint.setAntiAlias(true); - paint.setStyle(this.paintStyle); - paint.setStrokeWidth(this.paintStrokeWidth); - paint.setStrokeCap(this.lineCap); - paint.setStrokeJoin(Paint.Join.ROUND); // fixed - - if (this.mode == Mode.ERASER) { - // Eraser - paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); - paint.setARGB(0, 0, 0, 0); - - // paint.setColor(this.baseColor); - // paint.setShadowLayer(this.blur, 0F, 0F, this.baseColor); - } else { - // Otherwise - paint.setColor(this.paintStrokeColor); - paint.setShadowLayer(this.blur, 0F, 0F, this.paintStrokeColor); - paint.setAlpha(this.opacity); - } - - return paint; - } - - /** - * This method initialize Path. - * Namely, this method creates the instance of Path, - * and moves current position. - * - * @param event This is argument of onTouchEvent method - * @return path This is returned as the instance of Path - */ - private Path createPath(MotionEvent event) { - Path path = new Path(); - - // Save for ACTION_MOVE - this.startX = scaleX(event.getX()); - this.startY = scaleY(event.getY()); - - path.moveTo(this.startX, this.startY); - - return path; - } - - /** - * This method updates the lists for the instance of Path and Paint. - * "Undo" and "Redo" are enabled by this method. - * - * @param path the instance of Path - */ - private void updateHistory(Path path) { - if (this.historyPointer == this.pathLists.size()) { - this.pathLists.add(path); - this.paintLists.add(this.createPaint()); - this.historyPointer++; - } else { - // On the way of Undo or Redo - this.pathLists.set(this.historyPointer, path); - this.paintLists.set(this.historyPointer, this.createPaint()); - this.historyPointer++; - - for (int i = this.historyPointer, size = this.paintLists.size(); i < size; i++) { - this.pathLists.remove(this.historyPointer); - this.paintLists.remove(this.historyPointer); - } - } - } - - /** - * This method gets the instance of Path that pointer indicates. - * - * @return the instance of Path - */ - private Path getCurrentPath() { - return this.pathLists.get(this.historyPointer - 1); - } - - /** - * This method defines processes on MotionEvent.ACTION_DOWN - * - * @param event This is argument of onTouchEvent method - */ - private void onActionDown(MotionEvent event) { - switch (this.mode) { - case DRAW : - case ERASER : - if ((this.drawer != Drawer.QUADRATIC_BEZIER) && (this.drawer != Drawer.QUBIC_BEZIER)) { - // Oherwise - this.updateHistory(this.createPath(event)); - this.isDown = true; - } else { - // Bezier - if ((this.startX == 0F) && (this.startY == 0F)) { - // The 1st tap - this.updateHistory(this.createPath(event)); - } else { - // The 2nd tap - this.controlX = event.getX(); - this.controlY = event.getY(); - - this.isDown = true; - } - } - - break; - case TEXT : - this.startX = event.getX(); - this.startY = event.getY(); - - break; - default : - break; - } - } - - /** - * This method defines processes on MotionEvent.ACTION_MOVE - * - * @param event This is argument of onTouchEvent method - */ - private void onActionMove(MotionEvent event) { - float x = event.getX(); - float y = event.getY(); - - switch (this.mode) { - case DRAW : - case ERASER : - - if ((this.drawer != Drawer.QUADRATIC_BEZIER) && (this.drawer != Drawer.QUBIC_BEZIER)) { - if (!isDown) { - return; - } - - Path path = this.getCurrentPath(); - - switch (this.drawer) { - case PEN : - for (int i = 0; i < event.getHistorySize(); i++) { - path.lineTo(scaleX(event.getHistoricalX(i)), scaleY(event.getHistoricalY(i))); - } - break; - case LINE : - path.reset(); - path.moveTo(this.startX, this.startY); - path.lineTo(x, y); - break; - case RECTANGLE : - path.reset(); - path.addRect(this.startX, this.startY, x, y, Path.Direction.CCW); - break; - case CIRCLE : - double distanceX = Math.abs((double)(this.startX - x)); - double distanceY = Math.abs((double)(this.startX - y)); - double radius = Math.sqrt(Math.pow(distanceX, 2.0) + Math.pow(distanceY, 2.0)); - - path.reset(); - path.addCircle(this.startX, this.startY, (float)radius, Path.Direction.CCW); - break; - case ELLIPSE : - RectF rect = new RectF(this.startX, this.startY, x, y); - - path.reset(); - path.addOval(rect, Path.Direction.CCW); - break; - default : - break; - } - } else { - if (!isDown) { - return; - } - - Path path = this.getCurrentPath(); - - path.reset(); - path.moveTo(scaleX(this.startX), scaleY(this.startY)); - path.quadTo(this.controlX, this.controlY, x, y); - } - - break; - case TEXT : - this.startX = x; - this.startY = y; - - break; - default : - break; - } - } - - /** - * This method defines processes on MotionEvent.ACTION_DOWN - * - * @param event This is argument of onTouchEvent method - */ - private void onActionUp(MotionEvent event) { - if (isDown) { - this.startX = 0F; - this.startY = 0F; - this.isDown = false; - } - } - - public SavedState saveState() { - return new SavedState(pathLists, paintLists, historyPointer, initialWidth, initialHeight, canvasWidth, canvasHeight); - } - - public void restoreState(@NonNull SavedState state) { - this.pathLists.clear(); - this.pathLists.addAll(state.getPaths()); - - this.paintLists.clear(); - this.paintLists.addAll(state.getPaints()); - - this.historyPointer = state.getHistoryPointer(); - - this.initialWidth = state.getInitialWidth(); - this.initialHeight = state.getInitialHeight(); - - postInvalidate(); - } - - public void setActive(boolean active) { - this.active = active; - } - - /** - * This method updates the instance of Canvas (View) - * - * @param canvas the new instance of Canvas - */ - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - canvas.drawColor(this.baseColor); - render(canvas); - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); - this.canvasWidth = w; - this.canvasHeight = h; - - if (initialWidth == 0) { - initialWidth = canvasWidth; - } - - if (initialHeight == 0) { - initialHeight = canvasHeight; - } - } - - public void render(Canvas canvas) { - render(canvas, initialWidth, initialHeight, canvasWidth, canvasHeight, pathLists, paintLists, historyPointer); - } - - public static void render(Canvas canvas, int initialWidth, int initialHeight, int canvasWidth, int canvasHeight, List pathLists, List paintLists, int historyPointer) { - float scaleX = 1f; - float scaleY = 1f; - - if (initialWidth > 0) { - scaleX *= (float) canvasWidth / initialWidth; - } - - if (initialHeight > 0) { - scaleY *= (float) canvasHeight / initialHeight; - } - - scaleX *= (float) canvas.getWidth() / canvasWidth; - scaleY *= (float) canvas.getHeight() / canvasHeight; - - Matrix matrix = new Matrix(); - matrix.setScale(scaleX, scaleY); - - for (int i = 0; i < historyPointer; i++) { - Path path = pathLists.get(i); - Paint paint = paintLists.get(i); - - Path scaledPath = new Path(); - path.transform(matrix, scaledPath); - - Paint scaledPaint = new Paint(paint); - scaledPaint.setStrokeWidth(scaledPaint.getStrokeWidth() * scaleX); - - canvas.drawPath(scaledPath, scaledPaint); - } - } - - /** - * This method set event listener for drawing. - * - * @param event the instance of MotionEvent - * @return - */ - @Override - public boolean onTouchEvent(MotionEvent event) { - if (!active) return false; - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - this.onActionDown(event); - break; - case MotionEvent.ACTION_MOVE : - this.onActionMove(event); - break; - case MotionEvent.ACTION_UP : - this.onActionUp(event); - break; - default : - break; - } - - // Re draw - this.invalidate(); - - return true; - } - - /** - * This method is getter for mode. - * - * @return - */ - public Mode getMode() { - return this.mode; - } - - /** - * This method is setter for mode. - * - * @param mode - */ - public void setMode(Mode mode) { - this.mode = mode; - } - - /** - * This method is getter for drawer. - * - * @return - */ - public Drawer getDrawer() { - return this.drawer; - } - - /** - * This method is setter for drawer. - * - * @param drawer - */ - public void setDrawer(Drawer drawer) { - this.drawer = drawer; - } - - /** - * This method draws canvas again for Undo. - * - * @return If Undo is enabled, this is returned as true. Otherwise, this is returned as false. - */ - public boolean undo() { - if (this.historyPointer > 1) { - this.historyPointer--; - this.invalidate(); - - return true; - } else { - return false; - } - } - - /** - * This method draws canvas again for Redo. - * - * @return If Redo is enabled, this is returned as true. Otherwise, this is returned as false. - */ - public boolean redo() { - if (this.historyPointer < this.pathLists.size()) { - this.historyPointer++; - this.invalidate(); - - return true; - } else { - return false; - } - } - - /** - * This method initializes canvas. - * - * @return - */ - public void clear() { - Path path = new Path(); - path.moveTo(0F, 0F); - path.addRect(0F, 0F, 1000F, 1000F, Path.Direction.CCW); - path.close(); - - Paint paint = new Paint(); - paint.setColor(Color.WHITE); - paint.setStyle(Paint.Style.FILL); - - if (this.historyPointer == this.pathLists.size()) { - this.pathLists.add(path); - this.paintLists.add(paint); - this.historyPointer++; - } else { - // On the way of Undo or Redo - this.pathLists.set(this.historyPointer, path); - this.paintLists.set(this.historyPointer, paint); - this.historyPointer++; - - for (int i = this.historyPointer, size = this.paintLists.size(); i < size; i++) { - this.pathLists.remove(this.historyPointer); - this.paintLists.remove(this.historyPointer); - } - } - - // Clear - this.invalidate(); - } - - /** - * This method is getter for canvas background color - * - * @return - */ - public int getBaseColor() { - return this.baseColor; - } - - /** - * This method is setter for canvas background color - * - * @param color - */ - public void setBaseColor(int color) { - this.baseColor = color; - } - - /** - * This method is getter for stroke or fill. - * - * @return - */ - public Paint.Style getPaintStyle() { - return this.paintStyle; - } - - /** - * This method is setter for stroke or fill. - * - * @param style - */ - public void setPaintStyle(Paint.Style style) { - this.paintStyle = style; - } - - /** - * This method is getter for stroke color. - * - * @return - */ - public int getPaintStrokeColor() { - return this.paintStrokeColor; - } - - /** - * This method is setter for stroke color. - * - * @param color - */ - public void setPaintStrokeColor(int color) { - this.paintStrokeColor = color; - } - - /** - * This method is getter for fill color. - * But, current Android API cannot set fill color (?). - * - * @return - */ - public int getPaintFillColor() { - return this.paintFillColor; - }; - - /** - * This method is setter for fill color. - * But, current Android API cannot set fill color (?). - * - * @param color - */ - public void setPaintFillColor(int color) { - this.paintFillColor = color; - } - - /** - * This method is getter for stroke width. - * - * @return - */ - public float getPaintStrokeWidth() { - return this.paintStrokeWidth; - } - - /** - * This method is setter for stroke width. - * - * @param width - */ - public void setPaintStrokeWidth(float width) { - if (width >= 0) { - this.paintStrokeWidth = width; - } else { - this.paintStrokeWidth = 3F; - } - } - - /** - * This method is getter for alpha. - * - * @return - */ - public int getOpacity() { - return this.opacity; - } - - /** - * This method is setter for alpha. - * The 1st argument must be between 0 and 255. - * - * @param opacity - */ - public void setOpacity(int opacity) { - if ((opacity >= 0) && (opacity <= 255)) { - this.opacity = opacity; - } else { - this.opacity= 255; - } - } - - /** - * This method is getter for amount of blur. - * - * @return - */ - public float getBlur() { - return this.blur; - } - - /** - * This method is setter for amount of blur. - * The 1st argument is greater than or equal to 0.0. - * - * @param blur - */ - public void setBlur(float blur) { - if (blur >= 0) { - this.blur = blur; - } else { - this.blur = 0F; - } - } - - /** - * This method is getter for line cap. - * - * @return - */ - public Paint.Cap getLineCap() { - return this.lineCap; - } - - /** - * This method is setter for line cap. - * - * @param cap - */ - public void setLineCap(Paint.Cap cap) { - this.lineCap = cap; - } - - /** - * This method gets current canvas as bitmap. - * - * @return This is returned as bitmap. - */ - public Bitmap getBitmap() { - this.setDrawingCacheEnabled(false); - this.setDrawingCacheEnabled(true); - - return Bitmap.createBitmap(this.getDrawingCache()); - } - - /** - * This method gets current canvas as scaled bitmap. - * - * @return This is returned as scaled bitmap. - */ - public Bitmap getScaleBitmap(int w, int h) { - this.setDrawingCacheEnabled(false); - this.setDrawingCacheEnabled(true); - - return Bitmap.createScaledBitmap(this.getDrawingCache(), w, h, true); - } - - /** - * This method draws the designated bitmap to canvas. - * - * @param bitmap - */ - public void drawBitmap(Bitmap bitmap) { - this.bitmap = bitmap; - this.invalidate(); - } - - /** - * This method draws the designated byte array of bitmap to canvas. - * - * @param byteArray This is returned as byte array of bitmap. - */ - public void drawBitmap(byte[] byteArray) { - this.drawBitmap(BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length)); - } - - /** - * This static method gets the designated bitmap as byte array. - * - * @param bitmap - * @param format - * @param quality - * @return This is returned as byte array of bitmap. - */ - public static byte[] getBitmapAsByteArray(Bitmap bitmap, CompressFormat format, int quality) { - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - bitmap.compress(format, quality, byteArrayOutputStream); - - return byteArrayOutputStream.toByteArray(); - } - - /** - * This method gets the bitmap as byte array. - * - * @param format - * @param quality - * @return This is returned as byte array of bitmap. - */ - public byte[] getBitmapAsByteArray(CompressFormat format, int quality) { - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - this.getBitmap().compress(format, quality, byteArrayOutputStream); - - return byteArrayOutputStream.toByteArray(); - } - - /** - * This method gets the bitmap as byte array. - * Bitmap format is PNG, and quality is 100. - * - * @return This is returned as byte array of bitmap. - */ - public byte[] getBitmapAsByteArray() { - return this.getBitmapAsByteArray(CompressFormat.PNG, 100); - } - - public @NonNull Set getUniqueColors() { - Set colors = new LinkedHashSet<>(); - - for (int i = 1; i < paintLists.size() && i < historyPointer; i++) { - int color = paintLists.get(i).getColor(); - colors.add(Color.rgb(Color.red(color), Color.green(color), Color.blue(color))); - } - - return colors; - } - - private float scaleX(float x) { - return ((float) initialWidth / canvasWidth) * x; - } - - private float scaleY(float y) { - return ((float) initialWidth / canvasWidth) * y; - } - - static class SavedState { - private final List paths; - private final List paints; - private final int historyPointer; - private final int initialWidth; - private final int initialHeight; - private final int canvasWidth; - private final int canvasHeight; - - SavedState(List paths, List paints, int historyPointer, int initialWidth, int initialHeight, int canvasWidth, int canvasHeight) { - this.paths = new ArrayList<>(paths); - this.paints = new ArrayList<>(paints); - this.historyPointer = historyPointer; - this.initialWidth = initialWidth; - this.initialHeight = initialHeight; - this.canvasWidth = canvasWidth; - this.canvasHeight = canvasHeight; - } - - List getPaths() { - return paths; - } - - List getPaints() { - return paints; - } - - int getHistoryPointer() { - return historyPointer; - } - - int getInitialWidth() { - return initialWidth; - } - - int getInitialHeight() { - return initialHeight; - } - - int getCanvasWidth() { - return canvasWidth; - } - - int getCanvasHeight() { - return canvasHeight; - } - - boolean isEmpty() { - return paths.size() <= 1; - } - } -} \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/scribbles/widget/MotionView.java b/src/org/thoughtcrime/securesms/scribbles/widget/MotionView.java deleted file mode 100644 index 6210eef39..000000000 --- a/src/org/thoughtcrime/securesms/scribbles/widget/MotionView.java +++ /dev/null @@ -1,526 +0,0 @@ -/** - * Copyright (c) 2016 UPTech - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package org.thoughtcrime.securesms.scribbles.widget; - -import android.annotation.TargetApi; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.PointF; -import android.os.Build; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.view.GestureDetectorCompat; -import android.support.v4.view.ViewCompat; -import android.text.Editable; -import android.text.InputType; -import android.text.Selection; -import android.text.TextUtils; -import android.text.TextWatcher; -import android.util.AttributeSet; -import android.util.TypedValue; -import android.view.GestureDetector; -import android.view.Gravity; -import android.view.MotionEvent; -import android.view.ScaleGestureDetector; -import android.view.View; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputMethodManager; -import android.widget.EditText; -import android.widget.FrameLayout; - -import com.annimon.stream.Stream; - -import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.logging.Log; -import org.thoughtcrime.securesms.scribbles.multitouch.MoveGestureDetector; -import org.thoughtcrime.securesms.scribbles.multitouch.RotateGestureDetector; -import org.thoughtcrime.securesms.scribbles.widget.entity.MotionEntity; -import org.thoughtcrime.securesms.scribbles.widget.entity.TextEntity; - -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -public class MotionView extends FrameLayout implements TextWatcher { - - private static final String TAG = MotionView.class.getSimpleName(); - - public interface Constants { - float SELECTED_LAYER_ALPHA = 0.15F; - } - - public interface MotionViewCallback { - void onEntitySelected(@Nullable MotionEntity entity); - void onEntityDoubleTap(@NonNull MotionEntity entity); - } - - // layers - private final List entities = new ArrayList<>(); - @Nullable - private MotionEntity selectedEntity; - - private Paint selectedLayerPaint; - - // callback - @Nullable - private MotionViewCallback motionViewCallback; - - private EditText editText; - - // gesture detection - private ScaleGestureDetector scaleGestureDetector; - private RotateGestureDetector rotateGestureDetector; - private MoveGestureDetector moveGestureDetector; - private GestureDetectorCompat gestureDetectorCompat; - - // constructors - public MotionView(Context context) { - super(context); - init(context, null); - } - - public MotionView(Context context, AttributeSet attrs) { - super(context, attrs); - init(context, attrs); - } - - public MotionView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context, attrs); - } - - @SuppressWarnings("unused") - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public MotionView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - init(context, attrs); - } - - private void init(@NonNull Context context, @Nullable AttributeSet attrs) { - // I fucking love Android - setWillNotDraw(false); - - selectedLayerPaint = new Paint(); - selectedLayerPaint.setAlpha((int) (255 * Constants.SELECTED_LAYER_ALPHA)); - selectedLayerPaint.setAntiAlias(true); - - this.editText = new EditText(context, attrs); - ViewCompat.setAlpha(this.editText, 0); - this.editText.setLayoutParams(new LayoutParams(1, 1, Gravity.TOP | Gravity.LEFT)); - this.editText.setClickable(false); - this.editText.setBackgroundColor(Color.TRANSPARENT); - this.editText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 1); - this.editText.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD); - this.editText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI); - this.addView(editText); - this.editText.clearFocus(); - this.editText.addTextChangedListener(this); - this.editText.setId(R.id.motion_view_edittext); - - // init listeners - this.scaleGestureDetector = new ScaleGestureDetector(context, new ScaleListener()); - this.rotateGestureDetector = new RotateGestureDetector(context, new RotateListener()); - this.moveGestureDetector = new MoveGestureDetector(context, new MoveListener()); - this.gestureDetectorCompat = new GestureDetectorCompat(context, new TapsListener()); - - setOnTouchListener(onTouchListener); - - updateUI(); - } - - public SavedState saveState() { - return new SavedState(entities); - } - - public void restoreState(@NonNull SavedState savedState) { - this.entities.clear(); - this.entities.addAll(savedState.getEntities()); - - postInvalidate(); - } - - public void startEditing(TextEntity entity) { - editText.setFocusableInTouchMode(true); - editText.setFocusable(true); - editText.requestFocus(); - editText.setText(entity.getLayer().getText()); - Selection.setSelection(editText.getText(), editText.length()); - - InputMethodManager ims = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - ims.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT); - } - - public MotionEntity getSelectedEntity() { - return selectedEntity; - } - - public List getEntities() { - return entities; - } - - public void setMotionViewCallback(@Nullable MotionViewCallback callback) { - this.motionViewCallback = callback; - } - - public void addEntity(@Nullable MotionEntity entity) { - if (entity != null) { - entities.add(entity); - selectEntity(entity, false); - } - } - - public void addEntityAndPosition(@Nullable MotionEntity entity) { - if (entity != null) { - initEntityBorder(entity); - initialTranslateAndScale(entity); - entities.add(entity); - selectEntity(entity, true); - } - } - - public @NonNull Set getUniqueColors() { - Set colors = new LinkedHashSet<>(); - - for (MotionEntity entity : entities) { - if (entity instanceof TextEntity) { - colors.add(((TextEntity) entity).getLayer().getFont().getColor()); - } - } - - return colors; - } - - private void initEntityBorder(@NonNull MotionEntity entity ) { - // init stroke - int strokeSize = getResources().getDimensionPixelSize(R.dimen.scribble_stroke_size); - Paint borderPaint = new Paint(); - borderPaint.setStrokeWidth(strokeSize); - borderPaint.setAntiAlias(true); - borderPaint.setColor(getContext().getResources().getColor(R.color.sticker_selected_color)); - - entity.setBorderPaint(borderPaint); - } - - @Override - protected void dispatchDraw(Canvas canvas) { - super.dispatchDraw(canvas); - - // dispatch draw is called after child views is drawn. - // the idea that is we draw background stickers, than child views (if any), and than selected item - // to draw on top of child views - do it in dispatchDraw(Canvas) - // to draw below that - do it in onDraw(Canvas) - if (selectedEntity != null) { - selectedEntity.draw(canvas, selectedLayerPaint); - } - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - render(canvas, entities); - } - - public void render(Canvas canvas) { - unselectEntity(); - draw(canvas); - } - - public static void render(Canvas canvas, List entities) { - for (int i = 0; i < entities.size(); i++) { - entities.get(i).draw(canvas, null); - } - } - - /** - * as a side effect - the method deselects Entity (if any selected) - * @return bitmap with all the Entities at their current positions - */ - public Bitmap getThumbnailImage() { - selectEntity(null, false); - - Bitmap bmp = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); - // IMPORTANT: always create white background, cos if the image is saved in JPEG format, - // which doesn't have transparent pixels, the background will be black - bmp.eraseColor(Color.WHITE); - Canvas canvas = new Canvas(bmp); - render(canvas, entities); - - return bmp; - } - - private void updateUI() { - invalidate(); - } - - private void handleTranslate(PointF delta) { - if (selectedEntity != null) { - float newCenterX = selectedEntity.absoluteCenterX() + delta.x; - float newCenterY = selectedEntity.absoluteCenterY() + delta.y; - // limit entity center to screen bounds - boolean needUpdateUI = false; - if (newCenterX >= 0 && newCenterX <= getWidth()) { - selectedEntity.getLayer().postTranslate(delta.x / getWidth(), 0.0F); - needUpdateUI = true; - } - if (newCenterY >= 0 && newCenterY <= getHeight()) { - selectedEntity.getLayer().postTranslate(0.0F, delta.y / getHeight()); - needUpdateUI = true; - } - if (needUpdateUI) { - updateUI(); - } - } - } - - private void initialTranslateAndScale(@NonNull MotionEntity entity) { - entity.moveToCanvasCenter(); - entity.getLayer().setScale(entity.getLayer().initialScale()); - } - - private void selectEntity(@Nullable MotionEntity entity, boolean updateCallback) { - if (selectedEntity != null && entity != selectedEntity) { - selectedEntity.setIsSelected(false); - - if (selectedEntity instanceof TextEntity) { - if (TextUtils.isEmpty(((TextEntity) selectedEntity).getLayer().getText())) { - deletedSelectedEntity(); - } else { - editText.clearComposingText(); - editText.clearFocus(); - } - InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(editText.getWindowToken(), 0); - } - - } - if (entity != null) { - entity.setIsSelected(true); - } - selectedEntity = entity; - invalidate(); - if (updateCallback && motionViewCallback != null) { - motionViewCallback.onEntitySelected(entity); - } - } - - public void unselectEntity() { - if (selectedEntity != null) { - selectEntity(null, false); - } - } - - @Nullable - private MotionEntity findEntityAtPoint(float x, float y) { - MotionEntity selected = null; - PointF p = new PointF(x, y); - for (int i = entities.size() - 1; i >= 0; i--) { - if (entities.get(i).pointInLayerRect(p)) { - selected = entities.get(i); - break; - } - } - return selected; - } - - private void updateSelectionOnTap(MotionEvent e) { - MotionEntity entity = findEntityAtPoint(e.getX(), e.getY()); - selectEntity(entity, true); - } - - private void updateOnLongPress(MotionEvent e) { - // if layer is currently selected and point inside layer - move it to front - if (selectedEntity != null) { - PointF p = new PointF(e.getX(), e.getY()); - if (selectedEntity.pointInLayerRect(p)) { - bringLayerToFront(selectedEntity); - } - } - } - - private void bringLayerToFront(@NonNull MotionEntity entity) { - // removing and adding brings layer to front - if (entities.remove(entity)) { - entities.add(entity); - invalidate(); - } - } - - private void moveEntityToBack(@Nullable MotionEntity entity) { - if (entity == null) { - return; - } - if (entities.remove(entity)) { - entities.add(0, entity); - invalidate(); - } - } - - public void flipSelectedEntity() { - if (selectedEntity == null) { - return; - } - selectedEntity.getLayer().flip(); - invalidate(); - } - - public void moveSelectedBack() { - moveEntityToBack(selectedEntity); - } - - public void deletedSelectedEntity() { - if (selectedEntity == null) { - return; - } - if (entities.remove(selectedEntity)) { - selectedEntity.release(); - selectedEntity = null; - invalidate(); - } - } - - // memory - public void release() { - for (MotionEntity entity : entities) { - entity.release(); - } - } - - // gesture detectors - - private final View.OnTouchListener onTouchListener = new View.OnTouchListener() { - - @Override - public boolean onTouch(View v, MotionEvent event) { - if (scaleGestureDetector != null) { - scaleGestureDetector.onTouchEvent(event); - rotateGestureDetector.onTouchEvent(event); - moveGestureDetector.onTouchEvent(event); - gestureDetectorCompat.onTouchEvent(event); - } - return true; - } - }; - - private class TapsListener extends GestureDetector.SimpleOnGestureListener { - @Override - public boolean onDoubleTap(MotionEvent e) { - if (motionViewCallback != null && selectedEntity != null) { - motionViewCallback.onEntityDoubleTap(selectedEntity); - } - return true; - } - - @Override - public void onLongPress(MotionEvent e) { - updateOnLongPress(e); - } - - @Override - public boolean onSingleTapUp(MotionEvent e) { - updateSelectionOnTap(e); - return true; - } - - @Override - public boolean onDown(MotionEvent e) { - updateSelectionOnTap(e); - return false; - } - } - - private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { - @Override - public boolean onScale(ScaleGestureDetector detector) { - if (selectedEntity != null) { - float scaleFactorDiff = detector.getScaleFactor(); - Log.d(TAG, "ScaleFactorDiff: " + scaleFactorDiff); - selectedEntity.getLayer().postScale(scaleFactorDiff - 1.0F); - selectedEntity.updateEntity(); - updateUI(); - } - return true; - } - } - - private class RotateListener extends RotateGestureDetector.SimpleOnRotateGestureListener { - @Override - public boolean onRotate(RotateGestureDetector detector) { - if (selectedEntity != null) { - selectedEntity.getLayer().postRotate(-detector.getRotationDegreesDelta()); - updateUI(); - } - return true; - } - } - - private class MoveListener extends MoveGestureDetector.SimpleOnMoveGestureListener { - @Override - public boolean onMove(MoveGestureDetector detector) { - handleTranslate(detector.getFocusDelta()); - return true; - } - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - String text = s.toString(); - MotionEntity entity = getSelectedEntity(); - - if (entity != null && entity instanceof TextEntity) { - TextEntity textEntity = (TextEntity)entity; - - if (!textEntity.getLayer().getText().equals(text)) { - textEntity.getLayer().setText(text); - textEntity.updateEntity(); - MotionView.this.invalidate(); - } - } - } - - static class SavedState { - - private final List entities; - - SavedState(List entities) { - this.entities = new ArrayList<>(entities); - Stream.of(entities).forEach(e -> e.setIsSelected(false)); - } - - List getEntities() { - return entities; - } - - boolean isEmpty() { - return entities.isEmpty(); - } - } -} diff --git a/src/org/thoughtcrime/securesms/scribbles/widget/ScribbleView.java b/src/org/thoughtcrime/securesms/scribbles/widget/ScribbleView.java deleted file mode 100644 index a7453e24d..000000000 --- a/src/org/thoughtcrime/securesms/scribbles/widget/ScribbleView.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (C) 2016 Open Whisper Systems - * - * This program 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. - * - * This program 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 this program. If not, see . - */ -package org.thoughtcrime.securesms.scribbles.widget; - -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Build; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.widget.FrameLayout; -import android.widget.ImageView; - -import com.bumptech.glide.load.engine.DiskCacheStrategy; -import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; -import com.bumptech.glide.request.target.SimpleTarget; -import com.bumptech.glide.request.target.Target; -import com.bumptech.glide.request.transition.Transition; - -import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri; -import org.thoughtcrime.securesms.mms.GlideRequests; -import org.thoughtcrime.securesms.scribbles.widget.entity.MotionEntity; -import org.thoughtcrime.securesms.scribbles.widget.entity.TextEntity; -import org.thoughtcrime.securesms.util.Util; -import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; -import org.thoughtcrime.securesms.util.concurrent.SettableFuture; - -import java.util.LinkedHashSet; -import java.util.Set; - -public class ScribbleView extends FrameLayout { - - private static final String TAG = ScribbleView.class.getSimpleName(); - - public static final int DEFAULT_BRUSH_WIDTH = CanvasView.DEFAULT_STROKE_WIDTH; - - private ImageView imageView; - private MotionView motionView; - private CanvasView canvasView; - - private @Nullable Uri imageUri; - - public ScribbleView(Context context) { - super(context); - initialize(context); - } - - public ScribbleView(Context context, AttributeSet attrs) { - super(context, attrs); - initialize(context); - } - - public ScribbleView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - initialize(context); - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public ScribbleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - initialize(context); - } - - public void setImage(@NonNull GlideRequests glideRequests, @NonNull Uri uri) { - this.imageUri = uri; - - glideRequests.load(new DecryptableUri(uri)) - .diskCacheStrategy(DiskCacheStrategy.NONE) - .transition(DrawableTransitionOptions.withCrossFade()) - .fitCenter() - .into(imageView); - } - - public @NonNull ListenableFuture getRenderedImage(@NonNull GlideRequests glideRequests) { - return renderImage(getContext(), imageUri, saveState(), glideRequests); - } - - public static @NonNull ListenableFuture renderImage(@NonNull Context context, - @Nullable Uri imageUri, - @NonNull SavedState savedState, - @NonNull GlideRequests glideRequests) - { - final SettableFuture future = new SettableFuture<>(); - final boolean isLowMemory = Util.isLowMemory(context); - - if (imageUri == null) { - future.setException(new IllegalStateException("No image URI.")); - return future; - } - - int width = Target.SIZE_ORIGINAL; - int height = Target.SIZE_ORIGINAL; - - if (isLowMemory) { - width = 768; - height = 768; - } - - glideRequests.asBitmap() - .load(new DecryptableUri(imageUri)) - .diskCacheStrategy(DiskCacheStrategy.NONE) - .skipMemoryCache(true) - .override(width, height) - .into(new SimpleTarget() { - @Override - public void onResourceReady(@NonNull Bitmap bitmap, @Nullable Transition transition) { - Canvas canvas = new Canvas(bitmap); - MotionView.render(canvas, savedState.getMotionState().getEntities()); - CanvasView.render(canvas, - savedState.getCanvasState().getInitialWidth(), - savedState.getCanvasState().getInitialHeight(), - savedState.getCanvasState().getCanvasWidth(), - savedState.getCanvasState().getCanvasHeight(), - savedState.getCanvasState().getPaths(), - savedState.getCanvasState().getPaints(), - savedState.getCanvasState().getHistoryPointer()); - future.set(bitmap); - } - - @Override - public void onLoadFailed(@Nullable Drawable errorDrawable) { - future.setException(new Throwable("Failed to load image.")); - } - }); - - return future; - } - - public SavedState saveState() { - return new SavedState(canvasView.saveState(), motionView.saveState()); - } - - public void restoreState(@NonNull SavedState state) { - canvasView.restoreState(state.getCanvasState()); - motionView.restoreState(state.getMotionState()); - } - - private void initialize(@NonNull Context context) { - inflate(context, R.layout.scribble_view, this); - - this.imageView = findViewById(R.id.image_view); - this.motionView = findViewById(R.id.motion_view); - this.canvasView = findViewById(R.id.canvas_view); - } - - public void setMotionViewCallback(MotionView.MotionViewCallback callback) { - this.motionView.setMotionViewCallback(callback); - } - - @SuppressLint("ClickableViewAccessibility") - public void setDrawingChangedListener(@Nullable DrawingChangedListener listener) { - this.canvasView.setOnTouchListener((v, event) -> { - if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { - if (listener != null) { - listener.onDrawingChanged(); - } - } - return false; - }); - } - - public void setDrawingMode(boolean enabled) { - this.canvasView.setActive(enabled); - if (enabled) this.motionView.unselectEntity(); - } - - public void setDrawingBrushColor(int color) { - this.canvasView.setPaintFillColor(color); - this.canvasView.setPaintStrokeColor(color); - this.canvasView.setOpacity(Color.alpha(color)); - } - - public void setDrawingBrushWidth(int width) { - this.canvasView.setPaintStrokeWidth(width); - } - - public void addEntityAndPosition(MotionEntity entity) { - this.motionView.addEntityAndPosition(entity); - } - - public MotionEntity getSelectedEntity() { - return this.motionView.getSelectedEntity(); - } - - public void deleteSelected() { - this.motionView.deletedSelectedEntity(); - } - - public void clearSelection() { - this.motionView.unselectEntity(); - } - - public void undoDrawing() { - this.canvasView.undo(); - } - - public void startEditing(TextEntity entity) { - this.motionView.startEditing(entity); - } - - public @NonNull Set getUniqueColors() { - Set colors = new LinkedHashSet<>(); - - colors.addAll(motionView.getUniqueColors()); - colors.addAll(canvasView.getUniqueColors()); - - return colors; - } - - @Override - public void onMeasure(int width, int height) { - super.onMeasure(width, height); - - setMeasuredDimension(imageView.getMeasuredWidth(), imageView.getMeasuredHeight()); - - canvasView.measure(MeasureSpec.makeMeasureSpec(imageView.getMeasuredWidth(), MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(imageView.getMeasuredHeight(), MeasureSpec.EXACTLY)); - - motionView.measure(MeasureSpec.makeMeasureSpec(imageView.getMeasuredWidth(), MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(imageView.getMeasuredHeight(), MeasureSpec.EXACTLY)); - } - - public interface DrawingChangedListener { - void onDrawingChanged(); - } - - public static class SavedState { - private final CanvasView.SavedState canvasState; - private final MotionView.SavedState motionState; - - SavedState(@NonNull CanvasView.SavedState canvasState, @NonNull MotionView.SavedState motionState) { - this.canvasState = canvasState; - this.motionState = motionState; - } - - CanvasView.SavedState getCanvasState() { - return canvasState; - } - - MotionView.SavedState getMotionState() { - return motionState; - } - - public boolean isEmpty() { - return canvasState.isEmpty() && motionState.isEmpty(); - } - } -} diff --git a/src/org/thoughtcrime/securesms/scribbles/widget/VerticalSlideColorPicker.java b/src/org/thoughtcrime/securesms/scribbles/widget/VerticalSlideColorPicker.java index 27071eae7..878bd8bb4 100644 --- a/src/org/thoughtcrime/securesms/scribbles/widget/VerticalSlideColorPicker.java +++ b/src/org/thoughtcrime/securesms/scribbles/widget/VerticalSlideColorPicker.java @@ -172,6 +172,8 @@ public class VerticalSlideColorPicker extends View { viewWidth = w; viewHeight = h; + if (viewWidth <= 0 || viewHeight <= 0) return; + int barWidth = (int) (viewWidth * INDICATOR_TO_BAR_WIDTH_RATIO); centerX = viewWidth / 2; diff --git a/src/org/thoughtcrime/securesms/scribbles/widget/entity/ImageEntity.java b/src/org/thoughtcrime/securesms/scribbles/widget/entity/ImageEntity.java deleted file mode 100644 index 23bc3c619..000000000 --- a/src/org/thoughtcrime/securesms/scribbles/widget/entity/ImageEntity.java +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright (c) 2016 UPTech - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package org.thoughtcrime.securesms.scribbles.widget.entity; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.support.annotation.IntRange; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import org.thoughtcrime.securesms.scribbles.viewmodel.Layer; - - -public class ImageEntity extends MotionEntity { - - @NonNull - private final Bitmap bitmap; - - public ImageEntity(@NonNull Layer layer, - @NonNull Bitmap bitmap, - @IntRange(from = 1) int canvasWidth, - @IntRange(from = 1) int canvasHeight) { - super(layer, canvasWidth, canvasHeight); - - this.bitmap = bitmap; - float width = bitmap.getWidth(); - float height = bitmap.getHeight(); - - float widthAspect = 1.0F * canvasWidth / width; - float heightAspect = 1.0F * canvasHeight / height; - // fit the smallest size - holyScale = Math.min(widthAspect, heightAspect); - - // initial position of the entity - srcPoints[0] = 0; srcPoints[1] = 0; - srcPoints[2] = width; srcPoints[3] = 0; - srcPoints[4] = width; srcPoints[5] = height; - srcPoints[6] = 0; srcPoints[7] = height; - srcPoints[8] = 0; srcPoints[8] = 0; - } - - @Override - public void drawContent(@NonNull Canvas canvas, @Nullable Paint drawingPaint) { - canvas.drawBitmap(bitmap, matrix, drawingPaint); - } - - @Override - public int getWidth() { - return bitmap.getWidth(); - } - - @Override - public int getHeight() { - return bitmap.getHeight(); - } - - @Override - public void release() { - if (!bitmap.isRecycled()) { - bitmap.recycle(); - } - } -} \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/scribbles/widget/entity/MotionEntity.java b/src/org/thoughtcrime/securesms/scribbles/widget/entity/MotionEntity.java deleted file mode 100644 index 8c72e922c..000000000 --- a/src/org/thoughtcrime/securesms/scribbles/widget/entity/MotionEntity.java +++ /dev/null @@ -1,290 +0,0 @@ -/** - * Copyright (c) 2016 UPTech - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package org.thoughtcrime.securesms.scribbles.widget.entity; - -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.PointF; -import android.support.annotation.IntRange; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import org.thoughtcrime.securesms.util.MathUtils; -import org.thoughtcrime.securesms.scribbles.viewmodel.Layer; - - -@SuppressWarnings({"WeakerAccess"}) -public abstract class MotionEntity { - - /** - * data - */ - @NonNull - protected final Layer layer; - - /** - * transformation matrix for the entity - */ - protected final Matrix matrix = new Matrix(); - /** - * true - entity is selected and need to draw it's border - * false - not selected, no need to draw it's border - */ - private boolean isSelected; - - /** - * maximum scale of the initial image, so that - * the entity still fits within the parent canvas - */ - protected float holyScale; - - /** - * width of canvas the entity is drawn in - */ - @IntRange(from = 0) - protected int canvasWidth; - /** - * height of canvas the entity is drawn in - */ - @IntRange(from = 0) - protected int canvasHeight; - - /** - * Destination points of the entity - * 5 points. Size of array - 10; Starting upper left corner, clockwise - * last point is the same as first to close the circle - * NOTE: saved as a field variable in order to avoid creating array in draw()-like methods - */ - private final float[] destPoints = new float[10]; // x0, y0, x1, y1, x2, y2, x3, y3, x0, y0 - /** - * Initial points of the entity - * @see #destPoints - */ - protected final float[] srcPoints = new float[10]; // x0, y0, x1, y1, x2, y2, x3, y3, x0, y0 - - @NonNull - private Paint borderPaint = new Paint(); - - public MotionEntity(@NonNull Layer layer, - @IntRange(from = 1) int canvasWidth, - @IntRange(from = 1) int canvasHeight) { - this.layer = layer; - this.canvasWidth = canvasWidth; - this.canvasHeight = canvasHeight; - } - - private boolean isSelected() { - return isSelected; - } - - public void setIsSelected(boolean isSelected) { - this.isSelected = isSelected; - } - - /** - * S - scale matrix, R - rotate matrix, T - translate matrix, - * L - result transformation matrix - *

- * The correct order of applying transformations is : L = S * R * T - *

- * See more info: Game Dev: Transform Matrix multiplication order - *

- * Preconcat works like M` = M * S, so we apply preScale -> preRotate -> preTranslate - * the result will be the same: L = S * R * T - *

- * NOTE: postconcat (postScale, etc.) works the other way : M` = S * M, in order to use it - * we'd need to reverse the order of applying - * transformations : post holy scale -> postTranslate -> postRotate -> postScale - */ - protected void updateMatrix() { - // init matrix to E - identity matrix - matrix.reset(); - - float widthAspect = 1.0F * canvasWidth / getWidth(); - float heightAspect = 1.0F * canvasHeight / getHeight(); - // fit the smallest size - holyScale = Math.min(widthAspect, heightAspect); - - float topLeftX = layer.getX() * canvasWidth; - float topLeftY = layer.getY() * canvasHeight; - - float centerX = topLeftX + getWidth() * holyScale * 0.5F; - float centerY = topLeftY + getHeight() * holyScale * 0.5F; - - // calculate params - float rotationInDegree = layer.getRotationInDegrees(); - float scaleX = layer.getScale(); - float scaleY = layer.getScale(); - if (layer.isFlipped()) { - // flip (by X-coordinate) if needed - rotationInDegree *= -1.0F; - scaleX *= -1.0F; - } - - // applying transformations : L = S * R * T - - // scale - matrix.preScale(scaleX, scaleY, centerX, centerY); - - // rotate - matrix.preRotate(rotationInDegree, centerX, centerY); - - // translate - matrix.preTranslate(topLeftX, topLeftY); - - // applying holy scale - S`, the result will be : L = S * R * T * S` - matrix.preScale(holyScale, holyScale); - } - - public float absoluteCenterX() { - float topLeftX = layer.getX() * canvasWidth; - return topLeftX + getWidth() * holyScale * 0.5F; - } - - public float absoluteCenterY() { - float topLeftY = layer.getY() * canvasHeight; - - return topLeftY + getHeight() * holyScale * 0.5F; - } - - public PointF absoluteCenter() { - float topLeftX = layer.getX() * canvasWidth; - float topLeftY = layer.getY() * canvasHeight; - - float centerX = topLeftX + getWidth() * holyScale * 0.5F; - float centerY = topLeftY + getHeight() * holyScale * 0.5F; - - return new PointF(centerX, centerY); - } - - public void moveToCanvasCenter() { - moveCenterTo(new PointF(canvasWidth * 0.5F, canvasHeight * 0.5F)); - } - - public void moveCenterTo(PointF moveToCenter) { - PointF currentCenter = absoluteCenter(); - layer.postTranslate(1.0F * (moveToCenter.x - currentCenter.x) / canvasWidth, - 1.0F * (moveToCenter.y - currentCenter.y) / canvasHeight); - } - - private final PointF pA = new PointF(); - private final PointF pB = new PointF(); - private final PointF pC = new PointF(); - private final PointF pD = new PointF(); - - /** - * For more info: - * StackOverflow: How to check point is in rectangle - *

NOTE: it's easier to apply the same transformation matrix (calculated before) to the original source points, rather than - * calculate the result points ourselves - * @param point point - * @return true if point (x, y) is inside the triangle - */ - public boolean pointInLayerRect(PointF point) { - - updateMatrix(); - // map rect vertices - matrix.mapPoints(destPoints, srcPoints); - - pA.x = destPoints[0]; - pA.y = destPoints[1]; - pB.x = destPoints[2]; - pB.y = destPoints[3]; - pC.x = destPoints[4]; - pC.y = destPoints[5]; - pD.x = destPoints[6]; - pD.y = destPoints[7]; - - return MathUtils.pointInTriangle(point, pA, pB, pC) || MathUtils.pointInTriangle(point, pA, pD, pC); - } - - /** - * http://judepereira.com/blog/calculate-the-real-scale-factor-and-the-angle-of-rotation-from-an-android-matrix/ - * - * @param canvas Canvas to draw - * @param drawingPaint Paint to use during drawing - */ - public final void draw(@NonNull Canvas canvas, @Nullable Paint drawingPaint) { - - this.canvasWidth = canvas.getWidth(); - this.canvasHeight = canvas.getHeight(); - - updateMatrix(); - - canvas.save(); - - drawContent(canvas, drawingPaint); - - if (isSelected()) { - // get alpha from drawingPaint - int storedAlpha = borderPaint.getAlpha(); - if (drawingPaint != null) { - borderPaint.setAlpha(drawingPaint.getAlpha()); - } - drawSelectedBg(canvas); - // restore border alpha - borderPaint.setAlpha(storedAlpha); - } - - canvas.restore(); - } - - private void drawSelectedBg(Canvas canvas) { - matrix.mapPoints(destPoints, srcPoints); - //noinspection Range - canvas.drawLines(destPoints, 0, 8, borderPaint); - //noinspection Range - canvas.drawLines(destPoints, 2, 8, borderPaint); - } - - @NonNull - public Layer getLayer() { - return layer; - } - - public void setBorderPaint(@NonNull Paint borderPaint) { - this.borderPaint = borderPaint; - } - - protected abstract void drawContent(@NonNull Canvas canvas, @Nullable Paint drawingPaint); - - public abstract int getWidth(); - - public abstract int getHeight(); - - public void release() { - // free resources here - } - - public void updateEntity() {} - - @Override - protected void finalize() throws Throwable { - try { - release(); - } finally { - //noinspection ThrowFromFinallyBlock - super.finalize(); - } - } -} \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/scribbles/widget/entity/TextEntity.java b/src/org/thoughtcrime/securesms/scribbles/widget/entity/TextEntity.java deleted file mode 100644 index 73bfd315e..000000000 --- a/src/org/thoughtcrime/securesms/scribbles/widget/entity/TextEntity.java +++ /dev/null @@ -1,189 +0,0 @@ -/** - * Copyright (c) 2016 UPTech - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package org.thoughtcrime.securesms.scribbles.widget.entity; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.PointF; -import android.support.annotation.IntRange; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.Layout; -import android.text.StaticLayout; -import android.text.TextPaint; - -import org.thoughtcrime.securesms.scribbles.viewmodel.TextLayer; - - -public class TextEntity extends MotionEntity { - - private final TextPaint textPaint; - - @Nullable - private Bitmap bitmap; - - public TextEntity(@NonNull TextLayer textLayer, - @IntRange(from = 1) int canvasWidth, - @IntRange(from = 1) int canvasHeight) - { - super(textLayer, canvasWidth, canvasHeight); - this.textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); - - updateEntity(false); - } - - private void updateEntity(boolean moveToPreviousCenter) { - // save previous center - PointF oldCenter = absoluteCenter(); - - Bitmap newBmp = createBitmap(getLayer(), bitmap); - - // recycle previous bitmap (if not reused) as soon as possible - if (bitmap != null && bitmap != newBmp && !bitmap.isRecycled()) { - bitmap.recycle(); - } - - this.bitmap = newBmp; - - float width = bitmap.getWidth(); - float height = bitmap.getHeight(); - - @SuppressWarnings("UnnecessaryLocalVariable") - float widthAspect = 1.0F * canvasWidth / width; - - // for text we always match text width with parent width - this.holyScale = widthAspect; - - // initial position of the entity - srcPoints[0] = 0; - srcPoints[1] = 0; - srcPoints[2] = width; - srcPoints[3] = 0; - srcPoints[4] = width; - srcPoints[5] = height; - srcPoints[6] = 0; - srcPoints[7] = height; - srcPoints[8] = 0; - srcPoints[8] = 0; - - if (moveToPreviousCenter) { - // move to previous center - moveCenterTo(oldCenter); - } - } - - /** - * If reuseBmp is not null, and size of the new bitmap matches the size of the reuseBmp, - * new bitmap won't be created, reuseBmp it will be reused instead - * - * @param textLayer text to draw - * @param reuseBmp the bitmap that will be reused - * @return bitmap with the text - */ - @NonNull - private Bitmap createBitmap(@NonNull TextLayer textLayer, @Nullable Bitmap reuseBmp) { - - int boundsWidth = canvasWidth; - - // init params - size, color, typeface - textPaint.setStyle(Paint.Style.FILL); - textPaint.setTextSize(textLayer.getFont().getSize() * canvasWidth); - textPaint.setColor(textLayer.getFont().getColor()); -// textPaint.setTypeface(fontProvider.getTypeface(textLayer.getFont().getTypeface())); - - // drawing text guide : http://ivankocijan.xyz/android-drawing-multiline-text-on-canvas/ - // Static layout which will be drawn on canvas - StaticLayout sl = new StaticLayout( - textLayer.getText(), // - text which will be drawn - textPaint, - boundsWidth, // - width of the layout - Layout.Alignment.ALIGN_CENTER, // - layout alignment - 1, // 1 - text spacing multiply - 1, // 1 - text spacing add - true); // true - include padding - - // calculate height for the entity, min - Limits.MIN_BITMAP_HEIGHT - int boundsHeight = sl.getHeight(); - - // create bitmap not smaller than TextLayer.Limits.MIN_BITMAP_HEIGHT - int bmpHeight = (int) (canvasHeight * Math.max(TextLayer.Limits.MIN_BITMAP_HEIGHT, - 1.0F * boundsHeight / canvasHeight)); - - // create bitmap where text will be drawn - Bitmap bmp; - if (reuseBmp != null && reuseBmp.getWidth() == boundsWidth - && reuseBmp.getHeight() == bmpHeight) { - // if previous bitmap exists, and it's width/height is the same - reuse it - bmp = reuseBmp; - bmp.eraseColor(Color.TRANSPARENT); // erase color when reusing - } else { - bmp = Bitmap.createBitmap(boundsWidth, bmpHeight, Bitmap.Config.ARGB_8888); - } - - Canvas canvas = new Canvas(bmp); - canvas.save(); - - // move text to center if bitmap is bigger that text - if (boundsHeight < bmpHeight) { - //calculate Y coordinate - In this case we want to draw the text in the - //center of the canvas so we move Y coordinate to center. - float textYCoordinate = (bmpHeight - boundsHeight) / 2; - canvas.translate(0, textYCoordinate); - } - - //draws static layout on canvas - sl.draw(canvas); - canvas.restore(); - - return bmp; - } - - @Override - @NonNull - public TextLayer getLayer() { - return (TextLayer) layer; - } - - @Override - protected void drawContent(@NonNull Canvas canvas, @Nullable Paint drawingPaint) { - if (bitmap != null) { - canvas.drawBitmap(bitmap, matrix, drawingPaint); - } - } - - @Override - public int getWidth() { - return bitmap != null ? bitmap.getWidth() : 0; - } - - @Override - public int getHeight() { - return bitmap != null ? bitmap.getHeight() : 0; - } - - @Override - public void updateEntity() { - updateEntity(true); - } -} \ No newline at end of file