From 5a836f74df027bb568da17fbde4e641b6a56d2a9 Mon Sep 17 00:00:00 2001 From: ztenghui Date: Mon, 21 Jul 2014 15:59:06 -0700 Subject: [PATCH] Add negative sign separation support in the pathData bug:14585171 Change-Id: I61dec27856be09c44bb1d32ff61b3c3cd458cc34 --- core/java/android/util/PathParser.java | 93 +++++++++++++------ .../graphics/drawable/VectorDrawable.java | 4 +- tests/VectorDrawableTest/AndroidManifest.xml | 2 +- .../res/drawable/vector_drawable01.xml | 2 +- .../res/drawable/vector_drawable03.xml | 28 +++--- .../res/drawable/vector_drawable04.xml | 32 +++---- .../res/drawable/vector_drawable05.xml | 24 ++--- .../res/drawable/vector_drawable07.xml | 6 +- .../res/drawable/vector_drawable09.xml | 2 +- .../res/drawable/vector_drawable10.xml | 8 +- .../res/drawable/vector_drawable_favorite.xml | 4 +- 11 files changed, 121 insertions(+), 84 deletions(-) diff --git a/core/java/android/util/PathParser.java b/core/java/android/util/PathParser.java index f4a0448611911..c36421db9b06a 100644 --- a/core/java/android/util/PathParser.java +++ b/core/java/android/util/PathParser.java @@ -54,9 +54,11 @@ public class PathParser { ArrayList list = new ArrayList(); while (end < pathData.length()) { end = nextStart(pathData, end); - String s = pathData.substring(start, end); - float[] val = getFloats(s); - addNode(list, s.charAt(0), val); + String s = pathData.substring(start, end).trim(); + if (s.length() > 0) { + float[] val = getFloats(s); + addNode(list, s.charAt(0), val); + } start = end; end++; @@ -135,6 +137,12 @@ public class PathParser { 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. @@ -148,42 +156,73 @@ public class PathParser { return new float[0]; } try { - float[] tmp = new float[s.length()]; + float[] results = new float[s.length()]; int count = 0; - int pos = 1, end; - while ((end = extract(s, pos)) >= 0) { - if (pos < end) { - tmp[count++] = Float.parseFloat(s.substring(pos, end)); + 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; } - pos = end + 1; } - // handle the final float if there is one - if (pos < s.length()) { - tmp[count++] = Float.parseFloat(s.substring(pos, s.length())); - } - return Arrays.copyOf(tmp, count); - } catch (NumberFormatException e){ - Log.e(LOGTAG,"error in parsing \""+s+"\""); + 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 + * 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 - * @return the position of the next comma or space or -1 if none found + * @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 int extract(String s, int start) { - int space = s.indexOf(' ', start); - int comma = s.indexOf(',', start); - if (space == -1) { - return comma; + 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; + } } - if (comma == -1) { - return space; - } - return (comma > space) ? space : comma; + // When there is nothing found, then we put the end position to the end + // of the string. + result.mEndPosition = currentIndex; } /** diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index 13ef89bc4eb11..8ed6776d395a3 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -740,9 +740,7 @@ public class VectorDrawable extends Drawable { final float minScale = Math.min(scaleX, scaleY); mFinalPathMatrix.set(vGroup.mStackedMatrix); - mFinalPathMatrix.postScale(scaleX, scaleY, mViewportWidth / 2f, mViewportHeight / 2f); - mFinalPathMatrix.postTranslate( - w / 2f - mViewportWidth / 2f, h / 2f - mViewportHeight / 2f); + mFinalPathMatrix.postScale(scaleX, scaleY); vPath.toPath(mPath); final Path path = mPath; diff --git a/tests/VectorDrawableTest/AndroidManifest.xml b/tests/VectorDrawableTest/AndroidManifest.xml index a16b74901355a..ee62e5ee9faa6 100644 --- a/tests/VectorDrawableTest/AndroidManifest.xml +++ b/tests/VectorDrawableTest/AndroidManifest.xml @@ -100,7 +100,7 @@ + android:label="System icons" > diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml index 66a9452d53800..3b01e029e1c79 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml @@ -26,7 +26,7 @@ + android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0-6.671875-2.109375,0.421875 0.0-1.078125 + l 2.09375-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0 + l-5.046875,0.0 0.0-1.0Z" /> + android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0-5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375 + q 1.1718752-1.1875 1.4687502-1.53125 0.578125-0.625 0.796875-1.0625 + q 0.234375-0.453125 0.234375-0.875 0.0-0.703125-0.5-1.140625 + q-0.484375-0.4375-1.2656252-0.4375-0.5625,0.0-1.1875,0.1875 + q-0.609375,0.1875-1.3125,0.59375l 0.0-1.203125q 0.71875-0.28125 1.328125-0.421875 + q 0.625-0.15625 1.140625-0.15625 1.3593752,0.0 2.1718752,0.6875 + q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125-0.203125,1.015625 + q-0.203125,0.484375-0.734375,1.140625-0.15625,0.171875-0.9375,0.984375 + q-0.78125024,0.8125-2.2187502,2.265625Z" /> \ No newline at end of file diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml index 296e026116e72..d57ae8b756efc 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml @@ -28,41 +28,41 @@ android:name="clip1" android:pathData=" M 3.65, 6.125 - m -.001, 0 + m-.001, 0 a .001,.001 0 1,0 .002,0 - a .001,.001 0 1,0 -.002,0z" + a .001,.001 0 1,0-.002,0z" android:clipToPath="true" android:fill="#112233" /> diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml index 1633326ae2b0c..673c465242431 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml @@ -28,21 +28,21 @@ + android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0-6.671875-2.109375,0.421875 0.0-1.078125 + l 2.09375-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0 + l-5.046875,0.0 0.0-1.0Z" /> + android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0-5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375 + q 1.1718752-1.1875 1.4687502-1.53125 0.578125-0.625 0.796875-1.0625 + q 0.234375-0.453125 0.234375-0.875 0.0-0.703125-0.5-1.140625 + q-0.484375-0.4375-1.2656252-0.4375-0.5625,0.0-1.1875,0.1875 + q-0.609375,0.1875-1.3125,0.59375l 0.0-1.203125q 0.71875-0.28125 1.328125-0.421875 + q 0.625-0.15625 1.140625-0.15625 1.3593752,0.0 2.1718752,0.6875 + q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125-0.203125,1.015625 + q-0.203125,0.484375-0.734375,1.140625-0.15625,0.171875-0.9375,0.984375 + q-0.78125024,0.8125-2.2187502,2.265625Z" /> \ No newline at end of file diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml index 7c7e679a3d1e6..ccb0df0c9aa86 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml @@ -23,9 +23,9 @@ diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml index c93c85fef3bda..77434fca58f02 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml @@ -30,7 +30,7 @@ + android:pathData="M 100,20 l 0,0 0,140-80,0 z M 100,20 l 0,0 80,140-80,0 z"/> \ No newline at end of file diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml index 8484e9e2f1076..df24713e3ba00 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml @@ -28,19 +28,19 @@ + android:pathData="M49.001,60c-5.466,0-9.899,4.478-9.899,10s4.434,10,9.899,10c5.468,0,9.899-4.478,9.899-10S54.469,60,49.001,60z" /> + android:pathData="M28.001,48.787l7,7.07c7.731-7.811,20.269-7.81,28.001,0l6.999-7.07C58.403,37.071,39.599,37.071,28.001,48.787z" /> + android:pathData="M14.001,34.645 L21,41.716c15.464-15.621,40.536-15.621,56,0l7.001-7.071C64.672,15.119,33.33,15.119,14.001,34.645z" /> + android:pathData="M0,20.502l6.999,7.071 c23.196-23.431,60.806-23.431,84.002,0L98,20.503C70.938-6.834,27.063-6.834,0,20.502z" /> \ No newline at end of file diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_favorite.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable_favorite.xml index c8840f56a6b90..5a66e2d4bc9ff 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable_favorite.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable_favorite.xml @@ -32,11 +32,11 @@ android:fill="#ff000000" android:pathData="M2.100006104,-6 C0.1449127197,-6,1.600006104,-5.975006104,0,-5.975006104 - C-1.574996948,-5.975006104,0.00309753418,-6,-1.949996948,-6 + C-1.574996948,-5.975006104,0.00309753418,-6-1.949996948-6 C-4.492996216,-6,-5.949996948,-3.718399048,-5.949996948,-1.149993896 C-5.949996948,2.379302979,-5.699996948,5.100006104,0,5.100006104 C5.699996948,5.100006104,6,2.379302979,6,-1.149993896 - C6,-3.718399048,4.643005371,-6,2.100006104,-6" /> + C6,-3.718399048,4.643005371-6,2.100006104-6" /> \ No newline at end of file