From aeb49f4bb6f3ea375e937a6ac1104cb372f26eb2 Mon Sep 17 00:00:00 2001 From: seven332 Date: Thu, 8 Oct 2015 12:22:48 +0800 Subject: [PATCH] Use Vector --- .idea/compiler.xml | 45 +- .idea/encodings.xml | 10 +- .idea/gradle.xml | 35 +- .idea/inspectionProfiles/Project_Default.xml | 15 - .../inspectionProfiles/profiles_settings.xml | 7 - .idea/misc.xml | 77 ++- .idea/modules.xml | 20 +- .idea/runConfigurations.xml | 12 + .idea/scopes/scope_settings.xml | 5 - .idea/vcs.xml | 13 +- app/app.iml | 193 +++--- app/build.gradle | 18 +- .../android/content/res/VectorResources.java | 220 ------- .../java/com/hippo/ehviewer/AppContext.java | 6 - .../com/hippo/ehviewer/StartActivity.java | 3 +- .../com/hippo/ehviewer/ehclient/EhInfo.java | 3 +- .../ehviewer/service/DownloadService.java | 6 - .../com/hippo/ehviewer/ui/AbsActivity.java | 7 - .../ehviewer/ui/AbsPreferenceActivity.java | 7 - .../vectorold/animation/AnimatorInflater.java | 612 ------------------ .../animation/InterpolatorInflater.java | 125 ---- .../vectorold/animation/PathInterpolator.java | 219 ------- .../vectorold/content/VectorContext.java | 52 -- .../drawable/AnimatedVectorDrawable.java | 430 ------------ app/src/main/res/values/vectorold_attrs.xml | 240 ------- build.gradle | 2 +- settings.gradle | 2 +- vector/.gitignore | 1 + vector/build.gradle | 24 + vector/proguard-rules.pro | 17 + .../com/hippo/vector/ApplicationTest.java | 13 + vector/src/main/AndroidManifest.xml | 7 + .../java/com/hippo/vector}/PathParser.java | 100 ++- .../src/main/java/com/hippo/vector/Utils.java | 15 +- .../com/hippo/vector}/VectorDrawable.java | 358 +++++++--- vector/src/main/res/values/attrs.xml | 138 ++++ .../com/hippo/vector/ExampleUnitTest.java | 15 + vector/vector.iml | 95 +++ 38 files changed, 876 insertions(+), 2291 deletions(-) delete mode 100644 .idea/inspectionProfiles/Project_Default.xml delete mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/runConfigurations.xml delete mode 100644 .idea/scopes/scope_settings.xml delete mode 100644 app/src/main/java/android/content/res/VectorResources.java delete mode 100644 app/src/main/java/com/hippo/vectorold/animation/AnimatorInflater.java delete mode 100644 app/src/main/java/com/hippo/vectorold/animation/InterpolatorInflater.java delete mode 100644 app/src/main/java/com/hippo/vectorold/animation/PathInterpolator.java delete mode 100644 app/src/main/java/com/hippo/vectorold/content/VectorContext.java delete mode 100644 app/src/main/java/com/hippo/vectorold/drawable/AnimatedVectorDrawable.java delete mode 100644 app/src/main/res/values/vectorold_attrs.xml create mode 100644 vector/.gitignore create mode 100644 vector/build.gradle create mode 100644 vector/proguard-rules.pro create mode 100644 vector/src/androidTest/java/com/hippo/vector/ApplicationTest.java create mode 100644 vector/src/main/AndroidManifest.xml rename {app/src/main/java/com/hippo/vectorold/util => vector/src/main/java/com/hippo/vector}/PathParser.java (88%) rename app/src/main/java/com/hippo/vectorold/util/DrawableUtils.java => vector/src/main/java/com/hippo/vector/Utils.java (82%) rename {app/src/main/java/com/hippo/vectorold/drawable => vector/src/main/java/com/hippo/vector}/VectorDrawable.java (85%) create mode 100644 vector/src/main/res/values/attrs.xml create mode 100644 vector/src/test/java/com/hippo/vector/ExampleUnitTest.java create mode 100644 vector/vector.iml diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 28bb10af0..96cc43efa 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,23 +1,22 @@ - - - - - - + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml index c9ed3522c..97626ba45 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 1aaf3e588..0a8519e17 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -1,18 +1,19 @@ - - - - - + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index a1e308618..000000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 6933c1eaf..000000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index e1d91222a..1a3eaffb4 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,33 +1,46 @@ - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 464db56d3..cbeb48a33 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -1,10 +1,10 @@ - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 000000000..7f68460d8 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/scopes/scope_settings.xml b/.idea/scopes/scope_settings.xml deleted file mode 100644 index 0d5175ca0..000000000 --- a/.idea/scopes/scope_settings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index ab55cf163..35eb1ddfb 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,7 +1,6 @@ - - - - - - - + + + + + + \ No newline at end of file diff --git a/app/app.iml b/app/app.iml index 3cf49f3c0..d9de0c0fb 100644 --- a/app/app.iml +++ b/app/app.iml @@ -1,97 +1,98 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 4806fc553..9b62d523b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,14 +4,14 @@ apply plugin: 'com.android.application' android { compileSdkVersion 22 - buildToolsVersion '23.0.0 rc2' + buildToolsVersion '22.0.1' defaultConfig { applicationId "com.hippo.ehviewer" minSdkVersion 14 targetSdkVersion 22 - versionCode 46 - versionName "0.6.16.2" + versionCode 47 + versionName "0.6.16.3" } buildTypes { debug { @@ -24,6 +24,13 @@ android { } } + lintOptions { + checkReleaseBuilds false + // Or, if you prefer, you can continue to check for errors in release builds, + // but continue the build even when errors are found: + abortOnError false + } + // Disable default NdkCompile task // Set new jni lib dir sourceSets.main { @@ -59,6 +66,7 @@ clean { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:support-v4:22.2.0' - compile 'com.android.support:recyclerview-v7:22.2.0' + compile project(':vector') + compile 'com.android.support:support-v4:22.2.1' + compile 'com.android.support:recyclerview-v7:22.2.1' } diff --git a/app/src/main/java/android/content/res/VectorResources.java b/app/src/main/java/android/content/res/VectorResources.java deleted file mode 100644 index 1e678395d..000000000 --- a/app/src/main/java/android/content/res/VectorResources.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (C) 2015 Hippo Seven - * - * 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 android.content.res; - -import android.content.Context; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.support.v4.util.LongSparseArray; -import android.util.AttributeSet; -import android.util.TypedValue; -import android.util.Xml; - -import com.hippo.vectorold.drawable.AnimatedVectorDrawable; -import com.hippo.vectorold.drawable.VectorDrawable; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.ref.WeakReference; - -// TODO Only load register drawable from itself -/** - * It is a wrap - */ -public class VectorResources extends Resources { - - private static final String TAG = VectorResources.class.getSimpleName(); - - private Context mContext; - private Resources mBase; - - // These are protected by mAccessLock. - - /*package*/ final Object mAccessLock = new Object(); - /*package*/ final LongSparseArray > mDrawableCache - = new LongSparseArray >(0); - /*package*/ final LongSparseArray > mColorDrawableCache - = new LongSparseArray >(0); - - public VectorResources(Context context, Resources res) { - super(res.getAssets(), res.getDisplayMetrics(), res.getConfiguration()); - mContext = context; - mBase = res; - } - - public boolean isBase(Resources res) { - return mBase == res; - } - - @Override - Drawable loadDrawable(TypedValue value, int id) - throws NotFoundException { - boolean isColorDrawable = false; - if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT && - value.type <= TypedValue.TYPE_LAST_COLOR_INT) { - isColorDrawable = true; - } - final long key = isColorDrawable ? value.data : - (((long) value.assetCookie) << 32) | value.data; - - Drawable dr = getCachedDrawable(isColorDrawable ? mColorDrawableCache : mDrawableCache, key); - - if (dr != null) { - return dr; - } - - if (isColorDrawable) { - dr = new ColorDrawable(value.data); - } - - if (dr == null) { - if (value.string == null) { - throw new NotFoundException( - "Resource is not a Drawable (color or path): " + value); - } - - String file = value.string.toString(); - - if (file.endsWith(".xml")) { - // Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file); - try { - XmlResourceParser rp = getXml(id); - // XmlResourceParser rp = loadXmlResourceParser( - // file, id, value.assetCookie, "drawable"); - dr = createDrawableFromXml(rp); - rp.close(); - } catch (Exception e) { - // Trace.traceEnd(Trace.TRACE_TAG_RESOURCES); - NotFoundException rnf = new NotFoundException( - "File " + file + " from drawable resource ID #0x" - + Integer.toHexString(id)); - rnf.initCause(e); - throw rnf; - } - // Trace.traceEnd(Trace.TRACE_TAG_RESOURCES); - - } else { - // Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file); - try { - InputStream is = openRawResource(id, value); - //InputStream is = mAssets.openNonAsset( - // value.assetCookie, file, AssetManager.ACCESS_STREAMING); - // System.out.println("Opened file " + file + ": " + is); - dr = Drawable.createFromResourceStream(this, value, is, - file, null); - is.close(); - // System.out.println("Created stream: " + dr); - } catch (Exception e) { - // Trace.traceEnd(Trace.TRACE_TAG_RESOURCES); - NotFoundException rnf = new NotFoundException( - "File " + file + " from drawable resource ID #0x" - + Integer.toHexString(id)); - rnf.initCause(e); - throw rnf; - } - // Trace.traceEnd(Trace.TRACE_TAG_RESOURCES); - } - } - Drawable.ConstantState cs; - if (dr != null) { - dr.setChangingConfigurations(value.changingConfigurations); - cs = dr.getConstantState(); - if (cs != null) { - synchronized (mAccessLock) { - //Log.i(TAG, "Saving cached drawable @ #" + - // Integer.toHexString(key.intValue()) - // + " in " + this + ": " + cs); - if (isColorDrawable) { - mColorDrawableCache.put(key, new WeakReference(cs)); - } else { - mDrawableCache.put(key, new WeakReference(cs)); - } - } - } - } - - return dr; - } - - private Drawable getCachedDrawable( - LongSparseArray> drawableCache, - long key) { - synchronized (mAccessLock) { - WeakReference wr = drawableCache.get(key); - if (wr != null) { // we have the key - Drawable.ConstantState entry = wr.get(); - if (entry != null) { - //Log.i(TAG, "Returning cached drawable @ #" + - // Integer.toHexString(((Integer)key).intValue()) - // + " in " + this + ": " + entry); - return entry.newDrawable(this); - } - else { // our entry has been purged - drawableCache.delete(key); - } - } - } - return null; - } - - private Drawable createDrawableFromXml(XmlResourceParser parser) - throws XmlPullParserException, IOException { - AttributeSet attrs = Xml.asAttributeSet(parser); - - int type; - while ((type=parser.next()) != XmlPullParser.START_TAG && - type != XmlPullParser.END_DOCUMENT) { - // Empty loop - } - - if (type != XmlPullParser.START_TAG) { - throw new XmlPullParserException("No start tag found"); - } - - Drawable drawable = createDrawableFromXmlInner(parser, attrs); - - if (drawable == null) { - throw new RuntimeException("Unknown initial tag: " + parser.getName()); - } - - return drawable; - } - - private Drawable createDrawableFromXmlInner(XmlPullParser parser, AttributeSet attrs) - throws XmlPullParserException, IOException { - final Drawable drawable; - final String name = parser.getName(); - switch (name) { - case "vector": - VectorDrawable vectorDrawable = new VectorDrawable(); - vectorDrawable.inflate(this, parser, attrs); - drawable = vectorDrawable; - break; - case "animated-vector": - AnimatedVectorDrawable animatedVectorDrawable = new AnimatedVectorDrawable(); - animatedVectorDrawable.inflate(mContext, parser, attrs); - drawable = animatedVectorDrawable; - break; - default: - drawable = Drawable.createFromXmlInner(this, parser, attrs); - } - return drawable; - } -} diff --git a/app/src/main/java/com/hippo/ehviewer/AppContext.java b/app/src/main/java/com/hippo/ehviewer/AppContext.java index a71c422e6..0a401eee9 100644 --- a/app/src/main/java/com/hippo/ehviewer/AppContext.java +++ b/app/src/main/java/com/hippo/ehviewer/AppContext.java @@ -39,7 +39,6 @@ import com.hippo.ehviewer.util.ViewUtils; import com.hippo.ehviewer.widget.MaterialToast; import com.hippo.ehviewer.widget.SlidingDrawerLayout; -import com.hippo.vectorold.content.VectorContext; import java.io.File; import java.io.FileInputStream; @@ -177,9 +176,4 @@ private boolean handleException(Throwable ex) { public Typeface getFaceTypeface() { return mFaceTypeface; } - - @Override - protected void attachBaseContext(Context newBase) { - super.attachBaseContext(VectorContext.wrapContext(newBase)); - } } diff --git a/app/src/main/java/com/hippo/ehviewer/StartActivity.java b/app/src/main/java/com/hippo/ehviewer/StartActivity.java index 69bc791f0..3046a765a 100644 --- a/app/src/main/java/com/hippo/ehviewer/StartActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/StartActivity.java @@ -37,6 +37,7 @@ import com.hippo.ehviewer.util.ViewUtils; import com.hippo.ehviewer.widget.LockPatternUtils; import com.hippo.ehviewer.widget.SimpleImageView; +import com.hippo.vector.VectorDrawable; public class StartActivity extends AbsActivity { @@ -188,7 +189,7 @@ public void onCreate(Bundle savedInstanceState) { TextView text = (TextView) findViewById(R.id.text); text.setTypeface(Typeface.createFromAsset(getAssets(),"fonts/GloriaHallelujah.ttf")); SimpleImageView image = (SimpleImageView) findViewById(R.id.image); - image.setDrawable(R.drawable.sad_pandroid); + image.setDrawable(VectorDrawable.create(this, R.drawable.sad_pandroid)); // Update secret image here int state = Network.getNetworkState(this); diff --git a/app/src/main/java/com/hippo/ehviewer/ehclient/EhInfo.java b/app/src/main/java/com/hippo/ehviewer/ehclient/EhInfo.java index f2e5c4d4d..7f1f176f0 100644 --- a/app/src/main/java/com/hippo/ehviewer/ehclient/EhInfo.java +++ b/app/src/main/java/com/hippo/ehviewer/ehclient/EhInfo.java @@ -27,6 +27,7 @@ import com.hippo.ehviewer.util.Config; import com.hippo.ehviewer.util.MathUtils; import com.hippo.ehviewer.util.Utils; +import com.hippo.vector.VectorDrawable; import java.io.File; import java.io.FileInputStream; @@ -107,7 +108,7 @@ private EhInfo(final Context context){ mContext = context; mInfoPref = mContext.getSharedPreferences(PREF_NAME, 0); if (DEFAULT_AVATAR == null) - DEFAULT_AVATAR = context.getResources().getDrawable(R.drawable.default_avatar); + DEFAULT_AVATAR = VectorDrawable.create(context, R.drawable.default_avatar); mIsLogin = mInfoPref.getBoolean(KEY_LOGIN, DEFAULT_LOGIN); mUsername = mInfoPref.getString(KEY_USERNAME, DEFAULT_NAME); diff --git a/app/src/main/java/com/hippo/ehviewer/service/DownloadService.java b/app/src/main/java/com/hippo/ehviewer/service/DownloadService.java index 2f1249821..7186fc807 100644 --- a/app/src/main/java/com/hippo/ehviewer/service/DownloadService.java +++ b/app/src/main/java/com/hippo/ehviewer/service/DownloadService.java @@ -34,7 +34,6 @@ import com.hippo.ehviewer.ui.DownloadActivity; import com.hippo.ehviewer.util.Config; import com.hippo.ehviewer.util.Utils; -import com.hippo.vectorold.content.VectorContext; import java.util.ArrayList; import java.util.List; @@ -487,9 +486,4 @@ public synchronized void onDownloadOver(int gid, int legacy) { tryToStartDownload(); notifyUpdate(); } - - @Override - protected void attachBaseContext(Context newBase) { - super.attachBaseContext(VectorContext.wrapContext(newBase)); - } } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/AbsActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/AbsActivity.java index 1de0828ed..2b01b4774 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/AbsActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/AbsActivity.java @@ -17,13 +17,11 @@ package com.hippo.ehviewer.ui; import android.app.Activity; -import android.content.Context; import com.google.analytics.tracking.android.EasyTracker; import com.hippo.ehviewer.cache.ImageCache; import com.hippo.ehviewer.util.Config; import com.hippo.ehviewer.util.Ui; -import com.hippo.vectorold.content.VectorContext; public abstract class AbsActivity extends Activity { @@ -56,9 +54,4 @@ protected void onStop() { if (Config.getAllowAnalyics()) EasyTracker.getInstance(this).activityStop(this); } - - @Override - protected void attachBaseContext(Context newBase) { - super.attachBaseContext(VectorContext.wrapContext(newBase)); - } } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/AbsPreferenceActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/AbsPreferenceActivity.java index 6a09e7d3c..89299dce6 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/AbsPreferenceActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/AbsPreferenceActivity.java @@ -16,13 +16,11 @@ package com.hippo.ehviewer.ui; -import android.content.Context; import android.preference.PreferenceActivity; import com.google.analytics.tracking.android.EasyTracker; import com.hippo.ehviewer.util.Config; import com.hippo.ehviewer.util.Ui; -import com.hippo.vectorold.content.VectorContext; public abstract class AbsPreferenceActivity extends PreferenceActivity { @@ -50,9 +48,4 @@ public void onStop() { if (Config.getAllowAnalyics()) EasyTracker.getInstance(this).activityStop(this); } - - @Override - protected void attachBaseContext(Context newBase) { - super.attachBaseContext(VectorContext.wrapContext(newBase)); - } } diff --git a/app/src/main/java/com/hippo/vectorold/animation/AnimatorInflater.java b/app/src/main/java/com/hippo/vectorold/animation/AnimatorInflater.java deleted file mode 100644 index 6105dd0f9..000000000 --- a/app/src/main/java/com/hippo/vectorold/animation/AnimatorInflater.java +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Copyright (C) 2010 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.hippo.vectorold.animation; - -import android.animation.Animator; -import android.animation.AnimatorSet; -import android.animation.ArgbEvaluator; -import android.animation.ObjectAnimator; -import android.animation.TypeEvaluator; -import android.animation.ValueAnimator; -import android.content.Context; -import android.content.res.Resources; -import android.content.res.Resources.NotFoundException; -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.util.AttributeSet; -import android.util.Log; -import android.util.TypedValue; -import android.util.Xml; -import android.view.InflateException; - -import com.hippo.ehviewer.R; -import com.hippo.vectorold.util.PathParser; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.util.ArrayList; - -/** - * This class is used to instantiate animator XML files into Animator objects. - *

- * For performance reasons, inflation relies heavily on pre-processing of - * XML files that is done at build time. Therefore, it is not currently possible - * to use this inflater with an XmlPullParser over a plain XML file at runtime; - * it only works with an XmlPullParser returned from a compiled resource (R. - * something file.) - */ -public class AnimatorInflater { - private static final String TAG = "AnimatorInflater"; - /** - * These flags are used when parsing AnimatorSet objects - */ - private static final int TOGETHER = 0; - private static final int SEQUENTIALLY = 1; - - /** - * Enum values used in XML attributes to indicate the value for mValueType - */ - private static final int VALUE_TYPE_FLOAT = 0; - private static final int VALUE_TYPE_INT = 1; - private static final int VALUE_TYPE_PATH = 2; - private static final int VALUE_TYPE_COLOR = 4; - private static final int VALUE_TYPE_CUSTOM = 5; - - private static final boolean DBG_ANIMATOR_INFLATER = false; - - private static final ArgbEvaluator ARGB_EVALUATOR = new ArgbEvaluator(); - - /** - * Loads an {@link android.animation.Animator} object from a resource - * - * @param context Application context used to access resources - * @param id The resource id of the animation to load - * @return The animator object reference by the specified id - * @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded - */ - public static Animator loadAnimator(Context context, int id) - throws NotFoundException { - return loadAnimator(context, id, 1); - } - - public static Animator loadAnimator(Context context, int id, float pathErrorScale) { - Resources resources = context.getResources(); - XmlResourceParser parser = null; - try { - parser = resources.getAnimation(id); - return createAnimatorFromXml(context, parser, pathErrorScale); - } catch (XmlPullParserException ex) { - NotFoundException rnf = - new NotFoundException("Can't load animation resource ID #0x" + - Integer.toHexString(id)); - rnf.initCause(ex); - throw rnf; - } catch (IOException ex) { - NotFoundException rnf = - new NotFoundException("Can't load animation resource ID #0x" + - Integer.toHexString(id)); - rnf.initCause(ex); - throw rnf; - } finally { - if (parser != null) parser.close(); - } - } - - /* TODO Not support StateListAnimator - public static StateListAnimator loadStateListAnimator(Context context, int id) - throws NotFoundException { - XmlResourceParser parser = null; - try { - parser = context.getResources().getAnimation(id); - return createStateListAnimatorFromXml(context, parser, Xml.asAttributeSet(parser)); - } catch (XmlPullParserException ex) { - NotFoundException rnf = - new NotFoundException( - "Can't load state list animator resource ID #0x" + - Integer.toHexString(id) - ); - rnf.initCause(ex); - throw rnf; - } catch (IOException ex) { - NotFoundException rnf = - new NotFoundException( - "Can't load state list animator resource ID #0x" + - Integer.toHexString(id) - ); - rnf.initCause(ex); - throw rnf; - } finally { - if (parser != null) { - parser.close(); - } - } - } - */ - - /* TODO Not support StateListAnimator - private static StateListAnimator createStateListAnimatorFromXml(Context context, - XmlPullParser parser, AttributeSet attributeSet) - throws IOException, XmlPullParserException { - int type; - StateListAnimator stateListAnimator = new StateListAnimator(); - - while (true) { - type = parser.next(); - switch (type) { - case XmlPullParser.END_DOCUMENT: - case XmlPullParser.END_TAG: - return stateListAnimator; - - case XmlPullParser.START_TAG: - // parse item - Animator animator = null; - if ("item".equals(parser.getName())) { - int attributeCount = parser.getAttributeCount(); - int[] states = new int[attributeCount]; - int stateIndex = 0; - for (int i = 0; i < attributeCount; i++) { - int attrName = attributeSet.getAttributeNameResource(i); - if (attrName == R.attr.animation) { - animator = loadAnimator(context, - attributeSet.getAttributeResourceValue(i, 0)); - } else { - states[stateIndex++] = - attributeSet.getAttributeBooleanValue(i, false) ? - attrName : -attrName; - } - - } - if (animator == null) { - animator = createAnimatorFromXml(context, parser, 1f); - } - - if (animator == null) { - throw new NotFoundException( - "animation state item must have a valid animation"); - } - stateListAnimator - .addState(StateSet.trimStateSet(states, stateIndex), animator); - - } - break; - } - } - } - */ - - /** - * PathDataEvaluator is used to interpolate between two paths which are - * represented in the same format but different control points' values. - * The path is represented as an array of PathDataNode here, which is - * fundamentally an array of floating point numbers. - */ - private static class PathDataEvaluator implements TypeEvaluator { - private PathParser.PathDataNode[] mNodeArray; - - /** - * Create a PathParser.PathDataNode[] that does not reuse the animated value. - * Care must be taken when using this option because on every evaluation - * a new PathParser.PathDataNode[] will be allocated. - */ - private PathDataEvaluator() {} - - /** - * Create a PathDataEvaluator that reuses nodeArray for every evaluate() call. - * Caution must be taken to ensure that the value returned from - * {@link android.animation.ValueAnimator#getAnimatedValue()} is not cached, modified, or - * used across threads. The value will be modified on each evaluate() call. - * - * @param nodeArray The array to modify and return from evaluate. - */ - public PathDataEvaluator(PathParser.PathDataNode[] nodeArray) { - mNodeArray = nodeArray; - } - - @Override - public PathParser.PathDataNode[] evaluate(float fraction, - PathParser.PathDataNode[] startPathData, - PathParser.PathDataNode[] endPathData) { - if (!PathParser.canMorph(startPathData, endPathData)) { - throw new IllegalArgumentException("Can't interpolate between" - + " two incompatible pathData"); - } - - if (mNodeArray == null || !PathParser.canMorph(mNodeArray, startPathData)) { - mNodeArray = PathParser.deepCopyNodes(startPathData); - } - - for (int i = 0; i < startPathData.length; i++) { - mNodeArray[i].interpolatePathDataNode(startPathData[i], - endPathData[i], fraction); - } - - return mNodeArray; - } - } - - /** - * @param anim The animator, must not be null - * @param arrayAnimator Incoming typed array for Animator's attributes. - * @param arrayObjectAnimator Incoming typed array for Object Animator's - * attributes. - * @param pixelSize The relative pixel size, used to calculate the - * maximum error for path animations. - */ - private static void parseAnimatorFromTypeArray(ValueAnimator anim, - TypedArray arrayAnimator, TypedArray arrayObjectAnimator, float pixelSize) { - long duration = arrayAnimator.getInt(R.styleable.Animator_duration, 300); - - long startDelay = arrayAnimator.getInt(R.styleable.Animator_startOffset, 0); - - int valueType = arrayAnimator.getInt(R.styleable.Animator_valueType, - VALUE_TYPE_FLOAT); - - TypeEvaluator evaluator = null; - - boolean getFloats = (valueType == VALUE_TYPE_FLOAT); - - TypedValue tvFrom = arrayAnimator.peekValue(R.styleable.Animator_valueFrom); - boolean hasFrom = (tvFrom != null); - int fromType = hasFrom ? tvFrom.type : 0; - TypedValue tvTo = arrayAnimator.peekValue(R.styleable.Animator_valueTo); - boolean hasTo = (tvTo != null); - int toType = hasTo ? tvTo.type : 0; - - // TODO: Further clean up this part of code into 4 types : path, color, - // integer and float. - if (valueType == VALUE_TYPE_PATH) { - evaluator = setupAnimatorForPath(anim, arrayAnimator); - } else { - // Integer and float value types are handled here. - if ((hasFrom && (fromType >= TypedValue.TYPE_FIRST_COLOR_INT) && - (fromType <= TypedValue.TYPE_LAST_COLOR_INT)) || - (hasTo && (toType >= TypedValue.TYPE_FIRST_COLOR_INT) && - (toType <= TypedValue.TYPE_LAST_COLOR_INT))) { - // special case for colors: ignore valueType and get ints - getFloats = false; - evaluator = ARGB_EVALUATOR; - } - setupValues(anim, arrayAnimator, getFloats, hasFrom, fromType, hasTo, toType); - } - - anim.setDuration(duration); - anim.setStartDelay(startDelay); - - if (arrayAnimator.hasValue(R.styleable.Animator_repeatCount)) { - anim.setRepeatCount( - arrayAnimator.getInt(R.styleable.Animator_repeatCount, 0)); - } - if (arrayAnimator.hasValue(R.styleable.Animator_repeatMode)) { - anim.setRepeatMode( - arrayAnimator.getInt(R.styleable.Animator_repeatMode, - ValueAnimator.RESTART)); - } - if (evaluator != null) { - anim.setEvaluator(evaluator); - } - - if (arrayObjectAnimator != null) { - setupObjectAnimator(anim, arrayObjectAnimator, getFloats, pixelSize); - } - } - - /** - * Setup the Animator to achieve path morphing. - * - * @param anim The target Animator which will be updated. - * @param arrayAnimator TypedArray for the ValueAnimator. - * @return the PathDataEvaluator. - */ - private static TypeEvaluator setupAnimatorForPath(ValueAnimator anim, - TypedArray arrayAnimator) { - TypeEvaluator evaluator = null; - String fromString = arrayAnimator.getString(R.styleable.Animator_valueFrom); - String toString = arrayAnimator.getString(R.styleable.Animator_valueTo); - PathParser.PathDataNode[] nodesFrom = PathParser.createNodesFromPathData(fromString); - PathParser.PathDataNode[] nodesTo = PathParser.createNodesFromPathData(toString); - - if (nodesFrom != null) { - if (nodesTo != null) { - anim.setObjectValues(nodesFrom, nodesTo); - if (!PathParser.canMorph(nodesFrom, nodesTo)) { - throw new InflateException(arrayAnimator.getPositionDescription() - + " Can't morph from " + fromString + " to " + toString); - } - } else { - anim.setObjectValues((Object)nodesFrom); - } - evaluator = new PathDataEvaluator(PathParser.deepCopyNodes(nodesFrom)); - } else if (nodesTo != null) { - anim.setObjectValues((Object)nodesTo); - evaluator = new PathDataEvaluator(PathParser.deepCopyNodes(nodesTo)); - } - - if (DBG_ANIMATOR_INFLATER && evaluator != null) { - Log.v(TAG, "create a new PathDataEvaluator here"); - } - - return evaluator; - } - - /** - * Setup ObjectAnimator's property or values from pathData. - * - * @param anim The target Animator which will be updated. - * @param arrayObjectAnimator TypedArray for the ObjectAnimator. - * @param getFloats True if the value type is float. - * @param pixelSize The relative pixel size, used to calculate the - * maximum error for path animations. - */ - private static void setupObjectAnimator(ValueAnimator anim, TypedArray arrayObjectAnimator, - boolean getFloats, float pixelSize) { - ObjectAnimator oa = (ObjectAnimator) anim; - String pathData = arrayObjectAnimator.getString(R.styleable.PropertyAnimator_pathData); - - // Note that if there is a pathData defined in the Object Animator, - // valueFrom / valueTo will be ignored. - if (pathData != null) { - throw new IllegalStateException("Not support PropertyAnimator_pathData"); - /* TODO Not support pathData - String propertyXName = - arrayObjectAnimator.getString(R.styleable.PropertyAnimator_propertyXName); - String propertyYName = - arrayObjectAnimator.getString(R.styleable.PropertyAnimator_propertyYName); - - if (propertyXName == null && propertyYName == null) { - throw new InflateException(arrayObjectAnimator.getPositionDescription() - + " propertyXName or propertyYName is needed for PathData"); - } else { - JPath path = JPathParser.createPathFromPathData(pathData); - float error = 0.5f * pixelSize; // max half a pixel error - PathKeyframes keyframeSet = new PathKeyframes(path, error); - Keyframes xKeyframes; - Keyframes yKeyframes; - if (getFloats) { - xKeyframes = keyframeSet.createXFloatKeyframes(); - yKeyframes = keyframeSet.createYFloatKeyframes(); - } else { - xKeyframes = keyframeSet.createXIntKeyframes(); - yKeyframes = keyframeSet.createYIntKeyframes(); - } - PropertyValuesHolder x = null; - PropertyValuesHolder y = null; - if (propertyXName != null) { - x = PropertyValuesHolder.ofKeyframes(propertyXName, xKeyframes); - } - if (propertyYName != null) { - y = PropertyValuesHolder.ofKeyframes(propertyYName, yKeyframes); - } - if (x == null) { - oa.setValues(y); - } else if (y == null) { - oa.setValues(x); - } else { - oa.setValues(x, y); - } - } - */ - } else { - String propertyName = - arrayObjectAnimator.getString(R.styleable.PropertyAnimator_propertyName); - oa.setPropertyName(propertyName); - } - } - - /** - * Setup ValueAnimator's values. - * This will handle all of the integer, float and color types. - * - * @param anim The target Animator which will be updated. - * @param arrayAnimator TypedArray for the ValueAnimator. - * @param getFloats True if the value type is float. - * @param hasFrom True if "valueFrom" exists. - * @param fromType The type of "valueFrom". - * @param hasTo True if "valueTo" exists. - * @param toType The type of "valueTo". - */ - private static void setupValues(ValueAnimator anim, TypedArray arrayAnimator, - boolean getFloats, boolean hasFrom, int fromType, boolean hasTo, int toType) { - int valueFromIndex = R.styleable.Animator_valueFrom; - int valueToIndex = R.styleable.Animator_valueTo; - if (getFloats) { - float valueFrom; - float valueTo; - if (hasFrom) { - if (fromType == TypedValue.TYPE_DIMENSION) { - valueFrom = arrayAnimator.getDimension(valueFromIndex, 0f); - } else { - valueFrom = arrayAnimator.getFloat(valueFromIndex, 0f); - } - if (hasTo) { - if (toType == TypedValue.TYPE_DIMENSION) { - valueTo = arrayAnimator.getDimension(valueToIndex, 0f); - } else { - valueTo = arrayAnimator.getFloat(valueToIndex, 0f); - } - anim.setFloatValues(valueFrom, valueTo); - } else { - anim.setFloatValues(valueFrom); - } - } else { - if (toType == TypedValue.TYPE_DIMENSION) { - valueTo = arrayAnimator.getDimension(valueToIndex, 0f); - } else { - valueTo = arrayAnimator.getFloat(valueToIndex, 0f); - } - anim.setFloatValues(valueTo); - } - } else { - int valueFrom; - int valueTo; - if (hasFrom) { - if (fromType == TypedValue.TYPE_DIMENSION) { - valueFrom = (int) arrayAnimator.getDimension(valueFromIndex, 0f); - } else if ((fromType >= TypedValue.TYPE_FIRST_COLOR_INT) && - (fromType <= TypedValue.TYPE_LAST_COLOR_INT)) { - valueFrom = arrayAnimator.getColor(valueFromIndex, 0); - } else { - valueFrom = arrayAnimator.getInt(valueFromIndex, 0); - } - if (hasTo) { - if (toType == TypedValue.TYPE_DIMENSION) { - valueTo = (int) arrayAnimator.getDimension(valueToIndex, 0f); - } else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) && - (toType <= TypedValue.TYPE_LAST_COLOR_INT)) { - valueTo = arrayAnimator.getColor(valueToIndex, 0); - } else { - valueTo = arrayAnimator.getInt(valueToIndex, 0); - } - anim.setIntValues(valueFrom, valueTo); - } else { - anim.setIntValues(valueFrom); - } - } else { - if (hasTo) { - if (toType == TypedValue.TYPE_DIMENSION) { - valueTo = (int) arrayAnimator.getDimension(valueToIndex, 0f); - } else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) && - (toType <= TypedValue.TYPE_LAST_COLOR_INT)) { - valueTo = arrayAnimator.getColor(valueToIndex, 0); - } else { - valueTo = arrayAnimator.getInt(valueToIndex, 0); - } - anim.setIntValues(valueTo); - } - } - } - } - - private static Animator createAnimatorFromXml(Context context, XmlPullParser parser, - float pixelSize) - throws XmlPullParserException, IOException { - return createAnimatorFromXml(context, parser, Xml.asAttributeSet(parser), null, 0, - pixelSize); - } - - private static Animator createAnimatorFromXml(Context context, XmlPullParser parser, - AttributeSet attrs, AnimatorSet parent, int sequenceOrdering, float pixelSize) - throws XmlPullParserException, IOException { - - Animator anim = null; - ArrayList childAnims = null; - - // Make sure we are on a start tag. - int type; - int depth = parser.getDepth(); - - while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) - && type != XmlPullParser.END_DOCUMENT) { - - if (type != XmlPullParser.START_TAG) { - continue; - } - - String name = parser.getName(); - - if (name.equals("objectAnimator")) { - anim = loadObjectAnimator(context, attrs, pixelSize); - } else if (name.equals("animator")) { - anim = loadAnimator(context, attrs, null, pixelSize); - } else if (name.equals("set")) { - anim = new AnimatorSet(); - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AnimatorSet); - int ordering = a.getInt(R.styleable.AnimatorSet_ordering, - TOGETHER); - createAnimatorFromXml(context, parser, attrs, (AnimatorSet) anim, ordering, - pixelSize); - a.recycle(); - } else { - throw new RuntimeException("Unknown animator name: " + parser.getName()); - } - - if (parent != null) { - if (childAnims == null) { - childAnims = new ArrayList<>(); - } - childAnims.add(anim); - } - } - if (parent != null && childAnims != null) { - Animator[] animsArray = new Animator[childAnims.size()]; - int index = 0; - for (Animator a : childAnims) { - animsArray[index++] = a; - } - if (sequenceOrdering == TOGETHER) { - parent.playTogether(animsArray); - } else { - parent.playSequentially(animsArray); - } - } - - return anim; - - } - - private static ObjectAnimator loadObjectAnimator(Context context, AttributeSet attrs, - float pathErrorScale) throws NotFoundException { - ObjectAnimator anim = new ObjectAnimator(); - - loadAnimator(context, attrs, anim, pathErrorScale); - - return anim; - } - - /** - * Creates a new animation whose parameters come from the specified context - * and attributes set. - * - * @param context the context - * @param attrs The set of attributes holding the animation parameters - * @param anim Null if this is a ValueAnimator, otherwise this is an - * ObjectAnimator - */ - private static ValueAnimator loadAnimator(Context context, AttributeSet attrs, - ValueAnimator anim, float pathErrorScale) - throws NotFoundException { - - TypedArray arrayAnimator = context.obtainStyledAttributes(attrs, R.styleable.Animator); - TypedArray arrayObjectAnimator = null; - - // If anim is not null, then it is an object animator. - if (anim != null) { - arrayObjectAnimator = context.obtainStyledAttributes(attrs, - R.styleable.PropertyAnimator); - } - - if (anim == null) { - anim = new ValueAnimator(); - } - - parseAnimatorFromTypeArray(anim, arrayAnimator, arrayObjectAnimator, pathErrorScale); - - final int resID = - arrayAnimator.getResourceId(R.styleable.Animator_interpolator, 0); - if (resID > 0) { - anim.setInterpolator(InterpolatorInflater.loadInterpolator(context, resID)); - } - - arrayAnimator.recycle(); - if (arrayObjectAnimator != null) { - arrayObjectAnimator.recycle(); - } - - return anim; - } -} diff --git a/app/src/main/java/com/hippo/vectorold/animation/InterpolatorInflater.java b/app/src/main/java/com/hippo/vectorold/animation/InterpolatorInflater.java deleted file mode 100644 index e79cd5135..000000000 --- a/app/src/main/java/com/hippo/vectorold/animation/InterpolatorInflater.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2015 Hippo Seven - * - * 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.hippo.vectorold.animation; - -import android.content.Context; -import android.content.res.Resources; -import android.content.res.XmlResourceParser; -import android.os.Build; -import android.util.AttributeSet; -import android.util.Xml; -import android.view.animation.AccelerateDecelerateInterpolator; -import android.view.animation.AccelerateInterpolator; -import android.view.animation.AnticipateInterpolator; -import android.view.animation.AnticipateOvershootInterpolator; -import android.view.animation.BounceInterpolator; -import android.view.animation.CycleInterpolator; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; -import android.view.animation.LinearInterpolator; -import android.view.animation.OvershootInterpolator; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; - -public class InterpolatorInflater { - - /** - * Loads an {@link Interpolator} object from a resource - * - * @param context The Context - * @param id The resource id of the animation to load - * @return The interpolator object reference by the specified id - * @throws Resources.NotFoundException - */ - public static Interpolator loadInterpolator(Context context, int id) throws Resources.NotFoundException { - XmlResourceParser parser = null; - try { - parser = context.getResources().getAnimation(id); - return createInterpolatorFromXml(context, parser); - } catch (XmlPullParserException ex) { - Resources.NotFoundException rnf = new Resources.NotFoundException("Can't load animation resource ID #0x" + - Integer.toHexString(id)); - rnf.initCause(ex); - throw rnf; - } catch (IOException ex) { - Resources.NotFoundException rnf = new Resources.NotFoundException("Can't load animation resource ID #0x" + - Integer.toHexString(id)); - rnf.initCause(ex); - throw rnf; - } finally { - if (parser != null) - parser.close(); - } - - } - - private static Interpolator createInterpolatorFromXml(Context context, XmlPullParser parser) - throws XmlPullParserException, IOException { - - Interpolator interpolator = null; - - // Make sure we are on a start tag. - int type; - int depth = parser.getDepth(); - - while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) - && type != XmlPullParser.END_DOCUMENT) { - - if (type != XmlPullParser.START_TAG) { - continue; - } - - AttributeSet attrs = Xml.asAttributeSet(parser); - - String name = parser.getName(); - - if (name.equals("linearInterpolator")) { - interpolator = new LinearInterpolator(); - } else if (name.equals("accelerateInterpolator")) { - interpolator = new AccelerateInterpolator(context, attrs); - } else if (name.equals("decelerateInterpolator")) { - interpolator = new DecelerateInterpolator(context, attrs); - } else if (name.equals("accelerateDecelerateInterpolator")) { - interpolator = new AccelerateDecelerateInterpolator(); - } else if (name.equals("cycleInterpolator")) { - interpolator = new CycleInterpolator(context, attrs); - } else if (name.equals("anticipateInterpolator")) { - interpolator = new AnticipateInterpolator(context, attrs); - } else if (name.equals("overshootInterpolator")) { - interpolator = new OvershootInterpolator(context, attrs); - } else if (name.equals("anticipateOvershootInterpolator")) { - interpolator = new AnticipateOvershootInterpolator(context, attrs); - } else if (name.equals("bounceInterpolator")) { - interpolator = new BounceInterpolator(); - } else if (name.equals("pathInterpolator")) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - interpolator = new PathInterpolator(context, attrs); - } else { - interpolator = new android.view.animation.PathInterpolator(context, attrs); - } - } else { - throw new RuntimeException("Unknown interpolator name: " + parser.getName()); - } - - } - - return interpolator; - } -} diff --git a/app/src/main/java/com/hippo/vectorold/animation/PathInterpolator.java b/app/src/main/java/com/hippo/vectorold/animation/PathInterpolator.java deleted file mode 100644 index ebb4f5aee..000000000 --- a/app/src/main/java/com/hippo/vectorold/animation/PathInterpolator.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * 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.hippo.vectorold.animation; - -import android.content.Context; -import android.content.res.Resources; -import android.content.res.Resources.Theme; -import android.content.res.TypedArray; -import android.graphics.Path; -import android.graphics.PathMeasure; -import android.util.AttributeSet; -import android.view.InflateException; -import android.view.animation.Interpolator; - -import com.hippo.ehviewer.R; -import com.hippo.vectorold.util.PathParser; - -/** - * An interpolator that can traverse a Path that extends from Point - * (0, 0) to (1, 1). The x coordinate along the Path - * is the input value and the output is the y coordinate of the line at that point. - * This means that the Path must conform to a function y = f(x). - * - *

The Path must not have gaps in the x direction and must not - * loop back on itself such that there can be two points sharing the same x coordinate. - * It is alright to have a disjoint line in the vertical direction:

- *

- *     Path path = new Path();
- *     path.lineTo(0.25f, 0.25f);
- *     path.moveTo(0.25f, 0.5f);
- *     path.lineTo(1f, 1f);
- * 

- */ -public class PathInterpolator implements Interpolator { - - // This governs how accurate the approximation of the Path is. - private static final float PRECISION = 0.002f; - - private float[] mX; // x coordinates in the line - - private float[] mY; // y coordinates in the line - - /** - * Create an interpolator for an arbitrary Path. The Path - * must begin at (0, 0) and end at (1, 1). - * - * @param path The Path to use to make the line representing the interpolator. - */ - public PathInterpolator(Path path) { - initPath(path); - } - - /** - * Create an interpolator for a quadratic Bezier curve. The end points - * (0, 0) and (1, 1) are assumed. - * - * @param controlX The x coordinate of the quadratic Bezier control point. - * @param controlY The y coordinate of the quadratic Bezier control point. - */ - public PathInterpolator(float controlX, float controlY) { - initQuad(controlX, controlY); - } - - /** - * Create an interpolator for a cubic Bezier curve. The end points - * (0, 0) and (1, 1) are assumed. - * - * @param controlX1 The x coordinate of the first control point of the cubic Bezier. - * @param controlY1 The y coordinate of the first control point of the cubic Bezier. - * @param controlX2 The x coordinate of the second control point of the cubic Bezier. - * @param controlY2 The y coordinate of the second control point of the cubic Bezier. - */ - public PathInterpolator(float controlX1, float controlY1, float controlX2, float controlY2) { - initCubic(controlX1, controlY1, controlX2, controlY2); - } - - public PathInterpolator(Context context, AttributeSet attrs) { - this(context.getResources(), context.getTheme(), attrs); - } - - public PathInterpolator(Resources res, Theme theme, AttributeSet attrs) { - TypedArray a; - if (theme != null) { - a = theme.obtainStyledAttributes(attrs, R.styleable.PathInterpolator, 0, 0); - } else { - a = res.obtainAttributes(attrs, R.styleable.PathInterpolator); - } - parseInterpolatorFromTypeArray(a); - a.recycle(); - } - - private void parseInterpolatorFromTypeArray(TypedArray a) { - // If there is pathData defined in the xml file, then the controls points - // will be all coming from pathData. - if (a.hasValue(R.styleable.PathInterpolator_pathData)) { - String pathData = a.getString(R.styleable.PathInterpolator_pathData); - Path path = PathParser.createPathFromPathData(pathData); - if (path == null) { - throw new InflateException("The path is null, which is created" - + " from " + pathData); - } - initPath(path); - } else { - if (!a.hasValue(R.styleable.PathInterpolator_controlX1)) { - throw new InflateException("pathInterpolator requires the controlX1 attribute"); - } else if (!a.hasValue(R.styleable.PathInterpolator_controlY1)) { - throw new InflateException("pathInterpolator requires the controlY1 attribute"); - } - float x1 = a.getFloat(R.styleable.PathInterpolator_controlX1, 0); - float y1 = a.getFloat(R.styleable.PathInterpolator_controlY1, 0); - - boolean hasX2 = a.hasValue(R.styleable.PathInterpolator_controlX2); - boolean hasY2 = a.hasValue(R.styleable.PathInterpolator_controlY2); - - if (hasX2 != hasY2) { - throw new InflateException( - "pathInterpolator requires both controlX2 and controlY2 for cubic Beziers."); - } - - if (!hasX2) { - initQuad(x1, y1); - } else { - float x2 = a.getFloat(R.styleable.PathInterpolator_controlX2, 0); - float y2 = a.getFloat(R.styleable.PathInterpolator_controlY2, 0); - initCubic(x1, y1, x2, y2); - } - } - } - - private void initQuad(float controlX, float controlY) { - Path path = new Path(); - path.moveTo(0, 0); - path.quadTo(controlX, controlY, 1f, 1f); - initPath(path); - } - - private void initCubic(float x1, float y1, float x2, float y2) { - Path path = new Path(); - path.moveTo(0, 0); - path.cubicTo(x1, y1, x2, y2, 1f, 1f); - initPath(path); - } - - private void initPath(Path path) { - final PathMeasure pathMeasure = new PathMeasure(path, false /* forceClosed */); - - final float pathLength = pathMeasure.getLength(); - final int numPoints = (int) (pathLength / PRECISION) + 1; - - mX = new float[numPoints]; - mY = new float[numPoints]; - - final float[] position = new float[2]; - for (int i = 0; i < numPoints; ++i) { - final float distance = (i * pathLength) / (numPoints - 1); - pathMeasure.getPosTan(distance, position, null /* tangent */); - - mX[i] = position[0]; - mY[i] = position[1]; - } - } - - /** - * Using the line in the Path in this interpolator that can be described as - * y = f(x), finds the y coordinate of the line given t - * as the x coordinate. Values less than 0 will always return 0 and values greater - * than 1 will always return 1. - * - * @param t Treated as the x coordinate along the line. - * @return The y coordinate of the Path along the line where x = t. - * @see Interpolator#getInterpolation(float) - */ - @Override - public float getInterpolation(float t) { - if (t <= 0) { - return 0; - } else if (t >= 1) { - return 1; - } - // Do a binary search for the correct x to interpolate between. - int startIndex = 0; - int endIndex = mX.length - 1; - - while (endIndex - startIndex > 1) { - int midIndex = (startIndex + endIndex) / 2; - if (t < mX[midIndex]) { - endIndex = midIndex; - } else { - startIndex = midIndex; - } - } - - float xRange = mX[endIndex] - mX[startIndex]; - if (xRange == 0) { - return mY[startIndex]; - } - - float tInRange = t - mX[startIndex]; - float fraction = tInRange / xRange; - - float startY = mY[startIndex]; - float endY = mY[endIndex]; - return startY + (fraction * (endY - startY)); - } -} diff --git a/app/src/main/java/com/hippo/vectorold/content/VectorContext.java b/app/src/main/java/com/hippo/vectorold/content/VectorContext.java deleted file mode 100644 index 0bc1ab2d2..000000000 --- a/app/src/main/java/com/hippo/vectorold/content/VectorContext.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2015 Hippo Seven - * - * 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.hippo.vectorold.content; - -import android.content.Context; -import android.content.ContextWrapper; -import android.content.res.Resources; -import android.content.res.VectorResources; -import android.os.Build; - -public class VectorContext extends ContextWrapper { - - private VectorResources mVectorResources; - - public VectorContext(Context base) { - super(base); - } - - @Override - public Resources getResources() { - final Resources superResources = super.getResources(); - if (mVectorResources == null || mVectorResources.isBase(superResources)) { - mVectorResources = new VectorResources(this, superResources); - } - return mVectorResources; - } - - /** - * In {@link android.content.ContextWrapper#attachBaseContext(Context)}, - * do super.attachBaseContext(Vector.wrapContext(newBase));. - * - * @param context the context - * @return new context - */ - public static Context wrapContext(Context context) { - return Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ? new VectorContext(context) : context; - } -} diff --git a/app/src/main/java/com/hippo/vectorold/drawable/AnimatedVectorDrawable.java b/app/src/main/java/com/hippo/vectorold/drawable/AnimatedVectorDrawable.java deleted file mode 100644 index f69194055..000000000 --- a/app/src/main/java/com/hippo/vectorold/drawable/AnimatedVectorDrawable.java +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright (C) 2014 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.hippo.vectorold.drawable; - -import android.animation.Animator; -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.ColorFilter; -import android.graphics.PorterDuff; -import android.graphics.Rect; -import android.graphics.drawable.Animatable; -import android.graphics.drawable.Drawable; -import android.support.v4.util.ArrayMap; -import android.util.AttributeSet; -import android.util.Log; - -import com.hippo.vectorold.animation.AnimatorInflater; -import com.hippo.ehviewer.R; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.util.ArrayList; - -/** - * This class uses {@link android.animation.ObjectAnimator} and - * {@link android.animation.AnimatorSet} to animate the properties of a - * {@link android.graphics.drawable.VectorDrawable} to create an animated drawable. - *

- * AnimatedVectorDrawable are normally defined as 3 separate XML files. - *

- *

- * First is the XML file for {@link android.graphics.drawable.VectorDrawable}. - * Note that we allow the animation happen on the group's attributes and path's - * attributes, which requires they are uniquely named in this xml file. Groups - * and paths without animations do not need names. - *

- *
  • Here is a simple VectorDrawable in this vectordrawable.xml file. - *
    - * <vector xmlns:android="http://schemas.android.com/apk/res/android"
    - *     android:height="64dp"
    - *     android:width="64dp"
    - *     android:viewportHeight="600"
    - *     android:viewportWidth="600" >
    - *     <group
    - *         android:name="rotationGroup"
    - *         android:pivotX="300.0"
    - *         android:pivotY="300.0"
    - *         android:rotation="45.0" >
    - *         <path
    - *             android:name="v"
    - *             android:fillColor="#000000"
    - *             android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
    - *     </group>
    - * </vector>
    - * 
  • - *

    - * Second is the AnimatedVectorDrawable's xml file, which defines the target - * VectorDrawable, the target paths and groups to animate, the properties of the - * path and group to animate and the animations defined as the ObjectAnimators - * or AnimatorSets. - *

    - *
  • Here is a simple AnimatedVectorDrawable defined in this avd.xml file. - * Note how we use the names to refer to the groups and paths in the vectordrawable.xml. - *
    - * <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    - *   android:drawable="@drawable/vectordrawable" >
    - *     <target
    - *         android:name="rotationGroup"
    - *         android:animation="@anim/rotation" />
    - *     <target
    - *         android:name="v"
    - *         android:animation="@anim/path_morph" />
    - * </animated-vector>
    - * 
  • - *

    - * Last is the Animator xml file, which is the same as a normal ObjectAnimator - * or AnimatorSet. - * To complete this example, here are the 2 animator files used in avd.xml: - * rotation.xml and path_morph.xml. - *

    - *
  • Here is the rotation.xml, which will rotate the target group for 360 degrees. - *
    - * <objectAnimator
    - *     android:duration="6000"
    - *     android:propertyName="rotation"
    - *     android:valueFrom="0"
    - *     android:valueTo="360" />
    - * 
  • - *
  • Here is the path_morph.xml, which will morph the path from one shape to - * the other. Note that the paths must be compatible for morphing. - * In more details, the paths should have exact same length of commands , and - * exact same length of parameters for each commands. - * Note that the path string are better stored in strings.xml for reusing. - *
    - * <set xmlns:android="http://schemas.android.com/apk/res/android">
    - *     <objectAnimator
    - *         android:duration="3000"
    - *         android:propertyName="pathData"
    - *         android:valueFrom="M300,70 l 0,-70 70,70 0,0   -70,70z"
    - *         android:valueTo="M300,70 l 0,-70 70,0  0,140 -70,0 z"
    - *         android:valueType="pathType"/>
    - * </set>
    - * 
  • - * - * @attr ref android.R.styleable#AnimatedVectorDrawable_drawable - * @attr ref android.R.styleable#AnimatedVectorDrawableTarget_name - * @attr ref android.R.styleable#AnimatedVectorDrawableTarget_animation - */ -public class AnimatedVectorDrawable extends Drawable implements Animatable { - private static final String LOGTAG = AnimatedVectorDrawable.class.getSimpleName(); - - private static final String ANIMATED_VECTOR = "animated-vector"; - private static final String TARGET = "target"; - - private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false; - - private AnimatedVectorDrawableState mAnimatedVectorState; - - private boolean mMutated; - - public AnimatedVectorDrawable() { - mAnimatedVectorState = new AnimatedVectorDrawableState(null); - } - - private AnimatedVectorDrawable(AnimatedVectorDrawableState state, Resources res) { - mAnimatedVectorState = new AnimatedVectorDrawableState(state); - } - - @Override - public Drawable mutate() { - if (!mMutated && super.mutate() == this) { - mAnimatedVectorState.mVectorDrawable.mutate(); - mMutated = true; - } - return this; - } - - @Override - public ConstantState getConstantState() { - mAnimatedVectorState.mChangingConfigurations = getChangingConfigurations(); - return mAnimatedVectorState; - } - - @Override - public int getChangingConfigurations() { - return super.getChangingConfigurations() | mAnimatedVectorState.mChangingConfigurations; - } - - @Override - public void draw(Canvas canvas) { - mAnimatedVectorState.mVectorDrawable.draw(canvas); - if (isStarted()) { - invalidateSelf(); - } - } - - @Override - protected void onBoundsChange(Rect bounds) { - mAnimatedVectorState.mVectorDrawable.setBounds(bounds); - } - - @Override - protected boolean onStateChange(int[] state) { - return mAnimatedVectorState.mVectorDrawable.setState(state); - } - - @Override - protected boolean onLevelChange(int level) { - return mAnimatedVectorState.mVectorDrawable.setLevel(level); - } - - @Override - public int getAlpha() { - return mAnimatedVectorState.mVectorDrawable.getAlpha(); - } - - @Override - public void setAlpha(int alpha) { - mAnimatedVectorState.mVectorDrawable.setAlpha(alpha); - } - - @Override - public void setColorFilter(ColorFilter colorFilter) { - mAnimatedVectorState.mVectorDrawable.setColorFilter(colorFilter); - } - - @Override - public void setTintList(ColorStateList tint) { - mAnimatedVectorState.mVectorDrawable.setTintList(tint); - } - - @Override - public void setTintMode(PorterDuff.Mode tintMode) { - mAnimatedVectorState.mVectorDrawable.setTintMode(tintMode); - } - - @Override - public boolean setVisible(boolean visible, boolean restart) { - mAnimatedVectorState.mVectorDrawable.setVisible(visible, restart); - return super.setVisible(visible, restart); - } - - @Override - public boolean isStateful() { - return mAnimatedVectorState.mVectorDrawable.isStateful(); - } - - @Override - public int getOpacity() { - return mAnimatedVectorState.mVectorDrawable.getOpacity(); - } - - @Override - public int getIntrinsicWidth() { - return mAnimatedVectorState.mVectorDrawable.getIntrinsicWidth(); - } - - @Override - public int getIntrinsicHeight() { - return mAnimatedVectorState.mVectorDrawable.getIntrinsicHeight(); - } - - public void inflate(Context context, XmlPullParser parser, AttributeSet attrs) - throws XmlPullParserException, IOException { - Resources res = context.getResources(); - int eventType = parser.getEventType(); - float pathErrorScale = 1; - while (eventType != XmlPullParser.END_DOCUMENT) { - if (eventType == XmlPullParser.START_TAG) { - final String tagName = parser.getName(); - if (ANIMATED_VECTOR.equals(tagName)) { - final TypedArray a = res.obtainAttributes(attrs, - R.styleable.AnimatedVectorDrawable); - int drawableRes = a.getResourceId( - R.styleable.AnimatedVectorDrawable_drawable, 0); - if (drawableRes != 0) { - VectorDrawable vectorDrawable =(VectorDrawable) res.getDrawable( - drawableRes).mutate(); - vectorDrawable.setAllowCaching(false); - pathErrorScale = vectorDrawable.getPixelSize(); - mAnimatedVectorState.mVectorDrawable = vectorDrawable; - } - a.recycle(); - } else if (TARGET.equals(tagName)) { - final TypedArray a = res.obtainAttributes(attrs, - R.styleable.AnimatedVectorDrawableTarget); - final String target = a.getString( - R.styleable.AnimatedVectorDrawableTarget_name); - - int id = a.getResourceId( - R.styleable.AnimatedVectorDrawableTarget_animation, 0); - if (id != 0) { - Animator objectAnimator = AnimatorInflater.loadAnimator(context, id, pathErrorScale); - setupAnimatorsForTarget(target, objectAnimator); - } - a.recycle(); - } - } - - eventType = parser.next(); - } - } - - private static class AnimatedVectorDrawableState extends ConstantState { - int mChangingConfigurations; - VectorDrawable mVectorDrawable; - ArrayList mAnimators; - ArrayMap mTargetNameMap; - - public AnimatedVectorDrawableState(AnimatedVectorDrawableState copy) { - if (copy != null) { - mChangingConfigurations = copy.mChangingConfigurations; - if (copy.mVectorDrawable != null) { - mVectorDrawable = (VectorDrawable) copy.mVectorDrawable.getConstantState().newDrawable(); - mVectorDrawable.mutate(); - mVectorDrawable.setAllowCaching(false); - mVectorDrawable.setBounds(copy.mVectorDrawable.getBounds()); - } - if (copy.mAnimators != null) { - final int numAnimators = copy.mAnimators.size(); - mAnimators = new ArrayList<>(numAnimators); - mTargetNameMap = new ArrayMap<>(numAnimators); - for (int i = 0; i < numAnimators; ++i) { - Animator anim = copy.mAnimators.get(i); - Animator animClone = anim.clone(); - String targetName = copy.mTargetNameMap.get(anim); - Object targetObject = mVectorDrawable.getTargetByName(targetName); - animClone.setTarget(targetObject); - mAnimators.add(animClone); - mTargetNameMap.put(animClone, targetName); - } - } - } else { - mVectorDrawable = new VectorDrawable(); - } - } - - @Override - public Drawable newDrawable() { - return new AnimatedVectorDrawable(this, null); - } - - @Override - public Drawable newDrawable(Resources res) { - return new AnimatedVectorDrawable(this, res); - } - - @Override - public int getChangingConfigurations() { - return mChangingConfigurations; - } - } - - private void setupAnimatorsForTarget(String name, Animator animator) { - Object target = mAnimatedVectorState.mVectorDrawable.getTargetByName(name); - animator.setTarget(target); - if (mAnimatedVectorState.mAnimators == null) { - mAnimatedVectorState.mAnimators = new ArrayList<>(); - mAnimatedVectorState.mTargetNameMap = new ArrayMap<>(); - } - mAnimatedVectorState.mAnimators.add(animator); - mAnimatedVectorState.mTargetNameMap.put(animator, name); - if (DBG_ANIMATION_VECTOR_DRAWABLE) { - Log.v(LOGTAG, "add animator for target " + name + " " + animator); - } - } - - @Override - public boolean isRunning() { - final ArrayList animators = mAnimatedVectorState.mAnimators; - final int size = animators.size(); - for (int i = 0; i < size; i++) { - final Animator animator = animators.get(i); - if (animator.isRunning()) { - return true; - } - } - return false; - } - - private boolean isStarted() { - final ArrayList animators = mAnimatedVectorState.mAnimators; - final int size = animators.size(); - for (int i = 0; i < size; i++) { - final Animator animator = animators.get(i); - if (animator.isStarted()) { - return true; - } - } - return false; - } - - @Override - public void start() { - final ArrayList animators = mAnimatedVectorState.mAnimators; - final int size = animators.size(); - for (int i = 0; i < size; i++) { - final Animator animator = animators.get(i); - if (!animator.isStarted()) { - animator.start(); - } - } - invalidateSelf(); - } - - @Override - public void stop() { - final ArrayList animators = mAnimatedVectorState.mAnimators; - final int size = animators.size(); - for (int i = 0; i < size; i++) { - final Animator animator = animators.get(i); - animator.end(); - } - } - - /** - * Reverses ongoing animations or starts pending animations in reverse. - *

    - * NOTE: Only works of all animations are ValueAnimators. - * @hide - */ - /* - public void reverse() { - final ArrayList animators = mAnimatedVectorState.mAnimators; - final int size = animators.size(); - for (int i = 0; i < size; i++) { - final Animator animator = animators.get(i); - if (animator.canReverse()) { - animator.reverse(); - } else { - Log.w(LOGTAG, "AnimatedVectorDrawable can't reverse()"); - } - } - } - */ - - /** - * @hide - */ - /* - public boolean canReverse() { - final ArrayList animators = mAnimatedVectorState.mAnimators; - final int size = animators.size(); - for (int i = 0; i < size; i++) { - final Animator animator = animators.get(i); - if (!animator.canReverse()) { - return false; - } - } - return true; - } - */ -} diff --git a/app/src/main/res/values/vectorold_attrs.xml b/app/src/main/res/values/vectorold_attrs.xml deleted file mode 100644 index 42b1a8388..000000000 --- a/app/src/main/res/values/vectorold_attrs.xml +++ /dev/null @@ -1,240 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build.gradle b/build.gradle index fafdb58e5..c6371d6cd 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:1.3.0-beta2' + classpath 'com.android.tools.build:gradle:1.3.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/settings.gradle b/settings.gradle index e7b4def49..e25a440c7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':app' +include ':app', ':vector' diff --git a/vector/.gitignore b/vector/.gitignore new file mode 100644 index 000000000..3543521e9 --- /dev/null +++ b/vector/.gitignore @@ -0,0 +1 @@ +/build diff --git a/vector/build.gradle b/vector/build.gradle new file mode 100644 index 000000000..3c0867ffa --- /dev/null +++ b/vector/build.gradle @@ -0,0 +1,24 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 23 + buildToolsVersion "23.0.1" + + defaultConfig { + minSdkVersion 14 + targetSdkVersion 23 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + compile 'com.android.support:support-v4:22.2.1' +} diff --git a/vector/proguard-rules.pro b/vector/proguard-rules.pro new file mode 100644 index 000000000..ebd1ee4cd --- /dev/null +++ b/vector/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in E:\Android\android-sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/vector/src/androidTest/java/com/hippo/vector/ApplicationTest.java b/vector/src/androidTest/java/com/hippo/vector/ApplicationTest.java new file mode 100644 index 000000000..a43cd50a6 --- /dev/null +++ b/vector/src/androidTest/java/com/hippo/vector/ApplicationTest.java @@ -0,0 +1,13 @@ +package com.hippo.vector; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } +} \ No newline at end of file diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml new file mode 100644 index 000000000..c3eeb26fa --- /dev/null +++ b/vector/src/main/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/app/src/main/java/com/hippo/vectorold/util/PathParser.java b/vector/src/main/java/com/hippo/vector/PathParser.java similarity index 88% rename from app/src/main/java/com/hippo/vectorold/util/PathParser.java rename to vector/src/main/java/com/hippo/vector/PathParser.java index 178c542dd..9e5ec09e5 100644 --- a/app/src/main/java/com/hippo/vectorold/util/PathParser.java +++ b/vector/src/main/java/com/hippo/vector/PathParser.java @@ -1,18 +1,20 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2015 Hippo Seven * - * 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 + * 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 + * 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. + * 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.hippo.vectorold.util; +package com.hippo.vector; import android.graphics.Path; import android.util.Log; @@ -20,9 +22,6 @@ import java.util.ArrayList; import java.util.Arrays; -/** - * @hide - */ public class PathParser { static final String LOGTAG = PathParser.class.getSimpleName(); @@ -34,7 +33,11 @@ public static Path createPathFromPathData(String pathData) { Path path = new Path(); PathDataNode[] nodes = createNodesFromPathData(pathData); if (nodes != null) { - PathDataNode.nodesToPath(nodes, path); + try { + PathDataNode.nodesToPath(nodes, path); + } catch (RuntimeException e) { + throw new RuntimeException("Error in parsing " + pathData, e); + } return path; } return null; @@ -128,7 +131,12 @@ private static int nextStart(String s, int end) { while (end < s.length()) { c = s.charAt(end); - if (((c - 'A') * (c - 'Z') <= 0) || (((c - 'a') * (c - 'z') <= 0))) { + // Note that 'e' or 'E' are not valid path commands, but could be + // used for floating point numbers' scientific notation. + // Therefore, when searching for next command, we should ignore 'e' + // and 'E'. + if ((((c - 'A') * (c - 'Z') <= 0) || ((c - 'a') * (c - 'z') <= 0)) + && c != 'e' && c != 'E') { return end; } end++; @@ -142,9 +150,9 @@ private static void addNode(ArrayList list, char cmd, float[] val) private static class ExtractFloatResult { // We need to return the position of the next separator and whether the - // next float starts with a '-'. + // next float starts with a '-' or a '.'. int mEndPosition; - boolean mEndWithNegSign; + boolean mEndWithNegOrDot; } /** @@ -155,7 +163,7 @@ private static class ExtractFloatResult { * @return array of floats */ private static float[] getFloats(String s) { - if (s.charAt(0) == 'z' | s.charAt(0) == 'Z') { + if (s.charAt(0) == 'z' || s.charAt(0) == 'Z') { return new float[0]; } try { @@ -179,8 +187,8 @@ private static float[] getFloats(String s) { s.substring(startPosition, endPosition)); } - if (result.mEndWithNegSign) { - // Keep the '-' sign with next number. + if (result.mEndWithNegOrDot) { + // Keep the '-' or '.' sign with next number. startPosition = endPosition; } else { startPosition = endPosition + 1; @@ -188,8 +196,7 @@ private static float[] getFloats(String s) { } return Arrays.copyOf(results, count); } catch (NumberFormatException e) { - Log.e(LOGTAG, "error in parsing \"" + s + "\""); - throw e; + throw new RuntimeException("error in parsing \"" + s + "\"", e); } } @@ -201,11 +208,15 @@ private static float[] getFloats(String s) { * the starting position of next number, whether it is ending with a '-'. */ private static void extract(String s, int start, ExtractFloatResult result) { - // Now looking for ' ', ',' or '-' from the start. + // Now looking for ' ', ',', '.' or '-' from the start. int currentIndex = start; boolean foundSeparator = false; - result.mEndWithNegSign = false; + result.mEndWithNegOrDot = false; + boolean secondDot = false; + boolean isExponential = false; for (; currentIndex < s.length(); currentIndex++) { + boolean isPrevExponential = isExponential; + isExponential = false; char currentChar = s.charAt(currentIndex); switch (currentChar) { case ' ': @@ -213,11 +224,25 @@ private static void extract(String s, int start, ExtractFloatResult result) { foundSeparator = true; break; case '-': - if (currentIndex != start) { + // The negative sign following a 'e' or 'E' is not a separator. + if (currentIndex != start && !isPrevExponential) { + foundSeparator = true; + result.mEndWithNegOrDot = true; + } + break; + case '.': + if (!secondDot) { + secondDot = true; + } else { + // This is the second dot, and it is considered as a separator. foundSeparator = true; - result.mEndWithNegSign = true; + result.mEndWithNegOrDot = true; } break; + case 'e': + case 'E': + isExponential = true; + break; } if (foundSeparator) { break; @@ -254,7 +279,7 @@ private PathDataNode(PathDataNode n) { * @param path The target Path object. */ public static void nodesToPath(PathDataNode[] node, Path path) { - float[] current = new float[4]; + float[] current = new float[6]; char previousCommand = 'm'; for (int i = 0; i < node.length; i++) { addCommand(path, current, previousCommand, node[i].mType, node[i].mParams); @@ -287,6 +312,8 @@ private static void addCommand(Path path, float[] current, float currentY = current[1]; float ctrlPointX = current[2]; float ctrlPointY = current[3]; + float currentSegmentStartX = current[4]; + float currentSegmentStartY = current[5]; float reflectiveCtrlPointX; float reflectiveCtrlPointY; @@ -294,7 +321,15 @@ private static void addCommand(Path path, float[] current, case 'z': case 'Z': path.close(); - return; + // Path is closed here, but we need to move the pen to the + // closed position. So we cache the segment's starting position, + // and restore it here. + currentX = currentSegmentStartX; + currentY = currentSegmentStartY; + ctrlPointX = currentSegmentStartX; + ctrlPointY = currentSegmentStartY; + path.moveTo(currentX, currentY); + break; case 'm': case 'M': case 'l': @@ -324,17 +359,22 @@ private static void addCommand(Path path, float[] current, incr = 7; break; } + for (int k = 0; k < val.length; k += incr) { switch (cmd) { case 'm': // moveto - Start a new sub-path (relative) path.rMoveTo(val[k + 0], val[k + 1]); currentX += val[k + 0]; currentY += val[k + 1]; + currentSegmentStartX = currentX; + currentSegmentStartY = currentY; break; case 'M': // moveto - Start a new sub-path path.moveTo(val[k + 0], val[k + 1]); currentX = val[k + 0]; currentY = val[k + 1]; + currentSegmentStartX = currentX; + currentSegmentStartY = currentY; break; case 'l': // lineto - Draw a line from the current point (relative) path.rLineTo(val[k + 0], val[k + 1]); @@ -346,10 +386,6 @@ private static void addCommand(Path path, float[] current, currentX = val[k + 0]; currentY = val[k + 1]; break; - case 'z': // closepath - Close the current subpath - case 'Z': // closepath - Close the current subpath - path.close(); - break; case 'h': // horizontal lineto - Draws a horizontal line (relative) path.rLineTo(val[k + 0], 0); currentX += val[k + 0]; @@ -500,6 +536,8 @@ private static void addCommand(Path path, float[] current, current[1] = currentY; current[2] = ctrlPointX; current[3] = ctrlPointY; + current[4] = currentSegmentStartX; + current[5] = currentSegmentStartY; } private static void drawArc(Path p, diff --git a/app/src/main/java/com/hippo/vectorold/util/DrawableUtils.java b/vector/src/main/java/com/hippo/vector/Utils.java similarity index 82% rename from app/src/main/java/com/hippo/vectorold/util/DrawableUtils.java rename to vector/src/main/java/com/hippo/vector/Utils.java index 9a6498dea..9bff8bda3 100644 --- a/app/src/main/java/com/hippo/vectorold/util/DrawableUtils.java +++ b/vector/src/main/java/com/hippo/vector/Utils.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2015 Hippo Seven + * Copyright 2015 Hippo Seven * * 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 + * 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, @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.hippo.vectorold.util; +package com.hippo.vector; import android.content.res.ColorStateList; import android.graphics.Color; @@ -22,17 +22,14 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; -public class DrawableUtils { - - public static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN; +public class Utils { /** * Ensures the tint filter is consistent with the current tint color and * mode. */ - public static PorterDuffColorFilter updateTintFilter(Drawable drawable, - PorterDuffColorFilter tintFilter, ColorStateList tint, - PorterDuff.Mode tintMode) { + public static PorterDuffColorFilter updateTintFilter(Drawable drawable, PorterDuffColorFilter tintFilter, + ColorStateList tint, PorterDuff.Mode tintMode) { if (tint == null || tintMode == null) { return null; } diff --git a/app/src/main/java/com/hippo/vectorold/drawable/VectorDrawable.java b/vector/src/main/java/com/hippo/vector/VectorDrawable.java similarity index 85% rename from app/src/main/java/com/hippo/vectorold/drawable/VectorDrawable.java rename to vector/src/main/java/com/hippo/vector/VectorDrawable.java index 13b7933a6..6f861fa2d 100644 --- a/app/src/main/java/com/hippo/vectorold/drawable/VectorDrawable.java +++ b/vector/src/main/java/com/hippo/vector/VectorDrawable.java @@ -1,19 +1,22 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2015 Hippo Seven * - * 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 + * 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 + * 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. + * 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.hippo.vectorold.drawable; +package com.hippo.vector; +import android.content.Context; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.TypedArray; @@ -29,6 +32,7 @@ import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.Region; import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; @@ -37,10 +41,6 @@ import android.util.Log; import android.util.Xml; -import com.hippo.ehviewer.R; -import com.hippo.vectorold.util.DrawableUtils; -import com.hippo.vectorold.util.PathParser; - import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -183,6 +183,8 @@ public class VectorDrawable extends Drawable { private static final String LOGTAG = VectorDrawable.class.getSimpleName(); + private static final Mode DEFAULT_TINT_MODE = Mode.SRC_IN; + private static final String SHAPE_CLIP_PATH = "clip-path"; private static final String SHAPE_GROUP = "group"; private static final String SHAPE_PATH = "path"; @@ -213,9 +215,9 @@ public VectorDrawable() { mVectorState = new VectorDrawableState(); } - private VectorDrawable(@NonNull VectorDrawableState state, Resources res) { + private VectorDrawable(@NonNull VectorDrawableState state) { mVectorState = state; - mTintFilter = DrawableUtils.updateTintFilter(this, mTintFilter, state.mTint, state.mTintMode); + mTintFilter = Utils.updateTintFilter(this, mTintFilter, state.mTint, state.mTintMode); } @Override @@ -227,7 +229,7 @@ public Drawable mutate() { return this; } - Object getTargetByName(String name) { + public Object getTargetByName(String name) { return mVectorState.mVPathRenderer.mVGTargetsMap.get(name); } @@ -238,7 +240,7 @@ public ConstantState getConstantState() { } @Override - public void draw(Canvas canvas) { + public void draw(@NonNull Canvas canvas) { final Rect bounds = getBounds(); if (bounds.width() == 0 || bounds.height() == 0) { // too small to draw @@ -246,13 +248,8 @@ public void draw(Canvas canvas) { } final int saveCount = canvas.save(); - final boolean needMirroring = needMirroring(); canvas.translate(bounds.left, bounds.top); - if (needMirroring) { - canvas.translate(bounds.width(), 0); - canvas.scale(-1.0f, 1.0f); - } // Color filters always override tint filters. final ColorFilter colorFilter = mColorFilter == null ? mTintFilter : mColorFilter; @@ -304,17 +301,17 @@ public void setTintList(ColorStateList tint) { final VectorDrawableState state = mVectorState; if (state.mTint != tint) { state.mTint = tint; - mTintFilter = DrawableUtils.updateTintFilter(this, mTintFilter, tint, state.mTintMode); + mTintFilter = Utils.updateTintFilter(this, mTintFilter, tint, state.mTintMode); invalidateSelf(); } } @Override - public void setTintMode(Mode tintMode) { + public void setTintMode(@NonNull Mode tintMode) { final VectorDrawableState state = mVectorState; if (state.mTintMode != tintMode) { state.mTintMode = tintMode; - mTintFilter = DrawableUtils.updateTintFilter(this, mTintFilter, state.mTint, tintMode); + mTintFilter = Utils.updateTintFilter(this, mTintFilter, state.mTint, tintMode); invalidateSelf(); } } @@ -329,7 +326,7 @@ public boolean isStateful() { protected boolean onStateChange(int[] stateSet) { final VectorDrawableState state = mVectorState; if (state.mTint != null && state.mTintMode != null) { - mTintFilter = DrawableUtils.updateTintFilter(this, mTintFilter, state.mTint, state.mTintMode); + mTintFilter = Utils.updateTintFilter(this, mTintFilter, state.mTint, state.mTintMode); invalidateSelf(); return true; } @@ -372,10 +369,9 @@ public float getPixelSize() { return Math.min(scaleX, scaleY); } - /** @hide */ - public static VectorDrawable create(Resources resources, int rid) { + public static VectorDrawable create(Context context, int rid) { try { - final XmlPullParser parser = resources.getXml(rid); + final XmlPullParser parser = context.getResources().getXml(rid); final AttributeSet attrs = Xml.asAttributeSet(parser); int type; while ((type=parser.next()) != XmlPullParser.START_TAG && @@ -386,16 +382,20 @@ public static VectorDrawable create(Resources resources, int rid) { throw new XmlPullParserException("No start tag found"); } + final String name = parser.getName(); + if (!"vector".equals(name)) { + throw new IllegalStateException("It is not vector"); + } + final VectorDrawable drawable = new VectorDrawable(); - drawable.inflate(resources, parser, attrs); + drawable.inflate(context, parser, attrs); return drawable; } catch (XmlPullParserException e) { - Log.e(LOGTAG, "parser error", e); + throw new IllegalStateException("parser error", e); } catch (IOException e) { - Log.e(LOGTAG, "parser error", e); + throw new IllegalStateException("parser error", e); } - return null; } private static int applyAlpha(int color, float alpha) { @@ -405,21 +405,19 @@ private static int applyAlpha(int color, float alpha) { return color; } - @Override - public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs) + public void inflate(Context context, XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException, IOException { final VectorDrawableState state = mVectorState; - final VPathRenderer pathRenderer = new VPathRenderer(); - state.mVPathRenderer = pathRenderer; + state.mVPathRenderer = new VPathRenderer(); - final TypedArray a = res.obtainAttributes(attrs, R.styleable.VectorDrawable); + final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VectorDrawable); updateStateFromTypedArray(a); a.recycle(); state.mCacheDirty = true; - inflateInternal(res, parser, attrs); + inflateInternal(context, parser, attrs); - mTintFilter = DrawableUtils.updateTintFilter(this, mTintFilter, state.mTint, state.mTintMode); + mTintFilter = Utils.updateTintFilter(this, mTintFilter, state.mTint, state.mTintMode); } private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException { @@ -431,7 +429,7 @@ private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserExcepti final int tintMode = a.getInt(R.styleable.VectorDrawable_tintMode, -1); if (tintMode != -1) { - state.mTintMode = DrawableUtils.parseTintMode(tintMode, Mode.SRC_IN); + state.mTintMode = Utils.parseTintMode(tintMode, Mode.SRC_IN); } final ColorStateList tint = a.getColorStateList(R.styleable.VectorDrawable_tint); @@ -439,8 +437,7 @@ private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserExcepti state.mTint = tint; } - state.mAutoMirrored = a.getBoolean( - R.styleable.VectorDrawable_autoMirrored, state.mAutoMirrored); + setAllowCaching(a.getBoolean(R.styleable.VectorDrawable_allowCaching, true)); pathRenderer.mViewportWidth = a.getFloat( R.styleable.VectorDrawable_viewportWidth, pathRenderer.mViewportWidth); @@ -479,7 +476,7 @@ private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserExcepti } } - private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs) + private void inflateInternal(Context context, XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException, IOException { final VectorDrawableState state = mVectorState; final VPathRenderer pathRenderer = state.mVPathRenderer; @@ -498,7 +495,7 @@ private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet a if (SHAPE_PATH.equals(tagName)) { final VFullPath path = new VFullPath(); - path.inflate(res, attrs); + path.inflate(context, attrs); currentGroup.mChildren.add(path); if (path.getPathName() != null) { pathRenderer.mVGTargetsMap.put(path.getPathName(), path); @@ -507,7 +504,7 @@ private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet a state.mChangingConfigurations |= path.mChangingConfigurations; } else if (SHAPE_CLIP_PATH.equals(tagName)) { final VClipPath path = new VClipPath(); - path.inflate(res, attrs); + path.inflate(context, attrs); currentGroup.mChildren.add(path); if (path.getPathName() != null) { pathRenderer.mVGTargetsMap.put(path.getPathName(), path); @@ -515,7 +512,7 @@ private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet a state.mChangingConfigurations |= path.mChangingConfigurations; } else if (SHAPE_GROUP.equals(tagName)) { VGroup newChildGroup = new VGroup(); - newChildGroup.inflate(res, attrs); + newChildGroup.inflate(context, attrs); currentGroup.mChildren.add(newChildGroup); groupStack.push(newChildGroup); if (newChildGroup.getGroupName() != null) { @@ -573,39 +570,20 @@ public int getChangingConfigurations() { return super.getChangingConfigurations() | mVectorState.mChangingConfigurations; } - void setAllowCaching(boolean allowCaching) { + public void setAllowCaching(boolean allowCaching) { mAllowCaching = allowCaching; } - private boolean needMirroring() { - return isAutoMirrored(); - } - - @Override - public void setAutoMirrored(boolean mirrored) { - if (mVectorState.mAutoMirrored != mirrored) { - mVectorState.mAutoMirrored = mirrored; - invalidateSelf(); - } - } - - @Override - public boolean isAutoMirrored() { - return mVectorState.mAutoMirrored; - } - private static class VectorDrawableState extends ConstantState { int mChangingConfigurations; VPathRenderer mVPathRenderer; ColorStateList mTint = null; - Mode mTintMode = DrawableUtils.DEFAULT_TINT_MODE; - boolean mAutoMirrored; + Mode mTintMode = DEFAULT_TINT_MODE; Bitmap mCachedBitmap; ColorStateList mCachedTint; Mode mCachedTintMode; int mCachedRootAlpha; - boolean mCachedAutoMirrored; boolean mCacheDirty; /** Temporary paint object used to draw cached bitmaps. */ @@ -624,7 +602,6 @@ public VectorDrawableState(VectorDrawableState copy) { } mTint = copy.mTint; mTintMode = copy.mTintMode; - mAutoMirrored = copy.mAutoMirrored; } } @@ -683,7 +660,6 @@ public boolean canReuseCache() { if (!mCacheDirty && mCachedTint == mTint && mCachedTintMode == mTintMode - && mCachedAutoMirrored == mAutoMirrored && mCachedRootAlpha == mVPathRenderer.getRootAlpha()) { return true; } @@ -696,7 +672,6 @@ public void updateCacheStates() { mCachedTint = mTint; mCachedTintMode = mTintMode; mCachedRootAlpha = mVPathRenderer.getRootAlpha(); - mCachedAutoMirrored = mAutoMirrored; mCacheDirty = false; } @@ -704,14 +679,16 @@ public VectorDrawableState() { mVPathRenderer = new VPathRenderer(); } + @NonNull @Override public Drawable newDrawable() { - return new VectorDrawable(this, null); + return new VectorDrawable(this); } + @NonNull @Override public Drawable newDrawable(Resources res) { - return new VectorDrawable(this, res); + return new VectorDrawable(this); } @Override @@ -737,7 +714,6 @@ private static class VPathRenderer { // is no need for deep copying. private final Path mPath; private final Path mRenderPath; - private static final Matrix IDENTITY_MATRIX = new Matrix(); private final Matrix mFinalPathMatrix = new Matrix(); private Paint mStrokePaint; @@ -755,7 +731,7 @@ private static class VPathRenderer { int mRootAlpha = 0xFF; String mRootName = null; - final ArrayMap mVGTargetsMap = new ArrayMap(); + final ArrayMap mVGTargetsMap = new ArrayMap<>(); public VPathRenderer() { mRootGroup = new VGroup(); @@ -915,7 +891,7 @@ private static class VGroup { ///////////////////////////////////////////////////// // Variables below need to be copied (deep copy if applicable) for mutation. - final ArrayList mChildren = new ArrayList(); + final ArrayList mChildren = new ArrayList<>(); private float mRotate = 0; private float mPivotX = 0; @@ -954,7 +930,7 @@ public VGroup(VGroup copy, ArrayMap targetsMap) { VGroup copyGroup = (VGroup) copyChild; mChildren.add(new VGroup(copyGroup, targetsMap)); } else { - VPath newPath = null; + VPath newPath; if (copyChild instanceof VFullPath) { newPath = new VFullPath((VFullPath) copyChild); } else if (copyChild instanceof VClipPath) { @@ -981,8 +957,8 @@ public Matrix getLocalMatrix() { return mLocalMatrix; } - public void inflate(Resources res, AttributeSet attrs) { - final TypedArray a = res.obtainAttributes(attrs, + public void inflate(Context context, AttributeSet attrs) { + final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VectorDrawableGroup); updateStateFromTypedArray(a); a.recycle(); @@ -1173,8 +1149,8 @@ public VClipPath(VClipPath copy) { super(copy); } - public void inflate(Resources r, AttributeSet attrs) { - final TypedArray a = r.obtainAttributes(attrs, + public void inflate(Context context, AttributeSet attrs) { + final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VectorDrawableClipPath); updateStateFromTypedArray(a); a.recycle(); @@ -1204,7 +1180,7 @@ public boolean isClipPath() { /** * Normal path, which contains all the fill / paint information. */ - private static class VFullPath extends VPath { + public static class VFullPath extends VPath { ///////////////////////////////////////////////////// // Variables below need to be copied (deep copy if applicable) for mutation. int mStrokeColor = Color.TRANSPARENT; @@ -1228,7 +1204,6 @@ public VFullPath() { public VFullPath(VFullPath copy) { super(copy); - mStrokeColor = copy.mStrokeColor; mStrokeWidth = copy.mStrokeWidth; mStrokeAlpha = copy.mStrokeAlpha; @@ -1270,8 +1245,8 @@ private Paint.Join getStrokeLineJoin(int id, Paint.Join defValue) { } } - public void inflate(Resources r, AttributeSet attrs) { - final TypedArray a = r.obtainAttributes(attrs, + public void inflate(Context context, AttributeSet attrs) { + final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VectorDrawablePath); updateStateFromTypedArray(a); a.recycle(); @@ -1317,83 +1292,264 @@ private void updateStateFromTypedArray(TypedArray a) { /* Setters and Getters, used by animator from AnimatedVectorDrawable. */ @SuppressWarnings("unused") - int getStrokeColor() { + public int getStrokeColor() { return mStrokeColor; } @SuppressWarnings("unused") - void setStrokeColor(int strokeColor) { + public void setStrokeColor(int strokeColor) { mStrokeColor = strokeColor; } @SuppressWarnings("unused") - float getStrokeWidth() { + public float getStrokeWidth() { return mStrokeWidth; } @SuppressWarnings("unused") - void setStrokeWidth(float strokeWidth) { + public void setStrokeWidth(float strokeWidth) { mStrokeWidth = strokeWidth; } @SuppressWarnings("unused") - float getStrokeAlpha() { + public float getStrokeAlpha() { return mStrokeAlpha; } @SuppressWarnings("unused") - void setStrokeAlpha(float strokeAlpha) { + public void setStrokeAlpha(float strokeAlpha) { mStrokeAlpha = strokeAlpha; } @SuppressWarnings("unused") - int getFillColor() { + public int getFillColor() { return mFillColor; } @SuppressWarnings("unused") - void setFillColor(int fillColor) { + public void setFillColor(int fillColor) { mFillColor = fillColor; } @SuppressWarnings("unused") - float getFillAlpha() { + public float getFillAlpha() { return mFillAlpha; } @SuppressWarnings("unused") - void setFillAlpha(float fillAlpha) { + public void setFillAlpha(float fillAlpha) { mFillAlpha = fillAlpha; } @SuppressWarnings("unused") - float getTrimPathStart() { + public float getTrimPathStart() { return mTrimPathStart; } @SuppressWarnings("unused") - void setTrimPathStart(float trimPathStart) { + public void setTrimPathStart(float trimPathStart) { mTrimPathStart = trimPathStart; } @SuppressWarnings("unused") - float getTrimPathEnd() { + public float getTrimPathEnd() { return mTrimPathEnd; } @SuppressWarnings("unused") - void setTrimPathEnd(float trimPathEnd) { + public void setTrimPathEnd(float trimPathEnd) { mTrimPathEnd = trimPathEnd; } @SuppressWarnings("unused") - float getTrimPathOffset() { + public float getTrimPathOffset() { return mTrimPathOffset; } @SuppressWarnings("unused") - void setTrimPathOffset(float trimPathOffset) { + public void setTrimPathOffset(float trimPathOffset) { mTrimPathOffset = trimPathOffset; } } + + public final static Matrix IDENTITY_MATRIX = new Matrix() { + void oops() { + throw new IllegalStateException("Matrix can not be modified"); + } + + @Override + public void set(Matrix src) { + oops(); + } + + @Override + public void reset() { + oops(); + } + + @Override + public void setTranslate(float dx, float dy) { + oops(); + } + + @Override + public void setScale(float sx, float sy, float px, float py) { + oops(); + } + + @Override + public void setScale(float sx, float sy) { + oops(); + } + + @Override + public void setRotate(float degrees, float px, float py) { + oops(); + } + + @Override + public void setRotate(float degrees) { + oops(); + } + + @Override + public void setSinCos(float sinValue, float cosValue, float px, float py) { + oops(); + } + + @Override + public void setSinCos(float sinValue, float cosValue) { + oops(); + } + + @Override + public void setSkew(float kx, float ky, float px, float py) { + oops(); + } + + @Override + public void setSkew(float kx, float ky) { + oops(); + } + + @Override + public boolean setConcat(@NonNull Matrix a, @NonNull Matrix b) { + oops(); + return false; + } + + @Override + public boolean preTranslate(float dx, float dy) { + oops(); + return false; + } + + @Override + public boolean preScale(float sx, float sy, float px, float py) { + oops(); + return false; + } + + @Override + public boolean preScale(float sx, float sy) { + oops(); + return false; + } + + @Override + public boolean preRotate(float degrees, float px, float py) { + oops(); + return false; + } + + @Override + public boolean preRotate(float degrees) { + oops(); + return false; + } + + @Override + public boolean preSkew(float kx, float ky, float px, float py) { + oops(); + return false; + } + + @Override + public boolean preSkew(float kx, float ky) { + oops(); + return false; + } + + @Override + public boolean preConcat(@NonNull Matrix other) { + oops(); + return false; + } + + @Override + public boolean postTranslate(float dx, float dy) { + oops(); + return false; + } + + @Override + public boolean postScale(float sx, float sy, float px, float py) { + oops(); + return false; + } + + @Override + public boolean postScale(float sx, float sy) { + oops(); + return false; + } + + @Override + public boolean postRotate(float degrees, float px, float py) { + oops(); + return false; + } + + @Override + public boolean postRotate(float degrees) { + oops(); + return false; + } + + @Override + public boolean postSkew(float kx, float ky, float px, float py) { + oops(); + return false; + } + + @Override + public boolean postSkew(float kx, float ky) { + oops(); + return false; + } + + @Override + public boolean postConcat(@NonNull Matrix other) { + oops(); + return false; + } + + @Override + public boolean setRectToRect(@NonNull RectF src, @NonNull RectF dst, @NonNull ScaleToFit stf) { + oops(); + return false; + } + + @Override + public boolean setPolyToPoly(@NonNull float[] src, int srcIndex, @NonNull float[] dst, int dstIndex, + int pointCount) { + oops(); + return false; + } + + @Override + public void setValues(@NonNull float[] values) { + oops(); + } + }; } diff --git a/vector/src/main/res/values/attrs.xml b/vector/src/main/res/values/attrs.xml new file mode 100644 index 000000000..c0e332b4c --- /dev/null +++ b/vector/src/main/res/values/attrs.xml @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/test/java/com/hippo/vector/ExampleUnitTest.java b/vector/src/test/java/com/hippo/vector/ExampleUnitTest.java new file mode 100644 index 000000000..32b2c81a2 --- /dev/null +++ b/vector/src/test/java/com/hippo/vector/ExampleUnitTest.java @@ -0,0 +1,15 @@ +package com.hippo.vector; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * To work on unit tests, switch the Test Artifact in the Build Variants view. + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/vector/vector.iml b/vector/vector.iml new file mode 100644 index 000000000..5780ae9bd --- /dev/null +++ b/vector/vector.iml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file