summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjinwu <jinwu@codeaurora.org>2017-04-07 13:27:48 +0800
committerjinwu <jinwu@codeaurora.org>2017-04-10 11:24:45 +0800
commit4fafa7a04ab78f91bbbf59c5b722a84a9b62f85c (patch)
treefddbf3ccafbd5a8a4be79775a0b22baa30ad848e
parent348658059575aa7a3bd722a1f9b06d0683225e9c (diff)
downloadandroid_packages_apps_Gallery2-4fafa7a04ab78f91bbbf59c5b722a84a9b62f85c.tar.gz
android_packages_apps_Gallery2-4fafa7a04ab78f91bbbf59c5b722a84a9b62f85c.tar.bz2
android_packages_apps_Gallery2-4fafa7a04ab78f91bbbf59c5b722a84a9b62f85c.zip
SnapdragonGallery: update source code
Update the newest source code from N to O. Change-Id: I4404638c3111c40bb5d182c770383d9d4760eec2 CRs-Fixed: 2021069
-rw-r--r--Android.mk2
-rwxr-xr-xAndroidManifest.xml9
-rw-r--r--jni/filters/filters.h1
-rw-r--r--res/drawable-hdpi/blackboard.pngbin0 -> 12231 bytes
-rw-r--r--res/drawable-hdpi/bw.pngbin0 -> 13812 bytes
-rw-r--r--res/drawable-hdpi/motion.pngbin0 -> 13189 bytes
-rw-r--r--res/drawable-hdpi/negative.pngbin0 -> 19656 bytes
-rw-r--r--res/drawable-hdpi/posterize.pngbin0 -> 16930 bytes
-rw-r--r--res/drawable-hdpi/whiteboard.pngbin0 -> 13018 bytes
-rw-r--r--res/drawable-hdpi/zoom.pngbin0 -> 17337 bytes
-rw-r--r--res/drawable-xhdpi/blackboard.pngbin0 -> 24610 bytes
-rw-r--r--res/drawable-xhdpi/bw.pngbin0 -> 30239 bytes
-rw-r--r--res/drawable-xhdpi/motion.pngbin0 -> 27015 bytes
-rw-r--r--res/drawable-xhdpi/negative.pngbin0 -> 44515 bytes
-rw-r--r--res/drawable-xhdpi/none.pngbin0 -> 44479 bytes
-rw-r--r--res/drawable-xhdpi/posterize.pngbin0 -> 37259 bytes
-rw-r--r--res/drawable-xhdpi/three_d.pngbin0 -> 2639 bytes
-rw-r--r--res/drawable-xhdpi/whiteboard.pngbin0 -> 26494 bytes
-rw-r--r--res/drawable-xhdpi/zoom.pngbin0 -> 37610 bytes
-rw-r--r--res/drawable-xxhdpi/blackboard.pngbin0 -> 37472 bytes
-rw-r--r--res/drawable-xxhdpi/bw.pngbin0 -> 52504 bytes
-rw-r--r--res/drawable-xxhdpi/motion.pngbin0 -> 43611 bytes
-rw-r--r--res/drawable-xxhdpi/negative.pngbin0 -> 78232 bytes
-rw-r--r--res/drawable-xxhdpi/posterize.pngbin0 -> 63763 bytes
-rw-r--r--res/drawable-xxhdpi/three_d.pngbin0 -> 5794 bytes
-rw-r--r--res/drawable-xxhdpi/whiteboard.pngbin0 -> 38273 bytes
-rw-r--r--res/drawable-xxhdpi/zoom.pngbin0 -> 63260 bytes
-rw-r--r--res/drawable/arrow.xml35
-rw-r--r--res/drawable/arrow_down.xml35
-rw-r--r--res/drawable/filtershow_add_new.pngbin0 -> 1608 bytes
-rw-r--r--res/drawable/ic_watermark.xml48
-rw-r--r--res/drawable/ic_watermark_emotion.xml61
-rw-r--r--res/drawable/ic_watermark_food.xml68
-rw-r--r--res/drawable/ic_watermark_location.xml34
-rw-r--r--res/drawable/ic_watermark_selected.xml48
-rw-r--r--res/drawable/ic_watermark_time.xml142
-rw-r--r--res/drawable/ic_watermark_weather.xml82
-rw-r--r--res/drawable/icon_artistic_sun.xml93
-rw-r--r--res/drawable/icon_calendar.xml35
-rw-r--r--res/drawable/icon_cheers.xml94
-rw-r--r--res/drawable/icon_city.xml43
-rw-r--r--res/drawable/icon_cry.xml40
-rw-r--r--res/drawable/icon_cry_color.xml56
-rw-r--r--res/drawable/icon_fork_and_knife.xml34
-rw-r--r--res/drawable/icon_happy.xml96
-rw-r--r--res/drawable/icon_happy_color.xml117
-rw-r--r--res/drawable/icon_hello.xml39
-rw-r--r--res/drawable/icon_hourglass.xml48
-rw-r--r--res/drawable/icon_party.xml73
-rw-r--r--res/drawable/icon_peace.xml92
-rw-r--r--res/drawable/icon_pin.xml45
-rw-r--r--res/drawable/icon_rain.xml38
-rw-r--r--res/drawable/icon_snow.xml47
-rw-r--r--res/drawable/icon_stamp.xml128
-rw-r--r--res/drawable/icon_sun.xml36
-rw-r--r--res/drawable/icon_sunrise.xml55
-rw-r--r--res/drawable/icon_tea_time.xml139
-rw-r--r--res/drawable/icon_timestamp.xml43
-rw-r--r--res/drawable/icon_tools.xml42
-rw-r--r--res/drawable/icon_yum.xml34
-rw-r--r--res/drawable/ref_city.pngbin0 -> 144399 bytes
-rw-r--r--res/drawable/ref_flowers.pngbin0 -> 207633 bytes
-rw-r--r--res/drawable/watermark.xml33
-rw-r--r--res/layout-land/filtershow_presets_dialog.xml168
-rw-r--r--res/layout/activity_three_dimensional.xml84
-rw-r--r--res/layout/do_not_show_again_dialog.xml30
-rw-r--r--res/layout/filtershow_actionbar_dualcam_fusion.xml45
-rw-r--r--res/layout/filtershow_bottom_panel.xml14
-rw-r--r--res/layout/filtershow_category_panel_two.xml100
-rw-r--r--res/layout/filtershow_default_edittext.xml44
-rw-r--r--res/layout/filtershow_presets_dialog.xml166
-rw-r--r--res/layout/filtershow_watermark.xml53
-rw-r--r--res/layout/mediapicker_list_item.xml43
-rw-r--r--res/layout/mediapicker_panel.xml98
-rw-r--r--res/layout/movie_view.xml7
-rw-r--r--res/layout/three_d_button.xml52
-rw-r--r--res/menu/filtershow_menu_edit.xml38
-rwxr-xr-xres/values-zh-rCN/filtershow_strings.xml24
-rw-r--r--res/values/attrs.xml3
-rwxr-xr-xres/values/dimens.xml2
-rw-r--r--res/values/filtershow_color.xml5
-rw-r--r--res/values/filtershow_strings.xml41
-rw-r--r--res/values/filtershow_styles.xml8
-rw-r--r--res/values/filtershow_values.xml4
-rw-r--r--res/values/mediapicker_colors.xml38
-rw-r--r--res/values/mediapicker_dimens.xml38
-rw-r--r--src/com/android/gallery3d/app/AbstractGalleryActivity.java11
-rwxr-xr-xsrc/com/android/gallery3d/app/GalleryActivity.java28
-rw-r--r--src/com/android/gallery3d/app/MovieActivity.java11
-rw-r--r--src/com/android/gallery3d/app/MoviePlayer.java30
-rwxr-xr-xsrc/com/android/gallery3d/app/PhotoPage.java120
-rw-r--r--src/com/android/gallery3d/app/ThreeDButton.java109
-rw-r--r--src/com/android/gallery3d/app/dualcam3d/Effect.java211
-rw-r--r--src/com/android/gallery3d/app/dualcam3d/GLView.java186
-rw-r--r--src/com/android/gallery3d/app/dualcam3d/ThreeDimensionalActivity.java190
-rw-r--r--src/com/android/gallery3d/app/dualcam3d/gl/Error.java44
-rw-r--r--src/com/android/gallery3d/app/dualcam3d/gl/Mesh.java149
-rw-r--r--src/com/android/gallery3d/app/dualcam3d/gl/Renderer.java178
-rw-r--r--src/com/android/gallery3d/app/dualcam3d/gl/Settings.java47
-rw-r--r--src/com/android/gallery3d/app/dualcam3d/gl/Shader.java105
-rw-r--r--src/com/android/gallery3d/app/dualcam3d/gl/Texture.java65
-rw-r--r--src/com/android/gallery3d/app/dualcam3d/mpo/Task.java231
-rw-r--r--src/com/android/gallery3d/app/dualcam3d/threed/Controller.java182
-rw-r--r--src/com/android/gallery3d/app/dualcam3d/threed/Gyro.java115
-rwxr-xr-xsrc/com/android/gallery3d/data/TimeLineTitleMediaItem.java6
-rwxr-xr-xsrc/com/android/gallery3d/filtershow/FilterShowActivity.java667
-rw-r--r--src/com/android/gallery3d/filtershow/cache/ImageLoader.java100
-rw-r--r--src/com/android/gallery3d/filtershow/category/Action.java63
-rw-r--r--src/com/android/gallery3d/filtershow/category/CategoryAdapter.java33
-rw-r--r--src/com/android/gallery3d/filtershow/category/CategoryPanel.java13
-rw-r--r--src/com/android/gallery3d/filtershow/category/CategoryPanelLevelTwo.java156
-rw-r--r--src/com/android/gallery3d/filtershow/category/CategoryView.java88
-rwxr-xr-xsrc/com/android/gallery3d/filtershow/category/MainPanel.java151
-rw-r--r--src/com/android/gallery3d/filtershow/category/WaterMarkTimeView.java68
-rw-r--r--src/com/android/gallery3d/filtershow/category/WaterMarkView.java522
-rw-r--r--src/com/android/gallery3d/filtershow/data/FilterPresetDBHelper.java103
-rw-r--r--src/com/android/gallery3d/filtershow/data/FilterPresetSource.java162
-rw-r--r--src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java189
-rw-r--r--src/com/android/gallery3d/filtershow/editors/EditorTruePortraitFusion.java8
-rw-r--r--src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java329
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterPresetRepresentation.java163
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java27
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterWatermarkRepresentation.java204
-rwxr-xr-xsrc/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java14
-rwxr-xr-xsrc/com/android/gallery3d/filtershow/filters/ImageFilterDualCamSketch.java43
-rwxr-xr-xsrc/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java41
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterPreset.java99
-rw-r--r--src/com/android/gallery3d/filtershow/filters/SaveWaterMark.java199
-rwxr-xr-xsrc/com/android/gallery3d/filtershow/filters/TrueScannerActs.java35
-rwxr-xr-xsrc/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java41
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java4
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageTruePortraitFusion.java6
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/MasterImage.java42
-rw-r--r--src/com/android/gallery3d/filtershow/mediapicker/MediaAdapter.java177
-rw-r--r--src/com/android/gallery3d/filtershow/mediapicker/MediaPicker.java269
-rw-r--r--src/com/android/gallery3d/filtershow/mediapicker/MediaPickerFragment.java309
-rw-r--r--src/com/android/gallery3d/filtershow/mediapicker/SelectedImageView.java99
-rw-r--r--src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageDisplayTask.java69
-rw-r--r--src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderConfig.java202
-rw-r--r--src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderHandle.java91
-rw-r--r--src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderInfo.java57
-rw-r--r--src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderInstance.java93
-rw-r--r--src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderOptions.java58
-rw-r--r--src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderStub.java52
-rw-r--r--src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderTask.java258
-rw-r--r--src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageViewImpl.java153
-rw-r--r--src/com/android/gallery3d/filtershow/mediapicker/imageloader/ThreadFactoryImpl.java51
-rw-r--r--src/com/android/gallery3d/filtershow/mediapicker/imageloader/ViewScaleType.java54
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java1
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java28
-rwxr-xr-xsrc/com/android/gallery3d/filtershow/pipeline/ProcessingService.java14
-rw-r--r--src/com/android/gallery3d/filtershow/presets/PresetManagementDialog.java43
-rw-r--r--src/com/android/gallery3d/filtershow/tools/DualCameraNativeEngine.java62
-rw-r--r--src/com/android/gallery3d/filtershow/tools/FilterGeneratorNativeEngine.java75
-rw-r--r--src/com/android/gallery3d/filtershow/tools/SaveImage.java16
-rw-r--r--src/com/android/gallery3d/filtershow/ui/DoNotShowAgainDialog.java34
-rw-r--r--src/com/android/gallery3d/filtershow/ui/ExportDialog.java17
-rw-r--r--src/com/android/gallery3d/gadget/WidgetService.java7
-rw-r--r--src/com/android/gallery3d/mpo/MpoParser.java71
-rw-r--r--src/com/android/gallery3d/ui/ActionModeHandler.java1
-rw-r--r--src/com/android/gallery3d/ui/MenuExecutor.java1
-rw-r--r--src/com/android/gallery3d/ui/TileImageView.java4
-rw-r--r--src/org/codeaurora/gallery3d/video/SettingsActivity.java8
-rw-r--r--src/org/codeaurora/gallery3d/video/SpeakerHooker.java8
-rw-r--r--src/org/codeaurora/gallery3d/video/VideoSnapshotExt.java7
165 files changed, 10894 insertions, 253 deletions
diff --git a/Android.mk b/Android.mk
index cf42b2f7c..a37b7b581 100644
--- a/Android.mk
+++ b/Android.mk
@@ -42,7 +42,7 @@ LOCAL_OVERRIDES_PACKAGES := Gallery Gallery3D GalleryNew3D Gallery2
LOCAL_SDK_VERSION := current
LOCAL_JNI_SHARED_LIBRARIES := libjni_gallery_eglfence libjni_gallery_filters libjni_gallery_jpegstream
-LOCAL_SHARED_LIBRARIES += libjni_dualcamera libjni_trueportrait
+LOCAL_SHARED_LIBRARIES += libjni_dualcamera libjni_trueportrait libjni_filtergenerator
LOCAL_REQUIRED_MODULES := libts_detected_face_jni libts_face_beautify_jni
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index bfdd8f77a..ad336fca6 100755
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (c) 2010-2014, 2016, The Linux Foundation. All rights reserved.
+<!-- Copyright (c) 2010-2014, 2016-2017 The Linux Foundation. All rights reserved.
Not a Contribution.
Copyright (C) 2007 The Android Open Source Project
@@ -103,7 +103,7 @@
<activity android:name="com.android.gallery3d.app.GalleryActivity"
android:theme="@style/AppTheme"
- android:configChanges="keyboardHidden|orientation|screenSize">
+ android:configChanges="keyboardHidden|orientation|screenSize|locale|fontScale|layoutDirection">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
@@ -272,7 +272,7 @@
<activity
android:name="com.android.gallery3d.filtershow.FilterShowActivity"
android:theme="@style/Theme.FilterShow"
- android:configChanges="keyboardHidden|orientation|screenSize|locale|layoutDirection">
+ android:configChanges="keyboardHidden|orientation|screenSize|layoutDirection">
<intent-filter>
<action android:name="android.intent.action.EDIT" />
<category android:name="android.intent.category.DEFAULT" />
@@ -399,5 +399,8 @@
android:theme="@android:style/Theme.Material.Light"
android:configChanges="orientation|keyboardHidden|screenSize|mnc|mcc">
</activity>
+ <activity android:name="com.android.gallery3d.app.dualcam3d.ThreeDimensionalActivity"
+ android:configChanges="orientation|screenSize|layoutDirection">
+ </activity>
</application>
</manifest>
diff --git a/jni/filters/filters.h b/jni/filters/filters.h
index 14b69cdd4..3f8c3a07e 100644
--- a/jni/filters/filters.h
+++ b/jni/filters/filters.h
@@ -19,6 +19,7 @@
#include <jni.h>
#include <string.h>
+#include <stdlib.h>
#include <android/log.h>
#include <android/bitmap.h>
diff --git a/res/drawable-hdpi/blackboard.png b/res/drawable-hdpi/blackboard.png
new file mode 100644
index 000000000..6cb6e31d4
--- /dev/null
+++ b/res/drawable-hdpi/blackboard.png
Binary files differ
diff --git a/res/drawable-hdpi/bw.png b/res/drawable-hdpi/bw.png
new file mode 100644
index 000000000..fa8175473
--- /dev/null
+++ b/res/drawable-hdpi/bw.png
Binary files differ
diff --git a/res/drawable-hdpi/motion.png b/res/drawable-hdpi/motion.png
new file mode 100644
index 000000000..1a03479a2
--- /dev/null
+++ b/res/drawable-hdpi/motion.png
Binary files differ
diff --git a/res/drawable-hdpi/negative.png b/res/drawable-hdpi/negative.png
new file mode 100644
index 000000000..b4989d4af
--- /dev/null
+++ b/res/drawable-hdpi/negative.png
Binary files differ
diff --git a/res/drawable-hdpi/posterize.png b/res/drawable-hdpi/posterize.png
new file mode 100644
index 000000000..042b686c1
--- /dev/null
+++ b/res/drawable-hdpi/posterize.png
Binary files differ
diff --git a/res/drawable-hdpi/whiteboard.png b/res/drawable-hdpi/whiteboard.png
new file mode 100644
index 000000000..584da40a1
--- /dev/null
+++ b/res/drawable-hdpi/whiteboard.png
Binary files differ
diff --git a/res/drawable-hdpi/zoom.png b/res/drawable-hdpi/zoom.png
new file mode 100644
index 000000000..ea1211f29
--- /dev/null
+++ b/res/drawable-hdpi/zoom.png
Binary files differ
diff --git a/res/drawable-xhdpi/blackboard.png b/res/drawable-xhdpi/blackboard.png
new file mode 100644
index 000000000..287a6f717
--- /dev/null
+++ b/res/drawable-xhdpi/blackboard.png
Binary files differ
diff --git a/res/drawable-xhdpi/bw.png b/res/drawable-xhdpi/bw.png
new file mode 100644
index 000000000..d0052d162
--- /dev/null
+++ b/res/drawable-xhdpi/bw.png
Binary files differ
diff --git a/res/drawable-xhdpi/motion.png b/res/drawable-xhdpi/motion.png
new file mode 100644
index 000000000..7d2b8a6ba
--- /dev/null
+++ b/res/drawable-xhdpi/motion.png
Binary files differ
diff --git a/res/drawable-xhdpi/negative.png b/res/drawable-xhdpi/negative.png
new file mode 100644
index 000000000..a1eab0da7
--- /dev/null
+++ b/res/drawable-xhdpi/negative.png
Binary files differ
diff --git a/res/drawable-xhdpi/none.png b/res/drawable-xhdpi/none.png
new file mode 100644
index 000000000..703556222
--- /dev/null
+++ b/res/drawable-xhdpi/none.png
Binary files differ
diff --git a/res/drawable-xhdpi/posterize.png b/res/drawable-xhdpi/posterize.png
new file mode 100644
index 000000000..157ad30e3
--- /dev/null
+++ b/res/drawable-xhdpi/posterize.png
Binary files differ
diff --git a/res/drawable-xhdpi/three_d.png b/res/drawable-xhdpi/three_d.png
new file mode 100644
index 000000000..ab8d4df54
--- /dev/null
+++ b/res/drawable-xhdpi/three_d.png
Binary files differ
diff --git a/res/drawable-xhdpi/whiteboard.png b/res/drawable-xhdpi/whiteboard.png
new file mode 100644
index 000000000..1225d335f
--- /dev/null
+++ b/res/drawable-xhdpi/whiteboard.png
Binary files differ
diff --git a/res/drawable-xhdpi/zoom.png b/res/drawable-xhdpi/zoom.png
new file mode 100644
index 000000000..f3eac3d73
--- /dev/null
+++ b/res/drawable-xhdpi/zoom.png
Binary files differ
diff --git a/res/drawable-xxhdpi/blackboard.png b/res/drawable-xxhdpi/blackboard.png
new file mode 100644
index 000000000..0881d3b4c
--- /dev/null
+++ b/res/drawable-xxhdpi/blackboard.png
Binary files differ
diff --git a/res/drawable-xxhdpi/bw.png b/res/drawable-xxhdpi/bw.png
new file mode 100644
index 000000000..a2accdd11
--- /dev/null
+++ b/res/drawable-xxhdpi/bw.png
Binary files differ
diff --git a/res/drawable-xxhdpi/motion.png b/res/drawable-xxhdpi/motion.png
new file mode 100644
index 000000000..7eb4c2cff
--- /dev/null
+++ b/res/drawable-xxhdpi/motion.png
Binary files differ
diff --git a/res/drawable-xxhdpi/negative.png b/res/drawable-xxhdpi/negative.png
new file mode 100644
index 000000000..90a609fd0
--- /dev/null
+++ b/res/drawable-xxhdpi/negative.png
Binary files differ
diff --git a/res/drawable-xxhdpi/posterize.png b/res/drawable-xxhdpi/posterize.png
new file mode 100644
index 000000000..0bc95dffc
--- /dev/null
+++ b/res/drawable-xxhdpi/posterize.png
Binary files differ
diff --git a/res/drawable-xxhdpi/three_d.png b/res/drawable-xxhdpi/three_d.png
new file mode 100644
index 000000000..ab58b4553
--- /dev/null
+++ b/res/drawable-xxhdpi/three_d.png
Binary files differ
diff --git a/res/drawable-xxhdpi/whiteboard.png b/res/drawable-xxhdpi/whiteboard.png
new file mode 100644
index 000000000..f584c3fce
--- /dev/null
+++ b/res/drawable-xxhdpi/whiteboard.png
Binary files differ
diff --git a/res/drawable-xxhdpi/zoom.png b/res/drawable-xxhdpi/zoom.png
new file mode 100644
index 000000000..2c1dd02da
--- /dev/null
+++ b/res/drawable-xxhdpi/zoom.png
Binary files differ
diff --git a/res/drawable/arrow.xml b/res/drawable/arrow.xml
new file mode 100644
index 000000000..4f8d92c99
--- /dev/null
+++ b/res/drawable/arrow.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+
+<vector android:height="24dp" android:viewportHeight="50.0"
+ android:viewportWidth="60.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FFFFFF"
+ android:pathData="M0,25.001l8.975,0l13.434,-14.917l0.18,0l13.433,14.917l8.977,0l-22.41,-25.001l-0.18,0z"
+ android:strokeColor="#00000000" android:strokeWidth="1"/>
+</vector>
diff --git a/res/drawable/arrow_down.xml b/res/drawable/arrow_down.xml
new file mode 100644
index 000000000..61afba081
--- /dev/null
+++ b/res/drawable/arrow_down.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+
+<vector android:height="24dp" android:viewportHeight="50.0"
+ android:viewportWidth="60.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FFFFFF"
+ android:pathData="M0,-0l8.975,0l13.434,14.917l0.18,0l13.433,-14.917l8.977,0l-22.41,25.001l-0.18,0z"
+ android:strokeColor="#00000000" android:strokeWidth="1"/>
+</vector>
diff --git a/res/drawable/filtershow_add_new.png b/res/drawable/filtershow_add_new.png
new file mode 100644
index 000000000..9fe060edb
--- /dev/null
+++ b/res/drawable/filtershow_add_new.png
Binary files differ
diff --git a/res/drawable/ic_watermark.xml b/res/drawable/ic_watermark.xml
new file mode 100644
index 000000000..1c579413f
--- /dev/null
+++ b/res/drawable/ic_watermark.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="25"
+ android:viewportHeight="27">
+
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="2.13350288"
+ android:pathData="M14.9362,15.8471 L14.9362,11.5098
+C16.5957,10.3574,18.5791,8.83929,18.5791,6.57669
+C18.5791,3.01208,15.8574,2,12.5,2 C9.14256,2,6.42093,3.01208,6.42093,6.57669
+C6.42093,8.83929,8.40383,10.3574,10.0633,11.5098 L10.0633,15.8471 L2,17.49 L2,25
+L11.3331,25 L13.6669,25 L23,25 L23,17.49 L14.9362,15.8471 L14.9362,15.8471 Z" />
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="0.9482235"
+ android:pathData="M3,21 L23,21" />
+</vector> \ No newline at end of file
diff --git a/res/drawable/ic_watermark_emotion.xml b/res/drawable/ic_watermark_emotion.xml
new file mode 100644
index 000000000..bed9457cd
--- /dev/null
+++ b/res/drawable/ic_watermark_emotion.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="1008"
+ android:viewportHeight="1008">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M910.4,497.6c0,230.6-187.1,417.6-417.7,417.5C264.8,915,75.2,730.5,75.4,497
+C75.7,261.1,270.2,74.7,502.8,80C728.9,85.3,911,271.3,910.4,497.6z
+M493.3,112.1c-210.1-0.4-385.5,170-385.8,385
+c-0.3,214.3,173.7,386,385.4,385.9c214.2-0.1,381.8-173.3,385.5-378.3C882.3,289.8,708.1,112.1,493.3,112.1z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M482.3,742.1c-42.7-0.4-93.1-11.6-138.9-39.9c-29.1-17.9-52.7-41.2-67.1-72.7
+c-7.2-15.8-10.8-32.5-11.1-49.8c-0.2-9.9,6.8-17.5,16.3-18c9.6-0.5,17.5,6.1,17.8,16.2c1.5,42.6,25.7,70.9,59.1,92.9
+c31.5,20.8,66.7,31.1,104,35.2c38.9,4.3,77.2,0.9,114.4-11.2c34-11,64.4-28,87.3-56.4c13.9-17.2,22.1-36.6,22.3-59.1
+c0.1-10.7,7.7-17.9,17.7-17.7c9.9,0.2,16.9,7.7,16.7,18.5c-0.6,34.3-14.2,63.3-37,88.2c-28.3,30.8-63.9,49.5-103.5,61.4
+C551.7,738.3,522.6,742.1,482.3,742.1z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M478.9,398.4c0,51.8-41.8,93.4-93.9,93.4c-51.1,0-92.9-42.1-92.9-93.5c0-51.6,41.9-93.4,93.5-93.4
+C437.2,305,478.9,346.7,478.9,398.4z
+M385.4,336.9c-33.5,0.1-61.5,28.1-61.3,61.5c0.2,33.7,27.9,61.3,61.6,61.2
+c33.6-0.1,61.3-27.8,61.3-61.4C446.9,364.7,418.9,336.9,385.4,336.9z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M600.5,304.9c51.6,0.1,93.5,42,93.4,93.5c-0.1,52.1-42.3,93.8-95.1,93.2c-52.5-0.6-92.6-44.3-91.9-95.4
+C507.7,346.3,549.6,304.8,600.5,304.9z
+M600.7,336.9c-33.4-0.1-61.5,27.6-61.6,60.8c-0.1,34,27.1,61.7,60.8,62
+c33.7,0.3,61.5-27.1,62-60.9C662.4,365.5,634.2,337.1,600.7,336.9z" />
+</vector> \ No newline at end of file
diff --git a/res/drawable/ic_watermark_food.xml b/res/drawable/ic_watermark_food.xml
new file mode 100644
index 000000000..a5ecfcc28
--- /dev/null
+++ b/res/drawable/ic_watermark_food.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="1008dp"
+ android:height="1008dp"
+ android:viewportWidth="1008"
+ android:viewportHeight="1008">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M222,97.3c35.6,31.4,72.7,63.7,109.2,96.6c36.4,32.8,72.3,66.1,108.2,99.4c19.9,18.4,34.5,40,39.1,67.4
+c3.4,20.9,0.9,41.1-6,61c-0.7,2-1.5,4-2.4,6.6c23.4,21.8,46.8,43.7,70.7,65.9c9.1-8.5,18.1-16.8,27.1-25.2
+c16.9-15.8,33.9-31.5,50.7-47.4c1.2-1.1,2.2-3.8,1.7-5.3c-12.1-38-10.3-76.1,3.2-112.8c32.2-87.6,92.7-146.4,183-172.3
+c37.2-10.7,75-9.9,110.8,7c41.7,19.6,66,53.1,73.6,98.1c7.7,45.9-2.9,88.9-25,129c-33.5,61-82.5,104.9-148.3,128.6
+c-37.9,13.6-76.6,16.4-115.7,3.9c-1.4-0.4-3.8,0-4.7,0.9c-23.5,25-46.8,50.1-70.6,75.6c8.9,8.3,17.6,16.5,26.4,24.6
+c64.7,60.3,129.2,120.8,194.3,180.7c29.8,27.4,31.4,68.2,13.5,95.3c-26.6,40.5-82.3,44.8-115.9,8.8
+C681.2,815.3,617.7,747,554.1,678.7c-4.1-4.4-8.2-8.7-12.6-13.4c-10.5,11.2-20.7,22.1-30.9,33.1
+c-53.9,57.9-107.8,115.9-161.8,173.7c-20.1,21.4-45,29-73.2,21.6c-27.1-7.1-45-25.1-51.7-52.4c-7-28.4,0.9-53,22.4-73
+c68.3-63.6,136.5-127.1,204.8-190.7c1.4-1.3,2.8-2.7,4.5-4.4c-8-8.6-15.8-17-23.6-25.4c-12-12.9-24.2-25.8-36-38.8
+c-2.4-2.7-4.3-3-7.6-1.8c-27.8,10.4-55.8,11.8-83.9,1c-15.3-5.9-28.9-14.8-40-26.7C224.8,438.7,185.1,396,146,352.8
+c-27.7-30.6-54.6-62-81.9-93c-1.1-1.2-2.1-2.5-1.8-2.8C115.3,203.9,168.3,150.9,222,97.3z
+M661,427.1c-1.1,0.8-2.5,1.7-3.7,2.8
+c-36,33.4-72,66.9-107.9,100.4C474.5,600,399.7,669.8,324.9,739.5c-19.6,18.3-39.4,36.3-58.8,54.9c-17,16.3-16.3,42.2,1,58.8
+c16,15.3,42,14.1,57.4-2.5c36.7-39.5,73.5-79,110.3-118.5c75.4-80.9,150.7-161.8,226.1-242.7c10.1-10.8,20.2-21.6,29.7-31.8
+c9,3.6,17.1,7.7,25.6,10.3c30.4,9,60.5,5.9,89.7-4.7c60.5-21.8,104.7-62.4,134.1-119.1c16.5-31.8,25-65.7,18.8-101.8
+c-6.4-37.7-27-64.7-63.4-78.2c-30.7-11.4-61.9-9.1-92.1,1.4c-69.6,24.1-118.4,71.1-146.1,139C640.8,345,638.1,386.2,661,427.1z
+M205.7,157.2c55.8,54.8,111.5,109.6,166.8,164c-5.9,6.2-11.2,11.8-16.9,17.7C300,284.3,244.5,229.7,189.5,175.8
+c-6,6-11.5,11.4-17.1,17.1C227.5,247,283,301.5,337.9,355.5c-6.1,6.2-12,12-18.4,18.4c-54.7-54.7-109.6-109.6-164.2-164.2
+c-4.9,4.9-10,10-15.2,15.2c54.2,55.2,108.7,110.6,162.8,165.7c-5.9,5.9-11.4,11.5-17.3,17.4c-54.4-55.4-109.2-111.1-163.5-166.3
+c-5.5,5.6-10.9,10.9-16.4,16.5c0.6,0.7,1.6,1.9,2.5,3c29.1,32.9,57.9,66.2,87.5,98.7c30.7,33.8,61.6,67.3,93.4,100.1
+c21,21.7,47.5,28.2,76.7,20.2c11.7-3.2,22.7-8.9,34.7-13.7c25.6,27.5,52.2,56,78.9,84.7c12.6-11.7,24.8-23.1,37.3-34.8
+c-29.4-27.4-58.2-54.2-87-81.1c2.2-3.7,4.2-7,5.9-10.4c1.8-3.4,3.5-6.8,4.8-10.4c12.3-31.9,9.4-61.5-14-87.5
+c-8.4-9.4-17.6-18.2-27-26.7c-48.6-44.1-97.4-88-146.2-131.9c-10.4-9.3-21-18.4-31.4-27.5C216.6,146.3,211.4,151.5,205.7,157.2z
+M604.4,597.8c-13.6,14.6-27.1,29.1-40.6,43.6c1.7,1.9,3,3.4,4.4,4.8c44.3,47.5,88.5,95,132.8,142.5c23.3,25,46.5,49.9,69.9,74.8
+c7.8,8.4,17.9,12.1,29.2,12c16.8-0.2,31.6-10.9,37.3-26.3c6-16.1,1.9-32.6-10.9-44.6c-57.6-53.7-115.2-107.4-172.8-161
+C637.3,628.4,620.9,613.2,604.4,597.8z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M908.7,240.1c8.5,16.8,10.8,34.7,8.9,53c-6.6,64.5-59.1,123.9-122.2,138.2c-22.1,5-43.9,4.3-65-5.3
+c-0.7-0.3-1.5-0.8-3.5-1.8c51.7,0,93.1-21,127.5-56.5C888.7,332.3,908.5,290.3,908.7,240.1z" />
+</vector> \ No newline at end of file
diff --git a/res/drawable/ic_watermark_location.xml b/res/drawable/ic_watermark_location.xml
new file mode 100644
index 000000000..d430b6060
--- /dev/null
+++ b/res/drawable/ic_watermark_location.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="1008.0"
+ android:viewportWidth="1008.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FFFFFF" android:pathData="M831.5,356.4c-1,39.1 -8.9,76.5 -21.9,113.3c-16.9,48 -43.4,90.6 -72,132c-33.4,48.6 -68,96.3 -101.6,144.8c-26.1,37.6 -50.8,76.2 -69.5,118.2c-4.3,9.6 -7.8,19.5 -11.3,29.3c-6.2,17.1 -22.2,28.6 -40.5,28.7c-18.3,0.1 -35.1,-11.2 -40.6,-28.5c-11.4,-35.5 -28.8,-68 -48,-99.6c-29.6,-48.9 -63.2,-95.2 -96,-141.9c-28.5,-40.6 -57.1,-81.2 -81.5,-124.5c-22,-38.9 -37.7,-80.1 -44.2,-124.4c-9.3,-62.7 -1.5,-123.5 26.3,-180.6C277.1,128 352.5,67.8 456.6,47.9c102.9,-19.7 194.6,7.3 272.4,77.7c53.7,48.6 85.8,109.7 97.5,181.2C829.2,323.1 829.9,339.8 831.5,356.4zM233.1,360.8c0.3,4.4 0.5,12.9 1.3,21.4c4.1,43.4 17.6,83.8 38.2,122.1c21.9,40.7 48.5,78.4 74.6,116.4c33.7,49 67.8,97.7 100.4,147.4c23.4,35.6 43.6,73.2 56.6,114.2c1.6,5.2 5.5,8 10.3,8c5.3,-0.1 8.7,-2.8 10.5,-7.7c3.2,-8.6 6.1,-17.3 9.7,-25.7c17,-39.8 39.3,-76.7 63.7,-112.3c35.7,-52 72.7,-103.2 108.5,-155.2c28.3,-41 55,-82.8 72.2,-130.2c19,-52.5 24.6,-105.7 13.1,-160.5C760.6,148.2 613.6,50.3 462.8,79.2C329.7,104.7 233.1,221.4 233.1,360.8z"/>
+ <path android:fillColor="#FFFFFF" android:pathData="M368.6,344.7c0,-81.7 65.6,-147 147.6,-147c80.8,0 146.8,66.2 146.7,147.1c-0.1,81.2 -66.1,147.1 -147.3,147.1C434.4,491.9 368.6,426.1 368.6,344.7zM515.3,459.3c63.1,0 114.3,-50.8 115.1,-112.8c0.8,-61.1 -48.4,-116.3 -114.6,-116.5c-63.2,-0.2 -114.9,51.6 -114.9,114.7C400.9,407.8 452.3,459.3 515.3,459.3z"/>
+</vector>
diff --git a/res/drawable/ic_watermark_selected.xml b/res/drawable/ic_watermark_selected.xml
new file mode 100644
index 000000000..736c66bc4
--- /dev/null
+++ b/res/drawable/ic_watermark_selected.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="25"
+ android:viewportHeight="27">
+
+ <path
+ android:strokeColor="#4592F9"
+ android:strokeWidth="2.13350288"
+ android:pathData="M14.9362,15.8471 L14.9362,11.5098
+C16.5957,10.3574,18.5791,8.83929,18.5791,6.57669
+C18.5791,3.01208,15.8574,2,12.5,2 C9.14256,2,6.42093,3.01208,6.42093,6.57669
+C6.42093,8.83929,8.40383,10.3574,10.0633,11.5098 L10.0633,15.8471 L2,17.49 L2,25
+L11.3331,25 L13.6669,25 L23,25 L23,17.49 L14.9362,15.8471 L14.9362,15.8471 Z" />
+ <path
+ android:strokeColor="#4592F9"
+ android:strokeWidth="0.9482235"
+ android:pathData="M3,21 L23,21" />
+</vector> \ No newline at end of file
diff --git a/res/drawable/ic_watermark_time.xml b/res/drawable/ic_watermark_time.xml
new file mode 100644
index 000000000..9a0b9d8c5
--- /dev/null
+++ b/res/drawable/ic_watermark_time.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="360dp"
+ android:height="360dp"
+ android:viewportWidth="360"
+ android:viewportHeight="360">
+
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="12.2107"
+ android:strokeMiterLimit="10"
+ android:pathData="M180.2,330.3c-83.7,0-151.7-68.1-151.7-151.7
+S96.6,26.8,180.2,26.8s151.7,68.1,151.7,151.7S263.9,330.3,180.2,330.3z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M180.2,57.8c32.3,0,62.6,12.6,85.4,35.4c22.8,22.8,35.4,53.1,35.4,85.4s-12.6,62.6-35.4,85.4
+c-22.8,22.8-53.1,35.4-85.4,35.4s-62.6-12.6-85.4-35.4c-22.8-22.8-35.4-53.1-35.4-85.4S72,115.9,94.8,93.1
+C117.6,70.3,148,57.8,180.2,57.8
+M180.2,52.6c-69.6,0-126,56.4-126,126s56.4,126,126,126s126-56.4,126-126S249.8,52.6,180.2,52.6
+L180.2,52.6z" />
+ <path
+ android:strokeColor="#231F20"
+ android:strokeWidth="16.6991"
+ android:strokeMiterLimit="10"
+ android:pathData="M79.3,177.8" />
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="16.6991"
+ android:strokeMiterLimit="10"
+ android:pathData="M179.5,278" />
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="16.6991"
+ android:strokeMiterLimit="10"
+ android:pathData="M179.5,313.3" />
+ <path
+ android:strokeColor="#231F20"
+ android:strokeWidth="16.6991"
+ android:strokeMiterLimit="10"
+ android:pathData="M279.7,177.8" />
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="5.5664"
+ android:strokeMiterLimit="10"
+ android:pathData="M 179.2 103.7 L 179.2 82.4" />
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="5.5664"
+ android:strokeMiterLimit="10"
+ android:pathData="M 142.1 113.8 L 131.5 95.3" />
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="5.5664"
+ android:strokeMiterLimit="10"
+ android:pathData="M 115.1 141.1 L 96.7 130.4" />
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="5.5664"
+ android:strokeMiterLimit="10"
+ android:pathData="M 105.4 178.2 L 84.1 178.2" />
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="5.5664"
+ android:strokeMiterLimit="10"
+ android:pathData="M 115.5 215.2 L 97 225.9" />
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="5.5664"
+ android:strokeMiterLimit="10"
+ android:pathData="M 142.8 242.2 L 132.1 260.7" />
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="5.5664"
+ android:strokeMiterLimit="10"
+ android:pathData="M 179.9 252 L 179.9 273.3" />
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="5.5664"
+ android:strokeMiterLimit="10"
+ android:pathData="M 216.9 241.9 L 227.6 260.4" />
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="5.5664"
+ android:strokeMiterLimit="10"
+ android:pathData="M 243.9 214.6 L 262.4 225.3" />
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="5.5664"
+ android:strokeMiterLimit="10"
+ android:pathData="M 253.7 177.5 L 275 177.5" />
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="5.5664"
+ android:strokeMiterLimit="10"
+ android:pathData="M 243.6 140.5 L 262 129.8" />
+ <path
+ android:strokeColor="#231F20"
+ android:strokeWidth="5.5664"
+ android:strokeMiterLimit="10"
+ android:pathData="M 216.3 113.4 L 227 95" />
+ <path
+ android:strokeColor="#231F20"
+ android:strokeWidth="16.6991"
+ android:strokeMiterLimit="10"
+ android:pathData="M 179.5 177.8 H 179.5 V 177.8 H 179.5 V 177.8 Z" />
+ <path
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="12.2107"
+ android:strokeMiterLimit="10"
+ android:pathData="M 179.5 154.2 C 193.307118746 154.2 204.5 165.392881254 204.5 179.2 C 204.5 193.007118746 193.307118746 204.2 179.5 204.2 C 165.692881254 204.2 154.5 193.007118746 154.5 179.2 C 154.5 165.392881254 165.692881254 154.2 179.5 154.2 Z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M179.3,154.5c-2.1,6.6,59.5-80.7,59.5-80.7l-41.2,91.6L179.3,154.5z" />
+</vector> \ No newline at end of file
diff --git a/res/drawable/ic_watermark_weather.xml b/res/drawable/ic_watermark_weather.xml
new file mode 100644
index 000000000..d1477ab88
--- /dev/null
+++ b/res/drawable/ic_watermark_weather.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="1008dp"
+ android:height="1008dp"
+ android:viewportWidth="1008"
+ android:viewportHeight="1008">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M469.5,958.7c-5.9-13.1-11.4-25.3-17-37.5c-15.2-33-30.7-65.9-45.7-99c-4.8-10.6-11.7-16.6-23.2-20.3
+c-17.3-5.6-33.6-14-50.2-21.6c-3.6-1.7-6.5-2.1-10.1-0.7c-20.3,8.4-40.7,16.5-61,25.1c-29.9,12.7-59.6,25.8-89.4,38.6
+c-1.1,0.5-2.2,0.9-3.9,1.6c0.3-1.5,0.5-2.6,0.8-3.6c15.8-46.6,31.7-93.1,47.4-139.7c2-5.8,3.6-11.7,5.1-17.7
+c0.4-1.7,0.1-4.2-0.9-5.7c-17.1-26.1-30.2-54-39.4-83.8c-0.6-2-2.8-4.3-4.8-5.1c-25.6-9.7-51.2-19.3-76.9-28.7
+c-22.3-8.2-44.7-16.3-67-24.4c-1.2-0.5-2.4-1-4.5-1.9c2.4-1.4,4.3-2.4,6.2-3.4c43.7-23.5,87.4-47.1,131.3-70.5
+c4.4-2.3,6.5-5.1,7.3-10.1c6.6-40,20.9-77.3,42.3-111.7c1.8-3,1.8-5.2,0.4-8.2c-22.2-47.2-44.3-94.5-66.4-141.8
+c-0.7-1.5-1.4-3-2.4-5.2c1.7,0.5,2.9,0.9,4,1.3c49.4,19.4,98.8,38.8,148.2,58.3c3.5,1.4,6.1,1.3,9.5-0.9
+C350,215,394.6,198.4,443,192.2c3.3-0.4,4.5-2.3,5.8-4.7c19.4-37.1,38.7-74.3,58.1-111.4c4.2-8,8.4-16,13.1-25.1
+c2.3,6.8,4.3,12.5,6.2,18.2c14.6,42.9,29.2,85.8,43.7,128.7c1,2.9,2.5,4.3,5.4,5.1c43.1,13.2,81.7,34.7,115.6,64.4
+c2.6,2.3,4.9,3,8.4,2.2c44.3-10.8,88.7-21.3,133-32c10.4-2.5,20.9-5,32.1-7.7c-8.2,12.9-16,25.1-23.8,37.3
+c-22.3,35.1-44.6,70.3-66.9,105.4c-1.9,3-1.9,5.4-0.5,8.6c12.9,30.2,20.9,61.7,23.5,94.5c0.4,5.1,2.2,8.5,6.4,11.3
+c34.6,23.7,69,47.6,103.5,71.5c9.9,6.9,19.9,13.7,30.7,21.1c-10.5,2.8-20.1,5.4-29.7,8c-39.8,10.8-79.6,21.8-119.5,32.4
+c-9.5,2.5-15.7,7.1-19.6,16.9c-8,19.7-19.7,37.6-32.2,54.8c-1.3,1.8-2.1,4.8-1.7,6.8c6,27.3,12,54.6,18.5,81.8
+c6.6,27.8,13.7,55.5,20.6,83.2c0.3,1.1,0.4,2.3,0.7,4.2c-10.3-5.3-20-10.3-29.6-15.2c-35.1-18-70.3-36.1-105.5-53.9
+c-6.2-3.2-12.9-5.6-19.5-8c-1.9-0.7-4.5-0.6-6.3,0.2c-18.5,8.2-37.6,14.6-57.3,19.5c-1.9,0.5-4.2,2-5.2,3.6
+c-12.3,20.7-24.7,41.3-36.5,62.3c-14.5,25.8-28.3,52-42.5,78.1C471.4,955.5,470.7,956.6,469.5,958.7z
+M483.6,789.9
+c161.5-1,284.5-130.3,285.8-282.7c1.4-163.2-129.9-288.8-285.2-289C326.4,217.9,198.1,346,197.9,503.5
+C197.6,661.3,325.9,789.9,483.6,789.9z
+M731.4,813c-7.5-30.4-14.8-59.7-22-89.1c-0.4-0.3-0.8-0.7-1.1-1c-1.4,1.9-2.5,4.4-4.4,5.6
+c-8.9,6-10.1,13.4-6.5,23.2c3.2,8.4,4.5,17.5,6.9,27c-2.1-1.1-3.4-1.7-4.8-2.4c-9.7-5-19.4-10-29.1-14.9c-1.3-0.6-3.2-1.5-4.1-1
+c-5.5,3.4-10.7,7.1-16.2,10.8C677.3,785.2,703.8,798.8,731.4,813z
+M471.9,893.8c14-25.7,27.7-50.8,41.6-76.2c-1.4,0-2.6-0.1-3.7,0
+c-5.8,0.4-12.8-0.9-17,1.9c-4.4,2.9-6.2,9.9-9.1,15.1c-3.3,6-6.6,12.1-10.3,18.8c-1.2-2.4-1.9-4-2.7-5.6
+c-4.2-9.1-8.3-18.2-12.5-27.3c-0.6-1.3-2-2.9-3.3-3.1c-6.2-1-12.4-1.5-18.9-2.2C447.9,841.4,459.8,867.3,471.9,893.8z
+M217,792.8
+c27.5-11.9,53.9-23.3,80.7-34.8c-4.5-3.5-8.8-6.7-12.8-10.2c-2.2-1.9-4.1-2.2-6.8-1c-8.7,4-17.5,7.7-26.3,11.5
+c-1.2,0.5-2.5,0.9-4.5,1.6c3.9-11.3,7.4-21.6,10.9-31.9c0.4-1.4,0.6-3.5-0.1-4.4c-3.9-4.7-8.2-9-12.7-13.9
+C235.9,737.4,226.6,764.5,217,792.8z
+M786.5,590.1c27.7-7.4,54.6-14.7,82.6-22.2c-24.3-16.6-47.5-32.6-71.1-48.7
+c-0.4,5.5-0.5,10.3-1.3,15c-0.7,4.3,0.7,6.8,4.4,9.1c8.4,5.3,16.5,11.2,25.2,17.2c-1.5,0.5-2.3,0.9-3.1,1.1
+c-9.5,2.6-19.1,5-28.5,7.8c-1.5,0.4-3.4,1.7-3.7,3C789.3,577.9,788.1,583.6,786.5,590.1z
+M718.8,294.8c2.4,2.9,4.6,4.8,6,7.2
+c4.1,7.2,9.4,8.9,17.3,5.8c6.1-2.3,12.8-3.2,20.2-4.9c-5.5,8.6-10.3,16.1-15,23.7c-0.7,1.2-1.2,3.3-0.7,4.3c2.9,5,6.1,9.9,9.5,15.2
+c15.1-23.7,30-47.1,45.5-71.4C773.5,281.5,746.5,288.1,718.8,294.8z
+M143.3,526.3c8.1-4.3,15.5-8.3,22.8-12.3
+c1.2-0.7,2.9-1.9,3-2.9c0.3-6.1,0.1-12.3,0.1-19.1c-23.6,12.6-46.3,24.8-69.9,37.5c25.2,9.2,49.3,17.9,74,26.9
+c-0.8-5.6-1.7-10.6-2-15.6c-0.2-3.4-1.5-5-4.6-6C159.1,532.2,151.6,529.3,143.3,526.3z
+M205.7,237.1c-0.3,0.3-0.5,0.5-0.8,0.8
+c10.8,23.1,21.7,46.2,32.8,69.8c2.9-3.5,4.9-6.6,7.6-8.9c5-4.2,5.1-8.4,1.8-13.8c-2.7-4.4-4.5-9.4-7.1-15.1
+c7.7,3,14.3,5.6,20.8,8.1c1.1,0.4,3,0.7,3.6,0.2c4.6-4,8.9-8.2,13.6-12.7C253.5,255.9,229.6,246.5,205.7,237.1z
+M538.1,193.9
+c-7.9-23.2-15.6-45.9-23.6-69.7c-11.5,22.1-22.5,43.2-34,65.3c5.8,0,10.5-0.4,15.2,0.1c4,0.4,5.9-1,7.4-4.5c2.1-4.8,4.9-9.4,7.8-15
+c2.3,6.8,4.2,12.6,6.3,18.3c0.4,1.1,1.3,2.7,2.2,2.8C525.5,192.2,531.5,193,538.1,193.9z" />
+</vector> \ No newline at end of file
diff --git a/res/drawable/icon_artistic_sun.xml b/res/drawable/icon_artistic_sun.xml
new file mode 100644
index 000000000..46ad53e8c
--- /dev/null
+++ b/res/drawable/icon_artistic_sun.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+ android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M323,267.8c0,0,0.1-0.1,0.1-0.1c-3.5-2.8-6.8-5.7-10.4-8.3c-12-8.4-25.4-13.8-39.4-18.1
+ c-28.3-8.6-57.4-11.9-86.9-12.3c-16.4-0.2-32.7,0.7-48.9,2.8c-17.7,2.3-35,5.8-51.8,11.6c-12.2,4.2-24,9.4-34.4,17.2
+ c-2.7,2-5.1,4.2-7.6,6.3c0.1,0.1,0.2,0.2,0.2,0.4c0.4-0.1,0.8-0.2,1.2-0.4c10.7-5,21.9-9,33.3-12.2c33-9.2,66.7-13,100.9-13.3
+ c23.2-0.2,46.2,1.3,69.1,4.9c19.6,3.1,38.9,7.5,57.6,14.5C311.7,263,317.3,265.5,323,267.8 M120.6,221.9
+ c0.2-16.4,5.9-30.7,17.5-42.5c11.7-11.8,26-18.2,42.9-18.8c15.5-0.6,29.4,3.9,41.4,13.4c15.5,12.3,23.2,28.4,23.6,47.9
+ c2.9,0.6,5.6,1.1,8.3,1.6c0.3,0.1,0.9-0.4,1.1-0.8c0.2-0.5,0.2-1.2,0.2-1.7c-0.2-11.4-2.9-22.1-8.3-32.2
+ c-14.3-26.4-43.6-41.2-74-37.1c-16.5,2.2-30.7,9.3-42.2,21.1c-13.1,13.4-19.7,29.5-20.1,48.1c0,0.9,0.2,1.8,0.3,2.8
+ C114.6,223,117.6,222.4,120.6,221.9 M138.5,219.2c1.6-22.7,19.7-39.3,40.6-41.1c12.5-1.1,23.7,2.4,33.3,10.4
+ c9.6,8.1,14.7,18.4,15.6,30.7c3.3,0.4,6.4,0.9,9.8,1.3c-1.4-20.5-10.5-36.3-29-45.7c-20.5-10.5-40.7-8.6-59.2,5.1
+ c-13.5,10-20.1,23.9-20.9,40.5c0.7,0,1.2,0,1.6-0.1C133,219.9,135.7,219.6,138.5,219.2 M99.9,86.6c0.5,17.1,4.4,33,15.8,46.6
+ c7.3,8.7,16.5,14.8,27.3,18.9c1.8-6.8,3.3-13.3,3-20.1c-0.3-6.9-3.3-12.3-8.9-16.4c-2.8-2.1-5.8-3.9-8.8-5.7
+ c-6.4-3.9-12.9-7.7-18.3-12.9C106.5,93.7,103.4,90.1,99.9,86.6 M40.1,139.6c0.4,0.7,0.7,1.1,1,1.5c4.1,5.8,8.6,11.3,13.9,16.2
+ c16.2,15.1,35.4,22,57.7,20.3c0.5,0,1-0.2,1.6-0.4c-2-6.1-4.2-11.9-7.7-17.2c-4.1-6.3-9.7-10.4-17.3-11.4c-4.3-0.6-8.6-1-13-1.2
+ c-9.6-0.6-19.2-1.7-28.3-4.9C45.4,141.6,42.9,140.6,40.1,139.6 M324.4,139.7c-0.4,0.2-0.8,0.3-1.2,0.5c-7.7,3.3-15.7,5.5-24.1,6.3
+ c-6.5,0.6-13,1.1-19.6,1.6c-10.1,0.7-17.8,5.2-22.5,14.1c-2.2,4.2-3.9,8.6-5.8,13c-0.3,0.7-0.5,1.5-0.7,2.4
+ c12.1,1.2,23.7-0.1,34.8-4.5C302.3,166.3,314.6,154.5,324.4,139.7 M180.8,66.3c-1.7,3.1-3.4,6.1-4.9,9.1c-4.9,9.9-8,20.2-8,31.3
+ c0,12.9,4.5,24.3,12.6,34.4c0.3,0.4,0.7,0.7,1,1.1c5.4-5.1,10.5-10.2,14.1-16.5c3.4-5.9,3.8-12,1-18.3c-1.1-2.5-2.3-4.9-3.6-7.2
+ c-3.5-6.2-7-12.5-8.9-19.3C182.8,76.2,181.9,71.3,180.8,66.3 M265.2,86.7l-0.6-0.1c-0.1,0.1-0.3,0.2-0.4,0.3
+ c-6.8,9.1-15.6,15.9-25.5,21.7c-3.9,2.3-7.8,4.7-11.4,7.4c-4.1,3-6.9,6.9-7.9,11.9c-1.1,5.1-0.7,10.2,0.3,15.2c0.5,3,1.3,5.9,2,9
+ c0.5-0.2,0.8-0.2,1-0.3c10-4,18.8-9.8,25.8-17.9c8.2-9.4,12.8-20.5,14.8-32.6C264.3,96.4,264.6,91.5,265.2,86.7 M103.6,212.7
+ c-0.4-0.5-0.6-0.7-0.7-0.9c-4.9-4.2-10-8.1-15.8-11.1c-6-3-12.3-4.7-18.9-2.9c-4.9,1.3-9.7,3.2-14.3,5.3c-9.3,4-18.7,7.4-28.9,8.7
+ c-2.2,0.3-4.4,0.5-7,0.7c0.6,0.3,0.8,0.5,1.1,0.7c7.1,3.4,14.5,6.3,22.2,8.2c16.8,4.3,33.4,4.2,49.6-2.5
+ C95.2,217.2,99.3,214.8,103.6,212.7 M261.4,212.2c0.3,0.3,0.4,0.4,0.6,0.5c15.1,9.7,31.7,13.1,49.6,11c11.6-1.4,22.5-5,32.9-9.9
+ c0.7-0.3,1.4-0.7,2.5-1.2c-0.9-0.1-1.3-0.2-1.6-0.2c-9.5-0.6-18.7-2.8-27.5-6.4c-5.7-2.3-11.3-4.8-17-7c-4.5-1.7-9.3-2.3-14.1-1.4
+ C276.7,199.6,269.1,205.9,261.4,212.2 M146.7,218.3c2.7-0.2,5-0.5,7.3-0.5c1.9,0,2.7-0.6,3.1-2.5c3.1-13,16.6-21.8,30-19.7
+ c11.4,1.8,20,9.7,22.6,20.8c0.1,0.5,0.6,1.1,1,1.2c2.9,0.3,5.9,0.5,8.8,0.8c0-8.3-5.7-20.7-17.2-27.2c-12.8-7.3-25.8-7.3-38.5,0.3
+ C153.7,197.4,148.2,206.6,146.7,218.3"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M323,267.8c-5.7-2.3-11.3-4.8-17-6.9c-18.6-7-37.9-11.4-57.6-14.5c-22.9-3.6-45.9-5.1-69.1-4.9
+ c-34.2,0.3-67.9,4.1-100.9,13.3C67,258,55.9,262,45.1,267c-0.4,0.2-0.8,0.3-1.2,0.4c-0.1-0.1-0.2-0.2-0.2-0.4
+ c2.5-2.1,5-4.4,7.6-6.3c10.4-7.7,22.1-12.9,34.4-17.2c16.8-5.8,34.2-9.4,51.8-11.6c16.2-2.1,32.5-3,48.9-2.8
+ c29.5,0.4,58.6,3.7,86.9,12.3c14,4.2,27.4,9.7,39.4,18.1c3.6,2.6,7,5.5,10.4,8.3C323.1,267.7,323,267.8,323,267.8"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M120.6,221.9c-3.1,0.6-6.1,1.2-9.3,1.8c-0.1-1-0.4-1.9-0.3-2.8c0.4-18.5,7-34.7,20.1-48.1
+ c11.5-11.8,25.7-18.9,42.2-21.1c30.4-4.1,59.7,10.6,74,37.1c5.5,10.1,8.1,20.8,8.3,32.2c0,0.6,0,1.2-0.2,1.7
+ c-0.2,0.4-0.8,0.8-1.1,0.8c-2.8-0.5-5.5-1-8.3-1.6c-0.5-19.5-8.1-35.6-23.6-47.9c-12-9.5-25.9-13.9-41.4-13.4
+ c-16.8,0.6-31.2,6.9-42.9,18.8C126.5,191.1,120.8,205.4,120.6,221.9"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M138.5,219.2c-2.8,0.4-5.4,0.8-8.1,1.1c-0.4,0.1-0.9,0.1-1.6,0.1c0.8-16.7,7.4-30.5,20.9-40.5
+ c18.5-13.7,38.7-15.6,59.2-5.1c18.5,9.5,27.6,25.3,29,45.7c-3.4-0.5-6.5-0.9-9.8-1.3c-1-12.3-6-22.7-15.6-30.7
+ c-9.6-8-20.8-11.5-33.3-10.4C158.1,179.9,140.1,196.5,138.5,219.2"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M99.9,86.6c3.4,3.6,6.6,7.2,10.1,10.4c5.4,5.2,11.9,9,18.3,12.9c3,1.8,6,3.6,8.8,5.7
+ c5.6,4.1,8.5,9.5,8.9,16.4c0.3,6.8-1.2,13.3-3,20.1c-10.8-4.2-20-10.2-27.3-18.9C104.3,119.6,100.4,103.7,99.9,86.6"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M40.1,139.6c2.8,1,5.3,2,7.9,2.9c9.2,3.2,18.7,4.3,28.3,4.9c4.3,0.3,8.7,0.6,13,1.2
+ c7.6,1.1,13.2,5.2,17.3,11.5c3.4,5.3,5.6,11,7.7,17.2c-0.6,0.1-1.1,0.4-1.6,0.4c-22.4,1.7-41.6-5.2-57.7-20.3
+ c-5.2-4.9-9.8-10.3-13.9-16.2C40.8,140.7,40.5,140.3,40.1,139.6"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M324.4,139.7c-9.8,14.8-22.1,26.7-39.1,33.4c-11.1,4.4-22.7,5.7-34.8,4.5c0.3-0.9,0.4-1.7,0.7-2.4
+ c1.9-4.3,3.5-8.8,5.8-13c4.7-8.9,12.4-13.3,22.5-14.1c6.5-0.5,13.1-0.9,19.6-1.6c8.4-0.8,16.4-3.1,24.1-6.3
+ C323.6,139.9,324,139.8,324.4,139.7"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M180.8,66.3c1.1,5,1.9,9.9,3.2,14.6c1.9,6.9,5.5,13.1,8.9,19.3c1.3,2.4,2.5,4.8,3.6,7.2
+ c2.8,6.2,2.3,12.3-1,18.3c-3.6,6.3-8.6,11.4-14.1,16.5c-0.4-0.4-0.7-0.7-1-1.1c-8-10.1-12.5-21.5-12.6-34.4c0-11.1,3-21.4,8-31.3
+ C177.5,72.4,179.2,69.4,180.8,66.3"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M265.2,86.7c-0.6,4.8-0.9,9.7-1.7,14.5c-2,12.1-6.7,23.1-14.8,32.6c-7,8.1-15.8,13.9-25.8,17.9
+ c-0.2,0.1-0.5,0.1-1,0.3c-0.7-3.1-1.5-6-2-9c-0.9-5-1.4-10.1-0.3-15.2c1.1-5,3.8-8.9,7.9-11.9c3.7-2.6,7.5-5.1,11.4-7.4
+ c9.8-5.8,18.6-12.6,25.5-21.7c0.1-0.1,0.2-0.2,0.4-0.3L265.2,86.7z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M103.6,212.7c-4.3,2.2-8.4,4.5-12.7,6.3c-16.2,6.7-32.8,6.7-49.6,2.5c-7.7-1.9-15-4.8-22.2-8.2
+ c-0.3-0.1-0.5-0.3-1.1-0.7c2.6-0.3,4.8-0.5,7-0.7c10.1-1.2,19.6-4.6,28.9-8.7c4.7-2,9.4-3.9,14.3-5.3c6.6-1.8,13-0.2,18.9,2.9
+ c5.8,3,10.9,6.9,15.8,11.1C103.1,211.9,103.2,212.1,103.6,212.7"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M261.4,212.2c7.7-6.3,15.3-12.6,25.4-14.6c4.8-1,9.6-0.3,14.1,1.4c5.7,2.2,11.3,4.7,17,7
+ c8.8,3.6,18,5.7,27.5,6.4c0.4,0,0.7,0.1,1.6,0.2c-1.1,0.6-1.8,0.9-2.5,1.2c-10.5,4.9-21.4,8.5-32.9,9.9
+ c-17.9,2.1-34.5-1.3-49.6-11C261.8,212.6,261.7,212.5,261.4,212.2"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M146.7,218.3c1.5-11.7,7-20.9,17.1-26.9c12.6-7.6,25.7-7.6,38.5-0.3c11.5,6.5,17.2,18.9,17.2,27.2
+ c-2.9-0.2-5.9-0.5-8.8-0.8c-0.4,0-0.9-0.7-1-1.2c-2.6-11.1-11.2-19-22.6-20.8c-13.4-2.1-26.9,6.7-30,19.7
+ c-0.5,1.9-1.3,2.5-3.1,2.5C151.7,217.8,149.4,218.1,146.7,218.3"/>
+</vector>
diff --git a/res/drawable/icon_calendar.xml b/res/drawable/icon_calendar.xml
new file mode 100644
index 000000000..594eb33a5
--- /dev/null
+++ b/res/drawable/icon_calendar.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+ android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M137,60.4c29.4,0 58.5,0 87.7,0c0,0.8 0,1.4 0,2c0,7.2 -0.1,14.5 0.1,21.8c0.3,10.8 9.5,19.5 20.5,19.5c10.8,0 20.1,-8.6 20.5,-19.3c0.3,-7.2 0.1,-14.5 0.1,-21.8c0,-0.7 0,-1.4 0,-2.3c0.8,0 1.5,0 2.2,0c6.9,0 13.8,0 20.7,0c10.4,0 18.6,8.1 18.8,18.4c0,0.3 0,0.6 0,0.9c0,68.6 0,137.2 0,205.8c0,15.3 -10.1,27.5 -25.1,30.4c-1.8,0.4 -3.8,0.5 -5.6,0.5c-63.9,0 -127.8,0 -191.7,0c-17.4,0 -30.7,-13.3 -30.7,-30.7c0,-68.8 0,-137.5 0,-206.3c0,-11 8,-19 19,-19c6.8,0 13.5,0 20.3,0c0.7,0 1.3,0 2.2,0c0,0.9 0,1.6 0,2.3c0,6.8 0,13.6 0,20.5c0,11.4 9.2,20.6 20.6,20.6s20.6,-9.2 20.6,-20.6c0,-6.9 0,-13.8 0,-20.7C137,61.8 137,61.2 137,60.4zM287,146c-70.8,0 -141.5,0 -212.2,0c0,0.8 0,1.4 0,2.1c0,45.7 0,91.5 0,137.2c0,6.4 4.1,10.6 10.5,10.6c63.8,0 127.6,0 191.3,0c6.3,0 10.5,-4.2 10.5,-10.4c0,-45.8 0,-91.6 0,-137.4C287,147.4 287,146.7 287,146z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M234.8,61.1c0,-7.1 0,-14.2 0,-21.2c0,-6.3 4.4,-11 10.4,-11.1c5.9,-0.1 10.6,4.6 10.6,10.9c0,14.3 0,28.6 0,43c0,6.4 -4.7,11.1 -10.8,11c-5.9,-0.1 -10.4,-4.9 -10.4,-11.2C234.8,75.3 234.8,68.2 234.8,61.1z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M105.9,61.1c0,-7.1 0,-14.3 0,-21.4c0,-6.2 4.4,-10.8 10.4,-10.9c5.9,-0.1 10.5,4.5 10.6,10.7c0.1,7 0,13.9 0,20.9c0,7.5 0,15 0,22.5c0,4.5 -2,7.9 -6.1,9.8c-3.8,1.8 -7.5,1.4 -10.8,-1.2c-2.7,-2 -4.1,-4.8 -4.1,-8.2C105.9,75.9 105.9,68.5 105.9,61.1z"/>
+</vector>
diff --git a/res/drawable/icon_cheers.xml b/res/drawable/icon_cheers.xml
new file mode 100644
index 000000000..799f0151e
--- /dev/null
+++ b/res/drawable/icon_cheers.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+ android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M200.8,22.8c-0.7,0.2-1.1,0.3-1.6,0.4c-2.8,0.9-5.7,1.8-8.4,2.7c-0.9,0.3-1.5,0.1-2.1-0.4
+ c-2.4-1.8-4.7-3.6-7.1-5.5c-0.3-0.3-0.7-0.5-1.2-0.8c0,3.6,0,7.1,0,10.5c0,0.8-0.2,1.3-0.9,1.7c-1.4,0.9-2.8,1.9-4.2,2.8
+ c-1.5,1-2.9,2-4.6,3.2c3.1,1,6,2,8.9,2.9c1.6,0.4,2.6,1.1,2.9,2.9c0.4,1.9,1.1,3.8,1.6,5.7c0.3,1.1,0.6,2.1,1.1,3.4
+ c2.2-2.9,4.2-5.7,6.2-8.5c0.5-0.7,1-0.9,1.9-0.9c3.4,0.1,6.8,0,10.3,0c-0.2-0.3-0.4-0.6-0.6-1c-1.2-1.7-2.3-3.6-3.8-5.1
+ c-2-2.1-2.3-4.2-1-6.8C199.3,27.8,199.9,25.4,200.8,22.8z M184.3,111c4.7,19.5,9.4,38.7,13.9,58c1.7,7.1,5,13.3,10.3,18.3
+ c8.2,7.9,18.2,11.5,29.7,10.7c3.6-0.2,5.6,1.2,6.6,4.7c4.5,15.6,8.9,31.3,13.4,47c0.5,1.8,0.5,3.6-0.6,5c-1.3,1.8-2.7,3.6-4.4,5
+ c-3.8,3.1-8.3,5-12.9,6.6c-1.9,0.7-2.6,1.5-2.1,2.6c0.4,1.1,1.4,1.3,3.3,0.8c9.7-3,19.4-6.1,29.1-9.1c8.2-2.6,16.3-5.1,24.5-7.7
+ c0.3-0.1,0.6-0.2,0.9-0.3c1.1-0.4,1.7-1.1,1.4-2.2c-0.3-1.2-1.2-1.3-2.3-1.1c-3.2,0.7-6.4,1.5-9.6,1.9c-3.6,0.5-7.2,0.6-10.7-0.6
+ c-2.5-0.8-4.2-2.4-5-5c-0.7-2.3-1.5-4.5-2.3-6.7c-4.7-13.1-9.3-26.2-14-39.3c-1.1-3.2-0.3-5.6,2.6-7.4c6.2-4,10.9-9.3,13.9-16
+ c4.1-9.2,4.9-18.6,1.2-28c-6.3-16.1-12.9-32.1-19.3-48.2c-1.2-2.9-2.4-5.9-3.6-8.9C226.8,97.7,205.6,104.3,184.3,111z M126,51.7
+ c-0.3,0.6-0.5,1.1-0.6,1.6c-6.8,17.2-13.6,34.5-20.4,51.7c-1.7,4.3-3.3,8.5-3.6,13.1c-0.7,15.3,5.4,27.1,18.4,35.3
+ c3.5,2.2,4.4,4.3,3,8.3c-5.2,14.8-10.4,29.5-15.3,44.3c-1.4,4-3.9,6-7.8,6.6c-4.5,0.7-8.9,0.2-13.3-0.7c-1.6-0.3-3.1-0.8-4.6-1.1
+ c-1.1-0.3-2.1,0.2-2.3,1.2c-0.2,1.1,0.3,1.8,1.3,2.1c0.4,0.1,0.9,0.3,1.3,0.4c13,4,26,8,39.1,12c5,1.5,9.9,3,14.9,4.6
+ c1,0.3,1.9,0.4,2.6-0.6c0.6-1,0.1-2-1.3-2.6c-3.1-1.3-6.2-2.5-9.2-4c-3.2-1.6-6.1-3.6-8.2-6.5c-1.4-2-1.9-4.1-1.2-6.6
+ c4.3-15.2,8.6-30.4,12.7-45.7c1.4-5.2,3.2-6.2,8.2-6.3c14.3-0.3,25.2-6.7,32.7-18.8c2.8-4.5,3.9-9.6,5.1-14.7
+ c0.9-3.7,2-7.3,0.4-11.2c-0.5-1.2-0.7-2.5-1-3.8c-0.3-1.3-0.6-2.7-0.9-4.1c1.9-0.6,3.6-1.2,5.3-1.7c0.9-0.2,1.2-0.7,1.4-1.5
+ c1.7-7.5,3.5-15,5.2-22.5c0.7-3.1,1.4-6.1,2.1-9.3C168.5,64.7,147.3,58.2,126,51.7z M182.6,134.7c-7.9,20.1-22.5,30.4-44.1,31.4
+ c-0.6,2.1-1.2,4.4-1.9,6.6c-3.6,13-7.2,26.1-10.9,39.1c-0.4,1.2,0.2,1.8,1,2.5c2.9,2.5,6.3,4.2,9.8,5.6c1.1,0.4,2.2,0.8,3.4,1.2
+ c4.7,1.7,7.1,6.5,5.7,11.1c-1.5,4.6-6.4,7.2-11.1,5.8c-13.9-4.2-27.7-8.5-41.6-12.8c-4.9-1.5-9.9-3-14.8-4.6
+ c-3.8-1.2-6.2-4.9-5.9-8.7c0.2-4.1,2.9-7.5,6.9-8.2c1.6-0.3,3.4-0.1,5.1,0.3c4.2,1,8.3,1.9,12.5,1.7c0.3,0,0.5,0,0.8,0
+ c1.7-0.1,2.6-0.7,3.3-2.5c4.8-14.1,9.7-28.1,14.6-42.2c0.4-1.2,0.1-1.7-0.9-2.4c-14.6-10-21.3-23.9-20.3-41.5
+ c0.3-5.5,2.3-10.5,4.3-15.5c7.6-19.1,15.2-38.4,22.8-57.5c0.1-0.4,0.3-0.7,0.5-1.2c20.2,6.2,40.4,12.4,60.7,18.7
+ c-0.1-0.5-0.1-0.8-0.2-1.1c-1.4-4.7-2.8-9.4-4.2-14.1c-0.3-1-0.8-1.5-1.8-1.8c-5.3-1.7-10.5-3.4-15.7-5c-0.3-0.1-0.6-0.2-1.2-0.4
+ c0.5-0.4,0.9-0.7,1.2-0.9c4.5-3.1,9-6.2,13.6-9.2c0.9-0.6,1.1-1.1,1.1-2.1c-0.1-5.4,0-10.9,0-16.3V9c2.8,2.2,5.4,4.1,8.1,6.1
+ c2.2,1.7,4.3,3.4,6.5,4.9c0.4,0.3,1.2,0.4,1.7,0.3c5.7-1.8,11.4-3.6,17.4-5.5c-0.2,0.6-0.3,1-0.4,1.5c-1.8,5.1-3.6,10.2-5.5,15.3
+ c-0.3,0.9-0.3,1.5,0.3,2.4c3.5,4.7,6.9,9.5,10.5,14.3c-2,0-3.9,0-5.8,0c-4.2-0.1-8.4-0.2-12.6-0.3c-0.4,0-0.9,0.1-1.1,0.4
+ c-3.4,4.5-6.7,9-10.1,13.7c4.8,1.5,9.4,2.9,14.2,4.4c-2.7,11.7-5.4,23.3-8.2,35.2c20.8-6.5,41.4-13,62.1-19.5
+ c1.7,4.2,3.3,8.2,4.9,12.3c6.9,17.1,13.8,34.1,20.5,51.2c3.5,9,3.5,18.3,0.8,27.6c-2.9,9.9-8.7,17.8-17.2,23.8
+ c-0.8,0.6-0.9,1-0.6,1.9c5.2,14.6,10.4,29.2,15.5,43.8c0.3,0.8,0.8,1.1,1.6,1.3c3.7,0.7,7.4,0.1,11-0.7c1.8-0.4,3.5-0.9,5.3-1.3
+ c4.6-0.8,9,2,10.1,6.5c1.2,4.5-1.3,9.2-5.7,10.6c-10.8,3.5-21.7,6.8-32.5,10.2c-7.8,2.5-15.5,4.9-23.3,7.3
+ c-4.4,1.4-8.8-0.4-10.9-4.3c-1.9-3.7-1-8.4,2.4-11c0.9-0.7,2-1.2,3.1-1.6c4.2-1.6,8.4-3.3,11.9-6.2c2-1.6,2-1.7,1.3-4.1
+ c-4.1-14.3-8.2-28.5-12.2-42.8c-0.3-1.2-0.8-1.5-2-1.5c-20,0.7-38.6-12.3-44.3-31.2c-2-6.6-3.3-13.3-4.9-20
+ C185.7,147.7,184.2,141.4,182.6,134.7z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M220.3,53.6c-1.8,1.8-3.4,3.5-4.9,5.2c-0.6,0.6-1.1,0.9-2,0.7c-2.3-0.4-4.6-0.7-7-1.1c0,0.3,0,0.4,0.1,0.4
+ c0.7,1.3,1.2,2.7,2.1,3.8c1.7,2.2,1.6,4.2,0,6.4c-0.9,1.2-1.4,2.7-2.2,4.3c2.3-0.4,4.3-0.7,6.2-1.2c1.5-0.4,2.6-0.2,3.7,1.1
+ c0.9,1.1,2,2.1,3.1,3.1c0.4,0.4,0.9,0.8,1.4,1.3c0.3-2.5,0.7-4.6,0.9-6.8c0.1-1.3,0.6-1.8,1.7-2.3c2-0.9,3.9-2,6-3.1
+ c-2.4-1.1-4.4-2.2-6.5-3c-1-0.4-1.3-1-1.4-2C221.1,58.3,220.7,56.1,220.3,53.6z M196.7,51.9c4.9,0.8,9.6,1.5,14.2,2.2
+ c1.1,0.2,1.8,0.1,2.6-0.8c3.2-3.5,6.5-6.9,10-10.5c0.3,2,0.6,3.7,0.9,5.4c0.5,3.1,1,6.1,1.5,9.2c0.1,0.8,0.4,1.3,1.2,1.6
+ c4.2,1.9,8.3,3.9,12.5,5.8c0.3,0.1,0.5,0.3,0.9,0.5c-0.4,0.3-0.7,0.5-1,0.6c-4,2.1-8.1,4.1-12.1,6.2c-0.7,0.4-1.1,0.8-1.2,1.7
+ c-0.5,4.6-1.2,9.1-1.8,13.7c0,0.3-0.1,0.5-0.1,1c-1.4-1.3-2.6-2.5-3.9-3.7c-2.2-2.2-4.4-4.3-6.5-6.5c-0.7-0.7-1.3-0.9-2.3-0.7
+ c-4.3,0.9-8.7,1.7-13,2.5c-0.4,0.1-0.9,0.1-1.5,0.1c2.2-4.4,4.4-8.7,6.6-12.9c0.5-0.9,0.5-1.6,0-2.5c-2.1-3.7-4.2-7.5-6.2-11.3
+ C197.3,53,197.1,52.6,196.7,51.9z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M179,182.6c-0.6-2-1.1-3.6-1.5-5.2c-0.1-0.5,0.1-1.3,0.4-1.7c1-1.4,2.1-2.7,3.2-4c-0.1-0.1-0.1-0.3-0.2-0.4
+ c-1.6,0-3.3-0.1-4.9,0c-1,0.1-1.5-0.3-2-1.1c-0.8-1.4-1.8-2.7-2.8-4.3c-0.6,1.8-1.3,3.3-1.7,4.9c-0.3,0.9-0.8,1.3-1.7,1.5
+ c-1.6,0.4-3.2,0.8-5,1.3c1.3,1,2.4,2,3.5,2.6c1.4,0.8,1.7,1.9,1.5,3.4c-0.2,1.3-0.2,2.7-0.3,4.3c1.6-1.1,2.9-1.8,4.1-2.8
+ c0.9-0.7,1.7-0.8,2.8-0.3C175.8,181.5,177.3,182,179,182.6z M154.2,171.9c3.8-1,7.3-2,10.8-2.8c0.8-0.2,1.2-0.6,1.5-1.4
+ c1.2-3.4,2.4-6.8,3.7-10.4c1.5,2.3,3.1,4.3,4.2,6.6c1.5,3,3.5,4.3,6.9,3.9c2.5-0.3,5-0.1,7.5-0.1c0.1,0.1,0.1,0.3,0.1,0.4
+ c-0.5,0.6-0.9,1.2-1.4,1.8c-1.8,2.2-3.6,4.4-5.4,6.6c-0.5,0.6-0.6,1.2-0.4,2c1.1,3.4,2.1,6.9,3.1,10.5c-0.6-0.2-1-0.3-1.4-0.4
+ c-3-1.2-6.1-2.4-9.2-3.4c-0.5-0.2-1.3-0.1-1.8,0.2c-2.6,1.7-5.2,3.5-7.8,5.3c-0.4,0.3-0.9,0.6-1.5,1c0.1-2.7-0.1-5.1,0.4-7.5
+ c0.7-3.6-0.5-5.8-3.6-7.6C158.1,175.2,156.3,173.5,154.2,171.9z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M135.8,71.6c-0.1,0-0.1-0.1-0.2-0.1c-0.1,0.3-0.3,0.5-0.4,0.8c-6.4,13.6-12.8,27.2-19.1,40.8
+ c-2.2,4.8-2.8,9.9-1,15.1c0.1,0.4,0.4,0.8,0.7,1.5c0.7-0.9,1.3-1.4,1.7-2.1c0.9-1.7,1.9-3.5,2.6-5.3c4.9-11.9,8.5-24.3,12-36.7
+ C133.3,80.8,134.6,76.2,135.8,71.6z M107.9,120.8h4.9c0.2-1.1,0.4-2.2,0.6-3.4c0.8-4,2.9-7.5,4.6-11.2c6.4-13.7,12.8-27.4,19.2-41
+ c0.2-0.5,0.5-0.9,0.7-1.4c0.9-0.1,1.1,0.3,0.9,1.1c-5,18.4-9.6,37-16.5,54.9c-0.1,0.3-0.2,0.6-0.3,1.1c16.5,0.2,32.9,0.4,49.3,0.6
+ c-2,14.9-9.4,26.2-25.3,30c-4.7,1.1-9.5,1.1-14.2,0.3c-5.3-1-9.5-4.1-13.5-7.5c-6.6-5.8-10-13.2-10.4-22c0-0.3,0-0.6,0-0.9
+ C107.9,121.3,107.9,121.2,107.9,120.8z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M221.3,178.8c0.2,0,0.4-0.1,0.5-0.1c0-1.4,0.2-2.9,0-4.2c-0.8-4.5-1.6-9-2.7-13.4
+ c-3.1-12.5-7-24.7-11.1-36.8c-0.6-1.8-1.2-3.5-1.8-5.2c0.4,4.5,1.1,8.9,1.7,13.3c1.5,10.1,3,20.2,4.4,30.3c0.6,4.1,1.6,8.1,4,11.5
+ C217.8,176,219.3,177.7,221.3,178.8z M200.9,152h8.9c-0.4-2.9-0.8-5.5-1.2-8.2c-1.5-10.4-3-20.8-4.5-31.2
+ c-0.1-0.3,0.3-0.7,0.5-1.1c0.2,0,0.4,0.1,0.5,0.1c4.3,13.3,8.6,26.7,13,40.2c3.4,0,6.9,0,10.5,0c6.7-0.1,13.4-0.2,20.1-0.3
+ c5.1-0.1,10.2-0.1,15.2-0.2c1.1,0,1.5,0.4,1.8,1.4c3.3,12.5-1.7,25.9-12.4,33.4c-3.5,2.5-7.2,4.6-11.5,5.3
+ c-18.4,2.7-31.8-7.4-36.3-20.5c-1.4-4.1-2.1-8.5-3.2-12.7C201.9,156.2,201.4,154.2,200.9,152z"/>
+</vector>
diff --git a/res/drawable/icon_city.xml b/res/drawable/icon_city.xml
new file mode 100644
index 000000000..95c947d90
--- /dev/null
+++ b/res/drawable/icon_city.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+ android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M103,289 L97.1,289 L97.1,214.1 L73.8,233 L73.8,289 L67.9,289 L67.9,230.1 L103,201.7z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M152.3,289 L146.4,289 L146.4,219.7 L132.2,231.9 L132.2,155.7 L108.2,177.2 L108.2,289 L102.3,289
+ L102.3,174.4 L138.1,142.4 L138.1,219 L152.3,206.8z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M206.9,289 L201,289 L201,117.8 L159,158 L159,289 L153.2,289 L153.2,155.4 L206.9,103.9z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M229.3,39.8 L180.8,85.9 L180.8,129.2 L186.7,129.2 L186.7,88.5 L223.4,53.6 L223.4,113.3 L229.3,113.3z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M223.5,112.8 L248.5,143.1 L248.5,289 L288.4,289 L288.4,105.8 L228.9,39.9z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M137.8,142.8 L156.4,166.1 L156.4,289 L149.5,289 L149.5,214.7 L135.1,225.2z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M105.2,289 L100,289 L100.8,207.2 L105.2,210.7z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M204.2,289 L206.8,104.8 L240.9,148.3 L240.9,289z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M25.3,280.4h317.3v11.6h-317.3z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M50.1,300.4h267.7v8.3h-267.7z"/>
+</vector>
diff --git a/res/drawable/icon_cry.xml b/res/drawable/icon_cry.xml
new file mode 100644
index 000000000..6a3817979
--- /dev/null
+++ b/res/drawable/icon_cry.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="1008.0"
+ android:viewportWidth="1008.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M815.6,267.1c14.5,-2.7 27.8,-6.2 41.4,-7.5c26.9,-2.6 50.4,6.7 70.1,24.7c41.5,37.9 42.4,100.3 2.5,140.1c-1.2,1.2 -2.8,2.2 -4.3,3.4c7.1,6.3 13.8,11.7 19.8,17.7c17.4,17.4 33,36 41.6,59.5c30.6,83.6 -22.9,173.7 -110.6,186.3c-18.1,2.6 -36.2,1.7 -53.9,-3c-3.7,-1 -5.4,0 -7.5,2.9C757.3,770.7 681,822.3 584.5,840.4c-123.4,23.1 -232,-9.4 -324.8,-94.1c-8.2,-7.5 -16.6,-15 -25.7,-23.3c-6,1.8 -14.3,4.8 -22.9,7c-84.6,21.2 -172,-37.4 -184.3,-123.3c-6.8,-47.9 5.8,-89.8 38,-126.1c23,-25.9 49.5,-46.8 81,-61.2c2.8,-1.3 4,-3 4.6,-6c13.7,-74.1 46.7,-138.3 99.3,-192.2c51.4,-52.6 113.1,-87.8 185.1,-102.6c112.1,-23.2 214.3,0.2 305.6,69.8c28.8,21.9 53.2,48.1 74.1,77.6C815.1,266.6 815.8,267.3 815.6,267.1zM810.9,287.7c-1.4,-2.1 -2.6,-3.8 -3.8,-5.5c-14.9,-22.3 -31.9,-42.8 -51.7,-60.9c-85.9,-78.1 -186.5,-109.3 -301.2,-90.9c-84.3,13.6 -154.1,54.6 -209.7,119.3c-43.4,50.5 -69.9,109 -80.4,174.8c-0.5,2.9 -1.6,4.4 -4.3,5.5c-33.6,13.8 -61.4,35.3 -85.1,62.7c-28.2,32.6 -39.2,70.1 -32.4,112.5C54.6,682.2 130.2,733 206,715.2c11.7,-2.8 22.9,-7.5 34.9,-11.6c-0.5,-0.3 -0.2,-0.2 0.1,0c0.9,1 1.7,1.9 2.5,2.9c33.5,39.4 73.5,70.4 120.3,92.3c61,28.5 124.9,38.7 191.8,30.8c42.2,-5 82.1,-17.2 119.8,-36.8c54.9,-28.6 99.5,-68.8 133.6,-120.5c1.9,-2.9 3.5,-3.1 6.7,-2.2c10.3,2.6 20.7,5.8 31.2,6.7c51.9,4.1 100.1,-23.4 121.4,-70.9c19,-42.4 16.3,-84 -10.9,-122.8c-14.4,-20.5 -32.5,-37.2 -53.3,-51.1c-1.5,-1 -3,-2.2 -4.9,-3.6c3.4,-2.3 6.2,-4.2 8.9,-6.2c30.6,-21.3 42.9,-58.7 30.7,-93.8c-13.3,-38.3 -52.6,-57.4 -82.3,-53.7C840.6,276.7 825.7,280.8 810.9,287.7z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M797.6,325.8c1.6,-1.4 3,-2.7 4.5,-3.9c17.9,-15.6 38.9,-23.8 62.5,-24.1c26,-0.3 51,22.4 54.6,48.5c5.2,37.5 -23.2,68.5 -61,66.5c-9.4,-0.5 -18,-3.5 -26.1,-8.3c-1.5,-0.9 -3,-1.8 -5.2,-3.1c1.7,8.7 3.2,16.7 5,24.7c0.2,1 2.3,2 3.6,2.3c42.5,9.7 75.9,32.9 102.3,67.3c33.8,43.9 23.1,124.6 -44.8,151.1c-32.5,12.7 -63.8,8.6 -93,-10.5c-1.1,-0.7 -2.1,-1.4 -3.2,-2.1C736.6,734 650,793 532.8,800c-117.1,7 -210.1,-40.9 -282,-133c-0.9,0.7 -2.1,1.6 -3.3,2.6c-34.3,26.8 -72.2,33.5 -112.6,17.7c-39.8,-15.5 -63.1,-45.8 -69.7,-88c-5.9,-38.2 6.9,-70.5 33.2,-98.2c25.4,-26.8 55.1,-46.3 90.7,-56.3c2.6,-0.7 3.9,-1.8 4.2,-4.8c6,-48.7 21.6,-94.2 48.7,-135.2c52.6,-79.8 125.9,-129.4 220.5,-144.1c103.9,-16.1 195.2,12.8 272.6,84.1c24.2,22.3 43.9,48.3 60,77C795.9,323 796.6,324.2 797.6,325.8zM291,440.7c-2.6,-5.5 -6,-12 -8.6,-18.8c-0.6,-1.6 0.7,-5.1 2.1,-6c1.5,-1 4.6,-0.5 6.6,0.4c3,1.4 5.5,3.9 8.5,5.6c16.8,9.6 35.1,13.1 54.2,11.6c42.6,-3.4 79,-17.7 100.2,-58.2c0.8,-1.6 3.7,-3 5.4,-2.8c1.7,0.2 4.1,2.3 4.5,4c1,4.4 1.6,9 1.3,13.4c-1.1,16.8 -9.5,30.1 -21.5,41.1c-26.6,24.6 -58.7,34.1 -94.4,33.4c-2.1,0 -4.2,0 -6.2,0.4c-12.9,2.5 -23.3,9.4 -31.9,19c-20.4,22.6 -26.9,49.8 -24.1,79.2c2.4,24.7 0.4,48.4 -10.9,70.8c-1.6,3.1 -1.3,5.2 0.6,7.8c11.6,16.4 24.3,31.9 39.1,45.5c70.4,64.6 153.1,90.9 247.3,74.4c93.1,-16.3 161.2,-68.7 206.1,-151.6c1.5,-2.7 1.5,-4.8 0,-7.5c-10.6,-18.8 -13.6,-39.1 -12.1,-60.4c0.7,-9.8 1.1,-19.8 -0.1,-29.5c-2.8,-23.7 -13.4,-43.3 -33.7,-56.9c-2.7,-1.8 -5,-2 -8,-0.6c-4.8,2.2 -9.8,4.3 -14.9,5.6c-31.9,8.1 -62.3,3.3 -91.2,-11.4c-18.1,-9.2 -33.2,-21.8 -42.3,-40.5c-4.7,-9.7 -6.5,-20 -4.1,-30.6c0.5,-2.2 2.8,-4.8 4.8,-5.6c3.2,-1.2 5.1,1.4 6.4,4.4c4.7,10.7 12,19.5 20.8,27.1c20.9,17.8 45.5,27 72.5,29.4c24.8,2.2 48.4,-1.5 68.9,-17.1c1.5,-1.1 4.9,-1.1 6.5,-0.1c1.4,0.8 2.1,3.9 1.9,5.8c-0.3,3 -1.7,5.9 -2.4,8.4c17.7,-2.3 35.2,-4.6 53.6,-7c-2.7,-10.4 -5.4,-20.9 -8.2,-31.8c-10.9,3.3 -16.2,12.8 -25.2,17.9c3.3,-14.9 6.9,-29.6 11.1,-44.1c1.1,-3.7 1.1,-6.6 -0.6,-10.1c-14.7,-30.4 -33.8,-57.8 -58.3,-81.1c-72.5,-68.8 -158.7,-96.6 -256.4,-76.6c-112.6,23.1 -185.9,93 -220.9,202.6c-3.8,12 -5.8,24.6 -8.5,36.3C250.7,437.8 271.6,439.3 291,440.7zM311,462.4c-16.5,-4.5 -32.2,-7.7 -48.4,-9c-68.8,-5.2 -124.1,19.4 -166,74.4c-10.8,14.1 -15.9,30.2 -17.1,47.7c-4.2,61.7 46.5,110.3 107.9,103.7c47.4,-5.1 85.3,-47 85.2,-94.7c0,-14.8 -1.6,-29.7 -0.8,-44.5c1.5,-25.6 10.6,-48.5 28.3,-67.4C303.3,469.2 306.9,466.2 311,462.4zM738.7,447.4c26.3,22.7 35.2,51 34.8,83c-0.1,7.7 -1.4,15.5 -1.4,23.2c-0.1,63.8 67.4,104.8 123.8,75c49.6,-26.1 54.8,-85.5 33,-118.3c-16.7,-25.2 -39.1,-44.2 -66.7,-56.8c-29.7,-13.5 -60.9,-16.5 -92.9,-12C759.5,443 749.8,445.3 738.7,447.4zM786.4,374.9c0.6,0.2 0.9,0.3 1.2,0.3c18.8,-2.7 34.9,3.1 49.8,14.3c14.1,10.5 32.8,10.8 47.4,1.6c14.6,-9.2 22,-26.2 18.9,-43.6c-3.3,-18.9 -22.8,-35.3 -40.9,-34.4C826.8,315 796.1,339.7 786.4,374.9z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M401.6,648.3c1.3,-4.1 3.1,-12.6 6.7,-20.2c18.4,-38.2 44.9,-69.7 80.2,-93.4c13.6,-9.1 28.5,-15.6 45.5,-13c13.4,2 25.2,8.2 35.9,16.1c33.6,24.7 59.6,55.8 76.6,94c3.1,7.1 4.8,15.1 5.4,22.9c0.8,9.6 -5.6,14.7 -14.9,12.2c-7.3,-1.9 -14.3,-4.9 -21.2,-8.1c-18.9,-8.8 -37.4,-18.3 -56.4,-26.7c-21.5,-9.5 -43.5,-9.4 -65,0c-19.8,8.7 -39.1,18.4 -58.7,27.6c-5.5,2.6 -11.2,5 -17.1,6.6C407.2,669.5 401.5,664.7 401.6,648.3z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M480.7,305.7c-9.2,-1.8 -16.4,-3.7 -23.8,-4.6c-44,-5.1 -80.7,9.1 -110.3,41.8c-1.3,1.4 -2.4,3 -3.7,4.5c-4.1,4.5 -10,5.1 -14.2,1.5c-4.1,-3.5 -4.9,-9.5 -0.9,-13.9c6.7,-7.4 13.2,-15.2 21,-21.4c39.2,-31.6 83.4,-40.6 132,-27.7c8,2.1 11.4,9.8 6.7,15.5C485.4,303.7 482,304.8 480.7,305.7z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M568.6,279.9c51.8,0.6 90.4,18.1 120.2,54.4c3.5,4.3 3.9,8.7 1.3,12.5c-2.7,3.9 -6.6,5.4 -11,3.9c-2.1,-0.7 -4.2,-2.4 -5.7,-4.2c-24.5,-29.5 -55.9,-45.1 -94.2,-46.6c-12.8,-0.5 -25.4,1.4 -37.8,5c-8.3,2.4 -14.8,-3 -13.5,-11c0.8,-4.6 3.8,-7.1 8.1,-8C548.4,283.5 561,281.3 568.6,279.9z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M122.3,639.5c-9,-18.7 -14.4,-37.8 -14.5,-58.1c-0.1,-15.3 3.3,-29.8 11.6,-42.9c6.2,-9.8 14.3,-17.7 25,-24.2c-18.4,40 -19.1,77.2 12.4,111.1C145.4,630 134.2,634.6 122.3,639.5z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M903.8,603.7c-10.4,-4.2 -20.2,-8.2 -30.5,-12.5c12.6,-13.2 20.5,-28.3 22.1,-46.5c1.5,-17.9 -3,-34.5 -10.6,-50.5c0.4,-0.4 0.7,-0.7 1.1,-1.1c5.3,4.9 11.1,9.4 15.7,14.9c13.9,16.4 16.9,35.8 14.4,56.5C914.3,578 910.3,590.9 903.8,603.7z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M898.2,347.4c-4.4,3.4 -8.9,6.8 -13.8,10.5c-6.3,-20.6 -21.2,-29.7 -41.6,-32C860.8,314.5 885.7,325.8 898.2,347.4z"/>
+</vector>
diff --git a/res/drawable/icon_cry_color.xml b/res/drawable/icon_cry_color.xml
new file mode 100644
index 000000000..307937072
--- /dev/null
+++ b/res/drawable/icon_cry_color.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+ android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FFFFFF" android:pathData="M285,104.6c-2.8,-1.3 -5.9,-2.2 -9.1,-2.6c-14.8,-1.8 -28.7,7.6 -35.6,22.3c4.3,-20.7 21.1,-35.2 39.2,-33L285,104.6z"/>
+ <path android:fillColor="#FFE448"
+ android:pathData="M181.7,179.2m-112,0a112,112 0,1 1,224 0a112,112 0,1 1,-224 0"
+ android:strokeColor="#FFFFFF" android:strokeWidth="1.3498"/>
+ <path android:fillColor="#654E2B" android:pathData="M135.5,162.2c-12.4,3.1 -24.4,0.9 -31.3,-4.8c-1.3,-1.1 -3.4,0.2 -3,1.9c0,0 0,0 0,0.1c2.9,11.8 19.4,17.8 36.9,13.4s29.2,-17.4 26.3,-29.1c0,0 0,0 0,-0.1c-0.4,-1.7 -2.8,-1.9 -3.5,-0.2C157.5,151.6 148,159.1 135.5,162.2z"/>
+ <path android:fillColor="#654E2B" android:pathData="M227.8,162.2c12.4,3.1 24.4,0.9 31.3,-4.8c1.3,-1.1 3.4,0.2 3,1.9c0,0 0,0 0,0.1c-2.9,11.8 -19.4,17.8 -36.9,13.4s-29.2,-17.4 -26.3,-29.1c0,0 0,0 0,-0.1c0.4,-1.7 2.8,-1.9 3.5,-0.2C205.8,151.6 215.3,159.1 227.8,162.2z"/>
+ <path android:fillColor="#FFFFFF" android:pathData="M208,162.8"
+ android:strokeColor="#231F20" android:strokeWidth="1.3498"/>
+ <path android:fillColor="#FFFFFF" android:pathData="M114.8,162.8"
+ android:strokeColor="#231F20" android:strokeWidth="1.3498"/>
+ <path android:fillColor="#FFFFFF" android:pathData="M161.4,209.3"
+ android:strokeColor="#231F20" android:strokeWidth="1.3498"/>
+ <path android:fillColor="#6BB4EC" android:pathData="M118,172.8c-61.2,-21 -86.2,26.2 -86.2,26.2l-0.6,1.2c-5,11.3 -4.1,25.5 3.6,36.3c11.7,16.3 34.4,20.1 50.7,8.4c10.3,-7.3 15.6,-19 15.2,-30.8l0,-2c0,0 -5.2,-26.5 16.1,-38.9L118,172.8z"/>
+ <path android:fillColor="#FFFFFF" android:pathData="M57.8,230.2c-17.1,-17 -4.3,-38.7 -4.3,-38.7l0,0c-23.2,14.7 -7.8,43.5 -7.8,43.5l11.2,-4.6L57.8,230.2z"/>
+ <path android:fillColor="#6BB4EC" android:pathData="M253.5,167.7c54,-18.6 76.1,23.2 76.1,23.2l0.5,1.1c4.4,10 3.6,22.5 -3.2,32c-10.3,14.4 -30.3,17.7 -44.7,7.4c-9.1,-6.5 -13.7,-16.8 -13.4,-27.1l0,-1.8c0,0 4.6,-23.4 -14.2,-34.4L253.5,167.7z"/>
+ <path android:fillColor="#FFFFFF" android:pathData="M306.7,218.3c15.1,-15 3.8,-34.2 3.8,-34.2l0,0c20.5,13 6.9,38.4 6.9,38.4l-9.9,-4.1L306.7,218.3z"/>
+ <path android:fillColor="#6BB4EC" android:pathData="M272.3,148.1c6.2,-30.2 31.7,-29.1 31.7,-29.1l0.7,0.1c5.9,0.7 11.5,4.5 14,10.3c3.9,8.8 -0.1,19 -8.9,22.9c-5.5,2.4 -11.6,1.8 -16.3,-1.2l-0.8,-0.5c0,0 -9.6,-8.6 -19.9,-2.9L272.3,148.1z"/>
+ <path android:fillColor="#FFFFFF" android:pathData="M310.5,137.2c-2.8,-11.2 -14.9,-11.2 -14.9,-11.2l0,0c11.7,-6 19.8,7.4 19.8,7.4l-4.6,3.5L310.5,137.2z"/>
+ <path android:fillColor="#654E2B" android:pathData="M117.8,134.3L117.8,134.3c-1.6,-1.1 -2,-3.3 -0.8,-4.9c9.4,-12.1 23.9,-19.2 39.3,-19.2c5,0 9.9,0.7 14.6,2.2c1.9,0.6 2.8,2.6 2.1,4.4l0,0c-0.6,1.7 -2.4,2.5 -4.1,2c-4,-1.2 -8.3,-1.8 -12.5,-1.8c-13.3,0 -25.8,6.1 -34,16.5C121.2,134.9 119.2,135.3 117.8,134.3z"/>
+ <path android:fillColor="#654E2B" android:pathData="M242.1,134.3L242.1,134.3c1.6,-1.1 2,-3.3 0.8,-4.9c-9.4,-12.1 -23.9,-19.2 -39.3,-19.2c-5,0 -9.9,0.7 -14.6,2.2c-1.9,0.6 -2.8,2.6 -2.1,4.4l0,0c0.6,1.7 2.4,2.5 4.1,2c4,-1.2 8.3,-1.8 12.5,-1.8c13.3,0 25.8,6.1 34,16.5C238.6,134.9 240.6,135.3 242.1,134.3z"/>
+ <path android:fillColor="#00000000"
+ android:pathData="M342.5,186.5l-0.1,-0.2l-0.7,-1.5l-0.1,-0.2c-0.4,-0.8 -7.1,-13 -21.2,-22.8c5.1,-3.5 9,-8.4 11.3,-14.3c3,-7.7 2.8,-16.1 -0.5,-23.6c-4.4,-9.9 -13.9,-16.9 -24.7,-18.2l-0.2,0l-0.9,-0.1l-0.5,0c0,0 -0.4,0 -1,0c-1.7,0 -9.2,0.2 -17.7,4c-22.5,-33.6 -60.9,-55.8 -104.3,-55.8C119,53.6 67,99.8 57.6,159.8c-25.6,10.6 -37.1,31.7 -37.8,32.9l-0.1,0.2l-0.8,1.7l-0.1,0.2c-7.1,16.3 -5.2,35.3 5,49.6c9.3,13 24.5,20.8 40.5,20.8c0,0 0,0 0,0c7.6,0 14.9,-1.7 21.6,-5c23,27.1 57.4,44.4 95.7,44.4c43.6,0 82.1,-22.4 104.6,-56.3c4.7,1.6 9.6,2.4 14.6,2.4c14.7,0 28.5,-7.1 37.1,-19C347.3,218.8 349,201.4 342.5,186.5z"
+ android:strokeColor="#231F20" android:strokeWidth="5.3992"/>
+ <path android:fillColor="#654E2B" android:pathData="M228.1,244.2c-6,3.6 -29.7,-14.2 -41.7,-14.2c-8.9,0 -16.6,3.2 -25.5,7.7c-5.4,2.8 -13.1,8.5 -16.2,6.5c-12.4,-8 22.7,-50.9 41.7,-50.3C205.3,194.6 240.1,236.9 228.1,244.2z"/>
+</vector>
diff --git a/res/drawable/icon_fork_and_knife.xml b/res/drawable/icon_fork_and_knife.xml
new file mode 100644
index 000000000..7690c805f
--- /dev/null
+++ b/res/drawable/icon_fork_and_knife.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="28dp" android:viewportHeight="360.0"
+ android:viewportWidth="360.0" android:width="28dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M63.1,173.7c15.9,-0.3 31.7,-0.5 47.4,-0.8c-17.5,-17.8 -33.7,-36.8 -49.8,-55c12.7,-12.7 25.4,-25.3 38.1,-38.1c1.4,1.2 3.2,2.7 4.9,4.3c14,12.6 28.1,25.2 42.1,37.8c2.3,2.1 4.5,4.3 6.7,6.5c7.9,8.4 9.5,18.1 5.8,28.8c-0.4,1 -0.2,1.5 0.6,2.3c4.6,4.2 9.1,8.4 13.6,12.6c1,0.9 3.3,1 4.3,0.1c5.5,-5.1 11,-10.3 16.5,-15.4c0.3,-0.2 0.5,-0.8 0.4,-1.1c-4,-12.7 -1.5,-24.8 4.7,-36.1c8.3,-15.2 20.5,-25.9 37.1,-31.2c8.9,-2.9 17.9,-3.3 26.8,0.1c11.5,4.4 18.1,13.1 19.8,25.1c1.8,12.3 -1.8,23.5 -8.4,33.8c-7,11 -16.4,19.3 -28.2,24.8c-0.2,0.1 -0.4,0.2 -0.6,0.6c16.9,0.2 33.8,0.5 50.9,0.7c1.1,6.8 2.1,13.4 3.2,20.2c12.7,0.2 25.3,0.5 38,0.7c-0.1,0.3 -0.3,0.7 -0.5,1.2c-4.2,8.1 -8.3,16.3 -12.5,24.4c-0.5,0.9 -0.2,1.5 0.2,2.2c7.3,11.3 14.7,22.6 22,33.8c0.2,0.3 0.4,0.7 0.9,1.4c-20.9,-0.3 -41.6,-0.6 -62.4,-1c-0.2,-1.6 -0.5,-3.4 -0.7,-5.1c-0.6,-4.6 -1.1,-9.2 -1.6,-13.8c-0.1,-0.9 -0.5,-1.2 -1.3,-1.2c-10.5,0 -21,0 -31.4,-0.1c-2.6,0 -5.1,0 -7.7,0c0,0.1 -0.1,0.3 -0.1,0.4c1.6,1.5 3.1,3 4.7,4.4c3.3,2.9 5.9,6.2 6.8,10.6c1.7,7.6 -1.8,15.3 -8.7,19.1c-6.6,3.6 -15.2,2.6 -20.5,-2.9c-7.4,-7.7 -14.6,-15.6 -21.8,-23.4c-2.2,-2.4 -4.4,-4.8 -6.7,-7.1c-0.4,-0.4 -1,-0.7 -1.6,-0.7c-12.6,0 -25.2,0 -37.7,0c-1,0 -1.7,0.2 -2.4,1c-8.3,9 -16.7,18 -25.1,26.9c-6.6,7.1 -17.9,7.5 -24.7,0.8c-7.2,-7.1 -7.3,-18.1 -0.1,-25.1c1.1,-1.1 2.2,-2.1 3.4,-3.3c-0.4,-0.1 -0.7,-0.2 -1,-0.2c-9.8,0 -19.6,0.1 -29.4,0.1c-0.9,0 -1.3,0.3 -1.4,1.3c-0.6,5.7 -1.4,11.3 -2.1,17c-0.1,0.5 -0.1,1 -0.2,1.4c-20.7,0.3 -41.3,0.6 -62.3,1c0.5,-0.8 0.8,-1.2 1,-1.7c7.3,-11.2 14.6,-22.4 21.9,-33.6c0.6,-0.9 0.5,-1.5 0.1,-2.4c-4.2,-8.2 -8.4,-16.4 -12.6,-24.6c-0.1,-0.2 -0.2,-0.5 -0.3,-0.6c13.2,-0.3 26.3,-0.5 39.6,-0.8C61.5,186.9 62.3,180.4 63.1,173.7zM187.6,172.7c5.4,0 10.5,0 15.5,0c0.4,0 0.9,-0.4 1.2,-0.7c1.8,-1.9 3.6,-3.8 5.4,-5.8c0.6,-0.7 1.1,-0.9 1.9,-0.4c0.8,0.5 1.7,0.9 2.6,1.3c7.2,2.8 14.4,2.6 21.6,0.3c16.5,-5.3 28.2,-16.2 35.3,-31.9c3.1,-6.8 4.5,-14 3.2,-21.5c-1.6,-8.9 -6.5,-15.3 -15.1,-18.5c-6.5,-2.4 -13.2,-2.2 -19.7,-0.3c-17.1,5.1 -29.1,16.1 -36.4,32.2c-3,6.6 -4.2,13.7 -3.2,21c0.5,3.4 1.7,6.6 3.4,9.6C198.1,162.9 193,167.7 187.6,172.7zM86.9,102.3c13.3,13 26.5,26 39.5,38.8c-1.4,1.5 -2.8,2.9 -4.3,4.4c-13,-13 -26.1,-26.1 -39.2,-39.2c-1.2,1.2 -2.4,2.4 -3.6,3.7c12.9,13.2 25.9,26.4 38.8,39.5c-1.4,1.4 -2.7,2.8 -4.1,4.2c-13,-13.2 -26,-26.5 -39,-39.7c-1.4,1.3 -2.6,2.5 -3.9,3.8c0.3,0.4 0.5,0.7 0.8,1c5.5,6.2 10.9,12.5 16.5,18.6c8.5,9.3 17,18.6 25.7,27.8c4.9,5.3 11.1,7.5 18.2,5.8c3.1,-0.7 6,-2.2 9.2,-3.4c1,1.1 2.4,2.5 3.7,4c0.7,0.8 1.5,1.2 2.6,1.2c4.1,-0.1 8.3,0 12.4,0c0.4,0 0.8,0 1.6,-0.1c-4.6,-4.3 -9,-8.4 -13.4,-12.5c0.8,-1.7 1.7,-3.2 2.4,-4.8c3.2,-7.8 2.4,-15 -3.4,-21.4c-1.5,-1.6 -3.1,-3.2 -4.7,-4.7c-10.8,-9.9 -21.7,-19.7 -32.6,-29.5c-3.7,-3.3 -7.4,-6.5 -11.1,-9.7c-1.3,1.3 -2.6,2.5 -4,3.8c13.3,13 26.5,26.1 39.7,39c-1.4,1.5 -2.7,2.8 -4.1,4.2c-13.2,-12.9 -26.4,-25.9 -39.5,-38.8C89.6,99.7 88.3,101 86.9,102.3zM288,182.3c-72.4,-0.8 -144.6,-0.8 -216.9,0.2c-1.7,15.2 -3.4,30.3 -5.1,45.2c76.5,-0.2 152.7,-0.3 229,-0.5C292.7,212.2 290.3,197.4 288,182.3zM55.9,236.9c1.3,-11.5 2.5,-22.9 3.8,-34.4c-8.1,0.3 -16,0.5 -24,0.8c0.4,0.7 0.6,1.3 0.9,1.8c2.6,4.9 5.2,9.8 7.8,14.7c0.5,1 0.5,1.6 -0.1,2.5c-5.2,8.1 -10.4,16.3 -15.6,24.5c-0.2,0.4 -0.4,0.7 -0.7,1.2c12.5,-0.3 24.9,-0.5 37.3,-0.8c0.4,-3.4 0.8,-6.9 1.3,-10.4C63,236.9 59.5,236.9 55.9,236.9zM330,248.1c-0.4,-0.7 -0.7,-1.1 -1,-1.6c-5,-7.9 -10,-15.8 -15.1,-23.7c-0.8,-1.2 -0.9,-2.1 -0.1,-3.4c2.8,-5 5.4,-10.1 8.1,-15.2c0.2,-0.3 0.2,-0.6 0.4,-1c-7.4,-0.2 -14.6,-0.5 -21.9,-0.7c1.8,11.3 3.5,22.5 5.3,33.8c-4.8,0 -9.5,0 -14.3,0c0.5,3.8 0.9,7.3 1.3,10.9C305.1,247.6 317.4,247.9 330,248.1zM205.9,236.4c0,0.1 -0.1,0.2 -0.1,0.3c2.1,2.3 4.3,4.6 6.4,6.8c5.8,6.2 11.5,12.4 17.3,18.6c1.9,2.1 4.4,3.1 7.2,2.9c4.2,-0.3 7.3,-2.4 8.7,-6.5c1.4,-4 0.4,-7.6 -2.7,-10.5c-3.9,-3.6 -7.7,-7.3 -11.7,-10.8c-0.6,-0.5 -1.5,-0.9 -2.3,-0.9c-6.6,0 -13.1,0 -19.7,0C208,236.4 206.9,236.4 205.9,236.4zM144.1,236.6c-0.3,-0.1 -0.4,-0.1 -0.6,-0.1c-7.9,0 -15.8,0 -23.7,0.1c-0.5,0 -1.1,0.2 -1.4,0.6c-3.1,2.8 -6.2,5.6 -9.2,8.6c-3.9,3.8 -3.9,10 0,13.8s10.2,3.6 13.9,-0.4c5.1,-5.5 10.2,-11 15.3,-16.4C140.4,240.6 142.2,238.7 144.1,236.6z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M219.2,157.5c22.3,0.5 43.5,-21.5 43.1,-44c1.3,2.4 1.8,4.6 2.1,7c1.1,10.7 -3,19.6 -10,27.4c-5.4,6 -12.1,10.1 -20.1,11.6c-4.6,0.9 -9.2,0.7 -13.7,-1.2c-0.3,-0.1 -0.6,-0.2 -0.9,-0.4C219.6,157.8 219.5,157.7 219.2,157.5z"/>
+</vector>
diff --git a/res/drawable/icon_happy.xml b/res/drawable/icon_happy.xml
new file mode 100644
index 000000000..ed5327f20
--- /dev/null
+++ b/res/drawable/icon_happy.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="1008"
+ android:viewportHeight="1008">
+
+ <path
+ android:fillColor="?attr/fillColorSelector"
+ android:pathData="M491.1,869.9c-101.8-1.7-190.2-36.8-264.2-107.5c-22.9-21.9-42.3-46.5-59.1-73.3c-1.7-2.7-4.6-5.3-7.5-6.6
+c-42.7-19.2-75.5-48.7-91.8-93.1c-22.2-60.2-8.9-114.2,33.2-161.6c3.3-3.7,6.7-7.5,10.7-10.5c5.8-4.2,8.1-9.8,9.7-16.6
+c16.3-68.4,49.5-127.5,98.7-177.6c53.9-54.9,118.5-91,194.1-105.4c127.4-24.2,240,7.3,336.1,94.6c42.9,38.9,73.8,86.3,95,140.2
+c1,2.4,3,4.7,5.2,6.3c35,26.1,58,59.8,65,103.4c7,44.2-3.9,84.1-31.4,119c-9.2,11.7-20.9,21.3-31.4,32c-2,2.1-4.1,4.4-5.1,7
+c-42.6,109.6-118.5,185.6-228.7,226.9c-38.3,14.4-78.3,21.3-119.2,22.1C497.3,869.4,494.3,869.7,491.1,869.9z
+M490.9,853.6
+c3.2,0,6.3,0.1,9.5,0c38.7-1,76.6-7.4,112.9-21C721,792.4,794.6,717.8,835,610.2c0.9-2.5,2.8-4.7,4.7-6.6
+c10.4-10.3,22.2-19.4,31.3-30.7c25.9-32.1,36.2-68.9,29.1-109.9c-6.9-39.9-28.8-70.2-61.4-93.5c-2.7-2-5.3-5.1-6.5-8.2
+c-17.1-44.7-41.1-85.4-74.5-119.6c-97-99.5-214.4-135.9-350.1-106.1c-137.2,30.1-244.3,142-272.9,280c-0.5,2.3-2.3,4.6-4,6.5
+c-8.8,9.3-19,17.5-26.6,27.6C68.9,497,63.4,547.5,90.9,600.1c17.3,33.1,45.2,54.9,79.4,69c3.6,1.5,6.3,3.4,8.6,6.9
+C251,791.2,355.8,849.1,490.9,853.6z" />
+ <path
+ android:fillColor="?attr/fillColorSelector"
+ android:pathData="M514.3,723.5c-67.4-1-118.8-23.7-162.2-64.8c-37-35.1-61.5-77.9-75.4-126.8c-0.9-3.2-0.9-7.4,0.4-10.4
+c2-4.7,7.7-5.1,12.9-1.7c20.2,13.1,41.1,24.7,63.6,33.3c117.2,44.6,226.7,29.4,328.2-43.7c14.4-10.4,27.1-23,40.5-34.9
+c3.8-3.3,7.5-4.8,12.2-2.7c4.7,2.1,5.8,6.1,5.4,10.8c-4.1,48.5-18.1,93.7-45.1,134.4c-34.5,52.1-81,87.8-142.9,101.3
+C537.3,721.5,522.2,722.4,514.3,723.5z
+M498.3,691.2c35,0,59.6-5.2,82.9-16c47.7-22.1,80.7-58.8,103.2-105.6
+c2.8-5.8,2.3-10-1.3-13.2c-3.6-3.2-7.9-3.2-13.3-0.2c-10.9,6-21.7,12.3-32.9,17.7C586.7,598,533.7,610,478.1,609.9
+c-41.8,0-82.4-7.3-121.8-21.3c-4.4-1.6-8.6-1.8-11.7,2.4c-3,4.1-2,8.2,1.1,11.9c9.1,10.6,17.5,21.9,27.5,31.6
+C410.7,670.4,455.1,690.6,498.3,691.2z" />
+ <path
+ android:fillColor="?attr/fillColorSelector"
+ android:pathData="M164.1,436.6c16.1-121.6,120.1-256,286-276.3c177.5-21.7,316.7,95.4,356.9,227c-1.3-0.5-2.3-0.9-3.3-1.2
+c-11.9-4.1-23.8-8.5-35.8-12.3c-3.3-1-5.2-2.4-6.7-5.6c-40.4-85.6-106-141.4-197.5-165.4c-132.7-34.8-274.8,30.3-336.3,153
+c-9.6,19.3-17.4,39.2-22.8,60.1c-0.4,1.6-1.8,3.6-3.3,4.3c-11.9,5.6-23.9,10.9-35.8,16.2C165.1,436.5,164.6,436.5,164.1,436.6z" />
+ <path
+ android:fillColor="?attr/fillColorSelector"
+ android:pathData="M198.9,646.1c9.6,1.5,18.8,3,28,4.3c2.5,0.4,5,0.9,7.5,0.5c6.6-0.9,10.2,1.9,14,7.3
+c48.1,67.8,113,110.3,195.1,123.3c94,14.9,177.1-10.5,248-74.2c30.9-27.8,54.3-61.2,70.9-99.3c1.2-2.8,2.8-4.2,5.9-5.3
+c13.6-4.7,27-10,39.7-14.8c-27.1,98.9-123.6,211.4-273,230.8C374.4,839.7,249.1,745.2,198.9,646.1z" />
+ <path
+ android:fillColor="?attr/fillColorSelector"
+ android:pathData="M403.7,472.1c-11.4-10.2-18.2-22.9-21-37.6c-4.3-22-0.7-42.5,13-60.5c21.8-28.5,59.3-28.1,80.7,0.6
+c18.6,24.8,18.8,62.4,0.5,87.4c-0.9,1.2-1.9,2.3-3.4,4.1c-0.2-4.5-0.2-8.4-0.6-12.2c-1-10.3-5-19.3-12.3-26.7
+c-13.5-13.6-33.2-13.1-46,1.1c-9.5,10.5-12.7,23.1-11.3,37c0.2,1.8,0.5,3.6,0.7,5.4C404.3,471.2,404,471.5,403.7,472.1z" />
+ <path
+ android:fillColor="?attr/fillColorSelector"
+ android:pathData="M612.5,453.7c-0.6-5.9-0.6-11.4-1.7-16.7c-3.4-17.3-16.1-29.9-31.3-31.3c-10.8-1-19.6,3.3-26.5,11.2
+c-9.7,11.1-12.6,24.3-10.6,38.7c0.1,1,0.4,2,0.5,3c0,0.3-0.1,0.6-0.4,1.8c-2.7-2.8-5.2-5.1-7.4-7.8c-21.1-25.6-20.6-67.8,1-93
+c21.7-25.4,56.5-24.9,77.4,1.1c20.3,25.2,20.9,64.5,1.3,90.3C614.3,451.9,613.5,452.7,612.5,453.7z" />
+ <path
+ android:fillColor="?attr/fillColorSelector"
+ android:pathData="M449.2,281.7c0,8.4-6,14.7-14.5,15.3c-38.7,2.9-65.6,22.2-80.1,58.3c-3.8,9.4-12.1,13.5-20.7,10.2
+c-8.3-3.1-11.7-11.9-8.4-21.1c16-44.7,58.8-76.4,106-78.4C442,265.6,449.2,271.9,449.2,281.7z" />
+ <path
+ android:fillColor="?attr/fillColorSelector"
+ android:pathData="M556.6,254.6c43.5,1.6,76.7,18.7,100.5,53c5.9,8.5,4.6,17.7-2.9,22.9c-7.6,5.3-16.7,2.9-22.9-5.5
+c-22.4-30.8-52.4-43.5-90.1-37.4c-9.7,1.6-17.9-3.5-19.3-12.1c-1.5-9.4,3.9-17,13.8-18.5C543.3,255.9,551,255.3,556.6,254.6z" />
+ <path
+ android:fillColor="?attr/fillColorSelector"
+ android:pathData="M719.2,400c44.2,0.7,87.2,30.1,103.7,71.1c2.3,5.8,1,10.2-3.8,12.1c-4.5,1.8-8.4-0.3-11-5.7
+c-18.3-39.4-49.1-59.9-92.6-61.5c-5.8-0.2-9.4-3.2-9.4-8.1c0.1-4.8,3.7-7.8,9.5-7.9C716.9,400,718,400,719.2,400z" />
+ <path
+ android:fillColor="?attr/fillColorSelector"
+ android:pathData="M299,450.5c0.1,4.2-2.7,7.3-7.5,7.6c-13.8,1-27,4-39.3,10.3c-22.2,11.3-37.7,28.6-46.9,51.6
+c-0.2,0.6-0.4,1.3-0.7,1.9c-2,4.9-5.9,7-10.1,5.4c-4.3-1.6-6.5-5.8-4.2-10.7c4.2-9,8.2-18.4,13.9-26.4
+c20.7-29.3,49.5-44.6,85.1-47.2C295.2,442.6,298.9,445.7,299,450.5z" />
+</vector> \ No newline at end of file
diff --git a/res/drawable/icon_happy_color.xml b/res/drawable/icon_happy_color.xml
new file mode 100644
index 000000000..b03fd493f
--- /dev/null
+++ b/res/drawable/icon_happy_color.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="360"
+ android:viewportHeight="360">
+
+ <path
+ android:fillColor="#FFE448"
+ android:strokeColor="#FFFFFF"
+ android:strokeWidth="1.5402"
+ android:strokeMiterLimit="10"
+ android:pathData="M 181.4 51.1 C 251.981991028 51.1 309.2 108.318008972 309.2 178.9 C 309.2 249.481991028 251.981991028 306.7 181.4 306.7 C 110.818008972 306.7 53.6 249.481991028 53.6 178.9 C 53.6 108.318008972 110.818008972 51.1 181.4 51.1 Z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:strokeColor="#231F20"
+ android:strokeWidth="1.7331"
+ android:strokeMiterLimit="10"
+ android:pathData="M208.8,142.3" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:strokeColor="#231F20"
+ android:strokeWidth="1.5402"
+ android:strokeMiterLimit="10"
+ android:pathData="M103.9,166.4" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:strokeColor="#231F20"
+ android:strokeWidth="1.5402"
+ android:strokeMiterLimit="10"
+ android:pathData="M161.1,215.1" />
+ <path
+ android:fillColor="#FFE448"
+ android:pathData="M 86.8 149.6 C 116.568148016 149.6 140.7 170.060586933 140.7 195.3 C 140.7 220.539413067 116.568148016 241 86.8 241 C 57.0318519841 241 32.9 220.539413067 32.9 195.3 C 32.9 170.060586933 57.0318519841 149.6 86.8 149.6 Z" />
+ <path
+ android:fillColor="#FFE448"
+ android:pathData="M 273.4 133 C 303.168148016 133 327.3 153.460586933 327.3 178.7 C 327.3 203.939413067 303.168148016 224.4 273.4 224.4 C 243.631851984 224.4 219.5 203.939413067 219.5 178.7 C 219.5 153.460586933 243.631851984 133 273.4 133 Z" />
+ <path
+ android:fillColor="#654E2B"
+ android:pathData="M103.3,190.2c-2.5-1.7-5.7,0.7-5,3.6c12.6,46.1,51.9,78.2,95.7,74.7c45-3.6,79.4-43.7,82.9-93
+c0.2-3.4-3.9-5.2-6.3-2.8c-22.4,22.5-51.3,37.1-83.7,39.8C156.8,214.9,127.9,206.5,103.3,190.2z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M193.1,256.3c-26.7,2.1-52-11.5-68.2-34.5c-1.9-2.6,0.8-6.1,3.8-5c19,6.9,39,9.6,59.4,8
+c22.2-1.8,43.6-8.9,62.7-20.6c3.1-1.9,6.8,1.3,5.3,4.6C243.9,235.3,220.6,254,193.1,256.3z" />
+ <path
+ android:fillColor="#654E2B"
+ android:pathData="M181,151.6c0-14-9.4-25.3-21-25.3s-21,11.3-21,25.3c0,8.6,3.6,16.2,9.1,20.8c-0.4-1.6-0.6-3.2-0.6-5
+c0-9,6.1-16.3,13.6-16.3c7.5,0,13.6,7.3,13.6,16.3c0,0.9-0.1,1.8-0.2,2.6C178.4,165.4,181,158.9,181,151.6z" />
+ <path
+ android:fillColor="#654E2B"
+ android:pathData="M67.3,193.5L67.3,193.5c-1.6-0.4-2.5-2.1-2-3.7c4.3-12.4,14.1-22.2,26.6-26.5c4-1.4,8.2-2.1,12.4-2.3
+c1.7-0.1,3,1.3,3,3l0,0c-0.1,1.5-1.3,2.7-2.8,2.8c-3.6,0.1-7.2,0.8-10.7,2c-10.8,3.7-19.2,12.1-23,22.8
+C70.3,193.1,68.8,193.9,67.3,193.5z" />
+ <path
+ android:fillColor="#654E2B"
+ android:pathData="M307.4,176.5L307.4,176.5c1.7-0.5,2.5-2.4,1.9-4c-5.1-12.7-15.8-22.4-29.1-26.3c-4.3-1.2-8.7-1.8-13.1-1.8
+c-1.7,0-3.1,1.6-2.9,3.3l0,0c0.1,1.6,1.5,2.8,3.1,2.8c3.8,0,7.6,0.5,11.3,1.5c11.5,3.3,20.7,11.7,25.1,22.7
+C304.2,176.2,305.8,177,307.4,176.5z" />
+ <path
+ android:fillColor="#654E2B"
+ android:pathData="M234.4,147c0-14-9.4-25.3-21-25.3c-11.6,0-21,11.3-21,25.3c0,8.6,3.6,16.2,9.1,20.8c-0.4-1.6-0.6-3.2-0.6-5
+c0-9,6.1-16.3,13.6-16.3c7.5,0,13.6,7.3,13.6,16.3c0,0.9-0.1,1.8-0.2,2.6C231.8,160.8,234.4,154.3,234.4,147z" />
+ <path
+ android:fillColor="#654E2B"
+ android:strokeColor="#654E2B"
+ android:strokeWidth="6.1608"
+ android:strokeMiterLimit="10"
+ android:pathData="M122.1,128.4L122.1,128.4
+c-1.6-0.4-2.5-2.1-2-3.7c4.3-12.4,14.1-22.2,26.6-26.5c4-1.4,8.2-2.1,12.4-2.3c1.7-0.1,3,1.3,3,3l0,0c-0.1,1.5-1.3,2.7-2.8,2.8
+c-3.6,0.1-7.2,0.8-10.7,2c-10.8,3.7-19.2,12.1-23,22.8C125.1,127.9,123.6,128.8,122.1,128.4z" />
+ <path
+ android:strokeColor="#231F20"
+ android:strokeWidth="6.1608"
+ android:strokeMiterLimit="10"
+ android:pathData="M342.5,173.2c-1.5-18.1-11.5-33.6-26.6-43.6
+c-7.8-21.2-20.5-40.5-37.5-56.1c-26.5-24.4-60.9-37.8-96.8-37.8c-3.9,0-7.8,0.2-11.6,0.5c-38.1,3.1-72.8,20.8-97.6,49.9
+c-15.9,18.7-26.6,40.7-31.3,64.2c-2,1.6-3.8,3.2-5.6,5c-12.7,12.7-19,28.9-17.6,45.6c1.9,23,17.7,42,40.1,50.6
+c7.1,12.1,16,23.3,26.6,33c26.5,24.4,60.9,37.8,96.8,37.8c3.9,0,7.8-0.2,11.6-0.5c58.4-4.7,105.8-44,123.9-96.1
+c2.9-2.1,5.6-4.4,8.1-6.9C337.5,206.1,343.8,189.9,342.5,173.2z" />
+ <path
+ android:fillColor="#654E2B"
+ android:strokeColor="#654E2B"
+ android:strokeWidth="6.1608"
+ android:strokeMiterLimit="10"
+ android:pathData="M196.3,96.1L196.3,96.1
+c-0.5-1.6,0.5-3.3,2.2-3.6c12.9-2.7,26.3,0.7,36.4,9.2c3.3,2.8,6,5.9,8.3,9.5c0.9,1.4,0.4,3.3-1.1,4.1l0,0c-1.3,0.7-3,0.3-3.8-1
+c-2-3-4.4-5.8-7.2-8.2c-8.7-7.4-20.3-10.3-31.4-8C198.2,98.5,196.7,97.6,196.3,96.1z" />
+</vector> \ No newline at end of file
diff --git a/res/drawable/icon_hello.xml b/res/drawable/icon_hello.xml
new file mode 100644
index 000000000..1181ec257
--- /dev/null
+++ b/res/drawable/icon_hello.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="72.0"
+ android:viewportWidth="72.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M27.6,44.6c0,0 -0.1,0.1 -0.1,0.1c-0.4,1.1 -1.2,1.8 -2.4,1.9c-1.2,0.2 -2.4,-0.1 -3.5,-0.6c-0.1,0 -0.2,-0.1 -0.3,-0.1c-1.4,-1.2 -2.3,-2.6 -2.2,-4.6c0,-0.2 0.1,-0.5 0.2,-0.7c0.1,-0.2 0.1,-0.5 0.1,-0.7c-0.1,-0.9 -0.2,-1.7 -0.3,-2.6c-0.3,0.1 -0.5,0.2 -0.8,0.3c0,0 -0.1,0.1 -0.1,0.2c0.2,1.6 0.3,3.1 0.5,4.7c0.2,1.4 0.5,2.8 0.7,4.2c0.3,1.6 -0.8,3 -2.5,3.2c-1.2,0.1 -2.4,-0.1 -3.5,-0.6c-0.4,-0.2 -0.8,-0.6 -1.2,-0.9c-0.1,0 -0.1,-0.2 -0.1,-0.2c-0.5,-2.3 -0.8,-4.6 -1,-6.9c0,-0.4 -0.1,-0.7 -0.1,-1.1c0,-0.2 -0.1,-0.2 -0.2,-0.3c-1.5,-0.6 -2.6,-1.6 -2.9,-3.2c-0.2,-1.1 0.2,-2 1.1,-2.7c0.4,-0.3 0.9,-0.5 1.3,-0.8c0.1,-0.1 0.2,-0.1 0.2,-0.3c-0.1,-1.8 -0.1,-3.6 -0.1,-5.3c0,-1.6 0.1,-3.2 0.1,-4.8c0,-0.4 0.1,-0.8 0.1,-1.3c0,-0.2 0,-0.2 0.2,-0.2c1.3,-0.1 2.5,-0.2 3.8,-0.2c1.1,0 1.9,0.5 2.7,1.1c0,0 0.1,0.1 0.1,0.2c0.2,0.8 0.4,1.6 0.6,2.3c0.2,0.8 0.1,1.6 -0.1,2.3c-0.3,0.7 0,1.4 -0.1,2.1c0,0.3 0,0.5 0,0.8c0.3,-0.1 0.5,-0.1 0.7,-0.2c0,0 0.1,-0.1 0.1,-0.2c-0.1,-1.3 -0.1,-2.6 -0.2,-3.9c0,-1.5 0,-2.9 0,-4.4c0.1,-1.5 1.4,-2.7 2.9,-2.9c1.3,-0.1 2.4,0.1 3.5,0.8c0.2,0.1 0.4,0.3 0.6,0.4c0.2,0.1 0.3,0.3 0.3,0.5c0,1.2 0,2.3 0.1,3.5c0,1.1 0.1,2.1 0.1,3.2c0,0 0,0.1 0.1,0.1c0,-0.1 0.1,-0.2 0.1,-0.3c0.4,-1.1 1,-2.1 1.9,-2.8c1.7,-1.4 4.3,-1.2 5.9,0.4c0.3,0.3 0.6,0.6 0.9,1c0,-0.1 0,-0.3 0,-0.4c0,-2.1 0.1,-4.2 0.1,-6.4c0,-0.7 0.1,-1.4 0.6,-2c0.8,-0.9 1.7,-1.2 2.9,-1.1c1.1,0.1 2.2,0.6 3,1.4c0,0 0,-0.1 0,-0.1c0.3,-1.3 1.5,-2.2 3.1,-2.2c1.3,0.1 2.5,0.5 3.4,1.5c0.6,0.6 0.9,1.3 0.9,2.1c0,1.5 -0.1,3.1 -0.2,4.6c0,0 0,0.1 0,0.2c0.1,-0.2 0.2,-0.2 0.2,-0.3c0.7,-1.2 1.8,-2 3.1,-2.4c0.1,0 0.2,0 0.2,0c0.6,0.4 1.3,0.4 2.1,0.3c1.8,-0.1 3.3,0.5 4.4,1.9c0.7,0.9 1.2,1.9 1.5,3c0.4,1.3 0.5,2.7 0.5,4.1c0,2.2 -0.1,4.3 -0.6,6.4c-0.4,1.4 -0.9,2.7 -1.8,3.9c-2.3,2.9 -6.4,3 -8.8,0.3c-0.2,-0.2 -0.3,-0.4 -0.6,-0.7c0,0.5 0.1,0.8 0.1,1.2c0,0.2 0,0.4 -0.1,0.5c-0.8,2 -2.5,2.2 -4,1.8c-0.7,-0.2 -1.4,-0.5 -2.1,-0.9c-0.2,0.3 -0.4,0.7 -0.6,1c-0.8,0.8 -1.8,1 -2.8,0.9c-0.6,-0.1 -1.2,-0.3 -1.9,-0.5c-1.1,1.6 -2.6,2.7 -4.7,2.9C30.8,46.7 29.1,46 27.6,44.6zM13.3,37c0.2,1.6 0.3,3.2 0.5,4.8c0.2,1.7 0.5,3.4 0.7,5.1c0,0.1 0.1,0.3 0.2,0.3c0.6,0.2 1.2,0.4 1.8,0.4c0.4,0 0.6,-0.1 0.5,-0.6c-0.3,-2 -0.7,-4 -0.9,-6c-0.2,-1.5 -0.3,-3.1 -0.4,-4.7c0,-0.2 0,-0.3 0.2,-0.4c1.2,-0.4 2.3,-0.9 3.5,-1.3c0.6,-0.2 1.3,-0.4 1.9,-0.6c0.3,2.6 0.5,5.1 0.8,7.6c-0.5,-0.1 -0.5,0 -0.5,0.4c0.1,0.7 0.5,1.3 1,1.8c0.3,0.3 0.7,0.3 1.1,0.4c0.1,0 0.3,0.1 0.4,0.1c0.2,0 0.5,0 0.7,0s0.4,-0.2 0.3,-0.5c0,-0.2 -0.1,-0.4 -0.1,-0.6c-0.4,-2.5 -0.7,-5 -0.9,-7.5c-0.2,-2.9 -0.4,-5.7 -0.6,-8.6c-0.1,-1.9 -0.1,-3.8 -0.2,-5.7c0,-0.1 -0.1,-0.2 -0.2,-0.3c-0.4,-0.2 -0.9,-0.3 -1.4,-0.2c-0.6,0.1 -0.9,0.4 -0.9,1c0,0.4 0,0.9 0,1.3c0,2.8 0.1,5.5 0.3,8.3c0,0.3 0,0.5 0,0.8c-0.1,-0.1 -0.2,-0.1 -0.2,-0.1c-0.4,-0.3 -0.8,-0.4 -1.2,-0.2c-1.3,0.5 -2.6,1 -3.8,1.4c-0.1,0 -0.2,0.1 -0.4,0.1c0,-0.1 0,-0.1 0,-0.1c-0.1,-2.4 -0.1,-4.8 -0.2,-7.2c0,-0.1 0.1,-0.2 0.2,-0.3s0.2,-0.2 0.2,-0.3c-0.1,-0.5 -0.2,-1 -0.3,-1.5c0,-0.3 -0.2,-0.4 -0.4,-0.4c-0.6,0 -1.2,0 -1.8,0c-0.2,0 -0.3,0.1 -0.3,0.3c0,1.4 -0.1,2.8 -0.1,4.2c0,2.1 0.1,4.1 0.2,6.2c0,0.2 -0.1,0.3 -0.3,0.4c-0.7,0.4 -1.5,0.8 -2.2,1.1c-0.3,0.2 -0.3,0.3 -0.2,0.6c0.2,0.4 0.5,0.8 1,1c0.2,0.1 0.5,0.1 0.7,0C12.5,37.3 12.9,37.2 13.3,37zM53.1,23.5c0,0 -0.1,-0.1 -0.1,-0.1c-0.5,-0.6 -0.9,-0.7 -1.4,0c-0.4,0.5 -0.7,1 -1,1.6c-0.6,1.3 -0.9,2.7 -1.1,4.2c-0.3,2.1 -0.3,4.1 0.3,6.1c0.4,1.3 0.8,2.5 1.8,3.5c1.3,1.4 3.3,1.5 4.6,0.3c0.6,-0.6 1,-1.3 1.3,-2c0.5,-1.3 0.8,-2.6 0.9,-4c0.2,-2.1 0.2,-4.1 -0.2,-6.2c-0.2,-1 -0.5,-1.8 -1.1,-2.6C56,22.9 54,22.7 53.1,23.5zM35.2,37.5C35.2,37.5 35.1,37.5 35.2,37.5c-0.1,0.1 -0.1,0.2 -0.1,0.3c-0.2,0.7 -0.4,1.3 -0.7,2c-0.3,0.7 -0.8,1.3 -1.4,1.7c-1.4,0.9 -2.8,0.4 -3.3,-1.2c0,0 0,-0.1 0,-0.1c-0.3,-1.3 -0.4,-2.6 -0.3,-4c0,-0.2 0,-0.3 0.1,-0.5c0,0 0,0 0.1,0c0,0 0.1,0.1 0.1,0.1c0.4,0.5 0.9,0.8 1.5,0.8c0.9,0 1.5,-0.5 2,-1.3c0.4,-0.8 0.6,-1.6 0.7,-2.4c0.1,-1.4 0,-2.8 -0.2,-4.1c-0.1,-0.9 -0.4,-1.7 -1,-2.4c-0.8,-1 -2.3,-1.4 -3.4,0.1c-0.5,0.7 -0.8,1.5 -1.1,2.3c-0.9,3.4 -1.1,6.8 -0.6,10.2c0.2,1.4 0.7,2.7 1.7,3.7c0.9,0.9 1.9,1.5 3.2,1.5c1.5,0 2.6,-0.9 3.3,-2.1c0,-0.1 0,-0.2 0,-0.3c-0.1,-0.6 -0.3,-1.3 -0.4,-1.9C35.3,39 35.2,38.3 35.2,37.5zM43.6,32.8C43.6,32.8 43.7,32.8 43.6,32.8c0.1,0.6 0.1,1.2 0.1,1.9c0.1,1.5 0.1,2.9 0.2,4.4c0,0.4 0.1,0.8 0.5,1.1c0.5,0.3 1,0.5 1.6,0.6c0.6,0.1 0.7,0 0.7,-0.6c-0.1,-2.2 -0.3,-4.5 -0.3,-6.7c-0.1,-2 0,-4.1 0,-6.1c0,-1.4 0,-2.8 0.1,-4.2c0,-1.6 0.1,-3.3 0.2,-4.9c0,-0.2 0,-0.4 -0.1,-0.5c-0.5,-0.5 -1.2,-0.8 -1.9,-0.7c-0.3,0 -0.4,0.2 -0.5,0.5c-0.1,1.2 -0.2,2.5 -0.2,3.8c-0.1,2.5 -0.1,5.1 -0.2,7.6C43.6,30.2 43.6,31.5 43.6,32.8zM37.3,26.6C37.3,26.6 37.4,26.6 37.3,26.6c0.1,1.8 0,3.6 0.1,5.4c0.1,2.1 0.2,4.2 0.3,6.4c0,0.7 0.1,1.4 0.2,2.1c0,0.2 0.2,0.5 0.3,0.6c0.5,0.4 1.1,0.6 1.8,0.7c0.4,0 0.5,-0.1 0.5,-0.5c-0.2,-2.5 -0.4,-5.1 -0.5,-7.6c-0.1,-2.4 -0.1,-4.7 -0.1,-7.1c0,-2.4 0.1,-4.9 0.1,-7.3c0,-0.3 -0.1,-0.4 -0.3,-0.6c-0.5,-0.4 -1.1,-0.6 -1.7,-0.6c-0.4,0 -0.5,0.1 -0.6,0.5c0,0.8 -0.1,1.7 -0.1,2.5C37.4,22.9 37.3,24.7 37.3,26.6z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M60.7,53.2c-0.5,0 -0.9,0 -1.4,0c0,-0.1 0,-0.2 0,-0.3c0,-1 0,-2.1 0,-3.1c0,-0.2 0,-0.3 -0.1,-0.5c-0.1,-0.5 -0.5,-0.8 -1,-0.9c-0.5,-0.1 -1,0.2 -1.2,0.6c-0.1,0.2 -0.2,0.5 -0.2,0.8c0,1 0,2 0,3c0,0.1 0,0.2 0,0.3c-0.5,0 -0.9,0 -1.3,0c0,-1.9 0,-3.9 0,-5.8c0.4,0 0.9,0 1.3,0c0,0.3 0,0.5 0,0.8c0.5,-0.6 1.1,-1 1.8,-1c0.8,0 1.3,0.3 1.7,1c0.3,-0.2 0.5,-0.5 0.8,-0.6c1,-0.6 2.4,-0.3 2.9,0.5c0.2,0.4 0.3,0.8 0.3,1.3c0,1.3 0,2.6 0,3.9c-0.4,0 -0.9,0 -1.4,0c0,-0.1 0,-0.2 0,-0.3c0,-1 0,-2 0,-3c0,-0.1 0,-0.2 0,-0.3c-0.1,-0.8 -0.5,-1.2 -1.2,-1.2c-0.7,0 -1.2,0.5 -1.2,1.2c0,0.9 0,1.7 0,2.6C60.7,52.5 60.7,52.8 60.7,53.2z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M54.2,50.3c0,1.8 -1.4,3 -3.2,3c-1.7,0 -3,-1.3 -3,-3c0,-1.7 1.4,-3.1 3.2,-3.1C52.9,47.2 54.2,48.6 54.2,50.3zM49.3,50.2c0,1 0.8,1.9 1.8,1.9c1,0 1.8,-0.8 1.8,-1.8c0,-1 -0.8,-1.8 -1.8,-1.9C50.1,48.4 49.3,49.2 49.3,50.2z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M41.4,47.4c0.5,0 1,0 1.5,0c0,0.4 0,0.7 0,1.1c-0.5,0 -1,0 -1.5,0c0,1.6 0,3.1 0,4.7c-0.4,0 -0.9,0 -1.3,0c0,-1.6 0,-3.1 0,-4.7c-0.3,0 -0.5,0 -0.7,0c0,-0.4 0,-0.7 0,-1.1c0.2,0 0.5,0 0.7,0c0,-0.2 0,-0.4 0,-0.6c0,-1.1 0.7,-1.8 1.8,-1.8c0.3,0 0.6,0.1 0.9,0.1c0.1,0 0.2,0.1 0.2,0.2c0,0.3 0,0.6 0,1c-0.5,-0.1 -1,-0.3 -1.4,0.1C41.3,46.7 41.4,47 41.4,47.4z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M45.3,53.2c-0.5,0 -0.9,0 -1.3,0c0,-1.9 0,-3.9 0,-5.8c0.4,0 0.9,0 1.3,0c0,0.4 0,0.7 0,1.1c0.5,-0.8 1.1,-1.3 2.1,-1.2c0,0.5 0,0.9 0,1.4c-0.1,0 -0.2,0 -0.3,0c-1.1,0.1 -1.7,0.9 -1.7,2.1c0,0.7 0,1.4 0,2.1C45.3,53 45.3,53.1 45.3,53.2z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M51.3,31.8c0.3,0.1 0.6,0.1 0.8,0.2c0.2,-1.1 0.4,-2.2 0.6,-3.3c0.2,-1.1 0.5,-2.1 1,-3c0.2,-0.3 0.4,-0.6 0.6,-0.8c0.5,-0.5 1.2,-0.3 1.4,0.3c0.2,0.4 0.3,0.9 0.4,1.4c0.2,1.6 0.1,3.3 0,4.9c-0.1,1.4 -0.3,2.7 -0.7,4c-0.2,0.7 -0.5,1.3 -1,1.8c-0.7,0.7 -1.5,0.6 -2.1,-0.1c-0.5,-0.6 -0.7,-1.3 -0.8,-2.1c-0.2,-1 -0.2,-2.1 -0.2,-3.1C51.3,31.9 51.3,31.8 51.3,31.8z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M31.5,31c0,1 0,1.9 -0.3,2.9c-0.1,0.2 -0.2,0.5 -0.3,0.7c-0.2,0.3 -0.5,0.4 -0.8,0.3c-0.3,-0.1 -0.6,-0.4 -0.6,-0.7c0,-2.2 0.3,-4.4 0.8,-6.5c0,-0.2 0.1,-0.5 0.3,-0.5c0.3,0 0.3,0.3 0.4,0.5c0.3,0.9 0.4,1.9 0.4,2.9C31.5,30.6 31.5,30.8 31.5,31z"/>
+</vector>
diff --git a/res/drawable/icon_hourglass.xml b/res/drawable/icon_hourglass.xml
new file mode 100644
index 000000000..8b7e227fb
--- /dev/null
+++ b/res/drawable/icon_hourglass.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+ android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#00000000"
+ android:pathData="M204,166.6l-1-5.3c-1.1-5.9,0.5-12,4.3-16.7
+ l31.6-35.3c7.5-9.2,10.7-21.3,8.5-33l-8.3-45.9c-1.7-9.6-39.7-10.6-84.7-2.2S74.3,51.2,76,60.8l8.3,45.9
+ c2.1,11.7,9.3,21.9,19.6,27.8l41.9,21.6c5.2,3,8.8,8.1,9.9,14l1,5.3l1.1,6.2l1,5.3c1.1,5.9-0.5,12-4.3,16.7l-31.6,35.3
+ c-7.5,9.2-10.7,21.3-8.5,33l8.3,45.9c1.7,9.6,44.2,16.1,89.2,7.8c45-8.4,75.6-28.5,73.9-38.1l-8.3-45.9
+ c-2.1-11.7-9.3-21.9-19.6-27.8l-41.9-21.6c-5.2-3-8.8-8.1-9.9-14l-1-5.3L204,166.6z"
+ android:strokeColor="?attr/fillColorSelector" android:strokeWidth="11.6824"/>
+ <path android:fillColor="#00000000"
+ android:pathData="M224.6,39.8c1,5.4-27.9,15.4-64.4,22.2
+ c-36.6,6.8-67,7.9-68,2.5c-1-5.4,27.9-15.4,64.4-22.2C193.2,35.5,223.6,34.4,224.6,39.8z"
+ android:strokeColor="?attr/fillColorSelector" android:strokeWidth="3.512"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M262.6,268.1l0.1,0l-69.6-35.4c0,0-44,42.7-56.4,57.3c-2.8,2.6-4.2,5.2-3.8,7.5c1.7,9.6,34.7,13,71.5,6.2
+ c36.9-6.9,63.7-21.4,61.9-31C266,270.9,264.7,269.4,262.6,268.1"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M232.2,79.2c1.3,7.1-0.5,14.3-5,19.9l-31.6,35.3l-0.2,0.3c-6.8,8.2-13.9,19.8-12,30.4l2,16.5l-3.5,1.1
+ l-5.4-15.4c-1.9-10.5-13.8-19.5-23-24.8l-0.3-0.2l-41.9-21.6c-6.1-3.6-10.4-9.7-11.7-16.8l0.1-1c-1.3-7.2,27.3-18.6,63.9-25.5
+ c36.6-6.8,67.3-6.5,68.7,0.8L232.2,79.2z"/>
+</vector>
diff --git a/res/drawable/icon_party.xml b/res/drawable/icon_party.xml
new file mode 100644
index 000000000..d828103f7
--- /dev/null
+++ b/res/drawable/icon_party.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+ android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#00000000"
+ android:pathData="M76.1,159.7L35.2,312c-1.6,6 5.7,12 11.3,9.3l143.9,-68.6l0.5,-0.6c2.9,-3.6 -20.3,-27.3 -51.9,-53s-59.6,-43.6 -62.5,-40L76.1,159.7z"
+ android:strokeColor="?attr/fillColorSelector" android:strokeWidth="12.0143"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M83.3,175.9c-2.3,2.9,15.6,21.3,40.1,41.3c24.5,19.9,46.3,33.8,48.6,30.9c2.3-2.9-15.6-21.3-40.1-41.3
+ C107.4,186.9,85.6,173.1,83.3,175.9"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M177.3,214.5c16.8-8.7,42.6-13.8,59.7-4.5c10.7,5.9,16.9,17.1,18.2,33.3l17.2-1.4
+ c-2.3-27.8-16-40.9-27.1-47c-22.7-12.5-47.1,6.9-68.5,18.1L177.3,214.5z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M111.4,161.8l2,0.1c4.8-14.5,7.3-35.4-2.4-50.9c-10.9-17.5-19.4-21.2-39.8-24l-2.3,17.1
+ c20.6,2.8,31.6,15.9,36.4,23.5C112.3,138.7,114.7,152.1,111.4,161.8"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M156.3,196.8c12-12.8,36.8-32.4,65-47.4c22.8-12.1,56-25.6,84.4-20.8l2.9-17c-58.4-9.8-124.3,53.6-153,84.1
+ L156.3,196.8z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M138,177.1l1.8-0.3c0.7-1.7,1.4-3.6,2.2-5.6c11.9-29.8,48.2-78.7,18.7-104l-11.3,13.1
+ c20.2,17.3,0.3,67.2-9.2,91.1C139.4,173.5,138.7,175.4,138,177.1"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M300.8,175.1 L288.3,176 L280.5,166.3 L277.5,178.4 L265.8,182.9 L276.5,189.4 L277.1,201.9 L286.6,193.8
+ L298.7,197.1 L293.9,185.6z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M246.6,37.2 L226.6,51 L203.8,42.3 L210.7,65.6 L195.4,84.5 L219.8,85.1 L233.1,105.5 L241.2,82.6
+ L264.7,76.3 L245.4,61.5z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M144.5,121 L139.1,123.4 L134,120.4 L134.7,126.3 L130.2,130.2 L136.1,131.4 L138.4,136.8 L141.3,131.7
+ L147.2,131.1 L143.2,126.8z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M230.5,166.9c-2.2,2.7-1.8,6.7,0.9,8.9c2.7,2.2,6.7,1.8,8.9-0.9c2.2-2.7,1.8-6.7-0.9-8.9
+ C236.6,163.8,232.7,164.2,230.5,166.9"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M205.6,101.8c-0.7,0.9-0.6,2.1,0.3,2.8c0.9,0.7,2.1,0.6,2.8-0.3c0.7-0.9,0.6-2.1-0.3-2.8
+ C207.6,100.8,206.3,100.9,205.6,101.8"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M210.6,235.4c-2,2.4-1.6,6,0.8,7.9c2.4,2,6,1.6,7.9-0.8c2-2.4,1.6-6-0.8-7.9
+ C216.1,232.6,212.5,233,210.6,235.4"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M172.8,138.8c-2.7,3.3-2.2,8.1,1.1,10.7c3.3,2.7,8.1,2.2,10.7-1.1c2.7-3.3,2.2-8.1-1.1-10.7
+ C180.3,135.1,175.5,135.6,172.8,138.8"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M123.3,43c-1.7,2.1-1.4,5.3,0.7,7c2.1,1.7,5.3,1.4,7-0.7c1.7-2.1,1.4-5.3-0.7-7
+ C128.2,40.5,125.1,40.8,123.3,43"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M326.1,141.1c-1.7,2.1-1.4,5.3,0.7,7c2.1,1.7,5.3,1.4,7-0.7c1.7-2.1,1.4-5.3-0.7-7
+ C330.9,138.7,327.8,139,326.1,141.1"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M34.5,132c-2.8,3.4-2.3,8.4,1.1,11.2c3.4,2.8,8.4,2.3,11.2-1.1c2.8-3.4,2.3-8.4-1.1-11.2
+ C42.3,128,37.2,128.5,34.5,132"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M252.1,279c-0.9,1.1-0.8,2.8,0.4,3.7c1.1,0.9,2.8,0.8,3.7-0.4c0.9-1.1,0.8-2.8-0.4-3.7
+ C254.7,277.7,253,277.9,252.1,279"/>
+ <path android:fillColor="#00000000"
+ android:pathData="M134.3,278.8c-23,-2.7 -69.1,-46.9 -62.9,-94.6"
+ android:strokeColor="?attr/fillColorSelector" android:strokeWidth="2.9819"/>
+ <path android:fillColor="#00000000"
+ android:pathData="M89.1,300.1c-15.1,-6.2 -37.2,-37.1 -26.6,-76.9"
+ android:strokeColor="?attr/fillColorSelector" android:strokeWidth="2.9819"/>
+</vector>
diff --git a/res/drawable/icon_peace.xml b/res/drawable/icon_peace.xml
new file mode 100644
index 000000000..20d96ff40
--- /dev/null
+++ b/res/drawable/icon_peace.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="1008"
+ android:viewportHeight="1008">
+
+ <path
+ android:fillColor="?attr/fillColorSelector"
+ android:pathData="M398.1,414.5c-1.4-8.5-3.1-17.9-4.5-27.4c-5.9-40-12-80-17.5-120.1c-4-28.9-7.7-57.8-10.5-86.8
+c-2.4-24.9-1.4-49.7,9.5-73c14-29.9,37.7-47,70.5-50.1c42.9-4,73.2,15.9,94.3,51.7c13.1,22.2,19.6,46.9,24.9,71.9
+c6.5,31.1,12.7,62.3,19.1,93.4c0.1,0.6,0.3,1.2,0.8,3.4c1.1-2.9,1.7-4.5,2.2-6.1c5.7-16.5,11.2-33.1,17-49.5
+c6.5-18.5,15.9-35.5,28.3-50.8c29.7-36.5,72.5-44.5,113.6-21.3c31.2,17.6,44.6,45.2,45.4,80.1c0.5,23.3-5.2,45.5-11,67.8
+c-14.2,54.8-28.2,109.5-42.2,164.3c-0.6,2.5-1.6,4.6,1.3,7c29.5,24.3,45.2,56.4,52.5,93.3C805,628.4,793.7,691,764.7,751
+c-16.2,33.5-36.6,64.1-60,92.9c-25.7,31.6-58.8,52.1-96.9,65.1c-32.5,11.1-66.1,17.2-100.3,18.7c-28.4,1.2-56.9,1.2-85.3,0
+c-34.8-1.5-68.2-9.6-98.1-28.7c-22.5-14.5-39.8-34.1-55.5-55.5c-31.4-42.6-49.3-90.8-61.8-141.8c-7.1-28.9-14.2-57.8-19.2-87.2
+c-4.2-24.4-7.2-48.8-1.5-73.4c7.9-34.2,27.8-57.2,62.2-66.7c14.5-4,28.9-7.7,44.2-7.3c1.2,0,2.9-0.9,3.5-1.9
+c14.2-24.4,36.4-37.2,63.3-43.1C371.9,419.4,384.8,417.1,398.1,414.5z
+M582.1,332.8c-0.3,0-0.5-0.1-0.8-0.1
+c-1.7-8.8-3.4-17.5-5.2-26.3c-9.3-45.3-18.4-90.7-28.1-135.9c-4.8-22.2-12.1-43.7-25.2-62.6c-17.6-25.3-41.3-39.3-72.9-37.1
+c-30,2.2-51.3,17.2-63,45c-9.9,23.5-9.3,48.2-6.4,72.8c3.8,32.6,7.9,65.1,12.5,97.6c5.9,41.2,12.4,82.3,18.7,123.4
+c1.1,7.3,2.4,14.6,3.7,22.4c-2-0.2-3.3-0.5-4.6-0.5c-7.5-0.3-15.1-1.9-22.3-0.7c-14.5,2.5-29,5.9-43.1,10.3
+c-15.6,4.9-27.5,15.4-36.1,29.3c-2.4,3.9-4.4,8.1-6.1,11.2c-7.5,0-14.4-0.8-21,0.2c-10.5,1.5-20.9,3.8-31.2,6.5
+c-25.2,6.7-41.3,23.1-49.1,47.9c-7.3,23.3-5.1,46.6-1.5,70.2c5.6,37.3,15.2,73.6,24.9,110c7.7,29.2,17.5,57.6,32.6,84
+c13.7,23.9,28.9,46.8,48.5,66.4c29.5,29.5,66.2,42.5,106.8,46.2c29.6,2.7,59.2,2.8,88.8,1c31.9-1.9,63.3-6.5,93.8-16
+c36.1-11.3,68.4-28.8,93.4-57.9c25.3-29.5,46.6-61.6,63.4-96.6c27.3-56.9,38-116.1,25.5-178.6c-7.2-36-23.1-66.9-53-89.4
+c-3.4-2.5-3.9-4.7-2.9-8.6c15.5-59.9,30.9-119.9,46.3-179.8c4.9-19.1,9.4-38.1,8.8-58c-0.9-27.2-10.6-49.5-34.2-64.7
+c-35.8-22.9-73.3-17-100.1,15.9c-10.8,13.3-19.2,28.1-24.9,44.2c-9,25.6-17.5,51.3-26.1,77.1C588.6,311.9,585.4,322.4,582.1,332.8z" />
+ <path
+ android:fillColor="?attr/fillColorSelector"
+ android:pathData="M577.2,419.2c14.4-46,28.5-91.4,42.9-136.7c5-15.9,10.5-31.6,16.1-47.2c5.3-14.8,12.7-28.6,22.4-41
+c20.3-25.9,49.1-29.8,75.8-10.4c18.6,13.5,23.5,32.6,22.3,54.2c-1.2,21.3-7.8,41.5-13,61.9c-15.4,60.4-31,120.8-46.4,180.7
+c8.5,6.7,17.2,12.6,24.8,19.7c20.8,19,30.9,43.7,36,70.8c11.6,61.4-0.6,118.7-29.1,173.4c-15.4,29.7-34.2,57.1-56,82.5
+c-21.4,24.9-49.1,39.9-79.8,50c-35.4,11.6-72.1,16.3-109.1,16.8c-23.4,0.3-47-0.3-70.4-2c-46.4-3.3-83.5-23.8-111.6-61.6
+c-30.6-41.1-49.2-87-61.2-136.5c-7.7-31.4-15.1-62.7-20.3-94.6c-2.9-18-4.3-36.1,0.5-54c5.2-19.3,17-32,36.6-37
+c6.9-1.8,13.8-3.8,20.8-5.1c13.5-2.5,26.2-0.3,37.8,8.6c1-4.3,1.7-8.1,2.8-11.8c5.9-22.1,19.5-36.6,42.2-42
+c7.9-1.9,15.7-4.4,23.7-5.8c17.5-3.2,33.5,0.2,46.8,13.2c3-4.1,5.9-7.9,8.5-11.9c0.5-0.8,0.3-2.2,0.1-3.3
+c-12.9-65.7-22.1-132-31-198.3c-3.7-27.9-7-55.9-9.1-83.9c-0.9-11.4,0.4-23.4,2.9-34.6c10.8-48.3,64.5-50.9,89.4-28.5
+c13.4,12.1,22.4,27.2,27.2,44.1c7,24.4,12.9,49.2,18.1,74.1c13.2,64,25.6,128.2,38.4,192.3C576.4,416.6,576.8,417.7,577.2,419.2z
+M289,752.9c10.3,23.9,24,45,39.4,65.2c18.9,24.8,43.7,39.2,74.5,44.2c23.8,3.8,47.8,4.1,71.7,3.8c36.6-0.4,72.8-4.1,107.9-15.2
+c27.1-8.6,51.6-21.4,70.3-43.6c21.5-25.4,39.8-52.9,54.6-82.8c23.7-47.9,32.9-97.7,22.5-150.7c-6.5-32.8-23.9-56.9-54.1-71.6
+c-19.4-9.5-39.8-16.1-60.7-21.1c-33.4-8.1-67.4-12.5-101.6-15.9c-9.8-1-19.6-1.8-29.4-1.9c-13.8-0.2-26.6,9.5-29.1,20.5
+c-3.4,14.8-1.1,28.1,8.8,39.8c9.3,11,21.7,17.5,34.9,22.4c24.2,9,49.6,12.7,75.2,15c8.3,0.7,16.6,1,24.9,1.5
+c12.9,0.8,22.8,8.8,25.8,20.6c3.2,12.4-1.4,24.2-12.6,31c-26.7,16.3-53.6,32.3-80.3,48.6c-17.4,10.7-31,24.6-35.6,45.5
+c-2.9,13.2-3.2,26.5-1.8,39.8c1.4,13.6,3.7,27,5.6,40.5c1.4,10.1-6.3,18-16.1,16.4c-6.2-1-10.8-5.5-11.8-13.1
+c-2.4-19.3-5.3-38.6-6.2-58c-1.2-24.7,4.2-48,19.9-68c11-14,25.4-23.8,40.6-32.8c21.8-12.9,43.4-26,65.1-39
+c1.3-0.8,2.5-1.7,4.8-3.3c-46.5-2.8-91.4-7.3-131.3-29.3c0.9,24,1.8,48.1,2.8,72.2c0.9,21.2-4.3,40.9-13.5,59.7
+c-6.8,13.9-15.1,26.7-27.6,36.3c-17.1,13.1-37.1,12.7-52.7-2.1c-6.5-6.2-11.3-14.3-16.9-21.5c-0.9-1.2-1.6-2.6-2.6-4.3
+c-1.8,4.7-3.1,8.9-4.9,12.8C337.2,743.3,318.8,755.1,289,752.9z
+M552.5,440.9c-1.6-8.7-3.2-17.2-4.9-25.6
+C533.8,346,519.9,276.6,506,207.4c-3.9-19.6-7.8-39.2-15.9-57.6c-4-9.2-8.8-18-17-24.3c-16.1-12.5-37.5-5.7-42.6,13.9
+c-1.8,6.8-3,14.2-2.5,21.2c1.9,24.9,4,49.8,7.4,74.5c7.1,51.8,14.9,103.4,22.6,155.1c2.4,15.8,5.5,31.4,8.3,47.4
+C495.5,431.4,523.6,439.6,552.5,440.9z
+M671.4,467.9c0,0,0.3-0.5,0.5-1.2c17.6-68.5,35.2-136.9,52.6-205.4
+c3.1-12.1,5.5-24.3,3.7-37c-1.9-13.5-10.8-20-22.7-23.6c-10.7-3.3-17.9,2.5-24.1,10.1c-8.5,10.6-15.1,22.4-19.2,35.3
+c-21.1,66.2-42,132.5-62.9,198.8c-0.4,1.2-0.4,2.5-0.4,2.8C623.2,454.5,647,461.1,671.4,467.9z
+M441.3,618.3
+c-0.4,0-0.8-0.1-1.2-0.1c-0.9-30.3-3.4-60.5-10.4-90.1c-3.1-13.3-6.5-26.5-14.2-38.2c-5.8-8.7-13.9-12.3-24.1-10.3
+c-8.5,1.7-16.8,4.1-25.2,6.1c-10,2.4-16.8,8.8-19,18.5c-2.2,9.8-4.5,20.2-3.6,30c3.9,41.7,11.3,82.8,23.6,122.8
+c5,16.4,11,32.6,22.2,46c8.2,9.9,14.7,10.1,23.7,1.1c12.1-12.1,19.9-27,23.4-43.4C439.7,646.9,439.9,632.5,441.3,618.3z
+M245.3,569.8c0.9,8.3,1.4,14.8,2.4,21.2c4.8,29,9.1,58.1,18.4,86.2c5,15.1,10.7,29.8,21.7,41.7c8.6,9.3,16.5,9.4,25.3,0.6
+c9.3-9.3,14.9-20.8,15.7-33.7c0.7-11-0.8-22.2-1.8-33.3c-2.7-29.7-6-59.3-14-88.1c-2.4-8.4-5.6-16.7-9.4-24.6
+c-3.8-7.8-10.8-11.1-19.6-9.1c-7,1.6-13.9,3.4-20.8,5.2c-7.3,1.8-12.1,6.6-13.9,13.6C247.3,556.7,246.3,564.2,245.3,569.8z" />
+</vector> \ No newline at end of file
diff --git a/res/drawable/icon_pin.xml b/res/drawable/icon_pin.xml
new file mode 100644
index 000000000..4c3ac5212
--- /dev/null
+++ b/res/drawable/icon_pin.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+ android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M261.1,91.8C253.6,52,219.5,23.2,180,23c-4,0.4-7.9,0.5-11.9,1.1c-19.4,2.9-35.9,11.8-49.1,26.7
+ c-17.2,19.5-24,42.5-20.9,68.6c1.4,11.8,5.4,22.9,10.9,33.3c6.9,12.9,15.1,25,23.3,37c9.9,14.5,20,28.7,28.9,43.8
+ c6,10.2,11.6,20.6,15.2,32c0.6,1.9,1.6,2.8,3.1,2.8c1.5,0,2.5-0.9,3.2-2.8c1.1-3.1,2.2-6.1,3.5-9.1c5.5-12.7,12.7-24.4,20.4-35.8
+ c9.7-14.4,19.7-28.6,29.4-43c8.3-12.3,16.1-24.9,21.1-39.2C262.5,123.2,264.1,107.7,261.1,91.8 M179.1,148.7
+ c-23.8-0.5-42.3-20.6-42.2-44.4c0.1-24.4,19.2-44.1,43.1-44.1c23.9,0,43,19.7,43,44.4C223,129,203.6,149.2,179.1,148.7"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M245.2,278.5c-9.7-4.7-20-7.4-30.6-9.2c-1.6-0.3-3.5-1.1-4.7-0.5c-1.3,0.7-1.9,2.7-2.7,4.2
+ c-1.7,3.2-3.4,6.5-5.2,9.9c3.4,0.5,6.5,0.9,9.5,1.4c9.6,1.7,19.1,3.9,28,8.4c3.2,1.6,6.3,3.5,8.7,6.4c1.8,2.2,1.9,3.7-0.1,5.8
+ c-1.7,1.8-3.7,3.4-5.8,4.7c-7,4.3-14.8,6.6-22.7,8.4c-14.5,3.3-29.2,4.4-44,4c-11.8-0.3-23.6-1.6-35.1-4.3
+ c-7.8-1.9-15.4-4.2-22.2-8.7c-1.9-1.3-3.6-2.9-5.2-4.6c-1.4-1.5-1.3-3,0-4.6c1.3-1.5,2.7-2.9,4.3-4.1c4.6-3.3,9.9-5.3,15.2-7.1
+ c8.4-2.7,17-4.3,25.8-5.4c0-0.3,0-0.5-0.1-0.7c-2.2-4.4-4.5-8.7-6.8-13c-0.2-0.4-1-0.7-1.5-0.6c-7.8,1.8-15.7,3.3-23.4,5.6
+ c-8.3,2.5-16.1,6.2-22.5,12.6c-4.7,4.7-7.4,10.3-6.6,17.3c0.7,6,3.9,10.4,8.2,14.1c5.5,4.8,11.9,7.9,18.7,10.3
+ c17.4,6.3,35.5,8.4,53.8,8.6c7.4,0.1,14.8-0.3,22.2-0.9c12.3-1,24.3-3.2,36-7.4c7.5-2.7,14.6-6,20.6-11.6
+ c9.3-8.7,9.7-20.8,0.9-30.1C254.2,283.5,249.8,280.7,245.2,278.5"/>
+</vector>
diff --git a/res/drawable/icon_rain.xml b/res/drawable/icon_rain.xml
new file mode 100644
index 000000000..510aa083c
--- /dev/null
+++ b/res/drawable/icon_rain.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="72.0"
+ android:viewportWidth="72.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M52,46.1c0.8,1.1 1.6,2.2 2.3,3.3c0.8,1.1 1.5,2.3 1.9,3.6c1,3 -1.2,6.2 -4.4,6.2c-2.4,0 -4.4,-1.6 -4.7,-4c-0.2,-1 0,-1.9 0.2,-2.8c0.1,-0.4 0.2,-0.8 0.2,-1.2c0,0 -0.1,-0.1 -0.1,-0.1c-0.1,0.1 -0.1,0.2 -0.2,0.3c-3.4,3.8 -6.8,7.6 -10.2,11.4c-0.3,0.3 -0.6,0.6 -1,0.5c-0.6,0 -1,-0.6 -0.9,-1.2c0.1,-0.6 0.4,-1.2 0.6,-1.8c1.4,-4.3 2.9,-8.6 4.3,-12.9c0,-0.1 0.1,-0.2 0.1,-0.4c-0.2,0 -0.3,0 -0.4,0c-2.1,0 -4.2,0 -6.3,0c-1,0 -1.4,-0.3 -1.6,-1.2c-2.4,-0.1 -4.8,-0.6 -7.1,-1.7c0.2,0.4 0.3,0.8 0.4,1.2c1.2,3.7 -1.4,7.8 -5.2,8.4c-3.6,0.5 -6.8,-1.8 -7.5,-5.4c-0.2,-1 0,-2.1 0.1,-3.1c0.3,-2.1 0.9,-4.1 1.5,-6.1c0,-0.1 0.1,-0.2 0.1,-0.3c-0.1,0 -0.2,-0.1 -0.4,-0.1c-2.3,-0.9 -4.4,-2.2 -6,-4c-3.5,-3.9 -3.4,-9.3 0.2,-13.1c2.2,-2.3 4.9,-3.7 7.9,-4.5c0.8,-0.2 1.6,-0.3 2.3,-0.5c0.1,0 0.3,-0.1 0.3,-0.2c0.9,-4.8 3.6,-8.3 7.9,-10.5c6.1,-3.1 12.2,-3 18.1,0.4c2.9,1.7 5.1,4.1 6.3,7.3c0.1,0.2 0.2,0.2 0.4,0.3c3.3,0.5 6.3,1.7 8.8,3.8c2.2,1.8 3.8,4.1 4.4,6.9c0.7,3.5 -0.2,6.6 -2.4,9.3c-2.2,2.8 -5.2,4.4 -8.6,5.4c-1.9,0.5 -3.8,0.7 -5.7,0.7c-0.3,0 -0.5,0.1 -0.6,0.5c0.1,0 0.3,0 0.4,0c2.2,0 4.4,0 6.6,0c0.1,0 0.2,0 0.3,0c0.5,0 0.9,0.2 1.1,0.7c0.2,0.5 0,0.9 -0.3,1.3c-1,1.2 -2.1,2.3 -3.1,3.5C52.1,46 52.1,46.1 52,46.1zM33.3,37.5c0.2,-0.8 0.3,-1.5 0.5,-2.3C34,34.1 34,33 34.5,32c-2.5,-1.6 -4.5,-3.8 -5.8,-6.6c0.1,0 0.1,0.1 0.2,0.1c1.5,1.6 3.2,2.9 5.1,3.7c5.2,2.3 10.4,2.2 15.6,0.2c0.9,-0.4 1.8,-0.8 2.7,-1.2c0,0 0,0.1 0,0.1c-0.7,1.8 -1.3,3.6 -2,5.4c0,0.1 -0.1,0.2 -0.2,0.2C50,34 49.9,34 49.8,34.2c-0.4,0.9 -0.8,1.9 -1.2,2.8c0,0.1 -0.1,0.2 -0.1,0.4c0.2,0 0.3,0 0.4,0c1,-0.1 2.1,-0.2 3.1,-0.4c3,-0.7 5.7,-2 7.8,-4.4c2.6,-3 3,-7 0.9,-10.3c-1.3,-2.1 -3.2,-3.6 -5.5,-4.6c-1.9,-0.9 -3.8,-1.3 -5.9,-1.5c-0.3,0 -0.4,-0.2 -0.5,-0.4c-0.9,-3.2 -2.8,-5.5 -5.6,-7.2c-3.2,-2 -6.8,-2.7 -10.5,-2.2c-3.3,0.5 -6.3,1.8 -8.6,4.3c-1.9,2 -3.1,4.3 -3.2,7.1c0,0.4 -0.1,0.8 -0.1,1.2c-0.2,0 -0.3,0 -0.4,0c-1.6,0.1 -3.2,0.3 -4.7,0.8c-2.4,0.8 -4.6,1.9 -6.2,3.9c-1.4,1.7 -2,3.6 -1.6,5.7c0.3,1.8 1.3,3.2 2.6,4.4c2.2,2 4.8,3 7.6,3.4c1.1,0.2 2.2,0.2 3.4,0.3c0.2,0.5 0.4,1 0.6,1.5c0.7,1.3 1.8,2.1 3.1,2.7c1.5,0.8 3.2,1.3 4.8,1.5c0.7,0.1 1.4,0.1 2.1,0.2c0.2,-1.3 0.5,-2.6 0.7,-3.8c-1.6,-0.4 -3,-1 -4.2,-1.8c-1.3,-0.9 -2.8,-2.6 -3,-3.4C28.2,36.8 31.5,37.5 33.3,37.5zM38.3,58.5C38.3,58.5 38.3,58.5 38.3,58.5c4.9,-5.4 9.7,-10.7 14.6,-16.2c-0.2,0 -0.3,0 -0.5,0c-2,0 -4,0 -6,0c-0.2,0 -0.4,0 -0.5,0c-0.8,-0.2 -1.1,-1 -0.8,-1.8c0.8,-1.8 1.5,-3.6 2.3,-5.5c0.1,-0.2 0.1,-0.3 0.2,-0.6c-0.1,0 -0.2,0 -0.3,0c-3.2,0.5 -6.4,0.2 -9.5,-0.9c-0.6,-0.2 -1.2,-0.2 -1.8,-0.2c-0.8,4 -1.5,7.9 -2.3,11.9c0.2,0 0.3,0 0.5,0c2.2,0 4.4,0 6.6,0c1.1,0 1.7,0.8 1.3,1.8c-0.9,2.7 -1.8,5.4 -2.7,8C39,56.3 38.7,57.4 38.3,58.5zM15.5,39.3c0,0 0,0.1 0,0.1c-0.6,2 -1.2,4.1 -1.5,6.2c-0.1,0.9 -0.3,1.9 -0.1,2.8c0.6,2.8 3.2,4.6 6,4c2.8,-0.5 4.7,-3.4 4,-6.1c-0.3,-1.1 -0.9,-2.1 -1.3,-3.1c-0.1,-0.2 -0.3,-0.4 -0.4,-0.5c-0.9,-0.7 -1.6,-1.6 -2.2,-2.6c-0.1,-0.1 -0.2,-0.2 -0.4,-0.2c-0.4,-0.1 -0.8,-0.1 -1.2,-0.1C17.3,39.6 16.4,39.4 15.5,39.3zM51.2,47c-0.6,0.7 -1.3,1.4 -1.9,2.1c0,0.1 -0.1,0.1 -0.1,0.2c-0.5,1.7 -1,3.4 -1.1,5.2c-0.1,2.3 2.1,4.1 4.3,3.6c2.3,-0.5 3.5,-2.8 2.6,-5c-0.6,-1.4 -1.4,-2.7 -2.3,-4C52.3,48.4 51.7,47.7 51.2,47z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M25.6,63.4c0.1,-1.2 0.4,-2.6 0.8,-4c0.3,-1.1 0.7,-2.1 1.1,-3.2c0.4,-1 1,-1.2 1.8,-0.4c0.8,0.9 1.6,1.8 2.3,2.8c0.7,1.1 1.4,2.2 1.9,3.4c1.1,2.7 -0.9,5.7 -3.9,5.6C27.4,67.7 25.5,65.8 25.6,63.4zM28.6,56.8c-0.1,0.1 -0.1,0.2 -0.1,0.3c-0.7,1.7 -1.2,3.4 -1.5,5.1c-0.1,0.7 -0.3,1.4 -0.1,2c0.4,1.6 2.1,2.6 3.7,2.1c1.6,-0.5 2.4,-2.2 1.8,-3.8c-0.7,-1.8 -1.8,-3.3 -3,-4.8C29.1,57.4 28.9,57.1 28.6,56.8z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M11.3,27c2.9,4.4 6.9,5.9 12,5.1c-0.1,0.1 -0.1,0.2 -0.2,0.3c-0.4,0.6 -0.9,1.1 -1.2,1.7c-0.3,0.5 -0.6,0.6 -1.2,0.5c-4.4,-0.3 -8.2,-3.2 -9.2,-7.1C11.4,27.4 11.4,27.3 11.3,27z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M15.5,46.8c1,2.4 4.8,2.9 6.4,0.5c0.2,0.7 0.2,1.4 -0.2,2c-0.8,1.3 -2,1.8 -3.4,1.6c-1.4,-0.1 -2.4,-0.8 -3,-2.1C15.1,48.1 15.1,47.5 15.5,46.8z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M53.9,54.5c0.3,0.7 0,1.5 -0.6,2c-0.9,0.7 -2.4,0.7 -3.3,0c-0.8,-0.6 -1,-1.5 -0.7,-2.4c0.5,0.9 1.2,1.4 2.2,1.5C52.5,55.7 53.3,55.4 53.9,54.5z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M27.7,63.3c0.7,1.4 2.7,1.8 3.8,0.3c0.2,0.6 0,1.3 -0.6,1.7c-0.8,0.6 -2,0.5 -2.7,-0.1C27.6,64.7 27.4,64 27.7,63.3z"/>
+</vector>
diff --git a/res/drawable/icon_snow.xml b/res/drawable/icon_snow.xml
new file mode 100644
index 000000000..5dd65cd4d
--- /dev/null
+++ b/res/drawable/icon_snow.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="1008.0"
+ android:viewportWidth="1008.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M61.5,401.4c17.4,-30.1 34.5,-59.8 52,-90.1c15.3,8.8 30.4,17.5 46.6,26.8c-2.7,-10.3 -5.2,-19.4 -7.7,-29.1c3.7,-1.1 7.2,-2.1 10.7,-3c16.4,-4.5 32.8,-8.8 49.1,-13.4c2.5,-0.7 5.1,-2.3 7,-4.2c17.2,-16.3 34.2,-32.6 52.6,-50.2c6.2,7.2 13.7,15.8 21.2,24.4c0.6,-0.4 1.3,-0.9 1.9,-1.3c0,-18 0,-36.1 0,-54.5c34.8,0 69.1,0 104.2,0c0,17.2 0,34.5 0,51.8c0.5,0.2 0.9,0.4 1.4,0.5c6.4,-6.9 12.8,-13.8 20.2,-21.9c8.6,9.1 16.2,17.2 23.9,25.2c4.3,4.4 9,8.4 13,13.2c5.8,7 13.1,10.4 21.9,12.4c21.7,5.1 43.2,11 65.4,16.7c-2.9,11.4 -5.7,22.5 -8.8,34.8c16.8,-9.7 32.5,-18.7 48.7,-28.1c14.2,24.6 28.3,49 42.9,74.1c6.5,-10.2 13.5,-19.2 18.3,-29.3c2.5,-5.3 1.2,-12.4 1.5,-18.7c0.4,-9 0.7,-17.9 1.1,-27.1c4.6,0 8.8,0 14,0c-5.8,-6.5 -11.2,-12.6 -16.8,-19c16.6,-14.9 33,-29.7 49.8,-44.8c5.2,5.7 10.3,11.2 16.1,17.5c0.4,-3.9 0.8,-6.9 1.2,-10.4c12.2,0.6 24.4,1.2 36.5,1.6c2.2,0.1 4.6,-0.4 6.6,-1.4c12.5,-6.3 24.8,-12.8 37.6,-19.4c2.2,4 4.2,7.7 6.8,12.4c2.8,-8.5 5.4,-16.1 8.1,-24.3c21.3,6.9 42.2,13.7 63.7,20.7c-2.4,7.5 -4.6,14.7 -7.2,23c3.7,-1.9 6.5,-3.2 9.6,-4.8c5.2,10 10,20 15.4,29.7c1.8,3.3 4.6,6.5 7.8,8.6c11.7,7.9 23.7,15.3 35.9,23.1c-2.4,3.9 -4.6,7.5 -7.4,12.1c8.8,-1.8 16.6,-3.4 25.1,-5.2c4.7,21.9 9.3,43.6 13.9,65.6c-7.8,1.7 -15,3.3 -23.2,5.1c3.3,2.4 5.7,4.1 8.6,6.2c-6.6,10.3 -12.9,20.4 -19.6,30.3c-2.7,4 -4,8.2 -4.1,13c-0.3,12.1 -0.9,24.2 -1.4,36.5c-4.6,0 -8.9,0 -13.9,0c5.9,6.6 11.2,12.6 16.8,18.9c-16.7,15 -33.1,29.8 -49.9,44.9c-5.3,-5.8 -10.4,-11.4 -16.2,-17.8c-0.3,4 -0.5,6.9 -0.8,10c-5.5,0 -10.7,0.1 -16,0c-7.7,-0.3 -15.3,-0.9 -22.9,-1.1c-2.2,0 -4.6,0.6 -6.6,1.6c-12,6.1 -23.9,12.3 -36.1,18.7c-2.2,-4.1 -4.2,-7.8 -6.8,-12.4c-2.8,8.4 -5.3,16 -8.1,24.3c-21.2,-6.9 -42.2,-13.7 -63.7,-20.7c2.3,-7.5 4.6,-14.6 7.1,-22.8c-3.7,1.8 -6.4,3 -9.5,4.5c-3.7,-7.1 -8,-13.9 -10.9,-21.2c-4.7,-11.9 -12.6,-20.2 -23.8,-26.1c-7.5,-3.9 -14.4,-9 -22,-13.9c2.4,-3.9 4.6,-7.5 7.5,-12.1c-8.9,1.8 -16.7,3.4 -25,5.1c-1.9,-8.4 -3.7,-16.6 -5.5,-24.7c-0.3,0 -0.6,0.1 -0.9,0.1c-5.4,20.4 -10.8,40.7 -16.1,61.2c-0.5,1.8 0.1,3.9 0.6,5.8c6,21.8 12.1,43.6 18.3,66c-11.2,3.2 -22.3,6.3 -34.6,9.8c16.6,9.6 32.4,18.8 48.7,28.2c-17.3,29.9 -34.4,59.7 -52,90.1c-15.3,-8.8 -30.5,-17.5 -46.7,-26.8c2.7,10.3 5.2,19.5 7.7,29.1c-15.7,4.3 -30.8,9.2 -46.2,12.4c-14.4,3.1 -25.8,9.4 -35.7,20.5c-11.7,12.9 -25.2,24.2 -38.6,36.8c-6.7,-7 -14.6,-15.4 -22.6,-23.7c-0.4,0.3 -0.8,0.6 -1.2,0.8c0,18.1 0,36.2 0,54.6c-34.7,0 -69.1,0 -104,0c0,-17.4 0,-34.8 0,-53.5c-7.5,8 -14.1,15.1 -21.7,23.3c-10.9,-11.4 -20.7,-21.8 -30.6,-32.1c-5.6,-5.7 -11.2,-11.4 -17.1,-16.8c-1.5,-1.4 -3.7,-2.2 -5.7,-2.7c-20.9,-5.5 -41.9,-10.8 -62.8,-16.2c-1.1,-0.3 -2.2,-0.7 -3.8,-1.3c2.9,-11.3 5.7,-22.5 8.8,-34.6c-16.7,9.6 -32.6,18.8 -48.8,28.1c-17.4,-30.1 -34.6,-59.9 -52,-90.1c15.4,-8.9 30.4,-17.6 46.6,-27C98.2,581 89,578.5 79.4,576c4.4,-16.5 8.1,-32.7 13,-48.5c3.1,-10 2.9,-19.1 -0.2,-29.1c-6.1,-19.3 -11,-39 -16.6,-59c11.3,-3.2 22.5,-6.3 34.6,-9.7C93.6,420 77.8,410.9 61.5,401.4zM84.3,616.8c12,20.8 23.8,41.1 35.7,61.8c22.7,-13.1 44.9,-25.9 68.3,-39.4c-5.1,19.8 -9.8,38 -14.5,56.5c1.3,0.5 2.2,0.9 3.1,1.1c15.9,4.1 31.9,8.3 47.9,12.2c5.7,1.4 10.4,3.6 14.4,8.1c5.1,5.7 10.8,10.8 16.2,16.4c6,6.2 11.8,12.5 18.4,19.6c13.3,-13.3 25.6,-25.5 38.3,-38.1c0,25.5 0,50.7 0,75.8c24,0 47.4,0 71.5,0c0,-25.9 0,-51.5 0,-77.2c0.5,-0.3 1.1,-0.7 1.6,-1c12.9,13.9 25.7,27.7 37.7,40.6c11.1,-10.5 21.3,-19.2 30.3,-29c9.2,-10 18.9,-18.5 33.1,-20.1c0.3,0 0.7,-0.1 1,-0.2c12.2,-3.3 24.3,-6.6 36.9,-10.1c-4.6,-17.1 -9.1,-33.8 -14,-51.7c23,13.3 44.7,25.8 66.9,38.5c12,-20.8 23.8,-41.1 35.7,-61.8c-22.8,-13.2 -45.1,-26.1 -68.3,-39.5c19.5,-5.4 37.9,-10.6 56.4,-15.8c-4.6,-16.6 -8.7,-32.5 -13.5,-48.2c-2.2,-7.2 -2.2,-13.7 -0.1,-20.8c4.5,-15.2 8.2,-30.7 12.3,-46.4c-17.1,-4.6 -33.9,-9 -51.8,-13.8c23,-13.3 44.9,-25.9 66.9,-38.7c-12.1,-20.8 -23.9,-41.2 -35.7,-61.8c-22.9,13.2 -45.2,26.1 -68.3,39.4c5,-19.4 9.7,-38 14.5,-56.7c-21.5,-5.6 -42.3,-10.9 -63,-16.5c-2.3,-0.6 -4.6,-1.9 -6.3,-3.6c-10.4,-10.1 -20.6,-20.4 -30.9,-30.6c-1.3,-1.2 -2.6,-2.4 -4.9,-4.6c-12.5,12.5 -24.8,24.7 -37.4,37.3c0,-25.2 0,-50.4 0,-75.5c-24,0 -47.4,0 -71.3,0c0,25.9 0,51.5 0,77c-0.4,0.3 -0.8,0.5 -1.3,0.8c-13,-13.7 -26,-27.4 -39.9,-42c-2.6,3.1 -3.8,4.8 -5.3,6.3c-12.3,12.6 -24.6,25.3 -37.1,37.8c-1.8,1.8 -4.3,3.1 -6.7,3.8c-11,3.2 -22.1,6.1 -33.2,9.2c-5.1,1.4 -10.1,2.9 -15.4,4.4c4.6,17.1 9.1,33.8 14,51.6c-22.9,-13.2 -44.8,-25.8 -66.9,-38.6c-12,20.8 -23.8,41.2 -35.7,61.8c22.8,13.2 45,26 68.3,39.5c-19.6,5.5 -37.9,10.6 -56.4,15.8c5.2,18.7 10.1,36.9 15.3,54.9c1.5,5 1.5,9.6 0.1,14.6c-4.1,14.5 -7.8,29.2 -11.7,44.2c17.2,4.6 34,9 51.8,13.8C128.3,591.3 106.5,604 84.3,616.8zM694.6,265.9c-10,9 -19.8,17.8 -29.7,26.8c9.8,11 19.4,21.6 29.1,32.5c-11.3,0 -21.6,0 -33.5,0c0,7.8 -0.1,15.9 0,24c0.1,7.5 -1.4,14.3 -6.2,20.4c-3.9,4.9 -6.9,10.6 -10.6,16.2c8.2,5.3 16.3,10.6 25.3,16.5c-15,3.2 -28.6,6.1 -42.6,9.1c2.8,13.2 5.6,26.1 8.4,39.2c14.6,-3.1 28.4,-5.9 43.5,-9.1c-6.3,10 -11.9,18.8 -17.6,27.8c6.8,4.4 13.1,8.8 19.7,12.5c6.7,3.7 11.4,8.6 14.4,15.8c2.7,6.5 6.4,12.6 9.7,19c9,-4.6 17.4,-8.9 26.8,-13.7c-4.7,14.5 -8.9,27.8 -13.3,41.5c13,4.2 25.4,8.2 38.1,12.3c4.7,-14.3 9.1,-27.8 13.8,-42.2c5.3,10.1 10.2,19.5 15.4,29.2c9,-4.7 17.7,-9.3 26.5,-13.6c2.6,-1.2 5.6,-1.9 8.5,-2c9.3,-0.2 18.5,-0.1 28.3,-0.1c0.5,-8.7 1,-18.2 1.6,-28.9c10.2,11.3 19.6,21.7 29.2,32.2c10.2,-9.2 19.8,-17.9 29.7,-26.8c-9.9,-11 -19.4,-21.6 -29,-32.4c11.2,0 21.6,0 32.4,0c0.4,-9.3 0.6,-18.8 1.4,-28.2c0.3,-3.3 1.3,-6.8 3,-9.7c4.7,-8 9.9,-15.6 15,-23.5c-8.5,-5.5 -16.5,-10.7 -25.4,-16.5c14.7,-3.1 28.4,-6.1 42.6,-9.1c-2.8,-13.2 -5.6,-26.1 -8.3,-39.2c-14.6,3.1 -28.6,6 -43.5,9.1c6.3,-9.9 11.9,-18.7 17.7,-27.9c-9.6,-6.1 -19.1,-11.9 -28.3,-18.2c-2.6,-1.8 -5,-4.4 -6.6,-7.1c-4.1,-7.2 -7.7,-14.6 -11.5,-22.1c-8.9,4.5 -17.3,8.8 -26.9,13.8c4.7,-14.5 9,-27.8 13.4,-41.5c-12.8,-4.2 -25.3,-8.2 -38,-12.4c-4.6,13.9 -9,27.6 -13.8,42.2c-5.4,-10.3 -10.3,-19.6 -15.4,-29.2c-8.9,4.6 -17.1,9.3 -25.7,13.2c-3.7,1.7 -8.1,2.7 -12.2,2.8c-8.1,0.2 -16.1,-0.6 -24.4,-0.9c-0.5,10.1 -1.1,19.5 -1.6,30.1C713.5,286.8 704.2,276.6 694.6,265.9zM590.1,428.7c9.6,2.5 18.3,4.8 27.7,7.3c-1.5,-7.2 -2.9,-13.7 -4.4,-20.8C605.6,419.8 598.3,424 590.1,428.7z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M362.9,770.2c-10.5,0 -20.2,0 -30.5,0c0,-35.2 0,-70 0,-104.7c-19.4,19.1 -38.8,38.1 -58.2,57.1c-7.3,-7.5 -14.2,-14.6 -22.1,-22.7c5.1,-4.8 10.9,-9.8 16.3,-15.2c20.4,-20.4 40.7,-40.9 60.9,-61.4c1.6,-1.6 3,-4.2 3,-6.4c0.2,-27.2 0.1,-54.3 0.1,-81.5c0,-0.6 -0.1,-1.3 -0.3,-2.6c-1.9,1 -3.5,1.8 -5,2.6c-21.6,12.5 -43.1,25.1 -64.8,37.5c-3.8,2.2 -5.7,4.9 -6.7,9.1c-8.7,34.4 -17.6,68.7 -26.4,103c-0.3,1.1 -0.7,2.2 -1.3,3.8c-9.7,-2.5 -19.2,-4.9 -29.4,-7.5c7.1,-27.8 14.2,-55.2 21.6,-84.1c-31.6,18.2 -62,35.8 -92.8,53.5c-5.2,-8.9 -10,-17.4 -15.3,-26.4c30.5,-17.6 60.8,-35.1 92.1,-53.3c-27.2,-7.2 -53.3,-14.1 -80,-21.1c2.5,-9.7 5,-19.2 7.6,-29.1c1.9,0.4 3.6,0.6 5.3,1c33.6,8.8 67.3,17.7 100.9,26.4c1.8,0.5 4.2,0.8 5.6,-0.1c24,-13.7 47.9,-27.5 72.4,-41.6c-1.6,-1.1 -2.8,-1.9 -4,-2.6c-22.6,-13 -45.3,-26.1 -68,-38.9c-2,-1.1 -5.1,-1.2 -7.3,-0.6c-35,9.6 -69.9,19.3 -104.8,29c-0.8,0.2 -1.6,0.4 -3,0.8c-2.7,-9.7 -5.4,-19.2 -8.2,-29.3c27.7,-7.7 55.1,-15.4 83.6,-23.3c-31.5,-18.2 -61.9,-35.8 -92.7,-53.6c5.2,-9 10.2,-17.6 15.3,-26.5c30.6,17.7 60.8,35.1 92.2,53.2c-7.4,-27.2 -14.5,-53.2 -21.7,-79.8c9.8,-2.7 19.4,-5.3 29.4,-8.1c2.9,10.7 5.8,21.1 8.6,31.4c6.8,24.9 13.5,49.8 20.3,74.6c0.5,1.9 1.9,4.1 3.5,5c23.3,13.6 46.7,27 70,40.5c0.5,0.3 1.2,0.4 2.4,0.9c0,-2.3 0,-4 0,-5.8c0,-25.3 0,-50.7 -0.3,-76c0,-2.5 -1.3,-5.5 -3.1,-7.2c-25.2,-25 -50.6,-49.8 -75.9,-74.6c-1.3,-1.3 -2.8,-2.4 -4.8,-4.1c7.9,-7.3 15.2,-14 22.9,-21.1c19.7,19.3 39.9,39.1 61.1,59.9c0,-36.4 0,-71.4 0,-106.8c10.3,0 20.1,0 30.5,0c0,34.9 0,69.7 0,104.6c19.4,-19.4 38.5,-38.5 57.6,-57.5c7.8,7.9 14.8,15 22,22.4c-0.6,0.6 -1.6,1.9 -2.7,3c-24.5,24.7 -49.1,49.4 -73.6,74.2c-1.5,1.5 -2.9,3.9 -2.9,5.9c-0.2,28 -0.1,56 -0.1,84c0,0.5 0.2,1 0.3,1.8c0.8,-0.3 1.6,-0.5 2.3,-0.9c24.6,-14.2 49.3,-28.5 73.8,-42.9c1.8,-1.1 3.1,-3.7 3.7,-5.9c9,-34.4 17.9,-68.9 26.8,-103.4c0.4,-1.4 0.8,-2.9 1.4,-4.9c9.8,2.5 19.3,5 29.5,7.6c-7.2,28 -14.3,55.6 -21.6,84.1c31.4,-18.1 61.9,-35.7 92.8,-53.5c5.1,8.8 10.1,17.4 15.3,26.5c-30.6,17.7 -60.9,35.2 -92.2,53.3c27.3,7.2 53.4,14.1 80,21.1c-2.6,9.9 -5.1,19.5 -7.8,29.5c-15,-3.9 -29.6,-7.7 -44.2,-11.6c-20.6,-5.4 -41.2,-10.9 -61.8,-16.2c-2,-0.5 -4.8,-0.5 -6.5,0.5c-24,13.7 -47.9,27.5 -71.8,41.3c-0.7,0.4 -1.3,0.9 -2.4,1.7c1.9,1.2 3.3,2.2 4.9,3.1c22.1,12.7 44.1,25.4 66.3,37.9c2.3,1.3 5.7,1.7 8.3,1c35.8,-9.7 71.5,-19.7 107.9,-29.8c2.7,9.8 5.4,19.4 8.2,29.4c-27.7,7.7 -55,15.3 -83.6,23.3c31.4,18.2 61.9,35.8 92.7,53.6c-5.1,8.8 -10,17.4 -15.3,26.5c-30.6,-17.6 -60.9,-35.2 -92.2,-53.2c7.3,27 14.4,53.1 21.7,79.9c-9.8,2.7 -19.3,5.3 -29.4,8c-2.7,-9.8 -5.3,-19.2 -7.9,-28.6c-7,-25.7 -13.9,-51.4 -21.1,-77c-0.6,-2 -1.9,-4.4 -3.6,-5.5c-23.7,-13.9 -47.5,-27.6 -71.3,-41.3c-0.7,-0.4 -1.4,-0.6 -2.9,-1.3c0,1.8 0,3 0,4.3c0.1,26.2 0.1,52.3 0.4,78.5c0,2.3 1.3,5.1 3,6.8c25.9,25.7 52,51.2 78,76.8c0.6,0.6 1.4,0.9 1.9,1.1c-7.7,7.4 -14.8,14.3 -22.4,21.7c-19.2,-18.9 -39.5,-38.7 -60.7,-59.6C362.9,699.8 362.9,734.9 362.9,770.2z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M382.8,446.5c0,-14.9 0,-29.3 0.1,-43.7c0,-1.1 1,-2.4 1.9,-3.3c19.5,-19.7 39.1,-39.5 58.7,-59.2c0.3,-0.3 0.8,-0.5 1.9,-1.1c-3.2,12.4 -6.1,24.2 -9.2,36c-3.8,14.8 -7.6,29.6 -11.6,44.4c-0.5,1.9 -1.7,4.2 -3.2,5.1c-11.8,7.1 -23.8,13.9 -35.8,20.8C384.9,445.8 384.1,446 382.8,446.5zM399.6,417.9c10.4,-4.2 13.7,-9.9 14.3,-24.3c-3.4,3.4 -6.4,7 -10,9.8C399,407.2 398.2,412 399.6,417.9z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M539.2,506.6c-26.7,7.4 -52.9,14.8 -79.2,22c-1.4,0.4 -3.4,0.1 -4.7,-0.6c-11.1,-6.3 -22.2,-12.7 -33.3,-19.2c-0.4,-0.2 -0.6,-0.7 -1.1,-1.4c12.5,-7.2 24.8,-14.4 37.2,-21.4c1,-0.6 2.6,-0.6 3.7,-0.3c25.2,6.6 50.4,13.3 75.6,19.9C537.8,505.8 538.1,506 539.2,506.6zM475.8,506.9c-7.4,-2.8 -15,-6.7 -21.9,1C461.6,515.2 468.5,507.8 475.8,506.9z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M441.6,671.5c-4.9,-5.6 -9.6,-11.5 -14.9,-16.8c-13.4,-13.4 -27.1,-26.6 -40.6,-40c-1.1,-1.1 -2.5,-2.7 -2.5,-4c-0.2,-13.6 -0.1,-27.2 -0.1,-41.7c10.4,6 19.9,11.8 29.7,16.9c6.6,3.4 10,7.9 11.7,15.2c5.3,21.5 11.5,42.7 17.3,64c0.4,1.6 0.7,3.2 1.1,4.7C442.8,670.5 442.2,671 441.6,671.5zM411,615.7c-1.7,-13 -3.7,-16 -11.2,-17.3C397.6,608.1 406.8,610.3 411,615.7z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M311.8,567.9c0,14.8 0,28.4 -0.1,42c0,1.3 -0.7,3 -1.6,3.9c-17.9,18.1 -35.8,36.2 -53.8,54.2c-0.3,0.3 -0.8,0.5 -1.9,1c3.2,-12.7 6.3,-24.9 9.4,-37c3.3,-12.9 6.5,-25.8 10.1,-38.6c0.7,-2.5 2.8,-5.2 5.1,-6.6C289.5,580.5 300.3,574.6 311.8,567.9zM295,596.8c-9.2,2.7 -6.8,11.4 -9.2,17.5C291.1,609.7 298.2,606 295,596.8z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M311.4,444.4c-12.5,-7.2 -24.2,-13.9 -35.8,-20.7c-0.9,-0.5 -1.6,-1.7 -1.9,-2.7c-6.8,-24.8 -13.5,-49.6 -19.4,-75c5.8,5.6 11.5,11.1 17.2,16.7c12.6,12.4 25.1,24.7 37.6,37.2c1.1,1.1 2.1,2.7 2.2,4.1C311.5,417 311.4,430.2 311.4,444.4zM294.7,415.1c2.3,-8.8 -5.6,-10.7 -9.3,-15.3C287.3,405.5 285.7,413.3 294.7,415.1z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M275.7,506.3c-11.9,6.9 -22.9,13.3 -34.1,19.6c-1.4,0.8 -3.6,1.2 -5.1,0.8c-24.2,-6.2 -48.3,-12.6 -72.4,-19c-0.6,-0.2 -1.1,-0.6 -2.3,-1.2c17.5,-4.9 34.4,-9.6 51.3,-14.3c7.5,-2.1 15.1,-4.2 22.6,-6.2c1.5,-0.4 3.5,-0.6 4.6,0C252,492.5 263.4,499.2 275.7,506.3zM242.3,506.3c-6.2,-6.3 -11.8,-1.4 -17.5,0C230.5,507.5 236.3,512.4 242.3,506.3z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M690.8,475.1c-4.8,-3 -9.4,-6 -14.5,-9.2c8.6,-13.5 17,-26.8 26.1,-41.2c-20.2,4.3 -39.2,8.3 -58.8,12.4c-1.2,-5.6 -2.4,-11 -3.6,-16.9c19.4,-4.1 38.3,-8.2 58.4,-12.5c-13.5,-8.7 -26.2,-16.9 -39.1,-25.3c3.2,-5 6.3,-9.7 9.4,-14.6c16.7,10.8 33.2,21.3 49.4,32c3.2,2.1 6.2,2.6 9.8,1.7c13.6,-3.1 27.3,-5.9 41.7,-9c-1.9,-2.2 -3.5,-4.1 -5.1,-5.9c-8.4,-9.2 -16.7,-18.6 -25.3,-27.6c-1.5,-1.6 -4.2,-2.7 -6.3,-2.8c-19.1,-1 -38.3,-1.7 -57.4,-2.5c-1.1,0 -2.3,-0.3 -4.1,-0.5c0.3,-5.7 0.6,-11.2 0.8,-17c16.1,0.7 31.7,1.3 48.6,2c-13.9,-15.5 -27,-30.1 -40.2,-44.8c4.3,-3.8 8.3,-7.5 12.9,-11.6c13.1,14.5 26.1,28.9 40.1,44.4c0.8,-16.1 1.6,-30.9 2.3,-46.4c5.9,0.3 11.4,0.6 17.3,0.9c-0.8,16.7 -1.2,32.9 -2.6,48.9c-0.9,10 0.5,18.1 8.4,25.3c8.3,7.6 15.3,16.6 23.4,25.6c0.8,-2 1.4,-3.4 1.9,-4.9c3.9,-12.2 7.7,-24.4 11.8,-36.5c1.2,-3.5 0.7,-6.2 -0.9,-9.4c-9.3,-17.6 -18.5,-35.4 -28,-53.6c5.1,-2.7 10,-5.2 15.4,-8.1c7.5,14.4 14.8,28.3 22.6,43.2c6.3,-19.4 12.4,-38 18.7,-57.1c5.5,1.7 10.8,3.4 16.5,5.2c-6.1,18.7 -12.1,37.2 -18.4,56.9c14.3,-7.3 27.6,-14.1 41.3,-21.2c2.6,5.1 5.2,9.9 8,15.3c-7.9,4.1 -15.7,8.2 -23.4,12.2c-9.9,5.1 -19.9,10.1 -29.7,15.3c-1.8,0.9 -3.9,2.5 -4.5,4.2c-5,14.6 -9.7,29.3 -14.7,45c2.2,-0.3 3.7,-0.4 5.2,-0.7c13.7,-2.9 27.3,-5.7 40.9,-8.9c2.3,-0.5 4.8,-2.3 6.1,-4.3c11.1,-17 21.9,-34.2 33.2,-51.9c4.9,3.1 9.5,6 14.7,9.3c-8.6,13.6 -17,26.9 -26.1,41.2c20.1,-4.2 39.2,-8.3 58.8,-12.4c1.2,5.7 2.4,11 3.7,16.9c-19.3,4.1 -38.2,8.2 -58.4,12.5c13.6,8.8 26.2,16.9 39,25.3c-3.2,5 -6.1,9.5 -9.3,14.5c-4.5,-2.9 -8.7,-5.5 -12.8,-8.2c-12.6,-8.1 -25.1,-16.3 -37.8,-24.3c-1.9,-1.2 -4.7,-1.8 -6.8,-1.3c-14.9,2.9 -29.6,6.1 -45,9.4c0.8,1.2 1.3,2.1 2,2.9c9.3,10.3 18.4,20.6 27.9,30.6c1.6,1.7 4.4,2.9 6.8,3c19.1,1 38.2,1.8 57.4,2.6c1.1,0.1 2.2,0.3 3.4,0.5c0,5.5 0,10.8 0,16.9c-16.1,-0.7 -31.8,-1.3 -49,-2.1c13.8,15.4 26.8,29.9 40.2,44.8c-4.2,3.9 -8.3,7.6 -12.8,11.7c-13.2,-14.6 -26.2,-29.1 -40.1,-44.5c-0.8,15.9 -1.6,30.7 -2.3,45.6c-5.7,0 -11.2,0 -17.3,0c0.6,-12.7 1.2,-24.8 1.8,-37c0.4,-7.8 0.9,-15.6 1.2,-23.4c0.1,-1.6 0,-3.6 -1,-4.6c-10.4,-11.9 -21.1,-23.5 -32.3,-36c-3.3,10.3 -6.4,19.8 -9.5,29.4c-0.3,0.8 -0.3,1.7 -0.7,2.4c-5.8,10.5 -3.2,19.7 2.6,29.6c8.3,14 15.2,28.7 22.9,43.5c-5.2,2.7 -10,5.3 -15.3,8.1c-7.4,-14.1 -14.7,-28 -22.6,-43.2c-6.4,19.7 -12.5,38.2 -18.7,57.1c-5.5,-1.7 -10.7,-3.4 -16.5,-5.2c6.1,-18.7 12,-37.2 18.4,-56.9c-14.4,7.4 -27.6,14.2 -41.3,21.2c-2.7,-5.1 -5.2,-9.9 -8,-15.3c7.6,-3.9 15,-7.8 22.5,-11.7c10.3,-5.3 20.7,-10.6 31,-16c1.5,-0.8 3.4,-2 3.9,-3.5c5,-14.7 9.8,-29.6 14.9,-45.3c-10.9,2.3 -20.9,4.4 -30.9,6.6c-0.6,0.1 -1.3,0.6 -1.9,0.6c-11.8,-0.1 -18.1,6.9 -23.5,16.5c-7.4,13 -15.9,25.4 -24,38C692.7,472.4 691.8,473.6 690.8,475.1z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M815.9,372.4c2.6,-8.2 4.9,-15.3 7.3,-22.4c0.4,-1.2 1.7,-2.5 2.9,-3.1c13.2,-6.9 26.5,-13.7 39.8,-20.5c0.4,-0.2 0.9,-0.1 2.1,-0.2c-6.6,10.4 -13.4,20 -19,30.2c-4.3,8 -9.9,12.6 -19.1,13.3C825.6,369.9 821.3,371.3 815.9,372.4z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M825.3,411.5c8.6,-1.8 16.2,-3.5 23.8,-5c0.9,-0.2 2,0 2.8,0.5c12.3,7.8 24.5,15.7 36,23.1c-10.7,0 -22.1,-0.5 -33.4,0.2c-9.4,0.6 -16.2,-2.3 -21.4,-10.1C831.1,417.2 828.3,414.8 825.3,411.5z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M794.9,437.7c5.5,6.1 10.6,11.7 15.6,17.5c0.8,1 1.2,2.7 1.1,4.1c-0.6,14.1 -1.3,28.2 -2,43.8c-1.4,-2.4 -2.2,-3.6 -2.9,-4.9c-5.9,-11.3 -11.9,-22.6 -17.6,-34c-0.9,-1.8 -1.1,-4.5 -0.6,-6.4C790.3,451.1 792.6,444.7 794.9,437.7z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M708.8,468.3c7.7,-12.2 15.4,-24.4 23.3,-36.5c0.7,-1.1 2.2,-2.2 3.5,-2.5c6.8,-1.6 13.6,-2.9 21.3,-4.5c-2.6,7.9 -4.9,15.2 -7.3,22.5c-0.3,0.9 -1.4,1.8 -2.4,2.3c-12.5,6.5 -25,12.9 -37.5,19.4C709.3,468.8 709.1,468.5 708.8,468.3z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M764.9,295.9c6.9,13.2 13.4,25.6 19.8,38.2c0.5,1 0.5,2.6 0.2,3.7c-2,6.7 -4.2,13.3 -6.7,20.9c-5.5,-6.2 -10.7,-11.9 -15.7,-17.7c-0.4,-0.5 -0.4,-1.5 -0.4,-2.3c0.6,-13.3 1.2,-26.6 1.8,-39.8C763.9,298.1 764.4,297.4 764.9,295.9z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M748.3,385.5c-7.5,1.6 -13.8,3.1 -20.2,4.3c-1.5,0.3 -3.6,0.4 -4.8,-0.4c-11.8,-7.4 -23.4,-15 -34.9,-23.4c2,0 4.1,-0.1 6.1,0c11.5,0.5 22.9,0.9 34.4,1.5c1.4,0.1 3.2,0.3 4.1,1.2C738.1,374 742.8,379.5 748.3,385.5z"/>
+</vector>
diff --git a/res/drawable/icon_stamp.xml b/res/drawable/icon_stamp.xml
new file mode 100644
index 000000000..79456e426
--- /dev/null
+++ b/res/drawable/icon_stamp.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+ android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M342.7,119.2c-108.3,0-216.5,0-324.7-0.1c0,3.6,0,7.1,0,10.6c108.3,0,216.5,0,324.7,0.1
+ C342.7,126.3,342.7,122.8,342.7,119.2 M288.7,110.8C270.3,78.2,226.9,43.5,168,49.2c-26.8,2.6-50.3,13.1-70.6,30.9
+ c-10.1,8.8-18.5,19.1-25.4,30.8c3,0,5.8,0,8.5,0c0.9,0,1.5-0.3,2-1c11.4-17.1,26.1-30.5,44.3-39.8
+ c23.8-12.2,48.8-15.9,75-11.1c24,4.4,44.6,15.6,62,32.9c5.6,5.6,10.5,11.7,14.8,18.3c0.4,0.6,0.9,0.9,1.6,0.8
+ c2.5,0,5.1,0,7.6,0C288,110.9,288.3,110.9,288.7,110.8 M317.3,136.3c-91.3,0-182.6,0-273.9-0.1c0,2.6,0,5,0,7.5
+ c91.3,0,182.6,0,273.9,0.1C317.3,141.3,317.3,138.8,317.3,136.3 M268.9,110.9C249.2,83.2,212.1,60.6,167,66.1
+ c-15,1.8-29.1,6.7-42.1,14.4c-13,7.8-24,17.8-33.1,30.3c3.5,0,6.8,0,10.1,0c0.3,0,0.7-0.3,0.9-0.6c2.5-2.7,4.9-5.5,7.5-8
+ c15.9-15.2,34.7-24.5,56.4-27.6c12.4-1.7,24.7-1.2,36.8,1.8c21,5,38.6,15.8,52.9,32.1c1.6,1.8,3.1,2.6,5.4,2.4
+ C264.1,110.7,266.4,110.9,268.9,110.9 M171.5,111.3c0.6-0.3,0.9-0.4,1.3-0.6c2.5-1.3,5.1-2.7,7.6-4c0.7-0.4,1.2-0.3,1.8,0
+ c2.5,1.4,5.1,2.7,7.6,4.1c0.3,0.2,0.7,0.3,1.1,0.5c0-0.4,0-0.6-0.1-0.8c-0.5-3.1-1.1-6.2-1.6-9.3c-0.1-0.4,0.1-1,0.4-1.3
+ c1.7-1.8,3.5-3.5,5.3-5.2c0.6-0.6,1.3-1.2,2.1-2c-0.5-0.1-0.7-0.2-0.9-0.2c-2.9-0.4-5.8-0.9-8.8-1.3c-0.8-0.1-1.4-0.4-1.8-1.2
+ c-1.2-2.7-2.6-5.4-3.9-8c-0.1-0.2-0.3-0.5-0.5-0.8c-1.3,2.6-2.7,5-3.6,7.5c-0.8,2-2,2.6-3.9,2.8c-2.7,0.2-5.3,0.7-8.1,1.2
+ c0.2,0.2,0.3,0.4,0.5,0.5c2.2,2.2,4.5,4.5,6.7,6.7c0.4,0.4,0.6,0.8,0.5,1.4c-0.3,1.1-0.4,2.3-0.6,3.4
+ C172.3,106.8,171.9,108.9,171.5,111.3 M134.3,96.1c1.8,1.9,3.5,3.7,5.2,5.5c0.5,0.5,0.6,1,0.5,1.7c-0.4,2.4-0.8,4.9-1.3,7.5
+ c0.5-0.2,0.8-0.4,1.1-0.5c1.9-1,3.8-2,5.7-3.1c0.6-0.3,1-0.4,1.6,0c1.9,1.1,3.9,2.1,5.8,3.1c0.3,0.2,0.6,0.3,1,0.5
+ c-0.5-2.6-0.9-5.1-1.3-7.5c-0.1-0.7,0-1.1,0.5-1.7c1.8-1.8,3.5-3.7,5.2-5.5c-0.2,0-0.5-0.1-0.8-0.2c-2.2-0.3-4.4-0.7-6.6-1
+ c-0.7-0.1-1-0.4-1.2-0.9c-1-2.1-2-4.2-3-6.2c-0.1-0.2-0.3-0.4-0.4-0.7c-1.2,2.4-2.3,4.7-3.4,7c-0.2,0.5-0.5,0.8-1.1,0.9
+ C139.3,95.4,136.7,95.8,134.3,96.1 M216.1,87.1c-1.2,2.5-2.4,4.8-3.5,7.1c-0.3,0.5-0.5,0.8-1.2,0.9c-1.3,0.1-2.7,0.4-4,0.6
+ c-1.2,0.2-2.4,0.4-3.5,0.5c1.7,1.8,3.4,3.7,5.2,5.5c0.5,0.5,0.6,1,0.5,1.8c-0.4,2.4-0.8,4.9-1.3,7.5c0.5-0.2,0.8-0.4,1.1-0.5
+ c1.9-1,3.9-2,5.8-3.1c0.5-0.3,0.9-0.3,1.4,0c2,1.1,3.9,2.1,5.9,3.2c0.3,0.2,0.6,0.3,1,0.5c-0.4-2.6-0.8-5-1.3-7.4
+ c-0.1-0.8,0-1.3,0.6-1.8c1.8-1.8,3.5-3.6,5.2-5.4c-2.2-0.3-4.4-0.7-6.7-1c-1.1-0.1-1.8-0.5-2.3-1.6
+ C218.3,91.4,217.2,89.4,216.1,87.1"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M342.7,119.2c0,3.6,0,7.1,0,10.6c-108.2,0-216.4,0-324.7-0.1c0-3.5,0-7.1,0-10.6
+ C126.3,119.1,234.5,119.2,342.7,119.2"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M288.7,110.8c-0.4,0-0.7,0.1-1,0.1c-2.5,0-5.1,0-7.6,0c-0.7,0-1.2-0.2-1.6-0.8
+ c-4.3-6.6-9.3-12.7-14.8-18.3c-17.4-17.3-38-28.5-62-32.9c-26.2-4.8-51.3-1.1-75,11.1c-18.2,9.3-32.9,22.7-44.3,39.8
+ c-0.5,0.8-1.1,1.1-2,1c-2.7-0.1-5.5,0-8.5,0c7-11.7,15.4-22,25.4-30.8c20.3-17.8,43.9-28.3,70.6-30.9
+ C226.9,43.5,270.3,78.2,288.7,110.8"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M317.3,136.3c0,2.5,0,5,0,7.5c-91.3,0-182.6,0-273.9-0.1c0-2.5,0-5,0-7.5
+ C134.7,136.3,226,136.3,317.3,136.3"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M268.9,110.9c-2.5,0-4.8-0.2-7.1,0c-2.3,0.2-3.8-0.6-5.4-2.4c-14.3-16.3-31.9-27.1-52.9-32.1
+ c-12.1-2.9-24.4-3.5-36.8-1.8c-21.7,3.1-40.5,12.3-56.4,27.6c-2.6,2.5-5,5.4-7.5,8c-0.3,0.3-0.6,0.6-0.9,0.6c-3.3,0-6.5,0-10.1,0
+ c9.1-12.5,20.1-22.6,33.1-30.3c13-7.8,27.1-12.6,42.1-14.4C212.1,60.6,249.2,83.2,268.9,110.9"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M171.5,111.3c0.4-2.4,0.7-4.5,1.1-6.7c0.2-1.1,0.3-2.3,0.6-3.4c0.1-0.6,0-1-0.5-1.4
+ c-2.3-2.2-4.5-4.5-6.7-6.7c-0.1-0.1-0.3-0.3-0.5-0.5c2.8-0.4,5.4-0.9,8.1-1.2c2-0.2,3.2-0.8,3.9-2.8c1-2.6,2.4-4.9,3.6-7.5
+ c0.2,0.3,0.4,0.6,0.5,0.8c1.3,2.7,2.7,5.3,3.9,8c0.4,0.8,0.9,1.1,1.8,1.2c2.9,0.4,5.8,0.8,8.8,1.3c0.2,0,0.4,0.1,0.9,0.2
+ c-0.8,0.7-1.4,1.4-2.1,2c-1.8,1.7-3.5,3.5-5.3,5.2c-0.3,0.3-0.5,0.9-0.4,1.3c0.5,3.1,1,6.2,1.6,9.3c0,0.2,0,0.4,0.1,0.8
+ c-0.4-0.2-0.8-0.3-1.1-0.5c-2.6-1.4-5.1-2.7-7.6-4.1c-0.6-0.4-1.1-0.4-1.8,0c-2.5,1.4-5,2.7-7.6,4
+ C172.4,110.8,172.1,111,171.5,111.3"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M134.3,96.1c2.5-0.4,5-0.8,7.5-1.1c0.6-0.1,0.9-0.4,1.1-0.9c1.1-2.3,2.2-4.6,3.4-7
+ c0.2,0.3,0.3,0.5,0.4,0.7c1,2.1,2,4.2,3,6.2c0.3,0.5,0.6,0.9,1.2,0.9c2.2,0.3,4.4,0.6,6.6,1c0.3,0,0.6,0.1,0.8,0.2
+ c-1.7,1.8-3.5,3.7-5.2,5.5c-0.5,0.5-0.6,1-0.5,1.7c0.4,2.4,0.8,4.9,1.3,7.5c-0.4-0.2-0.8-0.3-1-0.5c-1.9-1-3.9-2-5.8-3.1
+ c-0.6-0.3-1-0.3-1.6,0c-1.9,1.1-3.8,2-5.7,3.1c-0.3,0.2-0.6,0.3-1.1,0.5c0.4-2.6,0.8-5.1,1.3-7.5c0.1-0.7,0-1.2-0.5-1.7
+ C137.7,99.8,136,98,134.3,96.1"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M216.1,87.1c1.1,2.3,2.2,4.4,3.1,6.5c0.5,1.1,1.2,1.5,2.3,1.6c2.3,0.3,4.5,0.6,6.7,1
+ c-1.7,1.8-3.4,3.7-5.2,5.4c-0.6,0.6-0.7,1.1-0.6,1.8c0.5,2.4,0.8,4.8,1.3,7.4c-0.4-0.2-0.7-0.3-1-0.5c-2-1-4-2.1-5.9-3.2
+ c-0.5-0.3-0.9-0.3-1.4,0c-1.9,1.1-3.9,2.1-5.8,3.1c-0.3,0.2-0.6,0.3-1.1,0.5c0.4-2.6,0.8-5.1,1.3-7.5c0.1-0.7,0-1.2-0.5-1.8
+ c-1.8-1.8-3.5-3.6-5.2-5.5c1.1-0.2,2.3-0.4,3.5-0.5c1.3-0.2,2.7-0.4,4-0.6c0.6-0.1,0.9-0.3,1.2-0.9
+ C213.7,91.9,214.8,89.6,216.1,87.1"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M342.7,234.5c-108.2,0-216.4,0-324.7-0.1c0,3.5,0,7.1,0,10.6c108.2,0,216.4,0,324.7,0.1
+ C342.7,241.6,342.7,238.1,342.7,234.5 M287.7,253.4c-2.5,0-5.1,0-7.6,0c-0.7,0-1.2,0.2-1.6,0.8c-4.3,6.6-9.3,12.7-14.8,18.3
+ c-17.4,17.3-38,28.5-62,32.9c-26.2,4.8-51.3,1.1-75-11.1c-18.2-9.4-32.9-22.7-44.3-39.9c-0.5-0.8-1.1-1.1-2-1
+ c-2.7,0.1-5.5,0-8.5,0c7,11.7,15.4,22,25.4,30.8c20.3,17.8,43.9,28.3,70.6,30.9c58.9,5.7,102.3-29,120.7-61.6
+ C288.3,253.5,288,253.4,287.7,253.4 M317.3,220.5c-91.3,0-182.6,0-273.9-0.1c0,2.5,0,5,0,7.5c91.3,0,182.6,0,273.9,0.1
+ C317.3,225.5,317.3,223,317.3,220.5 M261.7,253.4c-2.3-0.2-3.8,0.6-5.4,2.4c-14.3,16.3-31.9,27.1-52.9,32.1
+ c-12.1,2.9-24.4,3.5-36.8,1.7c-21.7-3.1-40.5-12.4-56.4-27.6c-2.6-2.5-5-5.4-7.5-8c-0.3-0.3-0.6-0.6-0.9-0.6c-3.3,0-6.5,0-10.1,0
+ c9.1,12.5,20.1,22.6,33.1,30.3c13,7.8,27.1,12.6,42.1,14.5c45.1,5.5,82.2-17.1,101.9-44.8C266.4,253.4,264,253.6,261.7,253.4
+ M172.6,259.7c0.2,1.1,0.3,2.3,0.6,3.4c0.1,0.6,0,1-0.5,1.4c-2.3,2.2-4.5,4.5-6.8,6.7c-0.1,0.1-0.3,0.3-0.5,0.5
+ c2.8,0.4,5.4,0.9,8.1,1.2c2,0.2,3.2,0.8,3.9,2.8c1,2.6,2.4,4.9,3.6,7.5c0.2-0.3,0.4-0.6,0.5-0.8c1.3-2.7,2.7-5.3,3.9-8
+ c0.4-0.8,0.9-1.1,1.8-1.2c2.9-0.4,5.8-0.8,8.8-1.3c0.2,0,0.4-0.1,0.9-0.2c-0.8-0.7-1.4-1.4-2.1-2c-1.8-1.7-3.5-3.5-5.3-5.2
+ c-0.3-0.3-0.5-0.9-0.4-1.3c0.5-3.1,1-6.2,1.6-9.3c0-0.2,0-0.4,0.1-0.8c-0.4,0.2-0.8,0.3-1.1,0.5c-2.6,1.4-5.1,2.7-7.6,4.1
+ c-0.6,0.4-1.1,0.4-1.8,0c-2.5-1.4-5-2.7-7.5-4c-0.3-0.2-0.7-0.3-1.3-0.6C171.9,255.4,172.2,257.5,172.6,259.7 M141.8,269.2
+ c0.6,0.1,0.9,0.4,1.1,0.9c1.1,2.3,2.2,4.6,3.4,7c0.2-0.3,0.3-0.5,0.4-0.7c1-2.1,2-4.2,3-6.2c0.3-0.5,0.6-0.9,1.2-0.9
+ c2.2-0.3,4.4-0.6,6.6-1c0.3,0,0.6-0.1,0.8-0.2c-1.7-1.8-3.5-3.7-5.2-5.5c-0.5-0.5-0.6-1-0.5-1.7c0.4-2.4,0.9-4.9,1.3-7.5
+ c-0.4,0.2-0.7,0.3-1,0.5c-1.9,1-3.9,2-5.8,3.1c-0.6,0.3-1,0.3-1.6,0c-1.9-1.1-3.8-2.1-5.7-3.1c-0.3-0.2-0.6-0.3-1.1-0.5
+ c0.4,2.6,0.8,5.1,1.3,7.5c0.1,0.7,0,1.2-0.5,1.7c-1.8,1.8-3.5,3.6-5.2,5.5C136.7,268.5,139.2,268.9,141.8,269.2 M219.2,270.7
+ c0.5-1.1,1.2-1.5,2.3-1.6c2.3-0.3,4.5-0.6,6.7-1c-1.7-1.8-3.4-3.7-5.2-5.4c-0.6-0.6-0.7-1.1-0.6-1.8c0.5-2.4,0.8-4.8,1.3-7.4
+ c-0.4,0.2-0.7,0.3-1,0.5c-2,1-4,2.1-5.9,3.2c-0.5,0.3-0.9,0.3-1.4,0c-1.9-1.1-3.9-2.1-5.8-3.1c-0.3-0.2-0.6-0.3-1.1-0.5
+ c0.4,2.6,0.8,5.1,1.3,7.5c0.1,0.7,0,1.2-0.5,1.8c-1.8,1.8-3.5,3.6-5.2,5.5c1.1,0.2,2.3,0.4,3.5,0.5c1.3,0.2,2.7,0.4,4,0.6
+ c0.6,0.1,0.9,0.3,1.2,0.9c1.1,2.3,2.2,4.6,3.5,7.1C217.1,274.9,218.3,272.9,219.2,270.7"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M342.7,245.2c0-3.6,0-7.1,0-10.6c-108.2,0-216.4,0-324.7-0.1c0,3.5,0,7.1,0,10.6
+ C126.2,245.1,234.4,245.1,342.7,245.2"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M288.6,253.5c-0.4,0-0.7-0.1-1-0.1c-2.5,0-5.1,0-7.6,0c-0.7,0-1.2,0.2-1.6,0.8
+ c-4.3,6.6-9.3,12.7-14.8,18.3c-17.4,17.3-38,28.5-62,32.9c-26.2,4.8-51.3,1.1-75-11.1c-18.2-9.4-32.9-22.7-44.3-39.9
+ c-0.5-0.8-1.1-1.1-2-1.1c-2.7,0.1-5.5,0-8.5,0c7,11.7,15.4,22,25.4,30.8c20.3,17.8,43.9,28.3,70.6,30.9
+ C226.8,320.8,270.2,286.1,288.6,253.5"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M317.3,228c0-2.5,0-5,0-7.5c-91.3,0-182.6,0-273.9-0.1c0,2.5,0,5,0,7.5C134.7,228,226,228,317.3,228"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M268.8,253.4c-2.5,0-4.8,0.2-7.1,0c-2.3-0.2-3.8,0.6-5.4,2.4c-14.3,16.3-31.9,27.1-52.9,32.1
+ c-12.1,2.9-24.4,3.5-36.8,1.7c-21.7-3.1-40.5-12.4-56.4-27.6c-2.6-2.5-5-5.4-7.5-8c-0.3-0.3-0.6-0.6-0.9-0.6c-3.3,0-6.5,0-10.1,0
+ c9.1,12.5,20.1,22.6,33.1,30.3c13,7.8,27.1,12.6,42.1,14.5C212.1,303.6,249.2,281.1,268.8,253.4"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M171.5,253c0.4,2.4,0.7,4.5,1.1,6.7c0.2,1.1,0.3,2.3,0.6,3.4c0.1,0.6,0,1-0.5,1.4
+ c-2.3,2.2-4.5,4.5-6.7,6.7c-0.1,0.1-0.3,0.3-0.5,0.5c2.8,0.4,5.4,0.9,8.1,1.2c2,0.2,3.2,0.8,3.9,2.8c1,2.6,2.4,4.9,3.6,7.5
+ c0.2-0.3,0.4-0.6,0.5-0.8c1.3-2.7,2.7-5.3,3.9-8c0.4-0.8,0.9-1.1,1.8-1.2c2.9-0.4,5.8-0.8,8.8-1.3c0.2,0,0.4-0.1,0.9-0.2
+ c-0.8-0.7-1.4-1.4-2.1-2c-1.8-1.7-3.5-3.5-5.3-5.2c-0.3-0.3-0.5-0.9-0.4-1.3c0.5-3.1,1-6.2,1.6-9.3c0-0.2,0-0.4,0.1-0.8
+ c-0.4,0.2-0.8,0.3-1.1,0.5c-2.6,1.4-5.1,2.7-7.6,4.1c-0.6,0.4-1.1,0.4-1.8,0c-2.5-1.4-5-2.7-7.6-4
+ C172.4,253.4,172.1,253.3,171.5,253"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M134.2,268.1c2.5,0.4,5,0.8,7.5,1.1c0.6,0.1,0.9,0.4,1.1,0.9c1.1,2.3,2.2,4.6,3.4,7
+ c0.2-0.3,0.3-0.5,0.4-0.7c1-2.1,2-4.2,3-6.2c0.3-0.5,0.6-0.9,1.2-0.9c2.2-0.3,4.4-0.6,6.6-1c0.3,0,0.6-0.1,0.8-0.2
+ c-1.7-1.8-3.5-3.7-5.2-5.5c-0.5-0.5-0.6-1-0.5-1.7c0.4-2.4,0.9-4.9,1.3-7.5c-0.4,0.2-0.8,0.3-1,0.5c-1.9,1-3.9,2-5.8,3.1
+ c-0.6,0.3-1,0.3-1.6,0c-1.9-1.1-3.8-2-5.7-3.1c-0.3-0.2-0.6-0.3-1.1-0.5c0.4,2.6,0.8,5.1,1.3,7.5c0.1,0.7,0,1.2-0.5,1.7
+ C137.7,264.4,136,266.3,134.2,268.1"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M216,277.2c1.1-2.3,2.2-4.4,3.1-6.5c0.5-1.1,1.2-1.5,2.3-1.6c2.3-0.3,4.5-0.6,6.7-1
+ c-1.7-1.8-3.4-3.7-5.2-5.4c-0.6-0.6-0.7-1.1-0.6-1.8c0.5-2.4,0.8-4.8,1.3-7.4c-0.4,0.2-0.7,0.3-1,0.5c-2,1-4,2.1-5.9,3.2
+ c-0.5,0.3-0.9,0.3-1.4,0c-1.9-1.1-3.9-2.1-5.8-3.1c-0.3-0.2-0.6-0.3-1.1-0.5c0.4,2.6,0.8,5.1,1.3,7.5c0.1,0.7,0,1.2-0.5,1.8
+ c-1.8,1.8-3.5,3.6-5.2,5.5c1.1,0.2,2.3,0.4,3.5,0.5c1.3,0.2,2.7,0.4,4,0.6c0.6,0.1,0.9,0.3,1.2,0.9
+ C213.7,272.4,214.8,274.7,216,277.2"/>
+</vector>
diff --git a/res/drawable/icon_sun.xml b/res/drawable/icon_sun.xml
new file mode 100644
index 000000000..a76f4066a
--- /dev/null
+++ b/res/drawable/icon_sun.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="1008.0"
+ android:viewportWidth="1008.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M160.4,465.7c-6.2,-8.6 -5.7,-18.2 -6.4,-27.4c-0.8,-10.3 -1.6,-20.6 -1.8,-30.9c-0.2,-12.9 5.6,-22.6 18.1,-27.1c17.7,-6.4 35.5,-12.3 53.4,-18.1c4.1,-1.3 6.6,-3.2 8.6,-7.1c4.7,-9.4 9.6,-18.6 15.1,-27.5c2.4,-3.8 2.3,-6.6 0.5,-10.4c-20.1,-42.6 -40,-85.2 -60,-127.9c-0.5,-1.1 -1,-2.3 -1.9,-4.4c12.1,4.7 23.4,9.1 34.6,13.6c34.7,13.6 69.4,27.2 104,41c3.1,1.2 5.3,1 8.1,-0.9c39.1,-26.5 82.3,-42.6 129.2,-48.4c3.6,-0.4 4.7,-2.7 5.9,-5.1c20.1,-38.7 40.2,-77.3 60.4,-116c1,-2 2.2,-4 3.7,-6.8c3.3,9.5 6.2,18.1 9.1,26.8c11.8,34.8 23.6,69.6 35.3,104.5c1.3,3.8 3.1,5.8 7.2,7c41.1,12.4 77.8,32.8 109.9,61.3c2.9,2.6 5.5,3.4 9.3,2.4c47.7,-11.6 95.4,-23 143.1,-34.5c1.5,-0.4 3.1,-0.6 5.8,-1.2c-5.7,9 -10.7,17 -15.8,24.9c-11.1,17.4 -22.2,34.8 -33.4,52.2c-1.7,2.6 -1.9,4.7 -1.2,7.8c3.6,15.4 7,30.8 10.1,46.3c0.5,2.6 -0.1,5.6 -0.7,8.4c-6,26.8 -12.4,53.5 -18.1,80.3c-1.1,5.1 -0.2,10.6 0.2,15.9c0.1,1.4 2.1,2.9 3.5,3.9c28.7,19.9 57.5,39.8 86.3,59.7c11.9,8.2 23.9,16.3 36.7,25.2c-2.9,0.8 -4.9,1.4 -6.9,2c-43,11.6 -86,23.4 -129.1,34.7c-8.3,2.2 -13,6.2 -16.3,14.4c-8.4,20.6 -20.3,39.3 -33.5,57.1c-1.3,1.7 -2.1,4.7 -1.6,6.7c7.1,30.8 14.3,61.6 21.7,92.3c4.5,18.9 9.4,37.8 14,56.7c0.2,0.9 0.3,1.9 0.7,3.8c-9.8,-5.1 -18.9,-9.8 -28,-14.4c-33.8,-17.3 -67.6,-34.4 -101.3,-51.8c-8.4,-4.3 -15.5,-4.5 -24.6,-0.7c-15.8,6.7 -32.6,11.2 -49.1,16.3c-3.7,1.1 -6.6,2.4 -8.6,6c-13.4,24 -27,47.8 -40.4,71.8c-10.3,18.6 -20.4,37.4 -31,57.1c-1.2,-2.6 -2.2,-4.4 -3,-6.3c-16.6,-36.5 -33.6,-72.8 -49.7,-109.5c-6.2,-14.1 -14.1,-23.5 -30.3,-27.8c-16.3,-4.3 -31.5,-13.2 -47,-20.5c-3.7,-1.7 -6.7,-2.2 -10.3,-0.7c-23,9.8 -46,19.4 -68.9,29.2c-21.9,9.4 -43.7,18.9 -65.5,28.4c-1.2,0.5 -2.5,0.9 -4.7,1.8c0.9,-2.7 1.5,-4.7 2.2,-6.6c15.2,-45.1 30.4,-90.1 45.8,-135.2c1.6,-4.7 1.1,-8.3 -1.8,-12.4c-16.3,-24.2 -28.4,-50.4 -36.6,-78.4c-1.1,-3.8 -3,-5.8 -6.6,-7.1c-42.5,-15.5 -85,-31.1 -127.4,-46.6c-1.5,-0.6 -3,-1.1 -5.5,-2.1C104.3,495.8 132,480.9 160.4,465.7zM264.6,597.6C309.2,692 422.2,764 550.4,737.8c122.5,-25 194.8,-128.4 204.8,-218.1c-3.7,3 -7.2,6 -10.9,8.8c-15.3,11.5 -33,16.7 -51.6,19.8c-29.6,5 -59.3,9 -89.4,4.5c-27.6,-4.1 -51.4,-15.2 -67.2,-39.3c-5.5,-8.3 -10,-17.3 -14.9,-26c-8.9,-16 -17.7,-32 -26.7,-47.9c-1.7,-3 -4.4,-5.5 -7.6,-9.4c-2,5 -4,8.5 -4.9,12.3c-3.9,16.7 -7.1,33.5 -11.1,50.1c-3.4,14.2 -6,28.8 -11.6,42.2c-9.5,23 -28.5,37.1 -50.7,47.1c-23.6,10.7 -48.7,15.7 -74.2,19c-15.2,2 -30.4,4.6 -45.7,2C280.6,601.5 272.6,599.4 264.6,597.6zM274,351.1c2,-0.1 3.5,-0.2 5,-0.3c22.4,-1.5 44.8,-4.1 67.2,-4.4c36.5,-0.3 72.9,1 109.4,1.3c8.3,0.1 16.9,-0.1 24.8,-2.3c29.5,-8.2 58.8,-16.8 87.9,-26.3c25.5,-8.3 50.9,-16.5 77.3,-21.5c9.7,-1.8 19.4,-3.4 29.4,-5.1C556.9,180 358,206.2 274,351.1zM393.6,377.7c0,-0.2 0,-0.4 0,-0.5c-5,0 -10,0.3 -15,0c-29.3,-1.8 -58.6,-1.4 -87.8,2.1c-36.2,4.4 -71.2,13.6 -105.2,26.8c-3.1,1.2 -4,2.9 -3.8,5.9c0.6,7.1 0.8,14.3 1.4,21.4c0.7,8.1 1.6,15.8 6,23.3c11.5,19.1 21.6,39 33.2,58.1c7,11.6 14.7,23.1 23.7,33.2c16.5,18.4 37.6,28.1 62.8,25.7c14.4,-1.3 28.8,-3.4 43,-5.9c19.7,-3.5 38.9,-8.9 56.3,-19.5c15.3,-9.3 25.2,-22.4 28.8,-40.1c3.2,-16 6.2,-32 10,-47.8c3.4,-13.7 6.7,-27.5 12.1,-40.5c8.7,-21.1 36.9,-24.5 50.9,-8c7.2,8.4 13.4,17.8 19,27.4c10.2,17.6 19.4,35.6 29.2,53.5c7.1,13 17.9,22.2 32.1,26.1c10.8,3 22.1,5.2 33.3,5.8c25.6,1.4 50.8,-2.9 75.8,-8.1c20.1,-4.2 35.9,-15.3 46.3,-32.9c5.8,-9.8 11.3,-20.3 14.2,-31.2c7.2,-26.8 13,-54 19.2,-81.1c1,-4.2 2.5,-8.7 1.8,-12.7c-2,-11.6 -4.8,-23.1 -7.6,-34.6c-0.3,-1.3 -2.5,-3.1 -4,-3.1c-12.6,-0.9 -25.3,-1.9 -37.9,-1.9c-37,0 -73.5,4.3 -109,14.6c-31.9,9.2 -63.7,19.2 -95.2,29.8c-31.1,10.5 -62.7,16 -95.6,14.2C418.9,377.2 406.2,377.7 393.6,377.7zM726.3,767.5c-6.4,-26 -12.6,-50.8 -18.6,-75.1c-16.7,13.4 -33.2,26.7 -49.7,39.9C680.2,743.7 702.7,755.4 726.3,767.5zM487.2,842c12,-22.1 23.6,-43.3 34.7,-63.9c-21.6,-0.6 -43.1,-1.2 -64.6,-1.8C467,797.7 476.9,819.5 487.2,842zM320.1,719.6c-14.8,-13.7 -29.3,-27.1 -43.9,-40.5c-7.7,22.7 -15.5,45.7 -23.7,69.8C276,738.7 298.1,729.1 320.1,719.6zM793.7,501.1c-3.3,19.9 -6.5,39.3 -9.7,59.2c22.6,-6 45.4,-12.1 69.2,-18.5C832.7,527.8 813.2,514.4 793.7,501.1zM302.5,260.9c-20,-7.8 -40.1,-15.8 -61.5,-24.2c9.7,20.7 18.8,40 27.8,59.2C280.2,284.1 291.2,272.6 302.5,260.9zM526.4,133.2c-9.7,18.6 -18.9,36.3 -28,53.9c16.2,1.3 31.6,2.5 47.6,3.8C539.5,172 533.1,153.2 526.4,133.2zM193.6,524.3c-6.9,-12.2 -12.9,-23 -19.2,-34.2c-10.1,5.4 -19.7,10.6 -30.2,16.2C160.9,512.4 176.5,518.1 193.6,524.3zM721.3,288.6c19.2,1.1 36.9,2.1 54.6,3c0.9,0 2.2,-0.2 2.6,-0.8c4,-5.9 7.8,-12 12.2,-19C767.1,277.5 744.9,282.9 721.3,288.6z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M598.6,587.3c10.3,12.3 20.3,24.3 31,37.2c-8.6,4 -16.4,8.2 -24.7,11.5c-36.8,14.7 -75.1,18.4 -114.3,15.6c-32.6,-2.4 -64,-10 -93.7,-24.1c-2.1,-1 -4.2,-2 -6.2,-3.2c-4.6,-2.5 -6.2,-5.8 -4.4,-9.7c1.9,-4.3 5.2,-4.8 9.6,-3.8c12.2,2.8 24.3,6 36.6,7.6c51.3,6.8 101.3,2.8 148.5,-20.7c3,-1.5 5.9,-3.2 8.7,-4.9C592.6,591.2 595.4,589.3 598.6,587.3z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M463.5,392.2c-23.8,20.1 -26.6,48 -32.5,74.5c-2.7,12 -5.4,24 -7.4,36.2c-3.2,19 -15,30.5 -31.7,38.2c-19.9,9.1 -41.2,13.1 -62.6,15.9c-9.6,1.2 -19.2,2.7 -28.8,2.5c-21.2,-0.5 -37.1,-11.7 -49.6,-27.9c-6.3,-8.1 -11.7,-17 -16.9,-25.9c-9.2,-15.6 -17.3,-31.9 -26.9,-47.3c-6.4,-10.3 -9.6,-21 -9.7,-32.9c-0.1,-9.9 -1.7,-7.5 7,-10.7c41.6,-15.3 84.7,-23.4 129,-23.7c31.3,-0.2 62.6,0.8 93.9,1.1C438.7,392.3 450.4,392.2 463.5,392.2zM443.6,400.7c-2.9,0 -4.9,0 -6.9,0c-18.1,-0.2 -36.3,0.1 -54.4,-0.7c-34.5,-1.6 -68.9,-1.6 -103.1,4c-23.9,3.9 -47.2,9.6 -69.9,17.9c-1.4,0.5 -3.6,1.9 -3.5,2.7c0.9,6.8 0.6,14.4 3.6,20.2c10.2,19.8 21.4,39.1 32.7,58.3c5.4,9.1 11.2,18.2 18,26.3c12.7,15.3 28.9,24 49.5,21.4c15.7,-2 31.5,-3.7 46.8,-7.3c12.8,-3 25.4,-7.8 37.4,-13.3c11.8,-5.3 19.2,-15 21.4,-28.3c1,-6.2 2.6,-12.4 4,-18.5C425.3,455.7 427.8,426.8 443.6,400.7z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M498.8,386.9c12.3,-3.6 23.4,-6.8 34.4,-10.2c30.9,-9.6 61.6,-20.1 92.8,-28.9c42.6,-12.1 86.3,-16 130.5,-13.1c3.5,0.2 5.3,1.2 5.9,5c0.9,6.2 2.5,12.4 3.8,18.6c0.3,1.3 0.5,2.7 0.2,3.9c-6.6,28.5 -13,57.1 -20,85.5c-2.9,11.7 -8.1,22.5 -15.4,32.2c-9.6,12.6 -22,20.4 -37.7,23.4c-25.2,4.8 -50.6,8.8 -76.3,6.7c-7.4,-0.6 -14.8,-2.2 -21.9,-4.3c-10.9,-3.3 -19.3,-10.3 -24.8,-20.5c-10.1,-18.7 -20.1,-37.5 -30.6,-56.1c-4.1,-7.2 -8.9,-14 -13.8,-20.8c-5.7,-7.8 -12.8,-13.9 -21.6,-18.2C502.9,389.3 501.4,388.4 498.8,386.9zM519.9,389.7c18.8,16.3 28.9,37.9 40.1,58.6c5.4,10.1 11.2,20 16.4,30.3c5.9,11.8 15.6,18.4 28.1,21c6.7,1.3 13.5,2.2 20.3,2.4c23.1,0.9 45.8,-2.9 68.4,-7.3c13.7,-2.7 24.4,-10.1 32.5,-21.5c7.9,-11.2 12.4,-23.9 15.5,-37.1c5,-21.2 9.3,-42.6 14.7,-63.7c2.3,-8.9 2.2,-17.2 -0.2,-25.9c-0.8,-2.8 -1.7,-3.8 -4.6,-3.8c-17.1,0.3 -34.3,-0.4 -51.4,0.8c-39.1,2.7 -76.7,12.4 -113.6,25.4C564.4,376.5 542.5,382.6 519.9,389.7z"/>
+</vector>
diff --git a/res/drawable/icon_sunrise.xml b/res/drawable/icon_sunrise.xml
new file mode 100644
index 000000000..3698a3fc3
--- /dev/null
+++ b/res/drawable/icon_sunrise.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+ android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M278.6,215.2h-16.8c0-44.5-35.2-80.7-78.5-80.7c-43.3,0-78.5,36.2-78.5,80.7H88.1c0-54,42.7-98,95.3-98
+ C235.9,117.2,278.6,161.1,278.6,215.2"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M230,54.1L224.1,51.9L210.1,91.5L215.9,93.7z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M216.6,95.1l-7.8-2.9l14.8-41.7l7.8,2.9L216.6,95.1z M211.4,90.9l3.9,1.5l13.3-37.7l-3.9-1.5L211.4,90.9z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M304.6,116L301.5,110.4L265.9,131.5L269,137.1z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M268.6,138.6l-4.2-7.4l37.4-22.2l4.2,7.4L268.6,138.6z M267.3,131.9l2.1,3.7l33.7-20l-2.1-3.7L267.3,131.9z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M130.6,55.9L136.5,53.7L150.5,93.4L144.7,95.6z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M144,97l-14.8-41.7l7.8-2.9L151.9,94L144,97z M132,56.5l13.3,37.7l3.9-1.5l-13.3-37.7L132,56.5z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M56,117.8L59.1,112.3L94.7,133.4L91.6,138.9z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M92,140.4l-37.4-22.2l4.2-7.4L96.1,133L92,140.4z M57.4,117.4l33.7,20l2.1-3.7l-33.7-20L57.4,117.4z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M312.4,314H51.7c-2.3,0-4.2-1.9-4.2-4.3c0-2.4,1.9-4.3,4.2-4.3h260.6c2.3,0,4.2,1.9,4.2,4.3
+ C316.6,312,314.7,314,312.4,314z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M234,211.6h-2.1c0-27.4-21.6-49.6-48.3-49.6c-26.6,0-48.3,22.3-48.3,49.6h-2.1c0-28.6,22.6-51.8,50.4-51.8
+ C211.4,159.9,234,183.1,234,211.6z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M312.4,219.4H51.7c-2.6,0-4.8-2.2-4.8-4.9c0-2.7,2.1-4.9,4.8-4.9h260.6c2.6,0,4.8,2.2,4.8,4.9
+ C317.1,217.2,315,219.4,312.4,219.4z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M334.7,228.4H23.1c-0.9,0-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6h311.6c0.9,0,1.6,0.7,1.6,1.6
+ C336.3,227.6,335.5,228.4,334.7,228.4z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M77.1,188l-42.9-4.5l0.9-8.5l42.9,4.5L77.1,188z M36.4,181.5l38.8,4.1l0.4-4.2l-38.8-4.1L36.4,181.5z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M111.3,112.4L82.6,79.2l6.2-5.7l28.7,33.2L111.3,112.4z M85.6,79.4l25.9,29.9l3.1-2.8L88.7,76.6L85.6,79.4z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M184.3,91.4l-8.3-0.1l0.3-44.4l8.3,0.1L184.3,91.4z M178.1,89.2l4.2,0l0.3-40.1l-4.2,0L178.1,89.2z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M284.8,173.9l-0.6-8.6l43-3.5l0.6,8.6L284.8,173.9z M286.4,167.3l0.3,4.3l38.8-3.1l-0.3-4.3L286.4,167.3z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M248.7,112l-6.1-5.9l29.5-32.4l6.1,5.9L248.7,112z M245.6,106.1l3,2.9l26.6-29.3l-3-2.9L245.6,106.1z"/>
+</vector>
diff --git a/res/drawable/icon_tea_time.xml b/res/drawable/icon_tea_time.xml
new file mode 100644
index 000000000..e1d9057bc
--- /dev/null
+++ b/res/drawable/icon_tea_time.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+ android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M92.4,213.4c-3.1-9.5-6.3-18.7-9.4-27.9c-0.1-0.4-0.8-0.9-1.3-0.9c-2.5-0.1-5.1-0.4-7.6-0.3
+ c-3.6,0.3-7.3,0.8-10.9,1.3c-1.4,0.1-1.6,1.1-1,2.3c0.6,1.3,1.4,2.5,2.1,3.5c5.4,6.6,11.8,11.9,18.9,16.5
+ C86.2,209.9,89.4,211.6,92.4,213.4z M189,39c0,0.3-0.1,0.5-0.1,0.8c-0.6,8.1-2.9,15.9-7.8,22.5c-3.1,4.3-6.9,8.1-10.4,12.1
+ c-2,2.4-4.3,4.6-6.1,7c-2.4,3.1-2.5,6.6-0.8,10.1c1,1.9,2.3,3.8,3.6,5.5c4.1,5.1,9.4,9,14.4,13.1c4,3.4,8,6.8,11.5,10.5
+ c4.1,4.3,6.5,9.5,6.1,15.8c0,0.1,0.1,0.1,0.3,0.3c3-3,5.5-6.1,5.1-10.8c-0.3-4.3-2.4-7.6-4.8-10.9c-2.1-2.8-4.4-5.5-6.5-8.1
+ c-3-3.9-5.9-7.9-7.8-12.5c-2.6-6.4-2.8-12.5,0.8-18.7c1.6-2.9,2.9-6,4-9.1C194.1,57.3,193.3,48,189,39z M77,159.9
+ c-2.5,0.1-4.8,0.3-7.1,0.5c-7,0.8-13.9,2.1-20.3,5.5c-9.5,5-14,13.8-12.3,24.3c1,6.1,3.9,11.4,7.5,16.4
+ c7.9,10.9,18.2,19.2,29.7,25.8c8.8,5,18,8.9,28.2,10.5c2.3,0.4,4.5,0.5,6.9,0.6c-3.4-5.6-6.6-10.9-9.9-16.3
+ c-0.3-0.4-0.9-0.8-1.4-0.9c-14.8-5.1-27.3-13.6-38.2-24.8c-3.1-3.3-6-6.6-7.4-11.1c-1.9-5.9,0.5-11.4,6-13.6
+ c1.1-0.5,2.3-1,3.5-1.1c5.3-0.5,10.4-0.9,15.5-1.3c0.8-0.1,1.5,0,2.4,0C79,169.4,78,164.7,77,159.9z M287.8,275.4
+ c-0.1,1-0.1,1.6-0.3,2.4c-0.8,4.1-3.5,6.9-6.6,9.3c-4.3,3.3-9.1,5.4-14,7.1c-16.9,6.1-34.5,8.5-52.4,9.6
+ c-13.1,0.9-26.4,0.9-39.6,0c-14.5-1-28.9-2.8-43.1-6.5c-7.8-2-15.3-4.6-22.2-8.9c-3-1.9-5.8-4.1-7.5-7.3c-0.8-1.4-1.1-3-1.8-4.5
+ c-5.3,4.9-5.9,10.9-1.1,16.1c2.4,2.6,5.3,4.9,8.1,6.9c6.6,4.4,14,7.1,21.5,9.4c17.8,5.5,36.1,7.8,54.6,8.5
+ c19.7,0.8,39.3-0.4,58.7-4c11.4-2.3,22.5-5.1,33-10.3c5.4-2.5,10.4-5.5,14.4-10c1.9-2.3,3.5-4.6,3.6-7.8
+ C293.3,281.3,290.8,278.4,287.8,275.4z M196.4,302c12.6,0,25.3-0.9,37.9-2.6c10.9-1.6,21.7-3.8,32-7.6c5.4-2,10.8-4.3,14.9-8.4
+ c1.5-1.5,2.8-3.5,3.6-5.5c1-2.6,0-4.9-2.4-6.4c-5.8-3.8-12-6.4-18.5-8.6c-1.4-0.5-2.3-0.3-3.4,0.6c-9.9,8.4-21.2,14.5-33.5,18.4
+ c-13.5,4.1-27.4,5-41.4,4.3c-13.6-0.9-26.7-4.3-38.9-10.4c-6.6-3.4-12.8-7.5-18.5-12.3c-0.5-0.4-1.4-0.9-1.9-0.8
+ c-7.8,2.5-15.3,5.6-21.8,10.5c-0.6,0.5-1.1,1.5-1.3,2.3c-0.4,2.3,0.5,4.3,2,6.1c2.8,3.5,6.5,5.8,10.4,7.6
+ c9.8,4.8,20.3,7.3,30.8,9.1C163,301,179.6,302.1,196.4,302z M193.8,134c-0.6-1.8-1.1-3.3-1.8-4.6c-0.3-0.5-1.1-1-1.8-1
+ c-3.9,0-7.8,0.1-11.6,0.3c-14.5,0.5-28.9,1.6-43.2,3.8c-11.3,1.8-22.4,3.9-33.2,7.6c-4.6,1.6-9.3,3.6-13.3,6.5
+ c-2.8,2-3.6,4.6-3,7.9c2.8,13.8,5.9,27.4,10.5,40.8c5.8,16.4,13.1,32,24,45.7c11.8,14.9,26.3,25.7,44.4,31.3
+ c12.6,3.9,25.7,4.6,38.7,3.8c13.5-1,26.4-4.6,38.2-11.5c14.4-8.4,25.4-20.3,34.2-34.3c14.8-23.5,21.9-49.8,27-76.9
+ c0.5-2.5-0.3-4.6-2.4-6.1c-1.6-1.1-3.3-2.3-4.9-3.3c-5.4-2.9-11.1-4.9-17-6.4c-20.7-5.5-41.8-7.6-63.2-8.8c-1.5-0.1-3,0-4.4,0
+ c-0.5,1.8-1,3.4-1.5,5.3c0.6,0.1,1.3,0.1,1.9,0.3c14.6,0.5,29.2,1.9,43.7,4.6c8.6,1.6,17.1,3.6,25.2,7.4c2.8,1.4,5.5,2.9,7.5,5.3
+ c2.1,2.6,2.1,5.5-0.1,8c-1.1,1.3-2.4,2.5-3.8,3.1c-3.9,1.9-7.9,3.9-12,5.3c-15.5,5-31.5,6.8-47.7,8c-15.3,1.1-30.7,1.4-45.9,0.8
+ c-16-0.6-32-2-47.8-5.3c-8-1.6-15.9-3.5-23.2-7.4c-2.3-1.1-4.5-2.8-6.3-4.6c-2.5-2.6-2.4-5.8,0.3-8.3c1.8-1.6,3.8-3,5.8-4.3
+ c5.1-2.8,10.8-4.4,16.4-5.9c20.2-4.9,40.7-6.5,61.2-7C187.8,133.9,190.6,134,193.8,134z M118.9,254c-0.9-0.4-1.8-1-2.5-1
+ c-8.6,1-17-0.1-25.2-2.6c-22.5-7.3-41.3-19.9-55.2-39.3c-4.5-6.3-7.6-13.3-8.5-21.2c-1.4-13,3.4-23.3,14.1-30.7
+ c6.3-4.4,13.4-6.5,20.8-7.8c4.1-0.6,8.4-0.9,12.5-1.4c0.5-0.1,1.3-0.5,1.3-1c0.9-5,4-8.5,7.9-11.3c6.4-4.5,13.6-7.1,21.2-9.3
+ c13-3.8,26.4-6.3,39.9-7.5c11.9-1.1,23.8-1.8,35.7-2.6c0.4,0,0.8-0.1,1.5-0.1c-0.9-0.8-1.6-1.3-2.3-1.9c-5-4.3-10-8.4-14.8-12.8
+ c-3.4-3.1-5.9-6.8-7.5-11c-1.9-5-1.4-9.8,1.6-14.1c1.8-2.5,3.9-4.9,5.9-7.1c3.4-3.9,7.1-7.5,10.3-11.6c6-8,7.9-17.3,7.5-27
+ c-0.3-4.1-1.1-8.3-1.4-12.5c-0.1-1.8,0.3-3.6,0.4-5.5c2.1,0.3,4,0.4,5.8,0.6c0.4,2.3,0.5,4.5,1.3,6.5c1.5,4.1,3.1,8,4.9,12
+ c3,6.9,5.3,13.9,5.3,21.4c0,8.6-2.6,16.5-6.8,23.9c-2.3,4-2.4,8-0.8,12.1c1.9,4.9,4.9,8.9,8,12.9c3.5,4.4,7.3,8.5,9.6,13.8
+ c0.1,0.4,0.9,0.6,1.3,0.6c5.5,0.4,10.9,0.5,16.4,1c20.3,1.5,40.3,4,59.8,10c5.6,1.8,11.1,3.9,16.3,7c1.8,1.1,3.5,2.5,5.1,3.9
+ c4.5,4,5.8,9.1,4.8,14.8c-2.9,15.4-6.5,30.5-11.8,45.3c-6.3,17.4-14.4,33.7-26,48.1c-1.5,1.9-3.3,3.8-4.9,5.8
+ c4,1.8,7.8,3.4,11.5,5.3c5.4,2.6,10.3,6,14.4,10.3c8.9,9.1,9.1,21,0.6,30.4c-5.1,5.8-11.6,9.5-18.5,12.6
+ c-11.9,5.5-24.4,8.8-37.3,11c-18.2,3.3-36.4,4.4-54.8,3.8c-22-0.6-43.7-3.4-64.7-10.5c-9.3-3.1-18.2-7.1-25.7-13.6
+ c-3.8-3.3-7-7-8.5-11.9c-2.6-8-0.3-15,5.1-21.2c5.1-5.8,11.6-9.6,18.7-12.8c2.5-1.1,5.1-2.3,7.8-3.4
+ C118.8,254.3,118.8,254.2,118.9,254z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M92.4,213.4c-3.1-9.5-6.3-18.7-9.4-27.9c-0.1-0.4-0.8-0.9-1.3-0.9c-2.5-0.1-5.1-0.4-7.6-0.3
+ c-3.6,0.3-7.3,0.8-10.9,1.3c-1.4,0.1-1.6,1.1-1,2.3c0.6,1.3,1.4,2.5,2.1,3.5c5.4,6.6,11.8,11.9,18.9,16.5
+ C86.2,209.9,89.4,211.6,92.4,213.4z M189,39c0,0.3-0.1,0.5-0.1,0.8c-0.6,8.1-2.9,15.9-7.8,22.5c-3.1,4.3-6.9,8.1-10.4,12.1
+ c-2,2.4-4.3,4.6-6.1,7c-2.4,3.1-2.5,6.6-0.8,10.1c1,1.9,2.3,3.8,3.6,5.5c4.1,5.1,9.4,9,14.4,13.1c4,3.4,8,6.8,11.5,10.5
+ c4.1,4.3,6.5,9.5,6.1,15.8c0,0.1,0.1,0.1,0.3,0.3c3-3,5.5-6.1,5.1-10.8c-0.3-4.3-2.4-7.6-4.8-10.9c-2.1-2.8-4.4-5.5-6.5-8.1
+ c-3-3.9-5.9-7.9-7.8-12.5c-2.6-6.4-2.8-12.5,0.8-18.7c1.6-2.9,2.9-6,4-9.1C194.1,57.3,193.3,48,189,39z M77,159.9
+ c-2.5,0.1-4.8,0.3-7.1,0.5c-7,0.8-13.9,2.1-20.3,5.5c-9.5,5-14,13.8-12.3,24.3c1,6.1,3.9,11.4,7.5,16.4
+ c7.9,10.9,18.2,19.2,29.7,25.8c8.8,5,18,8.9,28.2,10.5c2.3,0.4,4.5,0.5,6.9,0.6c-3.4-5.6-6.6-10.9-9.9-16.3
+ c-0.3-0.4-0.9-0.8-1.4-0.9c-14.8-5.1-27.3-13.6-38.2-24.8c-3.1-3.3-6-6.6-7.4-11.1c-1.9-5.9,0.5-11.4,6-13.6
+ c1.1-0.5,2.3-1,3.5-1.1c5.3-0.5,10.4-0.9,15.5-1.3c0.8-0.1,1.5,0,2.4,0C79,169.4,78,164.7,77,159.9z M287.8,275.4
+ c-0.1,1-0.1,1.6-0.3,2.4c-0.8,4.1-3.5,6.9-6.6,9.3c-4.3,3.3-9.1,5.4-14,7.1c-16.9,6.1-34.5,8.5-52.4,9.6
+ c-13.1,0.9-26.4,0.9-39.6,0c-14.5-1-28.9-2.8-43.1-6.5c-7.8-2-15.3-4.6-22.2-8.9c-3-1.9-5.8-4.1-7.5-7.3c-0.8-1.4-1.1-3-1.8-4.5
+ c-5.3,4.9-5.9,10.9-1.1,16.1c2.4,2.6,5.3,4.9,8.1,6.9c6.6,4.4,14,7.1,21.5,9.4c17.8,5.5,36.1,7.8,54.6,8.5
+ c19.7,0.8,39.3-0.4,58.7-4c11.4-2.3,22.5-5.1,33-10.3c5.4-2.5,10.4-5.5,14.4-10c1.9-2.3,3.5-4.6,3.6-7.8
+ C293.3,281.3,290.8,278.4,287.8,275.4z M196.4,302c12.6,0,25.3-0.9,37.9-2.6c10.9-1.6,21.7-3.8,32-7.6c5.4-2,10.8-4.3,14.9-8.4
+ c1.5-1.5,2.8-3.5,3.6-5.5c1-2.6,0-4.9-2.4-6.4c-5.8-3.8-12-6.4-18.5-8.6c-1.4-0.5-2.3-0.3-3.4,0.6c-9.9,8.4-21.2,14.5-33.5,18.4
+ c-13.5,4.1-27.4,5-41.4,4.3c-13.6-0.9-26.7-4.3-38.9-10.4c-6.6-3.4-12.8-7.5-18.5-12.3c-0.5-0.4-1.4-0.9-1.9-0.8
+ c-7.8,2.5-15.3,5.6-21.8,10.5c-0.6,0.5-1.1,1.5-1.3,2.3c-0.4,2.3,0.5,4.3,2,6.1c2.8,3.5,6.5,5.8,10.4,7.6
+ c9.8,4.8,20.3,7.3,30.8,9.1C163,301,179.6,302.1,196.4,302z M193.8,134c-0.6-1.8-1.1-3.3-1.8-4.6c-0.3-0.5-1.1-1-1.8-1
+ c-3.9,0-7.8,0.1-11.6,0.3c-14.5,0.5-28.9,1.6-43.2,3.8c-11.3,1.8-22.4,3.9-33.2,7.6c-4.6,1.6-9.3,3.6-13.3,6.5
+ c-2.8,2-3.6,4.6-3,7.9c2.8,13.8,5.9,27.4,10.5,40.8c5.8,16.4,13.1,32,24,45.7c11.8,14.9,26.3,25.7,44.4,31.3
+ c12.6,3.9,25.7,4.6,38.7,3.8c13.5-1,26.4-4.6,38.2-11.5c14.4-8.4,25.4-20.3,34.2-34.3c14.8-23.5,21.9-49.8,27-76.9
+ c0.5-2.5-0.3-4.6-2.4-6.1c-1.6-1.1-3.3-2.3-4.9-3.3c-5.4-2.9-11.1-4.9-17-6.4c-20.7-5.5-41.8-7.6-63.2-8.8c-1.5-0.1-3,0-4.4,0
+ c-0.5,1.8-1,3.4-1.5,5.3c0.6,0.1,1.3,0.1,1.9,0.3c14.6,0.5,29.2,1.9,43.7,4.6c8.6,1.6,17.1,3.6,25.2,7.4c2.8,1.4,5.5,2.9,7.5,5.3
+ c2.1,2.6,2.1,5.5-0.1,8c-1.1,1.3-2.4,2.5-3.8,3.1c-3.9,1.9-7.9,3.9-12,5.3c-15.5,5-31.5,6.8-47.7,8c-15.3,1.1-30.7,1.4-45.9,0.8
+ c-16-0.6-32-2-47.8-5.3c-8-1.6-15.9-3.5-23.2-7.4c-2.3-1.1-4.5-2.8-6.3-4.6c-2.5-2.6-2.4-5.8,0.3-8.3c1.8-1.6,3.8-3,5.8-4.3
+ c5.1-2.8,10.8-4.4,16.4-5.9c20.2-4.9,40.7-6.5,61.2-7C187.8,133.9,190.6,134,193.8,134z M118.9,254c-0.9-0.4-1.8-1-2.5-1
+ c-8.6,1-17-0.1-25.2-2.6c-22.5-7.3-41.3-19.9-55.2-39.3c-4.5-6.3-7.6-13.3-8.5-21.2c-1.4-13,3.4-23.3,14.1-30.7
+ c6.3-4.4,13.4-6.5,20.8-7.8c4.1-0.6,8.4-0.9,12.5-1.4c0.5-0.1,1.3-0.5,1.3-1c0.9-5,4-8.5,7.9-11.3c6.4-4.5,13.6-7.1,21.2-9.3
+ c13-3.8,26.4-6.3,39.9-7.5c11.9-1.1,23.8-1.8,35.7-2.6c0.4,0,0.8-0.1,1.5-0.1c-0.9-0.8-1.6-1.3-2.3-1.9c-5-4.3-10-8.4-14.8-12.8
+ c-3.4-3.1-5.9-6.8-7.5-11c-1.9-5-1.4-9.8,1.6-14.1c1.8-2.5,3.9-4.9,5.9-7.1c3.4-3.9,7.1-7.5,10.3-11.6c6-8,7.9-17.3,7.5-27
+ c-0.3-4.1-1.1-8.3-1.4-12.5c-0.1-1.8,0.3-3.6,0.4-5.5c2.1,0.3,4,0.4,5.8,0.6c0.4,2.3,0.5,4.5,1.3,6.5c1.5,4.1,3.1,8,4.9,12
+ c3,6.9,5.3,13.9,5.3,21.4c0,8.6-2.6,16.5-6.8,23.9c-2.3,4-2.4,8-0.8,12.1c1.9,4.9,4.9,8.9,8,12.9c3.5,4.4,7.3,8.5,9.6,13.8
+ c0.1,0.4,0.9,0.6,1.3,0.6c5.5,0.4,10.9,0.5,16.4,1c20.3,1.5,40.3,4,59.8,10c5.6,1.8,11.1,3.9,16.3,7c1.8,1.1,3.5,2.5,5.1,3.9
+ c4.5,4,5.8,9.1,4.8,14.8c-2.9,15.4-6.5,30.5-11.8,45.3c-6.3,17.4-14.4,33.7-26,48.1c-1.5,1.9-3.3,3.8-4.9,5.8
+ c4,1.8,7.8,3.4,11.5,5.3c5.4,2.6,10.3,6,14.4,10.3c8.9,9.1,9.1,21,0.6,30.4c-5.1,5.8-11.6,9.5-18.5,12.6
+ c-11.9,5.5-24.4,8.8-37.3,11c-18.2,3.3-36.4,4.4-54.8,3.8c-22-0.6-43.7-3.4-64.7-10.5c-9.3-3.1-18.2-7.1-25.7-13.6
+ c-3.8-3.3-7-7-8.5-11.9c-2.6-8-0.3-15,5.1-21.2c5.1-5.8,11.6-9.6,18.7-12.8c2.5-1.1,5.1-2.3,7.8-3.4
+ C118.8,254.3,118.8,254.2,118.9,254z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M208.3,14.8c-0.4,0.4-0.5,0.5-0.5,0.6c-4.8,11-4.8,21.9,0.6,32.7c1.8,3.4,2,7,1.1,10.6
+ c-1.3,5.1-4.1,9.4-7,13.6c-1.5,2.3-3.1,4.6-4.4,7.1c-1.4,2.5-2,5.1-1.6,8c0.5,3.9,3,6.6,5.9,9.6c-2.5-8.3,1.5-13.9,6.5-19
+ c1.9-2,4-3.8,6-5.8c3.4-3.3,6.8-6.5,9-10.8c2.4-4.4,2.1-8.4-0.8-12.4c-1.1-1.4-2.1-2.8-3.3-4.1c-3.9-4.5-7.4-9.4-9.3-15.1
+ C208.8,25.3,208.2,20.3,208.3,14.8z M209,0.8h2.1c0.9,2.6,0.1,5.3-0.1,7.9c-1.1,10-0.4,19.5,5.4,28.2c2,3.1,4.5,5.9,6.8,8.8
+ c1.9,2.4,3.8,4.9,4.4,7.9c0.8,3.5-0.1,6.6-1.8,9.6c-2.8,5-7,8.9-11,12.9c-2.9,2.8-5.8,5.6-8.1,8.8c-3.6,4.8-3.8,9.9-0.4,14.9
+ c1.4,2,2.6,4.1,4,6.3c-0.6,0.5-1.3,0.9-2,1.4c-4-4.4-8.1-8.5-11.9-13.1c-3.1-4-3.6-8.8-1.6-13.4c1.5-3.4,3.6-6.5,5.4-9.8
+ c1.9-3.4,4.1-6.8,5.8-10.4c1.9-3.9,1.8-7.9-0.3-11.9c-5.3-10.9-5.3-21.9-0.9-33c1.5-4,2.6-8.1,3.9-12.3C209,2.7,209,1.8,209,0.8z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M208.3,14.8c-0.4,0.4-0.5,0.5-0.5,0.6c-4.8,11-4.8,21.9,0.6,32.7c1.8,3.4,2,7,1.1,10.6
+ c-1.3,5.1-4.1,9.4-7,13.6c-1.5,2.3-3.1,4.6-4.4,7.1c-1.4,2.5-2,5.1-1.6,8c0.5,3.9,3,6.6,5.9,9.6c-2.5-8.3,1.5-13.9,6.5-19
+ c1.9-2,4-3.8,6-5.8c3.4-3.3,6.8-6.5,9-10.8c2.4-4.4,2.1-8.4-0.8-12.4c-1.1-1.4-2.1-2.8-3.3-4.1c-3.9-4.5-7.4-9.4-9.3-15.1
+ C208.8,25.3,208.2,20.3,208.3,14.8z M209,0.8h2.1c0.9,2.6,0.1,5.3-0.1,7.9c-1.1,10-0.4,19.5,5.4,28.2c2,3.1,4.5,5.9,6.8,8.8
+ c1.9,2.4,3.8,4.9,4.4,7.9c0.8,3.5-0.1,6.6-1.8,9.6c-2.8,5-7,8.9-11,12.9c-2.9,2.8-5.8,5.6-8.1,8.8c-3.6,4.8-3.8,9.9-0.4,14.9
+ c1.4,2,2.6,4.1,4,6.3c-0.6,0.5-1.3,0.9-2,1.4c-4-4.4-8.1-8.5-11.9-13.1c-3.1-4-3.6-8.8-1.6-13.4c1.5-3.4,3.6-6.5,5.4-9.8
+ c1.9-3.4,4.1-6.8,5.8-10.4c1.9-3.9,1.8-7.9-0.3-11.9c-5.3-10.9-5.3-21.9-0.9-33c1.5-4,2.6-8.1,3.9-12.3
+ C209,2.7,209,1.8,209,0.8z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M208.3,14.8c-0.4,0.4-0.5,0.5-0.5,0.6c-4.8,11-4.8,21.9,0.6,32.7c1.8,3.4,2,7,1.1,10.6
+ c-1.3,5.1-4.1,9.4-7,13.6c-1.5,2.3-3.1,4.6-4.4,7.1c-1.4,2.5-2,5.1-1.6,8c0.5,3.9,3,6.6,5.9,9.6c-2.5-8.3,1.5-13.9,6.5-19
+ c1.9-2,4-3.8,6-5.8c3.4-3.3,6.8-6.5,9-10.8c2.4-4.4,2.1-8.4-0.8-12.4c-1.1-1.4-2.1-2.8-3.3-4.1c-3.9-4.5-7.4-9.4-9.3-15.1
+ C208.8,25.3,208.2,20.3,208.3,14.8z M209,0.8h2.1c0.9,2.6,0.1,5.3-0.1,7.9c-1.1,10-0.4,19.5,5.4,28.2c2,3.1,4.5,5.9,6.8,8.8
+ c1.9,2.4,3.8,4.9,4.4,7.9c0.8,3.5-0.1,6.6-1.8,9.6c-2.8,5-7,8.9-11,12.9c-2.9,2.8-5.8,5.6-8.1,8.8c-3.6,4.8-3.8,9.9-0.4,14.9
+ c1.4,2,2.6,4.1,4,6.3c-0.6,0.5-1.3,0.9-2,1.4c-4-4.4-8.1-8.5-11.9-13.1c-3.1-4-3.6-8.8-1.6-13.4c1.5-3.4,3.6-6.5,5.4-9.8
+ c1.9-3.4,4.1-6.8,5.8-10.4c1.9-3.9,1.8-7.9-0.3-11.9c-5.3-10.9-5.3-21.9-0.9-33c1.5-4,2.6-8.1,3.9-12.3
+ C209,2.7,209,1.8,209,0.8z"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M279.8,179.6c-0.9,0.4-1.4,0.5-1.9,0.8c-5.5,1.6-11.1,3.4-16.6,4.9
+ c-1.4,0.4-1.8,0.9-1.9,2.3c-0.9,12.4-3.1,24.4-7,36.1c-3.6,11.3-8.9,21.7-14.4,32c-0.3,0.5-0.5,1-0.9,1.8c0.9-0.5,1.5-0.8,2-1
+ c0.4-0.3,0.6-0.5,1-0.8c10.9-9.4,19-20.8,25.2-33.7C271.5,208.3,276,194.3,279.8,179.6z M231.9,262c1.3-2.5,2.3-5.1,3.6-7.6
+ c5.5-10.4,10.8-20.8,14.4-32c3.9-12.1,6.1-24.7,7-37.4c0.1-1.1,0.4-1.5,1.5-1.8c7.4-2.1,14.6-4.4,21.9-6.6
+ c0.6-0.1,1.5-0.3,1.8,0c0.4,0.4,0.5,1.3,0.3,1.8c-3.8,15.4-8.5,30.4-15.3,44.8c-6.4,13.1-14.5,25-25.9,34.3
+ c-2.6,2.1-6,3.3-9,4.9C232.2,262.3,232.1,262.2,231.9,262z"/>
+</vector>
diff --git a/res/drawable/icon_timestamp.xml b/res/drawable/icon_timestamp.xml
new file mode 100644
index 000000000..72656c687
--- /dev/null
+++ b/res/drawable/icon_timestamp.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+ android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#00000000"
+ android:pathData="M180,183m-143.9,0a143.9,143.9 0,1 1,287.8 0a143.9,143.9 0,1 1,-287.8 0"
+ android:strokeColor="?attr/fillColorSelector" android:strokeWidth="19.0452"/>
+ <path android:fillColor="?attr/fillColorSelector" android:pathData="M180,65.2c65,0,117.8,52.9,117.8,117.8S245,300.8,180,300.8S62.2,248,62.2,183S115,65.2,180,65.2 M180,62.4
+ c-66.5,0-120.6,54.1-120.6,120.6S113.5,303.6,180,303.6S300.6,249.5,300.6,183S246.5,62.4,180,62.4"/>
+ <path android:fillColor="#00000000"
+ android:pathData="M71.1,137.7L288.4,137.7"
+ android:strokeColor="?attr/fillColorSelector" android:strokeWidth="4.4394"/>
+ <path android:fillColor="#00000000"
+ android:pathData="M72.1,232.2L289.4,232.2"
+ android:strokeColor="?attr/fillColorSelector" android:strokeWidth="4.4394"/>
+</vector>
diff --git a/res/drawable/icon_tools.xml b/res/drawable/icon_tools.xml
new file mode 100644
index 000000000..0a6c98a27
--- /dev/null
+++ b/res/drawable/icon_tools.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+
+<vector android:height="24dp" android:viewportHeight="66.0"
+ android:viewportWidth="69.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#00000000"
+ android:pathData="M55.01,4.19C55.07,4.21 54.95,4.15 55.01,4.19L55.01,4.19Z"
+ android:strokeColor="#020302" android:strokeWidth="4.8"/>
+ <path android:fillColor="#00000000"
+ android:pathData="M66.1,22.2C65.62,21.39 64.51,21.16 63.69,21.64L54.02,27.3C53.02,27.89 51.55,27.67 50.77,26.81C50.77,26.81 48.49,24.34 46.84,21.57C45.26,18.92 44.19,15.99 44.19,15.99C43.8,14.91 44.3,13.53 45.3,12.95L55.05,7.26C55.88,6.78 56.23,5.68 55.74,4.87C55.58,4.6 55.26,4.33 55.01,4.19C50.08,2.32 44.38,2.59 39.49,5.45C32.62,9.47 29.46,17.32 31.12,24.63L31.06,24.68C31.6,26.88 30.96,29.32 29.21,30.99L5.16,49.01C2.36,51.68 2.27,57.29 4.97,60.07C7.66,62.85 12.12,64.13 14.93,61.46L39.72,40.34C40.86,39.26 42.61,38.37 44.37,37.99C48.75,39.04 53.54,38.48 57.73,36.03C62.52,33.23 65.5,28.51 66.31,23.46C66.39,23.06 66.33,22.58 66.1,22.2L66.1,22.2Z"
+ android:strokeColor="#020302" android:strokeWidth="4.8"/>
+ <path android:fillColor="#020302"
+ android:pathData="M14.19,54.12C14.19,55.51 13.05,56.63 11.65,56.63C10.25,56.63 9.12,55.51 9.12,54.12C9.12,52.74 10.25,51.61 11.65,51.61C13.05,51.61 14.19,52.74 14.19,54.12"
+ android:strokeColor="#00000000" android:strokeWidth="1"/>
+</vector>
diff --git a/res/drawable/icon_yum.xml b/res/drawable/icon_yum.xml
new file mode 100644
index 000000000..9a7dfa656
--- /dev/null
+++ b/res/drawable/icon_yum.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<vector android:height="24dp" android:viewportHeight="831.0"
+ android:viewportWidth="1053.0" android:width="30dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#ffffff" android:pathData="M354.1,730.5c-4.2,14.1 -8.8,27.5 -12,41.2c-2.2,9.7 -6.6,14.8 -16.7,16.8c-13.7,2.7 -26.8,8.8 -40.5,10.5c-38.8,4.8 -75.8,-1.7 -108.6,-24.2c-20.2,-13.8 -32.7,-33.3 -35.4,-57.8c-2.6,-23.5 -4.7,-47.1 -5.6,-70.7c-0.8,-18.9 1.6,-37.8 11,-54.7c4.7,-8.5 11.4,-15.9 17,-23.8c1.4,-2 3,-4.1 3.4,-6.3c4.4,-22.9 8.7,-45.8 12.8,-68.7c0.3,-1.6 -0.2,-3.7 -1.1,-5c-23.2,-31.9 -46.6,-63.8 -69.9,-95.6c-0.9,-1.3 -2.3,-2.5 -3.8,-3c-20,-6.8 -34.7,-20 -46.1,-37.3c-13,-19.7 -23,-40.9 -30.4,-63.3c-11.7,-35.4 -3.5,-67 19,-95.6c20.6,-26.3 47.7,-39.5 81.2,-37.9c27.6,1.3 50,14 68.7,33.6c8.9,9.4 17.3,19.4 25.8,29.2c1.1,1.2 2.1,2.5 4.2,5c4.6,-9.6 9.6,-18.1 12.8,-27.2c8.3,-23.9 16.8,-47.7 30.7,-69.1c22.4,-34.4 54.4,-49.2 94.8,-46.7c7,0.4 13.1,-0.5 19.5,-3.6C441.9,48.7 502,36.2 565,39.3c80.3,4 152,31.2 214.9,81.3c4.3,3.4 7.6,4.4 13.2,2.6c49.4,-16.7 108.7,1.3 138.3,41.6c12.6,17.2 19.3,36.6 18.8,57.9c-0.7,30.6 -2.3,61.2 -3.8,91.8c-0.6,12.8 -1.9,25.6 -3.2,38.3c-0.4,3.7 1.6,4 4.2,4.6c26.3,6.9 46.3,22.2 59.7,45.8c10.6,18.7 14.1,39.1 12.5,60.2c-2.7,36.8 -15.8,69.7 -40,97.6c-29.2,33.7 -66.3,50.4 -111.1,48.9c-4,-0.1 -6.2,1.1 -8.4,4.4c-57.1,85.8 -135.8,141 -236.8,162.1c-93.2,19.5 -181.7,4.6 -264.4,-43.2C357.6,732.4 356.1,731.6 354.1,730.5zM343.3,704c1.8,1.2 3.2,2.1 4.5,3c82.1,54.4 171.9,73.5 268.3,54.4c101.6,-20.1 179.7,-75.9 235.1,-163.3c2.6,-4.1 4.9,-5.8 10.1,-5.1c24.2,3.3 47.1,-1.4 68.6,-12.7c48.4,-25.4 80,-85.3 72.8,-139.6c-4.4,-32.8 -22.9,-55.5 -54.5,-66.4c-7,-2.4 -14.5,-3.1 -22.3,-4.7c1.5,-18.8 3,-37.8 4.6,-56.9c2.5,-31 5.2,-62 3.7,-93.3c-0.9,-17.7 -6.6,-33.6 -17.5,-47.5c-28.4,-36.4 -87,-49.8 -128.8,-29.5c-2.5,1.2 -4.3,2.1 -7.1,-0.2c-62.4,-53.6 -134.7,-82.9 -216.9,-87c-58.8,-2.9 -115,8.3 -168.1,33.7c-10.5,5 -20.5,8 -32.6,7c-36.3,-2.8 -64.2,12.5 -82,44.2c-7.8,13.9 -14.6,28.5 -19.8,43.5c-6.1,17.7 -12.5,35 -23.3,50.4c-2.7,3.9 -4.7,8.4 -7,12.6c-0.6,1.1 -1.3,2.1 -2.2,3.6c-1.5,-1.8 -2.6,-3.2 -3.8,-4.5c-14.3,-16.5 -28,-33.6 -43.1,-49.2c-25.2,-25.9 -60,-32.7 -90.7,-18.7c-21.8,9.9 -35.5,27.4 -45.4,48.5c-6.6,14.2 -8.6,29 -5.2,44.3c6.5,29 19.2,55.2 36.7,79.1c9.1,12.5 21.4,20.8 36.3,25.2c2,0.6 4,2.3 5.3,4.1c25.4,34.5 50.7,69 75.9,103.6c1.4,1.9 2,5 1.6,7.2c-4.7,26.2 -9.5,52.4 -14.6,78.5c-0.6,3.1 -2.6,6.4 -4.9,8.6c-9,8.6 -15.7,18.5 -19.9,30.1c-5.2,14.5 -6.4,29.7 -5.6,44.8c1,18.6 3.2,37.1 4.5,55.7c1.7,24.6 13,43.4 33.7,56.4c25.4,16.1 53.7,20.8 83.2,20c17.6,-0.5 33.6,-7.8 50.2,-12.4c1.3,-0.4 2.6,-2.4 3.1,-3.9c3.1,-10 6.3,-20 9,-30.1C338,726.9 340.5,715.7 343.3,704z"/>
+ <path android:fillColor="#ffffff" android:pathData="M776.1,200.2c0.6,-1.6 1.3,-2.9 1.7,-4.3c5.5,-18.6 18.5,-28.9 37,-32.2c24.5,-4.4 47.5,0 67.8,14.7c16.8,12.1 23.8,29.4 22.9,49.5c-1.3,32.6 -3.3,65.2 -5.2,97.7c-1.3,23.3 -2.9,46.5 -4.3,69.8c-0.1,1.6 0,3.3 0,5.6c8.2,-0.5 15.9,-0.8 23.7,-1.4c26.4,-2.2 49.1,14.9 54,40.9c8,42.9 -20.6,107.6 -76.2,121.8c-24.5,6.2 -47.6,3.3 -68.4,-11.8c-0.5,-0.4 -1.1,-0.8 -1.7,-1.1c-0.2,-0.1 -0.6,-0.1 -1.7,-0.1c0.2,2.8 0.6,5.6 0.4,8.3c-0.2,2.6 -0.4,5.6 -1.6,7.8c-5.5,9.8 -12.9,18 -21.9,25c-4.8,3.8 -7.9,9.8 -11.9,14.7c-52.5,64.7 -119.9,104.2 -202.6,114.5c-99.1,12.3 -185.5,-16.9 -258,-85.9c-0.8,-0.8 -1.7,-1.6 -2.5,-2.4c-0.2,-0.2 -0.6,-0.2 -1.3,-0.3c-2.4,14.4 -4.4,28.9 -7.3,43.1c-4.9,23.6 -10.4,47.1 -15.8,70.5c-0.4,1.8 -2.4,4 -4.1,4.7c-28.8,11.4 -57,6.9 -84.6,-4c-17.5,-6.9 -28.5,-19.5 -29.7,-39.4c-1.2,-20.4 -3.5,-40.8 -4.3,-61.3c-0.3,-8.7 1.2,-17.6 3.4,-26.1c2.8,-11 9.9,-19.4 19.8,-25.4c1.7,-1 3.3,-3.3 3.7,-5.2c6.7,-34.8 13.3,-69.6 19.6,-104.5c0.4,-2.3 -0.3,-5.4 -1.7,-7.3c-30,-41.2 -60.2,-82.3 -90.3,-123.4c-1.9,-2.6 -4,-3.9 -7.3,-4.2c-10.6,-1 -19.5,-5.7 -26,-14.2c-15.5,-20.2 -26.1,-42.9 -32.4,-67.5c-4.4,-17.3 2.7,-31.7 12.7,-45c19.9,-26.3 52.7,-30.1 76.7,-7.3c15.4,14.6 28.9,31.3 42.5,47.7c15.5,18.7 30.3,38.1 45.3,57.2c0.8,1 1.7,2 2.7,3.2c4,-10.5 8.3,-20.5 11.5,-30.8c4.3,-13.8 7.8,-27.8 11.4,-41.8c7.5,-28.8 14.5,-57.8 27.9,-84.7c3.3,-6.5 7.2,-12.8 11.5,-18.6c12.4,-16.9 29.7,-23.2 50.2,-22.2c13.8,0.7 27,3.4 39.1,10.6c1.4,0.9 4.4,0.1 6.3,-0.8c27.8,-14 57.1,-24.1 87.9,-28.9c93.3,-14.5 177.1,7.4 250.6,66.9C756.1,181 765.7,190.7 776.1,200.2zM818.8,325.4c0.1,0.9 0.2,1.7 0.1,2.5c-0.8,17.6 -1.8,35.3 -2.4,52.9c-0.8,25 -2,50 2.4,74.8c3.2,17.9 7.6,35.5 17.3,51.2c13.6,22 35.4,29.2 59.1,19.1c20.4,-8.6 32.2,-25.1 39.5,-45.3c3.9,-10.7 6.3,-21.8 4.1,-33.3c-1.5,-7.9 -7,-12.4 -14.4,-12.2c-2.2,8.2 -3.7,16.6 -6.9,24.4c-3.1,7.5 -7.1,15.2 -12.5,21.3c-8.8,9.8 -23.5,8.1 -31.1,-2.7c-2.6,-3.8 -4.6,-8.1 -6.1,-12.5c-5.1,-14.8 -6.2,-30.3 -6.8,-45.8c-1.5,-36.9 2.6,-73.5 5.1,-110.2c1.9,-28.2 2.6,-56.5 3.9,-84.8c0.4,-9.6 -4.3,-16.2 -12.3,-20.6c-11,-6 -22.8,-8 -35.2,-6.3c-5.8,0.8 -9.5,3.3 -11.6,9.2c-14.4,42 -23.3,85.3 -31.2,128.9c-4.9,27.5 -9.9,55 -14.9,82.5c-0.2,1.4 -1,2.7 -1.5,4c-0.5,-0.1 -0.9,-0.1 -1.4,-0.2c-0.3,-1.9 -0.8,-3.8 -0.9,-5.6c-1,-15.4 -2.4,-30.9 -2.9,-46.3c-1.3,-34.6 -2.3,-69.2 -3.2,-103.8c-0.3,-9.5 -4.8,-15.7 -13.1,-19.5c-9.5,-4.5 -19.6,-4.8 -29.8,-3.7c-7.2,0.7 -11.7,4.1 -12.6,11.7c-0.3,2.3 -1.2,4.5 -1.7,6.8c-11.6,54.8 -23.3,109.7 -34.9,164.5c-0.3,1.6 -1,3.2 -1.5,4.8c-0.5,0 -1,-0.1 -1.5,-0.1c-0.3,-2 -1,-4 -1,-5.9c0,-22.5 -0.8,-45 0.3,-67.4c1.6,-33.9 4.4,-67.8 6.9,-101.7c0.4,-6 -1.8,-9.9 -6.6,-12.8c-8.8,-5.4 -18.5,-7.2 -28.7,-6.9c-3.7,0.1 -6.1,1.9 -7,5.3c-1.8,6.7 -3.8,13.5 -4.9,20.3c-5.4,33.6 -6.5,67.6 -6.5,101.6c0,26.8 0.8,53.6 2.8,80.3c1.7,22.9 5.1,45.6 8.9,68.3c2.4,14.3 7.9,27.9 17.9,39c12.4,13.8 32.2,14.7 44.2,2c1.5,-1.6 2.7,-4.4 2.4,-6.5c-3.2,-25.8 -1.7,-51.6 0.6,-77.3c3.7,-40.1 10.7,-79.8 18.6,-119.3c0.7,-3.4 2.1,-5 6,-4.4c0.2,1.5 0.6,3.1 0.7,4.7c1.1,15.6 1.5,31.3 3.2,46.8c4.4,39.4 9,78.7 14.2,118c1.7,13.3 4.9,26.6 12.4,38.2c10.1,15.6 31.5,17 43.6,2.9c1.1,-1.3 1.8,-3.6 1.7,-5.3c-0.5,-12.5 -2.4,-25 -1.9,-37.4c1.2,-29.6 2.7,-59.2 5.5,-88.7c3,-31.5 8.7,-62.6 16.8,-93.2C811.4,327 813.1,324.1 818.8,325.4zM273.6,413c-0.7,-0.9 -1.7,-2.1 -2.7,-3.4C236.2,365 201.8,320.3 166.8,276c-10,-12.6 -21.2,-24.4 -32.4,-35.9c-6,-6.2 -12.4,-6.5 -18.2,-3c-6.9,4.2 -14,16.4 -12.5,22.4c4.3,17.3 12.2,33 21.7,48c4.6,7.2 5.4,7.3 13.2,3.2c3.2,-1.7 6.1,-2.8 8.7,0.9c1,1.5 2.3,2.8 3.4,4.3c35.8,48.5 71.5,97.1 107.6,145.4c5,6.7 6.5,12.6 4.8,20.9c-8.8,44.6 -17.1,89.2 -25.4,133.9c-0.8,4.5 -2.4,6.4 -7.4,6.2c-10.1,-0.4 -13.4,3.1 -14.4,13c-2.2,21.9 1.9,43.5 3.4,65.2c0.5,7.3 4.2,10.7 10.2,13.1c12.1,4.7 24.7,6.5 37.6,7.2c4.8,0.3 8,-1 8.3,-6.5c0.2,-2.8 1.3,-5.5 1.8,-8.3c6.4,-37.2 12.9,-74.4 19.1,-111.7c8.7,-52.5 17,-105.1 25.9,-157.6c10.3,-60.9 21.3,-121.6 36.1,-181.6c6.9,-27.9 13.9,-55.9 27,-81.8c0.7,-1.4 -0.1,-4.2 -1.1,-5.7c-5.5,-8.2 -35,-10.8 -40.6,-3.7c-0.5,0.7 -1.3,1.1 -1.8,1.7c-4,6.1 -8.5,12 -11.6,18.5c-10.8,22.8 -17.6,47.1 -23,71.6C295.5,307.9 284.7,360.4 273.6,413zM500.2,485.7c0.7,0.2 1.4,0.4 2.2,0.7c0.5,3.1 1,6.2 1.6,9.2c3.3,16.8 8.2,33 19.2,46.6c18.9,23.2 52.1,22.6 70.3,-1c0.7,-0.9 1.5,-2.5 1.3,-3.5c-2.5,-9.2 -5.2,-18.4 -7.8,-27.7c-15.9,13.4 -28.1,11.3 -37.8,-7.3c-4.1,-7.9 -7.8,-16.6 -8.8,-25.2c-2.6,-22.6 -4.2,-45.4 -4.9,-68.2c-0.9,-31 -0.5,-62 -0.8,-93c-0.1,-11.8 -1,-23.6 -1.3,-35.4c-0.2,-5.2 -2.6,-8.9 -6.8,-11.5c-11.7,-7.2 -24.4,-9.7 -37.8,-7.3c-5.7,1 -7.8,4.1 -7.7,9.8c0.2,6.5 0.7,13 0.8,19.5c0.4,44.4 -3.4,88.5 -10,132.3c-5.1,33.6 -11.9,66.8 -22.7,99.1c-1.8,5.3 -3.7,10.5 -5.6,15.6c-11.1,-1.4 -8.4,0 -10.4,-9.2c-0.9,-4.2 -1.4,-8.5 -2,-12.8c-6.6,-48 -8,-96.2 -5.8,-144.5c1,-21.8 2.8,-43.5 4.7,-65.2c0.5,-5.5 -0.8,-9.2 -5.9,-10.9c-6.9,-2.3 -13.8,-4.6 -20.9,-6.2c-4.5,-1.1 -8.4,0.9 -10.4,5.1c-2.6,5.6 -5.2,11.2 -6.7,17.1c-7.6,29.7 -9.8,60.1 -11.2,90.5c-1.7,37.2 -0.8,74.2 3.9,111.2c4.7,36.5 41.5,67 69,72.7c15.2,3.1 24.6,-0.4 31.5,-14.3c5.1,-10.2 9.1,-21.1 11.6,-32.2c3.5,-15.4 5,-31.2 7.4,-46.8C498.6,490.4 499.5,488.1 500.2,485.7zM344.4,521.1c-0.8,2.5 -1.2,3.5 -1.4,4.6c-2.8,17.2 -5.3,34.5 -8.4,51.7c-1,5.2 0.2,8.7 3.6,12.5C403.6,663 485,695.1 582.5,684c58,-6.6 108.2,-31.2 151.3,-70.5c5.1,-4.6 9.8,-9.7 15.1,-15c-14.7,-4.5 -25.2,-13.2 -33.4,-24.7c-26.9,31.1 -74.3,31.2 -102.2,-1.7c-30.7,26.6 -63.8,28.9 -99.4,9.9c-1.1,2 -2.1,4 -3.3,6c-16,28.6 -40.9,39.7 -72.8,31.8c-27.1,-6.7 -48.9,-22 -67,-42.9C357.3,561.2 348.1,543.2 344.4,521.1zM730.6,206.9c-1.6,-1.4 -3.1,-2.8 -4.7,-4.2c-45.4,-38.3 -97.6,-60.3 -156.9,-65c-50.5,-4 -98.4,5.4 -143.9,27.6c-3.2,1.6 -4.2,3.4 -3.9,6.9c0.3,3.7 0.3,7.7 -1.1,11c-4.4,10.6 -10.1,20.6 -14.1,31.3c-4.7,12.7 -7.9,26 -12,39.7c19,-1 35.7,3.8 51.4,12.9c3.2,-25.5 21,-37 38.1,-39.9c19.7,-3.4 38.5,0 56.2,9.1c17.1,8.7 27.5,22.3 28.5,42c0.6,11.6 1.3,23.3 1.4,34.9c0.4,30.3 0.5,60.6 0.7,90.9c0,7.4 0,14.8 0,22.7c4.6,-1.1 8.8,0.2 8.4,-5.9c-0.8,-12.1 -1.3,-24.3 -1.4,-36.4c-0.3,-40.5 0.3,-81 6,-121.1c1.8,-12.6 4.7,-25.2 9.1,-37.1c5.7,-15.4 17.8,-24.5 34.7,-24.9c9.5,-0.2 19.5,0.3 28.6,2.6c10,2.5 19.3,7.6 29.7,11.9C698.4,207.8 714,207 730.6,206.9z"/>
+</vector>
diff --git a/res/drawable/ref_city.png b/res/drawable/ref_city.png
new file mode 100644
index 000000000..00592167b
--- /dev/null
+++ b/res/drawable/ref_city.png
Binary files differ
diff --git a/res/drawable/ref_flowers.png b/res/drawable/ref_flowers.png
new file mode 100644
index 000000000..22c11626d
--- /dev/null
+++ b/res/drawable/ref_flowers.png
Binary files differ
diff --git a/res/drawable/watermark.xml b/res/drawable/watermark.xml
new file mode 100644
index 000000000..5383d5c16
--- /dev/null
+++ b/res/drawable/watermark.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_selected="true" android:drawable="@drawable/ic_watermark_selected"/>
+ <item android:state_selected="false" android:drawable="@drawable/ic_watermark"/>
+</selector> \ No newline at end of file
diff --git a/res/layout-land/filtershow_presets_dialog.xml b/res/layout-land/filtershow_presets_dialog.xml
new file mode 100644
index 000000000..389eaec43
--- /dev/null
+++ b/res/layout-land/filtershow_presets_dialog.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="424dp"
+ android:layout_height="260dp"
+ android:background="#EFEFEF">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dp"
+ android:layout_marginTop="22dp"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/icon_tools"
+ android:layout_width="21dp"
+ android:layout_height="27dp"
+ android:src="@drawable/icon_tools"/>
+
+ <TextView
+ android:id="@+id/dialog_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingStart="8dp"
+ android:textColor="#000000"
+ android:textSize="16sp"
+ android:text="@string/filtershow_dialog_title"/>
+ </LinearLayout>
+
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginTop="20dp"
+ android:layout_marginStart="24dp"
+ android:layout_marginEnd="34dp">
+
+ <TextView
+ android:id="@+id/dialog_content"
+ android:layout_width="128dp"
+ android:layout_height="wrap_content"
+ android:textSize="13sp"
+ android:textColor="#000000"
+ android:text="@string/filtershow_dialog_content"/>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="28dp"
+ android:layout_marginEnd="34dp">
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/original_photo"
+ android:layout_width="105dp"
+ android:layout_height="79dp"
+ android:layout_gravity="center"
+ android:src="@drawable/ref_city" />
+
+ <TextView
+ android:id="@+id/original"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:textColor="#000000"
+ android:textSize="9sp"
+ android:text="@string/filtershow_dialog_original_photo" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/filter_photo"
+ android:layout_width="105dp"
+ android:layout_height="79dp"
+ android:layout_gravity="center"
+ android:src="@drawable/ref_flowers" />
+
+ <TextView
+ android:id="@+id/filter"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:textColor="#000000"
+ android:textSize="9sp"
+ android:text="@string/filtershow_dialog_apply_photo"/>
+ </LinearLayout>
+ </LinearLayout>
+ </LinearLayout>
+
+ <CheckBox
+ android:id="@+id/filtershow_check_box"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="18dp"
+ android:layout_marginTop="20dp"
+ android:textSize="13sp"
+ android:text="@string/filtershow_dialog_checkbox" />
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="2px"
+ android:layout_marginTop="10dp"
+ android:background="#D8D8D8" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="260dp">
+
+ <Button
+ android:id="@+id/cancel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/cancel"
+ android:textSize="13dp"
+ style="?android:attr/buttonBarButtonStyle" />
+
+ <Button
+ android:id="@+id/ok"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/ok_continue"
+ android:textSize="13dp"
+ style="?android:attr/buttonBarButtonStyle" />
+ </LinearLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/activity_three_dimensional.xml b/res/layout/activity_three_dimensional.xml
new file mode 100644
index 000000000..724427316
--- /dev/null
+++ b/res/layout/activity_three_dimensional.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ tools:context="com.android.gallery3d.app.dualcam3d.ThreeDimensionalActivity">
+
+ <com.android.gallery3d.app.dualcam3d.GLView
+ android:id="@+id/image"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <LinearLayout
+ android:id="@+id/mode_3d"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top|end"
+ android:paddingTop="130dp"
+ android:paddingRight="50dp"
+ android:orientation="vertical">
+
+ <ImageButton
+ android:id="@+id/three_dimensional"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:background="?android:attr/actionBarItemBackground"
+ android:src="@drawable/three_d"/>
+
+ <ImageButton
+ android:id="@+id/mode_gyro"
+ android:layout_width="wrap_content"
+ android:layout_height="40dp"
+ android:text="@string/grad"
+ android:textAlignment="center"
+ android:visibility="gone" />
+
+ <ImageButton
+ android:id="@+id/mode_auto"
+ android:layout_width="wrap_content"
+ android:layout_height="40dp"
+ android:text="@string/auto"
+ android:textAlignment="center"
+ android:visibility="gone" />
+
+ <ImageButton
+ android:id="@+id/mode_touch"
+ android:layout_width="wrap_content"
+ android:layout_height="40dp"
+ android:text="@string/trueportrait_touch_up"
+ android:textAlignment="center"
+ android:visibility="gone" />
+ </LinearLayout>
+
+</merge>
diff --git a/res/layout/do_not_show_again_dialog.xml b/res/layout/do_not_show_again_dialog.xml
index d3d229740..a9bbb432a 100644
--- a/res/layout/do_not_show_again_dialog.xml
+++ b/res/layout/do_not_show_again_dialog.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -29,28 +29,34 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
android:paddingTop="8dip"
android:paddingBottom="8dip"
android:paddingEnd="?android:attr/dialogPreferredPadding"
android:paddingStart="?android:attr/dialogPreferredPadding"
android:orientation="vertical" >
- <TextView
- android:id="@+id/message"
+ <ScrollView
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- style="@android:style/TextAppearance.Material.Subhead" />
-
- <Space
- android:layout_width="0dp"
- android:layout_height="5dp"/>
+ android:layout_height="match_parent"
+ android:layout_weight="2">
+ <TextView
+ android:id="@+id/message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="@android:style/TextAppearance.Material.Subhead" />
+ </ScrollView>
<CheckBox
android:id="@+id/do_not_show_chk"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_vertical"
+ android:gravity="center"
+ android:layout_weight="1"
+ android:minHeight="20dp"
+ android:paddingEnd="6dp"
style="@android:style/TextAppearance.Material.Subhead"
android:text="@string/do_not_show_again" />
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/res/layout/filtershow_actionbar_dualcam_fusion.xml b/res/layout/filtershow_actionbar_dualcam_fusion.xml
new file mode 100644
index 000000000..c5cec2572
--- /dev/null
+++ b/res/layout/filtershow_actionbar_dualcam_fusion.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1">
+
+ <ImageButton
+ android:id="@+id/pick_underlay"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_alignParentRight="true"
+ android:background="@android:color/transparent"
+ android:paddingEnd="16dp"
+ android:paddingStart="16dp"
+ android:src="@drawable/tp_bg_select" />
+
+</RelativeLayout> \ No newline at end of file
diff --git a/res/layout/filtershow_bottom_panel.xml b/res/layout/filtershow_bottom_panel.xml
index f7c220833..e99d0c566 100644
--- a/res/layout/filtershow_bottom_panel.xml
+++ b/res/layout/filtershow_bottom_panel.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -144,5 +144,15 @@
android:padding="2dip"
android:scaleType="centerInside"
android:src="@drawable/trueportrait_background" />
+
+ <ImageButton
+ android:id="@+id/waterMarkButton"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:background="@android:color/transparent"
+ android:padding="2dip"
+ android:scaleType="centerInside"
+ android:src="@drawable/watermark" />
</LinearLayout>
-</com.android.gallery3d.filtershow.CenteredLinearLayout> \ No newline at end of file
+</com.android.gallery3d.filtershow.CenteredLinearLayout>
diff --git a/res/layout/filtershow_category_panel_two.xml b/res/layout/filtershow_category_panel_two.xml
new file mode 100644
index 000000000..e807c88ef
--- /dev/null
+++ b/res/layout/filtershow_category_panel_two.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:theme="@android:style/Theme.DeviceDefault"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/transparent"
+ android:orientation="vertical">
+ <LinearLayout xmlns:custom="http://schemas.android.com/apk/res/org.codeaurora.gallery"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@color/edit_actionbar_background">
+
+ <HorizontalScrollView
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:background="@android:color/transparent"
+ android:scrollbars="none" >
+
+ <com.android.gallery3d.filtershow.category.CategoryTrack
+ android:id="@+id/listItems"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/category_panel_height"
+ android:background="@android:color/transparent"
+ custom:iconSize="@dimen/category_panel_icon_size"
+ android:divider="@android:color/transparent"
+ android:dividerPadding="8dip"
+ />
+
+ </HorizontalScrollView>
+
+ <com.android.gallery3d.filtershow.category.IconView
+ android:id="@+id/addButton"
+ android:layout_width="@dimen/category_panel_height"
+ android:layout_height="@dimen/category_panel_height"
+ android:src="@drawable/filtershow_add"/>
+
+ </LinearLayout>
+
+ <FrameLayout
+ android:id="@+id/bottom_panel"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/category_actionbar_panel_height"
+ android:background="@color/edit_actionbar_background"
+ android:visibility="visible">
+
+ <ImageButton
+ android:id="@+id/cancel"
+ android:layout_width="@dimen/category_actionbar_panel_height"
+ android:layout_height="@dimen/category_actionbar_panel_height"
+ android:background="?android:attr/actionBarItemBackground"
+ android:src="@drawable/cancel" />
+
+ <TextView
+ android:id="@+id/editor_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="16sp"
+ android:textColor="#fff"
+ android:layout_gravity="center"/>
+
+ <ImageButton
+ android:id="@+id/done"
+ android:layout_width="@dimen/category_actionbar_panel_height"
+ android:layout_height="@dimen/category_actionbar_panel_height"
+ android:background="?android:attr/actionBarItemBackground"
+ android:layout_gravity="right"
+ android:src="@drawable/done" />
+ </FrameLayout>
+
+</LinearLayout>
diff --git a/res/layout/filtershow_default_edittext.xml b/res/layout/filtershow_default_edittext.xml
new file mode 100644
index 000000000..9af4eb759
--- /dev/null
+++ b/res/layout/filtershow_default_edittext.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical" android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <EditText
+ android:id="@+id/filtershow_default_edit"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="19sp"
+ android:layout_marginRight="19sp"
+ android:focusable="true"
+ android:imeOptions="actionDone"
+ android:hint="@string/filter_name"
+ android:singleLine="true"/>
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/filtershow_presets_dialog.xml b/res/layout/filtershow_presets_dialog.xml
new file mode 100644
index 000000000..72db9133e
--- /dev/null
+++ b/res/layout/filtershow_presets_dialog.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="253dp"
+ android:layout_height="425dp"
+ android:background="#EFEFEF">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingStart="26dp"
+ android:paddingTop="22dp"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/icon_tools"
+ android:layout_width="21dp"
+ android:layout_height="20dp"
+ android:src="@drawable/icon_tools"/>
+
+ <TextView
+ android:id="@+id/dialog_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="11dp"
+ android:textColor="#000000"
+ android:textSize="16sp"
+ android:text="@string/filtershow_dialog_title"/>
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/dialog_content"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="21dp"
+ android:layout_marginEnd="33dp"
+ android:layout_marginTop="22dp"
+ android:textSize="13sp"
+ android:textColor="#000000"
+ android:text="@string/filtershow_dialog_content"/>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center_horizontal"
+ android:layout_marginTop="64dp"
+ android:layout_marginStart="21dp"
+ android:layout_marginEnd="21dp">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/original_photo"
+ android:layout_width="105dp"
+ android:layout_height="79dp"
+ android:layout_gravity="center"
+ android:src="@drawable/ref_city" />
+
+ <TextView
+ android:id="@+id/original"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:textColor="#000000"
+ android:textSize="9sp"
+ android:text="@string/filtershow_dialog_original_photo" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/filter_photo"
+ android:layout_width="105dp"
+ android:layout_height="79dp"
+ android:layout_gravity="center"
+ android:src="@drawable/ref_flowers" />
+
+ <TextView
+ android:id="@+id/filter"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:textColor="#000000"
+ android:textSize="9sp"
+ android:text="@string/filtershow_dialog_apply_photo"/>
+ </LinearLayout>
+ </LinearLayout>
+
+ <CheckBox
+ android:id="@+id/filtershow_check_box"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="25dp"
+ android:layout_marginTop="60dp"
+ android:textSize="13sp"
+ android:text="@string/filtershow_dialog_checkbox" />
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="2px"
+ android:layout_marginTop="18dp"
+ android:background="#D8D8D8" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="110dp"
+ android:layout_marginEnd="14dp">
+
+ <Button
+ android:id="@+id/cancel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/cancel"
+ android:textSize="13dp"
+ style="?android:attr/buttonBarButtonStyle" />
+
+ <Button
+ android:id="@+id/ok"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/ok_continue"
+ android:textSize="13dp"
+ style="?android:attr/buttonBarButtonStyle" />
+ </LinearLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/filtershow_watermark.xml b/res/layout/filtershow_watermark.xml
new file mode 100644
index 000000000..fe986cc5c
--- /dev/null
+++ b/res/layout/filtershow_watermark.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/root_layout"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <ImageView
+ android:id="@+id/image"
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:layout_gravity="left" />
+
+ <EditText
+ android:id="@+id/edit"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@null"
+ android:cursorVisible="true"
+ android:layout_gravity="left"
+ android:inputType="textNoSuggestions"
+ android:textColor="@color/watermark_text_color"
+ android:textColorHint="@color/watermark_text_color"
+ android:textSize="16sp" />
+
+</FrameLayout>
diff --git a/res/layout/mediapicker_list_item.xml b/res/layout/mediapicker_list_item.xml
new file mode 100644
index 000000000..12f8c63bf
--- /dev/null
+++ b/res/layout/mediapicker_list_item.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <com.android.gallery3d.filtershow.mediapicker.SelectedImageView
+ android:id="@+id/thumbnail"
+ android:layout_width="@dimen/picker_photo_size"
+ android:layout_height="@dimen/picker_photo_size"
+ android:layout_gravity="center"
+ android:scaleType="centerCrop" />
+</RelativeLayout>
diff --git a/res/layout/mediapicker_panel.xml b/res/layout/mediapicker_panel.xml
new file mode 100644
index 000000000..fb34ebfff
--- /dev/null
+++ b/res/layout/mediapicker_panel.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+
+<com.android.gallery3d.filtershow.mediapicker.MediaPicker
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <LinearLayout
+ android:id="@+id/mediapicker_slidestrip"
+ android:layout_width="match_parent"
+ android:layout_height="60dp"
+ android:gravity="bottom|center"
+ android:orientation="horizontal"
+ android:background="#00000000" >
+ <ImageButton
+ android:id="@+id/arrow"
+ android:layout_width="60dp"
+ android:layout_height="30dp"
+ android:layout_alignParentBottom="true"
+ android:src="@drawable/arrow"
+ android:background="#00000000" />
+ </LinearLayout>
+
+ <com.android.photos.views.HeaderGridView
+ android:id="@+id/grid"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:cacheColorHint="@android:color/transparent"
+ android:columnWidth="@dimen/picker_photo_size"
+ android:drawSelectorOnTop="true"
+ android:fadingEdge="none"
+ android:gravity="center"
+ android:horizontalSpacing="@dimen/picker_photo_spacing"
+ android:listSelector="@android:color/transparent"
+ android:numColumns="auto_fit"
+ android:paddingLeft="5dp"
+ android:paddingRight="5dp"
+ android:scrollbars="none"
+ android:stretchMode="columnWidth"
+ android:verticalSpacing="@dimen/picker_photo_spacing"/>
+
+ <LinearLayout
+ android:id="@+id/mediapicker_tabstrip"
+ android:layout_width="match_parent"
+ android:layout_height="60dp"
+ android:orientation="horizontal"
+ android:background="#c0000000" >
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <ImageButton
+ android:id="@+id/btn_no"
+ android:layout_width="60dp"
+ android:layout_height="60dp"
+ android:layout_centerVertical="true"
+ android:layout_alignParentLeft="true"
+ android:src="@drawable/cancel"
+ android:background="#00000000" />
+ <ImageButton
+ android:id="@+id/btn_yes"
+ android:layout_width="60dp"
+ android:layout_height="60dp"
+ android:layout_centerVertical="true"
+ android:layout_alignParentRight="true"
+ android:src="@drawable/done"
+ android:background="#00000000" />
+ </RelativeLayout>
+ </LinearLayout>
+
+</com.android.gallery3d.filtershow.mediapicker.MediaPicker>
diff --git a/res/layout/movie_view.xml b/res/layout/movie_view.xml
index de9584bb4..2679e38e8 100644
--- a/res/layout/movie_view.xml
+++ b/res/layout/movie_view.xml
@@ -21,11 +21,16 @@
android:layout_height="match_parent">
<org.codeaurora.gallery3d.video.CodeauroraVideoView android:id="@+id/surface_view"
- android:visibility="invisible"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" />
+ <View
+ android:id="@+id/surface_view_cover"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/black"/>
+
<ImageView
android:id="@+id/img_live"
android:layout_width="wrap_content"
diff --git a/res/layout/three_d_button.xml b/res/layout/three_d_button.xml
new file mode 100644
index 000000000..eb8366db3
--- /dev/null
+++ b/res/layout/three_d_button.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/three_d_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="100dp"
+ android:layout_marginEnd="50dp"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentEnd="true"
+ android:layout_gravity="bottom"
+ android:orientation="horizontal"
+ android:theme="@android:style/Theme.DeviceDefault"
+ android:visibility="gone">
+
+ <ImageButton
+ android:id="@+id/three_dimensional"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:background="?android:attr/actionBarItemBackground"
+ android:src="@drawable/three_d"
+ android:visibility="visible" />
+</LinearLayout>
diff --git a/res/menu/filtershow_menu_edit.xml b/res/menu/filtershow_menu_edit.xml
new file mode 100644
index 000000000..afab8cd14
--- /dev/null
+++ b/res/menu/filtershow_menu_edit.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:id="@+id/deleteButton"
+ android:title="@string/delete"/>
+ <item
+ android:id="@+id/renameButton"
+ android:title="@string/filtershow_preset_rename"/>
+</menu> \ No newline at end of file
diff --git a/res/values-zh-rCN/filtershow_strings.xml b/res/values-zh-rCN/filtershow_strings.xml
index 3d73589bf..0c372c2e1 100755
--- a/res/values-zh-rCN/filtershow_strings.xml
+++ b/res/values-zh-rCN/filtershow_strings.xml
@@ -154,9 +154,33 @@
<string name="filtershow_exif_f_stop" msgid="6081797865604483139">"光圈值"</string>
<string name="filtershow_exif_exposure_time" msgid="4099067062781294115">"曝光时间"</string>
<string name="filtershow_exif_copyright" msgid="8801875918803737581">"版权"</string>
+ <!-- Label for the "refocus" dual camera effect [CHAR LIMIT=15] -->
+ <string name="focus">对焦</string>
+ <!-- Label for the "fusion" dual camera effect [CHAR LIMIT=15] -->
+ <string name="fusion">背景切换</string>
+ <!-- Label for the "sketch" dual camera effect [CHAR LIMIT=15] -->
+ <string name="sketch">素描</string>
+ <!-- Label for the "halo" dual camera effect [CHAR LIMIT=15] -->
+ <string name="halo">光环</string>
+ <!-- Label for the "zoom" dual camera effect [CHAR LIMIT=15] -->
+ <string name="zoom">缩放模糊</string>
+ <!-- Label for the "motion" dual camera effect [CHAR LIMIT=15] -->
+ <string name="motion">动态模糊</string>
+ <!-- Label for the "bw" dual camera effect [CHAR LIMIT=15] -->
+ <string name="bw">去色</string>
+ <!-- Label for the "blackboard" dual camera effect [CHAR LIMIT=15] -->
+ <string name="blackboard">黑板</string>
+ <!-- Label for the "whiteboard" dual camera effect [CHAR LIMIT=15] -->
+ <string name="whiteboard">白板</string>
+ <!-- Label for the "posterize" dual camera effect [CHAR LIMIT=15] -->
+ <string name="posterize">色块化</string>
+ <!-- Label for the "negative" dual camera effect [CHAR LIMIT=15] -->
+ <string name="dc_negative">负片</string>
<string name="color">滤镜</string>
<string name="frames">相框</string>
+ <string name="dual_camera_effects">双摄像头效果</string>
+ <string name="dual_camera_effects_intro">此功能可将双摄像头效果应用到背景上,如动态模糊和素描。.你可以将两张照片合并到一起来创建一个有趣的效果。这个功能在你的摄像头和照片的主体有一个短距离时效果最好。</string>
<string name="trueportrait_intro">此功能用于增强人像照。你可以将效果应用于照片背景,例如“模糊”和“速写”。你也可以将两张照片拼在一起来给你的人像照创建一个有趣的背景。</string>
</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index eadd4f20b..80079dd46 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -47,4 +47,7 @@
<attr name="background" format="integer" />
<attr name="foreground" format="integer" />
</declare-styleable>
+ <declare-styleable name="FillColor">
+ <attr name="fillColorSelector" format="color" />
+ </declare-styleable>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 65cd26152..49aa5d599 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -235,4 +235,6 @@
<dimen name="toolbar_title_text_size">20dp</dimen>
<dimen name="toolbar_exit_padding_left">16dp</dimen>
+
+ <dimen name="watermark_default_size">75dp</dimen>
</resources>
diff --git a/res/values/filtershow_color.xml b/res/values/filtershow_color.xml
index b1d4111c2..666651b2c 100644
--- a/res/values/filtershow_color.xml
+++ b/res/values/filtershow_color.xml
@@ -37,7 +37,7 @@
<color name="filtershow_stateview_selected_text">#000000</color>
<color name="filtershow_categoryview_background">#1a1a1a</color>
<color name="filtershow_categoryview_text">#ffffff</color>
- <color name="filtershow_category_selection">#ffffffff</color>
+ <color name="filtershow_category_selection">#4592F9</color>
<color name="gradcontrol_point_center">#ffffffff</color>
<color name="gradcontrol_point_edge">#ffffffff</color>
<color name="gradcontrol_graypoint_center">#888888</color>
@@ -51,6 +51,7 @@
<color name="color_chooser_slected_border">#a7a7a7</color>
<color name="filtershow_image_mask">#4d000000</color>
<color name="filtershow_info_text">#DE000000</color>
+ <color name="filtershow_info_test">#00FF0000</color>
<color name="filtershow_color_none">#80000000</color>
<color name="filtershow_color_punch">#80000000</color>
@@ -67,4 +68,6 @@
<color name="bottom_panel_background_color">#A5000000</color>
<color name="crop_panel_background_color">#A5000000</color>
<color name="crop_text_color">#4f92e9</color>
+ <color name="watermark_text_color">#80ffffff</color>
+ <color name="watermark_highlight_color">#4592F9</color>
</resources> \ No newline at end of file
diff --git a/res/values/filtershow_strings.xml b/res/values/filtershow_strings.xml
index 7c0212e7e..be77814d5 100644
--- a/res/values/filtershow_strings.xml
+++ b/res/values/filtershow_strings.xml
@@ -208,6 +208,20 @@
<string name="sketch">Sketch</string>
<!-- Label for the "halo" dual camera effect [CHAR LIMIT=15] -->
<string name="halo">Halo</string>
+ <!-- Label for the "zoom" dual camera effect [CHAR LIMIT=15] -->
+ <string name="zoom">Zoom</string>
+ <!-- Label for the "motion" dual camera effect [CHAR LIMIT=15] -->
+ <string name="motion">Motion</string>
+ <!-- Label for the "bw" dual camera effect [CHAR LIMIT=15] -->
+ <string name="bw">B/W</string>
+ <!-- Label for the "blackboard" dual camera effect [CHAR LIMIT=15] -->
+ <string name="blackboard">Blackboard</string>
+ <!-- Label for the "whiteboard" dual camera effect [CHAR LIMIT=15] -->
+ <string name="whiteboard">Whiteboard</string>
+ <!-- Label for the "posterize" dual camera effect [CHAR LIMIT=15] -->
+ <string name="posterize">Posterize</string>
+ <!-- Label for the "negative" dual camera effect [CHAR LIMIT=15] -->
+ <string name="dc_negative">Negative</string>
<!-- Label for the "blur" true portrait effect [CHAR LIMIT=15] -->
<string name="blur">Blur</string>
<!-- Label for the "motion blur" true portrait effect [CHAR LIMIT=15] -->
@@ -350,6 +364,8 @@
<string name="fusion_pick_point">Pick Segment</string>
<string name="fusion_pick_underlay">Pick Underlay</string>
+ <string name="dual_camera_effects">Dual Camera Effects</string>
+ <string name="dual_camera_effects_intro">Allows you to apply background effects, such as "Motion" and "Sketch". You can also merge two photos together for interesting effects. This feature works best when you have a short distance your camera and the main subject of you picture.</string>
<string name="dualcam_no_segment_toast">No segment found at this point</string>
<string name="dualcam_filter_not_supported">Dual camera filters not supported for this image</string>
<string name="trueportrait_intro">Allows you to enhance photos of people. You can apply effects to the background, such as \"blur\" and \"sketch\". You can also merge two photos together to create interesting backgrounds for your portrait photos.</string>
@@ -359,11 +375,13 @@
<string name="trueportrait_edit_background_toast">Use your finger to paint in any areas of the background that were missed.</string>
<string name="trueportrait_edit_help">To zoom, use two fingers to pinch open or closed. You can also drag with two fingers to re-position the image. This can make it easier to fix any problem areas.</string>
<string name="trueportrait_fusion_intro">Your foreground person can be copied and pasted onto any photo in your Gallery. You can try using different background photos to create new and interesting portraits.</string>
+ <string name="dualcam_fusion_intro">Your foreground can be copied and pasted onto any photo in your Gallery. \n\nYou can try using different background photos to create new and interesting portraits.</string>
<string name="do_not_show_again">Do not show again</string>
<string name="trueportrait_touch_up">Touch Up</string>
<string name="fusion_pick_background">Select Background Photo</string>
<string name="color">Color</string>
+ <string name="ok_continue">Continue</string>
<string name="frames">Frames</string>
<string name="beautify">Beautify</string>
<string name="dualcam">Dual Camera</string>
@@ -372,8 +390,31 @@
<string name="background">Background</string>
<string name="brush_size">Brush Size</string>
+ <string name="pref_dualcam_intro_show_key" translatable="false">pref_dualcam_intro_show_key</string>
<string name="pref_trueportrait_intro_show_key" translatable="false">pref_trueportrait_intro_show_key</string>
<string name="pref_trueportrait_edit_intro_show_key" translatable="false">pref_trueportrait_edit_intro_show_key</string>
<string name="pref_trueportrait_fusion_intro_show_key" translatable="false">pref_trueportrait_fusion_intro_show_key</string>
<string name="pref_trueportrait_fusion_underlay_key" translatable="false">pref_trueportrait_fusion_underlay_key</string>
+ <string name="pref_dualcam_fusion_underlay_key" translatable="false">pref_dualcam_fusion_underlay_key</string>
+ <string name="pref_dualcam_fusion_intro_show_key" translatable="false">pref_trueportrait_fusion_intro_show_key</string>
+
+ <!--Filtershow dialog -->
+ <string name="filtershow_dialog_title">Custom Filter</string>
+ <string name="filtershow_dialog_content">Allows you to create a photo filter.\n\nSelect a photo you like and use it as a filter for other photos</string>
+ <string name="filtershow_dialog_original_photo">Original Photo</string>
+ <string name="filtershow_dialog_apply_photo">Colors to Apply</string>
+ <string name="filtershow_dialog_checkbox">Do not show again</string>
+ <string name="pref_filtergenerator_intro_show_key" translatable="false">pref_filtergenerator_intro_show_key</string>
+ <string name="filtershow_preset_title">Custom</string>
+ <string name="filtershow_preset_rename">Rename</string>
+ <string name="delete_before_exit">Delete Filter?</string>
+ <string name="rename_before_exit">Rename Filter</string>
+ <string name="filter_name">Filter name</string>
+ <string name="filter_name_notification">Name cannot be NULL.</string>
+ <string name="filter_name_duplicate">Name already existed, please input another one.</string>
+ <string name="watermark_location">Location</string>
+ <string name="watermark_time">Time</string>
+ <string name="watermark_weather">Weather</string>
+ <string name="watermark_emotions">Emotions</string>
+ <string name="watermark_food">Food</string>
</resources>
diff --git a/res/values/filtershow_styles.xml b/res/values/filtershow_styles.xml
index e8dd11040..6fa76a2af 100644
--- a/res/values/filtershow_styles.xml
+++ b/res/values/filtershow_styles.xml
@@ -64,4 +64,12 @@
<item name="android:background">@null</item>
</style>
+ <style name="DefaultFillColor">
+ <item name="fillColorSelector">#FFFFFF</item>
+ </style>
+
+ <style name="SelectedFillColor">
+ <item name="fillColorSelector">#4592F9</item>
+ </style>
+
</resources> \ No newline at end of file
diff --git a/res/values/filtershow_values.xml b/res/values/filtershow_values.xml
index 046c5440a..a7f43f802 100644
--- a/res/values/filtershow_values.xml
+++ b/res/values/filtershow_values.xml
@@ -22,7 +22,7 @@
<dimen name="state_panel_text_size">16dip</dimen>
<!-- Bottom Panel Height -->
- <dimen name="bottom_panel_height">60dip</dimen>
+ <dimen name="bottom_panel_height">50dip</dimen>
<!-- Category Panel Height -->
<dimen name="category_panel_height">90dip</dimen>
@@ -30,7 +30,7 @@
<!-- Category Panel Icon Size -->
<dimen name="category_panel_icon_size">80dip</dimen>
- <dimen name="category_actionbar_panel_height">60dip</dimen>
+ <dimen name="category_actionbar_panel_height">50dip</dimen>
<!-- Category Panel Text Size -->
<dimen name="category_panel_text_size">11dip</dimen>
diff --git a/res/values/mediapicker_colors.xml b/res/values/mediapicker_colors.xml
new file mode 100644
index 000000000..765e8b168
--- /dev/null
+++ b/res/values/mediapicker_colors.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+
+<resources>
+
+ <color name="picker_imageloading">#252528</color>
+ <color name="picker_grid_state_pressed">#DC007aff</color>
+ <color name="picker_grid_state_focused">#DC007aff</color>
+ <color name="picker_color">#007aff</color>
+
+</resources>
diff --git a/res/values/mediapicker_dimens.xml b/res/values/mediapicker_dimens.xml
new file mode 100644
index 000000000..ef432b5c1
--- /dev/null
+++ b/res/values/mediapicker_dimens.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. 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.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+-->
+
+<resources>
+
+ <dimen name="picker_photo_size">75dp</dimen>
+ <dimen name="picker_photo_spacing">4dp</dimen>
+ <dimen name="picker_border_size">3dp</dimen>
+ <dimen name="mediapicker_default_height">215dp</dimen>
+ <dimen name="mediapicker_land_height">90dp</dimen>
+</resources>
diff --git a/src/com/android/gallery3d/app/AbstractGalleryActivity.java b/src/com/android/gallery3d/app/AbstractGalleryActivity.java
index 709151a1a..c8898ee92 100644
--- a/src/com/android/gallery3d/app/AbstractGalleryActivity.java
+++ b/src/com/android/gallery3d/app/AbstractGalleryActivity.java
@@ -61,6 +61,7 @@ public abstract class AbstractGalleryActivity extends AbstractPermissionActivity
private TransitionStore mTransitionStore = new TransitionStore();
private PanoramaViewHelper mPanoramaViewHelper;
private Toolbar mToolbar;
+ public boolean isTopMenuShow = false;
private AlertDialog mAlertDialog = null;
private BroadcastReceiver mMountReceiver = new BroadcastReceiver() {
@@ -204,6 +205,12 @@ public abstract class AbstractGalleryActivity extends AbstractPermissionActivity
@Override
protected void onResume() {
super.onResume();
+ // If top menu shows, GLView is active,
+ // so don't need to resume it.
+ if (isTopMenuShow) {
+ isTopMenuShow = false;
+ return;
+ }
mGLRootView.lockRenderThread();
try {
getStateManager().resume();
@@ -218,6 +225,10 @@ public abstract class AbstractGalleryActivity extends AbstractPermissionActivity
@Override
protected void onPause() {
super.onPause();
+ // If top menu shows, don't pause GLView,
+ // so it can redraw when rotating.
+ if (isTopMenuShow)
+ return;
mOrientationManager.pause();
mGLRootView.onPause();
mGLRootView.lockRenderThread();
diff --git a/src/com/android/gallery3d/app/GalleryActivity.java b/src/com/android/gallery3d/app/GalleryActivity.java
index e18f1c2c6..95883afd5 100755
--- a/src/com/android/gallery3d/app/GalleryActivity.java
+++ b/src/com/android/gallery3d/app/GalleryActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
* Not a Contribution
*
* Copyright (C) 2009 The Android Open Source Project
@@ -27,6 +27,7 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
+import android.content.UriMatcher;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
@@ -91,6 +92,17 @@ public final class GalleryActivity extends AbstractGalleryActivity implements On
public static final String KEY_FROM_SNAPCAM = "from-snapcam";
public static final String KEY_TOTAL_NUMBER = "total-number";
+ private static final int ALL_DOWNLOADS = 1;
+ private static final int ALL_DOWNLOADS_ID = 2;
+ private static final UriMatcher sURIMatcher =
+ new UriMatcher(UriMatcher.NO_MATCH);
+ public static final String PERMISSION_ACCESS_ALL =
+ "android.permission.ACCESS_ALL_DOWNLOADS";
+ static {
+ sURIMatcher.addURI("downloads", "all_downloads", ALL_DOWNLOADS);
+ sURIMatcher.addURI("downloads", "all_downloads/#", ALL_DOWNLOADS_ID);
+ }
+
private static final String TAG = "GalleryActivity";
private Dialog mVersionCheckDialog;
private ListView mDrawerListView;
@@ -366,6 +378,17 @@ public final class GalleryActivity extends AbstractGalleryActivity implements On
} else if (Intent.ACTION_VIEW.equalsIgnoreCase(action)
|| ACTION_REVIEW.equalsIgnoreCase(action)){
mDrawerLayoutSupported = false;
+ Uri uri = intent.getData();
+ int flag = intent.getFlags();
+ int match = sURIMatcher.match(uri);
+ if ((match == ALL_DOWNLOADS || match == ALL_DOWNLOADS_ID) &&
+ (flag & Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
+ if (checkCallingOrSelfPermission(
+ PERMISSION_ACCESS_ALL) != PackageManager.PERMISSION_GRANTED) {
+ Log.w(TAG, "no permission to view: " + uri);
+ return;
+ }
+ }
startViewAction(intent);
} else {
mDrawerLayoutSupported = true;
@@ -750,7 +773,8 @@ public final class GalleryActivity extends AbstractGalleryActivity implements On
DualCameraNativeEngine.getInstance().initDepthMap(
primaryBm, auxiliaryBm, mpoFilepath,
- DualCameraNativeEngine.getInstance().getCalibFilepath(context));
+ DualCameraNativeEngine.getInstance().getCalibFilepath(context),
+ DualCameraNativeEngine.DEFAULT_BRIGHTNESS_INTENSITY);
primaryBm.recycle();
primaryBm = null;
diff --git a/src/com/android/gallery3d/app/MovieActivity.java b/src/com/android/gallery3d/app/MovieActivity.java
index 150b3807f..811cdca77 100644
--- a/src/com/android/gallery3d/app/MovieActivity.java
+++ b/src/com/android/gallery3d/app/MovieActivity.java
@@ -141,9 +141,11 @@ public class MovieActivity extends AbstractPermissionActivity {
|| audioManager.isBluetoothA2dpOn();
} else if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)
|| action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
- final int deviceClass = ((BluetoothDevice)
+ final BluetoothClass bc = ((BluetoothDevice)
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))
- .getBluetoothClass().getDeviceClass();
+ .getBluetoothClass();
+ if (bc == null) return;
+ final int deviceClass = bc.getDeviceClass();
if ((deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES)
|| (deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET)) {
mIsHeadsetOn = action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)
@@ -195,7 +197,7 @@ public class MovieActivity extends AbstractPermissionActivity {
if (isPermissionGranted()) {
init(intent, rootView, savedInstanceState);
}
-
+ registerScreenReceiver();
// DRM validation
// Uri original = intent.getData();
// String mimeType = intent.getType();
@@ -584,7 +586,6 @@ public class MovieActivity extends AbstractPermissionActivity {
mPlayer.requestAudioFocus();
super.onStart();
mMovieHooker.onStart();
- registerScreenReceiver();
}
@Override
@@ -600,7 +601,6 @@ public class MovieActivity extends AbstractPermissionActivity {
mControlResumed = false;
}
mMovieHooker.onStop();
- unregisterScreenReceiver();
}
@Override
@@ -687,6 +687,7 @@ public class MovieActivity extends AbstractPermissionActivity {
mPlayer.onDestroy();
super.onDestroy();
mMovieHooker.onDestroy();
+ unregisterScreenReceiver();
}
@Override
diff --git a/src/com/android/gallery3d/app/MoviePlayer.java b/src/com/android/gallery3d/app/MoviePlayer.java
index 162c0731c..5477a145f 100644
--- a/src/com/android/gallery3d/app/MoviePlayer.java
+++ b/src/com/android/gallery3d/app/MoviePlayer.java
@@ -100,7 +100,6 @@ public class MoviePlayer implements
private static final String KEY_VIDEO_STATE = "video_state";
private static final String VIRTUALIZE_EXTRA = "virtualize";
- private static final long BLACK_TIMEOUT = 500;
public static final int SERVER_TIMEOUT = 8801;
// If we resume the acitivty with in RESUMEABLE_TIMEOUT, we will keep playing.
@@ -115,6 +114,7 @@ public class MoviePlayer implements
private Context mContext;
private final CodeauroraVideoView mVideoView;
+ private final View mCoverView;
private final View mRootView;
private final Bookmarker mBookmarker;
private final Handler mHandler = new Handler();
@@ -194,16 +194,6 @@ public class MoviePlayer implements
}
};
- private Runnable mDelayVideoRunnable = new Runnable() {
- @Override
- public void run() {
- if (LOG) {
- Log.v(TAG, "mDelayVideoRunnable.run()");
- }
- mVideoView.setVisibility(View.VISIBLE);
- }
- };
-
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -227,6 +217,7 @@ public class MoviePlayer implements
mContext = movieActivity.getApplicationContext();
mRootView = rootView;
mVideoView = (CodeauroraVideoView) rootView.findViewById(R.id.surface_view);
+ mCoverView = rootView.findViewById(R.id.surface_view_cover);
mBookmarker = new Bookmarker(movieActivity);
mController = new MovieControllerOverlayNew(movieActivity);
@@ -279,18 +270,6 @@ public class MoviePlayer implements
}
});
- // The SurfaceView is transparent before drawing the first frame.
- // This makes the UI flashing when open a video. (black -> old screen
- // -> video) However, we have no way to know the timing of the first
- // frame. So, we hide the VideoView for a while to make sure the
- // video has been drawn on it.
- mVideoView.postDelayed(new Runnable() {
- @Override
- public void run() {
- mVideoView.setVisibility(View.VISIBLE);
- }
- }, BLACK_TIMEOUT);
-
setOnSystemUiVisibilityChangeListener();
// Hide system UI by default
showSystemUi(false);
@@ -506,10 +485,6 @@ public class MoviePlayer implements
public void onResume() {
mDragging = false;// clear drag info
if (mHasPaused) {
- //M: same as launch case to delay transparent.
- mVideoView.removeCallbacks(mDelayVideoRunnable);
- mVideoView.postDelayed(mDelayVideoRunnable, BLACK_TIMEOUT);
-
if (mServerTimeoutExt.handleOnResume() || mIsShowResumingDialog) {
mHasPaused = false;
return;
@@ -815,6 +790,7 @@ public class MoviePlayer implements
if (LOG) {
Log.v(TAG, "onPrepared(" + mp + ")");
}
+ mCoverView.setVisibility(View.GONE);
if (!isLocalFile()) {
mOverlayExt.setPlayingInfo(isLiveStreaming());
}
diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java
index 161d729da..a665b1427 100755
--- a/src/com/android/gallery3d/app/PhotoPage.java
+++ b/src/com/android/gallery3d/app/PhotoPage.java
@@ -30,6 +30,7 @@ import android.net.Uri;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateBeamUrisCallback;
import android.nfc.NfcEvent;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -47,6 +48,8 @@ import android.widget.Toast;
import android.widget.Toolbar;
import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.app.dualcam3d.ThreeDimensionalActivity;
import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.data.ComboAlbum;
import com.android.gallery3d.data.DataManager;
@@ -64,6 +67,9 @@ import com.android.gallery3d.data.SnailAlbum;
import com.android.gallery3d.data.SnailItem;
import com.android.gallery3d.data.SnailSource;
import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+import com.android.gallery3d.mpo.MpoParser;
import com.android.gallery3d.ui.DetailsHelper;
import com.android.gallery3d.ui.DetailsHelper.CloseListener;
import com.android.gallery3d.ui.DetailsHelper.DetailsSource;
@@ -83,7 +89,7 @@ import java.util.Locale;
public abstract class PhotoPage extends ActivityState implements
PhotoView.Listener, AppBridge.Server, ShareActionProvider.OnShareTargetSelectedListener,
- PhotoPageBottomControls.Delegate {
+ PhotoPageBottomControls.Delegate, ThreeDButton.Delegate{
private static final String TAG = "PhotoPage";
private static final int MSG_HIDE_BARS = 1;
@@ -111,6 +117,7 @@ public abstract class PhotoPage extends ActivityState implements
public static final String KEY_MEDIA_SET_PATH = "media-set-path";
public static final String KEY_MEDIA_ITEM_PATH = "media-item-path";
public static final String KEY_INDEX_HINT = "index-hint";
+ public static final String KEY_CURRENT_PHOTO_HINT = "currtent_photo_path";
public static final String KEY_OPEN_ANIMATION_RECT = "open-animation-rect";
public static final String KEY_APP_BRIDGE = "app-bridge";
public static final String KEY_TREAT_BACK_AS_UP = "treat-back-as-up";
@@ -208,6 +215,11 @@ public abstract class PhotoPage extends ActivityState implements
private int originalHeight = 0;
private int originalPadding = 0;
+ private ThreeDButton m3DButton;
+ private boolean bShow3DButton;
+ private LoadMpoDataTask mLoadMpoTask = new LoadMpoDataTask();;
+ private ParseMpoDataTask mParseMpoDateTask = new ParseMpoDataTask();
+
private final PanoramaSupportCallback mUpdatePanoramaMenuItemsCallback = new PanoramaSupportCallback() {
@Override
public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama,
@@ -302,6 +314,9 @@ public abstract class PhotoPage extends ActivityState implements
mIsPanorama = message.arg1 == 1;
mIsPanorama360 = message.arg2 == 1;
mBottomControls.refresh();
+ if (null != m3DButton) {
+ m3DButton.refresh();
+ }
}
break;
}
@@ -421,6 +436,12 @@ public abstract class PhotoPage extends ActivityState implements
//we only save index in onSaveState, set itemPath to null to get the right path later
itemPath = null;
}
+ if ((mCurrentPhoto == null) && (restoreState != null)) {
+ String curPath = restoreState.getString(KEY_CURRENT_PHOTO_HINT, null);
+ if (curPath != null)
+ mCurrentPhoto = (MediaItem)
+ mActivity.getDataManager().getMediaObject(curPath);
+ }
if (mSetPathString != null) {
mShowSpinner = true;
mAppBridge = (AppBridge) data.getParcelable(KEY_APP_BRIDGE);
@@ -591,6 +612,7 @@ public abstract class PhotoPage extends ActivityState implements
if (galleryRoot != null) {
if (mSecureAlbum == null) {
mBottomControls = new PhotoPageBottomControls(this, mActivity, galleryRoot);
+ m3DButton = new ThreeDButton(this, mActivity, galleryRoot);
}
}
@@ -611,6 +633,7 @@ public abstract class PhotoPage extends ActivityState implements
@Override
protected void onSaveState(Bundle outState) {
outState.putInt(KEY_INDEX_HINT,mCurrentIndex);
+ outState.putString(KEY_CURRENT_PHOTO_HINT, mCurrentPhoto.getFilePath());
super.onSaveState(outState);
}
@@ -662,6 +685,7 @@ public abstract class PhotoPage extends ActivityState implements
case R.id.photopage_bottom_control_share:
if (mModel != null && mModel.getMediaItem(0) != null) {
Uri uri = mActivity.getDataManager().getContentUri(mModel.getMediaItem(0).getPath());
+ mActivity.isTopMenuShow = true;
mShareIntent.setType(MenuExecutor.getMimeType(mModel
.getMediaItem(0).getMediaType()));
mShareIntent.putExtra(Intent.EXTRA_STREAM, uri);
@@ -690,6 +714,24 @@ public abstract class PhotoPage extends ActivityState implements
}
}
+ @Override
+ public boolean canDisplay3DButton() {
+ return bShow3DButton && mShowBars
+ && (mPhotoView == null ? false : !mPhotoView.getFilmMode());
+ }
+
+ @Override
+ public void on3DButtonClicked() {
+ if (mCurrentPhoto != null) {
+ Path p = mCurrentPhoto.getPath();
+ Uri uri = mActivity.getDataManager().getContentUri(p);
+ Intent intent = new Intent();
+ intent.setClass(mActivity, ThreeDimensionalActivity.class);
+ intent.setData(uri);
+ mActivity.startActivity(intent);
+ }
+ }
+
@TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
private void setupNfcBeamPush() {
if (!ApiHelper.HAS_SET_BEAM_PUSH_URIS) return;
@@ -828,6 +870,7 @@ public abstract class PhotoPage extends ActivityState implements
updateMenuOperations();
refreshBottomControlsWhenReady();
+ parseMpoData();
if (mShowDetails) {
mDetailsHelper.reloadDetails();
}
@@ -840,6 +883,9 @@ public abstract class PhotoPage extends ActivityState implements
private void updateCurrentPhoto(MediaItem photo) {
if (mCurrentPhoto == photo) return;
mCurrentPhoto = photo;
+ if (mPhotoView == null) {
+ return;
+ }
if (mPhotoView.getFilmMode()) {
requestDeferredUpdate();
} else {
@@ -934,7 +980,7 @@ public abstract class PhotoPage extends ActivityState implements
private void refreshHidingMessage() {
mHandler.removeMessages(MSG_HIDE_BARS);
if (mPhotoView == null) {
- mPhotoView = (PhotoView) mRootPane.getComponent(0);
+ return;
}
if (!mIsMenuVisible && !mPhotoView.getFilmMode()) {
mHandler.sendEmptyMessageDelayed(MSG_HIDE_BARS, HIDE_BARS_TIMEOUT);
@@ -1419,6 +1465,7 @@ public abstract class PhotoPage extends ActivityState implements
}
if (null != mModel) {
mModel.setCurrentPhoto(path, mCurrentIndex);
+ parseMpoData();
}
}
}
@@ -1464,11 +1511,23 @@ public abstract class PhotoPage extends ActivityState implements
}
if (path != null) {
mModel.setCurrentPhoto(Path.fromString(path), index);
+ parseMpoData();
}
}
}
}
+ private void parseMpoData() {
+ bShow3DButton = false;
+ if (DualCameraNativeEngine.getInstance().isLibLoaded()) {
+ if (mParseMpoDateTask.getStatus() != AsyncTask.Status.FINISHED) {
+ boolean r = mParseMpoDateTask.cancel(true);
+ }
+ mParseMpoDateTask = new ParseMpoDataTask();
+ mParseMpoDateTask.execute();
+ }
+ }
+
@Override
public void onPause() {
super.onPause();
@@ -1663,6 +1722,7 @@ public abstract class PhotoPage extends ActivityState implements
}
mActivity.getGLRoot().setOrientationSource(null);
if (mBottomControls != null) mBottomControls.cleanup();
+ if (m3DButton != null) m3DButton.cleanup();
mPhotoView.destroy();
mPhotoView = null;
// Remove all pending messages.
@@ -1761,4 +1821,60 @@ public abstract class PhotoPage extends ActivityState implements
}
}
+ public class ParseMpoDataTask extends AsyncTask<Void, Void, Void> {
+ private byte[] mPrimaryImgData = null;
+ private byte[] mAuxImgData = null;
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ if (mCurrentPhoto == null)return null;
+ MpoParser parser = MpoParser.parse(mActivity, mCurrentPhoto.getContentUri());
+ mPrimaryImgData = parser.readImgData(true);
+ mAuxImgData = parser.readImgData(false);
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ if (isCancelled()){
+ bShow3DButton = false;
+ m3DButton.refresh();
+ return;
+ }
+ if(mPrimaryImgData == null ||
+ mAuxImgData == null) {
+ // parse failed
+ bShow3DButton = false;
+ } else {
+ if (mLoadMpoTask.getStatus() != Status.FINISHED) {
+ boolean r = mLoadMpoTask.cancel(true);
+ }
+ bShow3DButton = true;
+ mLoadMpoTask = new LoadMpoDataTask();
+ mLoadMpoTask.execute(mPrimaryImgData, mAuxImgData);
+ }
+ m3DButton.refresh();
+ }
+ }
+
+ private class LoadMpoDataTask extends AsyncTask<byte[], Void, Boolean> {
+
+ @Override
+ protected Boolean doInBackground(byte[]... params) {
+ return MasterImage.getImage().loadMpo(mActivity, params[0], params[1], mCurrentPhoto.getContentUri());
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ if (isCancelled()){
+ bShow3DButton = false;
+ m3DButton.refresh();
+ return;
+ }
+ if (!result) {
+ bShow3DButton = result;
+ m3DButton.refresh();
+ }
+ }
+ }
}
diff --git a/src/com/android/gallery3d/app/ThreeDButton.java b/src/com/android/gallery3d/app/ThreeDButton.java
new file mode 100644
index 000000000..4cc146ab9
--- /dev/null
+++ b/src/com/android/gallery3d/app/ThreeDButton.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.app;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.widget.RelativeLayout;
+
+import org.codeaurora.gallery.R;
+
+public class ThreeDButton implements OnClickListener {
+ interface Delegate {
+ boolean canDisplay3DButton();
+
+ void on3DButtonClicked();
+ }
+
+ private Delegate mDelegate;
+ private ViewGroup root;
+ private ViewGroup mContainer;
+ private boolean mContainerVisible = false;
+
+ private Animation mAnimIn = new AlphaAnimation(0f, 1f);
+ private Animation mAnimOut = new AlphaAnimation(1f, 0f);
+ private static final int ANIM_DURATION = 200;
+
+ public ThreeDButton(Delegate delegate, Context context, RelativeLayout layout) {
+ mDelegate = delegate;
+ root = layout;
+ LayoutInflater inflater = (LayoutInflater) context
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mContainer = (ViewGroup) inflater
+ .inflate(R.layout.three_d_button, root, false);
+ mContainer.findViewById(R.id.three_dimensional).setOnClickListener(this);
+ root.addView(mContainer);
+ mAnimIn.setDuration(ANIM_DURATION);
+ mAnimOut.setDuration(ANIM_DURATION);
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (mContainer.getVisibility() == View.VISIBLE) {
+ mDelegate.on3DButtonClicked();
+ }
+ }
+
+ public void refresh() {
+ boolean visible = mDelegate.canDisplay3DButton();
+ if (visible != mContainerVisible) {
+ if (visible) {
+ show();
+ } else {
+ hide();
+ }
+ mContainerVisible = visible;
+ }
+ }
+
+ private void hide() {
+ mContainer.clearAnimation();
+ mAnimOut.reset();
+ mContainer.startAnimation(mAnimOut);
+ mContainer.setVisibility(View.GONE);
+ }
+
+ private void show() {
+ mContainer.clearAnimation();
+ mAnimIn.reset();
+ mContainer.startAnimation(mAnimIn);
+ mContainer.setVisibility(View.VISIBLE);
+ }
+
+ public void cleanup() {
+ root.removeView(mContainer);
+ }
+
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/Effect.java b/src/com/android/gallery3d/app/dualcam3d/Effect.java
new file mode 100644
index 000000000..0f9cde4cb
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/Effect.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.app.dualcam3d;
+
+import android.graphics.Bitmap;
+import android.util.Log;
+
+import com.android.gallery3d.app.dualcam3d.threed.Controller;
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+
+public class Effect implements GLView.Listener {
+ private static final String TAG = "Effect";
+ public static final int INTENSITY_MAX = 10;
+ public static final float DEFAULT_BRIGHTNESS_INTENSITY = 1.0f;
+ private static final int PREVIEW_DIMENSION_MAX = 1080;
+
+ enum Type {
+ NONE, FOCUS, HALO, SKETCH, FUSION, ZOOM,
+ MOTION, BW, BLACKBOARD, WHITEBOARD,
+ POSTERIZE, NEGATIVE, THREE_DIMENSIONAL
+ }
+
+ private final ThreeDimensionalActivity mActivity;
+ private Bitmap mBitmap;
+ private Type mType = Type.NONE;
+ private int mX;
+ private int mY;
+ private float mIntensity = 0.5f;
+ private boolean mIsPreview = true;
+
+ private int mScale;
+
+ private Controller mController;
+
+ private Thread mThread;
+ private Boolean mCancelled;
+
+ public Effect(ThreeDimensionalActivity activity) {
+ mActivity = activity;
+ }
+
+ public void setBitmap(Bitmap bitmap, int scale) {
+ mBitmap = bitmap;
+ scaleBitmap(scale);
+ }
+
+ public static int scale(int width, int height) {
+ int scale = 1;
+ while (width / scale > PREVIEW_DIMENSION_MAX || height / scale > PREVIEW_DIMENSION_MAX) {
+ scale *= 2;
+ }
+ return scale > 1 ? scale : 1;
+ }
+
+ private void scaleBitmap(int scale) {
+ if (scale != 1) {
+ mScale = scale;
+ } else if (mBitmap != null) {
+ int width = mBitmap.getWidth(), height = mBitmap.getHeight();
+ mX = width / 2;
+ mY = height / 2;
+ mScale = scale(width, height);
+ if (mScale != 1) {
+ mBitmap = Bitmap.createScaledBitmap(mBitmap,
+ width / mScale, height / mScale, false);
+ }
+ }
+ mActivity.sendMessage(ThreeDimensionalActivity.MSG_UPDATE_IMAGE, mBitmap);
+ }
+
+ public void set(Type type) {
+ if (type == Type.THREE_DIMENSIONAL) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ DualCameraNativeEngine.DepthMap3D map = DualCameraNativeEngine.getInstance()
+ .getDepthMap3D(mBitmap);
+ if (map != null) {
+ Log.d(TAG, "got 3d map");
+ mActivity.sendMessage(ThreeDimensionalActivity.MSG_UPDATE_IMAGE, mBitmap);
+ mActivity.sendMessage(ThreeDimensionalActivity.MSG_UPDATE_3D_DEPTH_MAP, map);
+ } else {
+ Log.e(TAG, "cannot get 3d map");
+ }
+ }
+ }).start();
+ if (mController == null) {
+ mController = mActivity.getController();
+ }
+ mController.start();
+ } else {
+ if (mController != null) {
+ mController.stop(true);
+ }
+ mActivity.sendMessage(ThreeDimensionalActivity.MSG_UPDATE_3D_DEPTH_MAP, null);
+ request();
+ }
+ mType = type;
+ }
+
+ private void setCoordination(float x, float y) {
+ if (x >= 0 && y >= 0 && x < mBitmap.getWidth() && y < mBitmap.getHeight()) {
+ mX = (int) (x * mScale);
+ mY = (int) (y * mScale);
+ }
+ }
+
+ public void setIntensity(float intensity) {
+ if (intensity < 0) intensity = 0;
+ if (intensity > INTENSITY_MAX) intensity = 1;
+ if (intensity != mIntensity) {
+ mIntensity = intensity / INTENSITY_MAX;
+ request();
+ }
+ }
+
+ private synchronized void request() {
+ notify();
+ }
+
+
+ public void recycle() {
+ if (mBitmap != null) {
+ mBitmap.recycle();
+ }
+ }
+
+ @Override
+ public void onMove(float deltaX, float deltaY) {
+ if (mType == Type.THREE_DIMENSIONAL && mController != null) {
+ mController.onMove(deltaX, deltaY);
+ }
+ }
+
+ @Override
+ public void onClick(float x, float y) {
+ if (mType != Type.THREE_DIMENSIONAL) {
+ setCoordination(x, y);
+ request();
+ }
+ }
+
+ @Override
+ public void onLayout(int width, int height) {
+ }
+
+ public void resume() {
+ if (mController != null && mType == Type.THREE_DIMENSIONAL) {
+ mController.start();
+ }
+ mCancelled = false;
+ mThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ while (!mCancelled) {
+ synchronized (Effect.this) {
+ try {
+ Effect.this.wait();
+ } catch (InterruptedException ignored) {
+ }
+ }
+ }
+ }
+ });
+ mThread.start();
+ }
+
+ public void pause() {
+ if (mController != null) {
+ mController.stop(false);
+ }
+ if (mThread != null) {
+ mCancelled = true;
+ synchronized (this) {
+ notify();
+ }
+ try {
+ mThread.join();
+ } catch (InterruptedException ignored) {
+ }
+ mThread = null;
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/GLView.java b/src/com/android/gallery3d/app/dualcam3d/GLView.java
new file mode 100644
index 000000000..181d3e095
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/GLView.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.app.dualcam3d;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Matrix;
+import android.graphics.PointF;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.Surface;
+
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+
+public class GLView extends GLSurfaceView {
+ private static final String TAG = "GLView";
+ private final com.android.gallery3d.app.dualcam3d.gl.Renderer mRenderer;
+
+ private Bitmap mBitmap;
+ private DualCameraNativeEngine.DepthMap3D mDepthMap;
+ private int mRotation;
+
+ public GLView(Context context) {
+ this(context, null);
+ }
+
+ public GLView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setEGLContextClientVersion(2);
+ mRenderer = new com.android.gallery3d.app.dualcam3d.gl.Renderer();
+ setRenderer(mRenderer);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
+ mRenderer.setImageBitmap(mBitmap);
+ mRenderer.set3DEffectDepthMap(mDepthMap);
+ requestRender();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mRenderer.setImageBitmap(null);
+ mRenderer.set3DEffectDepthMap(null);
+ }
+
+ public void setImageBitmap(Bitmap bitmap) {
+ mBitmap = bitmap;
+ mRenderer.setImageBitmap(bitmap);
+ mRenderer.set3DEffectDepthMap(null);
+ requestRender();
+ }
+
+ public void set3DEffectDepthMap(DualCameraNativeEngine.DepthMap3D map) {
+ mDepthMap = map;
+ mRenderer.set3DEffectDepthMap(map);
+ requestRender();
+ }
+
+ public void setOffset(float x, float y) {
+ mRenderer.setOffset(x, y);
+ requestRender();
+ }
+
+ public void setOffsetWithRotation(float x, float y) {
+ if (mRotation == Surface.ROTATION_0 || mRotation == Surface.ROTATION_180) {
+ //noinspection SuspiciousNameCombination
+ setOffset(y, x);
+ } else {
+ setOffset(x, y);
+ }
+ }
+
+ public void setOffsetDelta(float deltaX, float deltaY) {
+ mRenderer.setOffsetDelta(deltaX, deltaY);
+ requestRender();
+ }
+
+ public void recycle() {
+ mListener = null;
+ if (mBitmap != null) {
+ mBitmap.recycle();
+ mBitmap = null;
+ }
+ }
+
+ public void setRotation(int rotation) {
+ mRotation = rotation;
+ }
+
+ private static final float MOVE_THRESHOLD = 1.0f;
+ private PointF mLastPoint;
+ private int mLastAction = MotionEvent.ACTION_DOWN;
+ private Listener mListener;
+
+ public interface Listener {
+ void onMove(float deltaX, float deltaY);
+
+ void onClick(float x, float y);
+
+ void onLayout(int width, int height);
+ }
+
+ public void setListener(Listener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ Matrix invertMatrix = mRenderer.getImageInvertMatrix();
+ if (invertMatrix == null) {
+ return true;
+ }
+
+ float[] point = new float[]{event.getX(), event.getY()};
+ invertMatrix.mapPoints(point);
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mLastPoint = new PointF(point[0], point[1]);
+ mLastAction = MotionEvent.ACTION_DOWN;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (mLastPoint != null) {
+ float deltaX = point[0] - mLastPoint.x,
+ deltaY = point[1] - mLastPoint.y;
+ if (mLastAction == MotionEvent.ACTION_MOVE || (Math.abs(deltaX) > MOVE_THRESHOLD
+ && Math.abs(deltaY) > MOVE_THRESHOLD)) {
+ if (mListener != null) {
+ mListener.onMove(deltaX, deltaY);
+ }
+ mLastPoint.set(point[0], point[1]);
+ mLastAction = MotionEvent.ACTION_MOVE;
+ }
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ if (mLastAction != MotionEvent.ACTION_MOVE && mListener != null) {
+ mListener.onClick(point[0], point[1]);
+ }
+ mLastPoint = null;
+ mLastAction = MotionEvent.ACTION_UP;
+ break;
+ }
+ return true;
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ if (changed && mListener != null) {
+ mListener.onLayout(right - left, bottom - top);
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/ThreeDimensionalActivity.java b/src/com/android/gallery3d/app/dualcam3d/ThreeDimensionalActivity.java
new file mode 100644
index 000000000..18fe36394
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/ThreeDimensionalActivity.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+package com.android.gallery3d.app.dualcam3d;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.Window;
+import android.widget.LinearLayout;
+
+import com.android.gallery3d.app.dualcam3d.mpo.Task;
+import com.android.gallery3d.app.dualcam3d.threed.Controller;
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+
+import org.codeaurora.gallery.R;
+
+public class ThreeDimensionalActivity extends Activity {
+ private static final String TAG = ThreeDimensionalActivity.class.getSimpleName();
+
+ final static int MSG_UPDATE_IMAGE = 1;
+ final static int MSG_UPDATE_3D_DEPTH_MAP = 2;
+ private final static int MSG_IMAGE_LOADED = 3;
+ private final static int MSG_FINISH = 4;
+
+ private Effect mEffect;
+ private GLView mImageView;
+ private Task mTask;
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE_IMAGE:
+ if (mImageView != null) {
+ mImageView.setImageBitmap((Bitmap) msg.obj);
+ }
+ break;
+ case MSG_UPDATE_3D_DEPTH_MAP:
+ if (mImageView != null) {
+ mImageView.set3DEffectDepthMap((DualCameraNativeEngine.DepthMap3D) msg.obj);
+ }
+ break;
+ case MSG_IMAGE_LOADED:
+ mEffect.setBitmap((Bitmap) msg.obj, msg.arg1);
+ break;
+ case MSG_FINISH:
+ mEffect.set(Effect.Type.THREE_DIMENSIONAL);
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ Log.d(TAG, "onCreate");
+ super.onCreate(savedInstanceState);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ setContentView(R.layout.activity_three_dimensional);
+
+ mEffect = new Effect(this);
+ processIntent();
+ init();
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ }
+
+
+ private void init() {
+ mImageView = (GLView) findViewById(R.id.image);
+ mImageView.setListener(mEffect);
+ mImageView.setRotation(getWindowManager().getDefaultDisplay().getRotation());
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mImageView.onResume();
+ if (mEffect != null) {
+ mEffect.resume();
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mImageView.onPause();
+ if (mEffect != null) {
+ mEffect.pause();
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ if (DualCameraNativeEngine.getInstance().isLibLoaded()) {
+ DualCameraNativeEngine.getInstance().releaseDepthMap();
+ }
+ if (mEffect != null) {
+ mEffect.recycle();
+ mEffect = null;
+ }
+ mImageView.recycle();
+ mTask.cancel();
+ super.onDestroy();
+ }
+
+ private void processIntent() {
+ Intent intent = getIntent();
+ Uri uri = intent.getData();
+ if (uri == null) {
+ finish();
+ return;
+ }
+ startLoadImage(uri);
+ }
+
+ private void startLoadImage(Uri uri) {
+ if (DualCameraNativeEngine.getInstance().isLibLoaded()) {
+ mTask = new Task(this, uri, new Task.Listener() {
+ @Override
+ public void onBitmapLoaded(Bitmap bitmap, int scale) {
+ if (bitmap != null) {
+ mHandler.obtainMessage(MSG_IMAGE_LOADED, scale, 0, bitmap).sendToTarget();
+ } else {
+ finish();
+ }
+ }
+
+ @Override
+ public int onScale(int width, int height) {
+ return Effect.scale(width, height);
+ }
+
+ @Override
+ public void onFinish(boolean result) {
+ if (!result) {
+ finish();
+ } else {
+ sendMessage(MSG_FINISH, null);
+ }
+ }
+ });
+ mTask.start(Effect.DEFAULT_BRIGHTNESS_INTENSITY);
+ }
+ }
+
+ public void sendMessage(int what, Object obj) {
+ mHandler.obtainMessage(what, obj).sendToTarget();
+ }
+
+ public Controller getController() {
+ return new Controller(mImageView, (LinearLayout) findViewById(R.id.mode_3d));
+ }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Error.java b/src/com/android/gallery3d/app/dualcam3d/gl/Error.java
new file mode 100644
index 000000000..55f04dd32
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Error.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+package com.android.gallery3d.app.dualcam3d.gl;
+
+import android.opengl.GLES20;
+import android.util.Log;
+
+class Error {
+ private static final String TAG = "GL";
+
+ public static void check() {
+ int error = GLES20.glGetError();
+ if (error != 0) {
+ Throwable t = new Throwable();
+ Log.e(TAG, "error: " + error, t);
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Mesh.java b/src/com/android/gallery3d/app/dualcam3d/gl/Mesh.java
new file mode 100644
index 000000000..72d29ad9a
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Mesh.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+package com.android.gallery3d.app.dualcam3d.gl;
+
+import android.opengl.GLES20;
+
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+class Mesh {
+ private static final String TAG = "Mesh";
+
+ private static final float TAN_HALF_FOV =
+ (float) Math.tan(Math.toRadians(Settings.FIELD_OF_VIEW / 2));
+
+ public FloatBuffer vertices;
+ public FloatBuffer colors;
+ public FloatBuffer textures;
+ private IntBuffer indices;
+
+ private int indexLength;
+
+ public void render(Shader shader) {
+ if (vertices == null || textures == null || indices == null || indices.capacity() == 0)
+ return;
+ shader.setMesh(this);
+ GLES20.glDrawElements(GLES20.GL_TRIANGLES, indexLength, GLES20.GL_UNSIGNED_INT, indices);
+ }
+
+ private void rewindBuffers() {
+ vertices.position(0);
+ colors.position(0);
+ textures.position(0);
+ indices.position(0);
+ }
+
+ private static ByteBuffer allocateBuffer(int capacity) {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(capacity);
+ buffer.order(ByteOrder.nativeOrder());
+ return buffer;
+ }
+
+ public static Mesh create() {
+ Mesh m = new Mesh();
+
+ final int resolutionH = Settings.MESH_RESOLUTION_H;
+ final int resolutionV = Settings.MESH_RESOLUTION_V;
+ final int vertexCount = (resolutionH + 1) * (resolutionV + 1);
+ final int indexCount = resolutionH * resolutionV * 2;
+
+ m.vertices = allocateBuffer(vertexCount * 3 * 4).asFloatBuffer();
+ m.colors = allocateBuffer(vertexCount * 4 * 4).asFloatBuffer();
+ m.textures = allocateBuffer(vertexCount * 2 * 4).asFloatBuffer();
+ m.indices = allocateBuffer(indexCount * 3 * 4).asIntBuffer();
+ m.indexLength = indexCount * 3;
+
+ m.rewindBuffers();
+ return m;
+ }
+
+ private static float getVertexScale(float depth) {
+ return ((depth + Settings.CAMERA_POSITION) * TAN_HALF_FOV);
+ }
+
+ public void update(DualCameraNativeEngine.DepthMap3D depthMap, int width, int height,
+ float depth) {
+ final int resolutionH = depthMap == null ? 1 : Settings.MESH_RESOLUTION_H;
+ final int resolutionV = depthMap == null ? 1 : Settings.MESH_RESOLUTION_V;
+ indexLength = resolutionH * resolutionV * 2 * 3;
+
+ // / Correct aspect ratio of the rendered image, fit width
+ float scale = getVertexScale(Math.abs(depth));
+ if (depthMap != null) scale *= Settings.ENLARGE_IMAGE;
+ float sizeV = scale * height / width;
+
+ rewindBuffers();
+
+ for (int v = 0; v <= resolutionV; ++v) {
+ float vV = v / (float) resolutionV;
+ float v2 = sizeV - 2 * sizeV * vV;
+ int y = (int) (vV * (height - 1));
+ for (int h = 0; h <= resolutionH; ++h) {
+ float vH = h / (float) resolutionH;
+
+ int depthValue = 0;
+ if (depthMap != null) {
+ int x = (int) (vH * (width - 1));
+ depthValue = depthMap.pixels[y * depthMap.width + x];
+ }
+ vertices.put(-scale + 2 * scale * vH);
+ vertices.put(v2);
+ vertices.put(depthValue * Settings.DEPTH_RATIO);
+
+ colors.put(1f);
+ colors.put(1f);
+ colors.put(1f);
+ colors.put(1f);
+
+ textures.put(vH);
+ textures.put(vV);
+ }
+ }
+
+ for (int v = 0; v < resolutionV; ++v) {
+ for (int h = 0; h < resolutionH; ++h) {
+ int index = v * (resolutionH + 1) + h;
+
+ indices.put(index);
+ indices.put(index + (resolutionH + 1));
+ indices.put(index + 1);
+
+ indices.put(index + (resolutionH + 1));
+ indices.put(index + 1 + (resolutionH + 1));
+ indices.put(index + 1);
+ }
+ }
+ rewindBuffers();
+ }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Renderer.java b/src/com/android/gallery3d/app/dualcam3d/gl/Renderer.java
new file mode 100644
index 000000000..c2795f93d
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Renderer.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+package com.android.gallery3d.app.dualcam3d.gl;
+
+import android.graphics.Bitmap;
+import android.graphics.RectF;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+import android.opengl.Matrix;
+import android.util.Log;
+
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+public class Renderer implements GLSurfaceView.Renderer {
+ private static final String TAG = "Renderer";
+ public static final float THETA_MAX = (float) Math.toRadians(6);
+ private final float[] mProjectionMatrix = new float[16];
+
+ private float mOffsetX;
+ private float mOffsetY;
+
+ private Bitmap mImageBitmap;
+ private DualCameraNativeEngine.DepthMap3D mDepthMap;
+
+ private boolean mImageChanged;
+ private boolean mDepthMapChanged;
+
+ private RectF mSurfaceRect;
+ private android.graphics.Matrix mImageInvertMatrix;
+
+ private final Mesh mMesh = Mesh.create();
+ private Shader mShader;
+ private final Texture mImageTexture = new Texture();
+
+ public Renderer() {
+ }
+
+ public void setImageBitmap(Bitmap bitmap) {
+ mImageBitmap = bitmap;
+ mImageChanged = true;
+ mDepthMap = null;
+ mDepthMapChanged = true;
+ setImageInvertMatrix();
+ }
+
+ public void set3DEffectDepthMap(DualCameraNativeEngine.DepthMap3D map) {
+ mDepthMap = map;
+ mDepthMapChanged = true;
+ if (map == null) {
+ mOffsetX = 0;
+ mOffsetY = 0;
+ }
+ }
+
+ @Override
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ mShader = new Shader();
+ mShader.bind();
+ GLES20.glEnable(GLES20.GL_DEPTH_TEST);
+ GLES20.glEnable(GLES20.GL_BLEND);
+ GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ @Override
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ Log.d(TAG, "w=" + width + "x" + height);
+ float ratio = (float) width / height;
+ float sinY = (float) Math.sin(Math.toRadians(Settings.FIELD_OF_VIEW / 2)) / ratio;
+ float cosY = (float) Math.cos(Math.toRadians(Settings.FIELD_OF_VIEW / 2));
+ float fovY = (float) Math.toDegrees(Math.atan2(sinY, cosY) * 2.f);
+ Matrix.perspectiveM(mProjectionMatrix, 0, fovY, ratio, 0.1f, 500.f);
+ GLES20.glViewport(0, 0, width, height);
+ mSurfaceRect = new RectF(0, 0, width, height);
+ setImageInvertMatrix();
+ }
+
+ private void updateImage() {
+ if (mImageChanged) {
+ mImageTexture.upload(mImageBitmap);
+ mImageTexture.bind();
+ mImageChanged = false;
+ }
+ if (mDepthMapChanged) {
+ int width = mDepthMap == null ? mImageBitmap.getWidth() : mDepthMap.width;
+ int height = mDepthMap == null ? mImageBitmap.getHeight() : mDepthMap.height;
+ mMesh.update(mDepthMap, width, height, Settings.FOREGROUND_POSITION);
+ mDepthMapChanged = false;
+ }
+ }
+
+ private void updateMatrix() {
+ float x = (float) (Math.sin(mOffsetX) * Math.cos(mOffsetY)) * Settings.CAMERA_POSITION;
+ float y = (float) (Math.sin(mOffsetY)) * Settings.CAMERA_POSITION;
+ float z = (float) (Math.cos(mOffsetX) * Math.cos(mOffsetY)) * Settings.CAMERA_POSITION;
+
+ float[] viewMatrix = new float[16];
+ Matrix.setLookAtM(viewMatrix, 0, x, y, z, 0f, 0f, Settings.FOREGROUND_POSITION,
+ 0f, 1f, 0f);
+ float[] matrix = new float[16];
+ Matrix.multiplyMM(matrix, 0, mProjectionMatrix, 0, viewMatrix, 0);
+ mShader.setMatrix(matrix);
+ }
+
+ @Override
+ public void onDrawFrame(GL10 gl) {
+ if (mImageBitmap == null) {
+ return;
+ }
+
+ updateImage();
+ updateMatrix();
+
+ GLES20.glClearColor(0, 0, 0, 0);
+ GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
+ mMesh.render(mShader);
+ }
+
+ public void setOffset(float x, float y) {
+ mOffsetX = limit(x);
+ mOffsetY = limit(y);
+ }
+
+ public void setOffsetDelta(float deltaX, float deltaY) {
+ mOffsetX = limit(mOffsetX + deltaX);
+ mOffsetY = limit(mOffsetY + deltaY);
+ }
+
+ private float limit(float theta) {
+ if (theta < -THETA_MAX) return -THETA_MAX;
+ if (theta > THETA_MAX) return THETA_MAX;
+ return theta;
+ }
+
+ public android.graphics.Matrix getImageInvertMatrix() {
+ return mImageInvertMatrix;
+ }
+
+ private void setImageInvertMatrix() {
+ if (mImageBitmap != null && mSurfaceRect != null) {
+ RectF rect = new RectF(0, 0, mImageBitmap.getWidth(), mImageBitmap.getHeight());
+ if (mImageInvertMatrix == null) {
+ mImageInvertMatrix = new android.graphics.Matrix();
+ }
+ android.graphics.Matrix matrix = new android.graphics.Matrix();
+ matrix.setRectToRect(rect, mSurfaceRect, android.graphics.Matrix.ScaleToFit.CENTER);
+ matrix.invert(mImageInvertMatrix);
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Settings.java b/src/com/android/gallery3d/app/dualcam3d/gl/Settings.java
new file mode 100644
index 000000000..5321fdfc5
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Settings.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+package com.android.gallery3d.app.dualcam3d.gl;
+
+class Settings {
+ // Number of horizontal subdivisions (horizontal resolution)
+ static final int MESH_RESOLUTION_H = 300;
+ // Number of vertical subdivisions (vertical resolution)
+ static final int MESH_RESOLUTION_V = 450;
+ // Field of view of the viewport (horizontal)
+ static final float FIELD_OF_VIEW = 60.0f;
+ // Distance of the viewer from the texture
+ static final float CAMERA_POSITION = 2.75f;
+ // Offset between the background and the foreground
+ static final float FOREGROUND_POSITION = 0.0f;
+
+ static final float ENLARGE_IMAGE = 1.0f;
+
+ // Some hard-coded scalar for now
+ static final float DEPTH_RATIO = 0.003f;
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Shader.java b/src/com/android/gallery3d/app/dualcam3d/gl/Shader.java
new file mode 100644
index 000000000..3641b2676
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Shader.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+package com.android.gallery3d.app.dualcam3d.gl;
+
+import android.opengl.GLES20;
+
+class Shader {
+ private static final String vertexShaderCode = //
+ "uniform mat4 uMVPMatrix;" //
+ + "attribute vec4 vPosition;" //
+ + "attribute vec2 vTexCoord;" //
+ + "attribute vec4 vColor;" //
+ + "varying vec2 texCoord;" //
+ + "varying vec4 color;" //
+ + "void main() {" //
+ + " gl_Position = uMVPMatrix * vPosition;" //
+ + " texCoord = vTexCoord;" //
+ + " color = vColor;" //
+ + "}";
+
+ private static final String fragmentShaderCode = //
+ "precision mediump float;" //
+ + "uniform vec4 vColor;" //
+ + "varying vec2 texCoord;" //
+ + "varying vec4 color;" //
+ + "uniform sampler2D texSampler2D;" //
+ + "void main() {" //
+ + " gl_FragColor = texture2D(texSampler2D, texCoord);" //
+ + " gl_FragColor.w = color.w;" //
+ + "}";
+
+ private int shaderId = -1;
+
+ public Shader() {
+ int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
+ int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
+
+ shaderId = GLES20.glCreateProgram();
+ Error.check();
+ GLES20.glAttachShader(shaderId, vertexShader);
+ Error.check();
+ GLES20.glAttachShader(shaderId, fragmentShader);
+ Error.check();
+ GLES20.glLinkProgram(shaderId);
+ Error.check();
+ }
+
+ private static int loadShader(int type, String shaderCode) {
+ int shader = GLES20.glCreateShader(type);
+ GLES20.glShaderSource(shader, shaderCode);
+ Error.check();
+ GLES20.glCompileShader(shader);
+ Error.check();
+ return shader;
+ }
+
+ public void bind() {
+ GLES20.glUseProgram(shaderId);
+ }
+
+ public void setMesh(Mesh m) {
+ int vertexHandle = GLES20.glGetAttribLocation(shaderId, "vPosition");
+ GLES20.glEnableVertexAttribArray(vertexHandle);
+ GLES20.glVertexAttribPointer(vertexHandle, 3, GLES20.GL_FLOAT, false, 12, m.vertices);
+
+ int textureHandle = GLES20.glGetAttribLocation(shaderId, "vTexCoord");
+ GLES20.glEnableVertexAttribArray(textureHandle);
+ GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false, 8, m.textures);
+
+ int colorHandle = GLES20.glGetAttribLocation(shaderId, "vColor");
+ GLES20.glEnableVertexAttribArray(colorHandle);
+ GLES20.glVertexAttribPointer(colorHandle, 4, GLES20.GL_FLOAT, true, 16, m.colors);
+ }
+
+ public void setMatrix(float[] matrix) {
+ int matrixHandle = GLES20.glGetUniformLocation(shaderId, "uMVPMatrix");
+ GLES20.glUniformMatrix4fv(matrixHandle, 1, false, matrix, 0);
+ }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Texture.java b/src/com/android/gallery3d/app/dualcam3d/gl/Texture.java
new file mode 100644
index 000000000..e93df8c43
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Texture.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+package com.android.gallery3d.app.dualcam3d.gl;
+
+import android.graphics.Bitmap;
+import android.opengl.GLES20;
+import android.opengl.GLUtils;
+
+class Texture {
+ private final int[] mId = new int[1];
+ private boolean mInitialized = false;
+
+ private void init() {
+ if (!mInitialized) {
+ GLES20.glGenTextures(1, mId, 0);
+ Error.check();
+ mInitialized = true;
+ }
+ }
+
+ public void upload(Bitmap bitmap) {
+ init();
+
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mId[0]);
+ Error.check();
+
+ GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
+ GLES20.GL_NEAREST);
+ GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
+ GLES20.GL_LINEAR);
+
+ GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
+ }
+
+ public void bind() {
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mId[0]);
+ Error.check();
+ }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/mpo/Task.java b/src/com/android/gallery3d/app/dualcam3d/mpo/Task.java
new file mode 100644
index 000000000..d449cb82d
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/mpo/Task.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.app.dualcam3d.mpo;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Point;
+import android.net.Uri;
+import android.util.Log;
+
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+import com.android.gallery3d.mpo.MpoParser;
+
+import java.io.OutputStream;
+
+public class Task {
+ private static final String TAG = "ParseMpoTask";
+
+ public interface Listener {
+ void onBitmapLoaded(Bitmap bitmap, int scale);
+
+ int onScale(int width, int height);
+
+ void onFinish(boolean result);
+ }
+
+ private final Context mContext;
+ private final Uri mUri;
+ private final Listener mListener;
+ private boolean mCancelled;
+
+ private Thread mThread1;
+ private Thread mThread2;
+
+ public Task(final Context context, final Uri uri, final Listener listener) {
+ mContext = context;
+ mUri = uri;
+ mListener = listener;
+ mCancelled = false;
+ }
+
+ public void start(final float brIntensity) {
+ mThread1 = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ boolean result = parse(brIntensity);
+ mListener.onFinish(result);
+ }
+ });
+ mThread1.start();
+ }
+
+ public void cancel() {
+ mCancelled = true;
+ try {
+ if (mThread1 != null) {
+ mThread1.join();
+ }
+ if (mThread2 != null) {
+ mThread2.join();
+ }
+ } catch (InterruptedException ignored) {
+ }
+ }
+
+ private boolean parse(final float brIntensity) {
+ final Bitmap[] bitmaps = new Bitmap[2];
+ final byte[][] data = new byte[2][];
+
+ MpoParser parser = MpoParser.parse(mContext, mUri);
+ if (mCancelled) return false;
+ final boolean primaryForDisplay = parser.isPrimaryForDisplay();
+ if (!primaryForDisplay) {
+ decodeDisplayImg(parser);
+ try {
+ mThread2.join();
+ mThread2 = null;
+ } catch (InterruptedException ignored) {
+ }
+ }
+
+ final Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ bitmaps[0] = BitmapFactory.decodeByteArray(data[0], 0, data[0].length);
+ data[0] = null;
+ if (!mCancelled && primaryForDisplay && brIntensity == 0) {
+ mListener.onBitmapLoaded(bitmaps[0], 1);
+ }
+ }
+ };
+ data[0] = parser.readImgData(true);
+ if (mCancelled || data[0] == null) return false;
+ if (primaryForDisplay) {
+ mThread2 = new Thread(runnable);
+ mThread2.start();
+ } else {
+ runnable.run();
+ }
+
+ data[1] = parser.readImgData(false);
+ if (mCancelled || data[1] == null) return false;
+ bitmaps[1] = BitmapFactory.decodeByteArray(data[1], 0, data[1].length);
+ data[1] = null;
+ if (bitmaps[1] == null) return false;
+
+ if (primaryForDisplay) {
+ try {
+ mThread2.join();
+ mThread2 = null;
+ } catch (InterruptedException ignored) {
+ }
+ }
+ return loadDepthMap(bitmaps, brIntensity, primaryForDisplay);
+ }
+
+ private void decodeDisplayImg(final MpoParser parser) {
+ mThread2 = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ BitmapFactory.Options o = new BitmapFactory.Options();
+ o.inJustDecodeBounds = true;
+ byte[] data = parser.readImgData(0);
+ if (data == null && !mCancelled) {
+ mListener.onBitmapLoaded(null, 1);
+ return;
+ }
+ if (mCancelled) return;
+ BitmapFactory.decodeByteArray(data, 0, data.length, o);
+ o.inSampleSize = mListener.onScale(o.outWidth, o.outHeight);
+ o.inJustDecodeBounds = false;
+ if (mCancelled) return;
+ Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, o);
+ if (mCancelled) return;
+ mListener.onBitmapLoaded(bitmap, o.inSampleSize);
+ }
+ });
+ mThread2.start();
+ }
+
+ private boolean loadDepthMap(Bitmap[] bitmaps, float brIntensity, boolean primaryForDisplay) {
+ // check for pre-generated dm file
+ String mpoFilepath = ImageLoader.getLocalPathFromUri(mContext, mUri);
+ if (mpoFilepath == null) {
+ Log.d(TAG, "Could not get file path from " + mUri);
+ return false;
+ }
+ DualCameraNativeEngine engine = DualCameraNativeEngine.getInstance();
+
+ if (mCancelled) return false;
+ boolean ok = engine.initDepthMap(bitmaps[0], bitmaps[1], mpoFilepath,
+ engine.getCalibFilepath(mContext), brIntensity);
+ bitmaps[1].recycle();
+ if (!ok) return false;
+
+ Point size = new Point();
+ ok = engine.getDepthMapSize(size);
+ if (ok) {
+ Log.d(TAG, "ddm size: " + size.x + "x" + size.y);
+ if (size.x == 0 || size.y == 0) {
+ Log.w(TAG, "invalid ddm size: " + size.x + "x" + size.y);
+ } else {
+ Bitmap depthMap = Bitmap.createBitmap(size.x, size.y, Bitmap.Config.ALPHA_8);
+ if (engine.getDepthMap(depthMap)) {
+ if (!mCancelled && brIntensity != 0 && primaryForDisplay) {
+ scaleBitmap(bitmaps[0]);
+ }
+ return true;
+ } else {
+ Log.w(TAG, "getDepthMap returned false");
+ }
+ }
+ } else {
+ Log.w(TAG, "getDepthMapSize returned false");
+ }
+ return false;
+ }
+
+ private void save(Bitmap bitmap, String name) {
+ try {
+ OutputStream os = mContext.openFileOutput(name, Context.MODE_PRIVATE);
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 95, os);
+ os.close();
+ } catch (Exception ignored) {
+ }
+ }
+
+ private void scaleBitmap(Bitmap bitmap) {
+ int width = bitmap.getWidth(), height = bitmap.getHeight();
+ int scale = mListener.onScale(width, height);
+ width /= scale;
+ height /= scale;
+
+ Bitmap b = Bitmap.createScaledBitmap(bitmap, width, height, false);
+ int[] roi = new int[4];
+ boolean result = DualCameraNativeEngine.getInstance().getPrimaryImg(0, 0, roi, true, b);
+ if (result && roi[2] != width && roi[3] != height) {
+ b = Bitmap.createBitmap(b, roi[0], roi[1], roi[2], roi[3]);
+ }
+ mListener.onBitmapLoaded(b, scale);
+ }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/threed/Controller.java b/src/com/android/gallery3d/app/dualcam3d/threed/Controller.java
new file mode 100644
index 000000000..ff86d2bf5
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/threed/Controller.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.app.dualcam3d.threed;
+
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+
+import com.android.gallery3d.app.dualcam3d.GLView;
+import com.android.gallery3d.app.dualcam3d.gl.Renderer;
+
+import org.codeaurora.gallery.R;
+
+
+public class Controller implements Gyro.Listener {
+ private static final String TAG = "Controller";
+ private static final float ANGLE_PER_PIXEL = (float) Math.toRadians(0.03f);
+
+ private final GLView mGLView;
+ private final LinearLayout mModeView;
+ private Auto mAuto;
+ private Gyro mGyro;
+
+ public Controller(GLView glView, LinearLayout modeView) {
+ mGLView = glView;
+ mModeView = modeView;
+ View.OnClickListener listener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ int id = v.getId();
+ switch (id) {
+ case R.id.mode_gyro:
+ startGyro();
+ break;
+ case R.id.mode_auto:
+ startAuto();
+ break;
+ case R.id.mode_touch:
+ stop(false);
+ break;
+ case R.id.three_dimensional:
+ start();
+ break;
+ }
+ }
+ };
+ for (int i = modeView.getChildCount() - 1; i >= 0; --i) {
+ ImageButton b = (ImageButton) modeView.getChildAt(i);
+ b.setOnClickListener(listener);
+ }
+ }
+
+ private boolean startGyro() {
+ stop(false);
+ if (mGyro == null) {
+ mGyro = new Gyro(mGLView.getContext());
+ if (mGyro.start()) {
+ mGyro.setListener(this);
+ return true;
+ } else {
+ mGyro = null;
+ mModeView.findViewById(R.id.mode_gyro).setEnabled(false);
+ }
+ }
+ return false;
+ }
+
+ private void startAuto() {
+ stop(false);
+ if (mAuto == null) {
+ mAuto = new Auto();
+ mAuto.start(mGLView);
+ }
+ }
+
+ public void start() {
+ if (!startGyro()) {
+ startAuto();
+ }
+// mModeView.setVisibility(View.VISIBLE);
+ }
+
+ public void stop(boolean hide) {
+ if (mGyro != null) {
+ mGyro.stop();
+ mGyro = null;
+ }
+ if (mAuto != null) {
+ mAuto.stop();
+ mAuto = null;
+ }
+// if (hide) {
+// mModeView.setVisibility(View.INVISIBLE);
+// }
+ }
+
+ @Override
+ public void onGyroChanged(float thetaX, float thetaY) {
+ mGLView.setOffsetWithRotation(thetaX, thetaY);
+ }
+
+ public void onMove(float deltaX, float deltaY) {
+ stop(false);
+ mGLView.setOffsetDelta(deltaX * ANGLE_PER_PIXEL, deltaY * ANGLE_PER_PIXEL);
+ }
+
+ private static class Auto {
+ private Thread mThread;
+ private boolean mStop;
+
+ public void start(final GLView glView) {
+ mStop = false;
+ mThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ float x = 0, y = 0, speed = 0.003f, angle = 0.87f;
+ double deltaX = angle * speed;
+ double deltaY = Math.sqrt(speed * speed - deltaX * deltaX);
+
+ while (!mStop) {
+ x += deltaX;
+ y += deltaY;
+ glView.setOffset(x, y);
+
+ if (x >= Renderer.THETA_MAX || x <= -Renderer.THETA_MAX) {
+ deltaX = -deltaX;
+ }
+ if (y >= Renderer.THETA_MAX || y <= -Renderer.THETA_MAX) {
+ deltaY = -deltaY;
+ }
+ try {
+ Thread.sleep(15);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+ }
+ });
+ mThread.start();
+ }
+
+ public void stop() {
+ mStop = true;
+ if (mThread != null) {
+ try {
+ mThread.join();
+ mThread = null;
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/threed/Gyro.java b/src/com/android/gallery3d/app/dualcam3d/threed/Gyro.java
new file mode 100644
index 000000000..bb1d1c1de
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/threed/Gyro.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.app.dualcam3d.threed;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+
+class Gyro implements SensorEventListener {
+ private final SensorManager mSensorManager;
+ private final Sensor mGyro;
+
+ private static final float ALPHA = 0.4f;
+ private static final float ALPHA_ORIGIN = 0.95f;
+
+ private long mPrevTimestamp;
+ private float mPrevThetaX;
+ private float mPrevThetaY;
+ private float mPrevOriginX;
+ private float mPrevOriginY;
+ private float mPrevOmegaX;
+ private float mPrevOmegaY;
+
+ private Listener mListener;
+
+ interface Listener {
+ void onGyroChanged(float thetaX, float thetaY);
+ }
+
+ Gyro(Context context) {
+ mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+ mGyro = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
+ }
+
+ public boolean start() {
+ return mGyro != null
+ && mSensorManager.registerListener(this, mGyro, SensorManager.SENSOR_DELAY_UI);
+ }
+
+ public void stop() {
+ mSensorManager.unregisterListener(this);
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
+ float omegaX = event.values[0];
+ float omegaY = event.values[1];
+ update(omegaX, omegaY, event.timestamp);
+ }
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+
+ private void update(float omegaX, float omegaY, long timestamp) {
+ if (mPrevTimestamp == 0) {
+ mPrevTimestamp = timestamp;
+ return;
+ }
+ float deltaTimestamp = (float) (timestamp - mPrevTimestamp) / 1000_000_000;
+
+ float thetaX = mPrevThetaX + 0.5f * (mPrevOmegaX + omegaX) * deltaTimestamp;
+ float thetaY = mPrevThetaY + 0.5f * (mPrevOmegaY + omegaY) * deltaTimestamp;
+ float smoothThetaX = ALPHA * mPrevThetaX + ((1.0f - ALPHA) * thetaX);
+ float smoothThetaY = ALPHA * mPrevThetaY + ((1.0f - ALPHA) * thetaY);
+
+ mPrevOriginX = ALPHA_ORIGIN * mPrevOriginX + (1 - ALPHA_ORIGIN) * smoothThetaX;
+ mPrevOriginY = ALPHA_ORIGIN * mPrevOriginY + (1 - ALPHA_ORIGIN) * smoothThetaY;
+
+ mPrevTimestamp = timestamp;
+ mPrevOmegaX = omegaX;
+ mPrevOmegaY = omegaY;
+ mPrevThetaX = smoothThetaX;
+ mPrevThetaY = smoothThetaY;
+
+ if (mListener != null) {
+ mListener.onGyroChanged(smoothThetaX - mPrevOriginX, smoothThetaY - mPrevOriginY);
+ }
+ }
+
+ void setListener(Listener listener) {
+ mListener = listener;
+ }
+}
diff --git a/src/com/android/gallery3d/data/TimeLineTitleMediaItem.java b/src/com/android/gallery3d/data/TimeLineTitleMediaItem.java
index ee1bbba72..b3b91bbb1 100755
--- a/src/com/android/gallery3d/data/TimeLineTitleMediaItem.java
+++ b/src/com/android/gallery3d/data/TimeLineTitleMediaItem.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015,2017, The Linux Foundation. All rights reserved.
* Not a Contribution
*
* Copyright (C) 2010 The Android Open Source Project
@@ -30,8 +30,8 @@ import com.android.gallery3d.util.ThreadPool.Job;
public class TimeLineTitleMediaItem extends MediaItem {
private static final String TAG = "TimeLineTitleMediaItem";
private String mTitle;
- private static int mPhotoCount;
- private static int mVideoCount;
+ private int mPhotoCount;
+ private int mVideoCount;
public TimeLineTitleMediaItem(Path path) {
super(path);
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
index 8ada5af9b..96696b2db 100755
--- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java
+++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
@@ -17,8 +17,13 @@
package com.android.gallery3d.filtershow;
import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
import java.lang.ref.WeakReference;
+import java.sql.SQLException;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.Locale;
import java.util.Vector;
@@ -38,7 +43,9 @@ import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.Color;
+import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
@@ -48,6 +55,8 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.provider.Settings;
+import android.os.Message;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
@@ -56,34 +65,45 @@ import android.support.v4.print.PrintHelper;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
+import android.view.ContextMenu;
import android.view.Gravity;
+import android.view.LayoutInflater;
import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
+import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
+import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageButton;
+import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
import android.widget.RelativeLayout;
import android.widget.ShareActionProvider;
import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
+import android.widget.TextView;
import android.widget.Toast;
import org.codeaurora.gallery.R;
+import org.json.JSONObject;
+
import com.android.gallery3d.app.PhotoPage;
+import com.android.gallery3d.common.Utils;
import com.android.gallery3d.data.LocalAlbum;
import com.android.gallery3d.filtershow.cache.ImageLoader;
import com.android.gallery3d.filtershow.category.Action;
import com.android.gallery3d.filtershow.category.CategoryAdapter;
+import com.android.gallery3d.filtershow.category.CategoryPanelLevelTwo;
import com.android.gallery3d.filtershow.category.CategoryView;
import com.android.gallery3d.filtershow.category.EditorCropPanel;
import com.android.gallery3d.filtershow.category.MainPanel;
@@ -91,6 +111,10 @@ import com.android.gallery3d.filtershow.category.StraightenPanel;
import com.android.gallery3d.filtershow.category.SwipableView;
import com.android.gallery3d.filtershow.category.TruePortraitMaskEditorPanel;
import com.android.gallery3d.filtershow.category.TrueScannerPanel;
+import com.android.gallery3d.filtershow.data.FilterPresetDBHelper;
+import com.android.gallery3d.filtershow.data.FilterPresetSource;
+import com.android.gallery3d.filtershow.data.FilterPresetSource.SaveOption;
+import com.android.gallery3d.filtershow.category.WaterMarkView;
import com.android.gallery3d.filtershow.data.UserPresetsManager;
import com.android.gallery3d.filtershow.editors.Editor;
import com.android.gallery3d.filtershow.editors.EditorCrop;
@@ -105,19 +129,28 @@ import com.android.gallery3d.filtershow.editors.HazeBusterEditor;
import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
import com.android.gallery3d.filtershow.editors.SeeStraightEditor;
import com.android.gallery3d.filtershow.editors.TrueScannerEditor;
+import com.android.gallery3d.filtershow.filters.FilterDualCamBasicRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterDualCamFusionRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterDualCamSketchRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterFxRepresentation;
import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterPresetRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation;
import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterWatermarkRepresentation;
import com.android.gallery3d.filtershow.filters.FiltersManager;
import com.android.gallery3d.filtershow.filters.ImageFilter;
+import com.android.gallery3d.filtershow.filters.SaveWaterMark;
import com.android.gallery3d.filtershow.filters.SimpleMakeupImageFilter;
+import com.android.gallery3d.filtershow.filters.TrueScannerActs;
import com.android.gallery3d.filtershow.history.HistoryItem;
import com.android.gallery3d.filtershow.history.HistoryManager;
import com.android.gallery3d.filtershow.imageshow.ImageShow;
import com.android.gallery3d.filtershow.imageshow.MasterImage;
import com.android.gallery3d.filtershow.imageshow.Spline;
import com.android.gallery3d.filtershow.info.InfoPanel;
+import com.android.gallery3d.filtershow.mediapicker.MediaPickerFragment;
import com.android.gallery3d.filtershow.pipeline.CachingPipeline;
import com.android.gallery3d.filtershow.pipeline.ImagePreset;
import com.android.gallery3d.filtershow.pipeline.ProcessingService;
@@ -127,6 +160,7 @@ import com.android.gallery3d.filtershow.provider.SharedImageProvider;
import com.android.gallery3d.filtershow.state.StateAdapter;
import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine.DdmStatus;
+import com.android.gallery3d.filtershow.tools.FilterGeneratorNativeEngine;
import com.android.gallery3d.filtershow.tools.SaveImage;
import com.android.gallery3d.filtershow.tools.TruePortraitNativeEngine;
import com.android.gallery3d.filtershow.tools.XmpPresets;
@@ -134,6 +168,7 @@ import com.android.gallery3d.filtershow.tools.XmpPresets.XMresults;
import com.android.gallery3d.filtershow.ui.ExportDialog;
import com.android.gallery3d.filtershow.ui.FramedTextButton;
import com.android.gallery3d.mpo.MpoParser;
+import com.android.gallery3d.ui.SlotView;
import com.android.gallery3d.util.GalleryUtils;
import com.android.photos.data.GalleryBitmapPool;
import com.thundersoft.hz.selfportrait.detect.FaceDetect;
@@ -161,6 +196,8 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
private EditorPlaceHolder mEditorPlaceHolder = new EditorPlaceHolder(this);
private Editor mCurrentEditor = null;
+ private MediaPickerFragment mMediaPicker;
+
private static final int SELECT_PICTURE = 1;
public static final int SELECT_FUSION_UNDERLAY = 2;
private static final String LOGTAG = "FilterShowActivity";
@@ -168,6 +205,7 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
private boolean mShowingTinyPlanet = false;
private boolean mShowingImageStatePanel = false;
private boolean mShowingVersionsPanel = false;
+ private boolean mShowingFilterGenerator = false;
private final Vector<ImageShow> mImageViews = new Vector<ImageShow>();
@@ -203,6 +241,8 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
private CategoryAdapter mCategoryMakeupAdapter = null;
private CategoryAdapter mCategoryDualCamAdapter = null;
private CategoryAdapter mCategoryTruePortraitAdapter = null;
+ private CategoryAdapter mCategoryFilterPresetAdapter = null;
+ private ArrayList<CategoryAdapter> mCategoryWatermarkAdapters;
private int mCurrentPanel = MainPanel.LOOKS;
private Vector<FilterUserPresetRepresentation> mVersions =
new Vector<FilterUserPresetRepresentation>();
@@ -230,6 +270,30 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
private ProgressDialog mLoadingDialog;
private long mRequestId = -1;
+ private WaterMarkView mWaterMarkView;
+ private boolean hasWaterMark;
+ private String locationStr;
+ private String temperature;
+ protected Handler handler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case SaveWaterMark.MARK_SAVE_COMPLETE:
+ completeSaveImage((Uri) msg.obj, true);
+ break;
+ default:
+ break;
+ }
+ super.handleMessage(msg);
+ }
+ };
+ private SaveWaterMark mSaveWaterMark = new SaveWaterMark();
+
+ private DialogFragment mPresetDialog;
+ private FilterPresetSource mFilterPresetSource;
+ private ArrayList <SaveOption> tempFilterArray = new ArrayList<SaveOption>();
+ private boolean mChangeable = false;
+ private int mOrientation;
public ProcessingService getProcessingService() {
return mBoundService;
@@ -246,6 +310,7 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
private void registerFilter() {
IntentFilter filter = new IntentFilter();
filter.addAction(ProcessingService.SAVE_IMAGE_COMPLETE_ACTION);
+ filter.addAction(Intent.ACTION_LOCALE_CHANGED);
registerReceiver(mHandlerReceiver, filter);
}
@@ -253,8 +318,7 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- if (ProcessingService.SAVE_IMAGE_COMPLETE_ACTION.equals(action) &&
- !isSimpleEditAction()) {
+ if (ProcessingService.SAVE_IMAGE_COMPLETE_ACTION.equals(action)) {
Bundle bundle = intent.getExtras();
long requestId = bundle.getLong(ProcessingService.KEY_REQUEST_ID);
//only handle own request
@@ -264,6 +328,10 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
boolean releaseDualCam = bundle.getBoolean(ProcessingService.KEY_DUALCAM);
completeSaveImage(saveUri, releaseDualCam);
}
+ } else if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
+ FiltersManager.reset();
+ getProcessingService().setupPipeline();
+ fillCategories();
}
}
};
@@ -340,6 +408,7 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mOrientation = getResources().getConfiguration().orientation;
boolean onlyUsePortrait = getResources().getBoolean(R.bool.only_use_portrait);
if (onlyUsePortrait) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
@@ -390,6 +459,10 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
showActionBar(false);
}
+ if (representation.getFilterType() == FilterRepresentation.TYPE_WATERMARK_CATEGORY) {
+ loadWaterMarkPanel((FilterWatermarkRepresentation) representation);
+ }
+
if (currentId == ImageOnlyEditor.ID) {
mCurrentEditor.reflectCurrentFilter();
return;
@@ -510,6 +583,30 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
}.run();
}
+ private void loadWaterMarkPanel(final FilterWatermarkRepresentation representation) {
+ new Runnable() {
+ @Override
+ public void run() {
+ CategoryPanelLevelTwo panel = new CategoryPanelLevelTwo(representation.getAdapterId());
+ FragmentTransaction transaction =
+ getSupportFragmentManager().beginTransaction();
+ transaction.remove(getSupportFragmentManager().findFragmentByTag(
+ MainPanel.FRAGMENT_TAG));
+ transaction.replace(R.id.main_panel_container, panel,
+ MainPanel.FRAGMENT_TAG);
+ transaction.commitAllowingStateLoss();
+ }
+ }.run();
+ }
+
+ public void setLocation(String location) {
+ locationStr = location;
+ }
+
+ public void setTemperature(String temperature) {
+ this.temperature = temperature;
+ }
+
public void leaveSeekBarPanel() {
removeSeekBarPanel();
showDefaultImageView();
@@ -568,12 +665,18 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
if (action == MotionEvent.ACTION_DOWN) {
MasterImage.getImage().setShowsOriginal(true);
v.setPressed(true);
+ if (mWaterMarkView != null) {
+ mWaterMarkView.setVisibility(View.GONE);
+ }
}
if (action == MotionEvent.ACTION_UP
|| action == MotionEvent.ACTION_CANCEL
|| action == MotionEvent.ACTION_OUTSIDE) {
v.setPressed(false);
MasterImage.getImage().setShowsOriginal(false);
+ if (mWaterMarkView != null) {
+ mWaterMarkView.setVisibility(View.VISIBLE);
+ }
}
return false;
@@ -706,6 +809,7 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
masterImage.setScaleFactor(1);
masterImage.resetTranslation();
}
+ clearWaterMark();
}
public void adjustCompareButton(boolean scaled) {
@@ -735,6 +839,7 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
fillMakeup();
fillDualCamera();
fillTruePortrait();
+ fillWaterMarks();
}
public void setupStatePanel() {
@@ -806,6 +911,136 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
}
mUserPresetsManager.delete(rep.getId());
updateUserPresetsFromManager();
+ }
+
+ public void handlePreset(Action action,View view,int i) {
+ mChangeable = true;
+ mHandledSwipeView = view;
+ final Action ac = action;
+ mFilterPresetSource = new FilterPresetSource(this);
+ switch (i) {
+ case R.id.renameButton:
+ final View layout = View.inflate(this,R.layout.filtershow_default_edittext,null);
+ AlertDialog.Builder renameAlertDialogBuilder = new AlertDialog.Builder(this);
+ renameAlertDialogBuilder.setTitle(R.string.rename_before_exit);
+ renameAlertDialogBuilder.setView(layout);
+ renameAlertDialogBuilder.setPositiveButton(R.string.ok,
+ new DialogInterface.OnClickListener(){
+ @Override
+ public void onClick(DialogInterface dialog, int id){
+ EditText mEditText = (EditText) layout.findViewById(
+ R.id.filtershow_default_edit);
+ String name = String.valueOf(mEditText.getText());
+ if ( (name.trim().length() == 0)|| name.isEmpty()) {
+ Toast.makeText(getApplicationContext(),
+ getString(R.string.filter_name_notification),
+ Toast.LENGTH_SHORT).show();
+ } else if (isDuplicateName(name)) {
+ Toast.makeText(getApplicationContext(),
+ getString(R.string.filter_name_duplicate),
+ Toast.LENGTH_SHORT).show();
+ } else {
+ renamePreset(ac, name);
+ }
+ dialog.dismiss();
+ }
+ }
+ );
+ renameAlertDialogBuilder.setNegativeButton(mCancel,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick (DialogInterface dialog, int id){
+
+ }
+ }
+ );
+ renameAlertDialogBuilder.create().show();
+ break;
+
+ case R.id.deleteButton:
+ String name = action.getName();
+ AlertDialog.Builder deleteAlertDialogBuilder = new AlertDialog.Builder(this);
+ String textview ="Do you want to delete "+name+"?";
+ deleteAlertDialogBuilder.setMessage(textview)
+ .setTitle(R.string.delete_before_exit);
+ deleteAlertDialogBuilder.setPositiveButton(R.string.ok,
+ new DialogInterface.OnClickListener(){
+ @Override
+ public void onClick(DialogInterface dialog, int id){
+ ((SwipableView) mHandledSwipeView).delete();
+ dialog.dismiss();
+ }
+ }
+ );
+ deleteAlertDialogBuilder.setNegativeButton(mCancel,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick (DialogInterface dialog, int id){
+ dialog.dismiss();
+
+ }
+ }
+ );
+ deleteAlertDialogBuilder.create().show();
+ break;
+ }
+ }
+
+ public void removePreset(Action action) {
+ FilterPresetRepresentation rep =
+ (FilterPresetRepresentation)action.getRepresentation();
+ if (rep == null) {
+ return;
+ }
+ if (tempFilterArray.size() != 0) {
+ for (int i = 0; i < tempFilterArray.size(); i++) {
+ if (rep.getId() == tempFilterArray.get(i)._id) {
+ tempFilterArray.remove(i);
+ fillLooks();
+ return;
+ }
+ }
+ }
+ mFilterPresetSource.removePreset(rep.getId());
+ fillLooks();
+ }
+
+ public void renamePreset(Action action, String name) {
+ FilterPresetRepresentation rep =
+ (FilterPresetRepresentation)action.getRepresentation();
+ if (rep == null) {
+ return;
+ }
+ if (tempFilterArray.size() != 0) {
+ for (int i = 0; i < tempFilterArray.size(); i++) {
+ if (rep.getId() == tempFilterArray.get(i)._id) {
+ tempFilterArray.get(i).name = name;
+ fillLooks();
+ return;
+ }
+ }
+ }
+ mFilterPresetSource.updatePresetName(rep.getId(),name);
+ fillLooks();
+ }
+
+ public boolean isDuplicateName(String name) {
+ ArrayList<String> nameSum = new ArrayList<String>();
+ if (tempFilterArray.size() != 0) {
+ for (int i = 0; i < tempFilterArray.size(); i++)
+ nameSum.add(tempFilterArray.get(i).name);
+ }
+
+ ArrayList<SaveOption> ret = mFilterPresetSource.getAllUserPresets();
+ if (ret != null) {
+ for (int id = 0; id < ret.size(); id++)
+ nameSum.add(ret.get(id).name);
+ }
+
+ for (int i = 0; i < nameSum.size(); i++) {
+ if (name.equals(nameSum.get(i))) return true;
+ }
+ return false;
}
private void fillEffects() {
@@ -872,6 +1107,41 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
}
}
+ private void fillPresetFilter() {
+ FiltersManager filtersManager = FiltersManager.getManager();
+ ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getFilterPreset();
+ if(mChangeable) {
+ ArrayList<FilterRepresentation> mFilterPreset = new ArrayList<FilterRepresentation>();
+ ArrayList<SaveOption> ret = mFilterPresetSource.getAllUserPresets();
+ if (ret == null) return;
+ for (int id = 0; id < ret.size(); id ++) {
+ FilterPresetRepresentation representation = new FilterPresetRepresentation(
+ ret.get(id).name, ret.get(id)._id, id + 1);
+ Uri filteredUri = Uri.parse(ret.get(id).Uri);
+ representation.setUri(filteredUri);
+ representation.setSerializationName("Custom");
+ mFilterPreset.add(representation);
+ }
+ if (tempFilterArray.size() != 0){
+ for (int id = 0; id < tempFilterArray.size(); id ++) {
+ FilterPresetRepresentation representation = new FilterPresetRepresentation(
+ tempFilterArray.get(id).name, tempFilterArray.get(id)._id, id + 1);
+ Uri filteredUri = Uri.parse(tempFilterArray.get(id).Uri);
+ representation.setUri(filteredUri);
+ representation.setSerializationName("Custom");
+ mFilterPreset.add(representation);
+ }
+ }
+ filtersRepresentations = mFilterPreset;
+ mChangeable = false;
+ }
+
+ if (filtersRepresentations == null) return;
+ for (FilterRepresentation representation : filtersRepresentations) {
+ mCategoryLooksAdapter.add(new Action(this, representation, Action.FULL_VIEW,true));
+ }
+ }
+
private void fillTrueScanner() {
FiltersManager filtersManager = FiltersManager.getManager();
ArrayList<FilterRepresentation> trueScannerRepresentations = filtersManager.getTrueScanner();
@@ -929,6 +1199,27 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
}
}
+ private void fillWaterMarks() {
+ FiltersManager filtersManager = FiltersManager.getManager();
+ ArrayList<ArrayList<FilterRepresentation>> filters = new ArrayList<>();
+ filters.add(filtersManager.getWaterMarks());
+ filters.add(filtersManager.getLocations());
+ filters.add(filtersManager.getTimes());
+ filters.add(filtersManager.getWeathers());
+ filters.add(filtersManager.getEmotions());
+ filters.add(filtersManager.getFoods());
+ if (mCategoryWatermarkAdapters != null) {
+ mCategoryWatermarkAdapters.clear();
+ }
+ mCategoryWatermarkAdapters = new ArrayList<>();
+ for (int i = 0; i < filters.size(); i++) {
+ mCategoryWatermarkAdapters.add(new CategoryAdapter(this));
+ for (FilterRepresentation representation : filters.get(i)) {
+ mCategoryWatermarkAdapters.get(i).add(new Action(this, representation));
+ }
+ }
+ }
+
private void processIntent() {
Intent intent = getIntent();
if (intent.getBooleanExtra(LAUNCH_FULLSCREEN, false)) {
@@ -1060,6 +1351,30 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
return mCategoryTruePortraitAdapter;
}
+ public CategoryAdapter getCategoryWatermarkAdapter() {
+ return (mCategoryWatermarkAdapters != null) ? mCategoryWatermarkAdapters.get(0) : null;
+ }
+
+ public CategoryAdapter getCategoryLocationAdapter() {
+ return (mCategoryWatermarkAdapters != null) ? mCategoryWatermarkAdapters.get(1) : null;
+ }
+
+ public CategoryAdapter getCategoryTimeAdapter() {
+ return (mCategoryWatermarkAdapters != null) ? mCategoryWatermarkAdapters.get(2) : null;
+ }
+
+ public CategoryAdapter getCategoryWeatherAdapter() {
+ return (mCategoryWatermarkAdapters != null) ? mCategoryWatermarkAdapters.get(3) : null;
+ }
+
+ public CategoryAdapter getCategoryEmotionAdapter() {
+ return (mCategoryWatermarkAdapters != null) ? mCategoryWatermarkAdapters.get(4) : null;
+ }
+
+ public CategoryAdapter getCategoryFoodAdapter() {
+ return (mCategoryWatermarkAdapters != null) ? mCategoryWatermarkAdapters.get(5) : null;
+ }
+
public void removeFilterRepresentation(FilterRepresentation filterRepresentation) {
if (filterRepresentation == null) {
return;
@@ -1083,6 +1398,9 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
&& MasterImage.getImage().getCurrentFilterRepresentation() == filterRepresentation) {
return;
}
+ if (filterRepresentation.getFilterType() == FilterWatermarkRepresentation.TYPE_WATERMARK_CATEGORY) {
+ return;
+ }
if (filterRepresentation instanceof FilterUserPresetRepresentation
|| filterRepresentation instanceof FilterRotateRepresentation
|| filterRepresentation instanceof FilterMirrorRepresentation) {
@@ -1156,11 +1474,100 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
return;
}
}
+ if (representation.getFilterType() == FilterRepresentation.TYPE_DUALCAM) {
+ DisplayMetrics dm = getResources().getDisplayMetrics();
+ float[] mTmpPoint = new float[2];
+ mTmpPoint[0] = dm.widthPixels/2;
+ mTmpPoint[1] = dm.heightPixels/2;
+ Matrix m = MasterImage.getImage().getScreenToImageMatrix(true);
+ m.mapPoints(mTmpPoint);
+ if (representation instanceof FilterDualCamBasicRepresentation) {
+ ((FilterDualCamBasicRepresentation)representation).setPoint((int)mTmpPoint[0],(int)mTmpPoint[1]);
+ }
+ if (representation instanceof FilterDualCamFusionRepresentation) {
+ ((FilterDualCamFusionRepresentation)representation).setPoint((int)mTmpPoint[0],(int)mTmpPoint[1]);
+ }
+ if (representation instanceof FilterDualCamSketchRepresentation) {
+ ((FilterDualCamSketchRepresentation)representation).setPoint((int)mTmpPoint[0],(int)mTmpPoint[1]);
+ }
+ }
+ if (representation.getFilterType() == FilterRepresentation.TYPE_WATERMARK) {
+ showWaterMark(representation);
+ }
+ if (TrueScannerActs.SERIALIZATION_NAME.equals(representation.getSerializationName())) {
+ Bitmap b = MasterImage.getImage().getOriginalBitmapHighres();
+ int w = b.getWidth();
+ int h = b.getHeight();
+ if (w < h) {
+ w = h;
+ h = b.getWidth();
+ }
+ if (w <= TrueScannerActs.MIN_WIDTH
+ || h <= TrueScannerActs.MIN_HEIGHT) {
+ Toast.makeText(this, "Image size too small!", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ }
useFilterRepresentation(representation);
loadEditorPanel(representation);
}
+ private void showWaterMark(FilterRepresentation representation) {
+ FilterWatermarkRepresentation watermarkRepresentation =
+ (FilterWatermarkRepresentation)representation;
+ if (mWaterMarkView != null) {
+ rlImageContainer.removeView(mWaterMarkView);
+ hasWaterMark = false;
+ watermarkRepresentation.reset();
+ }
+ DisplayMetrics dm = getResources().getDisplayMetrics();
+ RelativeLayout.LayoutParams params =
+ new RelativeLayout.LayoutParams(dm.widthPixels,
+ dm.heightPixels);
+ String textHint;
+ switch (watermarkRepresentation.getMarkType()) {
+ case 0:
+ textHint = locationStr;
+ break;
+ case 2:
+ textHint = temperature;
+ break;
+ default:
+ textHint = watermarkRepresentation.getTextHint();
+ break;
+ }
+ WaterMarkView waterMarkView = watermarkRepresentation.getWaterMarkView(textHint);
+ rlImageContainer.addView(waterMarkView, params);
+ mWaterMarkView = waterMarkView;
+ mSaveWaterMark.useRepresentation(representation);
+ imgComparison.bringToFront();
+ mSaveWaterMark.getExifData(this, mSelectedImageUri);
+ mWaterMarkView.mTouchable = true;
+ hasWaterMark = true;
+ }
+
+ private void clearWaterMark() {
+ if (mWaterMarkView != null) {
+ rlImageContainer.removeView(mWaterMarkView);
+ mWaterMarkView = null;
+ hasWaterMark = false;
+ }
+ }
+
+ public void disableTouchEvent() {
+ if (mWaterMarkView == null) return;
+ mWaterMarkView.mTouchable = false;
+ }
+
+ public boolean isWaterMarked() {
+ return hasWaterMark;
+ }
+
+ public SaveWaterMark getSaveWaterMark() {
+ return mSaveWaterMark;
+ }
+
public Editor getEditor(int editorID) {
return mEditorPlaceHolder.getEditor(editorID);
}
@@ -1221,6 +1628,94 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
mCurrentDialog = null;
}
+ public void onMediaPickerStarted() {
+ mPresetDialog = null;
+ toggleComparisonButtonVisibility();
+ ActionBar actionBar = getActionBar();
+ actionBar.hide();
+ if (mMediaPicker == null)
+ mMediaPicker = MediaPickerFragment.newInstance(getApplicationContext());
+ getSupportFragmentManager()
+ .beginTransaction()
+ .replace(R.id.main_panel_container, mMediaPicker)
+ .commit();
+ }
+
+ public void onMediaPickerResult(Uri selImg) {
+ mFilterPresetSource = new FilterPresetSource(this);
+ int id = nameFilter(mFilterPresetSource, tempFilterArray);
+ FilterPresetRepresentation fp= new FilterPresetRepresentation(
+ getString(R.string.filtershow_preset_title) + id, id, id);
+ fp.setSerializationName("Custom");
+ fp.setUri(selImg);
+ ImagePreset preset = new ImagePreset();
+ preset.addFilter(fp);
+ SaveOption sp= new SaveOption();
+ sp._id = id;
+ sp.name = "Custom" + id;
+ sp.Uri = selImg.toString();
+ tempFilterArray.add(sp);
+ FiltersManager.getManager().addRepresentation(fp);
+ mCategoryLooksAdapter.add(new Action(this, fp, Action.FULL_VIEW, true));
+ useFilterRepresentation(fp);
+ int pos = mCategoryLooksAdapter.getPositionOfPresentation(fp);
+ if (pos != -1)
+ backAndSetCustomFilterSelected(pos);
+ }
+
+ private void backAndSetCustomFilterSelected(int pos) {
+ showComparisonButton();
+ removeSeekBarPanel();
+ showActionBar(true);
+ loadMainPanel();
+ if(mEditorPlaceHolder != null)
+ mEditorPlaceHolder.hide();
+ if(mImageShow != null)
+ mImageShow.setVisibility(View.VISIBLE);
+ updateCategories();
+ mCategoryLooksAdapter.setSelected(pos);
+ }
+
+ public void applyCustomFilterRepresentation(
+ FilterRepresentation filterRep, FilterRepresentation oldfilterRep) {
+ ImagePreset oldPreset = MasterImage.getImage().getPreset();
+ ImagePreset copy = new ImagePreset(oldPreset);
+ if (oldfilterRep != null)
+ copy.removeFilter(oldfilterRep);
+
+ FilterRepresentation rep = copy.getRepresentation(filterRep);
+ if (rep == null) {
+ filterRep = filterRep.copy();
+ copy.addFilter(filterRep);
+ } else {
+ if (filterRep.allowsSingleInstanceOnly()) {
+ // Don't just update the filter representation. Centralize the
+ // logic in the addFilter(), such that we can keep "None" as
+ // null.
+ if (!rep.equals(filterRep)) {
+ // Only do this if the filter isn't the same
+ // (state panel clicks can lead us here)
+ copy.removeFilter(rep);
+ copy.addFilter(filterRep);
+ }
+ }
+ }
+ MasterImage.getImage().setPreset(copy, filterRep, false);
+ }
+
+ public FilterRepresentation createUserPresentaion(Uri selImg, int index) {
+ FilterPresetRepresentation fp= new FilterPresetRepresentation(
+ getString(R.string.filtershow_preset_title) + index, index, index);
+ fp.setSerializationName("Custom");
+ fp.setUri(selImg);
+ return fp;
+ }
+
+ public FilterRepresentation getCurrentPresentation() {
+ ImagePreset preset = MasterImage.getImage().getPreset();
+ return preset.getLastRepresentation();
+ }
+
private class LoadHighresBitmapTask extends AsyncTask<Void, Void, Boolean> {
@Override
protected Boolean doInBackground(Void... params) {
@@ -1290,23 +1785,20 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
mAuxImgData == null) {
// parse failed
MasterImage.getImage().setDepthMapLoadingStatus(DdmStatus.DDM_FAILED);
- Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
- if (currentPanel instanceof MainPanel) {
- MainPanel mainPanel = (MainPanel) currentPanel;
- mainPanel.updateDualCameraButton();
- }
} else {
+ MasterImage.getImage().setDepthMapLoadingStatus(DdmStatus.DDM_LOADING);
mLoadMpoTask = new LoadMpoDataTask();
mLoadMpoTask.execute(mPrimaryImgData, mAuxImgData);
}
+ Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
+ if (currentPanel instanceof MainPanel) {
+ MainPanel mainPanel = (MainPanel) currentPanel;
+ mainPanel.updateDualCameraButton();
+ }
}
}
private class LoadMpoDataTask extends AsyncTask<byte[], Void, Boolean> {
- @Override
- protected void onPreExecute() {
- MasterImage.getImage().setDepthMapLoadingStatus(DdmStatus.DDM_LOADING);
- }
@Override
protected Boolean doInBackground(byte[]... params) {
@@ -1364,6 +1856,9 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
protected Boolean doInBackground(Uri... params) {
boolean result = false;
Bitmap src = ImageLoader.loadBitmap(FilterShowActivity.this, params[0], null);
+ if(src == null) {
+ return false;
+ }
FaceDetect fDetect = new FaceDetect();
fDetect.initialize();
FaceInfo[] faceInfos = fDetect.dectectFeatures(src);
@@ -1528,6 +2023,13 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
}
mUserPresetsManager.close();
+ if (mFilterPresetSource !=null) {
+ mFilterPresetSource.close();
+ }
+
+ if (tempFilterArray != null) {
+ tempFilterArray.clear();
+ }
unregisterReceiver(mHandlerReceiver);
doUnbindService();
if (mReleaseDualCamOnDestory && DualCameraNativeEngine.getInstance().isLibLoaded())
@@ -1537,7 +2039,7 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
// TODO: find a more robust way of handling image size selection
// for high screen densities.
- private int getScreenImageSize() {
+ public int getScreenImageSize() {
DisplayMetrics outMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
return Math.max(outMetrics.heightPixels, outMetrics.widthPixels);
@@ -1686,6 +2188,7 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
return true;
}*/
case R.id.resetHistoryButton: {
+ clearWaterMark();
resetHistory();
return true;
}
@@ -1716,8 +2219,14 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
}
public void addNewPreset() {
- DialogFragment dialog = new PresetManagementDialog();
- dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
+ boolean skipIntro = GalleryUtils.getBooleanPref(this,
+ this.getString(R.string.pref_filtergenerator_intro_show_key), false);
+ if (!skipIntro) {
+ mPresetDialog = new PresetManagementDialog();
+ mPresetDialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
+ } else {
+ onMediaPickerStarted();
+ }
}
private void manageUserPresets() {
@@ -1759,19 +2268,20 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
if (mCategoryLooksAdapter != null) {
fillLooks();
}
- if (presets.size() > 0) {
+ /* if (presets.size() > 0) {
mCategoryLooksAdapter.add(new Action(this, Action.SPACER));
- }
+ } */
mUserPresetsAdapter.clear();
+ if (presets.size() > 0) {
+ mCategoryLooksAdapter.add(new Action(this, Action.ADD_ACTION));
+ }
for (int i = 0; i < presets.size(); i++) {
FilterUserPresetRepresentation representation = presets.get(i);
mCategoryLooksAdapter.add(
new Action(this, representation, Action.FULL_VIEW, true));
mUserPresetsAdapter.add(new Action(this, representation, Action.FULL_VIEW));
}
- if (presets.size() > 0) {
- mCategoryLooksAdapter.add(new Action(this, Action.ADD_ACTION));
- }
+
mCategoryLooksAdapter.notifyDataSetChanged();
mCategoryLooksAdapter.notifyDataSetInvalidated();
}
@@ -1807,6 +2317,14 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
for (FilterRepresentation representation : filtersRepresentations) {
mCategoryLooksAdapter.add(new Action(this, representation, Action.FULL_VIEW));
}
+ if (FilterGeneratorNativeEngine.getInstance().isLibLoaded()) {
+ if (mUserPresetsManager.getRepresentations() == null
+ || mUserPresetsManager.getRepresentations().size() == 0) {
+ mCategoryLooksAdapter.add(new Action(this, Action.ADD_ACTION));
+ }
+ }
+
+ fillPresetFilter();
Fragment panel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
if (panel != null) {
@@ -1868,11 +2386,28 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
}
@Override
- public void onConfigurationChanged(Configuration newConfig)
- {
+ public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setDefaultValues();
+ if (mOrientation != newConfig.orientation) {
+ TrueScannerActs.setRotating(true);
+ mOrientation = newConfig.orientation;
+ }
+ switch (newConfig.orientation) {
+ case (Configuration.ORIENTATION_LANDSCAPE):
+ if (mPresetDialog != null) {
+ mPresetDialog.dismiss();
+ mPresetDialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
+ }
+ break;
+ case (Configuration.ORIENTATION_PORTRAIT):
+ if (mPresetDialog != null) {
+ mPresetDialog.dismiss();
+ mPresetDialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
+ }
+ break;
+ }
if (isShowEditCropPanel()) {
mIsReloadByConfigurationChanged = true;
loadEditorCropPanel();
@@ -1884,6 +2419,12 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
//fillCategories();
//loadMainPanel();
+ if (isWaterMarked()) {
+ DisplayMetrics dm = getResources().getDisplayMetrics();
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(dm.widthPixels,
+ dm.heightPixels);
+ rlImageContainer.updateViewLayout(mWaterMarkView, params);
+ }
if (mCurrentMenu != null) {
mCurrentMenu.dismiss();
mCurrentMenu = null;
@@ -1897,6 +2438,7 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
mCategoryFiltersAdapter.removeTinyPlanet();
}
stopLoadingIndicator();
+
}
public void setupMasterImage() {
@@ -1934,6 +2476,9 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
rep = historyItem.getFilterRepresentation();
}
mMasterImage.setPreset(original, rep, true);
+ mMasterImage.setFusionUnderlay(null);
+ mMasterImage.resetTranslation();
+ mMasterImage.setScaleFactor(1);
invalidateViews();
backToMain();
showSaveButtonIfNeed();
@@ -2064,6 +2609,74 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
}
+ private int nameFilter(FilterPresetSource source,
+ ArrayList <SaveOption> tempFilterArray) {
+ String s,s1,s2;
+ ArrayList<SaveOption> sp = source.getAllUserPresets();
+ ArrayList<Integer> temp = new ArrayList<Integer>();
+ if (sp != null) {
+ for (int i = 0; i < sp.size(); i++) {
+ s = sp.get(i).name;
+ if (s.length() > "Custom".length()) {
+ s1 = s.substring(0, 6);
+ if (s1.equals("Custom")) {
+ s2 = s.substring(6);
+ int tem;
+ try {
+ tem = Integer.parseInt(s2);
+ } catch (NumberFormatException e) {
+ continue;
+ }
+ temp.add(tem);
+ }
+ }
+ }
+ }
+
+ if (tempFilterArray.size() != 0 ){
+ for (int i = 0; i < tempFilterArray.size(); i++) {
+ s = tempFilterArray.get(i).name;
+ if (s.length() > "Custom".length()) {
+ s1 = s.substring(0, 6);
+ if (s1.equals("Custom")) {
+ s2 = s.substring(6);
+ int tem;
+ try {
+ tem = Integer.parseInt(s2);
+ } catch (NumberFormatException e) {
+ continue;
+ }
+ temp.add(tem);
+ }
+ }
+ }
+
+ }
+
+ if (temp != null) {
+ Collections.sort(temp);
+ for (int i = 1; i <= temp.size(); i++){
+ if (temp.get(i-1)!= i){
+ return i;
+ }
+ }
+ }
+ return temp.size()+1;
+ }
+
+
+ public static boolean completeSaveFilters (FilterPresetSource mFilterPresetSource,
+ ArrayList<SaveOption> tempFilterArray) {
+
+ for (int i = 0; i < tempFilterArray.size(); i++){
+ String name = tempFilterArray.get(i).name;
+ String filteredUri = tempFilterArray.get(i).Uri;
+ if (mFilterPresetSource.insertPreset(name,filteredUri) == false) return false;
+ }
+ tempFilterArray.clear();
+ return true;
+ }
+
public void saveImage() {
if (mImageShow.hasModifications()) {
// Get the name of the album, to which the image will be saved
@@ -2072,7 +2685,15 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
String albumName = LocalAlbum.getLocalizedName(getResources(), bucketId, null);
mReleaseDualCamOnDestory = false;
showSavingProgress(albumName);
- mImageShow.saveImage(this, null);
+ if (mWaterMarkView == null) {
+ mImageShow.saveImage(this, null);
+ } else {
+ mSaveWaterMark.saveImage(this, mMasterImage.getHighresImage(),
+ mSelectedImageUri, handler);
+ }
+ if (tempFilterArray.size() != 0) {
+ completeSaveFilters(mFilterPresetSource, tempFilterArray);
+ }
} else {
done();
}
@@ -2149,7 +2770,7 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
if (mHandledSwipeViewLastDelta > distance) {
((SwipableView) mHandledSwipeView).delete();
}
- }
+ }
return true;
}
return super.dispatchTouchEvent(ev);
diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
index d8560312c..f70a8fe7c 100644
--- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
+++ b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
@@ -17,6 +17,7 @@
package com.android.gallery3d.filtershow.cache;
import android.content.ContentResolver;
+import android.content.ContentUris;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
@@ -29,6 +30,9 @@ import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Log;
import android.webkit.MimeTypeMap;
@@ -82,13 +86,97 @@ public final class ImageLoader {
}
public static String getLocalPathFromUri(Context context, Uri uri) {
- Cursor cursor = context.getContentResolver().query(uri,
- new String[]{MediaStore.Images.Media.DATA}, null, null, null);
- if (cursor == null) {
- return null;
+
+ final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
+
+ // DocumentProvider
+ if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
+ // ExternalStorageProvider
+ if (isExternalStorageDocument(uri)) {
+ final String docId = DocumentsContract.getDocumentId(uri);
+ final String[] split = docId.split(":");
+ final String type = split[0];
+
+ if ("primary".equalsIgnoreCase(type)) {
+ return Environment.getExternalStorageDirectory() + "/" + split[1];
+ }
+ }
+ // DownloadsProvider
+ else if (isDownloadsDocument(uri)) {
+
+ final String id = DocumentsContract.getDocumentId(uri);
+ final Uri contentUri = ContentUris.withAppendedId(
+ Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
+
+ return getDataColumn(context, contentUri, null, null);
+ }
+ // MediaProvider
+ else if (isMediaDocument(uri)) {
+ final String docId = DocumentsContract.getDocumentId(uri);
+ final String[] split = docId.split(":");
+ final String type = split[0];
+
+ Uri contentUri = null;
+ if ("image".equals(type)) {
+ contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+ } else if ("video".equals(type)) {
+ contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
+ } else if ("audio".equals(type)) {
+ contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+ }
+
+ final String selection = "_id=?";
+ final String[] selectionArgs = new String[] { split[1] };
+
+ return getDataColumn(context, contentUri, selection, selectionArgs);
+ }
}
- int index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
- return cursor.moveToFirst() ? cursor.getString(index) : null;
+ return getDataColumn(context, uri, null, null);
+ }
+
+ public static String getDataColumn(Context context, Uri uri, String selection,
+ String[] selectionArgs) {
+
+ Cursor cursor = null;
+ final String column = "_data";
+ final String[] projection = { column };
+
+ try {
+ cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
+ null);
+ if (cursor != null && cursor.moveToFirst()) {
+ final int index = cursor.getColumnIndexOrThrow(column);
+ return cursor.getString(index);
+ }
+ } finally {
+ if (cursor != null)
+ cursor.close();
+ }
+ return null;
+ }
+
+ /**
+ * @param uri The Uri to check.
+ * @return Whether the Uri authority is ExternalStorageProvider.
+ */
+ public static boolean isExternalStorageDocument(Uri uri) {
+ return "com.android.externalstorage.documents".equals(uri.getAuthority());
+ }
+
+ /**
+ * @param uri The Uri to check.
+ * @return Whether the Uri authority is DownloadsProvider.
+ */
+ public static boolean isDownloadsDocument(Uri uri) {
+ return "com.android.providers.downloads.documents".equals(uri.getAuthority());
+ }
+
+ /**
+ * @param uri The Uri to check.
+ * @return Whether the Uri authority is MediaProvider.
+ */
+ public static boolean isMediaDocument(Uri uri) {
+ return "com.android.providers.media.documents".equals(uri.getAuthority());
}
/**
diff --git a/src/com/android/gallery3d/filtershow/category/Action.java b/src/com/android/gallery3d/filtershow/category/Action.java
index 731c07999..67a34cebe 100644
--- a/src/com/android/gallery3d/filtershow/category/Action.java
+++ b/src/com/android/gallery3d/filtershow/category/Action.java
@@ -20,10 +20,16 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
@@ -38,6 +44,7 @@ import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.imageshow.MasterImage;
import com.android.gallery3d.filtershow.pipeline.ImagePreset;
+import com.android.gallery3d.glrenderer.Texture;
public class Action implements RenderingRequestCaller {
@@ -58,6 +65,7 @@ public class Action implements RenderingRequestCaller {
private boolean mCanBeRemoved = false;
private int mTextSize = 32;
private boolean mIsDoubleAction = false;
+ private boolean mIsClickAction = false;
public Action(FilterShowActivity context, FilterRepresentation representation, int type,
boolean canBeRemoved) {
@@ -123,6 +131,16 @@ public class Action implements RenderingRequestCaller {
return;
}
+ if (mRepresentation.getFilterType() == FilterRepresentation.TYPE_WATERMARK ||
+ mRepresentation.getFilterType() == FilterRepresentation.TYPE_WATERMARK_CATEGORY) {
+ mImageFrame = imageFrame;
+ int w = mImageFrame.width();
+ int h = mImageFrame.height();
+ mImage = MasterImage.getImage().getBitmapCache().getBitmap(w, h, BitmapCache.ICON);
+ drawOverlay();
+ return;
+ }
+
Bitmap temp = MasterImage.getImage().getTemporaryThumbnailBitmap();
if (temp != null) {
mImage = temp;
@@ -173,15 +191,32 @@ public class Action implements RenderingRequestCaller {
canvas.drawBitmap(source, m, new Paint(Paint.FILTER_BITMAP_FLAG));
}
- @Override
- public void available(RenderingRequest request) {
- clearBitmap();
- mImage = request.getBitmap();
- if (mImage == null) {
- mImageFrame = null;
+ protected void drawOverlay() {
+ if (mRepresentation.isSvgOverlay()) {
+ mImage.eraseColor(0x00FFFFFF);
+ Canvas canvas = new Canvas(mImage);
+ canvas.drawARGB(0,255,255,255);
+ Drawable overlayDrawable = mContext.getResources().
+ getDrawable(mRepresentation.getOverlayId(), null);
+ if (null != mRepresentation.getCurrentTheme() && overlayDrawable.canApplyTheme()) {
+ overlayDrawable.applyTheme(mRepresentation.getCurrentTheme());
+ }
+ if(mIsClickAction) {
+ overlayDrawable.setColorFilter(mContext.getResources()
+ .getColor(R.color.watermark_highlight_color), PorterDuff.Mode.MULTIPLY);
+ } else {
+ overlayDrawable.clearColorFilter();
+ }
+ int with = mImageFrame.width()/9;
+ int height = mImageFrame.height()/8;
+ if (!TextUtils.isEmpty(getName())) {
+ overlayDrawable.setBounds(with,16,with*8,height*6);
+ } else {
+ overlayDrawable.setBounds(with,52,with*8,height*7);
+ }
+ overlayDrawable.draw(canvas);
return;
}
-
if (mRepresentation.getOverlayId() != 0 && mOverlayBitmap == null) {
mOverlayBitmap = BitmapFactory.decodeResource(
mContext.getResources(),
@@ -198,7 +233,17 @@ public class Action implements RenderingRequestCaller {
drawCenteredImage(mOverlayBitmap, mImage, false);
}
}
+ }
+ @Override
+ public void available(RenderingRequest request) {
+ clearBitmap();
+ mImage = request.getBitmap();
+ if (mImage == null) {
+ mImageFrame = null;
+ return;
+ }
+ drawOverlay();
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
@@ -220,6 +265,10 @@ public class Action implements RenderingRequestCaller {
mOverlayBitmap = overlayBitmap;
}
+ public void setClickAction() { mIsClickAction = true; }
+
+ public void clearClickAction() { mIsClickAction = false; }
+
public void clearBitmap() {
if (mImage != null
&& mImage != MasterImage.getImage().getTemporaryThumbnailBitmap()) {
diff --git a/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java b/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java
index 6c4f9fe87..22ffc04c6 100644
--- a/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java
+++ b/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java
@@ -24,6 +24,7 @@ import android.widget.ListView;
import org.codeaurora.gallery.R;
import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.filters.FilterPresetRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.filters.FilterTinyPlanetRepresentation;
import com.android.gallery3d.filtershow.pipeline.ImagePreset;
@@ -140,11 +141,31 @@ public class CategoryAdapter extends ArrayAdapter<Action> {
}
public void setSelected(View v) {
+ setSelected((Integer) v.getTag());
+ }
+
+ public int getPositionOfPresentation(FilterRepresentation rep) {
+ int pos = -1;
+ for (int i = 0; i < getCount(); i++) {
+ FilterRepresentation itemRep = getItem(i).getRepresentation();
+ if (itemRep == null) {
+ continue;
+ }
+ if (rep.getName().equalsIgnoreCase(
+ itemRep.getName())) {
+ pos = i;
+ break;
+ }
+ }
+ return pos;
+ }
+
+ public void setSelected(int pos) {
int old = mSelectedPosition;
- mSelectedPosition = (Integer) v.getTag();
if (old != -1) {
invalidateView(old);
}
+ mSelectedPosition = pos;
invalidateView(mSelectedPosition);
}
@@ -211,7 +232,11 @@ public class CategoryAdapter extends ArrayAdapter<Action> {
super.remove(action);
FilterShowActivity activity = (FilterShowActivity) getContext();
if (mCategory == MainPanel.LOOKS) {
- activity.removeLook(action);
+ if ((FilterPresetRepresentation)action.getRepresentation() != null ){
+ activity.removePreset(action);
+ } else {
+ activity.removeLook(action);
+ }
} else if (mCategory == MainPanel.VERSIONS) {
activity.removeVersion(action);
}
@@ -231,6 +256,10 @@ public class CategoryAdapter extends ArrayAdapter<Action> {
int pos = preset.getPositionForType(FilterRepresentation.TYPE_FX);
if (pos != -1) {
rep = preset.getFilterRepresentation(pos);
+ } else {
+ pos = preset.getPositionForType(FilterRepresentation.TYPE_PRESETFILTER);
+ if (pos != -1)
+ rep = preset.getFilterRepresentation(pos);
}
} else if (mCategory == MainPanel.BORDERS) {
int pos = preset.getPositionForType(FilterRepresentation.TYPE_BORDER);
diff --git a/src/com/android/gallery3d/filtershow/category/CategoryPanel.java b/src/com/android/gallery3d/filtershow/category/CategoryPanel.java
index 3b91f024e..26c1dc36d 100644
--- a/src/com/android/gallery3d/filtershow/category/CategoryPanel.java
+++ b/src/com/android/gallery3d/filtershow/category/CategoryPanel.java
@@ -35,9 +35,9 @@ public class CategoryPanel extends Fragment implements View.OnClickListener {
public static final String FRAGMENT_TAG = "CategoryPanel";
private static final String PARAMETER_TAG = "currentPanel";
- private int mCurrentAdapter = MainPanel.LOOKS;
- private CategoryAdapter mAdapter;
- private IconView mAddButton;
+ protected int mCurrentAdapter = MainPanel.LOOKS;
+ protected CategoryAdapter mAdapter;
+ protected IconView mAddButton;
public void setAdapter(int value) {
mCurrentAdapter = value;
@@ -133,6 +133,13 @@ public class CategoryPanel extends Fragment implements View.OnClickListener {
}
break;
}
+ case MainPanel.WATERMARK: {
+ mAdapter = activity.getCategoryWatermarkAdapter();
+ if (mAdapter != null) {
+ mAdapter.initializeSelection(MainPanel.WATERMARK);
+ }
+ break;
+ }
}
updateAddButtonVisibility();
}
diff --git a/src/com/android/gallery3d/filtershow/category/CategoryPanelLevelTwo.java b/src/com/android/gallery3d/filtershow/category/CategoryPanelLevelTwo.java
new file mode 100644
index 000000000..bbb1b8087
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/category/CategoryPanelLevelTwo.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+package com.android.gallery3d.filtershow.category;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterWatermarkRepresentation;
+import com.android.gallery3d.filtershow.filters.FiltersManager;
+
+import java.util.ArrayList;
+
+public class CategoryPanelLevelTwo extends CategoryPanel {
+
+ private View mBottomPanel;
+ private ImageButton mExitButton;
+ private ImageButton mApplyButton;
+ private TextView mEditName;
+ private ArrayList<FilterRepresentation> mFiltersRepresentations;
+
+ public CategoryPanelLevelTwo(int adapter) {
+ setAdapter(adapter);
+ }
+
+ public CategoryPanelLevelTwo() {}
+
+ @Override
+ public void loadAdapter(int adapter) {
+ super.loadAdapter(adapter);
+ FilterShowActivity activity = (FilterShowActivity) getActivity();
+ switch (adapter) {
+ case FilterWatermarkRepresentation.LOCATION: {
+ mAdapter = activity.getCategoryLocationAdapter();
+ if (mAdapter != null) {
+ mAdapter.initializeSelection(MainPanel.WATERMARK);
+ }
+ break;
+ }
+ case FilterWatermarkRepresentation.TIME: {
+ mAdapter = activity.getCategoryTimeAdapter();
+ if (mAdapter != null) {
+ mAdapter.initializeSelection(MainPanel.WATERMARK);
+ }
+ break;
+ }
+ case FilterWatermarkRepresentation.WEATHER: {
+ mAdapter = activity.getCategoryWeatherAdapter();
+ if (mAdapter != null) {
+ mAdapter.initializeSelection(MainPanel.WATERMARK);
+ }
+ break;
+ }
+ case FilterWatermarkRepresentation.EMOTIONS: {
+ mAdapter = activity.getCategoryEmotionAdapter();
+ if (mAdapter != null) {
+ mAdapter.initializeSelection(MainPanel.WATERMARK);
+ }
+ break;
+ }
+ case FilterWatermarkRepresentation.FOOD: {
+ mAdapter = activity.getCategoryFoodAdapter();
+ if (mAdapter != null) {
+ mAdapter.initializeSelection(MainPanel.WATERMARK);
+ }
+ break;
+ }
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ LinearLayout main = (LinearLayout) inflater.inflate(
+ R.layout.filtershow_category_panel_two, container,
+ false);
+ FiltersManager filtersManager = FiltersManager.getManager();
+ mFiltersRepresentations = filtersManager.getWaterMarks();
+ mBottomPanel = main.findViewById(R.id.bottom_panel);
+ mExitButton = (ImageButton) main.findViewById(R.id.cancel);
+ mApplyButton = (ImageButton) main.findViewById(R.id.done);
+ final FilterShowActivity activity = (FilterShowActivity) getActivity();
+ mApplyButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ //Todo xukd add watermark to bufferimage
+ activity.disableTouchEvent();
+ activity.backToMain();
+ activity.setActionBar();
+ }
+ });
+ mExitButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ activity.cancelCurrentFilter();
+ activity.backToMain();
+ activity.setActionBar();
+ }
+ });
+ mEditName = (TextView) main.findViewById(R.id.editor_name);
+ mEditName.setText(mFiltersRepresentations.get(
+ mCurrentAdapter % FilterWatermarkRepresentation.LOCATION).getTextId());
+ View panelView = main.findViewById(R.id.listItems);
+ if (panelView instanceof CategoryTrack) {
+ CategoryTrack panel = (CategoryTrack) panelView;
+ if (mAdapter != null) {
+ mAdapter.setOrientation(CategoryView.HORIZONTAL);
+ panel.setAdapter(mAdapter);
+ mAdapter.setContainer(panel);
+ }
+ }
+ mAddButton = (IconView) main.findViewById(R.id.addButton);
+ if (mAddButton != null) {
+ mAddButton.setOnClickListener(this);
+ updateAddButtonVisibility();
+ }
+ return main;
+ }
+
+ private void setEditName() {
+
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/category/CategoryView.java b/src/com/android/gallery3d/filtershow/category/CategoryView.java
index 940627290..d9788cf00 100644
--- a/src/com/android/gallery3d/filtershow/category/CategoryView.java
+++ b/src/com/android/gallery3d/filtershow/category/CategoryView.java
@@ -24,15 +24,25 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.ContextThemeWrapper;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ActionMode;
+import android.widget.PopupMenu;
import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.app.Log;
import com.android.gallery3d.filtershow.FilterShowActivity;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterWatermarkRepresentation;
import com.android.gallery3d.filtershow.ui.SelectionRenderer;
+import java.util.ArrayList;
+
public class CategoryView extends IconView
- implements View.OnClickListener, SwipableView{
+ implements View.OnClickListener, SwipableView,View.OnLongClickListener,PopupMenu.OnMenuItemClickListener{
private static final String LOGTAG = "CategoryView";
public static final int VERTICAL = 0;
@@ -44,6 +54,7 @@ public class CategoryView extends IconView
private int mSelectionStroke;
private Paint mBorderPaint;
private int mBorderStroke;
+ private Context mContext;
private float mStartTouchX = 0;
private float mStartTouchY = 0;
private float mDeleteSlope = 20;
@@ -55,7 +66,9 @@ public class CategoryView extends IconView
public CategoryView(Context context) {
super(context);
+ mContext = context;
setOnClickListener(this);
+ setOnLongClickListener(this);
Resources res = getResources();
mSelectionStroke = res.getDimensionPixelSize(R.dimen.thumbnail_margin);
mSelectPaint = new Paint();
@@ -65,7 +78,7 @@ public class CategoryView extends IconView
mSelectPaint.setColor(mSelectionColor);
mBorderPaint = new Paint(mSelectPaint);
-// mBorderPaint.setColor(Color.BLACK);
+ mBorderPaint.setColor(res.getColor(R.color.filtershow_info_test));
mBorderStroke = mSelectionStroke / 3;
}
@@ -121,11 +134,21 @@ public class CategoryView extends IconView
}
}
super.onDraw(canvas);
+ if (mAction.getRepresentation() == null) {
+ return;
+ }
if (mAdapter.isSelected(this)) {
- SelectionRenderer.drawSelection(canvas, getMargin() / 2, getMargin(),
- getWidth() - getMargin() / 2, getHeight() - getMargin(),
- mSelectionStroke, mSelectPaint, mBorderStroke, mBorderPaint);
+ mAction.setClickAction();
+ if (mAction.getRepresentation().getFilterType() != FilterRepresentation.TYPE_WATERMARK_CATEGORY
+ && mAction.getRepresentation().getFilterType() != FilterRepresentation.TYPE_WATERMARK) {
+ SelectionRenderer.drawSelection(canvas, getMargin() / 2, getMargin(),
+ getWidth() - getMargin() / 2, getHeight() - getMargin(),
+ mSelectionStroke, mSelectPaint, mBorderStroke, mBorderPaint);
+ }
+ } else {
+ mAction.clearClickAction();
}
+ mAction.drawOverlay();
}
public void setAction(Action action, CategoryAdapter adapter) {
@@ -135,10 +158,11 @@ public class CategoryView extends IconView
mCanBeRemoved = action.canBeRemoved();
setUseOnlyDrawable(false);
if (mAction.getType() == Action.ADD_ACTION) {
- Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.filtershow_add);
+ Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
+ R.drawable.filtershow_add_new);
setBitmap(bitmap);
- setUseOnlyDrawable(true);
- setText(getResources().getString(R.string.filtershow_add_button_looks));
+ // setUseOnlyDrawable(true);
+ // setText(getResources().getString(R.string.filtershow_add_button_looks));
} else {
setBitmap(mAction.getImage());
}
@@ -172,12 +196,13 @@ public class CategoryView extends IconView
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
activity.startTouchAnimation(this, event.getX(), event.getY());
}
- if (!canBeRemoved()) {
+ if (!canBeRemoved() || checkPreset()) {
return ret;
}
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
mStartTouchY = event.getY();
mStartTouchX = event.getX();
+
}
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
setTranslationX(0);
@@ -188,7 +213,7 @@ public class CategoryView extends IconView
if (getOrientation() == CategoryView.VERTICAL) {
delta = event.getX() - mStartTouchX;
}
- if (Math.abs(delta) > mDeleteSlope) {
+ if (Math.abs(delta) > mDeleteSlope) {
activity.setHandlesSwipeForView(this, mStartTouchX, mStartTouchY);
}
}
@@ -196,6 +221,34 @@ public class CategoryView extends IconView
}
@Override
+ public boolean onLongClick(View view){
+ if (canBeRemoved()){
+ mAdapter.setSelected(this);
+ PopupMenu popup = new PopupMenu((FilterShowActivity)getContext(),view);
+ popup.getMenuInflater().inflate(R.menu.filtershow_menu_edit,popup.getMenu());
+ popup.setOnMenuItemClickListener(this);
+ popup.show();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onMenuItemClick (MenuItem item) {
+ FilterShowActivity activity = (FilterShowActivity) getContext();
+ switch (item.getItemId()) {
+ case R.id.deleteButton:
+ activity.handlePreset(mAction,this,R.id.deleteButton);
+ return true;
+ case R.id.renameButton:
+ activity.handlePreset(mAction,this,R.id.renameButton);
+ return true;
+ }
+ return false;
+ }
+
+
+ @Override
public void delete() {
mAdapter.remove(mAction);
}
@@ -205,6 +258,10 @@ public class CategoryView extends IconView
super.drawBottomRect(canvas);
FilterRepresentation filterRepresentation = mAction.getRepresentation();
if (filterRepresentation != null) {
+ if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_WATERMARK
+ || filterRepresentation.getFilterType() == FilterRepresentation.TYPE_WATERMARK_CATEGORY) {
+ return;
+ }
if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_FX) {
mPaint.setColor(getResources().getColor(filterRepresentation.getColorId()));
} else {
@@ -219,4 +276,15 @@ public class CategoryView extends IconView
mPaint);
}
}
+
+ private boolean checkPreset () {
+ FilterRepresentation filterRepresentation = mAction.getRepresentation();
+ if (filterRepresentation != null) {
+ if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_PRESETFILTER) {
+ return true;
+ }
+ }
+ return false;
+ }
+
}
diff --git a/src/com/android/gallery3d/filtershow/category/MainPanel.java b/src/com/android/gallery3d/filtershow/category/MainPanel.java
index 24912bb24..9a5612983 100755
--- a/src/com/android/gallery3d/filtershow/category/MainPanel.java
+++ b/src/com/android/gallery3d/filtershow/category/MainPanel.java
@@ -19,9 +19,12 @@ package com.android.gallery3d.filtershow.category;
import android.content.res.Configuration;
import android.content.Context;
import android.content.DialogInterface;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
+import android.text.TextUtils;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -29,6 +32,7 @@ import android.widget.ImageButton;
import android.widget.LinearLayout;
import org.codeaurora.gallery.R;
+import org.json.JSONObject;
import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.filtershow.FilterShowActivity;
@@ -46,6 +50,9 @@ import com.android.gallery3d.filtershow.tools.TruePortraitNativeEngine;
import com.android.gallery3d.filtershow.ui.DoNotShowAgainDialog;
import com.android.gallery3d.util.GalleryUtils;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
public class MainPanel extends Fragment implements BottomPanel.BottomPanelDelegate {
private static final String LOGTAG = "MainPanel";
@@ -62,6 +69,7 @@ public class MainPanel extends Fragment implements BottomPanel.BottomPanelDelega
private ImageButton hazeBusterButton;
private ImageButton seeStraightButton;
private ImageButton truePortraitButton;
+ private ImageButton waterMarkButton;
public static final String FRAGMENT_TAG = "MainPanel";
public static final String EDITOR_TAG = "coming-from-editor-panel";
@@ -76,6 +84,7 @@ public class MainPanel extends Fragment implements BottomPanel.BottomPanelDelega
public static final int HAZEBUSTER = 8;
public static final int SEESTRAIGHT = 9;
public static final int TRUEPORTRAIT = 10;
+ public static final int WATERMARK = 11;
private int mCurrentSelected = -1;
private int mPreviousToggleVersions = -1;
@@ -134,6 +143,10 @@ public class MainPanel extends Fragment implements BottomPanel.BottomPanelDelega
}
break;
}
+ case WATERMARK: {
+ waterMarkButton.setSelected(value);
+ break;
+ }
}
}
@@ -220,6 +233,14 @@ public class MainPanel extends Fragment implements BottomPanel.BottomPanelDelega
truePortraitButton.setVisibility(View.GONE);
}
+ waterMarkButton = (ImageButton) bottomPanel.findViewById(R.id.waterMarkButton);
+
+ waterMarkButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ showPanel(WATERMARK);
+ }
+ });
looksButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -247,7 +268,23 @@ public class MainPanel extends Fragment implements BottomPanel.BottomPanelDelega
dualCamButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- showPanel(DUALCAM);
+ Context context = getActivity();
+ boolean skipIntro = GalleryUtils.getBooleanPref(context,
+ context.getString(R.string.pref_dualcam_intro_show_key), false);
+ if (skipIntro) {
+ showPanel(DUALCAM);
+ } else {
+ DoNotShowAgainDialog dialog = new DoNotShowAgainDialog(
+ R.string.dual_camera_effects, R.string.dual_camera_effects_intro,
+ R.string.pref_dualcam_intro_show_key);
+ dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ showPanel(DUALCAM);
+ }
+ });
+ dialog.show(getFragmentManager(), "dualcam_intro");
+ }
}
});
@@ -263,10 +300,10 @@ public class MainPanel extends Fragment implements BottomPanel.BottomPanelDelega
} else if(!skipIntro) {
DoNotShowAgainDialog dialog = new DoNotShowAgainDialog(
R.string.trueportrait, R.string.trueportrait_intro,
- R.string.pref_trueportrait_intro_show_key) {
+ R.string.pref_trueportrait_intro_show_key);
+ dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
- super.onDismiss(dialog);
if(facesDetected) {
showPanel(TRUEPORTRAIT);
} else {
@@ -274,7 +311,7 @@ public class MainPanel extends Fragment implements BottomPanel.BottomPanelDelega
TruePortraitNativeEngine.getInstance().showNoFaceDetectedDialog(getFragmentManager());
}
}
- };
+ });
dialog.show(getFragmentManager(), "trueportrait_intro");
} else {
v.setEnabled(false);
@@ -511,6 +548,94 @@ public class MainPanel extends Fragment implements BottomPanel.BottomPanelDelega
selection(mCurrentSelected, true);
}
+ public void loadWaterMarkPanel() {
+ if (mCurrentSelected == WATERMARK) {
+ return;
+ }
+ boolean fromRight = isRightAnimation(WATERMARK);
+ selection(mCurrentSelected, false);
+ CategoryPanel categoryPanel = new CategoryPanel();
+ categoryPanel.setAdapter(WATERMARK);
+ setCategoryFragment(categoryPanel, fromRight);
+ mCurrentSelected = WATERMARK;
+ selection(mCurrentSelected, true);
+ final FilterShowActivity activity = (FilterShowActivity) getActivity();
+// String url = "http://api.map.baidu.com/location/ip?ak=PR0TaSQODfSbVr7hkcNF4NkAYEixoxSy&coor=bd09ll";
+ String url = "";
+ new AsyncTask<String, Void, String>() {
+ @Override
+ protected String doInBackground(String... strings) {
+ HttpURLConnection connection = null;
+ String location = "";
+ try {
+ URL url = new URL(strings[0]);
+ connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setRequestProperty("Charset", "UTF-8");
+ connection.connect();
+ if (connection.getResponseCode() == 200) {
+ String result = WaterMarkView.convertStream2String(connection.getInputStream());
+ JSONObject resultJson = new JSONObject(result);
+ location = resultJson.getJSONObject("content").getString("address");
+ if (!TextUtils.isEmpty(location)) {
+ getWeather(activity, location);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (connection != null) {
+ connection.disconnect();
+ }
+ }
+ return location;
+ }
+
+ @Override
+ protected void onPostExecute(String s) {
+ activity.setLocation(s);
+ }
+ }.execute(url);
+ }
+
+ private void getWeather(final FilterShowActivity activity, String city) {
+// String url = "http://api.map.baidu.com/telematics/v3/weather?location="
+// + city + "&output=json&ak=PR0TaSQODfSbVr7hkcNF4NkAYEixoxSy";
+ String url = "";
+ new AsyncTask<String, Void, String>() {
+ @Override
+ protected String doInBackground(String... strings) {
+ HttpURLConnection connection = null;
+ String temperature = "";
+ try {
+ URL url = new URL(strings[0]);
+ connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setRequestProperty("Charset", "UTF-8");
+ connection.connect();
+ if (connection.getResponseCode() == 200) {
+ String result = WaterMarkView.convertStream2String(connection.getInputStream());
+ JSONObject resultJson = new JSONObject(result);
+ String weather = resultJson.getJSONArray("results").getJSONObject(0).getJSONArray("weather_data").getJSONObject(0).getString("date");
+ temperature = weather.substring(weather.indexOf(":")+1, weather.indexOf(")"));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (connection != null) {
+ connection.disconnect();
+ }
+ }
+ return temperature;
+ }
+
+ @Override
+ protected void onPostExecute(String s) {
+ activity.setTemperature(s);
+ }
+ }.execute(url);
+ }
+
public void showPanel(int currentPanel) {
FilterShowActivity activity = (FilterShowActivity) getActivity();
if (null == activity) {
@@ -561,6 +686,10 @@ public class MainPanel extends Fragment implements BottomPanel.BottomPanelDelega
loadCategoryTruePortraitPanel();
break;
}
+ case WATERMARK: {
+ loadWaterMarkPanel();
+ break;
+ }
}
if (currentPanel > 0) {
activity.adjustCompareButton(true);
@@ -631,18 +760,4 @@ public class MainPanel extends Fragment implements BottomPanel.BottomPanelDelega
dualCamButton.setVisibility(enable?View.VISIBLE:View.GONE);
}
}
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- if (ApiHelper.getBooleanFieldIfExists(newConfig, "userSetLocale", false)) {
- FiltersManager.reset();
- FilterShowActivity activity = (FilterShowActivity) getActivity();
- activity.getProcessingService().setupPipeline();
- activity.fillCategories();
- if (mCurrentSelected != -1) {
- showPanel(mCurrentSelected);
- }
- }
- }
}
diff --git a/src/com/android/gallery3d/filtershow/category/WaterMarkTimeView.java b/src/com/android/gallery3d/filtershow/category/WaterMarkTimeView.java
new file mode 100644
index 000000000..86a8a7628
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/category/WaterMarkTimeView.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+package com.android.gallery3d.filtershow.category;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
+import android.widget.EditText;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import org.codeaurora.gallery.R;
+
+public class WaterMarkTimeView extends WaterMarkView {
+ public WaterMarkTimeView(Context context) {
+ super(context);
+ }
+ public WaterMarkTimeView(Context context, Drawable drawable, int type) {
+ super(context);
+ init(context, drawable, type);
+ }
+
+ private void init(Context context, Drawable drawable, int type) {
+ DisplayMetrics dm = getResources().getDisplayMetrics();
+ widthScreen = dm.widthPixels;
+ heightScreen = dm.heightPixels;
+ initView(context, drawable, type);
+ }
+
+ private void initView(Context context, Drawable drawable, int type) {
+ LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ FrameLayout layout = (FrameLayout)inflater.inflate(R.layout.filtershow_watermark, this, true);
+ mImageView = (ImageView) layout.findViewById(R.id.image);
+ mMarkDrawable = drawable;
+ mImageView.setBackground(drawable);
+ markLayout = (FrameLayout) layout.findViewById(R.id.root_layout);
+
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/category/WaterMarkView.java b/src/com/android/gallery3d/filtershow/category/WaterMarkView.java
new file mode 100644
index 000000000..36ba392d3
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/category/WaterMarkView.java
@@ -0,0 +1,522 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+package com.android.gallery3d.filtershow.category;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.ViewGroup;
+import android.widget.EditText;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+
+import org.codeaurora.gallery.R;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class WaterMarkView extends FrameLayout {
+ private static final int NONE = 0;
+ private static final int DRAG = 1;
+ private static final int ZOOM = 2;
+
+ private int mode = NONE;
+
+ private float x_down = 0;
+ private float y_down = 0;
+ private float moveX;
+ private float moveY;
+ private float scaleMoveX = 0;
+ private float scaleMoveY = 0;
+ private float finalMoveX;
+ private float finalMoveY;
+ private float rotation;
+ private float oldRotation = 0;
+ private float lastRotation = 0;
+ private float finalRotation;
+ private float scale = 1f;
+ private float lastScale = 1f;
+ private float oldDist = 1f;
+ private float newDist;
+ private Rect imageBounds;
+ protected int widthScreen;
+ protected int heightScreen;
+ private String text;
+
+ private EditText mEditText;
+ protected FrameLayout markLayout;
+ protected Drawable mMarkDrawable;
+ protected ImageView mImageView;
+
+ //control the bounds of the watermark
+ private float markLeft;
+ private float markTop;
+ private float markRight;
+ private float markBottom;
+
+ private GeometryMathUtils.GeometryHolder mGeometry;
+ private Matrix mDisplaySegPointsMatrix;
+ private Matrix oldImageToScreenMatrix;
+ private RectF markLayoutRect = new RectF(markLeft, markTop, markRight, markBottom);
+ private int newWidth;
+ private int newHeight;
+ private int oldWidth;
+ private int oldHeight;
+ private boolean sizeChanged = false;
+ public boolean mTouchable;
+
+ public WaterMarkView(Context context) {
+ super(context);
+ }
+
+ public WaterMarkView(Context context, Drawable drawable, String text) {
+ super(context);
+ init(context, drawable, text);
+ }
+
+ private void init(Context context, Drawable drawable, String text) {
+ updateScreenSize();
+ initView(context, drawable, text);
+
+ MasterImage.getImage().addWaterMark(this);
+ mGeometry = new GeometryMathUtils.GeometryHolder();
+ imageBounds = MasterImage.getImage().getImageBounds();
+ }
+
+ private void initView(Context context, Drawable drawable, String text) {
+ LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ FrameLayout layout = (FrameLayout)inflater.inflate(R.layout.filtershow_watermark, this, true);
+ mImageView = (ImageView) layout.findViewById(R.id.image);
+ mMarkDrawable = drawable;
+ mImageView.setBackground(drawable);
+ markLayout = (FrameLayout) layout.findViewById(R.id.root_layout);
+ mEditText = (EditText) layout.findViewById(R.id.edit);
+ mEditText.setHint(text);
+ mEditText.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ setTextContent(s.toString());
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+
+ }
+ });
+ initMarkBounds();
+ }
+
+ public void clearEditTextCursor() {
+ mEditText.setCursorVisible(false);
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ if (oldw == 0 || oldh == 0) {
+ Bitmap mBitmap = MasterImage.getImage().getHighresImage();
+ oldImageToScreenMatrix = MasterImage.getImage().computeImageToScreen(mBitmap, 0, false);
+ return;
+ }
+ newWidth = w;
+ newHeight = h;
+ oldWidth = oldw;
+ oldHeight = oldh;
+ sizeChanged = true;
+ updateScreenSize();
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ if (rotation > 0 || rotation < 0) {
+ finalRotation = lastRotation + rotation;
+ markLayout.setRotation(finalRotation);
+ }
+ if (scale > 0) {
+ markLayout.setScaleX(scale);
+ markLayout.setScaleY(scale);
+ }
+ if (moveX != 0 || moveY != 0) {
+ finalMoveX = markLeft + moveX - scaleMoveX;
+ finalMoveY = markTop + moveY - scaleMoveY;
+ markLayout.setTranslationX(finalMoveX);
+ markLayout.setTranslationY(finalMoveY);
+ }
+ super.onLayout(changed, l, t, r, b);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (!mTouchable) return false;
+ switch (event.getAction() & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN:
+ markLayout.setFocusable(true);
+ markLayout.setFocusableInTouchMode(true);
+ mEditText.clearFocus();
+ mode = isOutMark(event) ? NONE : DRAG;
+ x_down = event.getX();
+ y_down = event.getY();
+ break;
+ case MotionEvent.ACTION_POINTER_DOWN:
+ mode = isOutMark(event) ? NONE : ZOOM;
+ if (mode == ZOOM) {
+ markLayout.setBackgroundResource(R.drawable.grid_pressed);
+ }
+ oldDist = spacing(event);
+ oldRotation = rotation(event);
+ break;
+ case MotionEvent.ACTION_MOVE:
+ switch (mode) {
+ case ZOOM:
+ rotation = rotation(event) - oldRotation;
+ newDist = spacing(event);
+ scale = (newDist / oldDist) * lastScale;
+ break;
+ case DRAG:
+ if (!outBound(event.getX(), event.getY())) {
+ moveX = event.getX() - x_down;
+ moveY = event.getY() - y_down;
+ }
+ break;
+ case NONE:
+ break;
+ }
+ requestLayout();
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_POINTER_UP:
+ switch (mode) {
+ case ZOOM:
+ lastRotation += rotation;
+ lastScale = scale;
+ float thisScale = newDist / oldDist;
+ if (thisScale > 0 && thisScale != 1f) {
+ float halfNewWidth = (markLayout.getMeasuredWidth() * scale) / 2;
+ float halfNewHeight = (markLayout.getMeasuredHeight() * scale) / 2;
+ float l, t, r, b;
+ l = markLeft;
+ t = markTop;
+ r = markRight;
+ b = markBottom;
+ markLeft = getMid(l, r) - halfNewWidth;
+ markTop = getMid(t, b) - halfNewHeight;
+ markRight = getMid(l, r) + halfNewWidth;
+ markBottom = getMid(t, b) + halfNewHeight;
+ updateMarkLayoutRect();
+ scaleMoveX = markLayout.getMeasuredWidth()/2 - halfNewWidth;
+ scaleMoveY = markLayout.getMeasuredHeight()/2 - halfNewHeight;
+ }
+ markLayout.setBackground(null);
+ break;
+ case DRAG:
+ if (moveX != 0) {
+ markLeft += moveX;
+ markRight += moveX;
+ }
+ if (moveY != 0) {
+ markTop += moveY;
+ markBottom += moveY;
+ }
+ updateMarkLayoutRect();
+ break;
+ }
+ moveX = 0;
+ moveY = 0;
+ rotation = 0;
+ mode = NONE;
+ break;
+ }
+ return true;
+ }
+
+ private boolean outBound(float x, float y) {
+ if (imageBounds == null) {
+ return true;
+ }
+ return x < (imageBounds.left < 0 ? 0 : imageBounds.left) + x_down - markLeft
+ || x > (imageBounds.right > widthScreen ? widthScreen : imageBounds.right) + x_down - markRight
+ || y < (imageBounds.top < 0 ? 0 : imageBounds.top) + y_down - markTop
+ || y > (imageBounds.bottom > heightScreen ? heightScreen : imageBounds.bottom) + y_down - markBottom;
+ }
+
+ private boolean isOutMark(MotionEvent event) {
+ switch (event.getAction() & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN:
+ float x = event.getX();
+ float y = event.getY();
+ return x < markLeft || x > markRight || y < markTop || y > markBottom;
+ case MotionEvent.ACTION_POINTER_DOWN:
+ float x0 = event.getX(0);
+ float y0 = event.getY(0);
+ float x1 = event.getX(1);
+ float y1 = event.getY(1);
+ return (x0 < markLeft || x0 > markRight || y0 < markTop || y0 > markBottom)
+ &&(x1 < markLeft || x1 > markRight || y1 < markTop || y1 > markBottom);
+ }
+ return false;
+ }
+ private float getMid(float x1, float x2) {
+ return (x1 + x2) / 2;
+ }
+
+ private float spacing(MotionEvent event) {
+ float x = event.getX(0) - event.getX(1);
+ float y = event.getY(0) - event.getY(1);
+ return (float) Math.sqrt(x * x + y * y);
+ }
+
+ private float rotation(MotionEvent event) {
+ double delta_x = (event.getX(0) - event.getX(1));
+ double delta_y = (event.getY(0) - event.getY(1));
+ double radians = Math.atan2(delta_y, delta_x);
+ return (float) Math.toDegrees(radians);
+ }
+
+ protected void initMarkBounds() {
+ if (widthScreen > heightScreen) {
+ if (MasterImage.getImage().getFilteredImage().getWidth() >
+ MasterImage.getImage().getFilteredImage().getHeight()) {
+ markLeft = dip2px(getContext(), 50);
+ } else {
+ markLeft = dip2px(getContext(), 200);
+ }
+ markTop = dip2px(getContext(), 35);
+ markBottom = markTop + dip2px(getContext(), 100);
+ markRight = markLeft + dip2px(getContext(), 80);
+ } else {
+ markLeft = dip2px(getContext(), 50);
+ if (MasterImage.getImage().getFilteredImage().getWidth() >
+ MasterImage.getImage().getFilteredImage().getHeight()) {
+ markTop = dip2px(getContext(), 200);
+ } else {
+ markTop = dip2px(getContext(), 70);
+ }
+ markBottom = markTop + dip2px(getContext(), 100);
+ markRight = markLeft + dip2px(getContext(), 80);
+ }
+ updateMarkLayoutRect();
+ markLayout.setTranslationX(markLeft);
+ markLayout.setTranslationY(markTop);
+ }
+
+ private void updateMarkLayoutRect() {
+ markLayoutRect.left = markLeft;
+ markLayoutRect.right = markRight;
+ markLayoutRect.top = markTop;
+ markLayoutRect.bottom = markBottom;
+ }
+
+ private void updateScreenSize() {
+ DisplayMetrics dm = getResources().getDisplayMetrics();
+ widthScreen = dm.widthPixels;
+ heightScreen = dm.heightPixels;
+ }
+
+ /**
+ * save view as a bitmap
+ */
+ public Bitmap creatNewPhoto() {
+ // get current view bitmap
+ markLayout.buildDrawingCache();
+ Bitmap bitmap = markLayout.getDrawingCache();
+
+ Bitmap bmp = duplicateBitmap(bitmap);
+// if (bitmap != null && !bitmap.isRecycled()) { bitmap.recycle(); }
+ // clear the cache
+ markLayout.setDrawingCacheEnabled(false);
+ return bmp;
+ }
+
+ private Bitmap duplicateBitmap(Bitmap bmpSrc) {
+ if (null == bmpSrc) {
+ return null;
+ }
+
+ Rect r = MasterImage.getImage().getImageBounds();
+ Bitmap b = MasterImage.getImage().getFilteredImage();
+ Bitmap bmpDest = Bitmap.createBitmap(r.width(), r.height(), Bitmap.Config.ARGB_8888);
+ if (null != bmpDest) {
+ Canvas canvas = new Canvas(bmpDest);
+ Matrix m = new Matrix();
+ m.setScale(scale, scale);
+ m.postRotate(getFinalRotation());
+ if (b.getWidth() < b.getHeight()) {
+ int deltaX = (r.width() - widthScreen) / 2;
+ m.postTranslate((int) markLeft + deltaX, (int) markTop);
+ } else {
+ int deltaY = (r.height() - heightScreen) / 2;
+ m.postTranslate((int) markLeft, (int) markTop + deltaY);
+ }
+ canvas.drawBitmap(bmpSrc, m, null);
+ }
+ return bmpDest;
+ }
+
+ private int dip2px(Context context, float dipValue) {
+ final float scale = context.getResources().getDisplayMetrics().density;
+ return (int) (dipValue * scale + 0.5f);
+ }
+
+ /**
+ * @param left margin left
+ * @param top margin top
+ * @param right margin right
+ * @param bottom margin bottom
+ * @param gravity gravity value
+ * @param isDipValue true means the values of left top right bottom are dip not px
+ */
+ public void setTextPosition(int left, int top, int right, int bottom,
+ int gravity, boolean isDipValue) {
+ FrameLayout.LayoutParams params =
+ new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ if (isDipValue) {
+ left = dip2px(getContext(), left);
+ top = dip2px(getContext(), top);
+ right = dip2px(getContext(), right);
+ bottom = dip2px(getContext(), bottom);
+ }
+ params.gravity = gravity;
+ params.setMargins(left, top, right, bottom);
+ mEditText.setLayoutParams(params);
+ }
+
+ public void setTextVisibility(boolean visible) {
+ mEditText.setVisibility(visible ? VISIBLE : GONE);
+ }
+
+ public void setImageAlpha(int alpha) {
+ mMarkDrawable.setAlpha(alpha);
+ mImageView.setBackground(mMarkDrawable);
+ }
+
+ public static String convertStream2String(InputStream inputStream) {
+ StringBuilder sb = new StringBuilder();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
+ String oneLine;
+ try {
+ while ((oneLine = reader.readLine()) != null) {
+ sb.append(oneLine + "\n");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return sb.toString();
+ }
+
+ public RectF getMarkLayoutRect() {
+ return markLayoutRect;
+ }
+
+ public float getFinalMoveY() {
+ return finalMoveY;
+ }
+
+ public float getFinalRotation() {
+ return finalRotation;
+ }
+
+ public float getFinalMoveX() {
+ return finalMoveX;
+ }
+
+ public float getFinalScale() {
+ return lastScale;
+ }
+
+ public String getTextContent() {
+ return text;
+ }
+ public void setTextContent(String text) {
+ this.text = text;
+ }
+
+ public void update() {
+ imageBounds = MasterImage.getImage().getImageBounds();
+ if (!sizeChanged) return;
+ sizeChanged = false;
+ float mw = markLayoutRect.width();
+ Matrix mx = new Matrix();
+ mx.setTranslate(-markLayoutRect.width()/2, -markLayoutRect.height()/2);
+ mx.mapRect(markLayoutRect);
+ mx.reset();
+ oldImageToScreenMatrix.invert(mx);
+ mx.mapRect(markLayoutRect);
+ Bitmap mBitmap = MasterImage.getImage().getHighresImage();
+ oldImageToScreenMatrix = MasterImage.getImage().computeImageToScreen(mBitmap, 0, false);
+ oldImageToScreenMatrix.mapRect(markLayoutRect);
+ mx.reset();
+ mx.setTranslate(markLayoutRect.width()/2,markLayoutRect.height()/2);
+ mx.mapRect(markLayoutRect);
+
+// Bitmap mBitmap = MasterImage.getImage().getFilteredImage();
+// scale = scale * GeometryMathUtils.getWatermarkScale(mGeometry, mBitmap.getWidth(),
+// mBitmap.getHeight(), w, h, oldw, oldh);
+// mDisplaySegPointsMatrix = GeometryMathUtils.getWatermarkMatrix(mGeometry, mBitmap.getWidth(),
+// mBitmap.getHeight(), w, h, oldw, oldh);
+// mDisplaySegPointsMatrix.mapRect(markLayoutRect);
+ scale = scale * markLayoutRect.width() / mw;
+ markLeft = markLayoutRect.left;
+ markTop = markLayoutRect.top;
+ markRight = markLayoutRect.right;
+ markBottom = markLayoutRect.bottom;
+ markLayout.setPivotX(0);
+ markLayout.setPivotY(0);
+ markLayout.setScaleX(scale);
+ markLayout.setScaleY(scale);
+ markLayout.setTranslationX(markLayoutRect.left);
+ markLayout.setTranslationY(markLayoutRect.top);
+ requestLayout();
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/data/FilterPresetDBHelper.java b/src/com/android/gallery3d/filtershow/data/FilterPresetDBHelper.java
new file mode 100644
index 000000000..9840f9f84
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/data/FilterPresetDBHelper.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.filtershow.data;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+public class FilterPresetDBHelper extends SQLiteOpenHelper {
+
+ public static final int DATABASE_VERSION = 1;
+ public static final String DATABASE_NAME = "filterspreset.db";
+ private static final String SQL_CREATE_TABLE = "CREATE TABLE ";
+
+ public static interface FilterPreset {
+ /** The row uid */
+ public static final String _ID = "_id";
+ /** The table name */
+ public static final String TABLE = "filterspreset";
+ /** The preset name */
+ public static final String PRESET_ID = "preset_id";
+ /** A serialized preset of filters. */
+ public static final String FILTER_PRESET= "preset";
+ }
+
+ private static final String[][] CREATE_FILTER_PRESET = {
+ { FilterPreset._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" },
+ { FilterPreset.PRESET_ID, "TEXT" },
+ { FilterPreset.FILTER_PRESET, "Uri" },
+ };
+
+ public FilterPresetDBHelper(Context context, String name, int version) {
+ super(context, name, null, version);
+ }
+
+ public FilterPresetDBHelper(Context context, String name) {
+ this(context, name, DATABASE_VERSION);
+ }
+
+ public FilterPresetDBHelper(Context context) {
+ this(context, DATABASE_NAME);
+ }
+
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ createTable(db, FilterPreset.TABLE, CREATE_FILTER_PRESET);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ dropTable(db, FilterPreset.TABLE);
+ onCreate(db);
+ }
+
+ protected static void createTable(SQLiteDatabase db, String table, String[][] columns) {
+ StringBuilder create = new StringBuilder(SQL_CREATE_TABLE);
+ create.append(table).append('(');
+ boolean first = true;
+ for (String[] column : columns) {
+ if (!first) {
+ create.append(',');
+ }
+ first = false;
+ for (String val : column) {
+ create.append(val).append(' ');
+ }
+ }
+ create.append(')');
+ db.beginTransaction();
+ try {
+ db.execSQL(create.toString());
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ }
+
+ protected static void dropTable(SQLiteDatabase db, String table) {
+ db.beginTransaction();
+ try {
+ db.execSQL("drop table if exists " + table);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ }
+}
+
diff --git a/src/com/android/gallery3d/filtershow/data/FilterPresetSource.java b/src/com/android/gallery3d/filtershow/data/FilterPresetSource.java
new file mode 100644
index 000000000..f0cbba46b
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/data/FilterPresetSource.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.filtershow.data;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
+import android.net.Uri;
+import android.util.Log;
+
+import com.android.gallery3d.filtershow.data.FilterPresetDBHelper.FilterPreset;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.ArrayList;
+
+public class FilterPresetSource {
+ private static final String LOGTAG = "FilterStackSource";
+
+ private SQLiteDatabase database = null;
+ private final FilterPresetDBHelper dbHelper;
+ private Context mContext;
+
+ public FilterPresetSource(Context context) {
+ mContext = context;
+ dbHelper = new FilterPresetDBHelper(context);
+ open();
+ }
+
+ public void open() {
+ try {
+ database = dbHelper.getWritableDatabase();
+ } catch (SQLiteException e) {
+ Log.w(LOGTAG, "could not open database", e);
+ }
+ }
+
+ public void close() {
+ database = null;
+ dbHelper.close();
+ }
+
+ public static class SaveOption {
+ public int _id;
+ public String name;
+ public String Uri;
+ }
+
+ public boolean insertPreset(String presetName, String presetUri) {
+ boolean ret = true;
+ ContentValues val = new ContentValues();
+ val.put(FilterPreset.PRESET_ID, presetName);
+ val.put(FilterPreset.FILTER_PRESET, presetUri);
+ database.beginTransaction();
+ try {
+ ret = (-1 != database.insert(FilterPreset.TABLE, null, val));
+ database.setTransactionSuccessful();
+ } finally {
+ database.endTransaction();
+ }
+ return ret;
+ }
+
+ public void updatePresetName(int id, String presetName) {
+ ContentValues val = new ContentValues();
+ val.put(FilterPreset.PRESET_ID, presetName);
+ database.beginTransaction();
+ try {
+ database.update(FilterPreset.TABLE, val,FilterPreset._ID + " = ?",
+ new String[] { "" + id});
+ database.setTransactionSuccessful();
+ } finally {
+ database.endTransaction();
+ }
+ }
+
+ public boolean removePreset(int id) {
+ boolean ret = true;
+ database.beginTransaction();
+ try {
+ ret = (0 != database.delete(FilterPreset.TABLE, FilterPreset._ID + " = ?",
+ new String[] { "" + id }));
+ database.setTransactionSuccessful();
+ } finally {
+ database.endTransaction();
+ }
+ return ret;
+ }
+
+ public ArrayList<SaveOption> getAllUserPresets() {
+ ArrayList<SaveOption> ret = new ArrayList<SaveOption>();
+ Cursor c = null;
+ database.beginTransaction();
+ try {
+ c = database.query(FilterPreset.TABLE,
+ new String[] { FilterPreset._ID,
+ FilterPreset.PRESET_ID,
+ FilterPreset.FILTER_PRESET },
+ null, null, null, null, null, null);
+ if (c != null) {
+ boolean loopCheck = c.moveToFirst();
+ while (loopCheck) {
+ String id = (c.isNull(0)) ? null : c.getString(0);
+ String name = (c.isNull(1)) ? null : c.getString(1);
+ String filterUri = (c.isNull(2)) ? null : c.getString(2);
+ SaveOption so = new SaveOption();
+ try {
+ so._id = Integer.parseInt(id);
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+ so.name = name;
+ so.Uri = filterUri;
+ if (!checkUriExist(filterUri)) {
+ removePreset(so._id);
+ loopCheck = c.moveToNext();
+ continue;
+ }
+ ret.add(so);
+ loopCheck = c.moveToNext();
+ }
+ }
+ database.setTransactionSuccessful();
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ database.endTransaction();
+ }
+ return ret;
+ }
+
+ private boolean checkUriExist(String uriStr) {
+ boolean ret = true;
+ if (uriStr == null) return false;
+ Uri uri = Uri.parse(uriStr);
+ try {
+ InputStream is = mContext.getContentResolver().openInputStream(uri);
+ } catch (FileNotFoundException e) {
+ ret = false;
+ e.printStackTrace();
+ Log.e(LOGTAG, "FileNotFoundException for " + uri, e);
+ }
+ return ret;
+ }
+ }
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java b/src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java
index 2371ccb15..f298b75a4 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -30,37 +30,58 @@
package com.android.gallery3d.filtershow.editors;
import android.content.Context;
+import android.content.DialogInterface;
import android.net.Uri;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+import android.view.LayoutInflater;
+import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
-import android.widget.Button;
+import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
-import org.codeaurora.gallery.R;
import com.android.gallery3d.filtershow.FilterShowActivity;
import com.android.gallery3d.filtershow.filters.FilterDualCamFusionRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.imageshow.ImageFusion;
import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.ui.DoNotShowAgainDialog;
+import com.android.gallery3d.util.GalleryUtils;
+
+import org.codeaurora.gallery.R;
-public class EditorDualCamFusion extends ImageOnlyEditor {
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class EditorDualCamFusion extends Editor {
public static final String TAG = EditorDualCamFusion.class.getSimpleName();
public static final int ID = R.id.editorDualCamFusion;
protected ImageFusion mImageFusion;
- private Button mPickUnderlayBtn;
- private OnClickListener mPickBtnClickListener = new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- MasterImage.getImage().getActivity().pickImage(FilterShowActivity.SELECT_FUSION_UNDERLAY);
- }
- };
+ private Uri mUnderlayUri = Uri.EMPTY;
public EditorDualCamFusion() {
super(ID);
}
+ @Override
+ public boolean showsActionBar() {
+ return true;
+ }
+
+ @Override
+ public boolean showsActionBarControls() {
+ return false;
+ }
+
+ @Override
+ public void onPrepareOptionsMenu(Menu menu) {
+ menu.clear();
+ }
+
public boolean useUtilityPanel() {
return true;
}
@@ -77,48 +98,123 @@ public class EditorDualCamFusion extends ImageOnlyEditor {
@Override
public void setEditPanelUI(View editControl) {
- editControl.setVisibility(View.GONE);
+ ViewGroup controlContainer = (ViewGroup) editControl;
+ controlContainer.removeAllViews();
+
+ LayoutInflater inflater = (LayoutInflater) mContext.getSystemService
+ (Context.LAYOUT_INFLATER_SERVICE);
+ View controls = inflater.inflate(R.layout.filtershow_seekbar, controlContainer);
+ View seekbar = controls.findViewById(R.id.primarySeekBar);
+ seekbar.setVisibility(View.GONE);
+ View saveButton = controls.findViewById(R.id.slider_save);
+ if (saveButton != null) {
+ saveButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ FilterShowActivity activity = (FilterShowActivity) mContext;
+ finalApplyCalled();
+ activity.leaveSeekBarPanel();
+ }
+ });
+ }
+ View cancelButton = controls.findViewById(R.id.slider_cancel);
+ if (cancelButton != null) {
+ cancelButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ FilterShowActivity activity = (FilterShowActivity) mContext;
+ activity.cancelCurrentFilter();
+ activity.leaveSeekBarPanel();
+ }
+ });
+ }
}
@Override
public void openUtilityPanel(final LinearLayout accessoryViewList) {
- super.openUtilityPanel(accessoryViewList);
- mPickUnderlayBtn = (Button) accessoryViewList.findViewById(R.id.applyEffect);
- updateText();
- }
-
- public void setUnderlayImageUri(Uri uri) {
- FilterRepresentation filter = getLocalRepresentation();
- if(filter instanceof FilterDualCamFusionRepresentation) {
- mImageFusion.setUnderlay(uri);
- commitLocalRepresentation();
+ accessoryViewList.removeAllViews();
+
+ LayoutInflater inflater = (LayoutInflater) mContext.getSystemService
+ (Context.LAYOUT_INFLATER_SERVICE);
+ inflater.inflate(R.layout.filtershow_actionbar_dualcam_fusion, accessoryViewList);
+
+ View pickUnderlayBtn = accessoryViewList.findViewById(R.id.pick_underlay);
+ pickUnderlayBtn.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ MasterImage.getImage().getActivity().pickImage(FilterShowActivity.SELECT_FUSION_UNDERLAY);
+ }
+ });
+
+ // Look for previous underlay
+ String fusionUnderlay = GalleryUtils.getStringPref(mContext,
+ mContext.getString(R.string.pref_dualcam_fusion_underlay_key), null);
+ Uri fusionUri = Uri.EMPTY;
+
+ if (fusionUnderlay != null) {
+ fusionUri = Uri.parse(fusionUnderlay);
+ if (!uriExists(mContext, fusionUri))
+ fusionUri = Uri.EMPTY;
}
- }
- private void updateEffectButton(boolean enabled) {
- mPickUnderlayBtn.setEnabled(enabled);
- if(enabled) {
- mPickUnderlayBtn.setOnClickListener(mPickBtnClickListener);
- mPickUnderlayBtn.setText(R.string.fusion_pick_underlay);
- } else {
- mPickUnderlayBtn.setOnClickListener(null);
- mPickUnderlayBtn.setText(R.string.fusion_pick_point);
- }
+ setUnderlayImageUri(fusionUri);
}
-
- protected void updateText() {
- if(mPickUnderlayBtn != null) {
- updateEffectButton(hasSegment());
+ @Override
+ public void resume() {
+ if (mUnderlayUri.equals(Uri.EMPTY)) {
+ // No underlay set.
+ boolean skipIntro = GalleryUtils.getBooleanPref(mContext,
+ mContext.getString(R.string.pref_dualcam_fusion_intro_show_key), false);
+ if (!skipIntro) {
+ FragmentManager fm = ((FilterShowActivity) mContext).getSupportFragmentManager();
+ DoNotShowAgainDialog dialog =
+ (DoNotShowAgainDialog) fm.findFragmentByTag("dualcam_fusion_intro");
+ if (dialog == null) {
+ dialog = new DoNotShowAgainDialog(
+ R.string.fusion_pick_background, R.string.dualcam_fusion_intro,
+ R.string.pref_dualcam_fusion_intro_show_key);
+ dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ FilterShowActivity activity = (FilterShowActivity) mContext;
+ activity.cancelCurrentFilter();
+ activity.leaveSeekBarPanel();
+ }
+ });
+ dialog.setOnOkButtonClickListener(new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ MasterImage.getImage().getActivity().pickImage(FilterShowActivity.SELECT_FUSION_UNDERLAY);
+ }
+ });
+ dialog.setCancelable(true);
+ dialog.show(fm, "dualcam_fusion_intro");
+ } else if (dialog.isDetached()) {
+ FragmentTransaction ft = fm.beginTransaction();
+ ft.attach(dialog);
+ ft.commit();
+ } else if (dialog.isHidden()) {
+ FragmentTransaction ft = fm.beginTransaction();
+ ft.show(dialog);
+ ft.commit();
+ }
+ }
}
}
- private boolean hasSegment() {
+ public void setUnderlayImageUri(Uri uri) {
+ mUnderlayUri = uri;
FilterRepresentation filter = getLocalRepresentation();
- if(filter instanceof FilterDualCamFusionRepresentation) {
- return !((FilterDualCamFusionRepresentation) filter).getPoint().equals(-1,-1);
+ if (filter instanceof FilterDualCamFusionRepresentation) {
+ mImageFusion.setUnderlay(uri);
+ commitLocalRepresentation();
+
+ // save fusion underlay uri
+ GalleryUtils.setStringPref(mContext,
+ mContext.getString(R.string.pref_dualcam_fusion_underlay_key),
+ (uri != null) ? uri.toString() : null);
}
- return false;
}
@Override
@@ -130,4 +226,17 @@ public class EditorDualCamFusion extends ImageOnlyEditor {
mImageFusion.setRepresentation(dualRep);
}
}
+
+ private boolean uriExists(Context context, Uri uri) {
+ try {
+ InputStream stream = context.getContentResolver().openInputStream(uri);
+ stream.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ return false;
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return true;
+ }
}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitFusion.java b/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitFusion.java
index da6118c63..3b285a3b8 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitFusion.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitFusion.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -179,15 +179,15 @@ public class EditorTruePortraitFusion extends Editor {
if(dialog == null) {
dialog = new DoNotShowAgainDialog(
R.string.fusion_pick_background, R.string.trueportrait_fusion_intro,
- R.string.pref_trueportrait_fusion_intro_show_key) {
+ R.string.pref_trueportrait_fusion_intro_show_key);
+ dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
- super.onCancel(dialog);
FilterShowActivity activity = (FilterShowActivity) mContext;
activity.cancelCurrentFilter();
activity.leaveSeekBarPanel();
}
- };
+ });
dialog.setOnOkButtonClickListener(new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
diff --git a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
index b9c24fc27..949dfc00f 100644
--- a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
+++ b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
@@ -18,9 +18,17 @@ package com.android.gallery3d.filtershow.filters;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
+import android.net.Uri;
import android.util.Log;
+import android.view.ContextThemeWrapper;
+import android.view.Gravity;
import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.data.FilterPresetDBHelper;
+import com.android.gallery3d.filtershow.data.FilterPresetSource;
+import com.android.gallery3d.filtershow.data.FilterPresetSource.SaveOption;
import com.android.gallery3d.filtershow.editors.EditorTruePortraitBasic;
import com.android.gallery3d.filtershow.editors.EditorTruePortraitImageOnly;
import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
@@ -45,6 +53,13 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
protected ArrayList<FilterRepresentation> mHazeBuster = new ArrayList<FilterRepresentation>();
protected ArrayList<FilterRepresentation> mSeeStraight = new ArrayList<FilterRepresentation>();
protected ArrayList<FilterRepresentation> mTruePortrait = new ArrayList<FilterRepresentation>();
+ protected ArrayList<FilterRepresentation> mFilterPreset = new ArrayList<FilterRepresentation>();
+ protected ArrayList<FilterRepresentation> mWaterMarks = new ArrayList<FilterRepresentation>();
+ protected ArrayList<FilterRepresentation> mLocations = new ArrayList<FilterRepresentation>();
+ protected ArrayList<FilterRepresentation> mTimes = new ArrayList<FilterRepresentation>();
+ protected ArrayList<FilterRepresentation> mWeathers = new ArrayList<FilterRepresentation>();
+ protected ArrayList<FilterRepresentation> mEmotions = new ArrayList<FilterRepresentation>();
+ protected ArrayList<FilterRepresentation> mFoods = new ArrayList<FilterRepresentation>();
private static int mImageBorderSize = 4; // in percent
protected void init() {
@@ -157,6 +172,8 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
filters.add(ImageFilterDualCamSketch.class);
filters.add(ImageFilterTruePortrait.class);
filters.add(ImageFilterTruePortraitFusion.class);
+ filters.add(ImageFilterPreset.class);
+ filters.add(SaveWaterMark.class);
if(SimpleMakeupImageFilter.HAS_TS_MAKEUP) {
filters.add(ImageFilterMakeupWhiten.class);
@@ -194,6 +211,8 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
return mTruePortrait;
}
+ public ArrayList<FilterRepresentation> getFilterPreset(){ return mFilterPreset; }
+
public ArrayList<FilterRepresentation> getTools() {
return mTools;
}
@@ -214,6 +233,24 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
public ArrayList<FilterRepresentation> getSeeStraight() {
return mSeeStraight;
}
+ public ArrayList<FilterRepresentation> getWaterMarks() {
+ return mWaterMarks;
+ }
+ public ArrayList<FilterRepresentation> getLocations() {
+ return mLocations;
+ }
+ public ArrayList<FilterRepresentation> getTimes() {
+ return mTimes;
+ }
+ public ArrayList<FilterRepresentation> getWeathers() {
+ return mWeathers;
+ }
+ public ArrayList<FilterRepresentation> getEmotions() {
+ return mEmotions;
+ }
+ public ArrayList<FilterRepresentation> getFoods() {
+ return mFoods;
+ }
public void addBorders(Context context) {
// Do not localize
@@ -420,25 +457,249 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
//mTools.add(getRepresentation(ImageFilterRedEye.class));
}
+ public void addWaterMarks(Context context) {
+ int[] textId = {
+ R.string.watermark_location,
+ R.string.watermark_time,
+ R.string.watermark_weather,
+ R.string.watermark_emotions,
+ R.string.watermark_food
+ };
+
+ int[] overlayId = {
+ R.drawable.ic_watermark_location,
+ R.drawable.ic_watermark_time,
+ R.drawable.ic_watermark_weather,
+ R.drawable.ic_watermark_emotion,
+ R.drawable.ic_watermark_food
+ };
+
+ FilterWatermarkRepresentation[] waterMarkFilters = {
+ new FilterWatermarkRepresentation(context, FilterWatermarkRepresentation.NAME_LOCATION,
+ FilterWatermarkRepresentation.LOCATION),
+ new FilterWatermarkRepresentation(context, FilterWatermarkRepresentation.NAME_TIME,
+ FilterWatermarkRepresentation.TIME),
+ new FilterWatermarkRepresentation(context, FilterWatermarkRepresentation.NAME_WEATHER,
+ FilterWatermarkRepresentation.WEATHER),
+ new FilterWatermarkRepresentation(context, FilterWatermarkRepresentation.NAME_EMOTION,
+ FilterWatermarkRepresentation.EMOTIONS),
+ new FilterWatermarkRepresentation(context, FilterWatermarkRepresentation.NAME_FOOD,
+ FilterWatermarkRepresentation.FOOD)
+ };
+
+ for (int i = 0; i < textId.length; i++) {
+ FilterWatermarkRepresentation waterMark = waterMarkFilters[i];
+ waterMark.setTextId(textId[i]);
+ waterMark.setOverlayId(overlayId[i]);
+ waterMark.setOverlayOnly(true);
+ if (waterMark.getTextId() != 0) {
+ waterMark.setName(context.getString(waterMark.getTextId()));
+ }
+ mWaterMarks.add(waterMark);
+ }
+ }
+ public void addLocations(Context context) {
+ int[] overlayId = {
+ R.drawable.icon_pin,
+ R.drawable.icon_city,
+ R.drawable.icon_hello,
+ R.drawable.icon_stamp
+ };
+
+ FilterWatermarkRepresentation[] waterMarkFilters = {
+ new FilterWatermarkRepresentation(context, "LOCATION_PIN", "SAN DIEGO"),
+ new FilterWatermarkRepresentation(context, "LOCATION_CITY", "SAN DIEGO"),
+ new FilterWatermarkRepresentation(context, "LOCATION_HELLO","SAN DIEGO"),
+ new FilterWatermarkRepresentation(context, "LOCATION_STAMP","SAN DIEGO")
+ };
+
+ waterMarkFilters[0].new PositionInfo(0,
+ context.getResources().getDimensionPixelSize(R.dimen.watermark_default_size),
+ 0,0, Gravity.CENTER_HORIZONTAL);
+ waterMarkFilters[1].new PositionInfo(0,
+ context.getResources().getDimensionPixelSize(R.dimen.watermark_default_size),
+ 0,0, Gravity.CENTER_HORIZONTAL);
+ waterMarkFilters[2].new PositionInfo(0,60,0,0, Gravity.RIGHT, true);
+ waterMarkFilters[3].new PositionInfo(0,0,0,0, Gravity.CENTER);
+
+ for (int i = 0; i < waterMarkFilters.length; i++) {
+ FilterWatermarkRepresentation waterMark = waterMarkFilters[i];
+ waterMark.setOverlayId(overlayId[i],
+ new ContextThemeWrapper(context, R.style.DefaultFillColor).getTheme());
+ waterMark.setWaterMarkId(overlayId[i]);
+ waterMark.setMarkType(0);
+ mLocations.add(waterMark);
+ }
+ }
+ public void addTimes(Context context) {
+
+ int[] overlayId = {
+ R.drawable.icon_hourglass,
+ R.drawable.icon_timestamp,
+ R.drawable.icon_sunrise,
+ R.drawable.icon_calendar
+ };
+
+ FilterWatermarkRepresentation[] waterMarkFilters = {
+ new FilterWatermarkRepresentation(context, "TIME_HOURGLASS", null),
+ new FilterWatermarkRepresentation(context, "TIME_TIMESTAMP", null),
+ new FilterWatermarkRepresentation(context, "TIME_SUNRISE", null),
+ new FilterWatermarkRepresentation(context, "TIME_CALENDAR", null)
+ };
+
+ FilterWatermarkRepresentation.PositionInfo[] positionInfos = {
+ waterMarkFilters[0].new PositionInfo(
+ context.getResources().getDimensionPixelSize(R.dimen.watermark_default_size),
+ 0,0,0, Gravity.CENTER_VERTICAL),
+ waterMarkFilters[1].new PositionInfo(0,
+ context.getResources().getDimensionPixelSize(R.dimen.watermark_default_size),
+ 0,0, Gravity.CENTER_HORIZONTAL),
+ waterMarkFilters[2].new PositionInfo(0,
+ context.getResources().getDimensionPixelSize(R.dimen.watermark_default_size),
+ 0,0, Gravity.RIGHT),
+ waterMarkFilters[3].new PositionInfo(0,0,0,0, Gravity.CENTER)
+
+ };
+
+ for (int i = 0; i < waterMarkFilters.length; i++) {
+ FilterWatermarkRepresentation waterMark = waterMarkFilters[i];
+ waterMark.setOverlayId(overlayId[i],
+ new ContextThemeWrapper(context, R.style.DefaultFillColor).getTheme());
+ waterMark.setWaterMarkId(overlayId[i]);
+ waterMark.setMarkType(1);
+ mTimes.add(waterMark);
+ }
+ }
+ public void addWeather(Context context) {
+ int[] overlayId = {
+ R.drawable.icon_rain,
+ R.drawable.icon_snow,
+ R.drawable.icon_sun,
+ R.drawable.icon_artistic_sun
+ };
+
+ FilterWatermarkRepresentation[] waterMarkFilters = {
+ new FilterWatermarkRepresentation(context, "WEATHER_RAIN", "50F"),
+ new FilterWatermarkRepresentation(context, "WEATHER_SNOW", "30F"),
+ new FilterWatermarkRepresentation(context, "WEATHER_SUN", "78F"),
+ new FilterWatermarkRepresentation(context, "WEATHER_ARTISTIC_SUN", "78F")
+ };
+
+ waterMarkFilters[0].new PositionInfo(84, 40, 0, 0, true);
+ waterMarkFilters[1].new PositionInfo(60, 50, 0, 0, true);
+ waterMarkFilters[2].new PositionInfo(0, 66, 0, 0, Gravity.CENTER_HORIZONTAL, true);
+ waterMarkFilters[3].new PositionInfo(0, 56, 0, 0, Gravity.CENTER_HORIZONTAL, true);
+
+ for (int i = 0; i < waterMarkFilters.length; i++) {
+ FilterWatermarkRepresentation waterMark = waterMarkFilters[i];
+ waterMark.setOverlayId(overlayId[i],
+ new ContextThemeWrapper(context, R.style.DefaultFillColor).getTheme());
+ waterMark.setWaterMarkId(overlayId[i]);
+ waterMark.setMarkType(2);
+ mWeathers.add(waterMark);
+ }
+ }
+ public void addEmotions(Context context) {
+ int[] overlayId = {
+ R.drawable.icon_party,
+ R.drawable.icon_peace,
+ R.drawable.icon_cry,
+ R.drawable.icon_happy
+ };
+
+ FilterWatermarkRepresentation[] waterMarkFilters = {
+ new FilterWatermarkRepresentation(context, "EMOTION_PARTY", "Party!!"),
+ new FilterWatermarkRepresentation(context, "EMOTION_PEACE", "PEACE"),
+ new FilterWatermarkRepresentation(context, "EMOTION_CRY", null),
+ new FilterWatermarkRepresentation(context, "EMOTION_HAPPY", null)
+ };
+
+ waterMarkFilters[0].new PositionInfo(0,
+ context.getResources().getDimensionPixelSize(R.dimen.watermark_default_size),
+ 0, 0, Gravity.CENTER_HORIZONTAL);
+ waterMarkFilters[1].new PositionInfo(0,
+ context.getResources().getDimensionPixelSize(R.dimen.watermark_default_size),
+ 0, 0, Gravity.CENTER_HORIZONTAL);
+
+ for (int i = 0; i < waterMarkFilters.length; i++) {
+ FilterWatermarkRepresentation waterMark = waterMarkFilters[i];
+ waterMark.setOverlayId(overlayId[i],
+ new ContextThemeWrapper(context, R.style.DefaultFillColor).getTheme());
+ switch (i) {
+ case 2:
+ waterMark.setWaterMarkId(R.drawable.icon_cry_color);
+ waterMark.setMarkAlpha(255);
+ break;
+ case 3:
+ waterMark.setWaterMarkId(R.drawable.icon_happy_color);
+ waterMark.setMarkAlpha(255);
+ break;
+ default:
+ waterMark.setWaterMarkId(overlayId[i]);
+ break;
+ }
+ waterMark.setMarkType(3);
+ mEmotions.add(waterMark);
+ }
+ }
+ public void addFoods(Context context) {
+ int[] overlayId = {
+ R.drawable.icon_fork_and_knife,
+ R.drawable.icon_tea_time,
+ R.drawable.icon_cheers,
+ R.drawable.icon_yum
+ };
+
+ FilterWatermarkRepresentation[] waterMarkFilters = {
+ new FilterWatermarkRepresentation(context, "FOOD_FORK_KNIFE", "Breakfast"),
+ new FilterWatermarkRepresentation(context, "FOOD_TEA_TIME", "Tea Time"),
+ new FilterWatermarkRepresentation(context, "FOOD_CHEERS", "Cheers"),
+ new FilterWatermarkRepresentation(context, "FOOD_YUM", null)
+ };
+
+ waterMarkFilters[0].new PositionInfo(0,32,0,0,Gravity.CENTER_HORIZONTAL,true);
+ waterMarkFilters[1].new PositionInfo(0,
+ context.getResources().getDimensionPixelSize(R.dimen.watermark_default_size),
+ 0, 0, Gravity.CENTER_HORIZONTAL);
+ waterMarkFilters[2].new PositionInfo(0, 60, 0, 0, Gravity.CENTER_HORIZONTAL, true);
+
+ for (int i = 0; i < waterMarkFilters.length; i++) {
+ FilterWatermarkRepresentation waterMark = waterMarkFilters[i];
+ waterMark.setOverlayId(overlayId[i],
+ new ContextThemeWrapper(context, R.style.DefaultFillColor).getTheme());
+ waterMark.setWaterMarkId(overlayId[i]);
+ waterMark.setMarkType(4);
+ mFoods.add(waterMark);
+ }
+ }
+
public void addDualCam(Context context) {
int[] textId = {
R.string.focus,
- R.string.halo
+ R.string.halo,
+ R.string.motion,
+ R.string.posterize
};
int[] overlayId = {
R.drawable.focus,
- R.drawable.halo
+ R.drawable.halo,
+ R.drawable.motion,
+ R.drawable.posterize
};
String[] serializationNames = {
"DUAL_CAM_FOCUS",
- "DUAL_CAM_HALO"
+ "DUAL_CAM_HALO",
+ "DUAL_CAM_MOTION",
+ "DUAL_CAM_POSTERIZE"
};
// intensity range as defined by ddm lib
int[][] minMaxValues = {
{0,5,10},
+ {0,5,10},
+ {0,5,10},
{0,5,10}
};
@@ -460,13 +721,42 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
addRepresentation(dualCam);
}
- FilterDualCamSketchRepresentation sketch = new FilterDualCamSketchRepresentation(
- context.getString(R.string.sketch), R.string.sketch);
- sketch.setOverlayId(R.drawable.sketch);
- sketch.setOverlayOnly(true);
- sketch.setSerializationName("DUAL_CAM_SKETCH");
- mDualCam.add(sketch);
- addRepresentation(sketch);
+ int[] textId2 = {
+ R.string.sketch,
+ R.string.zoom,
+ R.string.bw,
+ R.string.blackboard,
+ R.string.whiteboard,
+ R.string.dc_negative
+ };
+
+ int[] overlayId2 = {
+ R.drawable.sketch,
+ R.drawable.zoom,
+ R.drawable.bw,
+ R.drawable.blackboard,
+ R.drawable.whiteboard,
+ R.drawable.negative
+ };
+
+ String[] serializationNames2 = {
+ "DUAL_CAM_SKETCH",
+ "DUAL_CAM_ZOOM",
+ "DUAL_CAM_BW",
+ "DUAL_CAM_BLACKBOARD",
+ "DUAL_CAM_WHITEBOARD",
+ "DUAL_CAM_NEGATIVE"
+ };
+
+ for (int i = 0; i < textId2.length; i++) {
+ FilterDualCamSketchRepresentation dualCam = new FilterDualCamSketchRepresentation(
+ context.getString(textId2[i]), textId2[i]);
+ dualCam.setOverlayId(overlayId2[i]);
+ dualCam.setOverlayOnly(true);
+ dualCam.setSerializationName(serializationNames2[i]);
+ mDualCam.add(dualCam);
+ addRepresentation(dualCam);
+ }
mDualCam.add(getRepresentation(ImageFilterDualCamFusion.class));
}
@@ -539,6 +829,23 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
mTruePortrait.add(getRepresentation(ImageFilterTruePortraitFusion.class));
}
+ public void addFilterPreset (Context context) {
+ FilterPresetSource fp = new FilterPresetSource(context);
+ ArrayList<SaveOption> ret = fp.getAllUserPresets();
+ if (ret == null) return;
+ for (int id = 0; id<ret.size(); id++){
+ FilterPresetRepresentation representation= new FilterPresetRepresentation (
+ ret.get(id).name,ret.get(id)._id,id+1);
+ Uri filteredUri = Uri.parse(ret.get(id).Uri);
+ representation.setUri(filteredUri);
+ representation.setSerializationName("Custom");
+ mFilterPreset.add(representation);
+ ImagePreset preset = new ImagePreset();
+ preset.addFilter(representation);
+ addRepresentation(representation);
+ }
+ }
+
public void removeRepresentation(ArrayList<FilterRepresentation> list,
FilterRepresentation representation) {
for (int i = 0; i < list.size(); i++) {
@@ -555,5 +862,7 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
filterBorder.setResources(resources);
ImageFilterFx filterFx = (ImageFilterFx) getFilter(ImageFilterFx.class);
filterFx.setResources(resources);
+ ImageFilterPreset filterPreset = (ImageFilterPreset) getFilter(ImageFilterPreset.class);
+ filterPreset.setResources(resources);
}
}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterPresetRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterPresetRepresentation.java
new file mode 100644
index 000000000..967bc28f5
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterPresetRepresentation.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.net.Uri;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
+
+import java.io.IOException;
+
+public class FilterPresetRepresentation extends FilterRepresentation {
+
+ private static final String LOGTAG = "FilterPresetRepresentation";
+
+ private static final String URI_TAG = "URI";
+
+ // TODO: When implementing serialization, we should find a unique way of
+ // specifying bitmaps / names (the resource IDs being random)
+ private int mBitmapResource = 0;
+ private int mNameResource = 0;
+ private Uri FilteredURI;
+ //private int mId;
+
+ public FilterPresetRepresentation(String name, int bitmapResource, int nameResource) {
+ super(name);
+ setFilterClass(ImageFilterPreset.class);
+ mBitmapResource = bitmapResource;
+ mNameResource = nameResource;
+ setFilterType(FilterRepresentation.TYPE_PRESETFILTER);
+ setTextId(nameResource);
+ setEditorId(ImageOnlyEditor.ID);
+ setShowParameterValue(false);
+ setSupportsPartialRendering(true);
+ }
+
+ @Override
+ public String toString() {
+ return "FilterPreset: " + hashCode() + " : " + getName() + " bitmap rsc: " + mBitmapResource;
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ FilterPresetRepresentation representation = new FilterPresetRepresentation(getName(), 0, 0);
+ copyAllParameters(representation);
+ return representation;
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ @Override
+ public synchronized void useParametersFrom(FilterRepresentation a) {
+ if (a instanceof FilterPresetRepresentation) {
+ FilterPresetRepresentation representation = (FilterPresetRepresentation) a;
+ setName(representation.getName());
+ setSerializationName(representation.getSerializationName());
+ setBitmapResource(representation.getBitmapResource());
+ setNameResource(representation.getNameResource());
+ setUri(representation.getUri());
+ }
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+ if (representation instanceof FilterPresetRepresentation) {
+ FilterPresetRepresentation fp = (FilterPresetRepresentation) representation;
+ if (fp.mNameResource == mNameResource
+ && fp.mBitmapResource == mBitmapResource) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean same(FilterRepresentation representation) {
+ if (!super.same(representation)) {
+ return false;
+ }
+ return equals(representation);
+ }
+
+ public void setUri (Uri URI) {FilteredURI = URI;}
+
+ public Uri getUri(){return FilteredURI;}
+
+ public void setId (int Id) {mBitmapResource = Id;}
+
+ public int getId() {
+ return mBitmapResource;
+ }
+
+ @Override
+ public boolean allowsSingleInstanceOnly() {
+ return true;
+ }
+
+ public int getNameResource() {
+ return mNameResource;
+ }
+
+ public void setNameResource(int nameResource) {
+ mNameResource = nameResource;
+ }
+
+ public int getBitmapResource() {
+ return mBitmapResource;
+ }
+
+ public void setBitmapResource(int bitmapResource) {
+ mBitmapResource = bitmapResource;
+ }
+
+ // Serialization...
+
+ public void serializeRepresentation(JsonWriter writer) throws IOException {
+ writer.beginObject();
+ {
+ writer.name(NAME_TAG);
+ writer.value(getName());
+ writer.name(URI_TAG);
+ writer.value(getUri().toString());
+ }
+ writer.endObject();
+ }
+
+ public void deSerializeRepresentation(JsonReader reader) throws IOException {
+ reader.beginObject();
+ while (reader.hasNext()) {
+ String name = reader.nextName();
+ if (name.equalsIgnoreCase(NAME_TAG)) {
+ setName(reader.nextString());
+ } else if (name.equalsIgnoreCase(URI_TAG)) {
+ setUri(Uri.parse(reader.nextString()));
+ } else {
+ reader.skipValue();
+ }
+ }
+ reader.endObject();
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
index bded1f506..e82748954 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
@@ -16,6 +16,7 @@
package com.android.gallery3d.filtershow.filters;
+import android.content.res.Resources;
import android.util.JsonReader;
import android.util.JsonWriter;
import android.util.Log;
@@ -40,6 +41,8 @@ public class FilterRepresentation {
private boolean mOverlayOnly = false;
private boolean mShowParameterValue = true;
private boolean mIsBooleanFilter = false;
+ private boolean isSvgOverlay = false;
+ private Resources.Theme currentTheme;
private String mSerializationName;
public static final byte TYPE_BORDER = 1;
public static final byte TYPE_FX = 2;
@@ -51,6 +54,9 @@ public class FilterRepresentation {
public static final byte TYPE_MAKEUP = 8;
public static final byte TYPE_DUALCAM = 9;
public static final byte TYPE_TRUEPORTRAIT = 10;
+ public static final byte TYPE_PRESETFILTER = 11;
+ public static final byte TYPE_WATERMARK_CATEGORY = 12;
+ public static final byte TYPE_WATERMARK = 13;
protected static final String NAME_TAG = "Name";
public FilterRepresentation(String name) {
@@ -198,6 +204,19 @@ public class FilterRepresentation {
mOverlayId = overlayId;
}
+ public void setOverlayId(int overlayId, Resources.Theme theme) {
+ mOverlayId = overlayId;
+ currentTheme = theme;
+ }
+
+ public Resources.Theme getCurrentTheme() {
+ return currentTheme;
+ }
+
+ public void setCurrentTheme(Resources.Theme theme) {
+ currentTheme = theme;
+ }
+
public boolean getOverlayOnly() {
return mOverlayOnly;
}
@@ -206,6 +225,14 @@ public class FilterRepresentation {
mOverlayOnly = value;
}
+ public boolean isSvgOverlay() {
+ return isSvgOverlay;
+ }
+
+ public void setSvgOverlay(boolean svgOverlay) {
+ isSvgOverlay = svgOverlay;
+ }
+
final public int getEditorId() {
return mEditorId;
}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterWatermarkRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterWatermarkRepresentation.java
new file mode 100644
index 000000000..20c8717ec
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterWatermarkRepresentation.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+package com.android.gallery3d.filtershow.filters;
+
+
+import android.content.Context;
+import android.view.ContextThemeWrapper;
+import android.view.Gravity;
+
+import com.android.gallery3d.filtershow.category.WaterMarkView;
+
+import org.codeaurora.gallery.R;
+
+public class FilterWatermarkRepresentation extends FilterRepresentation {
+ public static final String NAME_LOCATION = "LOCATION";
+ public static final String NAME_TIME = "TIME";
+ public static final String NAME_WEATHER = "WEATHER";
+ public static final String NAME_EMOTION = "EMOTION";
+ public static final String NAME_FOOD = "FOOD";
+
+ public static final int LOCATION = 12;
+ public static final int TIME = 13;
+ public static final int WEATHER = 14;
+ public static final int EMOTIONS = 15;
+ public static final int FOOD = 16;
+ private int adapterId;
+ private int waterMarkId;
+ private int markAlpha = -1;
+ private int markType = -1;
+ private String textHint = "HELLO";
+ private PositionInfo positionInfo;
+ private Context mContext;
+ private WaterMarkView currentMarkView;
+
+ //for main panel
+ public FilterWatermarkRepresentation(Context context, String name, int category) {
+ this(name);
+ mContext = context;
+ setFilterType(FilterRepresentation.TYPE_WATERMARK_CATEGORY);
+ loadCategory(category);
+ }
+
+ //for level-2 panel
+ public FilterWatermarkRepresentation(Context context, String name, String textHint) {
+ this(name);
+ mContext = context;
+ setFilterClass(SaveWaterMark.class);
+ setName("");
+ setFilterType(FilterRepresentation.TYPE_WATERMARK);
+ setCurrentTheme(new ContextThemeWrapper(mContext, R.style.DefaultFillColor).getTheme());
+ if (textHint != null) {
+ this.textHint = textHint;
+ }
+ }
+
+ public FilterWatermarkRepresentation(String name) {
+ super(name);
+ setSerializationName(name);
+ setShowParameterValue(false);
+ setSupportsPartialRendering(true);
+ setSvgOverlay(true);
+ setOverlayOnly(true);
+ }
+
+ private void loadCategory(int category) {
+ switch (category) {
+ case LOCATION:
+ setAdapterId(LOCATION);
+ break;
+ case TIME:
+ setAdapterId(TIME);
+ break;
+ case WEATHER:
+ setAdapterId(WEATHER);
+ break;
+ case EMOTIONS:
+ setAdapterId(EMOTIONS);
+ break;
+ case FOOD:
+ setAdapterId(FOOD);
+ break;
+ }
+ }
+
+ public int getAdapterId() {
+ return adapterId;
+ }
+
+ public void setAdapterId(int adapterId) {
+ this.adapterId = adapterId;
+ }
+
+
+ public int getWaterMarkId() {
+ return waterMarkId;
+ }
+
+ public void setWaterMarkId(int waterMarkId) {
+ this.waterMarkId = waterMarkId;
+ }
+
+ public void setMarkAlpha(int alpha) {
+ markAlpha = alpha;
+ }
+
+ public WaterMarkView getWaterMarkView() {
+ return getWaterMarkView(textHint);
+ }
+
+ public WaterMarkView getWaterMarkView(String textHint) {
+ if (currentMarkView == null) {
+ currentMarkView = new WaterMarkView(mContext,
+ mContext.getResources().getDrawable(getWaterMarkId(), getCurrentTheme()), textHint);
+ if (positionInfo != null) {
+ currentMarkView.setTextPosition(positionInfo.marginLeft, positionInfo.marginTop,
+ positionInfo.marginRight, positionInfo.marginBottom, positionInfo.gravity, positionInfo.isDip);
+ } else {
+ currentMarkView.setTextVisibility(false);
+ }
+ currentMarkView.setImageAlpha(markAlpha >= 0 ? markAlpha : 128);
+ }
+ return currentMarkView;
+ }
+
+ public void setMarkType(int markType) {
+ this.markType = markType;
+ }
+
+ public int getMarkType() {
+ return markType;
+ }
+
+ public void setTextHint(String textHint) {
+ this.textHint = textHint;
+ }
+
+ public String getTextHint() {
+ return textHint;
+ }
+
+ public void reset() {
+ currentMarkView = null;
+ }
+
+ protected class PositionInfo {
+ protected int marginLeft;
+ protected int marginTop;
+ protected int marginRight;
+ protected int marginBottom;
+ protected int gravity;
+ protected boolean isDip;
+ public PositionInfo() {
+ this(0, 0, 0, 0, Gravity.NO_GRAVITY, false);
+ }
+
+ public PositionInfo(int left, int top, int right, int bottom) {
+ this(left, top, right, bottom, Gravity.NO_GRAVITY, false);
+ }
+
+ public PositionInfo(int left, int top, int right, int bottom, int gravity) {
+ this(left, top, right, bottom, gravity, false);
+ }
+
+ public PositionInfo(int left, int top, int right, int bottom, boolean isDip) {
+ this(left, top, right, bottom, Gravity.NO_GRAVITY, isDip);
+ }
+
+ public PositionInfo(int left, int top, int right, int bottom, int gravity, boolean isDip) {
+ marginLeft = left;
+ marginTop = top;
+ marginRight = right;
+ marginBottom = bottom;
+ this.gravity = gravity;
+ this.isDip = isDip;
+ FilterWatermarkRepresentation.this.positionInfo = PositionInfo.this;
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java
index df34fedbe..212e4a864 100755
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015,2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -159,6 +159,18 @@ public class ImageFilterDualCamFusion extends ImageFilter {
roiRectF.right = (float)(roiRect[0] + roiRect[2])/(float)filteredW;
roiRectF.bottom = (float)(roiRect[1] + roiRect[3])/(float)filteredH;
+ int zoomOrientation = MasterImage.getImage().getZoomOrientation();
+ if (zoomOrientation == ImageLoader.ORI_ROTATE_90 ||
+ zoomOrientation == ImageLoader.ORI_ROTATE_180 ||
+ zoomOrientation == ImageLoader.ORI_ROTATE_270 ||
+ zoomOrientation == ImageLoader.ORI_TRANSPOSE ||
+ zoomOrientation == ImageLoader.ORI_TRANSVERSE) {
+ Matrix mt = new Matrix();
+ mt.preRotate(GeometryMathUtils.getRotationForOrientation(zoomOrientation),
+ 0.5f, 0.5f);
+ mt.mapRect(roiRectF);
+ }
+
// Check for ROI cropping
if(!FilterCropRepresentation.getNil().equals(roiRectF)) {
if(FilterCropRepresentation.getNil().equals(holder.crop)) {
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamSketch.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamSketch.java
index 97712db75..af165b770 100755
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamSketch.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamSketch.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -116,8 +116,33 @@ public class ImageFilterDualCamSketch extends ImageFilter {
}
filteredBitmap = MasterImage.getImage().getBitmapCache().getBitmap(filteredW, filteredH, BitmapCache.FILTERS);
- result = DualCameraNativeEngine.getInstance().applySketch(point.x, point.y,
- roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+
+ switch (mParameters.getTextId()) {
+ case R.string.sketch:
+ result = DualCameraNativeEngine.getInstance().applySketch(point.x, point.y,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ case R.string.zoom:
+ result = DualCameraNativeEngine.getInstance().applyZoom(point.x, point.y,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ case R.string.bw:
+ result = DualCameraNativeEngine.getInstance().applyBlackAndWhite(point.x, point.y,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ case R.string.blackboard:
+ result = DualCameraNativeEngine.getInstance().applyBlackBoard(point.x, point.y,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ case R.string.whiteboard:
+ result = DualCameraNativeEngine.getInstance().applyWhiteBoard(point.x, point.y,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ case R.string.dc_negative:
+ result = DualCameraNativeEngine.getInstance().applyNegative(point.x, point.y,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ }
if(result == false) {
Log.e(TAG, "Imagelib API failed");
@@ -148,6 +173,18 @@ public class ImageFilterDualCamSketch extends ImageFilter {
roiRectF.right = (float)(roiRect[0] + roiRect[2])/(float)filteredW;
roiRectF.bottom = (float)(roiRect[1] + roiRect[3])/(float)filteredH;
+ int zoomOrientation = MasterImage.getImage().getZoomOrientation();
+ if (zoomOrientation == ImageLoader.ORI_ROTATE_90 ||
+ zoomOrientation == ImageLoader.ORI_ROTATE_180 ||
+ zoomOrientation == ImageLoader.ORI_ROTATE_270 ||
+ zoomOrientation == ImageLoader.ORI_TRANSPOSE ||
+ zoomOrientation == ImageLoader.ORI_TRANSVERSE) {
+ Matrix mt = new Matrix();
+ mt.preRotate(GeometryMathUtils.getRotationForOrientation(zoomOrientation),
+ 0.5f, 0.5f);
+ mt.mapRect(roiRectF);
+ }
+
// Check for ROI cropping
if(!FilterCropRepresentation.getNil().equals(roiRectF)) {
if(FilterCropRepresentation.getNil().equals(holder.crop)) {
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java
index 49728f84c..01c75b5ae 100755
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -121,15 +121,24 @@ public class ImageFilterDualCamera extends ImageFilter {
filteredBitmap = MasterImage.getImage().getBitmapCache().getBitmap(filteredW, filteredH, BitmapCache.FILTERS);
- switch(mParameters.getTextId()) {
- case R.string.focus:
- result = DualCameraNativeEngine.getInstance().applyFocus(point.x, point.y, intensity,
- roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
- break;
- case R.string.halo:
- result = DualCameraNativeEngine.getInstance().applyHalo(point.x, point.y, intensity,
- roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
- break;
+ switch (mParameters.getTextId()) {
+ case R.string.focus:
+ result = DualCameraNativeEngine.getInstance().applyFocus(point.x, point.y, intensity,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ case R.string.halo:
+ result = DualCameraNativeEngine.getInstance().applyHalo(point.x, point.y, intensity,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ case R.string.motion:
+ result = DualCameraNativeEngine.getInstance().applyMotion(point.x, point.y, intensity,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ case R.string.posterize:
+ result = DualCameraNativeEngine.getInstance().applyPosterize(point.x, point.y, intensity,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+
}
if(result == false) {
@@ -162,6 +171,18 @@ public class ImageFilterDualCamera extends ImageFilter {
roiRectF.right = (float)(roiRect[0] + roiRect[2])/(float)filteredW;
roiRectF.bottom = (float)(roiRect[1] + roiRect[3])/(float)filteredH;
+ int zoomOrientation = MasterImage.getImage().getZoomOrientation();
+ if (zoomOrientation == ImageLoader.ORI_ROTATE_90 ||
+ zoomOrientation == ImageLoader.ORI_ROTATE_180 ||
+ zoomOrientation == ImageLoader.ORI_ROTATE_270 ||
+ zoomOrientation == ImageLoader.ORI_TRANSPOSE ||
+ zoomOrientation == ImageLoader.ORI_TRANSVERSE) {
+ Matrix mt = new Matrix();
+ mt.preRotate(GeometryMathUtils.getRotationForOrientation(zoomOrientation),
+ 0.5f, 0.5f);
+ mt.mapRect(roiRectF);
+ }
+
// Check for ROI cropping
if(!FilterCropRepresentation.getNil().equals(roiRectF)) {
if(FilterCropRepresentation.getNil().equals(holder.crop)) {
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterPreset.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterPreset.java
new file mode 100644
index 000000000..de52ee048
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterPreset.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.net.Uri;
+import com.android.gallery3d.app.Log;
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.tools.FilterGeneratorNativeEngine;
+
+public class ImageFilterPreset extends ImageFilter {
+
+ private static final String LOGTAG = "ImageFilterPreset";
+ private FilterPresetRepresentation mParameters = null;
+ private Bitmap mPresetBitmap = null;
+ private Resources mResources = null;
+ private int mPresetBitmapId = 0;
+ private Uri filterImageUri;
+
+ public ImageFilterPreset() { }
+
+ @Override
+
+ public void freeResources() {
+ if (mPresetBitmap != null) mPresetBitmap.recycle();
+ mPresetBitmap = null;
+ }
+
+ @Override
+ public FilterRepresentation getDefaultRepresentation() {
+ return null;
+ }
+
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterPresetRepresentation parameters = (FilterPresetRepresentation) representation;
+ mParameters = parameters;
+ }
+
+ public FilterPresetRepresentation getParameters() {
+ return mParameters;
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null || mResources == null) {
+ return bitmap;
+ }
+
+ int bitmapResourceId = getParameters().getBitmapResource();
+ if (bitmapResourceId == 0) { // null filter preset
+ return bitmap;
+ }
+
+ int highresPreviewSize = Math.min(MasterImage.MAX_BITMAP_DIM, MasterImage.getImage().getActivity().getScreenImageSize());
+
+ filterImageUri = getParameters().getUri();
+ Bitmap filter = ImageLoader.loadOrientedConstrainedBitmap(filterImageUri,
+ MasterImage.getImage().getActivity(), highresPreviewSize,
+ MasterImage.getImage().getOrientation(), new Rect());
+
+ FilterGeneratorNativeEngine.getInstance().filterGeneratorProcess(bitmap,filter,bitmap);
+ return bitmap;
+ }
+
+ public void setResources(Resources resources) {
+ mResources = resources;
+ }
+} \ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/filters/SaveWaterMark.java b/src/com/android/gallery3d/filtershow/filters/SaveWaterMark.java
new file mode 100644
index 000000000..f4fbd986a
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/SaveWaterMark.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2016-2017 The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+package com.android.gallery3d.filtershow.filters;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.exif.ExifInterface;
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.category.WaterMarkView;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.pipeline.ImagePreset;
+import com.android.gallery3d.filtershow.tools.SaveImage;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class SaveWaterMark {
+ private static final String LOGTAG = "SaveWaterMark";
+ public static final int MARK_SAVE_COMPLETE = 1;
+ private FilterWatermarkRepresentation waterMarkRp;
+ private Context mContext;
+ private static ExifInterface mExif = new ExifInterface();;
+
+ public void useRepresentation(FilterRepresentation representation) {
+ waterMarkRp = (FilterWatermarkRepresentation) representation;
+ }
+
+ public void saveImage(Context context, final Bitmap bitmap, Uri selectedUri, Handler handler,
+ int quality, float scaleFactor, boolean isScale) {
+ mContext = context;
+ WaterMarkView mWaterMarkView = waterMarkRp.getWaterMarkView();
+ mWaterMarkView.clearEditTextCursor();
+ Bitmap markBitmap = mWaterMarkView.creatNewPhoto();
+
+ new AsyncTask<Bitmap, Void, Uri>() {
+ @Override
+ protected Uri doInBackground(Bitmap... bitmaps) {
+ ImagePreset ip = MasterImage.getImage().getPreset();
+ FilterFusionRepresentation fusionRep = findFusionRepresentation(ip);
+ boolean hasFusion = (fusionRep != null && fusionRep.hasUnderlay());
+ Bitmap destinationBitmap = createBitmap(bitmap, bitmaps[0]);
+ Bitmap fusionBmp = null;
+ //sampleSize is 1 for fusion bitmap of 1:1 size,
+ //sizeConstraint is 0 for fusion without width or height constraint.
+ final int sampleSize = 1, sizeConstraint = 0;
+ if (hasFusion) {
+ fusionBmp = SaveImage.flattenFusion(mContext, Uri.parse(fusionRep.getUnderlay()), destinationBitmap,
+ sizeConstraint, sampleSize);
+ if(fusionBmp != null) {
+ destinationBitmap.recycle();
+ destinationBitmap = fusionBmp;
+ }
+ }
+ File destinationFile = SaveImage.getNewFile(context, selectedUri);
+ //ExifInterface exif = getExifData(context, selectedUri);
+ long time = System.currentTimeMillis();
+ Uri saveUri = selectedUri;
+ if (scaleFactor != 1f) {
+ // if we have a valid size
+ int w = (int) (destinationBitmap.getWidth() * scaleFactor);
+ int h = (int) (destinationBitmap.getHeight() * scaleFactor);
+ if (w == 0 || h == 0) {
+ w = 1;
+ h = 1;
+ }
+ destinationBitmap = Bitmap.createScaledBitmap(destinationBitmap, w, h, true);
+ }
+ if (SaveImage.putExifData(destinationFile, mExif, destinationBitmap, quality)) {
+ saveUri = SaveImage.linkNewFileToUri(context, selectedUri, destinationFile, time, false);
+ }
+ destinationBitmap.recycle();
+ return saveUri;
+ }
+
+ @Override
+ protected void onPostExecute(Uri uri) {
+ if (isScale) return;
+ Message message = new Message();
+ message.what = MARK_SAVE_COMPLETE;
+ message.obj = uri;
+ handler.sendMessage(message);
+ }
+ }.execute(markBitmap);
+ }
+
+ public void saveImage(Context context, Bitmap bitmap, Uri selectedUri, Handler handler) {
+ saveImage(context, bitmap, selectedUri, handler, 90, 1f, false);
+
+ }
+
+ public void exportImage(Context context, Bitmap bitmap, Uri selectedUri, int quality, float scaleFactor) {
+ saveImage(context, bitmap, selectedUri, null, quality, scaleFactor, true);
+ }
+
+ private Bitmap createBitmap(Bitmap src, Bitmap watermark) {
+ if (src == null) {
+ return null;
+ }
+ Rect r = MasterImage.getImage().getImageBounds();
+ int rw = r.width();
+ int rh = r.height();
+ Bitmap resizeSrc = Bitmap.createScaledBitmap(src,rw, rh,false);
+ //create the new blank bitmap
+ Bitmap newb = Bitmap.createBitmap(rw, rh, Bitmap.Config.ARGB_8888);
+ Canvas cv = new Canvas(newb);
+ //draw src into
+ cv.drawBitmap(resizeSrc, 0, 0, null);
+ //draw watermark into
+ cv.drawBitmap(watermark, 0, 0, null);
+ //save all clip
+ cv.save(Canvas.ALL_SAVE_FLAG);
+ //store
+ cv.restore();
+ watermark.recycle();
+ resizeSrc.recycle();
+ return newb;
+ }
+
+ private FilterFusionRepresentation findFusionRepresentation(ImagePreset preset) {
+ FilterDualCamFusionRepresentation dcRepresentation =
+ (FilterDualCamFusionRepresentation)preset.getFilterWithSerializationName(
+ FilterDualCamFusionRepresentation.SERIALIZATION_NAME);
+ FilterTruePortraitFusionRepresentation tpRepresentation =
+ (FilterTruePortraitFusionRepresentation)preset.getFilterWithSerializationName(
+ FilterTruePortraitFusionRepresentation.SERIALIZATION_NAME);
+
+ FilterFusionRepresentation fusionRep = null;
+
+ if(dcRepresentation != null)
+ fusionRep = (FilterFusionRepresentation) dcRepresentation;
+ else if (tpRepresentation != null)
+ fusionRep = (FilterFusionRepresentation) tpRepresentation;
+
+ return fusionRep;
+ }
+
+ public void getExifData(Context context, Uri source) {
+ //mExif = new ExifInterface();
+ String mimeType = context.getContentResolver().getType(source);
+ if (mimeType == null) {
+ mimeType = ImageLoader.getMimeType(source);
+ }
+ if (ImageLoader.JPEG_MIME_TYPE.equals(mimeType)) {
+ InputStream inStream = null;
+ try {
+ inStream = context.getContentResolver().openInputStream(source);
+ mExif.readExif(inStream);
+ } catch (FileNotFoundException e) {
+ Log.w(LOGTAG, "Cannot find file: " + source, e);
+ } catch (IOException e) {
+ Log.w(LOGTAG, "Cannot read exif for: " + source, e);
+ } catch (NullPointerException e) {
+ Log.w(LOGTAG, "Invalid exif data for: " + source, e);
+ } finally {
+ Utils.closeSilently(inStream);
+ }
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/TrueScannerActs.java b/src/com/android/gallery3d/filtershow/filters/TrueScannerActs.java
index 0a59a65c5..ccce699f5 100755
--- a/src/com/android/gallery3d/filtershow/filters/TrueScannerActs.java
+++ b/src/com/android/gallery3d/filtershow/filters/TrueScannerActs.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -48,8 +48,10 @@ import static com.android.gallery3d.filtershow.imageshow.ImageTrueScanner.*;
public class TrueScannerActs extends SimpleImageFilter {
public static final String SERIALIZATION_NAME = "TrueScannerActs";
- private static final int MIN_WIDTH = 512;
- private static final int MIN_HEIGHT = 512;
+ //The minimum resolution that TrueScanner library supports is VGA, i.e. 640x480.
+ public static final int MIN_WIDTH = 640;
+ public static final int MIN_HEIGHT = 480;
+ private static boolean rotating = false;
private static final boolean DEBUG = false;
private static boolean isTrueScannerEnabled = true;
private static boolean isPointsAcquired;
@@ -70,6 +72,10 @@ public class TrueScannerActs extends SimpleImageFilter {
return isTrueScannerEnabled;
}
+ public static boolean setRotating(boolean isRotating) {
+ return rotating = isRotating;
+ }
+
public TrueScannerActs() {
mName = "TrueScannerActs";
isPointsAcquired = false;
@@ -130,7 +136,13 @@ public class TrueScannerActs extends SimpleImageFilter {
public Bitmap apply(Bitmap bitmap, float not_use, int quality) {
if(bitmap == null)
return null;
- if(bitmap.getWidth() <= MIN_WIDTH && bitmap.getHeight() <= MIN_HEIGHT)
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ if (w < h) {
+ w = h;
+ h = bitmap.getWidth();
+ }
+ if(w <= MIN_WIDTH || h <= MIN_HEIGHT)
return bitmap;
if(ImageTrueScanner.getCordsUIState()) {
return bitmap;
@@ -150,12 +162,19 @@ public class TrueScannerActs extends SimpleImageFilter {
else
resultPts[i] = (int)((pts[i] - pts[POINTS_LEN+3])*yScale);
}
-
- rectifiedImage = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
+ if (rotating && rectifiedImage != null) {
+ acquireLock(false);
+ rotating = false;
+ return rectifiedImage;
+ }
+ rectifiedImage = Bitmap.createBitmap(
+ bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
int[] outputSize = processImage(bitmap, rectifiedImage, resultPts);
- rectifiedImage = Bitmap.createBitmap(rectifiedImage, 0, 0, outputSize[0], outputSize[1]);
+ rectifiedImage = Bitmap.createBitmap(
+ rectifiedImage, 0, 0, outputSize[0], outputSize[1]);
if(ImageTrueScanner.getRemoveGlareButtonStatus()) {
- Bitmap enhancedImage = Bitmap.createBitmap(outputSize[0], outputSize[1], Bitmap.Config.ARGB_8888);
+ Bitmap enhancedImage = Bitmap.createBitmap(
+ outputSize[0], outputSize[1], Bitmap.Config.ARGB_8888);
showProgressDialog();
enhanceImage(rectifiedImage, enhancedImage);
dismissProgressDialog();
diff --git a/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java b/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java
index 764312199..3b2a704d7 100755
--- a/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java
@@ -238,7 +238,7 @@ public final class GeometryMathUtils {
}
}
- private static int getRotationForOrientation(int orientation) {
+ public static int getRotationForOrientation(int orientation) {
switch (orientation) {
case ImageLoader.ORI_ROTATE_90:
return 90;
@@ -510,6 +510,45 @@ public final class GeometryMathUtils {
return m;
}
+ public static Matrix getWatermarkMatrix(GeometryHolder holder, int bitmapWidth,
+ int bitmapHeight, int viewWidth, int viewHeight
+ , int oldw, int oldh) {
+ int bh = bitmapHeight;
+ int bw = bitmapWidth;
+ if (GeometryMathUtils.needsDimensionSwap(holder.rotation)) {
+ bh = bitmapWidth;
+ bw = bitmapHeight;
+ }
+ float scale = GeometryMathUtils.getWatermarkScale(holder,bw, bh, viewWidth, viewHeight, oldw, oldh);
+ Matrix m = new Matrix();
+ m.setTranslate(-oldw / 2f, -oldh / 2f);
+ m.postScale(scale, scale);
+ m.postTranslate(viewWidth / 2f, viewHeight / 2f);
+ return m;
+ }
+
+ public static float getWatermarkScale(GeometryHolder holder, int bitmapWidth,
+ int bitmapHeight, int viewWidth, int viewHeight,
+ int oldw, int oldh) {
+ int bh = bitmapHeight;
+ int bw = bitmapWidth;
+ if (GeometryMathUtils.needsDimensionSwap(holder.rotation)) {
+ bh = bitmapWidth;
+ bw = bitmapHeight;
+ }
+ float oldScale = GeometryMathUtils.scale(bw, bh, oldw, oldh);
+ if (oldScale > 3.0f) {
+ oldScale = 3.0f;
+ }
+ oldScale *= SHOW_SCALE;
+ float scale = GeometryMathUtils.scale(bw, bh, viewWidth, viewHeight);
+ if (scale > 3.0f) {
+ scale = 3.0f;
+ }
+ scale *= SHOW_SCALE;
+ return scale / oldScale;
+ }
+
public static RectF getTrueCropRect(GeometryHolder holder, int bitmapWidth, int bitmapHeight) {
RectF r = new RectF(holder.crop);
FilterCropRepresentation.findScaledCrop(r, bitmapWidth, bitmapHeight);
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java b/src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java
index 962519373..1c506fd64 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -75,6 +75,6 @@ public class ImageDualCamera extends ImageShow {
}
private void calcScreenMapping() {
- mToOrig = getScreenToImageMatrix(true);
+ mToOrig = MasterImage.getImage().getScreenToImageMatrix(true);
}
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageTruePortraitFusion.java b/src/com/android/gallery3d/filtershow/imageshow/ImageTruePortraitFusion.java
index 8413c5dd9..dcce40e92 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageTruePortraitFusion.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageTruePortraitFusion.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -65,6 +65,10 @@ public class ImageTruePortraitFusion extends ImageShow {
}
mUnderlay = ImageLoader.loadConstrainedBitmap(uri, getContext(), MasterImage.MAX_BITMAP_DIM, new Rect(), false);
+ int ori = ImageLoader.getMetadataOrientation(getContext(), uri);
+ if (ori != ImageLoader.ORI_NORMAL) {
+ mUnderlay = ImageLoader.orientBitmap(mUnderlay, ori);
+ }
MasterImage.getImage().setFusionUnderlay(mUnderlay);
invalidate();
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
index 0a13da737..c1750b17f 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
@@ -21,6 +21,7 @@ import java.util.Vector;
import android.animation.Animator;
import android.animation.ValueAnimator;
+import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
@@ -36,6 +37,7 @@ import com.android.gallery3d.exif.ExifTag;
import com.android.gallery3d.filtershow.FilterShowActivity;
import com.android.gallery3d.filtershow.cache.BitmapCache;
import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.category.WaterMarkView;
import com.android.gallery3d.filtershow.filters.FilterDualCamFusionRepresentation;
import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
@@ -116,6 +118,7 @@ public class MasterImage implements RenderingRequestCaller {
private FilterShowActivity mActivity = null;
private Vector<ImageShow> mObservers = new Vector<ImageShow>();
+ private Vector<WaterMarkView> mWaterMarks = new Vector<WaterMarkView>();
private FilterRepresentation mCurrentFilterRepresentation;
private float mScaleFactor = 1.0f;
@@ -337,6 +340,17 @@ public class MasterImage implements RenderingRequestCaller {
mObservers.remove(observer);
}
+ public void addWaterMark(WaterMarkView waterMarkView) {
+ if (mWaterMarks.contains(waterMarkView)) {
+ return;
+ }
+ mWaterMarks.add(waterMarkView);
+ }
+
+ public void removeWaterMark(WaterMarkView waterMarkView) {
+ mWaterMarks.remove(waterMarkView);
+ }
+
public void setActivity(FilterShowActivity activity) {
mActivity = activity;
}
@@ -615,6 +629,11 @@ public class MasterImage implements RenderingRequestCaller {
}
}
+ public void notifyWaterMarks() {
+ for (WaterMarkView waterMarkView : mWaterMarks) {
+ waterMarkView.update();
+ }
+ }
public void resetGeometryImages(boolean force) {
if (mPreset == null) {
return;
@@ -727,9 +746,9 @@ public class MasterImage implements RenderingRequestCaller {
bitmapToDraw.getWidth(),
bitmapToDraw.getHeight());
scale = mImageShowSize.x / size.width();
- if (size.width() < size.height()) {
- scale = mImageShowSize.y / size.height();
- }
+ float tmp = mImageShowSize.y / size.height();
+ // Choose the smaller one to avoid master image beyound the screen.
+ scale = scale < tmp ? scale : tmp;
translateX = (mImageShowSize.x - (size.width() * scale)) / 2.0f;
translateY = (mImageShowSize.y - (size.height() * scale)) / 2.0f;
} else {
@@ -767,7 +786,7 @@ public class MasterImage implements RenderingRequestCaller {
return m;
}
- private Matrix getScreenToImageMatrix(boolean reflectRotation) {
+ public Matrix getScreenToImageMatrix(boolean reflectRotation) {
Matrix m = getImageToScreenMatrix(reflectRotation);
Matrix invert = new Matrix();
m.invert(invert);
@@ -846,6 +865,7 @@ public class MasterImage implements RenderingRequestCaller {
mBitmapCache.cache(mHighresBitmap);
mHighresBitmap = request.getBitmap();
notifyObservers();
+ notifyWaterMarks();
needsCheckModification = true;
}
}
@@ -960,7 +980,7 @@ public class MasterImage implements RenderingRequestCaller {
return mPreset.contains(FilterRepresentation.TYPE_TINYPLANET);
}
- public boolean loadMpo(byte[] primaryMpoData, byte[] auxiliaryMpoData) {
+ public boolean loadMpo(Context context, byte[] primaryMpoData, byte[] auxiliaryMpoData, Uri uri){
boolean loaded = false;
if(auxiliaryMpoData != null) {
@@ -971,7 +991,11 @@ public class MasterImage implements RenderingRequestCaller {
}
// check for pre-generated dm file
- String mpoFilepath = ImageLoader.getLocalPathFromUri(getActivity(), getUri());
+ String mpoFilepath = ImageLoader.getLocalPathFromUri(context, uri);
+ if(mpoFilepath == null) {
+ Log.d(LOGTAG, "Could not get file path from " + uri);
+ return false;
+ }
// read auxiliary image and generate depth map.
Bitmap auxiliaryBm = BitmapFactory.decodeByteArray(auxiliaryMpoData, 0, auxiliaryMpoData.length);
@@ -983,7 +1007,7 @@ public class MasterImage implements RenderingRequestCaller {
DualCameraNativeEngine.getInstance().initDepthMap(
primaryBm, auxiliaryBm, mpoFilepath,
- DualCameraNativeEngine.getInstance().getCalibFilepath(mActivity));
+ DualCameraNativeEngine.getInstance().getCalibFilepath(context),1.0f);
primaryBm.recycle();
primaryBm = null;
@@ -1017,6 +1041,10 @@ public class MasterImage implements RenderingRequestCaller {
return loaded;
}
+ public boolean loadMpo(byte[] primaryMpoData, byte[] auxiliaryMpoData) {
+ return loadMpo(getActivity(), primaryMpoData, auxiliaryMpoData, getUri());
+ }
+
public void setFusionUnderlay(Bitmap underlay) {
mFusionUnderlay = underlay;
}
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/MediaAdapter.java b/src/com/android/gallery3d/filtershow/mediapicker/MediaAdapter.java
new file mode 100644
index 000000000..380fa119a
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/MediaAdapter.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.MediaStore;
+import android.support.v4.widget.CursorAdapter;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.AbsListView.RecyclerListener;
+import android.widget.RelativeLayout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.android.gallery3d.filtershow.mediapicker.imageloader.ImageLoaderStub;
+import org.codeaurora.gallery.R;
+
+/**
+ * Adapter for display media item list.
+ */
+public class MediaAdapter extends CursorAdapter implements RecyclerListener {
+ private ImageLoaderStub mMediaImageLoader;
+ private Uri mMediaSelected;
+ private int mItemHeight = 0;
+ private int mNumColumns = 0;
+ private RelativeLayout.LayoutParams mImageViewLayoutParams;
+ private List<SelectedImageView> mImageViewSelected = new ArrayList<SelectedImageView>();
+
+ public MediaAdapter(Context context, Cursor c, int flags,
+ ImageLoaderStub mediaImageLoader) {
+ this(context, c, flags, null, mediaImageLoader);
+ }
+
+ public MediaAdapter(Context context, Cursor c, int flags,
+ Uri mediaSelected, ImageLoaderStub mediaImageLoader) {
+ super(context, c, flags);
+ mMediaSelected = mediaSelected;
+ mMediaImageLoader = mediaImageLoader;
+ mImageViewLayoutParams = new RelativeLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ final SelectedImageView imageView = (SelectedImageView) view.getTag();
+ final Uri uri;
+ uri = getPhotoUri(cursor);
+
+ boolean isSelected = isSelected(uri);
+ imageView.setSelected(isSelected);
+ if (isSelected) {
+ mImageViewSelected.add(imageView);
+ }
+ mMediaImageLoader.displayImage(uri, imageView);
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
+ View root = View
+ .inflate(context, R.layout.mediapicker_list_item, null);
+ SelectedImageView imageView = (SelectedImageView) root.findViewById(R.id.thumbnail);
+
+ imageView.setLayoutParams(mImageViewLayoutParams);
+ // Check the height matches our calculated column width
+ if (imageView.getLayoutParams().height != mItemHeight) {
+ imageView.setLayoutParams(mImageViewLayoutParams);
+ }
+ root.setTag(imageView);
+ return root;
+ }
+
+ public Uri getPhotoUri(Cursor cursor) {
+ String id = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
+ return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
+ }
+
+ /**
+ * Check media uri is selected or not.
+ *
+ * @param uri Uri of media item (photo, video)
+ * @return true if selected, false otherwise.
+ */
+ public boolean isSelected(Uri uri) {
+ if (uri == null)
+ return false;
+ if (mMediaSelected != null) {
+ if (mMediaSelected.equals(uri))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * If item selected then change to unselected and unselected to selected.
+ *
+ * @param item Item to update.
+ */
+ public void updateMediaSelected(Uri item,
+ SelectedImageView selImageView) {
+ if (mMediaSelected == null || !mMediaSelected.equals(item)) {
+ for (SelectedImageView picker : this.mImageViewSelected) {
+ picker.setSelected(false);
+ }
+ this.mImageViewSelected.clear();
+
+ mMediaSelected = item;
+ selImageView.setSelected(true);
+ this.mImageViewSelected.add(selImageView);
+ }
+ }
+
+ public void setMediaSelected(Uri item) {
+ mMediaSelected = item;
+ }
+
+ // set numcols
+ public void setNumColumns(int numColumns) {
+ mNumColumns = numColumns;
+ }
+
+ public int getNumColumns() {
+ return mNumColumns;
+ }
+
+ // set photo item height
+ public void setItemHeight(int height) {
+ if (height == mItemHeight) {
+ return;
+ }
+ mItemHeight = height;
+ mImageViewLayoutParams.height = height;
+ mImageViewLayoutParams.width = height;
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public void onMovedToScrapHeap(View view) {
+ SelectedImageView imageView = (SelectedImageView) view
+ .findViewById(R.id.thumbnail);
+ mImageViewSelected.remove(imageView);
+ }
+
+ public void onDestroyView() {
+ mImageViewSelected.clear();
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/MediaPicker.java b/src/com/android/gallery3d/filtershow/mediapicker/MediaPicker.java
new file mode 100644
index 000000000..7fa96faf9
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/MediaPicker.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.Build;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+
+import com.android.photos.views.HeaderGridView;
+
+import org.codeaurora.gallery.R;
+
+public class MediaPicker extends ViewGroup {
+
+ private LinearLayout mSelStrip;
+ private LinearLayout mSlideStrip;
+ private HeaderGridView mGridView;
+ private ImageButton mArrow;
+
+ private boolean mIsFullScreen, mLayoutChanged;
+ private int mCurrentDesiredHeight;
+
+ private final Handler mHandler = new Handler();
+ private int mDefaultGridHeight;
+ private TouchHandler mTouchHandler;
+
+ static Context mContext;
+
+ public MediaPicker(final Context context, final AttributeSet attrs) {
+ super(context, attrs);
+ mContext = context;
+ mIsFullScreen = true;
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mSlideStrip = (LinearLayout) findViewById(R.id.mediapicker_slidestrip);
+ mSelStrip = (LinearLayout) findViewById(R.id.mediapicker_tabstrip);
+ mGridView = (HeaderGridView) findViewById(R.id.grid);
+ mArrow = (ImageButton) findViewById(R.id.arrow);
+ mTouchHandler = new TouchHandler();
+ mArrow.setOnTouchListener(mTouchHandler);
+
+ addOnLayoutChangeListener(new OnLayoutChangeListener() {
+ private boolean mLandMode = isLandscapeMode();
+
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ final boolean newLandMode = isLandscapeMode();
+ if (mLandMode != newLandMode) {
+ mLandMode = newLandMode;
+ mLayoutChanged = true;
+ setupFullScreen(mIsFullScreen, false);
+ }
+ }
+ });
+ }
+
+ @Override
+ protected void onLayout(final boolean changed, final int left, final int top, final int right,
+ final int bottom) {
+ int y = bottom;
+ final int width = right - left;
+ final int selHight = mSelStrip.getMeasuredHeight();
+ mSelStrip.layout(0, y - selHight, width, y);
+ y -= selHight;
+
+ final int gridHeight = mGridView.getMeasuredHeight();
+ mGridView.layout(0, y - gridHeight, width, y);
+ y -= gridHeight;
+
+ mSlideStrip.layout(0, y - mSlideStrip.getMeasuredHeight(), width, y);
+ }
+
+ @Override
+ protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
+ int requestedHeight = MeasureSpec.getSize(heightMeasureSpec);
+ measureChild(mSelStrip, widthMeasureSpec, heightMeasureSpec);
+
+ int selStripHeight = mSelStrip.getMeasuredHeight();
+ measureChild(mSlideStrip, widthMeasureSpec, heightMeasureSpec);
+ int slideHeight = mSlideStrip.getMeasuredHeight();
+
+ final int gridAdjustedHeight = mCurrentDesiredHeight - selStripHeight - slideHeight;
+ int gridHeight;
+ if (gridAdjustedHeight < 0)
+ gridHeight = 0;
+ else if (gridAdjustedHeight < mDefaultGridHeight)
+ gridHeight = mDefaultGridHeight;
+ else
+ gridHeight = gridAdjustedHeight;
+
+ int gridHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ gridHeight, MeasureSpec.EXACTLY);
+ measureChild(mGridView, widthMeasureSpec, gridHeightMeasureSpec);
+ setMeasuredDimension(mGridView.getMeasuredWidth(), requestedHeight);
+ }
+
+ public void setupFullScreen(final boolean isFullScreen, final boolean animate) {
+ if (isFullScreen == mIsFullScreen && !mLayoutChanged) {
+ return;
+ }
+
+ mIsFullScreen = isFullScreen;
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ setViewHeight(animate);
+ }
+ });
+ }
+
+ private void setViewHeight(boolean animate) {
+ final int startHeight = mCurrentDesiredHeight;
+ int height = getContext().getResources().getDisplayMetrics().heightPixels;
+ if (!mIsFullScreen) {
+ height = measureHeight();
+ }
+ clearAnimation();
+ if (animate) {
+ final int deltaHeight = height - startHeight;
+ final Animation animation = new Animation() {
+ @Override
+ protected void applyTransformation(final float interpolatedTime,
+ final Transformation t) {
+ mCurrentDesiredHeight = (int) (startHeight + deltaHeight * interpolatedTime);
+ requestLayout();
+ }
+
+ @Override
+ public boolean willChangeBounds() {
+ return true;
+ }
+ };
+ animation.setDuration(500);
+ startAnimation(animation);
+ } else {
+ mCurrentDesiredHeight = height;
+ }
+ if (mIsFullScreen)
+ mArrow.setImageResource(R.drawable.arrow_down);
+ else
+ mArrow.setImageResource(R.drawable.arrow);
+ requestLayout();
+ }
+
+ private int measureHeight() {
+ final int measureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 1, MeasureSpec.AT_MOST);
+ measureChild(mSelStrip, measureSpec, measureSpec);
+ measureChild(mSlideStrip, measureSpec, measureSpec);
+ if (isLandscapeMode())
+ mDefaultGridHeight = getResources().getDimensionPixelSize(
+ R.dimen.mediapicker_land_height);
+ else
+ mDefaultGridHeight = getResources().getDimensionPixelSize(
+ R.dimen.mediapicker_default_height);
+ return mDefaultGridHeight + mSelStrip.getMeasuredHeight() + mSlideStrip.getMeasuredHeight();
+ }
+
+ private boolean isLandscapeMode() {
+ return mContext.getResources().getConfiguration().orientation
+ == Configuration.ORIENTATION_LANDSCAPE;
+ }
+
+ private class TouchHandler implements OnTouchListener {
+ private boolean mMoved = false;
+ private MotionEvent mDownEvent;
+ private static final float DIRECTION_RATIO = 1.1f;
+ private static final int TOUCH_THRESHOLD = 450;
+ private static final int TOUCH_SLOP = 24;
+
+
+ TouchHandler() {
+ }
+
+ boolean checkMoved(final MotionEvent mv) {
+ final float dx = mDownEvent.getRawX() - mv.getRawX();
+ final float dy = mDownEvent.getRawY() - mv.getRawY();
+ if (Math.abs(dy) > TOUCH_SLOP &&
+ (Math.abs(dy) / Math.abs(dx)) > DIRECTION_RATIO) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onTouch(final View view, final MotionEvent motionEvent) {
+ switch (motionEvent.getAction()) {
+ case MotionEvent.ACTION_UP: {
+ if (!mMoved || mDownEvent == null) {
+ return false;
+ }
+
+ final float dy = motionEvent.getRawY() - mDownEvent.getRawY();
+ final float dt =
+ (motionEvent.getEventTime() - mDownEvent.getEventTime()) / 1000.0f;
+ final float yVelocity = dy / dt;
+
+ if (checkMoved(motionEvent)) {
+ if ((yVelocity + TOUCH_THRESHOLD) < 0 && !mIsFullScreen) {
+ setupFullScreen(true, true);
+ } else if ((yVelocity - TOUCH_THRESHOLD) > 0 && mIsFullScreen) {
+ setupFullScreen(false, true);
+ }
+ }
+ mDownEvent = null;
+ mMoved = false;
+ break;
+ }
+ case MotionEvent.ACTION_DOWN: {
+ mDownEvent = MotionEvent.obtain(motionEvent);
+ return true;
+ }
+ case MotionEvent.ACTION_MOVE: {
+ if (mDownEvent == null) {
+ return mMoved;
+ }
+ if (checkMoved(motionEvent)) {
+ mMoved = true;
+ }
+ }
+ }
+ return mMoved;
+ }
+ }
+}
+
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/MediaPickerFragment.java b/src/com/android/gallery3d/filtershow/mediapicker/MediaPickerFragment.java
new file mode 100644
index 000000000..68e76fc98
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/MediaPickerFragment.java
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker;
+
+import android.app.Activity;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.provider.MediaStore;
+import android.provider.MediaStore.Images;
+import android.provider.MediaStore.MediaColumns;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ImageButton;
+
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.mediapicker.imageloader.ImageLoaderStub;
+import com.android.photos.views.HeaderGridView;
+
+import org.codeaurora.gallery.R;
+
+/**
+ * Display list of videos, photos from {@link MediaStore} and select one or many
+ * item from list depends on {@link MediaOptions} that passed when open media
+ * picker.
+ */
+public class MediaPickerFragment extends Fragment implements
+ LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener {
+ private static final String LOADER_EXTRA_URI = "loader_extra_uri";
+ private static final String LOADER_EXTRA_PROJECT = "loader_extra_project";
+ private static final String KEY_GRID_STATE = "grid_state";
+ private static final String KEY_MEDIA_SELECTED = "media_selected";
+ private HeaderGridView mGridView;
+
+ protected ImageLoaderStub mMediaImageLoader;
+ protected Context mContext;
+ protected static Context appContext;
+ protected FilterShowActivity mActivity;
+ protected FilterRepresentation mCntFp, mOldFp;
+
+ private MediaAdapter mMediaAdapter;
+
+ private Bundle mSavedInstanceState;
+ private Uri mMediaSelected;
+ private ImageButton mSelDone, mSelCancel;
+
+ private int mPhotoSize, mPhotoSpacing;
+ private int mIndexPreset;
+ private MediaPicker mMediaPicker;
+
+ public MediaPickerFragment() {
+ mSavedInstanceState = new Bundle();
+ }
+
+ public static MediaPickerFragment newInstance(Context context) {
+ MediaPickerFragment fragment = new MediaPickerFragment();
+ appContext = context;
+ return fragment;
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ mMediaImageLoader = new ImageLoaderStub(appContext);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (savedInstanceState != null) {
+ mMediaSelected = savedInstanceState
+ .getParcelable(KEY_MEDIA_SELECTED);
+ mSavedInstanceState = savedInstanceState;
+ }
+
+ // get the photo size and spacing
+ mPhotoSize = getResources().getDimensionPixelSize(
+ R.dimen.picker_photo_size);
+ mPhotoSpacing = getResources().getDimensionPixelSize(
+ R.dimen.picker_photo_spacing);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ mMediaPicker = (MediaPicker) inflater.inflate(
+ R.layout.mediapicker_panel,
+ container,
+ false);
+ mSelDone = (ImageButton) mMediaPicker.findViewById(R.id.btn_yes);
+ mSelCancel = (ImageButton) mMediaPicker.findViewById(R.id.btn_no);
+ mSelDone.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mMediaSelected != null) {
+ mActivity.onMediaPickerResult(mMediaSelected);
+ } else {
+ mActivity.useFilterRepresentation(mOldFp);
+ mActivity.onBackPressed();
+ }
+ }
+ });
+ mSelCancel.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mOldFp != null)
+ mActivity.useFilterRepresentation(mOldFp);
+ else
+ mActivity.setDefaultPreset();
+ mActivity.onBackPressed();
+ }
+ });
+
+ initView(mMediaPicker);
+ mMediaPicker.setupFullScreen(false, true);
+ return mMediaPicker;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ mContext = getActivity();
+ mActivity = (FilterShowActivity) mContext;
+ mOldFp = mActivity.getCurrentPresentation();
+ mIndexPreset = 100;
+ requestPic();
+ }
+
+ public void requestPic() {
+ requestMedia(Images.Media.EXTERNAL_CONTENT_URI,
+ new String[]{MediaColumns._ID});
+ }
+
+ private void requestMedia(Uri uri, String[] projects) {
+ Bundle bundle = new Bundle();
+ bundle.putStringArray(LOADER_EXTRA_PROJECT, projects);
+ bundle.putString(LOADER_EXTRA_URI, uri.toString());
+ getLoaderManager().initLoader(0, bundle, this);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ if (mGridView != null) {
+ mSavedInstanceState.putParcelable(KEY_GRID_STATE,
+ mGridView.onSaveInstanceState());
+ }
+ mSavedInstanceState.putParcelable(KEY_MEDIA_SELECTED,
+ mMediaSelected);
+ outState.putAll(mSavedInstanceState);
+ }
+
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
+ Uri uri = Uri.parse(bundle.getString(LOADER_EXTRA_URI));
+ String[] projects = bundle.getStringArray(LOADER_EXTRA_PROJECT);
+ String order = MediaColumns.DATE_ADDED + " DESC";
+ return new CursorLoader(mContext, uri, projects, null, null, order);
+ }
+
+ private void attachData(Cursor cursor) {
+ if (cursor == null || cursor.getCount() <= 0) {
+ switchToError();
+ return;
+ }
+ mGridView.setVisibility(View.VISIBLE);
+ if (mMediaSelected != null) {
+ mMediaSelected = null;
+ mMediaAdapter.setMediaSelected(mMediaSelected);
+ }
+ if (mMediaAdapter == null) {
+ mMediaAdapter = new MediaAdapter(mContext, cursor, 0,
+ mMediaImageLoader);
+ } else {
+ mMediaAdapter.swapCursor(cursor);
+ }
+ if (mGridView.getAdapter() == null) {
+ mGridView.setAdapter(mMediaAdapter);
+ mGridView.setRecyclerListener(mMediaAdapter);
+ }
+ Parcelable state = mSavedInstanceState.getParcelable(KEY_GRID_STATE);
+ if (state != null) {
+ mGridView.onRestoreInstanceState(state);
+ }
+ mMediaAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
+ attachData(cursor);
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {
+ // Preference:http://developer.android.com/guide/components/loaders.html#callback
+ if (mMediaAdapter != null)
+ mMediaAdapter.swapCursor(null);
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position,
+ long id) {
+ Object object = parent.getAdapter().getItem(position);
+ if (object instanceof Cursor) {
+ Uri uri;
+ uri = getPicUri((Cursor) object);
+
+ if (!uri.equals(mMediaSelected)) {
+ mIndexPreset++;
+ mCntFp = mActivity.createUserPresentaion(uri, mIndexPreset);
+ mActivity.applyCustomFilterRepresentation(mCntFp, mOldFp);
+ }
+
+ SelectedImageView selImageView = (SelectedImageView) view
+ .findViewById(R.id.thumbnail);
+ mMediaSelected = uri;
+ mMediaAdapter.updateMediaSelected(uri, selImageView);
+ }
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ if (mGridView != null) {
+ mSavedInstanceState.putParcelable(KEY_GRID_STATE,
+ mGridView.onSaveInstanceState());
+ mGridView = null;
+ }
+ if (mMediaAdapter != null) {
+ mMediaAdapter.onDestroyView();
+ }
+ }
+
+
+ private Uri getPicUri(Cursor cursor) {
+ String id = cursor.getString(cursor.getColumnIndex(MediaColumns._ID));
+ return Uri.withAppendedPath(Images.Media.EXTERNAL_CONTENT_URI, id);
+ }
+
+ private void switchToError() {
+ mGridView.setVisibility(View.GONE);
+ mSelDone.setVisibility(View.GONE);
+ mSelCancel.setVisibility(View.GONE);
+ }
+
+ private void initView(MediaPicker view) {
+ mGridView = (HeaderGridView) view.findViewById(R.id.grid);
+ mGridView.setOnItemClickListener(this);
+
+ mGridView.getViewTreeObserver().addOnGlobalLayoutListener(
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ if (mMediaAdapter != null
+ && mMediaAdapter.getNumColumns() == 0) {
+ final int numColumns = (int) Math.floor(mGridView
+ .getWidth() / (mPhotoSize + mPhotoSpacing));
+ if (numColumns > 0) {
+ final int columnWidth = (mGridView.getWidth() / numColumns)
+ - mPhotoSpacing;
+ mMediaAdapter.setNumColumns(numColumns);
+ mMediaAdapter.setItemHeight(columnWidth);
+ }
+ }
+ }
+ });
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/SelectedImageView.java b/src/com/android/gallery3d/filtershow/mediapicker/SelectedImageView.java
new file mode 100644
index 000000000..11b4ee6b1
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/SelectedImageView.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+import org.codeaurora.gallery.R;
+
+public class SelectedImageView extends ImageView {
+
+ private boolean sel;
+ private int size = 1;
+ private Paint border;
+
+ public SelectedImageView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ public SelectedImageView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ private void init() {
+ border = new Paint();
+ border.setAntiAlias(true);
+ border.setColor(getResources().getColor(R.color.picker_color));
+ size = getResources().getDimensionPixelSize(
+ R.dimen.picker_border_size);
+ }
+
+ public SelectedImageView(Context context) {
+ super(context);
+ init();
+ }
+
+ public void setSelected(boolean selected) {
+ if (selected != this.sel) {
+ this.sel = selected;
+ invalidate();
+ }
+ }
+
+ public boolean isSelected() {
+ return sel;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int width = getMeasuredWidth();
+ setMeasuredDimension(width, width);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ if (sel) {
+ canvas.drawRect(0, 0, size, getHeight(), border);
+ canvas.drawRect(getWidth() - size, 0, getWidth(),
+ getHeight(), border);
+ canvas.drawRect(0, 0, getWidth(), size, border);
+ canvas.drawRect(0, getHeight() - size, getWidth(),
+ getHeight(), border);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageDisplayTask.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageDisplayTask.java
new file mode 100644
index 000000000..e9efb55ca
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageDisplayTask.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import android.graphics.Bitmap;
+import android.util.Log;
+
+final class ImageDisplayTask implements Runnable {
+
+ private static final String TAG = "ImageDisplayTask";
+
+ private final Bitmap bitmap;
+ private final ImageViewImpl imageView;
+ private final String memoryCacheKey;
+ private final ImageLoaderHandle handle;
+
+ public ImageDisplayTask(Bitmap bitmap, ImageLoaderInfo imageLoadingInfo,
+ ImageLoaderHandle handle) {
+ this.bitmap = bitmap;
+ imageView = imageLoadingInfo.imageView;
+ memoryCacheKey = imageLoadingInfo.memoryCacheKey;
+ this.handle = handle;
+ }
+
+ @Override
+ public void run() {
+ if (imageView.isRecyled()) {
+ Log.d(TAG, "Image was recyled by GC. Task is cancelled. " + memoryCacheKey);
+ } else if (isViewWasReused()) {
+ Log.d(TAG, "Image is reused for another image. Task is cancelled. " + memoryCacheKey);
+ } else {
+ Log.d(TAG, "Display image in ImageAware (loaded from " + memoryCacheKey);
+ imageView.setImageBitmap(bitmap);
+ handle.cacheKeysForImageAwares.remove(imageView.getId());
+ }
+ }
+
+ private boolean isViewWasReused() {
+ String currentCacheKey = handle.cacheKeysForImageAwares.get(imageView.getId());
+ return !memoryCacheKey.equals(currentCacheKey);
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderConfig.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderConfig.java
new file mode 100644
index 000000000..f9ec8b22d
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderConfig.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.os.Handler;
+import android.os.Looper;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executor;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+
+public class ImageLoaderConfig {
+
+ private final String TAG = "ImageLoaderConfig";
+ private static final String URI_AND_SIZE_SEPARATOR = "_";
+ private static final String WIDTH_AND_HEIGHT_SEPARATOR = "x";
+ final Resources resources;
+
+ public static final int DEFAULT_THREAD_POOL_SIZE = 4;
+ public static final int DEFAULT_THREAD_PRIORITY = Thread.NORM_PRIORITY - 2;
+ public Context context;
+
+ public Executor taskExecutor = null;
+ public boolean customExecutor = false;
+
+ public int threadPoolSize = DEFAULT_THREAD_POOL_SIZE;
+ public int threadPriority = DEFAULT_THREAD_PRIORITY;
+
+ private LinkedHashMap<String, Bitmap> imageCacheMap;
+ private int icmMaxSize;
+ private int icmSize;
+ public ImageLoaderOptions defaultOptions = null;
+
+ public ImageLoaderConfig(Context context) {
+ this.context = context.getApplicationContext();
+ resources = context.getResources();
+ initEmptyFieldsWithDefaultValues();
+ }
+
+ public void cacheMapSizePercentage(int availableMemoryPercent) {
+ if (availableMemoryPercent <= 0 || availableMemoryPercent >= 100) {
+ throw new IllegalArgumentException("availableMemoryPercent must be in range (0 < % < 100)");
+ }
+
+ long availableMemory = Runtime.getRuntime().maxMemory();
+ icmMaxSize = (int) (availableMemory * (availableMemoryPercent / 100f));
+ }
+
+ private void initEmptyFieldsWithDefaultValues() {
+ if (taskExecutor == null) {
+ taskExecutor = createExecutor(threadPoolSize, threadPriority);
+ } else {
+ customExecutor = true;
+ }
+ if (imageCacheMap == null) {
+ icmSize = 0;
+ imageCacheMap = new LinkedHashMap<String, Bitmap>(0, 0.75f, true);
+ }
+ if (defaultOptions == null) {
+ defaultOptions = new ImageLoaderOptions();
+ }
+ }
+
+ public final Bitmap get(String key) {
+ if (key == null) {
+ throw new NullPointerException("key == null");
+ }
+
+ synchronized (this) {
+ return imageCacheMap.get(key);
+ }
+ }
+
+ public final boolean put(String key, Bitmap value) {
+ if (key == null || value == null) {
+ throw new NullPointerException("key == null || value == null");
+ }
+
+ synchronized (this) {
+ icmSize += sizeOf(value);
+ Bitmap previous = imageCacheMap.put(key, value);
+ if (previous != null) {
+ icmSize -= sizeOf(previous);
+ }
+ }
+
+ trimToSize(icmMaxSize);
+ return true;
+ }
+
+ private void trimToSize(int maxSize) {
+ while (true) {
+ String key;
+ Bitmap value;
+ synchronized (this) {
+ if (icmSize < 0 || (imageCacheMap.isEmpty() && icmSize != 0)) {
+ throw new IllegalStateException(getClass().getName() + ".sizeOf() is inconsistent!");
+ }
+
+ if (icmSize <= maxSize || imageCacheMap.isEmpty()) {
+ break;
+ }
+
+ Map.Entry<String, Bitmap> toEvict = imageCacheMap.entrySet().iterator().next();
+ if (toEvict == null) {
+ break;
+ }
+ key = toEvict.getKey();
+ value = toEvict.getValue();
+ imageCacheMap.remove(key);
+ icmSize -= sizeOf(value);
+ }
+ }
+ }
+
+ public final Bitmap remove(String key) {
+ if (key == null) {
+ throw new NullPointerException("key == null");
+ }
+
+ synchronized (this) {
+ Bitmap previous = imageCacheMap.remove(key);
+ if (previous != null) {
+ icmSize -= sizeOf(previous);
+ }
+ return previous;
+ }
+ }
+
+ private int sizeOf(Bitmap value) {
+ return value.getRowBytes() * value.getHeight();
+ }
+
+
+ public int defineHeightForImage(ImageViewImpl imageView) {
+ int height = imageView.getHeight();
+ if (height <= 0)
+ height = resources.getDisplayMetrics().heightPixels;
+ return height;
+ }
+
+ public int defineWidthForImage(ImageViewImpl imageView) {
+ int width = imageView.getWidth();
+ if (width <= 0)
+ width = resources.getDisplayMetrics().widthPixels;
+ return width;
+ }
+
+ public static String generateKey(String imageUri, int w, int h) {
+ return new StringBuilder(imageUri).append(URI_AND_SIZE_SEPARATOR).append(w)
+ .append(WIDTH_AND_HEIGHT_SEPARATOR).append(h).toString();
+ }
+
+ public static Executor createExecutor(int threadPoolSize, int threadPriority) {
+ BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<Runnable>();
+ return new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0L, TimeUnit.MILLISECONDS,
+ taskQueue, new ThreadFactoryImpl(threadPriority));
+ }
+
+ public static Handler defineHandler(ImageLoaderOptions options) {
+ Handler handler = options.getHandler();
+ if (handler == null && Looper.myLooper() == Looper.getMainLooper()) {
+ handler = new Handler();
+ }
+ return handler;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderHandle.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderHandle.java
new file mode 100644
index 000000000..a7ed640a1
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderHandle.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.locks.ReentrantLock;
+
+class ImageLoaderHandle {
+
+ final ImageLoaderConfig configuration;
+
+ public Executor taskExecutor;
+ public Executor taskDistributor;
+
+ public final Map<Integer, String> cacheKeysForImageAwares = Collections
+ .synchronizedMap(new HashMap<Integer, String>());
+ private final Map<String, ReentrantLock> uriLocks = new WeakHashMap<String, ReentrantLock>();
+ private final Object pauseLock = new Object();
+
+ ImageLoaderHandle(ImageLoaderConfig configuration) {
+ this.configuration = configuration;
+
+ taskExecutor = configuration.taskExecutor;
+ taskDistributor = createTaskDistributor();
+ }
+
+ /** Submits task to execution pool */
+ void submit(final ImageLoaderTask task) {
+ taskDistributor.execute(new Runnable() {
+ @Override
+ public void run() {
+ if (!configuration.customExecutor && ((ExecutorService) taskExecutor).isShutdown()) {
+ taskExecutor = configuration.createExecutor(configuration.threadPoolSize,
+ configuration.threadPriority);
+ }
+ taskExecutor.execute(task);
+ }
+ });
+ }
+
+ ReentrantLock getLockForUri(String uri) {
+ ReentrantLock lock = uriLocks.get(uri);
+ if (lock == null) {
+ lock = new ReentrantLock();
+ uriLocks.put(uri, lock);
+ }
+ return lock;
+ }
+
+ public static Executor createTaskDistributor() {
+ return Executors.newCachedThreadPool(new ThreadFactoryImpl(Thread.NORM_PRIORITY));
+ }
+
+ void prepareDisplayTaskFor(ImageViewImpl imageView, String memoryCacheKey) {
+ cacheKeysForImageAwares.put(imageView.getId(), memoryCacheKey);
+ }
+}
+
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderInfo.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderInfo.java
new file mode 100644
index 000000000..6514a68c3
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderInfo.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Information for load'n'display image task
+ */
+final class ImageLoaderInfo {
+
+ final String uri;
+ final String memoryCacheKey;
+ final ImageViewImpl imageView;
+ final int targetHeight;
+ final int targetWidth;
+ final ImageLoaderOptions options;
+ final ReentrantLock loadFromUriLock;
+
+ public ImageLoaderInfo(String uri, ImageViewImpl imageView, int height, int width, String memoryCacheKey,
+ ImageLoaderOptions options, ReentrantLock loadFromUriLock) {
+ this.uri = uri;
+ this.imageView = imageView;
+ this.targetHeight = height;
+ this.targetWidth = width;
+ this.options = options;
+ this.loadFromUriLock = loadFromUriLock;
+ this.memoryCacheKey = memoryCacheKey;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderInstance.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderInstance.java
new file mode 100644
index 000000000..5839d82bd
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderInstance.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import android.graphics.Bitmap;
+import android.text.TextUtils;
+import android.util.Log;
+
+public class ImageLoaderInstance {
+
+ private ImageLoaderHandle handle;
+ private ImageLoaderConfig configuration;
+ private volatile static ImageLoaderInstance instance;
+ private static final String TAG = "ImageLoaderInstance";
+
+ /** Returns singleton class instance */
+ public static ImageLoaderInstance getInstance() {
+ if (instance == null) {
+ synchronized (ImageLoaderInstance.class) {
+ if (instance == null) {
+ instance = new ImageLoaderInstance();
+ }
+ }
+ }
+ return instance;
+ }
+
+ protected ImageLoaderInstance() {
+ }
+
+ public synchronized void init(ImageLoaderConfig configuration) {
+ if (this.configuration == null) {
+ handle = new ImageLoaderHandle(configuration);
+ this.configuration = configuration;
+ }
+ }
+
+ public void displayImage(String uri, ImageViewImpl imageView, ImageLoaderOptions options){
+ if (imageView == null) {
+ throw new IllegalArgumentException("Null iamgeView were passed.");
+ }
+ if (TextUtils.isEmpty(uri)) {
+ handle.cacheKeysForImageAwares.remove(imageView.getId());
+ imageView.setImageDrawable(options.getImageForEmptyUri(configuration.resources));
+ return;
+ }
+
+ int imageHeight = configuration.defineHeightForImage(imageView);
+ int imageWidth = configuration.defineWidthForImage(imageView);
+ String memoryCacheKey = configuration.generateKey(uri, imageHeight, imageWidth);
+ handle.prepareDisplayTaskFor(imageView, memoryCacheKey);
+
+ Bitmap bmp = configuration.get(memoryCacheKey);
+ if (bmp != null && !bmp.isRecycled()) {
+ Log.d(TAG, "Load image from memory cache " + memoryCacheKey);
+ imageView.setImageBitmap(bmp);
+ } else {
+ imageView.setImageDrawable(options.getImageOnLoading(configuration.resources));
+ ImageLoaderInfo imageLoadingInfo = new ImageLoaderInfo(uri, imageView, imageHeight, imageWidth,
+ memoryCacheKey, options, handle.getLockForUri(uri));
+ ImageLoaderTask displayTask = new ImageLoaderTask(handle, imageLoadingInfo,
+ configuration.defineHandler(options));
+ handle.submit(displayTask);
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderOptions.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderOptions.java
new file mode 100644
index 000000000..2e6261fa0
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderOptions.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import org.codeaurora.gallery.R;
+
+public class ImageLoaderOptions {
+
+ private int imageResOnLoading = R.color.picker_imageloading;
+ private int imageResForEmptyUri = 0;
+ private Drawable imageOnLoading = null;
+ private Drawable imageForEmptyUri = null;
+ private Handler handler = null;
+
+ public Drawable getImageOnLoading(Resources res) {
+ return imageResOnLoading != 0 ? res.getDrawable(imageResOnLoading) : imageOnLoading;
+ }
+
+ public Drawable getImageForEmptyUri(Resources res) {
+ return imageResForEmptyUri != 0 ? res.getDrawable(imageResForEmptyUri) : imageForEmptyUri;
+ }
+
+ public Handler getHandler() {
+ return handler;
+ }
+
+}
+
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderStub.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderStub.java
new file mode 100644
index 000000000..454715f7c
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderStub.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import android.content.Context;
+import android.net.Uri;
+import android.widget.ImageView;
+
+
+public class ImageLoaderStub {
+ private ImageLoaderConfig configuration;
+
+ public ImageLoaderStub(Context context) {
+ configuration = new ImageLoaderConfig(context);
+ configuration.cacheMapSizePercentage(30);
+ ImageLoaderInstance.getInstance().init(configuration);
+ }
+
+ public void displayImage(Uri uri, ImageView imageView) {
+ ImageLoaderOptions displayImageOptions = new ImageLoaderOptions();
+
+ ImageViewImpl imageViewImpl = new ImageViewImpl(imageView);
+ ImageLoaderInstance.getInstance().displayImage(uri.toString(), imageViewImpl, displayImageOptions);
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderTask.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderTask.java
new file mode 100644
index 000000000..7716a874d
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderTask.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import android.content.ContentResolver;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
+import android.net.Uri;
+import android.os.Handler;
+import android.util.Log;
+
+import java.io.Closeable;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.locks.ReentrantLock;
+
+final class ImageLoaderTask implements Runnable {
+
+ private final String TAG = "ImageLoaderTask";
+ private final ImageLoaderHandle handle;
+ private final ImageLoaderInfo imageLoadingInfo;
+ private final Handler handler;
+
+ final String uri;
+ private final String memoryCacheKey;
+ final ImageViewImpl imageView;
+ private int imageHeight, imageWidth;
+
+ public ImageLoaderTask(ImageLoaderHandle handle, ImageLoaderInfo imageLoadingInfo, Handler handler) {
+ this.handle = handle;
+ this.imageLoadingInfo = imageLoadingInfo;
+ this.handler = handler;
+
+ uri = imageLoadingInfo.uri;
+ memoryCacheKey = imageLoadingInfo.memoryCacheKey;
+ imageView = imageLoadingInfo.imageView;
+ imageHeight = imageLoadingInfo.targetHeight;
+ imageWidth = imageLoadingInfo.targetWidth;
+ }
+
+ @Override
+ public void run() {
+ if (isTaskAvailable()) return;
+
+ ReentrantLock loadFromUriLock = imageLoadingInfo.loadFromUriLock;
+ Log.d(TAG, "Start display image task " + memoryCacheKey);
+ loadFromUriLock.lock();
+ Bitmap bmp = null;
+ try {
+ checkTaskNotActual();
+ checkTaskInterrupted();
+ bmp = handle.configuration.get(memoryCacheKey);
+ if (bmp == null || bmp.isRecycled()) {
+ bmp = parseImage(uri);
+ if (bmp == null) return;
+
+ checkTaskNotActual();
+ checkTaskInterrupted();
+ if (bmp != null) {
+ Log.d(TAG, "Cache image in memory " + memoryCacheKey);
+ handle.configuration.put(memoryCacheKey, bmp);
+ }
+ } else {
+ Log.d(TAG, "Get cached bitmap from memory after waiting. " + memoryCacheKey);
+ }
+ checkTaskNotActual();
+ checkTaskInterrupted();
+ } catch (TaskInvalidException e) {
+ return;
+ } catch (IOException e) {
+ Log.e(TAG, e.toString());
+ } catch (OutOfMemoryError e) {
+ Log.e(TAG, e.toString());
+ } catch (Throwable e) {
+ Log.e(TAG, e.toString());
+ } finally {
+ loadFromUriLock.unlock();
+ }
+ ImageDisplayTask displayBitmapTask = new ImageDisplayTask(bmp, imageLoadingInfo, handle);
+ runTask(displayBitmapTask, handler, handle);
+ }
+
+
+ private Bitmap parseImage(String imageUri) throws IOException {
+ ViewScaleType viewScaleType = imageView.getScaleType();
+ Bitmap parsedBitmap;
+ BitmapFactory.Options opt;
+
+ InputStream imageStream = getImageStream(imageUri);
+ try {
+ opt = getImageOpt(imageStream);
+ imageStream = resetStream(imageStream, imageUri);
+ int scale = computeImageSampleSize(opt, imageHeight, imageWidth, viewScaleType);
+ BitmapFactory.Options decodingOptions = new BitmapFactory.Options();
+ decodingOptions.inSampleSize = scale;
+ parsedBitmap = BitmapFactory.decodeStream(imageStream, null, decodingOptions);
+ } finally {
+ closeSilently(imageStream);
+ }
+
+ if (parsedBitmap == null) {
+ Log.e(TAG, "Image can't be parsed: " + memoryCacheKey);
+ } else {
+ parsedBitmap = checkScale(parsedBitmap);
+ }
+ return parsedBitmap;
+ }
+
+ public static void closeSilently(Closeable closeable) {
+ try {
+ closeable.close();
+ } catch (Exception e) {
+ // Just catched here.
+ }
+ }
+
+ protected InputStream getImageStream(String imageUri) throws FileNotFoundException {
+ ContentResolver res = handle.configuration.context.getContentResolver();
+ Uri uri = Uri.parse(imageUri);
+ return res.openInputStream(uri);
+ }
+
+ protected BitmapFactory.Options getImageOpt(InputStream imageStream)
+ throws IOException {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeStream(imageStream, null, options);
+
+ return options;
+ }
+
+ protected InputStream resetStream(InputStream imageStream, String imageUri) throws IOException {
+ try {
+ imageStream.reset();
+ } catch (IOException e) {
+ closeSilently(imageStream);
+ imageStream = getImageStream(imageUri);
+ }
+ return imageStream;
+ }
+
+ public static int computeImageSampleSize(BitmapFactory.Options opt, int h, int w,
+ ViewScaleType viewScaleType) {
+ final int width = opt.outWidth/2;
+ final int height = opt.outHeight/2;
+ final int maxWidth = 2048;
+ final int maxHeight = 2048;
+
+ int scale = 1;
+ switch (viewScaleType) {
+ case FIT_INSIDE:
+ while ((width / scale) > w || (height / scale) > h) {
+ scale *= 2;
+ }
+ break;
+ case CROP:
+ while ((width / scale) > w && (height / scale) > h) {
+ scale *= 2;
+ }
+ break;
+ }
+ while ((opt.outWidth / scale) > maxWidth || (opt.outHeight / scale) > maxHeight) {
+ scale *= 2;
+ }
+ return scale;
+ }
+
+ protected Bitmap checkScale(Bitmap subsampledBitmap) {
+ Matrix m = new Matrix();
+
+ Bitmap finalBitmap = Bitmap.createBitmap(subsampledBitmap, 0, 0, subsampledBitmap.getWidth(),
+ subsampledBitmap.getHeight(), m, true);
+ if (finalBitmap != subsampledBitmap) {
+ subsampledBitmap.recycle();
+ }
+ return finalBitmap;
+ }
+
+ private boolean isTaskAvailable() {
+ if (isRecyled() || isCached())
+ return true;
+ return false;
+ }
+
+ private void checkTaskNotActual() throws TaskInvalidException {
+ if (isRecyled()) {
+ throw new TaskInvalidException();
+ }
+ if (isCached()) {
+ throw new TaskInvalidException();
+ }
+ }
+
+ private boolean isRecyled() {
+ if (imageView.isRecyled()) {
+ Log.d(TAG,"ImageAware was collected by GC. Task is cancelled: " + memoryCacheKey);
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isCached() {
+ String cntCacheKey = handle.cacheKeysForImageAwares.get(imageView.getId());
+ if (!memoryCacheKey.equals(cntCacheKey)) {
+ Log.d(TAG, "Imageview is cached for another image: " + memoryCacheKey);
+ return true;
+ }
+ return false;
+ }
+
+ private void checkTaskInterrupted() throws TaskInvalidException {
+ if (Thread.interrupted()) {
+ throw new TaskInvalidException();
+ }
+ }
+
+ static void runTask(Runnable r, Handler handler, ImageLoaderHandle handle) {
+ if (handler == null) {
+ handle.taskDistributor.execute(r);
+ } else {
+ handler.post(r);
+ }
+ }
+
+ class TaskInvalidException extends Exception {
+ }
+}
+
+
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageViewImpl.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageViewImpl.java
new file mode 100644
index 000000000..3f1e2b1b5
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageViewImpl.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import android.graphics.Bitmap;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Looper;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+
+
+public class ImageViewImpl{
+
+ private final static String TAG = "ImageViewImpl";
+ protected Reference<View> viewRef;
+
+
+ public ImageViewImpl(ImageView imageView) {
+ if (imageView == null) throw new IllegalArgumentException("view must not be null");
+
+ this.viewRef = new WeakReference<View>(imageView);
+ }
+
+ public int getWidth() {
+ int width = 0;
+ View view = viewRef.get();
+ if (view != null) {
+ final ViewGroup.LayoutParams params = view.getLayoutParams();
+
+ if (width <= 0 && params != null) width = params.width; // Get layout width parameter
+ }
+ if (width <= 0) {
+ ImageView imageView = (ImageView) viewRef.get();
+ if (imageView != null) {
+ width = getImageViewFieldValue(imageView, "mMaxWidth"); // Check maxWidth parameter
+ }
+ }
+ return width;
+ }
+
+ public int getHeight() {
+ int height = 0;
+ View view = viewRef.get();
+ if (view != null) {
+ final ViewGroup.LayoutParams params = view.getLayoutParams();
+ if (height <= 0 && params != null) height = params.height; // Get layout height parameter
+ return height;
+ }
+ if (height <= 0) {
+ ImageView imageView = (ImageView) viewRef.get();
+ if (imageView != null) {
+ height = getImageViewFieldValue(imageView, "mMaxHeight"); // Check maxHeight parameter
+ }
+ }
+ return height;
+ }
+
+ public boolean setImageDrawable(Drawable drawable) {
+ if (Looper.myLooper() == Looper.getMainLooper()) {
+ View view = viewRef.get();
+ if (view != null) {
+ ((ImageView) view).setImageDrawable(drawable);
+ if (drawable instanceof AnimationDrawable) {
+ ((AnimationDrawable)drawable).start();
+ }
+ return true;
+ }
+ } else {
+ Log.w(TAG, "Can't set a bitmap into view. You should call ImageLoader on UI thread for it.");
+ }
+ return false;
+ }
+
+ public int getId() {
+ View view = viewRef.get();
+ return view == null ? super.hashCode() : view.hashCode();
+ }
+
+ private static int getImageViewFieldValue(Object object, String fieldName) {
+ int value = 0;
+ try {
+ Field field = ImageView.class.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ int fieldValue = (Integer) field.get(object);
+ if (fieldValue > 0 && fieldValue < Integer.MAX_VALUE) {
+ value = fieldValue;
+ }
+ } catch (Exception e) {
+ Log.e(TAG, e.toString());
+ }
+ return value;
+ }
+
+ public ViewScaleType getScaleType() {
+ ImageView imageView = (ImageView) viewRef.get();
+ if (imageView != null) {
+ return ViewScaleType.fromImageView(imageView);
+ }
+ return ViewScaleType.CROP;
+ }
+
+ public boolean setImageBitmap(Bitmap bitmap) {
+ if (Looper.myLooper() == Looper.getMainLooper()) {
+ View view = viewRef.get();
+ if (view != null) {
+ ((ImageView) view).setImageBitmap(bitmap);
+ return true;
+ }
+ } else {
+ Log.w(TAG, "Can't set a bitmap into view. You should call ImageLoader on UI thread for it.");
+ }
+ return false;
+ }
+
+ public boolean isRecyled() {
+ return viewRef.get() == null;
+ }
+}
+
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ThreadFactoryImpl.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ThreadFactoryImpl.java
new file mode 100644
index 000000000..fe3f582f7
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ThreadFactoryImpl.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import java.util.concurrent.ThreadFactory;
+
+class ThreadFactoryImpl implements ThreadFactory {
+
+ private final ThreadGroup group;
+ private final int threadPriority;
+
+ ThreadFactoryImpl(int threadPriority) {
+ this.threadPriority = threadPriority;
+ group = Thread.currentThread().getThreadGroup();
+ }
+
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread t = new Thread(group, r);
+ if (t.isDaemon()) t.setDaemon(false);
+ t.setPriority(threadPriority);
+ return t;
+ }
+} \ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ViewScaleType.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ViewScaleType.java
new file mode 100644
index 000000000..2984693a1
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ViewScaleType.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import android.widget.ImageView;
+
+
+public enum ViewScaleType {
+ FIT_INSIDE,
+ CROP;
+
+ public static ViewScaleType fromImageView(ImageView imageView) {
+ switch (imageView.getScaleType()) {
+ case FIT_CENTER:
+ case FIT_XY:
+ case FIT_START:
+ case FIT_END:
+ case CENTER_INSIDE:
+ return FIT_INSIDE;
+ case MATRIX:
+ case CENTER:
+ case CENTER_CROP:
+ default:
+ return CROP;
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java b/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
index 0b84f5203..b56fdba3c 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
@@ -129,6 +129,7 @@ public class FilterEnvironment {
ImageFilter filter = mFiltersManager.getFilterForRepresentation(representation);
if (filter == null){
Log.e(LOGTAG,"No ImageFilter for "+representation.getSerializationName());
+ return bitmap;
}
filter.useRepresentation(representation);
filter.setEnvironment(this);
diff --git a/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java b/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
index 445407df9..96e7faa11 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
@@ -32,6 +32,7 @@ import android.util.Log;
import org.codeaurora.gallery.R;
import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.data.FilterPresetDBHelper;
import com.android.gallery3d.filtershow.filters.BaseFiltersManager;
import com.android.gallery3d.filtershow.filters.FilterCropRepresentation;
import com.android.gallery3d.filtershow.filters.FilterDualCamFusionRepresentation;
@@ -39,6 +40,7 @@ import com.android.gallery3d.filtershow.filters.FilterDualCamSketchRepresentatio
import com.android.gallery3d.filtershow.filters.FilterFxRepresentation;
import com.android.gallery3d.filtershow.filters.FilterImageBorderRepresentation;
import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterPresetRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation;
import com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation;
@@ -50,6 +52,7 @@ import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
import com.android.gallery3d.filtershow.imageshow.MasterImage;
import com.android.gallery3d.filtershow.state.State;
import com.android.gallery3d.filtershow.state.StateAdapter;
+import com.android.gallery3d.filtershow.tools.FilterGeneratorNativeEngine;
public class ImagePreset {
@@ -413,7 +416,8 @@ public class ImagePreset {
boolean replaced = false;
for (int i = 0; i < mFilters.size(); i++) {
FilterRepresentation current = mFilters.elementAt(i);
- if (current.getFilterType() == FilterRepresentation.TYPE_FX) {
+ if (current.getFilterType() == FilterRepresentation.TYPE_FX
+ || (current.getFilterType() == FilterRepresentation.TYPE_PRESETFILTER)) {
mFilters.remove(i);
replaced = true;
if (!isNoneFxFilter(representation)) {
@@ -425,6 +429,23 @@ public class ImagePreset {
if (!replaced && !isNoneFxFilter(representation)) {
mFilters.add(representation);
}
+ } else if (representation.getFilterType() == FilterRepresentation.TYPE_PRESETFILTER) {
+ boolean replaced = false;
+ for (int i = 0; i < mFilters.size(); i++) {
+ FilterRepresentation current = mFilters.elementAt(i);
+ if ((current.getFilterType() == FilterRepresentation.TYPE_PRESETFILTER)
+ || (current.getFilterType() == FilterRepresentation.TYPE_FX)) {
+ mFilters.remove(i);
+ replaced = true;
+ if (!isNonePresetFilter(representation)) {
+ mFilters.add(i, representation);
+ }
+ break;
+ }
+ }
+ if (!replaced && !isNonePresetFilter(representation)) {
+ mFilters.add(representation);
+ }
} else {
mFilters.add(representation);
}
@@ -495,6 +516,11 @@ public class ImagePreset {
representation.getFilterType() == FilterRepresentation.TYPE_TRUEPORTRAIT;
}
+ private boolean isNonePresetFilter(FilterRepresentation representation) {
+ return representation instanceof FilterPresetRepresentation &&
+ ((FilterPresetRepresentation) representation).getTextId() == R.string.none;
+ }
+
public FilterRepresentation getRepresentation(FilterRepresentation filterRepresentation) {
for (int i = 0; i < mFilters.size(); i++) {
FilterRepresentation representation = mFilters.elementAt(i);
diff --git a/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java b/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java
index 3948b6eea..2bff90b24 100755
--- a/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java
@@ -308,6 +308,13 @@ public class ProcessingService extends Service {
filtersManager.addHazeBuster();
filtersManager.addSeeStraight();
filtersManager.addTruePortrait(this);
+ filtersManager.addFilterPreset(this);
+ filtersManager.addWaterMarks(this);
+ filtersManager.addLocations(this);
+ filtersManager.addTimes(this);
+ filtersManager.addWeather(this);
+ filtersManager.addEmotions(this);
+ filtersManager.addFoods(this);
FiltersManager highresFiltersManager = FiltersManager.getHighresManager();
highresFiltersManager.addLooks(this);
@@ -320,6 +327,13 @@ public class ProcessingService extends Service {
highresFiltersManager.addHazeBuster();
highresFiltersManager.addSeeStraight();
highresFiltersManager.addTruePortrait(this);
+ highresFiltersManager.addFilterPreset(this);
+ highresFiltersManager.addWaterMarks(this);
+ highresFiltersManager.addLocations(this);
+ highresFiltersManager.addTimes(this);
+ highresFiltersManager.addWeather(this);
+ highresFiltersManager.addEmotions(this);
+ highresFiltersManager.addFoods(this);
}
private void tearDownPipeline() {
diff --git a/src/com/android/gallery3d/filtershow/presets/PresetManagementDialog.java b/src/com/android/gallery3d/filtershow/presets/PresetManagementDialog.java
index 4d7fdafb4..6841fe8c2 100644
--- a/src/com/android/gallery3d/filtershow/presets/PresetManagementDialog.java
+++ b/src/com/android/gallery3d/filtershow/presets/PresetManagementDialog.java
@@ -16,50 +16,71 @@
package com.android.gallery3d.filtershow.presets;
+import android.app.AlertDialog;
+import android.app.Dialog;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
+import android.transition.ChangeClipBounds;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import org.codeaurora.gallery.R;
import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.util.GalleryUtils;
+
+//import static com.android.gallery3d.filtershow.FilterShowActivity.SELECT_FILTER;
public class PresetManagementDialog extends DialogFragment implements View.OnClickListener {
private UserPresetsAdapter mAdapter;
private EditText mEditText;
+ private CheckBox mCheckBox;
+ private boolean checked;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.filtershow_presets_management_dialog, container);
-
+ View view = inflater.inflate(R.layout.filtershow_presets_dialog, container);
FilterShowActivity activity = (FilterShowActivity) getActivity();
mAdapter = activity.getUserPresetsAdapter();
- mEditText = (EditText) view.findViewById(R.id.editView);
+ mCheckBox = (CheckBox) view.findViewById(R.id.filtershow_check_box);
view.findViewById(R.id.cancel).setOnClickListener(this);
view.findViewById(R.id.ok).setOnClickListener(this);
- getDialog().setTitle(getString(R.string.filtershow_save_preset));
+ view.findViewById(R.id.filtershow_check_box).setOnClickListener(this);
return view;
}
@Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ Dialog dialog = super.onCreateDialog(savedInstanceState);
+ dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ return dialog;
+ }
+
+
+ @Override
public void onClick(View v) {
FilterShowActivity activity = (FilterShowActivity) getActivity();
switch (v.getId()) {
case R.id.cancel:
- mAdapter.clearChangedRepresentations();
- mAdapter.clearDeletedRepresentations();
- activity.updateUserPresetsFromAdapter(mAdapter);
+// mAdapter.clearChangedRepresentations();
+// mAdapter.clearDeletedRepresentations();
+// activity.updateUserPresetsFromAdapter(mAdapter);
+
dismiss();
break;
case R.id.ok:
- String text = String.valueOf(mEditText.getText());
- activity.saveCurrentImagePreset(text);
- mAdapter.updateCurrent();
- activity.updateUserPresetsFromAdapter(mAdapter);
+ // String text = String.valueOf(mEditText.getText());
+ // activity.saveCurrentImagePreset(text);
+ checked = mCheckBox.isChecked();
+ GalleryUtils.setBooleanPref(activity,activity.getString(R.string.pref_filtergenerator_intro_show_key),checked);
+ activity.onMediaPickerStarted ();
+ // mAdapter.updateCurrent();
+ // activity.updateUserPresetsFromAdapter(mAdapter);
dismiss();
break;
}
diff --git a/src/com/android/gallery3d/filtershow/tools/DualCameraNativeEngine.java b/src/com/android/gallery3d/filtershow/tools/DualCameraNativeEngine.java
index f44f4d6d1..8b58bc890 100644
--- a/src/com/android/gallery3d/filtershow/tools/DualCameraNativeEngine.java
+++ b/src/com/android/gallery3d/filtershow/tools/DualCameraNativeEngine.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -38,6 +38,9 @@ import android.util.Log;
public class DualCameraNativeEngine {
private static final String TAG = "DualCameraNativeEngine";
+
+ public static final float DEFAULT_BRIGHTNESS_INTENSITY = 1.0f;
+
static {
try {
System.loadLibrary("jni_dualcamera");
@@ -56,7 +59,7 @@ public class DualCameraNativeEngine {
DDM_LOADING,
DDM_LOADED,
DDM_FAILED
- };
+ }
public static final String DEPTH_MAP_EXT = "dm";
private static final String CALIBRATION_FILENAME = "ddm_calib_file.dat";
@@ -64,10 +67,11 @@ public class DualCameraNativeEngine {
private static DualCameraNativeEngine mInstance;
- private DualCameraNativeEngine() {}
+ private DualCameraNativeEngine() {
+ }
public static void createInstance() {
- if(mInstance == null) {
+ if (mInstance == null) {
mInstance = new DualCameraNativeEngine();
}
}
@@ -86,7 +90,7 @@ public class DualCameraNativeEngine {
return calibFile.getAbsolutePath();
}
- native public boolean initDepthMap(Bitmap primaryRGBA, Bitmap auxiliaryRGBA, String mpoFilepath, String calibFilepath);
+ native public boolean initDepthMap(Bitmap primaryRGBA, Bitmap auxiliaryRGBA, String mpoFilepath, String calibFilepath, float brIntensity);
native public void releaseDepthMap();
@@ -94,11 +98,59 @@ public class DualCameraNativeEngine {
native public boolean getDepthMap(Bitmap dataBuffer);
+ native private boolean get3DEffectImages(Bitmap bitmap, Bitmap depthMap);
+
native public boolean applyFocus(int focusPointX, int focusPointY, float intensity, int[] roiRect, boolean isPreview, Bitmap outBm);
+ native public boolean applyFocusStar(int focusPointX, int focusPointY, float intensity, int[] roiRect, boolean isPreview, Bitmap outBm);
+
+ native public boolean applyFocusHexagon(int focusPointX, int focusPointY, float intensity, int[] roiRect, boolean isPreview, Bitmap outBm);
+
native public boolean applyHalo(int focusPointX, int focusPointY, float intensity, int[] roiRect, boolean isPreview, Bitmap outBm);
+ native public boolean applyMotion(int focusPointX, int focusPointY, float intensity, int[] roiRect, boolean isPreview, Bitmap outBm);
+
native public boolean applySketch(int focusPointX, int focusPointY, int[] roiRect, boolean isPreview, Bitmap outBm);
+ native public boolean applyZoom(int focusPointX, int focusPointY, int[] roiRect, boolean isPreview, Bitmap outBm);
+
+ native public boolean applyBlackAndWhite(int focusPointX, int focusPointY, int[] roiRect, boolean isPreview, Bitmap outBm);
+
+ native public boolean applyBlackBoard(int focusPointX, int focusPointY, int[] roiRect, boolean isPreview, Bitmap outBm);
+
+ native public boolean applyWhiteBoard(int focusPointX, int focusPointY, int[] roiRect, boolean isPreview, Bitmap outBm);
+
+ native public boolean applyPosterize(int focusPointX, int focusPointY, float intensity, int[] roiRect, boolean isPreview, Bitmap outBm);
+
+ native public boolean applyNegative(int focusPointX, int focusPointY, int[] roiRect, boolean isPreview, Bitmap outBm);
+
native public boolean getForegroundImg(int focusPointX, int focusPointY, int[] roiRect, boolean isPreview, Bitmap outBm);
+
+ native public boolean getPrimaryImg(int focusPointX, int focusPointY, int[] roiRect, boolean isPreview, Bitmap outBm);
+
+ public static class DepthMap3D {
+ public char[] pixels;
+ public int width;
+ public int height;
+ }
+
+ public DepthMap3D getDepthMap3D(Bitmap bitmap) {
+ int width = bitmap.getWidth(), height = bitmap.getHeight();
+ Bitmap depthMap = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
+ boolean ok = get3DEffectImages(bitmap, depthMap);
+ if (!ok) return null;
+
+ DepthMap3D map = new DepthMap3D();
+ map.width = width;
+ map.height = height;
+ map.pixels = new char[width * height];
+
+ int[] pixels = new int[width * height];
+ depthMap.getPixels(pixels, 0, width, 0, 0, width, height);
+ for (int i = width * height - 1; i >= 0; --i) {
+ map.pixels[i] = (char) (pixels[i] & 0xff);
+ }
+ depthMap.recycle();
+ return map;
+ }
}
diff --git a/src/com/android/gallery3d/filtershow/tools/FilterGeneratorNativeEngine.java b/src/com/android/gallery3d/filtershow/tools/FilterGeneratorNativeEngine.java
new file mode 100644
index 000000000..f95688d0d
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/tools/FilterGeneratorNativeEngine.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. 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.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+package com.android.gallery3d.filtershow.tools;
+
+import java.io.File;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Point;
+import android.util.Log;
+
+public class FilterGeneratorNativeEngine {
+ private static final String TAG = "FilterGeneratorNativeEngine";
+ static {
+ try {
+ System.loadLibrary("jni_filtergenerator");
+ mLibLoaded = true;
+ Log.v(TAG, "successfully loaded filter generator lib");
+ } catch (UnsatisfiedLinkError e) {
+ Log.e(TAG, "failed to load filter generator lib");
+ mLibLoaded = false;
+ }
+ }
+
+ private static boolean mLibLoaded;
+
+ private static FilterGeneratorNativeEngine mInstance;
+
+ private FilterGeneratorNativeEngine() {}
+
+ public static void createInstance() {
+ if(mInstance == null) {
+ mInstance = new FilterGeneratorNativeEngine();
+ }
+ }
+
+ public static FilterGeneratorNativeEngine getInstance() {
+ createInstance();
+ return mInstance;
+ }
+
+ public boolean isLibLoaded() {
+ return mLibLoaded;
+ }
+
+ native public boolean filterGeneratorProcess (Bitmap srcRGBA, Bitmap refRGBA, Bitmap dstRGBA);
+
+}
diff --git a/src/com/android/gallery3d/filtershow/tools/SaveImage.java b/src/com/android/gallery3d/filtershow/tools/SaveImage.java
index 073aca4cd..859fdca78 100644
--- a/src/com/android/gallery3d/filtershow/tools/SaveImage.java
+++ b/src/com/android/gallery3d/filtershow/tools/SaveImage.java
@@ -272,7 +272,7 @@ public class SaveImage {
return exif;
}
- public boolean putExifData(File file, ExifInterface exif, Bitmap image,
+ public static boolean putExifData(File file, ExifInterface exif, Bitmap image,
int jpegCompressQuality) {
boolean ret = false;
OutputStream s = null;
@@ -366,7 +366,7 @@ public class SaveImage {
FilterFusionRepresentation fusionRep = findFusionRepresentation(preset);
boolean hasFusion = (fusionRep != null && fusionRep.hasUnderlay());
if(hasFusion) {
- previewBmp = flattenFusion(Uri.parse(fusionRep.getUnderlay()), mPreviewImage,
+ previewBmp = flattenFusion(mContext, Uri.parse(fusionRep.getUnderlay()), mPreviewImage,
Math.max(mPreviewImage.getWidth(), mPreviewImage.getHeight()), 0);
// If we fail to flatten, save original image
if(previewBmp == null) {
@@ -450,7 +450,7 @@ public class SaveImage {
FilterFusionRepresentation fusionRep = findFusionRepresentation(preset);
boolean hasFusion = (fusionRep != null && fusionRep.hasUnderlay());
if(hasFusion) {
- Bitmap underlay = flattenFusion(
+ Bitmap underlay = flattenFusion(mContext,
Uri.parse(fusionRep.getUnderlay()), bitmap, 0, sampleSize);
if(underlay != null) {
bitmap.recycle();
@@ -814,19 +814,23 @@ public class SaveImage {
return fusionRep;
}
- private Bitmap flattenFusion(Uri underlayUri, Bitmap bitmap, int sizeConstraint, int sampleSize) {
+ public static Bitmap flattenFusion(Context context, Uri underlayUri, Bitmap bitmap, int sizeConstraint, int sampleSize) {
// fusion. decode underlay image and get dest rect
Bitmap underlay = null;
if(sizeConstraint != 0) {
- underlay = ImageLoader.loadConstrainedBitmap(underlayUri, mContext,
+ underlay = ImageLoader.loadConstrainedBitmap(underlayUri, context,
sizeConstraint, null, false);
} else if (sampleSize != 0) {
- underlay = ImageLoader.loadBitmapWithBackouts(mContext, underlayUri, sampleSize);
+ underlay = ImageLoader.loadBitmapWithBackouts(context, underlayUri, sampleSize);
}
if(underlay != null) {
+ int ori = ImageLoader.getMetadataOrientation(context, underlayUri);
+ if (ori != ImageLoader.ORI_NORMAL) {
+ underlay = ImageLoader.orientBitmap(underlay, ori);
+ }
RectF destRect = new RectF();
Rect imageBounds = MasterImage.getImage().getImageBounds();
Rect underlayBounds = MasterImage.getImage().getFusionBounds();
diff --git a/src/com/android/gallery3d/filtershow/ui/DoNotShowAgainDialog.java b/src/com/android/gallery3d/filtershow/ui/DoNotShowAgainDialog.java
index e9245d540..90895fd68 100644
--- a/src/com/android/gallery3d/filtershow/ui/DoNotShowAgainDialog.java
+++ b/src/com/android/gallery3d/filtershow/ui/DoNotShowAgainDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -49,6 +49,8 @@ public class DoNotShowAgainDialog extends DialogFragment {
private int mMessageId;
private CheckBox mDoNotShowAgainChk;
private DialogInterface.OnClickListener mButtonClickListener;
+ private DialogInterface.OnDismissListener mDialogDismissListener;
+ private DialogInterface.OnCancelListener mCancelListener;
public DoNotShowAgainDialog(int titleId, int msgId, int sharedPrefKeyId) {
mTitleId = titleId;
@@ -83,4 +85,34 @@ public class DoNotShowAgainDialog extends DialogFragment {
public void setOnOkButtonClickListener(DialogInterface.OnClickListener listener) {
mButtonClickListener = listener;
}
+
+ public void setOnDismissListener (DialogInterface.OnDismissListener listener) {
+ mDialogDismissListener = listener;
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ super.onDismiss(dialog);
+ if (mDialogDismissListener != null) {
+ mDialogDismissListener.onDismiss(dialog);
+ }
+ }
+
+ public void setOnCancelListener(DialogInterface.OnCancelListener listener) {
+ mCancelListener = listener;
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ super.onCancel(dialog);
+ if (mCancelListener != null) {
+ mCancelListener.onCancel(dialog);
+ }
+ }
+
+ @Override
+ public void onPause() {
+ this.dismiss();
+ super.onPause();
+ }
}
diff --git a/src/com/android/gallery3d/filtershow/ui/ExportDialog.java b/src/com/android/gallery3d/filtershow/ui/ExportDialog.java
index 6ec3cfed5..f73f3c076 100644
--- a/src/com/android/gallery3d/filtershow/ui/ExportDialog.java
+++ b/src/com/android/gallery3d/filtershow/ui/ExportDialog.java
@@ -105,11 +105,18 @@ public class ExportDialog extends DialogFragment implements SeekBar.OnSeekBarCha
Uri sourceUri = MasterImage.getImage().getUri();
File dest = SaveImage.getNewFile(activity, activity.getSelectedImageUri());
float scaleFactor = mExportWidth / (float) mOriginalBounds.width();
- Intent processIntent = ProcessingService.getSaveIntent(activity,
- MasterImage.getImage().getPreset(), dest,
- activity.getSelectedImageUri(), sourceUri, true,
- mSeekBar.getProgress(), scaleFactor, false, -1);
- activity.startService(processIntent);
+ if (!activity.isWaterMarked()) {
+ Intent processIntent = ProcessingService.getSaveIntent(activity,
+ MasterImage.getImage().getPreset(), dest,
+ activity.getSelectedImageUri(), sourceUri, true,
+ mSeekBar.getProgress(), scaleFactor, false, -1);
+ activity.startService(processIntent);
+ } else {
+ activity.getSaveWaterMark().saveImage(activity,
+ MasterImage.getImage().getHighresImage(),
+ activity.getSelectedImageUri(), null, mSeekBar.getProgress(),
+ scaleFactor, true);
+ }
}
});
builder.setNegativeButton(R.string.cancel, null);
diff --git a/src/com/android/gallery3d/gadget/WidgetService.java b/src/com/android/gallery3d/gadget/WidgetService.java
index dd05b6732..c139affa0 100644
--- a/src/com/android/gallery3d/gadget/WidgetService.java
+++ b/src/com/android/gallery3d/gadget/WidgetService.java
@@ -118,7 +118,12 @@ public class WidgetService extends RemoteViewsService {
@Override
public RemoteViews getViewAt(int position) {
- Bitmap bitmap = mSource.getImage(position);
+ Bitmap bitmap = null;
+ try {
+ bitmap = mSource.getImage(position);
+ } catch (UnsupportedOperationException e){
+ // catch exception here to avoid FC
+ }
boolean isDrm = false;
// if (DrmHelper.isDrmFile(DrmHelper.getFilePath(
diff --git a/src/com/android/gallery3d/mpo/MpoParser.java b/src/com/android/gallery3d/mpo/MpoParser.java
index b872db640..5e652b742 100644
--- a/src/com/android/gallery3d/mpo/MpoParser.java
+++ b/src/com/android/gallery3d/mpo/MpoParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -304,6 +304,75 @@ public class MpoParser {
return depthMap;
}
+ public byte[] readImgData(int index) {
+ if (mMpEntries.isEmpty()) return null;
+ MpEntry mpEntry = mMpEntries.get(index);
+ if (mpEntry == null) return null;
+
+ InputStream is = null;
+ ByteArrayOutputStream os = null;
+ byte[] data = null;
+ try {
+ is = mContentResolver.openInputStream(mUri);
+ data = new byte[mpEntry.mImgSize];
+
+ is.skip((mpEntry.mImgDataOffset > 0) ? mpEntry.mImgDataOffset + mMpHeaderOffset :
+ mpEntry.mImgDataOffset);
+ if (is.read(data) == -1) {
+ Log.d(LOGTAG, "read EOF. invalid offset/size");
+ data = null;
+ } else {
+ // verify we have well formed jpeg data
+ ByteBuffer buffer = ByteBuffer.wrap(data);
+ if (buffer.getShort(0) != MpoHeader.SOI) {
+ Log.d(LOGTAG, "non valid SOI. offset incorrect.");
+ data = null;
+ } else if (buffer.getShort(buffer.limit() - 2) != MpoHeader.EOI) {
+ Log.d(LOGTAG, "non valid EOI. size incorrect. attempting to read further till " +
+ "EOI");
+ os = new ByteArrayOutputStream(data.length);
+ os.write(data);
+
+ byte[] readArray = new byte[2];
+ ByteBuffer readBuf = ByteBuffer.wrap(readArray);
+
+ readArray[0] = data[data.length - 2];
+ readArray[1] = data[data.length - 1];
+
+ data = null;
+
+ boolean validJpg = true;
+ while (readBuf.getShort(0) != MpoHeader.EOI) {
+ int read = is.read();
+ if (read == -1) {
+ Log.d(LOGTAG, "reached EOF before EOI. invalid file");
+ validJpg = false;
+ break;
+ }
+ readArray[0] = readArray[1];
+ readArray[1] = (byte) (read & 0xFF);
+
+ os.write(read);
+ }
+
+ if (validJpg)
+ data = os.toByteArray();
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ Utils.closeSilently(is);
+ Utils.closeSilently(os);
+ }
+
+ return data;
+ }
+
+ public boolean isPrimaryForDisplay() {
+ return mMpEntries.size() == 2;
+ }
+
class MpEntry {
int mImgAttribute;
int mImgSize;
diff --git a/src/com/android/gallery3d/ui/ActionModeHandler.java b/src/com/android/gallery3d/ui/ActionModeHandler.java
index 0b367d7dc..30489f9e2 100644
--- a/src/com/android/gallery3d/ui/ActionModeHandler.java
+++ b/src/com/android/gallery3d/ui/ActionModeHandler.java
@@ -197,6 +197,7 @@ public class ActionModeHandler implements Callback, PopupList.OnPopupItemClickLi
} else if (action == R.id.action_share) {
String shareTitle = mActivity.getResources().
getString(R.string.share_dialogue_title);
+ mActivity.isTopMenuShow = true;
mActivity.startActivity(Intent.createChooser(
shareIntent, shareTitle));
return true;
diff --git a/src/com/android/gallery3d/ui/MenuExecutor.java b/src/com/android/gallery3d/ui/MenuExecutor.java
index 8f3409131..673ba6609 100644
--- a/src/com/android/gallery3d/ui/MenuExecutor.java
+++ b/src/com/android/gallery3d/ui/MenuExecutor.java
@@ -295,6 +295,7 @@ public class MenuExecutor {
// }
Activity activity = mActivity;
+ mActivity.isTopMenuShow = true;
activity.startActivity(Intent.createChooser(
intent, activity.getString(R.string.set_as)));
}
diff --git a/src/com/android/gallery3d/ui/TileImageView.java b/src/com/android/gallery3d/ui/TileImageView.java
index 05bc9aff5..f07353ed2 100644
--- a/src/com/android/gallery3d/ui/TileImageView.java
+++ b/src/com/android/gallery3d/ui/TileImageView.java
@@ -470,6 +470,10 @@ public class TileImageView extends GLView {
}
void queueForUpload(Tile tile) {
+ // if getGLRoot retun null, then maybe no place to show
+ // these decode tiles.
+ if (getGLRoot() == null)
+ return;
synchronized (this) {
mUploadQueue.push(tile);
}
diff --git a/src/org/codeaurora/gallery3d/video/SettingsActivity.java b/src/org/codeaurora/gallery3d/video/SettingsActivity.java
index f2b1bebac..6372d49b4 100644
--- a/src/org/codeaurora/gallery3d/video/SettingsActivity.java
+++ b/src/org/codeaurora/gallery3d/video/SettingsActivity.java
@@ -112,7 +112,13 @@ public class SettingsActivity extends AbstractPermissionPreferenceActivity {
private void init() {
mSubscriptionManager = SubscriptionManager.from(this);
- mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
+ try{
+ mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
+ }catch (Exception e) {
+ Log.e(TAG,e.toString());
+ mSubscriptionManager = null;
+ return;
+ }
// Initialize mActiveSubInfo
int max = mSubscriptionManager.getActiveSubscriptionInfoCountMax();
mActiveSubInfos = new ArrayList<SubscriptionInfo>(max);
diff --git a/src/org/codeaurora/gallery3d/video/SpeakerHooker.java b/src/org/codeaurora/gallery3d/video/SpeakerHooker.java
index e21452f90..912de96a5 100644
--- a/src/org/codeaurora/gallery3d/video/SpeakerHooker.java
+++ b/src/org/codeaurora/gallery3d/video/SpeakerHooker.java
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2014, The Linux Foundation. All rights reserved.
+Copyright (c) 2014,2017 The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -111,9 +111,11 @@ public class SpeakerHooker extends MovieHooker {
|| mAudioManager.isBluetoothA2dpOn();
} else if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)
|| action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
- final int deviceClass = ((BluetoothDevice)
+ final BluetoothClass bc = ((BluetoothDevice)
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))
- .getBluetoothClass().getDeviceClass();
+ .getBluetoothClass();
+ if (bc == null) return;
+ final int deviceClass = bc.getDeviceClass();
if ((deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES)
|| (deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET)) {
mIsHeadsetOn = action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)
diff --git a/src/org/codeaurora/gallery3d/video/VideoSnapshotExt.java b/src/org/codeaurora/gallery3d/video/VideoSnapshotExt.java
index c6bcc6a3f..135e33a7b 100644
--- a/src/org/codeaurora/gallery3d/video/VideoSnapshotExt.java
+++ b/src/org/codeaurora/gallery3d/video/VideoSnapshotExt.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016,2017 The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -40,6 +40,8 @@ import android.os.Environment;
import android.provider.MediaStore.Images;
import android.provider.MediaStore.Images.ImageColumns;
import android.util.Log;
+import android.webkit.URLUtil;
+
import org.codeaurora.gallery.R;
import com.android.gallery3d.app.MovieControllerOverlay;
import com.android.gallery3d.app.MovieControllerOverlayNew;
@@ -146,6 +148,9 @@ public class VideoSnapshotExt implements IVideoSnapshotListener {
private Bitmap doVideoSnap(Uri videoUri, int snapPosition) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+ if (videoUri == null || !URLUtil.isValidUrl(videoUri.toString())) {
+ return null;
+ }
retriever.setDataSource(mContext, videoUri);
String durationString =
retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);