From c2e82f118b8643bda0b9fa9798fe95f19237f2f9 Mon Sep 17 00:00:00 2001 From: xalag Date: Fri, 8 Mar 2019 23:31:47 +0100 Subject: [PATCH 1/9] Refactored models. Changed model hierarchy. Extracted Model parsing to seperate class. --- .../harjot/vectormaster/ModelParser.java | 224 +++++++ .../vectormaster/VectorMasterDrawable.java | 206 +----- .../harjot/vectormaster/VectorMasterView.java | 216 +------ .../vectormaster/models/ClipPathModel.java | 58 +- .../vectormaster/models/GroupModel.java | 201 +----- .../harjot/vectormaster/models/Model.java | 69 ++ .../vectormaster/models/ParentModel.java | 122 ++++ .../harjot/vectormaster/models/PathModel.java | 597 +++++++++--------- .../vectormaster/models/VectorModel.java | 116 +--- 9 files changed, 758 insertions(+), 1051 deletions(-) create mode 100644 vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/ModelParser.java create mode 100644 vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java create mode 100644 vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/ModelParser.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/ModelParser.java new file mode 100644 index 0000000..23c62b3 --- /dev/null +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/ModelParser.java @@ -0,0 +1,224 @@ +package com.sdsmdg.harjot.vectormaster; + +import android.content.res.Resources; +import com.sdsmdg.harjot.vectormaster.models.ClipPathModel; +import com.sdsmdg.harjot.vectormaster.models.GroupModel; +import com.sdsmdg.harjot.vectormaster.models.ParentModel; +import com.sdsmdg.harjot.vectormaster.models.PathModel; +import com.sdsmdg.harjot.vectormaster.models.VectorModel; +import com.sdsmdg.harjot.vectormaster.utilities.Utils; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.util.Stack; + +public class ModelParser { + + int getAttrPosition(XmlPullParser xpp, String attrName) { + for (int i = 0; i < xpp.getAttributeCount(); i++) { + if (xpp.getAttributeName(i).equals(attrName)) { + return i; + } + } + return -1; + } + + public VectorModel buildVectorModel(Resources resources, int resID) { + + if (resID == -1) { + return null; + } + + XmlPullParser xpp = resources.getXml(resID); + + int tempPosition; + VectorModel vectorModel = new VectorModel(); + PathModel pathModel = new PathModel(); + GroupModel groupModel = new GroupModel(); + ClipPathModel clipPathModel = new ClipPathModel(); + Stack parentModelStack = new Stack<>(); + parentModelStack.push(vectorModel); + + try { + int event = xpp.getEventType(); + while (event != XmlPullParser.END_DOCUMENT) { + String name = xpp.getName(); + switch (event) { + case XmlPullParser.START_TAG: + if (name.equals("vector")) { + tempPosition = getAttrPosition(xpp, "viewportWidth"); + vectorModel.setViewportWidth((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.VECTOR_VIEWPORT_WIDTH); + + tempPosition = getAttrPosition(xpp, "viewportHeight"); + vectorModel.setViewportHeight((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.VECTOR_VIEWPORT_HEIGHT); + + tempPosition = getAttrPosition(xpp, "alpha"); + vectorModel.setAlpha((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.VECTOR_ALPHA); + + tempPosition = getAttrPosition(xpp, "name"); + vectorModel.setName((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); + + tempPosition = getAttrPosition(xpp, "width"); + vectorModel.setWidth((tempPosition != -1) ? + Utils.getFloatFromDimensionString(xpp.getAttributeValue(tempPosition)) : + DefaultValues.VECTOR_WIDTH); + + tempPosition = getAttrPosition(xpp, "height"); + vectorModel.setHeight((tempPosition != -1) ? + Utils.getFloatFromDimensionString(xpp.getAttributeValue(tempPosition)) : + DefaultValues.VECTOR_HEIGHT); + } else if (name.equals("path")) { + pathModel = new PathModel(); + + tempPosition = getAttrPosition(xpp, "name"); + pathModel.setName((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); + + tempPosition = getAttrPosition(xpp, "fillAlpha"); + pathModel.setFillAlpha((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.PATH_FILL_ALPHA); + + tempPosition = getAttrPosition(xpp, "fillColor"); + pathModel.setFillColor((tempPosition != -1) ? + Utils.getColorFromString(xpp.getAttributeValue(tempPosition)) : + DefaultValues.PATH_FILL_COLOR); + + tempPosition = getAttrPosition(xpp, "fillType"); + pathModel.setFillType((tempPosition != -1) ? + Utils.getFillTypeFromString(xpp.getAttributeValue(tempPosition)) : + DefaultValues.PATH_FILL_TYPE); + + tempPosition = getAttrPosition(xpp, "pathData"); + pathModel.setPathData((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); + + tempPosition = getAttrPosition(xpp, "strokeAlpha"); + pathModel.setStrokeAlpha((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.PATH_STROKE_ALPHA); + + tempPosition = getAttrPosition(xpp, "strokeColor"); + pathModel.setStrokeColor((tempPosition != -1) ? + Utils.getColorFromString(xpp.getAttributeValue(tempPosition)) : + DefaultValues.PATH_STROKE_COLOR); + + tempPosition = getAttrPosition(xpp, "strokeLineCap"); + pathModel.setStrokeLineCap((tempPosition != -1) ? + Utils.getLineCapFromString(xpp.getAttributeValue(tempPosition)) : + DefaultValues.PATH_STROKE_LINE_CAP); + + tempPosition = getAttrPosition(xpp, "strokeLineJoin"); + pathModel.setStrokeLineJoin((tempPosition != -1) ? + Utils.getLineJoinFromString(xpp.getAttributeValue(tempPosition)) : + DefaultValues.PATH_STROKE_LINE_JOIN); + + tempPosition = getAttrPosition(xpp, "strokeMiterLimit"); + pathModel.setStrokeMiterLimit((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.PATH_STROKE_MITER_LIMIT); + + tempPosition = getAttrPosition(xpp, "strokeWidth"); + pathModel.setStrokeWidth((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.PATH_STROKE_WIDTH); + + tempPosition = getAttrPosition(xpp, "trimPathEnd"); + pathModel.setTrimPathEnd((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.PATH_TRIM_PATH_END); + + tempPosition = getAttrPosition(xpp, "trimPathOffset"); + pathModel.setTrimPathOffset((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.PATH_TRIM_PATH_OFFSET); + + tempPosition = getAttrPosition(xpp, "trimPathStart"); + pathModel.setTrimPathStart((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.PATH_TRIM_PATH_START); + + } else if (name.equals("group")) { + groupModel = new GroupModel(); + + tempPosition = getAttrPosition(xpp, "name"); + groupModel.setName((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); + + tempPosition = getAttrPosition(xpp, "pivotX"); + groupModel.setPivotX((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.GROUP_PIVOT_X); + + tempPosition = getAttrPosition(xpp, "pivotY"); + groupModel.setPivotY((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.GROUP_PIVOT_Y); + + tempPosition = getAttrPosition(xpp, "rotation"); + groupModel.setRotation((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.GROUP_ROTATION); + + tempPosition = getAttrPosition(xpp, "scaleX"); + groupModel.setScaleX((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.GROUP_SCALE_X); + + tempPosition = getAttrPosition(xpp, "scaleY"); + groupModel.setScaleY((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.GROUP_SCALE_Y); + + tempPosition = getAttrPosition(xpp, "translateX"); + groupModel.setTranslateX((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.GROUP_TRANSLATE_X); + + tempPosition = getAttrPosition(xpp, "translateY"); + groupModel.setTranslateY((tempPosition != -1) ? + Float.parseFloat(xpp.getAttributeValue(tempPosition)) : + DefaultValues.GROUP_TRANSLATE_Y); + + parentModelStack.push(groupModel); + } else if (name.equals("clip-path")) { + clipPathModel = new ClipPathModel(); + + tempPosition = getAttrPosition(xpp, "name"); + clipPathModel.setName((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); + + tempPosition = getAttrPosition(xpp, "pathData"); + clipPathModel.setPathData((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); + } + break; + + case XmlPullParser.END_TAG: + if (name.equals("path")) { + pathModel.calculateStatic(); + parentModelStack.peek().addChild(pathModel); + vectorModel.getFullpath().addPath(pathModel.getPath()); + } else if (name.equals("clip-path")) { + parentModelStack.peek().addChild(clipPathModel); + } else if (name.equals("group")) { + ParentModel topGroupModel = parentModelStack.pop(); + parentModelStack.peek().addChild(topGroupModel); + } else if (name.equals("vector")) { + vectorModel.calculateStatic(); + } + break; + } + event = xpp.next(); + } + } catch (XmlPullParserException | IOException e) { + e.printStackTrace(); + } + + return vectorModel; + + } + +} diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java index 8fd7d1e..d2b94be 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java @@ -13,6 +13,7 @@ import com.sdsmdg.harjot.vectormaster.models.ClipPathModel; import com.sdsmdg.harjot.vectormaster.models.GroupModel; +import com.sdsmdg.harjot.vectormaster.models.ParentModel; import com.sdsmdg.harjot.vectormaster.models.PathModel; import com.sdsmdg.harjot.vectormaster.models.VectorModel; import com.sdsmdg.harjot.vectormaster.utilities.Utils; @@ -35,8 +36,6 @@ public class VectorMasterDrawable extends Drawable { private float offsetX = 0.0f, offsetY = 0.0f; private float scaleX = 1.0f, scaleY = 1.0f; - private XmlPullParser xpp; - String TAG = "VECTOR_MASTER"; private Matrix scaleMatrix; @@ -78,166 +77,11 @@ private void init() { } private void buildVectorModel() { - if (resID == -1) { vectorModel = null; return; } - - xpp = resources.getXml(resID); - - int tempPosition; - PathModel pathModel = new PathModel(); - vectorModel = new VectorModel(); - GroupModel groupModel = new GroupModel(); - ClipPathModel clipPathModel = new ClipPathModel(); - Stack groupModelStack = new Stack<>(); - - try { - int event = xpp.getEventType(); - while (event != XmlPullParser.END_DOCUMENT) { - String name = xpp.getName(); - switch (event) { - case XmlPullParser.START_TAG: - if (name.equals("vector")) { - tempPosition = getAttrPosition(xpp, "viewportWidth"); - vectorModel.setViewportWidth((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.VECTOR_VIEWPORT_WIDTH); - - tempPosition = getAttrPosition(xpp, "viewportHeight"); - vectorModel.setViewportHeight((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.VECTOR_VIEWPORT_HEIGHT); - - tempPosition = getAttrPosition(xpp, "alpha"); - vectorModel.setAlpha((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.VECTOR_ALPHA); - - tempPosition = getAttrPosition(xpp, "name"); - vectorModel.setName((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); - - tempPosition = getAttrPosition(xpp, "width"); - vectorModel.setWidth((tempPosition != -1) ? Utils.getFloatFromDimensionString(xpp.getAttributeValue(tempPosition)) : DefaultValues.VECTOR_WIDTH); - - tempPosition = getAttrPosition(xpp, "height"); - vectorModel.setHeight((tempPosition != -1) ? Utils.getFloatFromDimensionString(xpp.getAttributeValue(tempPosition)) : DefaultValues.VECTOR_HEIGHT); - } else if (name.equals("path")) { - pathModel = new PathModel(); - - tempPosition = getAttrPosition(xpp, "name"); - pathModel.setName((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); - - tempPosition = getAttrPosition(xpp, "fillAlpha"); - pathModel.setFillAlpha((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_FILL_ALPHA); - - tempPosition = getAttrPosition(xpp, "fillColor"); - pathModel.setFillColor((tempPosition != -1) ? Utils.getColorFromString(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_FILL_COLOR); - - tempPosition = getAttrPosition(xpp, "fillType"); - pathModel.setFillType((tempPosition != -1) ? Utils.getFillTypeFromString(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_FILL_TYPE); - - tempPosition = getAttrPosition(xpp, "pathData"); - pathModel.setPathData((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); - - tempPosition = getAttrPosition(xpp, "strokeAlpha"); - pathModel.setStrokeAlpha((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_STROKE_ALPHA); - - tempPosition = getAttrPosition(xpp, "strokeColor"); - pathModel.setStrokeColor((tempPosition != -1) ? Utils.getColorFromString(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_STROKE_COLOR); - - tempPosition = getAttrPosition(xpp, "strokeLineCap"); - pathModel.setStrokeLineCap((tempPosition != -1) ? Utils.getLineCapFromString(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_STROKE_LINE_CAP); - - tempPosition = getAttrPosition(xpp, "strokeLineJoin"); - pathModel.setStrokeLineJoin((tempPosition != -1) ? Utils.getLineJoinFromString(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_STROKE_LINE_JOIN); - - tempPosition = getAttrPosition(xpp, "strokeMiterLimit"); - pathModel.setStrokeMiterLimit((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_STROKE_MITER_LIMIT); - - tempPosition = getAttrPosition(xpp, "strokeWidth"); - pathModel.setStrokeWidth((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_STROKE_WIDTH); - - tempPosition = getAttrPosition(xpp, "trimPathEnd"); - pathModel.setTrimPathEnd((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_TRIM_PATH_END); - - tempPosition = getAttrPosition(xpp, "trimPathOffset"); - pathModel.setTrimPathOffset((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_TRIM_PATH_OFFSET); - - tempPosition = getAttrPosition(xpp, "trimPathStart"); - pathModel.setTrimPathStart((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_TRIM_PATH_START); - - pathModel.buildPath(useLegacyParser); - } else if (name.equals("group")) { - groupModel = new GroupModel(); - - tempPosition = getAttrPosition(xpp, "name"); - groupModel.setName((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); - - tempPosition = getAttrPosition(xpp, "pivotX"); - groupModel.setPivotX((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.GROUP_PIVOT_X); - - tempPosition = getAttrPosition(xpp, "pivotY"); - groupModel.setPivotY((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.GROUP_PIVOT_Y); - - tempPosition = getAttrPosition(xpp, "rotation"); - groupModel.setRotation((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.GROUP_ROTATION); - - tempPosition = getAttrPosition(xpp, "scaleX"); - groupModel.setScaleX((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.GROUP_SCALE_X); - - tempPosition = getAttrPosition(xpp, "scaleY"); - groupModel.setScaleY((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.GROUP_SCALE_Y); - - tempPosition = getAttrPosition(xpp, "translateX"); - groupModel.setTranslateX((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.GROUP_TRANSLATE_X); - - tempPosition = getAttrPosition(xpp, "translateY"); - groupModel.setTranslateY((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.GROUP_TRANSLATE_Y); - - groupModelStack.push(groupModel); - } else if (name.equals("clip-path")) { - clipPathModel = new ClipPathModel(); - - tempPosition = getAttrPosition(xpp, "name"); - clipPathModel.setName((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); - - tempPosition = getAttrPosition(xpp, "pathData"); - clipPathModel.setPathData((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); - - clipPathModel.buildPath(useLegacyParser); - } - break; - - case XmlPullParser.END_TAG: - if (name.equals("path")) { - if (groupModelStack.size() == 0) { - vectorModel.addPathModel(pathModel); - } else { - groupModelStack.peek().addPathModel(pathModel); - } - vectorModel.getFullpath().addPath(pathModel.getPath()); - } else if (name.equals("clip-path")) { - if (groupModelStack.size() == 0) { - vectorModel.addClipPathModel(clipPathModel); - } else { - groupModelStack.peek().addClipPathModel(clipPathModel); - } - } else if (name.equals("group")) { - GroupModel topGroupModel = groupModelStack.pop(); - if (groupModelStack.size() == 0) { - topGroupModel.setParent(null); - vectorModel.addGroupModel(topGroupModel); - } else { - topGroupModel.setParent(groupModelStack.peek()); - groupModelStack.peek().addGroupModel(topGroupModel); - } - } else if (name.equals("vector")) { - vectorModel.buildTransformMatrices(); - } - break; - } - event = xpp.next(); - } - } catch (XmlPullParserException | IOException e) { - e.printStackTrace(); - } - + vectorModel = new ModelParser().buildVectorModel(resources, resID); } private int getAttrPosition(XmlPullParser xpp, String attrName) { @@ -306,10 +150,10 @@ public void draw(Canvas canvas) { if (left != 0 || top != 0) { tempSaveCount = canvas.save(); canvas.translate(left, top); - vectorModel.drawPaths(canvas, offsetX, offsetY, scaleX, scaleY); + vectorModel.draw(canvas, offsetX, offsetY, scaleX, scaleY); canvas.restoreToCount(tempSaveCount); } else { - vectorModel.drawPaths(canvas, offsetX, offsetY, scaleX, scaleY); + vectorModel.draw(canvas, offsetX, offsetY, scaleX, scaleY); } } @@ -354,12 +198,12 @@ private void buildScaleMatrix() { } private void scaleAllPaths() { - vectorModel.scaleAllPaths(scaleMatrix); + vectorModel.scalePaths(scaleMatrix); } private void scaleAllStrokes() { strokeRatio = Math.min(width / vectorModel.getWidth(), height / vectorModel.getHeight()); - vectorModel.scaleAllStrokeWidth(strokeRatio); + vectorModel.scaleStrokeWidth(strokeRatio); } public Path getFullPath() { @@ -370,47 +214,15 @@ public Path getFullPath() { } public GroupModel getGroupModelByName(String name) { - GroupModel gModel; - for (GroupModel groupModel : vectorModel.getGroupModels()) { - if (Utils.isEqual(groupModel.getName(), name)) { - return groupModel; - } else { - gModel = groupModel.getGroupModelByName(name); - if (gModel != null) - return gModel; - } - } - return null; + return vectorModel.getGroupModelByName(name); } public PathModel getPathModelByName(String name) { - PathModel pModel = null; - for (PathModel pathModel : vectorModel.getPathModels()) { - if (Utils.isEqual(pathModel.getName(), name)) { - return pathModel; - } - } - for (GroupModel groupModel : vectorModel.getGroupModels()) { - pModel = groupModel.getPathModelByName(name); - if (pModel != null && Utils.isEqual(pModel.getName(), name)) - return pModel; - } - return pModel; + return vectorModel.getPathModelByName(name); } public ClipPathModel getClipPathModelByName(String name) { - ClipPathModel cModel = null; - for (ClipPathModel clipPathModel : vectorModel.getClipPathModels()) { - if (Utils.isEqual(clipPathModel.getName(), name)) { - return clipPathModel; - } - } - for (GroupModel groupModel : vectorModel.getGroupModels()) { - cModel = groupModel.getClipPathModelByName(name); - if (cModel != null && Utils.isEqual(cModel.getName(), name)) - return cModel; - } - return cModel; + return vectorModel.getClipPathModelByName(name); } public void update() { diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java index 0f63c36..1b5e79a 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java @@ -13,13 +13,6 @@ import com.sdsmdg.harjot.vectormaster.models.GroupModel; import com.sdsmdg.harjot.vectormaster.models.PathModel; import com.sdsmdg.harjot.vectormaster.models.VectorModel; -import com.sdsmdg.harjot.vectormaster.utilities.Utils; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.util.Stack; public class VectorMasterView extends View { @@ -30,8 +23,6 @@ public class VectorMasterView extends View { int resID = -1; boolean useLegacyParser = true; - XmlPullParser xpp; - String TAG = "VECTOR_MASTER"; private Matrix scaleMatrix; @@ -83,169 +74,8 @@ void buildVectorModel() { return; } - xpp = resources.getXml(resID); - - int tempPosition; - PathModel pathModel = new PathModel(); - vectorModel = new VectorModel(); - GroupModel groupModel = new GroupModel(); - ClipPathModel clipPathModel = new ClipPathModel(); - Stack groupModelStack = new Stack<>(); - - try { - int event = xpp.getEventType(); - while (event != XmlPullParser.END_DOCUMENT) { - String name = xpp.getName(); - switch (event) { - case XmlPullParser.START_TAG: - if (name.equals("vector")) { - tempPosition = getAttrPosition(xpp, "viewportWidth"); - vectorModel.setViewportWidth((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.VECTOR_VIEWPORT_WIDTH); - - tempPosition = getAttrPosition(xpp, "viewportHeight"); - vectorModel.setViewportHeight((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.VECTOR_VIEWPORT_HEIGHT); - - tempPosition = getAttrPosition(xpp, "alpha"); - vectorModel.setAlpha((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.VECTOR_ALPHA); - - tempPosition = getAttrPosition(xpp, "name"); - vectorModel.setName((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); + vectorModel = new ModelParser().buildVectorModel(resources, resID); - tempPosition = getAttrPosition(xpp, "width"); - vectorModel.setWidth((tempPosition != -1) ? Utils.getFloatFromDimensionString(xpp.getAttributeValue(tempPosition)) : DefaultValues.VECTOR_WIDTH); - - tempPosition = getAttrPosition(xpp, "height"); - vectorModel.setHeight((tempPosition != -1) ? Utils.getFloatFromDimensionString(xpp.getAttributeValue(tempPosition)) : DefaultValues.VECTOR_HEIGHT); - } else if (name.equals("path")) { - pathModel = new PathModel(); - - tempPosition = getAttrPosition(xpp, "name"); - pathModel.setName((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); - - tempPosition = getAttrPosition(xpp, "fillAlpha"); - pathModel.setFillAlpha((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_FILL_ALPHA); - - tempPosition = getAttrPosition(xpp, "fillColor"); - pathModel.setFillColor((tempPosition != -1) ? Utils.getColorFromString(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_FILL_COLOR); - - tempPosition = getAttrPosition(xpp, "fillType"); - pathModel.setFillType((tempPosition != -1) ? Utils.getFillTypeFromString(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_FILL_TYPE); - - tempPosition = getAttrPosition(xpp, "pathData"); - pathModel.setPathData((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); - - tempPosition = getAttrPosition(xpp, "strokeAlpha"); - pathModel.setStrokeAlpha((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_STROKE_ALPHA); - - tempPosition = getAttrPosition(xpp, "strokeColor"); - pathModel.setStrokeColor((tempPosition != -1) ? Utils.getColorFromString(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_STROKE_COLOR); - - tempPosition = getAttrPosition(xpp, "strokeLineCap"); - pathModel.setStrokeLineCap((tempPosition != -1) ? Utils.getLineCapFromString(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_STROKE_LINE_CAP); - - tempPosition = getAttrPosition(xpp, "strokeLineJoin"); - pathModel.setStrokeLineJoin((tempPosition != -1) ? Utils.getLineJoinFromString(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_STROKE_LINE_JOIN); - - tempPosition = getAttrPosition(xpp, "strokeMiterLimit"); - pathModel.setStrokeMiterLimit((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_STROKE_MITER_LIMIT); - - tempPosition = getAttrPosition(xpp, "strokeWidth"); - pathModel.setStrokeWidth((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_STROKE_WIDTH); - - tempPosition = getAttrPosition(xpp, "trimPathEnd"); - pathModel.setTrimPathEnd((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_TRIM_PATH_END); - - tempPosition = getAttrPosition(xpp, "trimPathOffset"); - pathModel.setTrimPathOffset((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_TRIM_PATH_OFFSET); - - tempPosition = getAttrPosition(xpp, "trimPathStart"); - pathModel.setTrimPathStart((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.PATH_TRIM_PATH_START); - - pathModel.buildPath(useLegacyParser); - } else if (name.equals("group")) { - groupModel = new GroupModel(); - - tempPosition = getAttrPosition(xpp, "name"); - groupModel.setName((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); - - tempPosition = getAttrPosition(xpp, "pivotX"); - groupModel.setPivotX((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.GROUP_PIVOT_X); - - tempPosition = getAttrPosition(xpp, "pivotY"); - groupModel.setPivotY((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.GROUP_PIVOT_Y); - - tempPosition = getAttrPosition(xpp, "rotation"); - groupModel.setRotation((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.GROUP_ROTATION); - - tempPosition = getAttrPosition(xpp, "scaleX"); - groupModel.setScaleX((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.GROUP_SCALE_X); - - tempPosition = getAttrPosition(xpp, "scaleY"); - groupModel.setScaleY((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.GROUP_SCALE_Y); - - tempPosition = getAttrPosition(xpp, "translateX"); - groupModel.setTranslateX((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.GROUP_TRANSLATE_X); - - tempPosition = getAttrPosition(xpp, "translateY"); - groupModel.setTranslateY((tempPosition != -1) ? Float.parseFloat(xpp.getAttributeValue(tempPosition)) : DefaultValues.GROUP_TRANSLATE_Y); - - groupModelStack.push(groupModel); - } else if (name.equals("clip-path")) { - clipPathModel = new ClipPathModel(); - - tempPosition = getAttrPosition(xpp, "name"); - clipPathModel.setName((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); - - tempPosition = getAttrPosition(xpp, "pathData"); - clipPathModel.setPathData((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); - - clipPathModel.buildPath(useLegacyParser); - } - break; - - case XmlPullParser.END_TAG: - if (name.equals("path")) { - if (groupModelStack.size() == 0) { - vectorModel.addPathModel(pathModel); - } else { - groupModelStack.peek().addPathModel(pathModel); - } - vectorModel.getFullpath().addPath(pathModel.getPath()); - } else if (name.equals("clip-path")) { - if (groupModelStack.size() == 0) { - vectorModel.addClipPathModel(clipPathModel); - } else { - groupModelStack.peek().addClipPathModel(clipPathModel); - } - } else if (name.equals("group")) { - GroupModel topGroupModel = groupModelStack.pop(); - if (groupModelStack.size() == 0) { - topGroupModel.setParent(null); - vectorModel.addGroupModel(topGroupModel); - } else { - topGroupModel.setParent(groupModelStack.peek()); - groupModelStack.peek().addGroupModel(topGroupModel); - } - } else if (name.equals("vector")) { - vectorModel.buildTransformMatrices(); - } - break; - } - event = xpp.next(); - } - } catch (XmlPullParserException | IOException e) { - e.printStackTrace(); - } - - } - - int getAttrPosition(XmlPullParser xpp, String attrName) { - for (int i = 0; i < xpp.getAttributeCount(); i++) { - if (xpp.getAttributeName(i).equals(attrName)) { - return i; - } - } - return -1; } public int getResID() { @@ -282,7 +112,7 @@ protected void onDraw(Canvas canvas) { setAlpha(vectorModel.getAlpha()); - vectorModel.drawPaths(canvas); + vectorModel.draw(canvas); } @@ -302,12 +132,12 @@ void buildScaleMatrix() { } void scaleAllPaths() { - vectorModel.scaleAllPaths(scaleMatrix); + vectorModel.scalePaths(scaleMatrix); } void scaleAllStrokes() { strokeRatio = Math.min(width / vectorModel.getWidth(), height / vectorModel.getHeight()); - vectorModel.scaleAllStrokeWidth(strokeRatio); + vectorModel.scaleStrokeWidth(strokeRatio); } public Path getFullPath() { @@ -318,47 +148,15 @@ public Path getFullPath() { } public GroupModel getGroupModelByName(String name) { - GroupModel gModel; - for (GroupModel groupModel : vectorModel.getGroupModels()) { - if (Utils.isEqual(groupModel.getName(), name)) { - return groupModel; - } else { - gModel = groupModel.getGroupModelByName(name); - if (gModel != null) - return gModel; - } - } - return null; + return vectorModel.getGroupModelByName(name); } public PathModel getPathModelByName(String name) { - PathModel pModel = null; - for (PathModel pathModel : vectorModel.getPathModels()) { - if (Utils.isEqual(pathModel.getName(), name)) { - return pathModel; - } - } - for (GroupModel groupModel : vectorModel.getGroupModels()) { - pModel = groupModel.getPathModelByName(name); - if (pModel != null && Utils.isEqual(pModel.getName(), name)) - return pModel; - } - return pModel; + return vectorModel.getPathModelByName(name); } public ClipPathModel getClipPathModelByName(String name) { - ClipPathModel cModel = null; - for (ClipPathModel clipPathModel : vectorModel.getClipPathModels()) { - if (Utils.isEqual(clipPathModel.getName(), name)) { - return clipPathModel; - } - } - for (GroupModel groupModel : vectorModel.getGroupModels()) { - cModel = groupModel.getClipPathModelByName(name); - if (cModel != null && Utils.isEqual(cModel.getName(), name)) - return cModel; - } - return cModel; + return vectorModel.getClipPathModelByName(name); } public void update() { diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java index d37c0df..f6492da 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java @@ -1,17 +1,13 @@ package com.sdsmdg.harjot.vectormaster.models; - +import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; -import android.graphics.RectF; - -import com.sdsmdg.harjot.vectormaster.utilities.parser.PathParser; -public class ClipPathModel { - private String name; +public class ClipPathModel extends Model { private String pathData; private Path originalPath; @@ -27,20 +23,31 @@ public ClipPathModel() { clipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); } - public void buildPath(boolean useLegacyParser) { - if (useLegacyParser) { - originalPath = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); - } else { - originalPath = PathParser.doPath(pathData); - } + @Override + public void prepare(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY) { + canvas.clipPath(getScaledAndOffsetPath(path, offsetX, offsetY, scaleX, scaleY)); + } - path = new Path(originalPath); + @Override + public void draw(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY) { + //clip path does no drawing } - public void transform(Matrix matrix) { + @Override + public void calculateStatic() { + originalPath = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); path = new Path(originalPath); + } + + @Override + public void scaleStrokeWidth(float ratio) { - path.transform(matrix); + } + + @Override + public void scalePaths(Matrix originalScaleMatrix, Matrix concatTransformMatrix) { + path = new Path(originalPath); + path.transform(concatTransformMatrix); } public Paint getClipPaint() { @@ -51,14 +58,6 @@ public void setClipPaint(Paint clipPaint) { this.clipPaint = clipPaint; } - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - public String getPathData() { return pathData; } @@ -75,19 +74,6 @@ public void setPath(Path path) { this.path = path; } - public Path getScaledAndOffsetPath(float offsetX, float offsetY, float scaleX, float scaleY) { - Path newPath = new Path(path); - newPath.offset(offsetX, offsetY); - newPath.transform(getScaleMatrix(newPath, scaleX, scaleY)); - return newPath; - } - public Matrix getScaleMatrix(Path srcPath, float scaleX, float scaleY) { - Matrix scaleMatrix = new Matrix(); - RectF rectF = new RectF(); - srcPath.computeBounds(rectF, true); - scaleMatrix.setScale(scaleX, scaleY, rectF.left, rectF.top); - return scaleMatrix; - } } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java index af4f439..6a66cd7 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java @@ -1,31 +1,16 @@ package com.sdsmdg.harjot.vectormaster.models; - -import android.graphics.Canvas; import android.graphics.Matrix; import com.sdsmdg.harjot.vectormaster.DefaultValues; -import com.sdsmdg.harjot.vectormaster.utilities.Utils; - -import java.util.ArrayList; -public class GroupModel { - private String name; +public class GroupModel extends ParentModel { private float rotation; private float pivotX, pivotY; private float scaleX, scaleY; private float translateX, translateY; - private Matrix scaleMatrix; - private Matrix originalTransformMatrix; - private Matrix finalTransformMatrix; - private GroupModel parent; - - private ArrayList groupModels; - private ArrayList pathModels; - private ArrayList clipPathModels; - public GroupModel() { rotation = DefaultValues.GROUP_ROTATION; pivotX = DefaultValues.GROUP_PIVOT_X; @@ -34,185 +19,15 @@ public GroupModel() { scaleY = DefaultValues.GROUP_SCALE_Y; translateX = DefaultValues.GROUP_TRANSLATE_X; translateY = DefaultValues.GROUP_TRANSLATE_Y; - - groupModels = new ArrayList<>(); - pathModels = new ArrayList<>(); - clipPathModels = new ArrayList<>(); - } - - public void drawPaths(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY) { - for (ClipPathModel clipPathModel : clipPathModels) { - canvas.clipPath(clipPathModel.getScaledAndOffsetPath(offsetX, offsetY, scaleX, scaleY)); - } - for (GroupModel groupModel : groupModels) { - groupModel.drawPaths(canvas, offsetX, offsetY, scaleX, scaleY); - } - for (PathModel pathModel : pathModels) { - if (pathModel.isFillAndStroke()) { - pathModel.makeFillPaint(); - canvas.drawPath(pathModel.getScaledAndOffsetPath(offsetX, offsetY, scaleX, scaleY), pathModel.getPathPaint()); - pathModel.makeStrokePaint(); - canvas.drawPath(pathModel.getScaledAndOffsetPath(offsetX, offsetY, scaleX, scaleY), pathModel.getPathPaint()); - } else { - canvas.drawPath(pathModel.getScaledAndOffsetPath(offsetX, offsetY, scaleX, scaleY), pathModel.getPathPaint()); - } - } - } - - public void drawPaths(Canvas canvas) { - for (ClipPathModel clipPathModel : clipPathModels) { - canvas.clipPath(clipPathModel.getPath()); - } - for (GroupModel groupModel : groupModels) { - groupModel.drawPaths(canvas); - } - for (PathModel pathModel : pathModels) { - if (pathModel.isFillAndStroke()) { - pathModel.makeFillPaint(); - canvas.drawPath(pathModel.getPath(), pathModel.getPathPaint()); - pathModel.makeStrokePaint(); - canvas.drawPath(pathModel.getPath(), pathModel.getPathPaint()); - } else { - canvas.drawPath(pathModel.getPath(), pathModel.getPathPaint()); - } - } - } - - public void scaleAllPaths(Matrix scaleMatrix) { - this.scaleMatrix = scaleMatrix; - finalTransformMatrix = new Matrix(originalTransformMatrix); - finalTransformMatrix.postConcat(scaleMatrix); - for (GroupModel groupModel : groupModels) { - groupModel.scaleAllPaths(scaleMatrix); - } - for (PathModel pathModel : pathModels) { - pathModel.transform(finalTransformMatrix); - } - for (ClipPathModel clipPathModel : clipPathModels) { - clipPathModel.transform(finalTransformMatrix); - } - } - - public void scaleAllStrokeWidth(float ratio) { - for (GroupModel groupModel : groupModels) { - groupModel.scaleAllStrokeWidth(ratio); - } - for (PathModel pathModel : pathModels) { - pathModel.setStrokeRatio(ratio); - } - } - - public void buildTransformMatrix() { - - originalTransformMatrix = new Matrix(); - - originalTransformMatrix.postScale(scaleX, scaleY, pivotX, pivotY); - originalTransformMatrix.postRotate(rotation, pivotX, pivotY); - originalTransformMatrix.postTranslate(translateX, translateY); - - if (parent != null) { - originalTransformMatrix.postConcat(parent.getOriginalTransformMatrix()); - } - - for (GroupModel groupModel : groupModels) { - groupModel.buildTransformMatrix(); - } - } - - public void updateAndScalePaths() { - if (scaleMatrix != null) { - buildTransformMatrix(); - scaleAllPaths(scaleMatrix); - } - } - - public GroupModel getGroupModelByName(String name) { - GroupModel grpModel = null; - for (GroupModel groupModel : groupModels) { - if (Utils.isEqual(groupModel.getName(), name)) { - grpModel = groupModel; - return grpModel; - } else { - grpModel = groupModel.getGroupModelByName(name); - if (grpModel != null) - return grpModel; - } - } - return grpModel; - } - - public PathModel getPathModelByName(String name) { - PathModel pModel = null; - for (PathModel pathModel : pathModels) { - if (Utils.isEqual(pathModel.getName(), name)) { - return pathModel; - } - } - for (GroupModel groupModel : groupModels) { - pModel = groupModel.getPathModelByName(name); - if (pModel != null && Utils.isEqual(pModel.getName(), name)) - return pModel; - } - return pModel; - } - - public ClipPathModel getClipPathModelByName(String name) { - ClipPathModel cModel = null; - for (ClipPathModel clipPathModel : getClipPathModels()) { - if (Utils.isEqual(clipPathModel.getName(), name)) { - return clipPathModel; - } - } - for (GroupModel groupModel : getGroupModels()) { - cModel = groupModel.getClipPathModelByName(name); - if (cModel != null && Utils.isEqual(cModel.getName(), name)) - return cModel; - } - return cModel; - } - - public Matrix getOriginalTransformMatrix() { - return originalTransformMatrix; - } - - public GroupModel getParent() { - return parent; - } - - public void setParent(GroupModel parent) { - this.parent = parent; - } - - public void addGroupModel(GroupModel groupModel) { - groupModels.add(groupModel); - } - - public ArrayList getGroupModels() { - return groupModels; - } - - public void addPathModel(PathModel pathModel) { - pathModels.add(pathModel); - } - - public ArrayList getPathModels() { - return pathModels; - } - - public void addClipPathModel(ClipPathModel clipPathModel) { - clipPathModels.add(clipPathModel); - } - - public ArrayList getClipPathModels() { - return clipPathModels; - } - - public String getName() { - return name; } - public void setName(String name) { - this.name = name; + @Override + protected Matrix createTransformMatrix() { + Matrix transformMatrix = new Matrix(); + transformMatrix.postScale(scaleX, scaleY, pivotX, pivotY); + transformMatrix.postRotate(rotation, pivotX, pivotY); + transformMatrix.postTranslate(translateX, translateY); + return transformMatrix; } public float getRotation() { diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java new file mode 100644 index 0000000..32ac29d --- /dev/null +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java @@ -0,0 +1,69 @@ +package com.sdsmdg.harjot.vectormaster.models; + +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Path; +import android.graphics.RectF; + +public abstract class Model { + + private String name; + private ParentModel parent; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ParentModel getParent() { + return parent; + } + + public void setParent(ParentModel parent) { + this.parent = parent; + } + + public abstract void calculateStatic(); + + public abstract void scalePaths(Matrix originalScaleMatrix, Matrix concatTransformMatrix); + + public abstract void scaleStrokeWidth(float ratio); + + public abstract void prepare(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY); + + public abstract void draw(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY); + + public void draw(Canvas canvas) { + draw(canvas, 0.0f, 0.0f, 1.0f, 1.0f); + } + + public void prepare(Canvas canvas) { + prepare(canvas, 0.0f, 0.0f, 1.0f, 1.0f); + } + + public Path getScaledAndOffsetPath(Path srcPath, float offsetX, float offsetY, float scaleX, float scaleY) { + if (offsetX == 0 && offsetY == 0 && scaleX == 1 && scaleY == 1) { + return srcPath; + } else { + Path newPath = new Path(srcPath); + newPath.offset(offsetX, offsetY); + newPath.transform(getScaleMatrix(newPath, scaleX, scaleY)); + return newPath; + } + } + + public Matrix getScaleMatrix(Path srcPath, float scaleX, float scaleY) { + Matrix scaleMatrix = new Matrix(); + RectF rectF = new RectF(); + srcPath.computeBounds(rectF, true); + scaleMatrix.setScale(scaleX, scaleY, rectF.left, rectF.top); + return scaleMatrix; + } + + + + +} diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java new file mode 100644 index 0000000..fdbc0e2 --- /dev/null +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java @@ -0,0 +1,122 @@ +package com.sdsmdg.harjot.vectormaster.models; + +import android.graphics.Canvas; +import android.graphics.Matrix; + +import java.util.ArrayList; + +public abstract class ParentModel extends Model { + + private ArrayList children = new ArrayList<>(0); + private Matrix scaleMatrix; + private Matrix transformMatrix; + + public ArrayList getChildren() { + return children; + } + + public void addChild(Model model) { + getChildren().add(model); + model.setParent(this); + } + + public Matrix getTransformMatrix() { + return transformMatrix; + } + + protected Matrix createTransformMatrix() { + return new Matrix(); + } + + @Override + public void calculateStatic() { + //create own matrix + transformMatrix = createTransformMatrix(); + //add the one from the parrent if there is a parent + if (getParent() != null) { + transformMatrix.postConcat(getParent().getTransformMatrix()); + } + //tell all children to do the calculation + for (Model model : getChildren()) { + model.calculateStatic(); + } + } + + @Override + public void scalePaths(Matrix originalScaleMatrix, Matrix concatTransformMatrix) { + this.scaleMatrix = originalScaleMatrix; + Matrix finalTransformMatrix = new Matrix(getTransformMatrix()); + finalTransformMatrix.postConcat(scaleMatrix); + for (Model child : children) { + child.scalePaths(originalScaleMatrix, finalTransformMatrix); + } + } + + public void scalePaths(Matrix originalScaleMatrix) { + scalePaths(originalScaleMatrix, null); //because we are a parentModel only the first Matrix matters the second one is not used. + } + + public void updateAndScalePaths() { + if (scaleMatrix != null) { + calculateStatic(); + scalePaths(scaleMatrix); + } + } + + @Override + public void scaleStrokeWidth(float ratio) { + for (Model model : getChildren()) { + model.scaleStrokeWidth(ratio); + } + } + + @Override + public void prepare(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY) { + //parents by default do not prepare the canvas recursively + } + + @Override + public void draw(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY) { + //parents prepare just their own children before they draw + for (Model child : getChildren()) { + child.prepare(canvas, offsetX, offsetY, scaleX, scaleY); + } + for (Model child : getChildren()) { + child.draw(canvas, offsetX, offsetY, scaleX, scaleY); + } + } + + public GroupModel getGroupModelByName(String name) { + return (GroupModel) getModelByTypeAndName(GroupModel.class, name); + } + + public PathModel getPathModelByName(String name) { + return (PathModel) getModelByTypeAndName(PathModel.class, name); + } + + public ClipPathModel getClipPathModelByName(String name) { + return (ClipPathModel) getModelByTypeAndName(ClipPathModel.class, name); + } + + public Model getModelByTypeAndName(Class clazz, String name) { + if (name == null) { + return null; + } + for (Model child : children) { + //check if the child is the searched model + if (name.equals(child.getName()) && clazz.isAssignableFrom(child.getClass())) { + return child; + } + //ask the child to check its children for the searched model + if (child instanceof ParentModel) { + Model subchild = ((ParentModel) child).getModelByTypeAndName(clazz, name); + if (subchild != null) { + return subchild; + } + } + //its not this child and not one of its children or children-children, so go on to the next child + } + return null; //searched element was not found withis this parent + } + +} diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java index d91dc67..1b7837f 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java @@ -1,314 +1,309 @@ package com.sdsmdg.harjot.vectormaster.models; +import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PathMeasure; -import android.graphics.RectF; import com.sdsmdg.harjot.vectormaster.DefaultValues; -import com.sdsmdg.harjot.vectormaster.VectorMasterView; import com.sdsmdg.harjot.vectormaster.utilities.Utils; -import com.sdsmdg.harjot.vectormaster.utilities.parser.PathParser; - -public class PathModel { - - private String name; - - private float fillAlpha; - private int fillColor; - - private Path.FillType fillType; - - private String pathData; - - private float trimPathStart, trimPathEnd, trimPathOffset; - - private float strokeAlpha; - private int strokeColor; - private Paint.Cap strokeLineCap; - private Paint.Join strokeLineJoin; - private float strokeMiterLimit; - private float strokeWidth; - - private float strokeRatio; - - private boolean isFillAndStroke = false; - - // Support for trim-paths is not available - - private Path originalPath; - private Path path; - private Path trimmedPath; - private Paint pathPaint; - - private Matrix scaleMatrix; - - public PathModel() { - fillAlpha = DefaultValues.PATH_FILL_ALPHA; - fillColor = DefaultValues.PATH_FILL_COLOR; - fillType = DefaultValues.PATH_FILL_TYPE; - trimPathStart = DefaultValues.PATH_TRIM_PATH_START; - trimPathEnd = DefaultValues.PATH_TRIM_PATH_END; - trimPathOffset = DefaultValues.PATH_TRIM_PATH_OFFSET; - strokeAlpha = DefaultValues.PATH_STROKE_ALPHA; - strokeColor = DefaultValues.PATH_STROKE_COLOR; - strokeLineCap = DefaultValues.PATH_STROKE_LINE_CAP; - strokeLineJoin = DefaultValues.PATH_STROKE_LINE_JOIN; - strokeMiterLimit = DefaultValues.PATH_STROKE_MITER_LIMIT; - strokeWidth = DefaultValues.PATH_STROKE_WIDTH; - strokeRatio = DefaultValues.PATH_STROKE_RATIO; - - pathPaint = new Paint(); - pathPaint.setAntiAlias(true); - updatePaint(); - } - - public void buildPath(boolean useLegacyParser) { - if (useLegacyParser) { - originalPath = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); - } else { - originalPath = PathParser.doPath(pathData); - } - if (originalPath != null) - originalPath.setFillType(fillType); +public class PathModel extends Model { + + private float fillAlpha; + private int fillColor; + + private Path.FillType fillType; + + private String pathData; + + private float trimPathStart, trimPathEnd, trimPathOffset; + + private float strokeAlpha; + private int strokeColor; + private Paint.Cap strokeLineCap; + private Paint.Join strokeLineJoin; + private float strokeMiterLimit; + private float strokeWidth; + + private float strokeRatio; + + private boolean isFillAndStroke = false; + + // Support for trim-paths is not available + + private Path originalPath; + private Path path; + private Path trimmedPath; + private Paint pathPaint; + + private Matrix scaleMatrix; + + public PathModel() { + fillAlpha = DefaultValues.PATH_FILL_ALPHA; + fillColor = DefaultValues.PATH_FILL_COLOR; + fillType = DefaultValues.PATH_FILL_TYPE; + trimPathStart = DefaultValues.PATH_TRIM_PATH_START; + trimPathEnd = DefaultValues.PATH_TRIM_PATH_END; + trimPathOffset = DefaultValues.PATH_TRIM_PATH_OFFSET; + strokeAlpha = DefaultValues.PATH_STROKE_ALPHA; + strokeColor = DefaultValues.PATH_STROKE_COLOR; + strokeLineCap = DefaultValues.PATH_STROKE_LINE_CAP; + strokeLineJoin = DefaultValues.PATH_STROKE_LINE_JOIN; + strokeMiterLimit = DefaultValues.PATH_STROKE_MITER_LIMIT; + strokeWidth = DefaultValues.PATH_STROKE_WIDTH; + strokeRatio = DefaultValues.PATH_STROKE_RATIO; + + pathPaint = new Paint(); + pathPaint.setAntiAlias(true); + updatePaint(); + } + + @Override + public void prepare(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY) { + //path do not prepare + } + + @Override + public void draw(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY) { + Path pathToDraw = getScaledAndOffsetPath(path, offsetX, offsetY, scaleX, scaleY); + if (isFillAndStroke()) { + makeFillPaint(); + canvas.drawPath(pathToDraw, getPathPaint()); + makeStrokePaint(); + canvas.drawPath(pathToDraw, getPathPaint()); + } else { + canvas.drawPath(pathToDraw, getPathPaint()); + } + } + + public void updatePaint() { + pathPaint.setStrokeWidth(strokeWidth * strokeRatio); + + if (fillColor != Color.TRANSPARENT && strokeColor != Color.TRANSPARENT) { + isFillAndStroke = true; + } else if (fillColor != Color.TRANSPARENT) { + pathPaint.setColor(fillColor); + pathPaint.setAlpha(Utils.getAlphaFromFloat(fillAlpha)); + pathPaint.setStyle(Paint.Style.FILL); + isFillAndStroke = false; + } else if (strokeColor != Color.TRANSPARENT) { + pathPaint.setColor(strokeColor); + pathPaint.setAlpha(Utils.getAlphaFromFloat(strokeAlpha)); + pathPaint.setStyle(Paint.Style.STROKE); + isFillAndStroke = false; + } else { + pathPaint.setColor(Color.TRANSPARENT); + } + + pathPaint.setStrokeCap(strokeLineCap); + pathPaint.setStrokeJoin(strokeLineJoin); + pathPaint.setStrokeMiter(strokeMiterLimit); + } + + public void makeStrokePaint() { + pathPaint.setColor(strokeColor); + pathPaint.setAlpha(Utils.getAlphaFromFloat(strokeAlpha)); + pathPaint.setStyle(Paint.Style.STROKE); + } + + public void makeFillPaint() { + pathPaint.setColor(fillColor); + pathPaint.setAlpha(Utils.getAlphaFromFloat(fillAlpha)); + pathPaint.setStyle(Paint.Style.FILL); + } + + @Override + public void scalePaths(Matrix originalScaleMatrix, Matrix concatTransformMatrix) { + scaleMatrix = concatTransformMatrix; + trimPath(); + } + + @Override + public void calculateStatic() { + originalPath = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); + if (originalPath != null) { + originalPath.setFillType(fillType); + } + path = new Path(originalPath); + } + + @Override + public void scaleStrokeWidth(float ratio) { + setStrokeRatio(ratio); + } + + public void trimPath() { + if (scaleMatrix != null) { + if (trimPathStart == 0 && trimPathEnd == 1 && trimPathOffset == 0) { path = new Path(originalPath); - } - - public void updatePaint() { - pathPaint.setStrokeWidth(strokeWidth * strokeRatio); - - if (fillColor != Color.TRANSPARENT && strokeColor != Color.TRANSPARENT) { - isFillAndStroke = true; - } else if (fillColor != Color.TRANSPARENT) { - pathPaint.setColor(fillColor); - pathPaint.setAlpha(Utils.getAlphaFromFloat(fillAlpha)); - pathPaint.setStyle(Paint.Style.FILL); - isFillAndStroke = false; - } else if (strokeColor != Color.TRANSPARENT) { - pathPaint.setColor(strokeColor); - pathPaint.setAlpha(Utils.getAlphaFromFloat(strokeAlpha)); - pathPaint.setStyle(Paint.Style.STROKE); - isFillAndStroke = false; - } else { - pathPaint.setColor(Color.TRANSPARENT); - } - - pathPaint.setStrokeCap(strokeLineCap); - pathPaint.setStrokeJoin(strokeLineJoin); - pathPaint.setStrokeMiter(strokeMiterLimit); - } - - public void makeStrokePaint() { - pathPaint.setColor(strokeColor); - pathPaint.setAlpha(Utils.getAlphaFromFloat(strokeAlpha)); - pathPaint.setStyle(Paint.Style.STROKE); - } - - public void makeFillPaint() { - pathPaint.setColor(fillColor); - pathPaint.setAlpha(Utils.getAlphaFromFloat(fillAlpha)); - pathPaint.setStyle(Paint.Style.FILL); - } - - public void transform(Matrix matrix) { - scaleMatrix = matrix; - - trimPath(); - } - - public void trimPath() { - if (scaleMatrix != null) { - if (trimPathStart == 0 && trimPathEnd == 1 && trimPathOffset == 0) { - path = new Path(originalPath); - path.transform(scaleMatrix); - } else { - PathMeasure pathMeasure = new PathMeasure(originalPath, false); - float length = pathMeasure.getLength(); - trimmedPath = new Path(); - pathMeasure.getSegment((trimPathStart + trimPathOffset) * length, (trimPathEnd + trimPathOffset) * length, trimmedPath, true); - path = new Path(trimmedPath); - path.transform(scaleMatrix); - } - } - } - - public Path getTrimmedPath() { - return trimmedPath; - } - - public void setTrimmedPath(Path trimmedPath) { - this.trimmedPath = trimmedPath; - } - - public Path getPath() { - return path; - } - - public void setPath(Path path) { - this.path = path; - } - - public Path getScaledAndOffsetPath(float offsetX, float offsetY, float scaleX, float scaleY) { - Path newPath = new Path(path); - newPath.offset(offsetX, offsetY); - newPath.transform(getScaleMatrix(newPath, scaleX, scaleY)); - return newPath; - } - - public Matrix getScaleMatrix(Path srcPath, float scaleX, float scaleY) { - Matrix scaleMatrix = new Matrix(); - RectF rectF = new RectF(); - srcPath.computeBounds(rectF, true); - scaleMatrix.setScale(scaleX, scaleY, rectF.left, rectF.top); - return scaleMatrix; - } - - public Paint getPathPaint() { - return pathPaint; - } - - public void setPathPaint(Paint pathPaint) { - this.pathPaint = pathPaint; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public float getFillAlpha() { - return fillAlpha; - } - - public void setFillAlpha(float fillAlpha) { - this.fillAlpha = fillAlpha; - updatePaint(); - } - - public int getFillColor() { - return fillColor; - } - - public void setFillColor(int fillColor) { - this.fillColor = fillColor; - updatePaint(); - } - - public Path.FillType getFillType() { - return fillType; - } - - public void setFillType(Path.FillType fillType) { - this.fillType = fillType; - if (originalPath != null) - originalPath.setFillType(fillType); - } - - public String getPathData() { - return pathData; - } - - public void setPathData(String pathData) { - this.pathData = pathData; - } - - public float getTrimPathStart() { - return trimPathStart; - } - - public void setTrimPathStart(float trimPathStart) { - this.trimPathStart = trimPathStart; - trimPath(); - } - - public float getTrimPathEnd() { - return trimPathEnd; - } - - public void setTrimPathEnd(float trimPathEnd) { - this.trimPathEnd = trimPathEnd; - trimPath(); - } - - public float getTrimPathOffset() { - return trimPathOffset; - } - - public void setTrimPathOffset(float trimPathOffset) { - this.trimPathOffset = trimPathOffset; - trimPath(); - } - - public float getStrokeAlpha() { - return strokeAlpha; - } - - public void setStrokeAlpha(float strokeAlpha) { - this.strokeAlpha = strokeAlpha; - updatePaint(); - } - - public int getStrokeColor() { - return strokeColor; - } - - public void setStrokeColor(int strokeColor) { - this.strokeColor = strokeColor; - updatePaint(); - } - - public Paint.Cap getStrokeLineCap() { - return strokeLineCap; - } - - public void setStrokeLineCap(Paint.Cap strokeLineCap) { - this.strokeLineCap = strokeLineCap; - updatePaint(); - } - - public Paint.Join getStrokeLineJoin() { - return strokeLineJoin; - } - - public void setStrokeLineJoin(Paint.Join strokeLineJoin) { - this.strokeLineJoin = strokeLineJoin; - updatePaint(); - } - - public float getStrokeMiterLimit() { - return strokeMiterLimit; - } - - public void setStrokeMiterLimit(float strokeMiterLimit) { - this.strokeMiterLimit = strokeMiterLimit; - updatePaint(); - } - - public float getStrokeWidth() { - return strokeWidth; - } - - public void setStrokeWidth(float strokeWidth) { - this.strokeWidth = strokeWidth; - updatePaint(); - } - - public float getStrokeRatio() { - return strokeRatio; - } - - public void setStrokeRatio(float strokeRatio) { - this.strokeRatio = strokeRatio; - updatePaint(); - } - - public boolean isFillAndStroke() { - return isFillAndStroke; - } + path.transform(scaleMatrix); + } else { + PathMeasure pathMeasure = new PathMeasure(originalPath, false); + float length = pathMeasure.getLength(); + trimmedPath = new Path(); + pathMeasure + .getSegment((trimPathStart + trimPathOffset) * length, (trimPathEnd + trimPathOffset) * length, trimmedPath, + true); + path = new Path(trimmedPath); + path.transform(scaleMatrix); + } + } + } + + public Path getTrimmedPath() { + return trimmedPath; + } + + public void setTrimmedPath(Path trimmedPath) { + this.trimmedPath = trimmedPath; + } + + public Path getPath() { + return path; + } + + public void setPath(Path path) { + this.path = path; + } + + public Paint getPathPaint() { + return pathPaint; + } + + public void setPathPaint(Paint pathPaint) { + this.pathPaint = pathPaint; + } + + public float getFillAlpha() { + return fillAlpha; + } + + public void setFillAlpha(float fillAlpha) { + this.fillAlpha = fillAlpha; + updatePaint(); + } + + public int getFillColor() { + return fillColor; + } + + public void setFillColor(int fillColor) { + this.fillColor = fillColor; + updatePaint(); + } + + public Path.FillType getFillType() { + return fillType; + } + + public void setFillType(Path.FillType fillType) { + this.fillType = fillType; + if (originalPath != null) + originalPath.setFillType(fillType); + } + + public String getPathData() { + return pathData; + } + + public void setPathData(String pathData) { + this.pathData = pathData; + } + + public float getTrimPathStart() { + return trimPathStart; + } + + public void setTrimPathStart(float trimPathStart) { + this.trimPathStart = trimPathStart; + trimPath(); + } + + public float getTrimPathEnd() { + return trimPathEnd; + } + + public void setTrimPathEnd(float trimPathEnd) { + this.trimPathEnd = trimPathEnd; + trimPath(); + } + + public float getTrimPathOffset() { + return trimPathOffset; + } + + public void setTrimPathOffset(float trimPathOffset) { + this.trimPathOffset = trimPathOffset; + trimPath(); + } + + public float getStrokeAlpha() { + return strokeAlpha; + } + + public void setStrokeAlpha(float strokeAlpha) { + this.strokeAlpha = strokeAlpha; + updatePaint(); + } + + public int getStrokeColor() { + return strokeColor; + } + + public void setStrokeColor(int strokeColor) { + this.strokeColor = strokeColor; + updatePaint(); + } + + public Paint.Cap getStrokeLineCap() { + return strokeLineCap; + } + + public void setStrokeLineCap(Paint.Cap strokeLineCap) { + this.strokeLineCap = strokeLineCap; + updatePaint(); + } + + public Paint.Join getStrokeLineJoin() { + return strokeLineJoin; + } + + public void setStrokeLineJoin(Paint.Join strokeLineJoin) { + this.strokeLineJoin = strokeLineJoin; + updatePaint(); + } + + public float getStrokeMiterLimit() { + return strokeMiterLimit; + } + + public void setStrokeMiterLimit(float strokeMiterLimit) { + this.strokeMiterLimit = strokeMiterLimit; + updatePaint(); + } + + public float getStrokeWidth() { + return strokeWidth; + } + + public void setStrokeWidth(float strokeWidth) { + this.strokeWidth = strokeWidth; + updatePaint(); + } + + public float getStrokeRatio() { + return strokeRatio; + } + + public void setStrokeRatio(float strokeRatio) { + this.strokeRatio = strokeRatio; + updatePaint(); + } + + public boolean isFillAndStroke() { + return isFillAndStroke; + } } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java index c523c95..2b5d09d 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java @@ -1,18 +1,11 @@ package com.sdsmdg.harjot.vectormaster.models; -import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Matrix; import android.graphics.Path; -import android.graphics.Region; import com.sdsmdg.harjot.vectormaster.enums.TintMode; -import java.util.ArrayList; - -public class VectorModel { - - private String name; +public class VectorModel extends ParentModel { private float width, height; @@ -25,111 +18,12 @@ public class VectorModel { private float viewportWidth, viewportHeight; - private ArrayList groupModels; - private ArrayList pathModels; - private ArrayList clipPathModels; - private Path fullpath; - private Matrix scaleMatrix; - public VectorModel() { - groupModels = new ArrayList<>(); - pathModels = new ArrayList<>(); - clipPathModels = new ArrayList<>(); fullpath = new Path(); } - public void drawPaths(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY) { - for (ClipPathModel clipPathModel : clipPathModels) { - canvas.clipPath(clipPathModel.getScaledAndOffsetPath(offsetX, offsetY, scaleX, scaleY)); - } - for (GroupModel groupModel : groupModels) { - groupModel.drawPaths(canvas, offsetX, offsetY, scaleX, scaleY); - } - for (PathModel pathModel : pathModels) { - if (pathModel.isFillAndStroke()) { - pathModel.makeFillPaint(); - canvas.drawPath(pathModel.getScaledAndOffsetPath(offsetX, offsetY, scaleX, scaleY), pathModel.getPathPaint()); - pathModel.makeStrokePaint(); - canvas.drawPath(pathModel.getScaledAndOffsetPath(offsetX, offsetY, scaleX, scaleY), pathModel.getPathPaint()); - } else { - canvas.drawPath(pathModel.getScaledAndOffsetPath(offsetX, offsetY, scaleX, scaleY), pathModel.getPathPaint()); - } - } - } - - public void drawPaths(Canvas canvas) { - for (ClipPathModel clipPathModel : clipPathModels) { - canvas.clipPath(clipPathModel.getPath()); - } - for (GroupModel groupModel : groupModels) { - groupModel.drawPaths(canvas); - } - for (PathModel pathModel : pathModels) { - if (pathModel.isFillAndStroke()) { - pathModel.makeFillPaint(); - canvas.drawPath(pathModel.getPath(), pathModel.getPathPaint()); - pathModel.makeStrokePaint(); - canvas.drawPath(pathModel.getPath(), pathModel.getPathPaint()); - } else { - canvas.drawPath(pathModel.getPath(), pathModel.getPathPaint()); - } - } - } - - public void scaleAllPaths(Matrix scaleMatrix) { - this.scaleMatrix = scaleMatrix; - for (GroupModel groupModel : groupModels) { - groupModel.scaleAllPaths(scaleMatrix); - } - for (PathModel pathModel : pathModels) { - pathModel.transform(scaleMatrix); - } - for (ClipPathModel clipPathModel : clipPathModels) { - clipPathModel.transform(scaleMatrix); - } - } - - public void scaleAllStrokeWidth(float ratio) { - for (GroupModel groupModel : groupModels) { - groupModel.scaleAllStrokeWidth(ratio); - } - for (PathModel pathModel : pathModels) { - pathModel.setStrokeRatio(ratio); - } - } - - public void buildTransformMatrices() { - for (GroupModel groupModel : groupModels) { - groupModel.buildTransformMatrix(); - } - } - - public void addGroupModel(GroupModel groupModel) { - groupModels.add(groupModel); - } - - public ArrayList getGroupModels() { - return groupModels; - } - - public void addPathModel(PathModel pathModel) { - pathModels.add(pathModel); - } - - public ArrayList getPathModels() { - return pathModels; - } - - public void addClipPathModel(ClipPathModel clipPathModel) { - clipPathModels.add(clipPathModel); - } - - public ArrayList getClipPathModels() { - return clipPathModels; - } - public Path getFullpath() { return fullpath; } @@ -138,14 +32,6 @@ public void setFullpath(Path fullpath) { this.fullpath = fullpath; } - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - public float getWidth() { return width; } From 445bea4f1aac46c85d0459f2cf80b7513876581d Mon Sep 17 00:00:00 2001 From: Xalag Date: Sat, 9 Mar 2019 04:23:59 +0100 Subject: [PATCH 2/9] Simplified propagation of translation matrixes through the model. Changes are now taken into account in next onDraw() latest. --- .../harjot/vectormaster/ModelParser.java | 4 +- .../vectormaster/VectorMasterDrawable.java | 26 +-- .../harjot/vectormaster/VectorMasterView.java | 16 +- .../vectormaster/models/ClipPathModel.java | 37 ++-- .../vectormaster/models/GroupModel.java | 185 ++++++++++-------- .../harjot/vectormaster/models/Model.java | 45 +---- .../vectormaster/models/ParentModel.java | 59 +----- .../harjot/vectormaster/models/PathModel.java | 91 +++++---- .../vectormaster/models/VectorModel.java | 26 ++- 9 files changed, 217 insertions(+), 272 deletions(-) diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/ModelParser.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/ModelParser.java index 23c62b3..d355d24 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/ModelParser.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/ModelParser.java @@ -198,16 +198,14 @@ public VectorModel buildVectorModel(Resources resources, int resID) { case XmlPullParser.END_TAG: if (name.equals("path")) { - pathModel.calculateStatic(); parentModelStack.peek().addChild(pathModel); - vectorModel.getFullpath().addPath(pathModel.getPath()); } else if (name.equals("clip-path")) { parentModelStack.peek().addChild(clipPathModel); } else if (name.equals("group")) { ParentModel topGroupModel = parentModelStack.pop(); parentModelStack.peek().addChild(topGroupModel); } else if (name.equals("vector")) { - vectorModel.calculateStatic(); + vectorModel.init(); } break; } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java index d2b94be..b9bf2aa 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java @@ -13,16 +13,10 @@ import com.sdsmdg.harjot.vectormaster.models.ClipPathModel; import com.sdsmdg.harjot.vectormaster.models.GroupModel; -import com.sdsmdg.harjot.vectormaster.models.ParentModel; import com.sdsmdg.harjot.vectormaster.models.PathModel; import com.sdsmdg.harjot.vectormaster.models.VectorModel; import com.sdsmdg.harjot.vectormaster.utilities.Utils; - import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.util.Stack; public class VectorMasterDrawable extends Drawable { @@ -126,8 +120,6 @@ protected void onBoundsChange(Rect bounds) { height = bounds.height(); buildScaleMatrix(); - scaleAllPaths(); - scaleAllStrokes(); } } @@ -145,15 +137,20 @@ public void draw(Canvas canvas) { setBounds(0, 0, temp1, temp2); } + strokeRatio = Math.min(width / vectorModel.getWidth(), height / vectorModel.getHeight()); + Matrix translation = new Matrix(scaleMatrix); + translation.postTranslate(offsetX, offsetY); + translation.postScale(scaleX, scaleY); + setAlpha(Utils.getAlphaFromFloat(vectorModel.getAlpha())); if (left != 0 || top != 0) { tempSaveCount = canvas.save(); canvas.translate(left, top); - vectorModel.draw(canvas, offsetX, offsetY, scaleX, scaleY); + vectorModel.draw(canvas, translation, strokeRatio); canvas.restoreToCount(tempSaveCount); } else { - vectorModel.draw(canvas, offsetX, offsetY, scaleX, scaleY); + vectorModel.draw(canvas, translation, strokeRatio); } } @@ -197,15 +194,6 @@ private void buildScaleMatrix() { scaleMatrix.postScale(ratio, ratio, width / 2, height / 2); } - private void scaleAllPaths() { - vectorModel.scalePaths(scaleMatrix); - } - - private void scaleAllStrokes() { - strokeRatio = Math.min(width / vectorModel.getWidth(), height / vectorModel.getHeight()); - vectorModel.scaleStrokeWidth(strokeRatio); - } - public Path getFullPath() { if (vectorModel != null) { return vectorModel.getFullpath(); diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java index 1b5e79a..3ff035b 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java @@ -94,8 +94,6 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { height = h; buildScaleMatrix(); - scaleAllPaths(); - scaleAllStrokes(); } } @@ -110,9 +108,12 @@ protected void onDraw(Canvas canvas) { return; } + strokeRatio = Math.min(width / vectorModel.getWidth(), height / vectorModel.getHeight()); + Matrix translation = new Matrix(scaleMatrix); + setAlpha(vectorModel.getAlpha()); - vectorModel.draw(canvas); + vectorModel.draw(canvas, translation, scaleRatio); } @@ -131,15 +132,6 @@ void buildScaleMatrix() { scaleMatrix.postScale(ratio, ratio, width / 2, height / 2); } - void scaleAllPaths() { - vectorModel.scalePaths(scaleMatrix); - } - - void scaleAllStrokes() { - strokeRatio = Math.min(width / vectorModel.getWidth(), height / vectorModel.getHeight()); - vectorModel.scaleStrokeWidth(strokeRatio); - } - public Path getFullPath() { if (vectorModel != null) { return vectorModel.getFullpath(); diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java index f6492da..a82b343 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java @@ -10,45 +10,47 @@ public class ClipPathModel extends Model { private String pathData; - private Path originalPath; private Path path; + private Path transformedPath; + private Matrix lastTransformation; private Paint clipPaint; public ClipPathModel() { path = new Path(); - clipPaint = new Paint(); clipPaint.setAntiAlias(true); clipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); } @Override - public void prepare(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY) { - canvas.clipPath(getScaledAndOffsetPath(path, offsetX, offsetY, scaleX, scaleY)); + public void init() { + preparePath(new Matrix()); } @Override - public void draw(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY) { - //clip path does no drawing + public void prepare(Canvas canvas, Matrix parentTransformation, float strokeRatio) { + canvas.clipPath(preparePath(parentTransformation)); } @Override - public void calculateStatic() { - originalPath = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); - path = new Path(originalPath); + public void draw(Canvas canvas, Matrix parentTransformation, float strokeRatio) { + //clip path does no drawing } - @Override - public void scaleStrokeWidth(float ratio) { - + private Path preparePath(Matrix transformation) { + //try caching as much as possible to do path calculation only if necessary + if (path == null) { + path = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); + transformedPath = null; + } + if (transformedPath == null || lastTransformation == null || !lastTransformation.equals(transformation)) { + transformedPath = transform(path, transformation); + lastTransformation = transformation; + } + return transformedPath; } - @Override - public void scalePaths(Matrix originalScaleMatrix, Matrix concatTransformMatrix) { - path = new Path(originalPath); - path.transform(concatTransformMatrix); - } public Paint getClipPaint() { return clipPaint; @@ -64,6 +66,7 @@ public String getPathData() { public void setPathData(String pathData) { this.pathData = pathData; + path = null; } public Path getPath() { diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java index 6a66cd7..bd23779 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java @@ -1,93 +1,110 @@ package com.sdsmdg.harjot.vectormaster.models; +import android.graphics.Canvas; import android.graphics.Matrix; import com.sdsmdg.harjot.vectormaster.DefaultValues; public class GroupModel extends ParentModel { - private float rotation; - private float pivotX, pivotY; - private float scaleX, scaleY; - private float translateX, translateY; - - public GroupModel() { - rotation = DefaultValues.GROUP_ROTATION; - pivotX = DefaultValues.GROUP_PIVOT_X; - pivotY = DefaultValues.GROUP_PIVOT_Y; - scaleX = DefaultValues.GROUP_SCALE_X; - scaleY = DefaultValues.GROUP_SCALE_Y; - translateX = DefaultValues.GROUP_TRANSLATE_X; - translateY = DefaultValues.GROUP_TRANSLATE_Y; - } - - @Override - protected Matrix createTransformMatrix() { - Matrix transformMatrix = new Matrix(); - transformMatrix.postScale(scaleX, scaleY, pivotX, pivotY); - transformMatrix.postRotate(rotation, pivotX, pivotY); - transformMatrix.postTranslate(translateX, translateY); - return transformMatrix; - } - - public float getRotation() { - return rotation; - } - - public void setRotation(float rotation) { - this.rotation = rotation; - updateAndScalePaths(); - } - - public float getPivotX() { - return pivotX; - } - - public void setPivotX(float pivotX) { - this.pivotX = pivotX; - } - - public float getPivotY() { - return pivotY; - } - - public void setPivotY(float pivotY) { - this.pivotY = pivotY; - } - - public float getScaleX() { - return scaleX; - } - - public void setScaleX(float scaleX) { - this.scaleX = scaleX; - updateAndScalePaths(); - } - - public float getScaleY() { - return scaleY; - } - - public void setScaleY(float scaleY) { - this.scaleY = scaleY; - updateAndScalePaths(); - } - - public float getTranslateX() { - return translateX; - } - - public void setTranslateX(float translateX) { - this.translateX = translateX; - updateAndScalePaths(); - } - - public float getTranslateY() { - return translateY; - } - - public void setTranslateY(float translateY) { - this.translateY = translateY; - updateAndScalePaths(); - } + private float rotation; + private float pivotX, pivotY; + private float scaleX, scaleY; + private float translateX, translateY; + private Matrix ownTransformation; + + public GroupModel() { + rotation = DefaultValues.GROUP_ROTATION; + pivotX = DefaultValues.GROUP_PIVOT_X; + pivotY = DefaultValues.GROUP_PIVOT_Y; + scaleX = DefaultValues.GROUP_SCALE_X; + scaleY = DefaultValues.GROUP_SCALE_Y; + translateX = DefaultValues.GROUP_TRANSLATE_X; + translateY = DefaultValues.GROUP_TRANSLATE_Y; + } + + @Override + public void draw(Canvas canvas, Matrix parentTransformation, float strokeRatio) { + + Matrix transformation = new Matrix(parentTransformation); + transformation.preConcat(ownTransformation); + + super.draw(canvas, transformation, strokeRatio); + } + + protected void createOwnTransformation() { + Matrix transformation = new Matrix(); + transformation.postScale(scaleX, scaleY, pivotX, pivotY); + transformation.postRotate(rotation, pivotX, pivotY); + transformation.postTranslate(translateX, translateY); + + ownTransformation = transformation; + } + + private void markAsDirty() { + createOwnTransformation(); + } + + public float getRotation() { + return rotation; + } + + public void setRotation(float rotation) { + this.rotation = rotation; + markAsDirty(); + } + + public float getPivotX() { + return pivotX; + } + + public void setPivotX(float pivotX) { + this.pivotX = pivotX; + markAsDirty(); + } + + public float getPivotY() { + return pivotY; + } + + public void setPivotY(float pivotY) { + this.pivotY = pivotY; + markAsDirty(); + } + + public float getScaleX() { + return scaleX; + } + + public void setScaleX(float scaleX) { + this.scaleX = scaleX; + markAsDirty(); + } + + public float getScaleY() { + return scaleY; + } + + public void setScaleY(float scaleY) { + this.scaleY = scaleY; + markAsDirty(); + } + + public float getTranslateX() { + return translateX; + } + + public void setTranslateX(float translateX) { + this.translateX = translateX; + markAsDirty(); + } + + public float getTranslateY() { + return translateY; + } + + public void setTranslateY(float translateY) { + this.translateY = translateY; + markAsDirty(); + } } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java index 32ac29d..39c562d 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java @@ -3,7 +3,6 @@ import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Path; -import android.graphics.RectF; public abstract class Model { @@ -26,44 +25,14 @@ public void setParent(ParentModel parent) { this.parent = parent; } - public abstract void calculateStatic(); + public abstract void init(); + public abstract void prepare(Canvas canvas, Matrix parentTransformation, float strokeRatio); + public abstract void draw(Canvas canvas, Matrix parentTransformation, float strokeRatio); - public abstract void scalePaths(Matrix originalScaleMatrix, Matrix concatTransformMatrix); - - public abstract void scaleStrokeWidth(float ratio); - - public abstract void prepare(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY); - - public abstract void draw(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY); - - public void draw(Canvas canvas) { - draw(canvas, 0.0f, 0.0f, 1.0f, 1.0f); + protected Path transform(Path path, Matrix transformation) { + Path resultPath = new Path(path); + resultPath.transform(transformation); + return resultPath; } - public void prepare(Canvas canvas) { - prepare(canvas, 0.0f, 0.0f, 1.0f, 1.0f); - } - - public Path getScaledAndOffsetPath(Path srcPath, float offsetX, float offsetY, float scaleX, float scaleY) { - if (offsetX == 0 && offsetY == 0 && scaleX == 1 && scaleY == 1) { - return srcPath; - } else { - Path newPath = new Path(srcPath); - newPath.offset(offsetX, offsetY); - newPath.transform(getScaleMatrix(newPath, scaleX, scaleY)); - return newPath; - } - } - - public Matrix getScaleMatrix(Path srcPath, float scaleX, float scaleY) { - Matrix scaleMatrix = new Matrix(); - RectF rectF = new RectF(); - srcPath.computeBounds(rectF, true); - scaleMatrix.setScale(scaleX, scaleY, rectF.left, rectF.top); - return scaleMatrix; - } - - - - } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java index fdbc0e2..305ed00 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java @@ -8,8 +8,6 @@ public abstract class ParentModel extends Model { private ArrayList children = new ArrayList<>(0); - private Matrix scaleMatrix; - private Matrix transformMatrix; public ArrayList getChildren() { return children; @@ -20,69 +18,26 @@ public void addChild(Model model) { model.setParent(this); } - public Matrix getTransformMatrix() { - return transformMatrix; - } - - protected Matrix createTransformMatrix() { - return new Matrix(); - } - - @Override - public void calculateStatic() { - //create own matrix - transformMatrix = createTransformMatrix(); - //add the one from the parrent if there is a parent - if (getParent() != null) { - transformMatrix.postConcat(getParent().getTransformMatrix()); - } - //tell all children to do the calculation - for (Model model : getChildren()) { - model.calculateStatic(); - } - } - - @Override - public void scalePaths(Matrix originalScaleMatrix, Matrix concatTransformMatrix) { - this.scaleMatrix = originalScaleMatrix; - Matrix finalTransformMatrix = new Matrix(getTransformMatrix()); - finalTransformMatrix.postConcat(scaleMatrix); - for (Model child : children) { - child.scalePaths(originalScaleMatrix, finalTransformMatrix); - } - } - - public void scalePaths(Matrix originalScaleMatrix) { - scalePaths(originalScaleMatrix, null); //because we are a parentModel only the first Matrix matters the second one is not used. - } - - public void updateAndScalePaths() { - if (scaleMatrix != null) { - calculateStatic(); - scalePaths(scaleMatrix); - } - } - @Override - public void scaleStrokeWidth(float ratio) { - for (Model model : getChildren()) { - model.scaleStrokeWidth(ratio); + public void init() { + for (Model child : getChildren()) { + child.init(); } } @Override - public void prepare(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY) { + public void prepare(Canvas canvas, Matrix parentTransformation, float strokeRatio) { //parents by default do not prepare the canvas recursively } @Override - public void draw(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY) { + public void draw(Canvas canvas, Matrix parentTransformation, float strokeRatio) { //parents prepare just their own children before they draw for (Model child : getChildren()) { - child.prepare(canvas, offsetX, offsetY, scaleX, scaleY); + child.prepare(canvas, parentTransformation, strokeRatio); } for (Model child : getChildren()) { - child.draw(canvas, offsetX, offsetY, scaleX, scaleY); + child.draw(canvas, parentTransformation, strokeRatio); } } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java index 1b7837f..add0bef 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java @@ -34,13 +34,12 @@ public class PathModel extends Model { // Support for trim-paths is not available - private Path originalPath; private Path path; private Path trimmedPath; + private Path transformedPath; + private Matrix lastTransformation; private Paint pathPaint; - private Matrix scaleMatrix; - public PathModel() { fillAlpha = DefaultValues.PATH_FILL_ALPHA; fillColor = DefaultValues.PATH_FILL_COLOR; @@ -62,13 +61,14 @@ public PathModel() { } @Override - public void prepare(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY) { + public void prepare(Canvas canvas, Matrix parentTransformation, float strokeRatio) { //path do not prepare } @Override - public void draw(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY) { - Path pathToDraw = getScaledAndOffsetPath(path, offsetX, offsetY, scaleX, scaleY); + public void draw(Canvas canvas, Matrix parentTransformation, float strokeRatio) { + Path pathToDraw = preparePath(parentTransformation); + pathPaint.setStrokeWidth(strokeWidth * this.strokeRatio * strokeRatio); if (isFillAndStroke()) { makeFillPaint(); canvas.drawPath(pathToDraw, getPathPaint()); @@ -79,9 +79,12 @@ public void draw(Canvas canvas, float offsetX, float offsetY, float scaleX, floa } } - public void updatePaint() { - pathPaint.setStrokeWidth(strokeWidth * strokeRatio); + @Override + public void init() { + preparePath(new Matrix()); + } + public void updatePaint() { if (fillColor != Color.TRANSPARENT && strokeColor != Color.TRANSPARENT) { isFillAndStroke = true; } else if (fillColor != Color.TRANSPARENT) { @@ -115,42 +118,37 @@ public void makeFillPaint() { pathPaint.setStyle(Paint.Style.FILL); } - @Override - public void scalePaths(Matrix originalScaleMatrix, Matrix concatTransformMatrix) { - scaleMatrix = concatTransformMatrix; - trimPath(); - } - - @Override - public void calculateStatic() { - originalPath = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); - if (originalPath != null) { - originalPath.setFillType(fillType); + private Path preparePath(Matrix transformation) { + //try caching as much as possible to do path calculation only if necessary + if (path == null) { + path = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); + trimmedPath = null; } - path = new Path(originalPath); - } - - @Override - public void scaleStrokeWidth(float ratio) { - setStrokeRatio(ratio); + if (trimmedPath == null) { + trimmedPath = trimPath(path); + transformedPath = null; + } + if (transformedPath == null || lastTransformation == null || !lastTransformation.equals(transformation)) { + transformedPath = transform(trimmedPath, transformation); + } + transformedPath.setFillType(fillType); + return transformedPath; } - public void trimPath() { - if (scaleMatrix != null) { + public Path trimPath(Path path) { if (trimPathStart == 0 && trimPathEnd == 1 && trimPathOffset == 0) { - path = new Path(originalPath); - path.transform(scaleMatrix); + return new Path(path); } else { - PathMeasure pathMeasure = new PathMeasure(originalPath, false); + PathMeasure pathMeasure = new PathMeasure(path, false); float length = pathMeasure.getLength(); - trimmedPath = new Path(); - pathMeasure - .getSegment((trimPathStart + trimPathOffset) * length, (trimPathEnd + trimPathOffset) * length, trimmedPath, - true); - path = new Path(trimmedPath); - path.transform(scaleMatrix); + Path trimmedPath = new Path(); + pathMeasure.getSegment( + (trimPathStart + trimPathOffset) * length, + (trimPathEnd + trimPathOffset) * length, + trimmedPath, + true); + return trimmedPath; } - } } public Path getTrimmedPath() { @@ -167,6 +165,7 @@ public Path getPath() { public void setPath(Path path) { this.path = path; + this.trimmedPath = null; } public Paint getPathPaint() { @@ -201,8 +200,6 @@ public Path.FillType getFillType() { public void setFillType(Path.FillType fillType) { this.fillType = fillType; - if (originalPath != null) - originalPath.setFillType(fillType); } public String getPathData() { @@ -211,6 +208,7 @@ public String getPathData() { public void setPathData(String pathData) { this.pathData = pathData; + this.path = null; } public float getTrimPathStart() { @@ -219,7 +217,7 @@ public float getTrimPathStart() { public void setTrimPathStart(float trimPathStart) { this.trimPathStart = trimPathStart; - trimPath(); + this.trimmedPath = null; } public float getTrimPathEnd() { @@ -228,7 +226,7 @@ public float getTrimPathEnd() { public void setTrimPathEnd(float trimPathEnd) { this.trimPathEnd = trimPathEnd; - trimPath(); + this.trimmedPath = null; } public float getTrimPathOffset() { @@ -237,7 +235,7 @@ public float getTrimPathOffset() { public void setTrimPathOffset(float trimPathOffset) { this.trimPathOffset = trimPathOffset; - trimPath(); + this.trimmedPath = null; } public float getStrokeAlpha() { @@ -294,16 +292,17 @@ public void setStrokeWidth(float strokeWidth) { updatePaint(); } + public boolean isFillAndStroke() { + return isFillAndStroke; + } + public float getStrokeRatio() { return strokeRatio; } public void setStrokeRatio(float strokeRatio) { this.strokeRatio = strokeRatio; - updatePaint(); } - public boolean isFillAndStroke() { - return isFillAndStroke; - } + } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java index 2b5d09d..04ad0fe 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java @@ -1,8 +1,11 @@ package com.sdsmdg.harjot.vectormaster.models; +import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Matrix; import android.graphics.Path; +import android.util.Log; import com.sdsmdg.harjot.vectormaster.enums.TintMode; public class VectorModel extends ParentModel { @@ -19,13 +22,34 @@ public class VectorModel extends ParentModel { private float viewportWidth, viewportHeight; private Path fullpath; + private long averageDrawTime = 0L; + private int drawCount = 0; public VectorModel() { fullpath = new Path(); } public Path getFullpath() { - return fullpath; + //TODO: traverse the model to collect the currently translated pathes + throw new UnsupportedOperationException("Not implemented yet."); + } + + @Override + public void draw(Canvas canvas, Matrix parentTransformation, float strokeRatio) { + long startTime = System.nanoTime(); + super.draw(canvas, parentTransformation, strokeRatio); + long endTime = System.nanoTime(); + long drawTime = endTime - startTime; + if (averageDrawTime == 0) { + averageDrawTime = drawTime; + } else { + averageDrawTime = ((averageDrawTime + drawTime) / 2); + } + drawCount++; + if (drawCount == 50) { + drawCount = 0; + Log.i("DrawTimeTag", "Draw took average " + averageDrawTime + " nanosecs"); + } } public void setFullpath(Path fullpath) { From 40f1457355da23418aa0652f36c47a753ee787c8 Mon Sep 17 00:00:00 2001 From: Xalag Date: Sat, 9 Mar 2019 05:18:24 +0100 Subject: [PATCH 3/9] Try optimize models for faster processing. Removed init method. --- .../harjot/vectormaster/ModelParser.java | 2 +- .../vectormaster/models/ClipPathModel.java | 5 -- .../vectormaster/models/GroupModel.java | 15 ++++- .../harjot/vectormaster/models/Model.java | 1 - .../vectormaster/models/ParentModel.java | 7 --- .../harjot/vectormaster/models/PathModel.java | 60 +++++++------------ 6 files changed, 36 insertions(+), 54 deletions(-) diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/ModelParser.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/ModelParser.java index d355d24..e58904e 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/ModelParser.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/ModelParser.java @@ -205,7 +205,7 @@ public VectorModel buildVectorModel(Resources resources, int resID) { ParentModel topGroupModel = parentModelStack.pop(); parentModelStack.peek().addChild(topGroupModel); } else if (name.equals("vector")) { - vectorModel.init(); + //we are done with parsing } break; } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java index a82b343..e464f5b 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java @@ -23,11 +23,6 @@ public ClipPathModel() { clipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); } - @Override - public void init() { - preparePath(new Matrix()); - } - @Override public void prepare(Canvas canvas, Matrix parentTransformation, float strokeRatio) { canvas.clipPath(preparePath(parentTransformation)); diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java index bd23779..dd77f5a 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java @@ -12,6 +12,9 @@ public class GroupModel extends ParentModel { private float scaleX, scaleY; private float translateX, translateY; private Matrix ownTransformation; + private boolean ownTransformationChanged = true; + private Matrix lastParentTransformation; + private Matrix lastTransformation; public GroupModel() { rotation = DefaultValues.GROUP_ROTATION; @@ -26,10 +29,15 @@ public GroupModel() { @Override public void draw(Canvas canvas, Matrix parentTransformation, float strokeRatio) { - Matrix transformation = new Matrix(parentTransformation); - transformation.preConcat(ownTransformation); + //try to keep transformed matrix the same instance as long as the values do not change + if (ownTransformationChanged || lastParentTransformation != parentTransformation) { + lastParentTransformation = parentTransformation; + lastTransformation = new Matrix(parentTransformation); + lastTransformation.preConcat(ownTransformation); + ownTransformationChanged = false; + } - super.draw(canvas, transformation, strokeRatio); + super.draw(canvas, lastTransformation, strokeRatio); } protected void createOwnTransformation() { @@ -39,6 +47,7 @@ protected void createOwnTransformation() { transformation.postTranslate(translateX, translateY); ownTransformation = transformation; + ownTransformationChanged = true; } private void markAsDirty() { diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java index 39c562d..73efd06 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java @@ -25,7 +25,6 @@ public void setParent(ParentModel parent) { this.parent = parent; } - public abstract void init(); public abstract void prepare(Canvas canvas, Matrix parentTransformation, float strokeRatio); public abstract void draw(Canvas canvas, Matrix parentTransformation, float strokeRatio); diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java index 305ed00..f89a066 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java @@ -18,13 +18,6 @@ public void addChild(Model model) { model.setParent(this); } - @Override - public void init() { - for (Model child : getChildren()) { - child.init(); - } - } - @Override public void prepare(Canvas canvas, Matrix parentTransformation, float strokeRatio) { //parents by default do not prepare the canvas recursively diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java index add0bef..af045ab 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java @@ -67,7 +67,13 @@ public void prepare(Canvas canvas, Matrix parentTransformation, float strokeRati @Override public void draw(Canvas canvas, Matrix parentTransformation, float strokeRatio) { - Path pathToDraw = preparePath(parentTransformation); + //try caching as much as possible to do path calculation only if necessary + if (transformedPath == null || lastTransformation == null || !lastTransformation.equals(parentTransformation)) { + transformedPath = transform(trimmedPath, parentTransformation); + lastTransformation = parentTransformation; + } + transformedPath.setFillType(fillType); + Path pathToDraw = transformedPath; pathPaint.setStrokeWidth(strokeWidth * this.strokeRatio * strokeRatio); if (isFillAndStroke()) { makeFillPaint(); @@ -79,11 +85,6 @@ public void draw(Canvas canvas, Matrix parentTransformation, float strokeRatio) } } - @Override - public void init() { - preparePath(new Matrix()); - } - public void updatePaint() { if (fillColor != Color.TRANSPARENT && strokeColor != Color.TRANSPARENT) { isFillAndStroke = true; @@ -118,36 +119,25 @@ public void makeFillPaint() { pathPaint.setStyle(Paint.Style.FILL); } - private Path preparePath(Matrix transformation) { - //try caching as much as possible to do path calculation only if necessary - if (path == null) { - path = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); - trimmedPath = null; - } - if (trimmedPath == null) { - trimmedPath = trimPath(path); - transformedPath = null; - } - if (transformedPath == null || lastTransformation == null || !lastTransformation.equals(transformation)) { - transformedPath = transform(trimmedPath, transformation); - } - transformedPath.setFillType(fillType); - return transformedPath; - } + public void trimPath() { + if (path == null) { + return; + } - public Path trimPath(Path path) { if (trimPathStart == 0 && trimPathEnd == 1 && trimPathOffset == 0) { - return new Path(path); + trimmedPath = new Path(path); + transformedPath = null; } else { PathMeasure pathMeasure = new PathMeasure(path, false); float length = pathMeasure.getLength(); - Path trimmedPath = new Path(); + Path trimmed = new Path(); pathMeasure.getSegment( (trimPathStart + trimPathOffset) * length, (trimPathEnd + trimPathOffset) * length, - trimmedPath, + trimmed, true); - return trimmedPath; + trimmedPath = trimmed; + transformedPath = null; } } @@ -155,17 +145,13 @@ public Path getTrimmedPath() { return trimmedPath; } - public void setTrimmedPath(Path trimmedPath) { - this.trimmedPath = trimmedPath; - } - public Path getPath() { return path; } public void setPath(Path path) { this.path = path; - this.trimmedPath = null; + trimPath(); } public Paint getPathPaint() { @@ -208,7 +194,8 @@ public String getPathData() { public void setPathData(String pathData) { this.pathData = pathData; - this.path = null; + this.path = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); + trimPath(); } public float getTrimPathStart() { @@ -217,7 +204,7 @@ public float getTrimPathStart() { public void setTrimPathStart(float trimPathStart) { this.trimPathStart = trimPathStart; - this.trimmedPath = null; + trimPath(); } public float getTrimPathEnd() { @@ -226,7 +213,7 @@ public float getTrimPathEnd() { public void setTrimPathEnd(float trimPathEnd) { this.trimPathEnd = trimPathEnd; - this.trimmedPath = null; + trimPath(); } public float getTrimPathOffset() { @@ -235,7 +222,7 @@ public float getTrimPathOffset() { public void setTrimPathOffset(float trimPathOffset) { this.trimPathOffset = trimPathOffset; - this.trimmedPath = null; + trimPath(); } public float getStrokeAlpha() { @@ -304,5 +291,4 @@ public void setStrokeRatio(float strokeRatio) { this.strokeRatio = strokeRatio; } - } From 8d09c6708c2ed7afeb89dd87aabafc11e4447c98 Mon Sep 17 00:00:00 2001 From: Xalag Date: Tue, 26 Mar 2019 21:05:17 +0100 Subject: [PATCH 4/9] Stabelized path transformations. Added fullpath collection, but as in the initial implementation this only collects the untransformed paths. --- .../vectormaster/VectorMasterDrawable.java | 32 ++- .../harjot/vectormaster/VectorMasterView.java | 22 +- .../vectormaster/models/ClipPathModel.java | 122 +++++----- .../vectormaster/models/GroupModel.java | 44 ++-- .../harjot/vectormaster/models/Model.java | 17 +- .../vectormaster/models/ParentModel.java | 23 +- .../harjot/vectormaster/models/PathModel.java | 131 +++++++---- .../vectormaster/models/VectorModel.java | 219 +++++++++--------- 8 files changed, 353 insertions(+), 257 deletions(-) diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java index b9bf2aa..bf070da 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java @@ -32,7 +32,9 @@ public class VectorMasterDrawable extends Drawable { String TAG = "VECTOR_MASTER"; - private Matrix scaleMatrix; + private Matrix scaleMatrix = new Matrix(); + private boolean scaleMatrixChanged = true; + private Matrix newScaleMatrix = new Matrix(); //create a matrix object which is reused on every scaleMatrix creation private int width = -1, height = -1; @@ -138,19 +140,19 @@ public void draw(Canvas canvas) { } strokeRatio = Math.min(width / vectorModel.getWidth(), height / vectorModel.getHeight()); - Matrix translation = new Matrix(scaleMatrix); - translation.postTranslate(offsetX, offsetY); - translation.postScale(scaleX, scaleY); setAlpha(Utils.getAlphaFromFloat(vectorModel.getAlpha())); + vectorModel.calculate(scaleMatrix, scaleMatrixChanged, strokeRatio); + scaleMatrixChanged = false; + if (left != 0 || top != 0) { tempSaveCount = canvas.save(); canvas.translate(left, top); - vectorModel.draw(canvas, translation, strokeRatio); + vectorModel.draw(canvas); canvas.restoreToCount(tempSaveCount); } else { - vectorModel.draw(canvas, translation, strokeRatio); + vectorModel.draw(canvas); } } @@ -181,9 +183,9 @@ public int getIntrinsicHeight() { } private void buildScaleMatrix() { - scaleMatrix = new Matrix(); - scaleMatrix.postTranslate(width / 2 - vectorModel.getViewportWidth() / 2, height / 2 - vectorModel.getViewportHeight() / 2); + newScaleMatrix.reset(); + newScaleMatrix.postTranslate(width / 2 - vectorModel.getViewportWidth() / 2, height / 2 - vectorModel.getViewportHeight() / 2); float widthRatio = width / vectorModel.getViewportWidth(); float heightRatio = height / vectorModel.getViewportHeight(); @@ -191,7 +193,13 @@ private void buildScaleMatrix() { scaleRatio = ratio; - scaleMatrix.postScale(ratio, ratio, width / 2, height / 2); + newScaleMatrix.postScale(ratio, ratio, width / 2, height / 2); + + newScaleMatrix.postTranslate(offsetX, offsetY); + newScaleMatrix.postScale(scaleX, scaleY); + + scaleMatrix.set(newScaleMatrix); + scaleMatrixChanged = true; } public Path getFullPath() { @@ -226,7 +234,7 @@ public float getStrokeRatio() { } public Matrix getScaleMatrix() { - return scaleMatrix; + return new Matrix(scaleMatrix); //make a copy so that from outside the real scaleMatrix cannot be manipulated because this would not be propagated to the VectorModel correctly because scaleMatrixChanged would not be set. } public float getOffsetX() { @@ -235,6 +243,7 @@ public float getOffsetX() { public void setOffsetX(float offsetX) { this.offsetX = offsetX; + buildScaleMatrix(); invalidateSelf(); } @@ -244,6 +253,7 @@ public float getOffsetY() { public void setOffsetY(float offsetY) { this.offsetY = offsetY; + buildScaleMatrix(); invalidateSelf(); } @@ -253,6 +263,7 @@ public float getScaleX() { public void setScaleX(float scaleX) { this.scaleX = scaleX; + buildScaleMatrix(); invalidateSelf(); } @@ -262,6 +273,7 @@ public float getScaleY() { public void setScaleY(float scaleY) { this.scaleY = scaleY; + buildScaleMatrix(); invalidateSelf(); } } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java index 3ff035b..f49f837 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java @@ -25,7 +25,10 @@ public class VectorMasterView extends View { String TAG = "VECTOR_MASTER"; - private Matrix scaleMatrix; + private Matrix scaleMatrix = new Matrix(); + private boolean scaleMatrixChanged; + private Matrix newScaleMatrix = new Matrix(); //create a matrix object which is reused on every scaleMatrix creation + int width = 0, height = 0; @@ -109,19 +112,19 @@ protected void onDraw(Canvas canvas) { } strokeRatio = Math.min(width / vectorModel.getWidth(), height / vectorModel.getHeight()); - Matrix translation = new Matrix(scaleMatrix); setAlpha(vectorModel.getAlpha()); - vectorModel.draw(canvas, translation, scaleRatio); + vectorModel.calculate(scaleMatrix, scaleMatrixChanged, strokeRatio); + scaleMatrixChanged = false; + vectorModel.draw(canvas); } void buildScaleMatrix() { - scaleMatrix = new Matrix(); - - scaleMatrix.postTranslate(width / 2 - vectorModel.getViewportWidth() / 2, height / 2 - vectorModel.getViewportHeight() / 2); + newScaleMatrix.reset(); + newScaleMatrix.postTranslate(width / 2 - vectorModel.getViewportWidth() / 2, height / 2 - vectorModel.getViewportHeight() / 2); float widthRatio = width / vectorModel.getViewportWidth(); float heightRatio = height / vectorModel.getViewportHeight(); @@ -129,7 +132,10 @@ void buildScaleMatrix() { scaleRatio = ratio; - scaleMatrix.postScale(ratio, ratio, width / 2, height / 2); + newScaleMatrix.postScale(ratio, ratio, width / 2, height / 2); + + scaleMatrix.set(newScaleMatrix); + scaleMatrixChanged = true; } public Path getFullPath() { @@ -164,6 +170,6 @@ public float getStrokeRatio() { } public Matrix getScaleMatrix() { - return scaleMatrix; + return new Matrix(scaleMatrix); } } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java index e464f5b..7b6f4cf 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java @@ -8,70 +8,72 @@ import android.graphics.PorterDuffXfermode; public class ClipPathModel extends Model { - private String pathData; - - private Path path; - private Path transformedPath; - private Matrix lastTransformation; - - private Paint clipPaint; - - public ClipPathModel() { - path = new Path(); - clipPaint = new Paint(); - clipPaint.setAntiAlias(true); - clipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); - } - - @Override - public void prepare(Canvas canvas, Matrix parentTransformation, float strokeRatio) { - canvas.clipPath(preparePath(parentTransformation)); - } - - @Override - public void draw(Canvas canvas, Matrix parentTransformation, float strokeRatio) { - //clip path does no drawing - } - - private Path preparePath(Matrix transformation) { - //try caching as much as possible to do path calculation only if necessary - if (path == null) { - path = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); - transformedPath = null; - } - if (transformedPath == null || lastTransformation == null || !lastTransformation.equals(transformation)) { - transformedPath = transform(path, transformation); - lastTransformation = transformation; - } - return transformedPath; - } - - - public Paint getClipPaint() { - return clipPaint; - } - - public void setClipPaint(Paint clipPaint) { - this.clipPaint = clipPaint; - } - - public String getPathData() { - return pathData; + private String pathData; + + private Path path; + private Path transformedPath = new Path(); + private Matrix lastParentTransformation; + + private Paint clipPaint; + + public ClipPathModel() { + path = new Path(); + clipPaint = new Paint(); + clipPaint.setAntiAlias(true); + clipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); + } + + @Override + public void calculate(Matrix parentTransformation, Boolean transformationChanged, float strokeRatio) { + if (transformationChanged || lastParentTransformation == null) { + lastParentTransformation = parentTransformation; + calculateTransformedPath(); } + } - public void setPathData(String pathData) { - this.pathData = pathData; - path = null; - } + @Override + public void prepare(Canvas canvas) { + canvas.clipPath(transformedPath); + } - public Path getPath() { - return path; - } + @Override + public void draw(Canvas canvas) { + //clip path does no drawing + } - public void setPath(Path path) { - this.path = path; + private void calculateTransformedPath() { + if (path == null || lastParentTransformation == null) { + return; } - - + transformedPath.rewind(); + path.transform(lastParentTransformation, transformedPath); + } + + public Paint getClipPaint() { + return clipPaint; + } + + public void setClipPaint(Paint clipPaint) { + this.clipPaint = clipPaint; + } + + public String getPathData() { + return pathData; + } + + public void setPathData(String pathData) { + this.pathData = pathData; + Path path = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); + setPath(path); + } + + public Path getPath() { + return path; + } + + public void setPath(Path path) { + this.path = path; + calculateTransformedPath(); + } } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java index dd77f5a..93a5f96 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java @@ -1,6 +1,5 @@ package com.sdsmdg.harjot.vectormaster.models; -import android.graphics.Canvas; import android.graphics.Matrix; import com.sdsmdg.harjot.vectormaster.DefaultValues; @@ -13,8 +12,8 @@ public class GroupModel extends ParentModel { private float translateX, translateY; private Matrix ownTransformation; private boolean ownTransformationChanged = true; - private Matrix lastParentTransformation; private Matrix lastTransformation; + private Matrix lastTransformationWorkMatrix; //reuses this one matrix object if lastTransformation is created by concatination public GroupModel() { rotation = DefaultValues.GROUP_ROTATION; @@ -27,26 +26,39 @@ public GroupModel() { } @Override - public void draw(Canvas canvas, Matrix parentTransformation, float strokeRatio) { - - //try to keep transformed matrix the same instance as long as the values do not change - if (ownTransformationChanged || lastParentTransformation != parentTransformation) { - lastParentTransformation = parentTransformation; - lastTransformation = new Matrix(parentTransformation); - lastTransformation.preConcat(ownTransformation); + public void calculate(Matrix parentTransformation, Boolean transformationChanged, float strokeRatio) { + if (ownTransformationChanged || transformationChanged) { + if (ownTransformation == null) { + lastTransformation = parentTransformation; //no own transformation necessary, so passthrough + } else { + if (lastTransformationWorkMatrix == null) { + lastTransformationWorkMatrix = new Matrix(); //we create the work matrix only if this group needs one. After that it will be reused. + } + lastTransformationWorkMatrix.setConcat(parentTransformation, ownTransformation); //own transformation necessary, so concat with parent transformation + lastTransformation = lastTransformationWorkMatrix; + } ownTransformationChanged = false; + super.calculate(lastTransformation, true, strokeRatio); + } else { + super.calculate(lastTransformation, false, strokeRatio); } - - super.draw(canvas, lastTransformation, strokeRatio); } protected void createOwnTransformation() { - Matrix transformation = new Matrix(); - transformation.postScale(scaleX, scaleY, pivotX, pivotY); - transformation.postRotate(rotation, pivotX, pivotY); - transformation.postTranslate(translateX, translateY); + //check if we need an own transformation matrix. if there is nothing to transform, do not build a matrix + if (scaleX != 1.0 || scaleY != 1.0 || rotation != 0 || translateX != 0 || translateY != 0) { + if (ownTransformation == null) { + ownTransformation = new Matrix(); //try to create new matrix objects as less as possible + } else { + ownTransformation.reset(); + } + ownTransformation.postScale(scaleX, scaleY, pivotX, pivotY); + ownTransformation.postRotate(rotation, pivotX, pivotY); + ownTransformation.postTranslate(translateX, translateY); + } else { + ownTransformation = null; + } - ownTransformation = transformation; ownTransformationChanged = true; } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java index 73efd06..859670d 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java @@ -25,13 +25,16 @@ public void setParent(ParentModel parent) { this.parent = parent; } - public abstract void prepare(Canvas canvas, Matrix parentTransformation, float strokeRatio); - public abstract void draw(Canvas canvas, Matrix parentTransformation, float strokeRatio); - - protected Path transform(Path path, Matrix transformation) { - Path resultPath = new Path(path); - resultPath.transform(transformation); - return resultPath; + public abstract void calculate(Matrix parentTransformation, Boolean transformationChanged, float strokeRatio); + public abstract void prepare(Canvas canvas); + public abstract void draw(Canvas canvas); + + /** + * adds the UNTRANSFORMED path to collectedPath + * @return + */ + public void collectFullPath(Path collectedPath) { + //by default nothing to collect } } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java index f89a066..01a5a5b 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java @@ -2,6 +2,7 @@ import android.graphics.Canvas; import android.graphics.Matrix; +import android.graphics.Path; import java.util.ArrayList; @@ -19,18 +20,32 @@ public void addChild(Model model) { } @Override - public void prepare(Canvas canvas, Matrix parentTransformation, float strokeRatio) { + public void calculate(Matrix parentTransformation, Boolean transformationChanged, float strokeRatio) { + for (Model child : getChildren()) { + child.calculate(parentTransformation, transformationChanged, strokeRatio); + } + } + + @Override + public void prepare(Canvas canvas) { //parents by default do not prepare the canvas recursively } @Override - public void draw(Canvas canvas, Matrix parentTransformation, float strokeRatio) { + public void draw(Canvas canvas) { //parents prepare just their own children before they draw for (Model child : getChildren()) { - child.prepare(canvas, parentTransformation, strokeRatio); + child.prepare(canvas); } for (Model child : getChildren()) { - child.draw(canvas, parentTransformation, strokeRatio); + child.draw(canvas); + } + } + + @Override + public void collectFullPath(Path collectedPath) { + for (Model child : getChildren()) { + child.collectFullPath(collectedPath); } } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java index af045ab..38ecb09 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java @@ -7,6 +7,7 @@ import android.graphics.Path; import android.graphics.PathMeasure; +import android.util.Log; import com.sdsmdg.harjot.vectormaster.DefaultValues; import com.sdsmdg.harjot.vectormaster.utilities.Utils; @@ -27,19 +28,25 @@ public class PathModel extends Model { private Paint.Join strokeLineJoin; private float strokeMiterLimit; private float strokeWidth; - private float strokeRatio; + private boolean strokeChanged; + + private long averageDrawTime = 0L; + private int drawCount = 0; private boolean isFillAndStroke = false; // Support for trim-paths is not available private Path path; + private PathMeasure pathMeasure; private Path trimmedPath; - private Path transformedPath; - private Matrix lastTransformation; + private Path transformedPath = new Path(); private Paint pathPaint; + private Matrix lastParentTransformation; + private float lastStrokeRatio; + public PathModel() { fillAlpha = DefaultValues.PATH_FILL_ALPHA; fillColor = DefaultValues.PATH_FILL_COLOR; @@ -61,27 +68,33 @@ public PathModel() { } @Override - public void prepare(Canvas canvas, Matrix parentTransformation, float strokeRatio) { + public void calculate(Matrix parentTransformation, Boolean transformationChanged, float strokeRatio) { + if (transformationChanged || lastParentTransformation == null) { + lastParentTransformation = parentTransformation; + calculateTransformedPath(); + } + if (strokeChanged || lastStrokeRatio != strokeRatio) { + strokeChanged = false; + lastStrokeRatio = strokeRatio; + pathPaint.setStrokeWidth(strokeWidth * this.strokeRatio * strokeRatio); + } + } + + @Override + public void prepare(Canvas canvas) { //path do not prepare } @Override - public void draw(Canvas canvas, Matrix parentTransformation, float strokeRatio) { - //try caching as much as possible to do path calculation only if necessary - if (transformedPath == null || lastTransformation == null || !lastTransformation.equals(parentTransformation)) { - transformedPath = transform(trimmedPath, parentTransformation); - lastTransformation = parentTransformation; - } + public void draw(Canvas canvas) { transformedPath.setFillType(fillType); - Path pathToDraw = transformedPath; - pathPaint.setStrokeWidth(strokeWidth * this.strokeRatio * strokeRatio); if (isFillAndStroke()) { makeFillPaint(); - canvas.drawPath(pathToDraw, getPathPaint()); + canvas.drawPath(transformedPath, getPathPaint()); makeStrokePaint(); - canvas.drawPath(pathToDraw, getPathPaint()); + canvas.drawPath(transformedPath, getPathPaint()); } else { - canvas.drawPath(pathToDraw, getPathPaint()); + canvas.drawPath(transformedPath, getPathPaint()); } } @@ -119,30 +132,58 @@ public void makeFillPaint() { pathPaint.setStyle(Paint.Style.FILL); } - public void trimPath() { - if (path == null) { - return; - } - - if (trimPathStart == 0 && trimPathEnd == 1 && trimPathOffset == 0) { - trimmedPath = new Path(path); - transformedPath = null; - } else { - PathMeasure pathMeasure = new PathMeasure(path, false); - float length = pathMeasure.getLength(); - Path trimmed = new Path(); - pathMeasure.getSegment( - (trimPathStart + trimPathOffset) * length, - (trimPathEnd + trimPathOffset) * length, - trimmed, - true); - trimmedPath = trimmed; - transformedPath = null; - } + private void calculateTransformedPath() { + if (trimmedPath == null || lastParentTransformation == null) { + return; + } + + transformedPath.rewind(); + trimmedPath.transform(lastParentTransformation, transformedPath); + } + + private void calculateTrimmedPath() { + if (path == null) { + return; + } + + // long startTime = System.nanoTime(); + if (trimPathStart != 0 || trimPathEnd != 1 || trimPathOffset != 0) { + float trimStart = trimPathStart + trimPathOffset; + float trimEnd = trimPathEnd + trimPathOffset; + float length = pathMeasure.getLength(); + trimmedPath.rewind(); + pathMeasure.getSegment( + trimStart * length, + trimEnd * length, + trimmedPath, + true); + } else { + trimmedPath.set(path); + } +/* + long endTime = System.nanoTime(); + long drawTime = endTime - startTime; + if (averageDrawTime == 0) { + averageDrawTime = drawTime; + } else { + averageDrawTime = ((averageDrawTime + drawTime) / 2); + } + drawCount++; + if (drawCount == 500) { + drawCount = 0; + Log.i("TrimTimeTag", "Trim path took average " + averageDrawTime + " nanosecs"); + } +*/ + calculateTransformedPath(); + } + + @Override + public void collectFullPath(Path collectedPath) { + collectedPath.addPath(getPath()); } public Path getTrimmedPath() { - return trimmedPath; + return new Path(trimmedPath); } public Path getPath() { @@ -151,7 +192,9 @@ public Path getPath() { public void setPath(Path path) { this.path = path; - trimPath(); + this.pathMeasure = new PathMeasure(path, false); + this.trimmedPath = new Path(path); + calculateTrimmedPath(); } public Paint getPathPaint() { @@ -160,6 +203,7 @@ public Paint getPathPaint() { public void setPathPaint(Paint pathPaint) { this.pathPaint = pathPaint; + strokeChanged = true; } public float getFillAlpha() { @@ -194,8 +238,8 @@ public String getPathData() { public void setPathData(String pathData) { this.pathData = pathData; - this.path = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); - trimPath(); + Path path = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); + setPath(path); } public float getTrimPathStart() { @@ -204,7 +248,7 @@ public float getTrimPathStart() { public void setTrimPathStart(float trimPathStart) { this.trimPathStart = trimPathStart; - trimPath(); + calculateTrimmedPath(); } public float getTrimPathEnd() { @@ -213,7 +257,7 @@ public float getTrimPathEnd() { public void setTrimPathEnd(float trimPathEnd) { this.trimPathEnd = trimPathEnd; - trimPath(); + calculateTrimmedPath(); } public float getTrimPathOffset() { @@ -222,7 +266,7 @@ public float getTrimPathOffset() { public void setTrimPathOffset(float trimPathOffset) { this.trimPathOffset = trimPathOffset; - trimPath(); + calculateTrimmedPath(); } public float getStrokeAlpha() { @@ -276,7 +320,7 @@ public float getStrokeWidth() { public void setStrokeWidth(float strokeWidth) { this.strokeWidth = strokeWidth; - updatePaint(); + strokeChanged = true; } public boolean isFillAndStroke() { @@ -289,6 +333,7 @@ public float getStrokeRatio() { public void setStrokeRatio(float strokeRatio) { this.strokeRatio = strokeRatio; + strokeChanged = true; } } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java index 04ad0fe..5298d47 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java @@ -10,113 +10,114 @@ public class VectorModel extends ParentModel { - private float width, height; - - private float alpha = 1.0f; - - private boolean autoMirrored = false; - - private int tint = Color.TRANSPARENT; - private TintMode tintMode = TintMode.SCR_IN; - - private float viewportWidth, viewportHeight; - - private Path fullpath; - private long averageDrawTime = 0L; - private int drawCount = 0; - - public VectorModel() { - fullpath = new Path(); - } - - public Path getFullpath() { - //TODO: traverse the model to collect the currently translated pathes - throw new UnsupportedOperationException("Not implemented yet."); - } - - @Override - public void draw(Canvas canvas, Matrix parentTransformation, float strokeRatio) { - long startTime = System.nanoTime(); - super.draw(canvas, parentTransformation, strokeRatio); - long endTime = System.nanoTime(); - long drawTime = endTime - startTime; - if (averageDrawTime == 0) { - averageDrawTime = drawTime; - } else { - averageDrawTime = ((averageDrawTime + drawTime) / 2); - } - drawCount++; - if (drawCount == 50) { - drawCount = 0; - Log.i("DrawTimeTag", "Draw took average " + averageDrawTime + " nanosecs"); - } - } - - public void setFullpath(Path fullpath) { - this.fullpath = fullpath; - } - - public float getWidth() { - return width; - } - - public void setWidth(float width) { - this.width = width; - } - - public float getHeight() { - return height; - } - - public void setHeight(float height) { - this.height = height; - } - - public float getAlpha() { - return alpha; - } - - public void setAlpha(float alpha) { - this.alpha = alpha; - } - - public boolean isAutoMirrored() { - return autoMirrored; - } - - public void setAutoMirrored(boolean autoMirrored) { - this.autoMirrored = autoMirrored; - } - - public int getTint() { - return tint; - } - - public void setTint(int tint) { - this.tint = tint; - } - - public TintMode getTintMode() { - return tintMode; - } - - public void setTintMode(TintMode tintMode) { - this.tintMode = tintMode; - } - - public float getViewportWidth() { - return viewportWidth; - } - - public void setViewportWidth(float viewportWidth) { - this.viewportWidth = viewportWidth; - } - - public float getViewportHeight() { - return viewportHeight; - } - - public void setViewportHeight(float viewportHeight) { - this.viewportHeight = viewportHeight; - } + private float width, height; + + private float alpha = 1.0f; + + private boolean autoMirrored = false; + + private int tint = Color.TRANSPARENT; + private TintMode tintMode = TintMode.SCR_IN; + + private float viewportWidth, viewportHeight; + + private Path fullpath; + private long averageDrawTime = 0L; + private int drawCount = 0; + + public VectorModel() { + fullpath = new Path(); + } + + /** + * returns the UNTRANSFORMED paths + * @return + */ + public Path getFullpath() { + Path fullPath = new Path(); + collectFullPath(fullPath); + return fullPath; + } + + @Override + public void draw(Canvas canvas) { + long startTime = System.nanoTime(); + super.draw(canvas); + long endTime = System.nanoTime(); + long drawTime = endTime - startTime; + if (averageDrawTime == 0) { + averageDrawTime = drawTime; + } else { + averageDrawTime = ((averageDrawTime + drawTime) / 2); + } + drawCount++; + if (drawCount == 50) { + drawCount = 0; + Log.i("DrawTimeTag", "Draw took average " + averageDrawTime + " nanosecs"); + } + } + + public float getWidth() { + return width; + } + + public void setWidth(float width) { + this.width = width; + } + + public float getHeight() { + return height; + } + + public void setHeight(float height) { + this.height = height; + } + + public float getAlpha() { + return alpha; + } + + public void setAlpha(float alpha) { + this.alpha = alpha; + } + + public boolean isAutoMirrored() { + return autoMirrored; + } + + public void setAutoMirrored(boolean autoMirrored) { + this.autoMirrored = autoMirrored; + } + + public int getTint() { + return tint; + } + + public void setTint(int tint) { + this.tint = tint; + } + + public TintMode getTintMode() { + return tintMode; + } + + public void setTintMode(TintMode tintMode) { + this.tintMode = tintMode; + } + + public float getViewportWidth() { + return viewportWidth; + } + + public void setViewportWidth(float viewportWidth) { + this.viewportWidth = viewportWidth; + } + + public float getViewportHeight() { + return viewportHeight; + } + + public void setViewportHeight(float viewportHeight) { + this.viewportHeight = viewportHeight; + } } From 3ac304f13a4f31a5f2255e52c03691f495238b46 Mon Sep 17 00:00:00 2001 From: Xalag Date: Tue, 26 Mar 2019 21:39:25 +0100 Subject: [PATCH 5/9] Added some comments. Removed draw time measure code. --- .../vectormaster/models/GroupModel.java | 1 - .../harjot/vectormaster/models/Model.java | 9 ++++++- .../vectormaster/models/ParentModel.java | 13 +++++++++- .../harjot/vectormaster/models/PathModel.java | 22 +--------------- .../vectormaster/models/VectorModel.java | 26 ------------------- 5 files changed, 21 insertions(+), 50 deletions(-) diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java index 93a5f96..9b02410 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java @@ -1,7 +1,6 @@ package com.sdsmdg.harjot.vectormaster.models; import android.graphics.Matrix; - import com.sdsmdg.harjot.vectormaster.DefaultValues; public class GroupModel extends ParentModel { diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java index 859670d..27bd128 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java @@ -25,12 +25,19 @@ public void setParent(ParentModel parent) { this.parent = parent; } + /** + * The rendering process always calls calculate(), perform(), draw() so that the models recalculate dynamically if needed. + * The methods should cache as much as possible and avoid allocation of new objects. + * @param parentTransformation + * @param transformationChanged + * @param strokeRatio + */ public abstract void calculate(Matrix parentTransformation, Boolean transformationChanged, float strokeRatio); public abstract void prepare(Canvas canvas); public abstract void draw(Canvas canvas); /** - * adds the UNTRANSFORMED path to collectedPath + * adds the UNTRANSFORMED path (if the model has one) to collectedPath * @return */ public void collectFullPath(Path collectedPath) { diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java index 01a5a5b..43ac613 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ParentModel.java @@ -10,13 +10,24 @@ public abstract class ParentModel extends Model { private ArrayList children = new ArrayList<>(0); + /** + * If you want to add a model consider using addChild() instead. + * Gets the list of children from this parent model. + * Make sure to add/remove/insert models only on the main-thread because the list of children is not thread save. + * Also make sure to call childModel.setParent(parent) when adding children to this list. + */ public ArrayList getChildren() { return children; } + /** + * Adds a child model to this parent model. Also automatically sets the parent on the child model. + * Make sure to add new models on the main-thread because the list of children is not thread save. + * @param model + */ public void addChild(Model model) { - getChildren().add(model); model.setParent(this); + getChildren().add(model); } @Override diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java index 38ecb09..6440c54 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java @@ -7,7 +7,6 @@ import android.graphics.Path; import android.graphics.PathMeasure; -import android.util.Log; import com.sdsmdg.harjot.vectormaster.DefaultValues; import com.sdsmdg.harjot.vectormaster.utilities.Utils; @@ -31,13 +30,8 @@ public class PathModel extends Model { private float strokeRatio; private boolean strokeChanged; - private long averageDrawTime = 0L; - private int drawCount = 0; - private boolean isFillAndStroke = false; - // Support for trim-paths is not available - private Path path; private PathMeasure pathMeasure; private Path trimmedPath; @@ -146,7 +140,6 @@ private void calculateTrimmedPath() { return; } - // long startTime = System.nanoTime(); if (trimPathStart != 0 || trimPathEnd != 1 || trimPathOffset != 0) { float trimStart = trimPathStart + trimPathOffset; float trimEnd = trimPathEnd + trimPathOffset; @@ -160,20 +153,7 @@ private void calculateTrimmedPath() { } else { trimmedPath.set(path); } -/* - long endTime = System.nanoTime(); - long drawTime = endTime - startTime; - if (averageDrawTime == 0) { - averageDrawTime = drawTime; - } else { - averageDrawTime = ((averageDrawTime + drawTime) / 2); - } - drawCount++; - if (drawCount == 500) { - drawCount = 0; - Log.i("TrimTimeTag", "Trim path took average " + averageDrawTime + " nanosecs"); - } -*/ + calculateTransformedPath(); } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java index 5298d47..1c76571 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java @@ -1,11 +1,8 @@ package com.sdsmdg.harjot.vectormaster.models; -import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Matrix; import android.graphics.Path; -import android.util.Log; import com.sdsmdg.harjot.vectormaster.enums.TintMode; public class VectorModel extends ParentModel { @@ -21,12 +18,7 @@ public class VectorModel extends ParentModel { private float viewportWidth, viewportHeight; - private Path fullpath; - private long averageDrawTime = 0L; - private int drawCount = 0; - public VectorModel() { - fullpath = new Path(); } /** @@ -39,24 +31,6 @@ public Path getFullpath() { return fullPath; } - @Override - public void draw(Canvas canvas) { - long startTime = System.nanoTime(); - super.draw(canvas); - long endTime = System.nanoTime(); - long drawTime = endTime - startTime; - if (averageDrawTime == 0) { - averageDrawTime = drawTime; - } else { - averageDrawTime = ((averageDrawTime + drawTime) / 2); - } - drawCount++; - if (drawCount == 50) { - drawCount = 0; - Log.i("DrawTimeTag", "Draw took average " + averageDrawTime + " nanosecs"); - } - } - public float getWidth() { return width; } From 143fdbf4794c2408fa94147a0badde40b8ce1650 Mon Sep 17 00:00:00 2001 From: Xalag Date: Tue, 26 Mar 2019 21:55:59 +0100 Subject: [PATCH 6/9] Fixed useLegacyParser option. --- .../com/sdsmdg/harjot/vectormaster/ModelParser.java | 6 +++--- .../harjot/vectormaster/VectorMasterDrawable.java | 2 +- .../sdsmdg/harjot/vectormaster/VectorMasterView.java | 2 +- .../harjot/vectormaster/models/ClipPathModel.java | 12 +++++++++++- .../sdsmdg/harjot/vectormaster/models/PathModel.java | 12 +++++++++++- 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/ModelParser.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/ModelParser.java index e58904e..13d5101 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/ModelParser.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/ModelParser.java @@ -24,7 +24,7 @@ int getAttrPosition(XmlPullParser xpp, String attrName) { return -1; } - public VectorModel buildVectorModel(Resources resources, int resID) { + public VectorModel buildVectorModel(Resources resources, int resID, boolean useLegacyParser) { if (resID == -1) { return null; @@ -96,7 +96,7 @@ public VectorModel buildVectorModel(Resources resources, int resID) { DefaultValues.PATH_FILL_TYPE); tempPosition = getAttrPosition(xpp, "pathData"); - pathModel.setPathData((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); + pathModel.setPathData((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null, useLegacyParser); tempPosition = getAttrPosition(xpp, "strokeAlpha"); pathModel.setStrokeAlpha((tempPosition != -1) ? @@ -192,7 +192,7 @@ public VectorModel buildVectorModel(Resources resources, int resID) { clipPathModel.setName((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); tempPosition = getAttrPosition(xpp, "pathData"); - clipPathModel.setPathData((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null); + clipPathModel.setPathData((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null, useLegacyParser); } break; diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java index bf070da..6f71cdb 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java @@ -77,7 +77,7 @@ private void buildVectorModel() { vectorModel = null; return; } - vectorModel = new ModelParser().buildVectorModel(resources, resID); + vectorModel = new ModelParser().buildVectorModel(resources, resID, useLegacyParser); } private int getAttrPosition(XmlPullParser xpp, String attrName) { diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java index f49f837..f30dfe3 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java @@ -77,7 +77,7 @@ void buildVectorModel() { return; } - vectorModel = new ModelParser().buildVectorModel(resources, resID); + vectorModel = new ModelParser().buildVectorModel(resources, resID, useLegacyParser); } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java index 7b6f4cf..5a66745 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java @@ -6,6 +6,7 @@ import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; +import com.sdsmdg.harjot.vectormaster.utilities.parser.PathParser; public class ClipPathModel extends Model { private String pathData; @@ -62,8 +63,17 @@ public String getPathData() { } public void setPathData(String pathData) { + setPathData(pathData, true); + } + + public void setPathData(String pathData, boolean useLegacyParser) { this.pathData = pathData; - Path path = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); + Path path = null; + if (useLegacyParser) { + path = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); + } else { + path = PathParser.doPath(pathData); + } setPath(path); } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java index 6440c54..e760456 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java @@ -9,6 +9,7 @@ import com.sdsmdg.harjot.vectormaster.DefaultValues; import com.sdsmdg.harjot.vectormaster.utilities.Utils; +import com.sdsmdg.harjot.vectormaster.utilities.parser.PathParser; public class PathModel extends Model { @@ -217,8 +218,17 @@ public String getPathData() { } public void setPathData(String pathData) { + setPathData(pathData, true); + } + + public void setPathData(String pathData, boolean useLegacyParser) { this.pathData = pathData; - Path path = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); + Path path = null; + if (useLegacyParser) { + path = com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(pathData); + } else { + path = PathParser.doPath(pathData); + } setPath(path); } From 690c4b8d7b54441640fa9b301354f2ff90a39a2d Mon Sep 17 00:00:00 2001 From: Xalag Date: Tue, 26 Mar 2019 22:31:12 +0100 Subject: [PATCH 7/9] Updated Gradle and targetSdkVersion --- app/build.gradle | 12 ++++++------ build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- vectormaster/build.gradle | 9 ++++----- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 1b28df4..ee7b576 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,12 +1,12 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion '26.0.2' + compileSdkVersion 28 + buildToolsVersion '28.0.3' defaultConfig { applicationId "com.sdsmdg.harjot.vectormasterdemo" minSdkVersion 16 - targetSdkVersion 25 + targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -21,7 +21,7 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:25.3.0' - compile project(":vectormaster") + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation project(":vectormaster") } diff --git a/build.gradle b/build.gradle index a0db355..d50214f 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.0.1' + classpath 'com.android.tools.build:gradle:3.3.2' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8909a54..1eb2bea 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Nov 17 02:03:24 IST 2017 +#Tue Mar 26 22:16:32 CET 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip diff --git a/vectormaster/build.gradle b/vectormaster/build.gradle index d121b0c..e094c9c 100644 --- a/vectormaster/build.gradle +++ b/vectormaster/build.gradle @@ -25,12 +25,12 @@ ext { } android { - compileSdkVersion 25 - buildToolsVersion '26.0.2' + compileSdkVersion 28 + buildToolsVersion '28.0.3' defaultConfig { minSdkVersion 16 - targetSdkVersion 25 + targetSdkVersion 28 versionCode 1 versionName "1.0" @@ -46,8 +46,7 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:25.3.0' + implementation fileTree(dir: 'libs', include: ['*.jar']) } apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle' From 9ec45fc6c9bba4da05b69e89f621f94b82ac00e1 Mon Sep 17 00:00:00 2001 From: Xalag Date: Tue, 26 Mar 2019 23:38:24 +0100 Subject: [PATCH 8/9] Updated library version --- vectormaster/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vectormaster/build.gradle b/vectormaster/build.gradle index e094c9c..d57ac72 100644 --- a/vectormaster/build.gradle +++ b/vectormaster/build.gradle @@ -13,7 +13,7 @@ ext { siteUrl = 'https://github.com/harjot-oberai/VectorMaster/' gitUrl = 'https://github.com/harjot-oberai/VectorMaster/.git' - libraryVersion = '1.1.3' + libraryVersion = '1.2.0' developerId = 'harjot-oberai' developerName = 'Harjot Singh Oberai' From a46027be19da3120d38d132b12171ce6894299db Mon Sep 17 00:00:00 2001 From: Xalag Date: Tue, 26 Mar 2019 23:39:37 +0100 Subject: [PATCH 9/9] Fixed seldom flickering. --- .../vectormaster/models/GroupModel.java | 32 +++++++++---------- .../harjot/vectormaster/models/Model.java | 16 ++++++++++ .../harjot/vectormaster/models/PathModel.java | 2 +- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java index 9b02410..3ac3690 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java @@ -10,7 +10,9 @@ public class GroupModel extends ParentModel { private float scaleX, scaleY; private float translateX, translateY; private Matrix ownTransformation; + private Matrix ownTransformationWorkMatrix; //reuses this one matrix object if lastTransformation is created by concatination private boolean ownTransformationChanged = true; + private boolean hasOwnTransformation = false; private Matrix lastTransformation; private Matrix lastTransformationWorkMatrix; //reuses this one matrix object if lastTransformation is created by concatination @@ -27,16 +29,16 @@ public GroupModel() { @Override public void calculate(Matrix parentTransformation, Boolean transformationChanged, float strokeRatio) { if (ownTransformationChanged || transformationChanged) { - if (ownTransformation == null) { - lastTransformation = parentTransformation; //no own transformation necessary, so passthrough - } else { - if (lastTransformationWorkMatrix == null) { - lastTransformationWorkMatrix = new Matrix(); //we create the work matrix only if this group needs one. After that it will be reused. - } + ownTransformationChanged = false; + + if (hasOwnTransformation) { + lastTransformationWorkMatrix = initializeMatrix(lastTransformationWorkMatrix, null); lastTransformationWorkMatrix.setConcat(parentTransformation, ownTransformation); //own transformation necessary, so concat with parent transformation lastTransformation = lastTransformationWorkMatrix; + } else { + lastTransformation = parentTransformation; //no own transformation necessary, so passthrough } - ownTransformationChanged = false; + super.calculate(lastTransformation, true, strokeRatio); } else { super.calculate(lastTransformation, false, strokeRatio); @@ -46,16 +48,14 @@ public void calculate(Matrix parentTransformation, Boolean transformationChanged protected void createOwnTransformation() { //check if we need an own transformation matrix. if there is nothing to transform, do not build a matrix if (scaleX != 1.0 || scaleY != 1.0 || rotation != 0 || translateX != 0 || translateY != 0) { - if (ownTransformation == null) { - ownTransformation = new Matrix(); //try to create new matrix objects as less as possible - } else { - ownTransformation.reset(); - } - ownTransformation.postScale(scaleX, scaleY, pivotX, pivotY); - ownTransformation.postRotate(rotation, pivotX, pivotY); - ownTransformation.postTranslate(translateX, translateY); + ownTransformationWorkMatrix = initializeMatrix(ownTransformationWorkMatrix, null); + ownTransformationWorkMatrix.postScale(scaleX, scaleY, pivotX, pivotY); + ownTransformationWorkMatrix.postRotate(rotation, pivotX, pivotY); + ownTransformationWorkMatrix.postTranslate(translateX, translateY); + ownTransformation = initializeMatrix(ownTransformation, ownTransformationWorkMatrix); + hasOwnTransformation = true; } else { - ownTransformation = null; + hasOwnTransformation = false; } ownTransformationChanged = true; diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java index 27bd128..8c96e03 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/Model.java @@ -44,4 +44,20 @@ public void collectFullPath(Path collectedPath) { //by default nothing to collect } + protected Matrix initializeMatrix(Matrix matrix, Matrix initialValue) { + if (matrix == null) { + matrix = new Matrix(); //try to create new matrix objects as less as possible + if (initialValue != null) { + matrix.set(initialValue); + } + } else { + if (initialValue != null) { + matrix.set(initialValue); + } else { + matrix.reset(); + } + } + return matrix; + } + } diff --git a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java index e760456..a20e586 100644 --- a/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java +++ b/vectormaster/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java @@ -132,7 +132,7 @@ private void calculateTransformedPath() { return; } - transformedPath.rewind(); + //transformedPath.rewind(); trimmedPath.transform(lastParentTransformation, transformedPath); }