mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2025-12-12 00:52:40 +01:00
DroidFish: Added svg-android code for SVG support. See http://code.google.com/p/svg-android/.
This commit is contained in:
306
DroidFish/src/com/larvalabs/svgandroid/ParserHelper.java
Normal file
306
DroidFish/src/com/larvalabs/svgandroid/ParserHelper.java
Normal file
@@ -0,0 +1,306 @@
|
||||
package com.larvalabs.svgandroid;
|
||||
|
||||
/*
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You 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.
|
||||
|
||||
*/
|
||||
/**
|
||||
* Parses numbers from SVG text. Based on the Batik Number Parser (Apache 2 License).
|
||||
*
|
||||
* @author Apache Software Foundation, Larva Labs LLC
|
||||
*/
|
||||
public class ParserHelper {
|
||||
|
||||
private char current;
|
||||
private CharSequence s;
|
||||
public int pos;
|
||||
private int n;
|
||||
|
||||
public ParserHelper(CharSequence s, int pos) {
|
||||
this.s = s;
|
||||
this.pos = pos;
|
||||
n = s.length();
|
||||
current = s.charAt(pos);
|
||||
}
|
||||
|
||||
private char read() {
|
||||
if (pos < n) {
|
||||
pos++;
|
||||
}
|
||||
if (pos == n) {
|
||||
return '\0';
|
||||
} else {
|
||||
return s.charAt(pos);
|
||||
}
|
||||
}
|
||||
|
||||
public void skipWhitespace() {
|
||||
while (pos < n) {
|
||||
if (Character.isWhitespace(s.charAt(pos))) {
|
||||
advance();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void skipNumberSeparator() {
|
||||
while (pos < n) {
|
||||
char c = s.charAt(pos);
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case ',':
|
||||
case '\n':
|
||||
case '\t':
|
||||
advance();
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void advance() {
|
||||
current = read();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the content of the buffer and converts it to a float.
|
||||
*/
|
||||
public float parseFloat() {
|
||||
int mant = 0;
|
||||
int mantDig = 0;
|
||||
boolean mantPos = true;
|
||||
boolean mantRead = false;
|
||||
|
||||
int exp = 0;
|
||||
int expDig = 0;
|
||||
int expAdj = 0;
|
||||
boolean expPos = true;
|
||||
|
||||
switch (current) {
|
||||
case '-':
|
||||
mantPos = false;
|
||||
// fallthrough
|
||||
case '+':
|
||||
current = read();
|
||||
}
|
||||
|
||||
m1: switch (current) {
|
||||
default:
|
||||
return Float.NaN;
|
||||
|
||||
case '.':
|
||||
break;
|
||||
|
||||
case '0':
|
||||
mantRead = true;
|
||||
l: for (;;) {
|
||||
current = read();
|
||||
switch (current) {
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
break l;
|
||||
case '.': case 'e': case 'E':
|
||||
break m1;
|
||||
default:
|
||||
return 0.0f;
|
||||
case '0':
|
||||
}
|
||||
}
|
||||
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
mantRead = true;
|
||||
l: for (;;) {
|
||||
if (mantDig < 9) {
|
||||
mantDig++;
|
||||
mant = mant * 10 + (current - '0');
|
||||
} else {
|
||||
expAdj++;
|
||||
}
|
||||
current = read();
|
||||
switch (current) {
|
||||
default:
|
||||
break l;
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (current == '.') {
|
||||
current = read();
|
||||
m2: switch (current) {
|
||||
default:
|
||||
case 'e': case 'E':
|
||||
if (!mantRead) {
|
||||
reportUnexpectedCharacterError( current );
|
||||
return 0.0f;
|
||||
}
|
||||
break;
|
||||
|
||||
case '0':
|
||||
if (mantDig == 0) {
|
||||
l: for (;;) {
|
||||
current = read();
|
||||
expAdj--;
|
||||
switch (current) {
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
break l;
|
||||
default:
|
||||
if (!mantRead) {
|
||||
return 0.0f;
|
||||
}
|
||||
break m2;
|
||||
case '0':
|
||||
}
|
||||
}
|
||||
}
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
l: for (;;) {
|
||||
if (mantDig < 9) {
|
||||
mantDig++;
|
||||
mant = mant * 10 + (current - '0');
|
||||
expAdj--;
|
||||
}
|
||||
current = read();
|
||||
switch (current) {
|
||||
default:
|
||||
break l;
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (current) {
|
||||
case 'e': case 'E':
|
||||
current = read();
|
||||
switch (current) {
|
||||
default:
|
||||
reportUnexpectedCharacterError( current );
|
||||
return 0f;
|
||||
case '-':
|
||||
expPos = false;
|
||||
case '+':
|
||||
current = read();
|
||||
switch (current) {
|
||||
default:
|
||||
reportUnexpectedCharacterError( current );
|
||||
return 0f;
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
}
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
}
|
||||
|
||||
en: switch (current) {
|
||||
case '0':
|
||||
l: for (;;) {
|
||||
current = read();
|
||||
switch (current) {
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
break l;
|
||||
default:
|
||||
break en;
|
||||
case '0':
|
||||
}
|
||||
}
|
||||
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
l: for (;;) {
|
||||
if (expDig < 3) {
|
||||
expDig++;
|
||||
exp = exp * 10 + (current - '0');
|
||||
}
|
||||
current = read();
|
||||
switch (current) {
|
||||
default:
|
||||
break l;
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
if (!expPos) {
|
||||
exp = -exp;
|
||||
}
|
||||
exp += expAdj;
|
||||
if (!mantPos) {
|
||||
mant = -mant;
|
||||
}
|
||||
|
||||
return buildFloat(mant, exp);
|
||||
}
|
||||
|
||||
private void reportUnexpectedCharacterError(char c) {
|
||||
throw new RuntimeException("Unexpected char '" + c + "'.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a float from mantissa and exponent.
|
||||
*/
|
||||
public static float buildFloat(int mant, int exp) {
|
||||
if (exp < -125 || mant == 0) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (exp >= 128) {
|
||||
return (mant > 0)
|
||||
? Float.POSITIVE_INFINITY
|
||||
: Float.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
||||
if (exp == 0) {
|
||||
return mant;
|
||||
}
|
||||
|
||||
if (mant >= (1 << 26)) {
|
||||
mant++; // round up trailing bits if they will be dropped.
|
||||
}
|
||||
|
||||
return (float) ((exp > 0) ? mant * pow10[exp] : mant / pow10[-exp]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Array of powers of ten. Using double instead of float gives a tiny bit more precision.
|
||||
*/
|
||||
private static final double[] pow10 = new double[128];
|
||||
|
||||
static {
|
||||
for (int i = 0; i < pow10.length; i++) {
|
||||
pow10[i] = Math.pow(10, i);
|
||||
}
|
||||
}
|
||||
|
||||
public float nextFloat() {
|
||||
skipWhitespace();
|
||||
float f = parseFloat();
|
||||
skipNumberSeparator();
|
||||
return f;
|
||||
}
|
||||
}
|
||||
120
DroidFish/src/com/larvalabs/svgandroid/SVG.java
Normal file
120
DroidFish/src/com/larvalabs/svgandroid/SVG.java
Normal file
@@ -0,0 +1,120 @@
|
||||
package com.larvalabs.svgandroid;
|
||||
|
||||
import android.graphics.Picture;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.PictureDrawable;
|
||||
|
||||
/*
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You 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.
|
||||
|
||||
*/
|
||||
/**
|
||||
* Describes a vector Picture object, and optionally its bounds.
|
||||
*
|
||||
* @author Larva Labs, LLC
|
||||
*/
|
||||
public class SVG {
|
||||
|
||||
/**
|
||||
* The parsed Picture object.
|
||||
*/
|
||||
private Picture picture;
|
||||
|
||||
/**
|
||||
* These are the bounds for the SVG specified as a hidden "bounds" layer in the SVG.
|
||||
*/
|
||||
private RectF bounds;
|
||||
|
||||
/**
|
||||
* These are the estimated bounds of the SVG computed from the SVG elements while parsing.
|
||||
* Note that this could be null if there was a failure to compute limits (ie. an empty SVG).
|
||||
*/
|
||||
private RectF limits = null;
|
||||
|
||||
/**
|
||||
* Construct a new SVG.
|
||||
* @param picture the parsed picture object.
|
||||
* @param bounds the bounds computed from the "bounds" layer in the SVG.
|
||||
*/
|
||||
SVG(Picture picture, RectF bounds) {
|
||||
this.picture = picture;
|
||||
this.bounds = bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the limits of the SVG, which are the estimated bounds computed by the parser.
|
||||
* @param limits the bounds computed while parsing the SVG, may not be entirely accurate.
|
||||
*/
|
||||
void setLimits(RectF limits) {
|
||||
this.limits = limits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a picture drawable from the SVG.
|
||||
* @return the PictureDrawable.
|
||||
*/
|
||||
public PictureDrawable createPictureDrawable() {
|
||||
return new PictureDrawable(picture);
|
||||
// return new PictureDrawable(picture) {
|
||||
// @Override
|
||||
// public int getIntrinsicWidth() {
|
||||
// if (bounds != null) {
|
||||
// return (int) bounds.width();
|
||||
// } else if (limits != null) {
|
||||
// return (int) limits.width();
|
||||
// } else {
|
||||
// return -1;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public int getIntrinsicHeight() {
|
||||
// if (bounds != null) {
|
||||
// return (int) bounds.height();
|
||||
// } else if (limits != null) {
|
||||
// return (int) limits.height();
|
||||
// } else {
|
||||
// return -1;
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parsed SVG picture data.
|
||||
* @return the picture.
|
||||
*/
|
||||
public Picture getPicture() {
|
||||
return picture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bounding rectangle for the SVG, if one was specified.
|
||||
* @return rectangle representing the bounds.
|
||||
*/
|
||||
public RectF getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bounding rectangle for the SVG that was computed upon parsing. It may not be entirely accurate for certain curves or transformations, but is often better than nothing.
|
||||
* @return rectangle representing the computed bounds.
|
||||
*/
|
||||
public RectF getLimits() {
|
||||
return limits;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.larvalabs.svgandroid;
|
||||
|
||||
/**
|
||||
* Runtime exception thrown when there is a problem parsing an SVG.
|
||||
*
|
||||
* @author Larva Labs, LLC
|
||||
*/
|
||||
public class SVGParseException extends RuntimeException {
|
||||
|
||||
public SVGParseException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public SVGParseException(String s, Throwable throwable) {
|
||||
super(s, throwable);
|
||||
}
|
||||
|
||||
public SVGParseException(Throwable throwable) {
|
||||
super(throwable);
|
||||
}
|
||||
}
|
||||
1247
DroidFish/src/com/larvalabs/svgandroid/SVGParser.java
Normal file
1247
DroidFish/src/com/larvalabs/svgandroid/SVGParser.java
Normal file
File diff suppressed because it is too large
Load Diff
26
DroidFish/src/com/larvalabs/svgandroid/package-info.java
Normal file
26
DroidFish/src/com/larvalabs/svgandroid/package-info.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Provides a mechanism to parse a limited version of SVG Basic 1.1 files in to <code>android.graphics.Picture</code>
|
||||
* objects.
|
||||
*
|
||||
* This allows vector graphics files to be saved out of illustration software (such as Adobe Illustrator) as SVG Basic
|
||||
* and then used directly in an Android app. The <code>android.graphics.Picture</code> is a very optimized and
|
||||
* convenient vector graphics class. Performance is very good on a wide array of Android devices.
|
||||
* <p/>
|
||||
* Note that only SVG features that can be directly converted in to Android graphics calls are supported.
|
||||
* The following SVG Basic 1.1 features are not supported and will be ignored by the parser:
|
||||
* <ul>
|
||||
* <li>All text and font features.
|
||||
* <li>Styles.
|
||||
* <li>Symbols, conditional processing.
|
||||
* <li>Patterns.
|
||||
* <li>Masks, filters and views.
|
||||
* <li>Interactivity, linking, scripting and animation.
|
||||
* </ul>
|
||||
* Even with the above features missing, users will find that most Illustrator drawings will render perfectly well on
|
||||
* Android with this library.
|
||||
*
|
||||
* See the {@link com.larvalabs.svgandroid.SVGParser SVGParser} class for instructions on how to use the parser.
|
||||
*
|
||||
* @see com.larvalabs.svgandroid.SVGParser
|
||||
*/
|
||||
package com.larvalabs.svgandroid;
|
||||
Reference in New Issue
Block a user