diff --git a/core/src/processing/core/PShape.java b/core/src/processing/core/PShape.java index a1a5fb99e..cd95310ce 100644 --- a/core/src/processing/core/PShape.java +++ b/core/src/processing/core/PShape.java @@ -85,7 +85,7 @@ public class PShape implements PConstants { protected int family; /** ELLIPSE, LINE, QUAD; TRIANGLE_FAN, QUAD_STRIP; etc. */ - protected int kind; + protected int primitive; protected PMatrix matrix; @@ -140,7 +140,7 @@ public class PShape implements PConstants { static public final int BEZIER_VERTEX = 1; static public final int CURVE_VERTEX = 2; static public final int BREAK = 3; - /** Array of VERTEX, BEZIER_VERTEX, and CURVE_VERTEXT calls. */ + /** Array of VERTEX, BEZIER_VERTEX, and CURVE_VERTEX calls. */ protected int vertexCodeCount; protected int[] vertexCodes; /** True if this is a closed path. */ @@ -427,10 +427,10 @@ public class PShape implements PConstants { protected void drawPrimitive(PGraphics g) { - if (kind == POINT) { + if (primitive == POINT) { g.point(params[0], params[1]); - } else if (kind == LINE) { + } else if (primitive == LINE) { if (params.length == 4) { // 2D g.line(params[0], params[1], params[2], params[3]); @@ -439,18 +439,18 @@ public class PShape implements PConstants { params[3], params[4], params[5]); } - } else if (kind == TRIANGLE) { + } else if (primitive == TRIANGLE) { g.triangle(params[0], params[1], params[2], params[3], params[4], params[5]); - } else if (kind == QUAD) { + } else if (primitive == QUAD) { g.quad(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7]); - } else if (kind == RECT) { + } else if (primitive == RECT) { if (image != null) { g.imageMode(CORNER); g.image(image, params[0], params[1], params[2], params[3]); @@ -459,29 +459,29 @@ public class PShape implements PConstants { g.rect(params[0], params[1], params[2], params[3]); } - } else if (kind == ELLIPSE) { + } else if (primitive == ELLIPSE) { g.ellipseMode(CORNER); g.ellipse(params[0], params[1], params[2], params[3]); - } else if (kind == ARC) { + } else if (primitive == ARC) { g.ellipseMode(CORNER); g.arc(params[0], params[1], params[2], params[3], params[4], params[5]); - } else if (kind == BOX) { + } else if (primitive == BOX) { if (params.length == 1) { g.box(params[0]); } else { g.box(params[0], params[1], params[2]); } - } else if (kind == SPHERE) { + } else if (primitive == SPHERE) { g.sphere(params[0]); } } protected void drawGeometry(PGraphics g) { - g.beginShape(kind); + g.beginShape(primitive); if (style) { for (int i = 0; i < vertexCount; i++) { g.vertex(vertices[i]); @@ -722,6 +722,95 @@ public class PShape implements PConstants { // } + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + + /** The shape type, one of GROUP, PRIMITIVE, PATH, or GEOMETRY. */ + public int getFamily() { + return family; + } + + + public int getPrimitive() { + return primitive; + } + + + public int getVertexCount() { + return vertexCount; + } + + + public float[] getVertex(int index) { + if (index < 0 || index >= vertexCount) { + String msg = "No vertex " + index + " for this shape, " + + "only vertices 0 through " + (vertexCount-1) + "."; + throw new IllegalArgumentException(msg); + } + return vertices[index]; + } + + + public float getVertexX(int index) { + return vertices[index][X]; + } + + + public float getVertexY(int index) { + return vertices[index][Y]; + } + + + public float getVertexZ(int index) { + return vertices[index][Z]; + } + + + public int[] getVertexCodes() { + if (vertexCodes.length != vertexCodeCount) { + vertexCodes = PApplet.subset(vertexCodes, 0, vertexCodeCount); + } + return vertexCodes; + } + + + public int getVertexCodeCount() { + return vertexCodeCount; + } + + + /** + * One of VERTEX, BEZIER_VERTEX, CURVE_VERTEX, or BREAK. + */ + public int getVertexCode(int index) { + return vertexCodes[index]; + } + + + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + + // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html + public boolean contains(float x, float y) { + if (family == PATH) { + boolean c = false; + for (int i = 0, j = vertexCount-1; i < vertexCount; j = i++) { + if (((vertices[i][Y] > y) != (vertices[j][Y] > y)) && + (x < + (vertices[j][X]-vertices[i][X]) * + (y-vertices[i][Y]) / + (vertices[j][1]-vertices[i][Y]) + + vertices[i][X])) { + c = !c; + } + } + return c; + } else { + throw new IllegalArgumentException("The contains() method is only implemented for paths."); + } + } + + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . diff --git a/core/src/processing/core/PShapeSVG.java b/core/src/processing/core/PShapeSVG.java index 15770bddb..33be6c6a7 100644 --- a/core/src/processing/core/PShapeSVG.java +++ b/core/src/processing/core/PShapeSVG.java @@ -241,6 +241,15 @@ public class PShapeSVG extends PShape { element = properties; name = properties.getStringAttribute("id"); + // @#$(* adobe illustrator mangles names of objects when re-saving + if (name != null) { + while (true) { + String[] m = PApplet.match(name, "_x(.*)_"); + if (m == null) break; + char repair = (char) PApplet.unhex(m[1]); + name = name.replace(m[0], "" + repair); + } + } String displayStr = properties.getStringAttribute("display", "inline"); visible = !displayStr.equals("none"); @@ -329,8 +338,9 @@ public class PShapeSVG extends PShape { } else if (name.equals("linearGradient")) { return new LinearGradient(this, elem); - } else if (name.equals("text")) { - PGraphics.showWarning("Text in SVG files is not currently supported, " + + } else if (name.equals("text") || name.equals("font")) { + PGraphics.showWarning("Text and fonts in SVG files " + + "are not currently supported, " + "convert text to outlines instead."); } else if (name.equals("filter")) { @@ -339,6 +349,15 @@ public class PShapeSVG extends PShape { } else if (name.equals("mask")) { PGraphics.showWarning("Masks are not supported."); + } else if (name.equals("pattern")) { + PGraphics.showWarning("Patterns are not supported."); + + } else if (name.equals("stop")) { + // stop tag is handled by gradient parser, so don't warn about it + + } else if (name.equals("sodipodi:namedview")) { + // these are always in Inkscape files, the warnings get tedious + } else { PGraphics.showWarning("Ignoring <" + name + "> tag."); } @@ -347,7 +366,7 @@ public class PShapeSVG extends PShape { protected void parseLine() { - kind = LINE; + primitive = LINE; family = PRIMITIVE; params = new float[] { element.getFloatAttribute("x1"), @@ -367,7 +386,7 @@ public class PShapeSVG extends PShape { * @param circle true if this is a circle and not an ellipse */ protected void parseEllipse(boolean circle) { - kind = ELLIPSE; + primitive = ELLIPSE; family = PRIMITIVE; params = new float[4]; @@ -390,7 +409,7 @@ public class PShapeSVG extends PShape { protected void parseRect() { - kind = RECT; + primitive = RECT; family = PRIMITIVE; params = new float[] { element.getFloatAttribute("x"), @@ -425,7 +444,7 @@ public class PShapeSVG extends PShape { protected void parsePath() { family = PATH; - kind = 0; + primitive = 0; String pathData = element.getStringAttribute("d"); if (pathData == null) return;