diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index a484507f7..f1d02f3b7 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -28,7 +28,7 @@ void set*(***); *** get*(); } --keepclassmembers public class * extends com.hippo.drawable.VectorDrawable.VGroup { +-keepclassmembers public class * extends com.hippo.vectorold.drawable.VectorDrawable.VGroup { void set*(***); *** get*(); } diff --git a/app/src/main/java/android/content/res/VectorResources.java b/app/src/main/java/android/content/res/VectorResources.java index f711181b6..7ed07dab7 100644 --- a/app/src/main/java/android/content/res/VectorResources.java +++ b/app/src/main/java/android/content/res/VectorResources.java @@ -23,8 +23,8 @@ import android.util.AttributeSet; import android.util.TypedValue; import android.util.Xml; -import com.hippo.drawable.AnimatedVectorDrawable; -import com.hippo.drawable.VectorDrawable; +import com.hippo.vectorold.drawable.AnimatedVectorDrawable; +import com.hippo.vectorold.drawable.VectorDrawable; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; diff --git a/app/src/main/java/com/hippo/ehviewer/EhApplication.java b/app/src/main/java/com/hippo/ehviewer/EhApplication.java index 81c03e171..33dcc2b76 100644 --- a/app/src/main/java/com/hippo/ehviewer/EhApplication.java +++ b/app/src/main/java/com/hippo/ehviewer/EhApplication.java @@ -20,7 +20,7 @@ import android.content.Context; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.imagepipeline.backends.okhttp.OkHttpImagePipelineConfigFactory; import com.facebook.imagepipeline.core.ImagePipelineConfig; -import com.hippo.content.VectorContext; +import com.hippo.vectorold.content.VectorContext; import com.hippo.ehviewer.network.EhOkHttpClient; import com.hippo.ehviewer.util.Config; import com.hippo.scene.SceneApplication; diff --git a/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java index 645ef4386..d39484eb1 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java @@ -26,7 +26,7 @@ import android.view.Gravity; import android.view.View; import android.widget.AdapterView; -import com.hippo.content.VectorContext; +import com.hippo.vectorold.content.VectorContext; import com.hippo.ehviewer.Constants; import com.hippo.ehviewer.R; import com.hippo.ehviewer.ui.scene.GalleryListScene; diff --git a/app/src/main/java/com/hippo/graphics/JPath.java b/app/src/main/java/com/hippo/graphics/JPath.java deleted file mode 100644 index 1fc2ec3f6..000000000 --- a/app/src/main/java/com/hippo/graphics/JPath.java +++ /dev/null @@ -1,641 +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 - * 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.graphics; - -import java.util.LinkedList; -import java.util.List; - -public class JPath { - - private List mActionList = new LinkedList<>(); - - /** startX, startY, length**/ - private float[] mTemp = new float[2]; - - { - mTemp[0] = 0f; - mTemp[1] = 0f; - } - - public void close() { - // Empty - } - - /** - * Set the beginning of the next contour to the point (x,y). - * - * @param x The x-coordinate of the start of a new contour - * @param y The y-coordinate of the start of a new contour - */ - public void moveTo(float x, float y) { - mActionList.add(new MoveAction(x, y)); - } - - /** - * Set the beginning of the next contour relative to the last point on the - * previous contour. If there is no previous contour, this is treated the - * same as moveTo(). - * - * @param dx The amount to add to the x-coordinate of the end of the - * previous contour, to specify the start of a new contour - * @param dy The amount to add to the y-coordinate of the end of the - * previous contour, to specify the start of a new contour - */ - public void rMoveTo(float dx, float dy) { - mActionList.add(new RMoveAction(dx, dy)); - } - - /** - * Add a line from the last point to the specified point (x,y). - * If no moveTo() call has been made for this contour, the first point is - * automatically set to (0,0). - * - * @param x The x-coordinate of the end of a line - * @param y The y-coordinate of the end of a line - */ - public void lineTo(float x, float y) { - mActionList.add(new LineToAction(x, y)); - } - - /** - * Same as lineTo, but the coordinates are considered relative to the last - * point on this contour. If there is no previous point, then a moveTo(0,0) - * is inserted automatically. - * - * @param dx The amount to add to the x-coordinate of the previous point on - * this contour, to specify a line - * @param dy The amount to add to the y-coordinate of the previous point on - * this contour, to specify a line - */ - public void rLineTo(float dx, float dy) { - mActionList.add(new RLineToAction(dx, dy)); - } - - /** - * Add a quadratic bezier from the last point, approaching control point - * (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for - * this contour, the first point is automatically set to (0,0). - * - * @param x1 The x-coordinate of the control point on a quadratic curve - * @param y1 The y-coordinate of the control point on a quadratic curve - * @param x2 The x-coordinate of the end point on a quadratic curve - * @param y2 The y-coordinate of the end point on a quadratic curve - */ - public void quadTo(float x1, float y1, float x2, float y2) { - mActionList.add(new QuadToAction(x1, y1, x2, y2)); - } - - /** - * Same as quadTo, but the coordinates are considered relative to the last - * point on this contour. If there is no previous point, then a moveTo(0,0) - * is inserted automatically. - * - * @param dx1 The amount to add to the x-coordinate of the last point on - * this contour, for the control point of a quadratic curve - * @param dy1 The amount to add to the y-coordinate of the last point on - * this contour, for the control point of a quadratic curve - * @param dx2 The amount to add to the x-coordinate of the last point on - * this contour, for the end point of a quadratic curve - * @param dy2 The amount to add to the y-coordinate of the last point on - * this contour, for the end point of a quadratic curve - */ - public void rQuadTo(float dx1, float dy1, float dx2, float dy2) { - mActionList.add(new RQuadToAction(dx1, dy1, dx2, dy2)); - } - - /** - * Add a cubic bezier from the last point, approaching control points - * (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been - * made for this contour, the first point is automatically set to (0,0). - * - * @param x1 The x-coordinate of the 1st control point on a cubic curve - * @param y1 The y-coordinate of the 1st control point on a cubic curve - * @param x2 The x-coordinate of the 2nd control point on a cubic curve - * @param y2 The y-coordinate of the 2nd control point on a cubic curve - * @param x3 The x-coordinate of the end point on a cubic curve - * @param y3 The y-coordinate of the end point on a cubic curve - */ - public void cubicTo(float x1, float y1, float x2, float y2, - float x3, float y3) { - mActionList.add(new CubicToAction(x1, y1, x2, y2, x3, y3)); - } - - /** - * Same as cubicTo, but the coordinates are considered relative to the - * current point on this contour. If there is no previous point, then a - * moveTo(0,0) is inserted automatically. - */ - public void rCubicTo(float x1, float y1, float x2, float y2, - float x3, float y3) { - mActionList.add(new RCubicToAction(x1, y1, x2, y2, x3, y3)); - } - - /** - * Approximate the Path with a series of line segments. - * This returns float[] with the array containing point components. - * There are three components for each point, in order: - * - *

Two points may share the same fraction along its length when there is - * a move action within the Path.

- * - * @param acceptableError The acceptable error for a line on the - * Path. Typically this would be 0.5 so that - * the error is less than half a pixel. - * @return An array of components for points approximating the Path. - */ - public float[] approximate(float acceptableError) { - PointMap pm = new PointMap(); - for (PathAction pa : mActionList) { - pa.approximate(pm, mTemp, acceptableError); - } - return pm.generate(); - } - - /** - * Returns true if the path is empty (contains no lines or curves) - * - * @return true if the path is empty (contains no lines or curves) - */ - public boolean isEmpty() { - return mActionList.isEmpty(); - } - - /** - * Clear any lines and curves from the path, making it empty. - * This does NOT change the fill-type setting. - */ - public void reset() { - mActionList.clear(); - } - - private static final class PointMap { - - private int size = 0; - - private Link firstLink; - private Link lastLink; - - float totalLength = 0f; - - private static final class Link { - /** It is only for bezier **/ - float t; - float x; - float y; - /** It should be Length first **/ - float f = -1; - - private Link previous, next; - - Link(float t, float x, float y, float f, Link p, Link n) { - this.t = t; - this.x = x; - this.y = y; - this.f = f; - this.previous = p; - this.next = n; - } - } - - public static final class Iterator { - - final PointMap parent; - Link link; - - private Iterator(PointMap p, Link l) { - parent = p; - link = l; - } - - boolean hasNext() { - return link.next != null; - } - - Iterator nextIterator() { - if (hasNext()) { - return new Iterator(parent, link.next); - } else { - return null; - } - } - - // Move iterator to the new data - void addBefore(float t, float x, float y, float f) { - Link p = link.previous; - Link l = new Link(t, x, y, f, p, link); - link.previous = l; - p.next = l; - link = l; - parent.size++; - } - } - - public void add(float t, float x, float y, float f) { - Link link = new Link(t, x, y, f, null, null); - if (lastLink != null) { - link.previous = lastLink; - lastLink.next = link; - } - lastLink = link; - if (firstLink == null) { - firstLink = link; - } - size++; - } - - // Get a iterator at first data or null - public Iterator iterator() { - if (firstLink != null) { - return new Iterator(this, firstLink); - } else { - return null; - } - } - - public Iterator lastIterator() { - if (lastLink != null) { - return new Iterator(this, lastLink); - } else { - return null; - } - } - - public float[] generate() { - int index = 0; - float[] result = new float[size * 3]; - for (Link link = firstLink; link != null; link = link.next) { - result[index++] = link.f / totalLength; - result[index++] = link.x; - result[index++] = link.y; - } - return result; - } - } - - - private abstract static class PathAction { - public abstract void approximate(PointMap pointMap, float[] startPoint, float acceptableError); - } - - private static class MoveAction extends PathAction { - - private float mX; - private float mY; - - public MoveAction(float x, float y) { - mX = x; - mY = y; - } - - @Override - public void approximate(PointMap pointMap, float[] startPoint, float acceptableError) { - float x = mX; - float y = mY; - pointMap.add(0f, x, y, pointMap.totalLength); - startPoint[0] = x; - startPoint[1] = y; - } - } - - private static class RMoveAction extends PathAction { - - private float mDx; - private float mDy; - - public RMoveAction(float dx, float dy) { - mDx = dx; - mDy = dy; - } - - @Override - public void approximate(PointMap pointMap, float[] startPoint, float acceptableError) { - float x = startPoint[0] + mDx; - float y = startPoint[1] + mDy; - pointMap.add(0f, x, y, pointMap.totalLength); - startPoint[0] = x; - startPoint[1] = y; - } - } - - private static class LineToAction extends PathAction { - - private float mX; - private float mY; - - public LineToAction(float x, float y) { - mX = x; - mY = y; - } - - @Override - public void approximate(PointMap pointMap, float[] startPoint, float acceptableError) { - if (pointMap.size == 0) { - // No start point in map, just add it - pointMap.add(0f, startPoint[0], startPoint[1], 0f); - } - - float x = mX; - float y = mY; - float length = dist(startPoint[0], startPoint[1], x, y) + - pointMap.totalLength; - pointMap.add(0f, x, y, length); - pointMap.totalLength = length; - startPoint[0] = x; - startPoint[1] = y; - } - } - - private static class RLineToAction extends PathAction { - - private float mDx; - private float mDy; - - public RLineToAction(float dx, float dy) { - mDx = dx; - mDy = dy; - } - - @Override - public void approximate(PointMap pointMap, float[] startPoint, float acceptableError) { - if (pointMap.size == 0) { - // No start point in map, just add it - pointMap.add(0f, startPoint[0], startPoint[1], 0f); - } - - float x = startPoint[0] + mDx; - float y = startPoint[1] + mDy; - float length = (float) Math.hypot(mDx, mDy) + - pointMap.totalLength; - pointMap.add(0f, x, y, length); - pointMap.totalLength = length; - startPoint[0] = x; - startPoint[1] = y; - } - } - - private static class QuadToAction extends PathAction { - - private float mX1; - private float mY1; - private float mX2; - private float mY2; - - public QuadToAction(float x1, float y1, float x2, float y2) { - mX1 = x1; - mY1 = y1; - mX2 = x2; - mY2 = y2; - } - - @Override - public void approximate(PointMap pointMap, float[] startPoint, float acceptableError) { - float[] control = new float[]{ - startPoint[0], startPoint[1], - mX1, mY1, - mX2, mY2 - }; - bezierApproximate(pointMap, control, acceptableError, false); - startPoint[0] = control[0]; - startPoint[1] = control[1]; - } - } - - private static class RQuadToAction extends PathAction { - - private float mDx1; - private float mDy1; - private float mDx2; - private float mDy2; - - public RQuadToAction(float dx1, float dy1, float dx2, float dy2) { - mDx1 = dx1; - mDy1 = dy1; - mDx2 = dx2; - mDy2 = dy2; - } - - @Override - public void approximate(PointMap pointMap, float[] startPoint, float acceptableError) { - float startX = startPoint[0]; - float startY = startPoint[1]; - float[] control = new float[]{ - startX, startY, - startX + mDx1, startY + mDy1, - startX + mDx2, startY + mDy2 - }; - bezierApproximate(pointMap, control, acceptableError, false); - startPoint[0] = control[0]; - startPoint[1] = control[1]; - } - } - - private static class CubicToAction extends PathAction { - - private float mX1; - private float mY1; - private float mX2; - private float mY2; - private float mX3; - private float mY3; - - public CubicToAction(float x1, float y1, float x2, float y2, float x3, float y3) { - mX1 = x1; - mY1 = y1; - mX2 = x2; - mY2 = y2; - mX3 = x3; - mY3 = y3; - } - - @Override - public void approximate(PointMap pointMap, float[] startPoint, float acceptableError) { - float[] control = new float[]{ - startPoint[0], startPoint[1], - mX1, mY1, - mX2, mY2, - mX3, mY3 - }; - bezierApproximate(pointMap, control, acceptableError, true); - startPoint[0] = control[0]; - startPoint[1] = control[1]; - } - } - - private static class RCubicToAction extends PathAction { - - private float mDx1; - private float mDy1; - private float mDx2; - private float mDy2; - private float mDx3; - private float mDy3; - - public RCubicToAction(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) { - mDx1 = dx1; - mDy1 = dy1; - mDx2 = dx2; - mDy2 = dy2; - mDx3 = dx3; - mDy3 = dy3; - } - - @Override - public void approximate(PointMap pointMap, float[] startPoint, float acceptableError) { - float startX = startPoint[0]; - float startY = startPoint[1]; - float[] control = new float[]{ - startX, startY, - startX + mDx1, startY + mDy1, - startX + mDx2, startY + mDy2, - startX + mDx3, startY + mDy3, - }; - bezierApproximate(pointMap, control, acceptableError, true); - startPoint[0] = control[0]; - startPoint[1] = control[1]; - } - } - - - // Divides Bezier curves until linear interpolation is very close to accurate, using - // errorSquared as a metric. Cubic Bezier curves can have an inflection point that improperly - // short-circuit subdivision. If you imagine an S shape, the top and bottom points being the - // starting and end points, linear interpolation would mark the center where the curve places - // the point. It is clearly not the case that we can linearly interpolate at that point. - // doubleCheckDivision forces a second examination between subdivisions to ensure that linear - // interpolation works. - private static void bezierApproximate(PointMap pointMap, float[] control, - float acceptableError, boolean isCubic) { - float errorSquared = acceptableError * acceptableError; - - if (pointMap.size == 0) { - // No start point in map, just add it - pointMap.add(0f, control[0], control[1], 0f); - } - - PointMap.Iterator iter = pointMap.lastIterator(); - // Make sure start t is 0 - iter.link.t = 0f; - - // Add end point - if (isCubic) { - pointMap.add(1f, control[6], control[7], 0); - } else { - pointMap.add(1f, control[4], control[5], 0); - } - - // Get next iterator - PointMap.Iterator next = iter.nextIterator(); - - boolean doubleCheckDivision = isCubic; - while (next != null) { - boolean needsSubdivision; - - do { - PointMap.Link iterLink = iter.link; - PointMap.Link nextLink = next.link; - - float midT = (iterLink.t + nextLink.t) / 2; - float midX = (iterLink.x + nextLink.x) / 2; - float midY = (iterLink.y + nextLink.y) / 2; - - float midPointX = bezierX(midT, control, isCubic); - float midPointY = bezierY(midT, control, isCubic); - - needsSubdivision = isOutOfErrorSquared(midX, midY, midPointX, midPointY, errorSquared); - - if (!needsSubdivision && doubleCheckDivision) { - float quarterT = (iterLink.t + midT) / 2; - float quarterX = (iterLink.x + midPointX) / 2; - float quarterY = (iterLink.y + midPointY) / 2; - - float quarterPointX = bezierX(quarterT, control, isCubic); - float quarterPointY = bezierY(quarterT, control, isCubic); - - needsSubdivision = isOutOfErrorSquared(quarterX, quarterY, quarterPointX, quarterPointY, errorSquared); - if (needsSubdivision) { - // Found an inflection point. No need to double-check. - doubleCheckDivision = false; - } - } - if (needsSubdivision) { - // Add length soon - next.addBefore(midT, midPointX, midPointY, 0); - } else { - float length = dist(iterLink.x, iterLink.y, nextLink.x, nextLink.y); - iterLink.f = pointMap.totalLength; - pointMap.totalLength += length; - } - } while (needsSubdivision); - - iter = next; - next = next.nextIterator(); - } - - PointMap.Link iterLink = iter.link; - iterLink.f = pointMap.totalLength; - control[0] = iterLink.x; - control[1] = iterLink.y; - } - - private static boolean isOutOfErrorSquared(float midX, float midY, - float midPointX, float midPointY, float errorSquared) { - float xError = midPointX - midX; - float yError = midPointY - midY; - float midErrorSquared = (xError * xError) + (yError * yError); - return midErrorSquared > errorSquared; - } - - private static float bezierX(float t, float[] control, boolean isCubic) { - if (isCubic) { - return cubicCoordinateCalculation(t, control[0], control[2], control[4], control[6]); - } else { - return quadraticCoordinateCalculation(t, control[0], control[2], control[4]); - } - } - - private static float bezierY(float t, float[] control, boolean isCubic) { - if (isCubic) { - return cubicCoordinateCalculation(t, control[1], control[3], control[5], control[7]); - } else { - return quadraticCoordinateCalculation(t, control[1], control[3], control[5]); - } - } - - private static float quadraticCoordinateCalculation(float t, float p0, float p1, float p2) { - float oneMinusT = 1 - t; - return oneMinusT * ((oneMinusT * p0) + (t * p1)) + t * ((oneMinusT * p1) + (t * p2)); - } - - private static float cubicCoordinateCalculation(float t, float p0, float p1, float p2, float p3) { - float oneMinusT = 1 - t; - float oneMinusTSquared = oneMinusT * oneMinusT; - float oneMinusTCubed = oneMinusTSquared * oneMinusT; - float tSquared = t * t; - float tCubed = tSquared * t; - return (oneMinusTCubed * p0) + (3 * oneMinusTSquared * t * p1) - + (3 * oneMinusT * tSquared * p2) + (tCubed * p3); - } - - private static float dist(float x1, float y1, float x2, float y2) { - final float x = (x2 - x1); - final float y = (y2 - y1); - return (float) Math.hypot(x, y); - } -} diff --git a/app/src/main/java/com/hippo/util/DrawableUtils.java b/app/src/main/java/com/hippo/util/DrawableUtils.java index e450772e6..0b7872b9f 100644 --- a/app/src/main/java/com/hippo/util/DrawableUtils.java +++ b/app/src/main/java/com/hippo/util/DrawableUtils.java @@ -15,10 +15,6 @@ package com.hippo.util; -import android.content.res.ColorStateList; -import android.graphics.Color; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; import android.os.Build; @@ -26,39 +22,6 @@ import com.hippo.widget.Hotspotable; public class DrawableUtils { - public static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN; - - /** - * 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) { - if (tint == null || tintMode == null) { - return null; - } - - final int color = tint.getColorForState(drawable.getState(), Color.TRANSPARENT); - return new PorterDuffColorFilter(color, tintMode); - } - - /** - * Parses a {@link PorterDuff.Mode} from a tintMode - * attribute's enum value. - */ - public static PorterDuff.Mode parseTintMode(int value, PorterDuff.Mode defaultMode) { - switch (value) { - case 3: return PorterDuff.Mode.SRC_OVER; - case 5: return PorterDuff.Mode.SRC_IN; - case 9: return PorterDuff.Mode.SRC_ATOP; - case 14: return PorterDuff.Mode.MULTIPLY; - case 15: return PorterDuff.Mode.SCREEN; - case 16: return PorterDuff.Mode.ADD; - default: return defaultMode; - } - } - @SuppressWarnings("RedundantCast") public static void setHotspot(Drawable drawable, float x, float y) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { diff --git a/app/src/main/java/com/hippo/util/JPathParser.java b/app/src/main/java/com/hippo/util/JPathParser.java deleted file mode 100644 index a68564fb3..000000000 --- a/app/src/main/java/com/hippo/util/JPathParser.java +++ /dev/null @@ -1,652 +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.util; - -import android.util.Log; - -import com.hippo.graphics.JPath; - -import java.util.ArrayList; -import java.util.Arrays; - -/** - * @hide - */ -public class JPathParser { - static final String LOGTAG = JPathParser.class.getSimpleName(); - - /** - * @param pathData The string representing a path, the same as "d" string in svg file. - * @return the generated Path object. - */ - public static JPath createPathFromPathData(String pathData) { - JPath path = new JPath(); - PathDataNode[] nodes = createNodesFromPathData(pathData); - if (nodes != null) { - PathDataNode.nodesToPath(nodes, path); - return path; - } - return null; - } - - /** - * @param pathData The string representing a path, the same as "d" string in svg file. - * @return an array of the PathDataNode. - */ - public static PathDataNode[] createNodesFromPathData(String pathData) { - if (pathData == null) { - return null; - } - int start = 0; - int end = 1; - - ArrayList list = new ArrayList(); - while (end < pathData.length()) { - end = nextStart(pathData, end); - String s = pathData.substring(start, end).trim(); - if (s.length() > 0) { - float[] val = getFloats(s); - addNode(list, s.charAt(0), val); - } - - start = end; - end++; - } - if ((end - start) == 1 && start < pathData.length()) { - addNode(list, pathData.charAt(start), new float[0]); - } - return list.toArray(new PathDataNode[list.size()]); - } - - /** - * @param source The array of PathDataNode to be duplicated. - * @return a deep copy of the source. - */ - public static PathDataNode[] deepCopyNodes(PathDataNode[] source) { - if (source == null) { - return null; - } - PathDataNode[] copy = new PathDataNode[source.length]; - for (int i = 0; i < source.length; i ++) { - copy[i] = new PathDataNode(source[i]); - } - return copy; - } - - /** - * @param nodesFrom The source path represented in an array of PathDataNode - * @param nodesTo The target path represented in an array of PathDataNode - * @return whether the nodesFrom can morph into nodesTo - */ - public static boolean canMorph(PathDataNode[] nodesFrom, PathDataNode[] nodesTo) { - if (nodesFrom == null || nodesTo == null) { - return false; - } - - if (nodesFrom.length != nodesTo.length) { - return false; - } - - for (int i = 0; i < nodesFrom.length; i ++) { - if (nodesFrom[i].mType != nodesTo[i].mType - || nodesFrom[i].mParams.length != nodesTo[i].mParams.length) { - return false; - } - } - return true; - } - - /** - * Update the target's data to match the source. - * Before calling this, make sure canMorph(target, source) is true. - * - * @param target The target path represented in an array of PathDataNode - * @param source The source path represented in an array of PathDataNode - */ - public static void updateNodes(PathDataNode[] target, PathDataNode[] source) { - for (int i = 0; i < source.length; i ++) { - target[i].mType = source[i].mType; - for (int j = 0; j < source[i].mParams.length; j ++) { - target[i].mParams[j] = source[i].mParams[j]; - } - } - } - - private static int nextStart(String s, int end) { - char c; - - while (end < s.length()) { - c = s.charAt(end); - if (((c - 'A') * (c - 'Z') <= 0) || (((c - 'a') * (c - 'z') <= 0))) { - return end; - } - end++; - } - return end; - } - - private static void addNode(ArrayList list, char cmd, float[] val) { - list.add(new PathDataNode(cmd, val)); - } - - private static class ExtractFloatResult { - // We need to return the position of the next separator and whether the - // next float starts with a '-'. - int mEndPosition; - boolean mEndWithNegSign; - } - - /** - * Parse the floats in the string. - * This is an optimized version of parseFloat(s.split(",|\\s")); - * - * @param s the string containing a command and list of floats - * @return array of floats - */ - private static float[] getFloats(String s) { - if (s.charAt(0) == 'z' | s.charAt(0) == 'Z') { - return new float[0]; - } - try { - float[] results = new float[s.length()]; - int count = 0; - int startPosition = 1; - int endPosition = 0; - - ExtractFloatResult result = new ExtractFloatResult(); - int totalLength = s.length(); - - // The startPosition should always be the first character of the - // current number, and endPosition is the character after the current - // number. - while (startPosition < totalLength) { - extract(s, startPosition, result); - endPosition = result.mEndPosition; - - if (startPosition < endPosition) { - results[count++] = Float.parseFloat( - s.substring(startPosition, endPosition)); - } - - if (result.mEndWithNegSign) { - // Keep the '-' sign with next number. - startPosition = endPosition; - } else { - startPosition = endPosition + 1; - } - } - return Arrays.copyOf(results, count); - } catch (NumberFormatException e) { - Log.e(LOGTAG, "error in parsing \"" + s + "\""); - throw e; - } - } - - /** - * Calculate the position of the next comma or space or negative sign - * @param s the string to search - * @param start the position to start searching - * @param result the result of the extraction, including the position of the - * 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. - int currentIndex = start; - boolean foundSeparator = false; - result.mEndWithNegSign = false; - for (; currentIndex < s.length(); currentIndex++) { - char currentChar = s.charAt(currentIndex); - switch (currentChar) { - case ' ': - case ',': - foundSeparator = true; - break; - case '-': - if (currentIndex != start) { - foundSeparator = true; - result.mEndWithNegSign = true; - } - break; - } - if (foundSeparator) { - break; - } - } - // When there is nothing found, then we put the end position to the end - // of the string. - result.mEndPosition = currentIndex; - } - - /** - * Each PathDataNode represents one command in the "d" attribute of the svg - * file. - * An array of PathDataNode can represent the whole "d" attribute. - */ - public static class PathDataNode { - private char mType; - private float[] mParams; - - private PathDataNode(char type, float[] params) { - mType = type; - mParams = params; - } - - private PathDataNode(PathDataNode n) { - mType = n.mType; - mParams = Arrays.copyOf(n.mParams, n.mParams.length); - } - - /** - * Convert an array of PathDataNode to Path. - * - * @param node The source array of PathDataNode. - * @param path The target Path object. - */ - public static void nodesToPath(PathDataNode[] node, JPath path) { - float[] current = new float[4]; - char previousCommand = 'm'; - for (int i = 0; i < node.length; i++) { - addCommand(path, current, previousCommand, node[i].mType, node[i].mParams); - previousCommand = node[i].mType; - } - } - - /** - * The current PathDataNode will be interpolated between the - * nodeFrom and nodeTo according to the - * fraction. - * - * @param nodeFrom The start value as a PathDataNode. - * @param nodeTo The end value as a PathDataNode - * @param fraction The fraction to interpolate. - */ - public void interpolatePathDataNode(PathDataNode nodeFrom, - PathDataNode nodeTo, float fraction) { - for (int i = 0; i < nodeFrom.mParams.length; i++) { - mParams[i] = nodeFrom.mParams[i] * (1 - fraction) - + nodeTo.mParams[i] * fraction; - } - } - - private static void addCommand(JPath path, float[] current, - char previousCmd, char cmd, float[] val) { - - int incr = 2; - float currentX = current[0]; - float currentY = current[1]; - float ctrlPointX = current[2]; - float ctrlPointY = current[3]; - float reflectiveCtrlPointX; - float reflectiveCtrlPointY; - - switch (cmd) { - case 'z': - case 'Z': - path.close(); - return; - case 'm': - case 'M': - case 'l': - case 'L': - case 't': - case 'T': - incr = 2; - break; - case 'h': - case 'H': - case 'v': - case 'V': - incr = 1; - break; - case 'c': - case 'C': - incr = 6; - break; - case 's': - case 'S': - case 'q': - case 'Q': - incr = 4; - break; - case 'a': - case 'A': - 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]; - 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]; - break; - case 'l': // lineto - Draw a line from the current point (relative) - path.rLineTo(val[k + 0], val[k + 1]); - currentX += val[k + 0]; - currentY += val[k + 1]; - break; - case 'L': // lineto - Draw a line from the current point - path.lineTo(val[k + 0], val[k + 1]); - 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]; - break; - case 'H': // horizontal lineto - Draws a horizontal line - path.lineTo(val[k + 0], currentY); - currentX = val[k + 0]; - break; - case 'v': // vertical lineto - Draws a vertical line from the current point (r) - path.rLineTo(0, val[k + 0]); - currentY += val[k + 0]; - break; - case 'V': // vertical lineto - Draws a vertical line from the current point - path.lineTo(currentX, val[k + 0]); - currentY = val[k + 0]; - break; - case 'c': // curveto - Draws a cubic Bézier curve (relative) - path.rCubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3], - val[k + 4], val[k + 5]); - - ctrlPointX = currentX + val[k + 2]; - ctrlPointY = currentY + val[k + 3]; - currentX += val[k + 4]; - currentY += val[k + 5]; - - break; - case 'C': // curveto - Draws a cubic Bézier curve - path.cubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3], - val[k + 4], val[k + 5]); - currentX = val[k + 4]; - currentY = val[k + 5]; - ctrlPointX = val[k + 2]; - ctrlPointY = val[k + 3]; - break; - case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp) - reflectiveCtrlPointX = 0; - reflectiveCtrlPointY = 0; - if (previousCmd == 'c' || previousCmd == 's' - || previousCmd == 'C' || previousCmd == 'S') { - reflectiveCtrlPointX = currentX - ctrlPointX; - reflectiveCtrlPointY = currentY - ctrlPointY; - } - path.rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY, - val[k + 0], val[k + 1], - val[k + 2], val[k + 3]); - - ctrlPointX = currentX + val[k + 0]; - ctrlPointY = currentY + val[k + 1]; - currentX += val[k + 2]; - currentY += val[k + 3]; - break; - case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp) - reflectiveCtrlPointX = currentX; - reflectiveCtrlPointY = currentY; - if (previousCmd == 'c' || previousCmd == 's' - || previousCmd == 'C' || previousCmd == 'S') { - reflectiveCtrlPointX = 2 * currentX - ctrlPointX; - reflectiveCtrlPointY = 2 * currentY - ctrlPointY; - } - path.cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY, - val[k + 0], val[k + 1], val[k + 2], val[k + 3]); - ctrlPointX = val[k + 0]; - ctrlPointY = val[k + 1]; - currentX = val[k + 2]; - currentY = val[k + 3]; - break; - case 'q': // Draws a quadratic Bézier (relative) - path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]); - ctrlPointX = currentX + val[k + 0]; - ctrlPointY = currentY + val[k + 1]; - currentX += val[k + 2]; - currentY += val[k + 3]; - break; - case 'Q': // Draws a quadratic Bézier - path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]); - ctrlPointX = val[k + 0]; - ctrlPointY = val[k + 1]; - currentX = val[k + 2]; - currentY = val[k + 3]; - break; - case 't': // Draws a quadratic Bézier curve(reflective control point)(relative) - reflectiveCtrlPointX = 0; - reflectiveCtrlPointY = 0; - if (previousCmd == 'q' || previousCmd == 't' - || previousCmd == 'Q' || previousCmd == 'T') { - reflectiveCtrlPointX = currentX - ctrlPointX; - reflectiveCtrlPointY = currentY - ctrlPointY; - } - path.rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY, - val[k + 0], val[k + 1]); - ctrlPointX = currentX + reflectiveCtrlPointX; - ctrlPointY = currentY + reflectiveCtrlPointY; - currentX += val[k + 0]; - currentY += val[k + 1]; - break; - case 'T': // Draws a quadratic Bézier curve (reflective control point) - reflectiveCtrlPointX = currentX; - reflectiveCtrlPointY = currentY; - if (previousCmd == 'q' || previousCmd == 't' - || previousCmd == 'Q' || previousCmd == 'T') { - reflectiveCtrlPointX = 2 * currentX - ctrlPointX; - reflectiveCtrlPointY = 2 * currentY - ctrlPointY; - } - path.quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY, - val[k + 0], val[k + 1]); - ctrlPointX = reflectiveCtrlPointX; - ctrlPointY = reflectiveCtrlPointY; - currentX = val[k + 0]; - currentY = val[k + 1]; - break; - case 'a': // Draws an elliptical arc - // (rx ry x-axis-rotation large-arc-flag sweep-flag x y) - drawArc(path, - currentX, - currentY, - val[k + 5] + currentX, - val[k + 6] + currentY, - val[k + 0], - val[k + 1], - val[k + 2], - val[k + 3] != 0, - val[k + 4] != 0); - currentX += val[k + 5]; - currentY += val[k + 6]; - ctrlPointX = currentX; - ctrlPointY = currentY; - break; - case 'A': // Draws an elliptical arc - drawArc(path, - currentX, - currentY, - val[k + 5], - val[k + 6], - val[k + 0], - val[k + 1], - val[k + 2], - val[k + 3] != 0, - val[k + 4] != 0); - currentX = val[k + 5]; - currentY = val[k + 6]; - ctrlPointX = currentX; - ctrlPointY = currentY; - break; - } - previousCmd = cmd; - } - current[0] = currentX; - current[1] = currentY; - current[2] = ctrlPointX; - current[3] = ctrlPointY; - } - - private static void drawArc(JPath p, - float x0, - float y0, - float x1, - float y1, - float a, - float b, - float theta, - boolean isMoreThanHalf, - boolean isPositiveArc) { - - /* Convert rotation angle from degrees to radians */ - double thetaD = Math.toRadians(theta); - /* Pre-compute rotation matrix entries */ - double cosTheta = Math.cos(thetaD); - double sinTheta = Math.sin(thetaD); - /* Transform (x0, y0) and (x1, y1) into unit space */ - /* using (inverse) rotation, followed by (inverse) scale */ - double x0p = (x0 * cosTheta + y0 * sinTheta) / a; - double y0p = (-x0 * sinTheta + y0 * cosTheta) / b; - double x1p = (x1 * cosTheta + y1 * sinTheta) / a; - double y1p = (-x1 * sinTheta + y1 * cosTheta) / b; - - /* Compute differences and averages */ - double dx = x0p - x1p; - double dy = y0p - y1p; - double xm = (x0p + x1p) / 2; - double ym = (y0p + y1p) / 2; - /* Solve for intersecting unit circles */ - double dsq = dx * dx + dy * dy; - if (dsq == 0.0) { - Log.w(LOGTAG, " Points are coincident"); - return; /* Points are coincident */ - } - double disc = 1.0 / dsq - 1.0 / 4.0; - if (disc < 0.0) { - Log.w(LOGTAG, "Points are too far apart " + dsq); - float adjust = (float) (Math.sqrt(dsq) / 1.99999); - drawArc(p, x0, y0, x1, y1, a * adjust, - b * adjust, theta, isMoreThanHalf, isPositiveArc); - return; /* Points are too far apart */ - } - double s = Math.sqrt(disc); - double sdx = s * dx; - double sdy = s * dy; - double cx; - double cy; - if (isMoreThanHalf == isPositiveArc) { - cx = xm - sdy; - cy = ym + sdx; - } else { - cx = xm + sdy; - cy = ym - sdx; - } - - double eta0 = Math.atan2((y0p - cy), (x0p - cx)); - - double eta1 = Math.atan2((y1p - cy), (x1p - cx)); - - double sweep = (eta1 - eta0); - if (isPositiveArc != (sweep >= 0)) { - if (sweep > 0) { - sweep -= 2 * Math.PI; - } else { - sweep += 2 * Math.PI; - } - } - - cx *= a; - cy *= b; - double tcx = cx; - cx = cx * cosTheta - cy * sinTheta; - cy = tcx * sinTheta + cy * cosTheta; - - arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep); - } - - /** - * Converts an arc to cubic Bezier segments and records them in p. - * - * @param p The target for the cubic Bezier segments - * @param cx The x coordinate center of the ellipse - * @param cy The y coordinate center of the ellipse - * @param a The radius of the ellipse in the horizontal direction - * @param b The radius of the ellipse in the vertical direction - * @param e1x E(eta1) x coordinate of the starting point of the arc - * @param e1y E(eta2) y coordinate of the starting point of the arc - * @param theta The angle that the ellipse bounding rectangle makes with horizontal plane - * @param start The start angle of the arc on the ellipse - * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse - */ - private static void arcToBezier(JPath p, - double cx, - double cy, - double a, - double b, - double e1x, - double e1y, - double theta, - double start, - double sweep) { - // Taken from equations at: http://spaceroots.org/documents/ellipse/node8.html - // and http://www.spaceroots.org/documents/ellipse/node22.html - - // Maximum of 45 degrees per cubic Bezier segment - int numSegments = Math.abs((int) Math.ceil(sweep * 4 / Math.PI)); - - double eta1 = start; - double cosTheta = Math.cos(theta); - double sinTheta = Math.sin(theta); - double cosEta1 = Math.cos(eta1); - double sinEta1 = Math.sin(eta1); - double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1); - double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1); - - double anglePerSegment = sweep / numSegments; - for (int i = 0; i < numSegments; i++) { - double eta2 = eta1 + anglePerSegment; - double sinEta2 = Math.sin(eta2); - double cosEta2 = Math.cos(eta2); - double e2x = cx + (a * cosTheta * cosEta2) - (b * sinTheta * sinEta2); - double e2y = cy + (a * sinTheta * cosEta2) + (b * cosTheta * sinEta2); - double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2; - double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2; - double tanDiff2 = Math.tan((eta2 - eta1) / 2); - double alpha = - Math.sin(eta2 - eta1) * (Math.sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3; - double q1x = e1x + alpha * ep1x; - double q1y = e1y + alpha * ep1y; - double q2x = e2x - alpha * ep2x; - double q2y = e2y - alpha * ep2y; - - p.cubicTo((float) q1x, - (float) q1y, - (float) q2x, - (float) q2y, - (float) e2x, - (float) e2y); - eta1 = eta2; - e1x = e2x; - e1y = e2y; - ep1x = ep2x; - ep1y = ep2y; - } - } - } -} diff --git a/app/src/main/java/com/hippo/animation/AnimatorInflater.java b/app/src/main/java/com/hippo/vectorold/animation/AnimatorInflater.java similarity index 97% rename from app/src/main/java/com/hippo/animation/AnimatorInflater.java rename to app/src/main/java/com/hippo/vectorold/animation/AnimatorInflater.java index 77593530e..b231c8bd3 100644 --- a/app/src/main/java/com/hippo/animation/AnimatorInflater.java +++ b/app/src/main/java/com/hippo/vectorold/animation/AnimatorInflater.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.hippo.animation; +package com.hippo.vectorold.animation; import android.animation.Animator; import android.animation.AnimatorSet; @@ -33,7 +33,7 @@ import android.util.Xml; import android.view.InflateException; import com.hippo.ehviewer.R; -import com.hippo.util.PathParser; +import com.hippo.vectorold.util.PathParser; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -72,12 +72,12 @@ public class AnimatorInflater { private static final ArgbEvaluator ARGB_EVALUATOR = new ArgbEvaluator(); /** - * Loads an {@link Animator} object from a resource + * 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 NotFoundException when the animation cannot be loaded + * @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded */ public static Animator loadAnimator(Context context, int id) throws NotFoundException { @@ -208,7 +208,7 @@ public class AnimatorInflater { /** * Create a PathDataEvaluator that reuses nodeArray for every evaluate() call. * Caution must be taken to ensure that the value returned from - * {@link ValueAnimator#getAnimatedValue()} is not cached, modified, or + * {@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. @@ -313,7 +313,7 @@ public class AnimatorInflater { * @return the PathDataEvaluator. */ private static TypeEvaluator setupAnimatorForPath(ValueAnimator anim, - TypedArray arrayAnimator) { + TypedArray arrayAnimator) { TypeEvaluator evaluator = null; String fromString = arrayAnimator.getString(R.styleable.Animator_valueFrom); String toString = arrayAnimator.getString(R.styleable.Animator_valueTo); @@ -371,9 +371,9 @@ public class AnimatorInflater { throw new InflateException(arrayObjectAnimator.getPositionDescription() + " propertyXName or propertyYName is needed for PathData"); } else { - Path path = PathParser.createPathFromPathData(pathData); + JPath path = JPathParser.createPathFromPathData(pathData); float error = 0.5f * pixelSize; // max half a pixel error - PathKeyframes keyframeSet = KeyframeSet.ofPath(path, error); + PathKeyframes keyframeSet = new PathKeyframes(path, error); Keyframes xKeyframes; Keyframes yKeyframes; if (getFloats) { diff --git a/app/src/main/java/com/hippo/animation/InterpolatorInflater.java b/app/src/main/java/com/hippo/vectorold/animation/InterpolatorInflater.java similarity index 97% rename from app/src/main/java/com/hippo/animation/InterpolatorInflater.java rename to app/src/main/java/com/hippo/vectorold/animation/InterpolatorInflater.java index 526e1863c..5a726980c 100644 --- a/app/src/main/java/com/hippo/animation/InterpolatorInflater.java +++ b/app/src/main/java/com/hippo/vectorold/animation/InterpolatorInflater.java @@ -13,7 +13,7 @@ * limitations under the License. */ -package com.hippo.animation; +package com.hippo.vectorold.animation; import android.content.Context; import android.content.res.Resources; @@ -108,10 +108,10 @@ public class InterpolatorInflater { } else if (name.equals("bounceInterpolator")) { interpolator = new BounceInterpolator(); } else if (name.equals("pathInterpolator")) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - interpolator = new android.view.animation.PathInterpolator(context, attrs); - } else { + 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()); diff --git a/app/src/main/java/com/hippo/animation/PathInterpolator.java b/app/src/main/java/com/hippo/vectorold/animation/PathInterpolator.java similarity index 82% rename from app/src/main/java/com/hippo/animation/PathInterpolator.java rename to app/src/main/java/com/hippo/vectorold/animation/PathInterpolator.java index d515e53bb..9d3ab0600 100644 --- a/app/src/main/java/com/hippo/animation/PathInterpolator.java +++ b/app/src/main/java/com/hippo/vectorold/animation/PathInterpolator.java @@ -13,19 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.hippo.animation; +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.graphics.JPath; -import com.hippo.util.JPathParser; +import com.hippo.vectorold.util.PathParser; /** * An interpolator that can traverse a Path that extends from Point @@ -58,7 +59,7 @@ public class PathInterpolator implements Interpolator { * * @param path The Path to use to make the line representing the interpolator. */ - public PathInterpolator(JPath path) { + public PathInterpolator(Path path) { initPath(path); } @@ -90,7 +91,6 @@ public class PathInterpolator implements Interpolator { this(context.getResources(), context.getTheme(), attrs); } - /** @hide */ public PathInterpolator(Resources res, Theme theme, AttributeSet attrs) { TypedArray a; if (theme != null) { @@ -99,7 +99,6 @@ public class PathInterpolator implements Interpolator { a = res.obtainAttributes(attrs, R.styleable.PathInterpolator); } parseInterpolatorFromTypeArray(a); - //setChangingConfiguration(a.getChangingConfigurations()); a.recycle(); } @@ -108,7 +107,7 @@ public class PathInterpolator implements Interpolator { // will be all coming from pathData. if (a.hasValue(R.styleable.PathInterpolator_pathData)) { String pathData = a.getString(R.styleable.PathInterpolator_pathData); - JPath path = JPathParser.createPathFromPathData(pathData); + Path path = PathParser.createPathFromPathData(pathData); if (path == null) { throw new InflateException("The path is null, which is created" + " from " + pathData); @@ -142,49 +141,35 @@ public class PathInterpolator implements Interpolator { } private void initQuad(float controlX, float controlY) { - JPath path = new JPath(); + 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) { - JPath path = new JPath(); + Path path = new Path(); path.moveTo(0, 0); path.cubicTo(x1, y1, x2, y2, 1f, 1f); initPath(path); } - private void initPath(JPath path) { - float[] pointComponents = path.approximate(PRECISION); + private void initPath(Path path) { + final PathMeasure pathMeasure = new PathMeasure(path, false /* forceClosed */); - int numPoints = pointComponents.length / 3; - if (pointComponents[1] != 0 || pointComponents[2] != 0 - || pointComponents[pointComponents.length - 2] != 1 - || pointComponents[pointComponents.length - 1] != 1) { - throw new IllegalArgumentException("The Path must start at (0,0) and end at (1,1)"); - } + final float pathLength = pathMeasure.getLength(); + final int numPoints = (int) (pathLength / PRECISION) + 1; mX = new float[numPoints]; mY = new float[numPoints]; - float prevX = 0; - float prevFraction = 0; - int componentIndex = 0; - for (int i = 0; i < numPoints; i++) { - float fraction = pointComponents[componentIndex++]; - float x = pointComponents[componentIndex++]; - float y = pointComponents[componentIndex++]; - if (fraction == prevFraction && x != prevX) { - throw new IllegalArgumentException( - "The Path cannot have discontinuity in the X axis."); - } - if (x < prevX) { - throw new IllegalArgumentException("The Path cannot loop back on itself."); - } - mX[i] = x; - mY[i] = y; - prevX = x; - prevFraction = fraction; + + 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]; } } diff --git a/app/src/main/java/com/hippo/content/VectorContext.java b/app/src/main/java/com/hippo/vectorold/content/VectorContext.java similarity index 97% rename from app/src/main/java/com/hippo/content/VectorContext.java rename to app/src/main/java/com/hippo/vectorold/content/VectorContext.java index 682a9c834..ec2ebbc65 100644 --- a/app/src/main/java/com/hippo/content/VectorContext.java +++ b/app/src/main/java/com/hippo/vectorold/content/VectorContext.java @@ -13,7 +13,7 @@ * limitations under the License. */ -package com.hippo.content; +package com.hippo.vectorold.content; import android.content.Context; import android.content.ContextWrapper; diff --git a/app/src/main/java/com/hippo/drawable/AnimatedVectorDrawable.java b/app/src/main/java/com/hippo/vectorold/drawable/AnimatedVectorDrawable.java similarity index 99% rename from app/src/main/java/com/hippo/drawable/AnimatedVectorDrawable.java rename to app/src/main/java/com/hippo/vectorold/drawable/AnimatedVectorDrawable.java index 1273e62b8..f69194055 100644 --- a/app/src/main/java/com/hippo/drawable/AnimatedVectorDrawable.java +++ b/app/src/main/java/com/hippo/vectorold/drawable/AnimatedVectorDrawable.java @@ -12,7 +12,7 @@ * the License. */ -package com.hippo.drawable; +package com.hippo.vectorold.drawable; import android.animation.Animator; import android.content.Context; @@ -29,7 +29,7 @@ import android.support.v4.util.ArrayMap; import android.util.AttributeSet; import android.util.Log; -import com.hippo.animation.AnimatorInflater; +import com.hippo.vectorold.animation.AnimatorInflater; import com.hippo.ehviewer.R; import org.xmlpull.v1.XmlPullParser; diff --git a/app/src/main/java/com/hippo/drawable/VectorDrawable.java b/app/src/main/java/com/hippo/vectorold/drawable/VectorDrawable.java similarity index 99% rename from app/src/main/java/com/hippo/drawable/VectorDrawable.java rename to app/src/main/java/com/hippo/vectorold/drawable/VectorDrawable.java index 155202b7d..13b7933a6 100644 --- a/app/src/main/java/com/hippo/drawable/VectorDrawable.java +++ b/app/src/main/java/com/hippo/vectorold/drawable/VectorDrawable.java @@ -12,7 +12,7 @@ * the License. */ -package com.hippo.drawable; +package com.hippo.vectorold.drawable; import android.content.res.ColorStateList; import android.content.res.Resources; @@ -38,8 +38,8 @@ import android.util.Log; import android.util.Xml; import com.hippo.ehviewer.R; -import com.hippo.util.DrawableUtils; -import com.hippo.util.PathParser; +import com.hippo.vectorold.util.DrawableUtils; +import com.hippo.vectorold.util.PathParser; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; diff --git a/app/src/main/java/com/hippo/vectorold/util/DrawableUtils.java b/app/src/main/java/com/hippo/vectorold/util/DrawableUtils.java new file mode 100644 index 000000000..fa1da39ff --- /dev/null +++ b/app/src/main/java/com/hippo/vectorold/util/DrawableUtils.java @@ -0,0 +1,58 @@ +/* + * 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 + * 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; + +import android.content.res.ColorStateList; +import android.graphics.Color; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.Drawable; + +public class DrawableUtils { + + public static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN; + + /** + * 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) { + if (tint == null || tintMode == null) { + return null; + } + + final int color = tint.getColorForState(drawable.getState(), Color.TRANSPARENT); + return new PorterDuffColorFilter(color, tintMode); + } + + /** + * Parses a {@link PorterDuff.Mode} from a tintMode + * attribute's enum value. + */ + public static PorterDuff.Mode parseTintMode(int value, PorterDuff.Mode defaultMode) { + switch (value) { + case 3: return PorterDuff.Mode.SRC_OVER; + case 5: return PorterDuff.Mode.SRC_IN; + case 9: return PorterDuff.Mode.SRC_ATOP; + case 14: return PorterDuff.Mode.MULTIPLY; + case 15: return PorterDuff.Mode.SCREEN; + case 16: return PorterDuff.Mode.ADD; + default: return defaultMode; + } + } +} diff --git a/app/src/main/java/com/hippo/util/PathParser.java b/app/src/main/java/com/hippo/vectorold/util/PathParser.java similarity index 99% rename from app/src/main/java/com/hippo/util/PathParser.java rename to app/src/main/java/com/hippo/vectorold/util/PathParser.java index 3bd595dc9..178c542dd 100644 --- a/app/src/main/java/com/hippo/util/PathParser.java +++ b/app/src/main/java/com/hippo/vectorold/util/PathParser.java @@ -12,7 +12,7 @@ * the License. */ -package com.hippo.util; +package com.hippo.vectorold.util; import android.graphics.Path; import android.util.Log; diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 4e8281158..9bfacfcf4 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -54,245 +54,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/values/vectorold_attrs.xml b/app/src/main/res/values/vectorold_attrs.xml new file mode 100644 index 000000000..42b1a8388 --- /dev/null +++ b/app/src/main/res/values/vectorold_attrs.xml @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +