/* * * * Copyright 2015. Appsi Mobile * * * * 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.larvalabs.svgandroid; import android.content.res.AssetManager; import android.content.res.Resources; import android.graphics.ColorFilter; import android.util.Log; import com.larvalabs.svgandroid.SVGParser.SVGHandler; import org.xml.sax.InputSource; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.zip.GZIPInputStream; /** * Builder for reading SVGs. Specify input, specify any parsing options (optional), then call * {@link #build()} to parse * and return a {@link SVG}. * * @since 24/12/2012 */ public class SVGBuilder { private InputStream data; private Integer searchColor = null; private Integer replaceColor = null; private ColorFilter strokeColorFilter = null, fillColorFilter = null; private boolean whiteMode = false; private boolean overideOpacity = false; private boolean closeInputStream = true; /** * Parse SVG data from an input stream. * * @param svgData the input stream, with SVG XML data in UTF-8 character encoding. * * @return the parsed SVG. */ public SVGBuilder readFromInputStream(InputStream svgData) { this.data = svgData; return this; } /** * Parse SVG data from a string. * * @param svgData the string containing SVG XML data. */ public SVGBuilder readFromString(String svgData) { this.data = new ByteArrayInputStream(svgData.getBytes()); return this; } /** * Parse SVG data from an Android application resource. * * @param resources the Android context resources. * @param resId the ID of the raw resource SVG. */ public SVGBuilder readFromResource(Resources resources, int resId) { this.data = resources.openRawResource(resId); return this; } /** * Parse SVG data from an Android application asset. * * @param assetMngr the Android asset manager. * @param svgPath the path to the SVG file in the application's assets. * * @throws IOException if there was a problem reading the file. */ public SVGBuilder readFromAsset(AssetManager assetMngr, String svgPath) throws IOException { this.data = assetMngr.open(svgPath); return this; } public SVGBuilder clearColorSwap() { searchColor = replaceColor = null; return this; } /** * Replaces a single colour with another. * * @param searchColor The colour in the SVG. * @param replaceColor The desired colour. */ public SVGBuilder setColorSwap(int searchColor, int replaceColor) { return setColorSwap(searchColor, replaceColor, false); } /** * Replaces a single colour with another, affecting the opacity. * * @param searchColor The colour in the SVG. * @param replaceColor The desired colour. * @param overideOpacity If true, combines the opacity defined in the SVG resource with the * alpha of replaceColor. */ public SVGBuilder setColorSwap(int searchColor, int replaceColor, boolean overideOpacity) { this.searchColor = searchColor; this.replaceColor = replaceColor; this.overideOpacity = overideOpacity; return this; } /** * In white-mode, fills are drawn in white and strokes are not drawn at all. */ public SVGBuilder setWhiteMode(boolean whiteMode) { this.whiteMode = whiteMode; return this; } /** * Applies a {@link ColorFilter} to the paint objects used to render the SVG. */ public SVGBuilder setColorFilter(ColorFilter colorFilter) { this.strokeColorFilter = this.fillColorFilter = colorFilter; return this; } /** * Applies a {@link ColorFilter} to strokes in the SVG. */ public SVGBuilder setStrokeColorFilter(ColorFilter colorFilter) { this.strokeColorFilter = colorFilter; return this; } /** * Applies a {@link ColorFilter} to fills in the SVG. */ public SVGBuilder setFillColorFilter(ColorFilter colorFilter) { this.fillColorFilter = colorFilter; return this; } /** * Whether or not to close the input stream after reading (ie. after calling {@link #build()} * .<br> * <em>(default is true)</em> */ public SVGBuilder setCloseInputStreamWhenDone(boolean closeInputStream) { this.closeInputStream = closeInputStream; return this; } /** * Loads, reads, parses the SVG (or SVGZ). * * @return the parsed SVG. * @throws SVGParseException if there is an error while parsing. */ public SVG build() throws SVGParseException { if (data == null) { throw new IllegalStateException( "SVG input not specified. Call one of the readFrom...() methods first."); } try { final SVGHandler handler = new SVGHandler(); handler.setColorSwap(searchColor, replaceColor, overideOpacity); handler.setWhiteMode(whiteMode); if (strokeColorFilter != null) { handler.strokePaint.setColorFilter(strokeColorFilter); } if (fillColorFilter != null) { handler.fillPaint.setColorFilter(fillColorFilter); } // SVGZ support (based on https://github.com/josefpavlik/svg-android/commit/fc0522b2e1): if (!data.markSupported()) { data = new BufferedInputStream(data); // decorate stream so we can use mark/reset } try { data.mark(4); byte[] magic = new byte[2]; int r = data.read(magic, 0, 2); int magicInt = (magic[0] + ((magic[1]) << 8)) & 0xffff; data.reset(); if (r == 2 && magicInt == GZIPInputStream.GZIP_MAGIC) { // Log.d(SVGParser.TAG, "SVG is gzipped"); data = new GZIPInputStream(data); } } catch (IOException ioe) { throw new SVGParseException(ioe); } return SVGParser.parse(new InputSource(data), handler); } finally { if (closeInputStream) { try { data.close(); } catch (IOException e) { Log.e(SVGParser.TAG, "Error closing SVG input stream.", e); } } } } }