diff options
57 files changed, 4600 insertions, 4492 deletions
diff --git a/src/ooxml/java/org/apache/poi/xdgf/exceptions/XDGFException.java b/src/ooxml/java/org/apache/poi/xdgf/exceptions/XDGFException.java index 3e173779c8..379877e0d4 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/exceptions/XDGFException.java +++ b/src/ooxml/java/org/apache/poi/xdgf/exceptions/XDGFException.java @@ -22,29 +22,32 @@ import org.apache.poi.POIXMLException; public class XDGFException { - /** - * Creates an error message to be thrown - */ - public static POIXMLException error(String message, Object o) { - return new POIXMLException(o.toString() + ": " + message); - } - - public static POIXMLException error(String message, Object o, Throwable t) { - return new POIXMLException(o.toString() + ": " + message, t); - } - - // - // Use these to wrap error messages coming up so that we have at least - // some idea where the error was located - // - - public static POIXMLException wrap(POIXMLDocumentPart part, POIXMLException e) { - return new POIXMLException(part.getPackagePart().getPartName().toString() + ": " + e.getMessage(), - e.getCause() == null ? e : e.getCause()); - } - - public static POIXMLException wrap(String where, POIXMLException e) { - return new POIXMLException(where + ": " + e.getMessage(), - e.getCause() == null ? e : e.getCause()); - } + /** + * Creates an error message to be thrown + */ + public static POIXMLException error(String message, Object o) { + return new POIXMLException(o.toString() + ": " + message); + } + + public static POIXMLException error(String message, Object o, Throwable t) { + return new POIXMLException(o.toString() + ": " + message, t); + } + + // + // Use these to wrap error messages coming up so that we have at least + // some idea where the error was located + // + + public static POIXMLException wrap(POIXMLDocumentPart part, + POIXMLException e) { + return new POIXMLException(part.getPackagePart().getPartName() + .toString() + + ": " + e.getMessage(), e.getCause() == null ? e + : e.getCause()); + } + + public static POIXMLException wrap(String where, POIXMLException e) { + return new POIXMLException(where + ": " + e.getMessage(), + e.getCause() == null ? e : e.getCause()); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/geom/Dimension2dDouble.java b/src/ooxml/java/org/apache/poi/xdgf/geom/Dimension2dDouble.java index 63a5031f75..94b887e04e 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/geom/Dimension2dDouble.java +++ b/src/ooxml/java/org/apache/poi/xdgf/geom/Dimension2dDouble.java @@ -21,53 +21,53 @@ import java.awt.geom.Dimension2D; public class Dimension2dDouble extends Dimension2D { - double width; - double height; - - public Dimension2dDouble() { - width = 0d; - height = 0d; - } - - public Dimension2dDouble(double width, double height) { - this.width = width; - this.height = height; - } - - @Override - public double getWidth() { - return width; - } + double width; + double height; - @Override - public double getHeight() { - return height; - } + public Dimension2dDouble() { + width = 0d; + height = 0d; + } - @Override - public void setSize(double width, double height) { - this.width = width; - this.height = height; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Dimension2dDouble) { - Dimension2dDouble other = (Dimension2dDouble)obj; - return width == other.width && height == other.height; - } - - return false; - } - - @Override - public int hashCode() { - double sum = width + height; - return (int)Math.ceil(sum * (sum + 1)/2 + width); - } - - @Override - public String toString() { - return "Dimension2dDouble[" + width + ", " + height + "]"; - } + public Dimension2dDouble(double width, double height) { + this.width = width; + this.height = height; + } + + @Override + public double getWidth() { + return width; + } + + @Override + public double getHeight() { + return height; + } + + @Override + public void setSize(double width, double height) { + this.width = width; + this.height = height; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Dimension2dDouble) { + Dimension2dDouble other = (Dimension2dDouble) obj; + return width == other.width && height == other.height; + } + + return false; + } + + @Override + public int hashCode() { + double sum = width + height; + return (int) Math.ceil(sum * (sum + 1) / 2 + width); + } + + @Override + public String toString() { + return "Dimension2dDouble[" + width + ", " + height + "]"; + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/geom/SplineCollector.java b/src/ooxml/java/org/apache/poi/xdgf/geom/SplineCollector.java index 23f2636846..f1037a4fb8 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/geom/SplineCollector.java +++ b/src/ooxml/java/org/apache/poi/xdgf/geom/SplineCollector.java @@ -20,60 +20,56 @@ package org.apache.poi.xdgf.geom; import java.awt.geom.Point2D; import java.util.ArrayList; +import org.apache.poi.ss.formula.functions.LookupUtils.ValueVector; import org.apache.poi.xdgf.usermodel.XDGFShape; import org.apache.poi.xdgf.usermodel.section.geometry.SplineKnot; import org.apache.poi.xdgf.usermodel.section.geometry.SplineStart; -import com.graphbuilder.curve.ControlPath; -import com.graphbuilder.curve.ShapeMultiPath; -import com.graphbuilder.curve.ValueVector; -import com.graphbuilder.geom.PointFactory; - public class SplineCollector { - SplineStart _start; - ArrayList<SplineKnot> _knots = new ArrayList<>(); - - public SplineCollector(SplineStart start) { - _start = start; - } - - public void addKnot(SplineKnot knot) { - if (!knot.getDel()) - _knots.add(knot); - } - - public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { - // ok, we have the start, and all knots... do something with this - - Point2D last = path.getCurrentPoint(); - - // create a control path and knots - ControlPath controlPath = new ControlPath(); - ValueVector knots = new ValueVector(_knots.size() + 3); - - double firstKnot = _start.getB(); - double lastKnot = _start.getC(); - int degree = _start.getD(); - - // first/second knot - knots.add(firstKnot); - knots.add(_start.getA()); - - // first/second control point - controlPath.addPoint(PointFactory.create(last.getX(), last.getY())); - controlPath.addPoint(PointFactory.create(_start.getX(), _start.getY())); - - // middle knots/control points - for (SplineKnot knot: _knots) { - knots.add(knot.getA()); - controlPath.addPoint(PointFactory.create(knot.getX(), knot.getY())); - } - - // last knot - knots.add(lastKnot); - - ShapeMultiPath shape = SplineRenderer.createNurbsSpline(controlPath, knots, null, degree); - path.append(shape, true); - } + SplineStart _start; + ArrayList<SplineKnot> _knots = new ArrayList<SplineKnot>(); + + public SplineCollector(SplineStart start) { + _start = start; + } + + public void addKnot(SplineKnot knot) { + if (!knot.getDel()) + _knots.add(knot); + } + + public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { + // ok, we have the start, and all knots... do something with this + + Point2D last = path.getCurrentPoint(); + + // create a control path and knots + ControlPath controlPath = new ControlPath(); + ValueVector knots = new ValueVector(_knots.size() + 3); + + double firstKnot = _start.getB(); + double lastKnot = _start.getC(); + int degree = _start.getD(); + + // first/second knot + knots.add(firstKnot); + knots.add(_start.getA()); + + // first/second control point + controlPath.addPoint(PointFactory.create(last.getX(), last.getY())); + controlPath.addPoint(PointFactory.create(_start.getX(), _start.getY())); + + // middle knots/control points + for (SplineKnot knot: _knots) { + knots.add(knot.getA()); + controlPath.addPoint(PointFactory.create(knot.getX(), knot.getY())); + } + + // last knot + knots.add(lastKnot); + + ShapeMultiPath shape = SplineRenderer.createNurbsSpline(controlPath, knots, null, degree); + path.append(shape, true); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/geom/SplineRenderer.java b/src/ooxml/java/org/apache/poi/xdgf/geom/SplineRenderer.java index 060555d429..7757860084 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/geom/SplineRenderer.java +++ b/src/ooxml/java/org/apache/poi/xdgf/geom/SplineRenderer.java @@ -17,52 +17,46 @@ package org.apache.poi.xdgf.geom; -import com.graphbuilder.curve.ControlPath; -import com.graphbuilder.curve.GroupIterator; -import com.graphbuilder.curve.NURBSpline; -import com.graphbuilder.curve.ShapeMultiPath; -import com.graphbuilder.curve.ValueVector; +import org.apache.poi.ss.formula.functions.LookupUtils.ValueVector; public class SplineRenderer { - public static ShapeMultiPath createNurbsSpline(ControlPath controlPoints, - ValueVector knots, - ValueVector weights, - int degree) { - - double firstKnot = knots.get(0); - double lastKnot = knots.get(knots.size()-1); - - // scale knots to [0, 1] based on first/last knots - for (int i = 0; i < knots.size(); i++) { - knots.set((knots.get(i) - firstKnot)/lastKnot, i); - } - - // if we don't have enough knots, duplicate the last knot until we do - for (int i = knots.size(); i < controlPoints.numPoints() + degree + 1; i++) { - knots.add(1); - } - - GroupIterator gi = new GroupIterator("0:n-1", controlPoints.numPoints()); - - NURBSpline spline = new NURBSpline(controlPoints, gi); - - spline.setDegree(degree); - spline.setKnotVectorType(NURBSpline.NON_UNIFORM); - spline.setKnotVector(knots); - - if (weights == null) { - spline.setUseWeightVector(false); - } else { - spline.setWeightVector(weights); - } - - // now that this is done, add it to the path - ShapeMultiPath shape = new ShapeMultiPath(); - shape.setFlatness(0.01); - - spline.appendTo(shape); - return shape; - } - + public static ShapeMultiPath createNurbsSpline(ControlPath controlPoints, + ValueVector knots, ValueVector weights, int degree) { + + double firstKnot = knots.get(0); + double lastKnot = knots.get(knots.size() - 1); + + // scale knots to [0, 1] based on first/last knots + for (int i = 0; i < knots.size(); i++) { + knots.set((knots.get(i) - firstKnot) / lastKnot, i); + } + + // if we don't have enough knots, duplicate the last knot until we do + for (int i = knots.size(); i < controlPoints.numPoints() + degree + 1; i++) { + knots.add(1); + } + + GroupIterator gi = new GroupIterator("0:n-1", controlPoints.numPoints()); + + NURBSpline spline = new NURBSpline(controlPoints, gi); + + spline.setDegree(degree); + spline.setKnotVectorType(NURBSpline.NON_UNIFORM); + spline.setKnotVector(knots); + + if (weights == null) { + spline.setUseWeightVector(false); + } else { + spline.setWeightVector(weights); + } + + // now that this is done, add it to the path + ShapeMultiPath shape = new ShapeMultiPath(); + shape.setFlatness(0.01); + + spline.appendTo(shape); + return shape; + } + } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFBaseContents.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFBaseContents.java index 79edbd970c..ac4c196029 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFBaseContents.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFBaseContents.java @@ -44,116 +44,116 @@ import com.microsoft.schemas.office.visio.x2012.main.ShapeSheetType; */ public class XDGFBaseContents extends XDGFXMLDocumentPart { - protected PageContentsType _pageContents; - - // shapes without parents - protected List<XDGFShape> _toplevelShapes = new ArrayList<>(); - protected Map<Long, XDGFShape> _shapes = new HashMap<>(); - protected List<XDGFConnection> _connections = new ArrayList<>(); - - public XDGFBaseContents(PackagePart part, PackageRelationship rel, XDGFDocument document) { - super(part, rel, document); - } - - @Internal - public PageContentsType getXmlObject() { - return _pageContents; - } - - - @Override - protected void onDocumentRead() { - - if (_pageContents.isSetShapes()) { - for (ShapeSheetType shapeSheet: _pageContents.getShapes().getShapeArray()) { - XDGFShape shape = new XDGFShape(shapeSheet, this, _document); - _toplevelShapes.add(shape); - addToShapeIndex(shape); - } - } - - if (_pageContents.isSetConnects()) { - for (ConnectType connect: _pageContents.getConnects().getConnectArray()) { - - XDGFShape from = _shapes.get(connect.getFromSheet()); - XDGFShape to = _shapes.get(connect.getToSheet()); - - if (from == null) - throw new POIXMLException(this.toString() + "; Connect; Invalid from id: " + connect.getFromSheet()); - - if (to == null) - throw new POIXMLException(this.toString() + "; Connect; Invalid to id: " + connect.getToSheet()); - - _connections.add(new XDGFConnection(connect, from, to)); - } - } - } - - protected void addToShapeIndex(XDGFShape shape) { - _shapes.put(shape.getID(), shape); - - List<XDGFShape> shapes = shape.getShapes(); - if (shapes == null) - return; - - for (XDGFShape subshape: shapes) - addToShapeIndex(subshape); - } - - // - // API - // - - /** - * - * @param graphics - */ - public void draw(Graphics2D graphics) { - visitShapes(new ShapeRenderer(graphics)); - } - - - public XDGFShape getShapeById(long id) { - return _shapes.get(id); - } - - public Map<Long, XDGFShape> getShapesMap() { - return Collections.unmodifiableMap(_shapes); - } - - public Collection<XDGFShape> getShapes() { - return _shapes.values(); - } - - public List<XDGFShape> getTopLevelShapes() { - return Collections.unmodifiableList(_toplevelShapes); - } - - // get connections - public List<XDGFConnection> getConnections() { - return Collections.unmodifiableList(_connections); - } - - @Override - public String toString() { - return getPackagePart().getPartName().toString(); - } - - - /** - * Provides iteration over the shapes using the visitor pattern, and provides - * an easy way to convert shape coordinates into global coordinates - */ - public void visitShapes(ShapeVisitor visitor) { - try { - for (XDGFShape shape: _toplevelShapes) { - shape.visitShapes(visitor, new AffineTransform(), 0); - } - } catch (StopVisiting e) { - // intentionally empty - } catch (POIXMLException e) { - throw XDGFException.wrap(this, e); - } - } - + protected PageContentsType _pageContents; + + // shapes without parents + protected List<XDGFShape> _toplevelShapes = new ArrayList<XDGFShape>(); + protected Map<Long, XDGFShape> _shapes = new HashMap<Long, XDGFShape>(); + protected List<XDGFConnection> _connections = new ArrayList<XDGFConnection>(); + + public XDGFBaseContents(PackagePart part, PackageRelationship rel, XDGFDocument document) { + super(part, rel, document); + } + + @Internal + public PageContentsType getXmlObject() { + return _pageContents; + } + + + @Override + protected void onDocumentRead() { + + if (_pageContents.isSetShapes()) { + for (ShapeSheetType shapeSheet: _pageContents.getShapes().getShapeArray()) { + XDGFShape shape = new XDGFShape(shapeSheet, this, _document); + _toplevelShapes.add(shape); + addToShapeIndex(shape); + } + } + + if (_pageContents.isSetConnects()) { + for (ConnectType connect: _pageContents.getConnects().getConnectArray()) { + + XDGFShape from = _shapes.get(connect.getFromSheet()); + XDGFShape to = _shapes.get(connect.getToSheet()); + + if (from == null) + throw new POIXMLException(this.toString() + "; Connect; Invalid from id: " + connect.getFromSheet()); + + if (to == null) + throw new POIXMLException(this.toString() + "; Connect; Invalid to id: " + connect.getToSheet()); + + _connections.add(new XDGFConnection(connect, from, to)); + } + } + } + + protected void addToShapeIndex(XDGFShape shape) { + _shapes.put(shape.getID(), shape); + + List<XDGFShape> shapes = shape.getShapes(); + if (shapes == null) + return; + + for (XDGFShape subshape: shapes) + addToShapeIndex(subshape); + } + + // + // API + // + + /** + * + * @param graphics + */ + public void draw(Graphics2D graphics) { + visitShapes(new ShapeRenderer(graphics)); + } + + + public XDGFShape getShapeById(long id) { + return _shapes.get(id); + } + + public Map<Long, XDGFShape> getShapesMap() { + return Collections.unmodifiableMap(_shapes); + } + + public Collection<XDGFShape> getShapes() { + return _shapes.values(); + } + + public List<XDGFShape> getTopLevelShapes() { + return Collections.unmodifiableList(_toplevelShapes); + } + + // get connections + public List<XDGFConnection> getConnections() { + return Collections.unmodifiableList(_connections); + } + + @Override + public String toString() { + return getPackagePart().getPartName().toString(); + } + + + /** + * Provides iteration over the shapes using the visitor pattern, and provides + * an easy way to convert shape coordinates into global coordinates + */ + public void visitShapes(ShapeVisitor visitor) { + try { + for (XDGFShape shape: _toplevelShapes) { + shape.visitShapes(visitor, new AffineTransform(), 0); + } + } catch (StopVisiting e) { + // intentionally empty + } catch (POIXMLException e) { + throw XDGFException.wrap(this, e); + } + } + } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFCell.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFCell.java index ef16a545d2..171b68d4f9 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFCell.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFCell.java @@ -25,126 +25,131 @@ import org.apache.poi.util.Internal; import com.microsoft.schemas.office.visio.x2012.main.CellType; /** - * There are a lot of different cell types. Cell is really just an attribute - * of the thing that it's attached to. Will probably refactor this once I - * figure out a better way to use them - * - * The various attributes of a Cell are constrained, and are better defined - * in the XSD 1.1 visio schema + * There are a lot of different cell types. Cell is really just an attribute of + * the thing that it's attached to. Will probably refactor this once I figure + * out a better way to use them + * + * The various attributes of a Cell are constrained, and are better defined in + * the XSD 1.1 visio schema */ public class XDGFCell { - public static Boolean maybeGetBoolean(Map<String, XDGFCell> cells, String name) { - XDGFCell cell = cells.get(name); - if (cell == null) - return null; - - if (cell.getValue().equals("0")) - return false; - if (cell.getValue().equals("1")) - return true; - - throw new POIXMLException("Invalid boolean value for '" + cell.getName() + "'"); - } - - public static Double maybeGetDouble(Map<String, XDGFCell> cells, String name) { - XDGFCell cell = cells.get(name); - if (cell != null) - return parseDoubleValue(cell._cell); - return null; - } - - public static Integer maybeGetInteger(Map<String, XDGFCell> cells, String name) { - XDGFCell cell = cells.get(name); - if (cell != null) - return parseIntegerValue(cell._cell); - return null; - } - - public static String maybeGetString(Map<String, XDGFCell> cells, String name) { - XDGFCell cell = cells.get(name); - if (cell != null) { - String v = cell._cell.getV(); - if (v.equals("Themed")) - return null; - return v; - } - return null; - } - - public static Double parseDoubleValue(CellType cell) { - try { - return Double.parseDouble(cell.getV()); - } catch (NumberFormatException e) { - if (cell.getV().equals("Themed")) - return null; - throw new POIXMLException("Invalid float value for '" + cell.getN() + "': " + e); - } - } - - public static Integer parseIntegerValue(CellType cell) { - try { - return Integer.parseInt(cell.getV()); - } catch (NumberFormatException e) { - if (cell.getV().equals("Themed")) - return null; - throw new POIXMLException("Invalid integer value for '" + cell.getN() + "': " + e); - } - } - - // returns a length, converts it to inches? - public static Double parseVLength(CellType cell) { - try { - return Double.parseDouble(cell.getV()); - } catch (NumberFormatException e) { - if (cell.getV().equals("Themed")) - return null; - throw new POIXMLException("Invalid float value for '" + cell.getN() + "': " + e); - } - } - - - CellType _cell; - - public XDGFCell(CellType cell) { - _cell = cell; - } - - @Internal - CellType getXmlObject() { - return _cell; - } - - /** - * Represents the name of the ShapeSheet cell. - */ - public String getName() { - return _cell.getN(); - } - - /** - * Represents the value of the cell. - */ - public String getValue() { - return _cell.getV(); - } - - /** - * Represents the element’s formula. This attribute can contain one of the following strings: - * - ‘(some formula)’ if the formula exists locally - * - No Formula if the formula is locally deleted or blocked - * - Inh if the formula is inherited. - */ - public String getFormula() { - return _cell.getF(); - } - - /* - * Indicates that the formula evaluates to an error. The value of E is the - * current value (an error message string); the value of the V attribute is - * the last valid value. - */ - public String getError() { - return _cell.getE(); - } + public static Boolean maybeGetBoolean(Map<String, XDGFCell> cells, + String name) { + XDGFCell cell = cells.get(name); + if (cell == null) + return null; + + if (cell.getValue().equals("0")) + return false; + if (cell.getValue().equals("1")) + return true; + + throw new POIXMLException("Invalid boolean value for '" + + cell.getName() + "'"); + } + + public static Double maybeGetDouble(Map<String, XDGFCell> cells, String name) { + XDGFCell cell = cells.get(name); + if (cell != null) + return parseDoubleValue(cell._cell); + return null; + } + + public static Integer maybeGetInteger(Map<String, XDGFCell> cells, + String name) { + XDGFCell cell = cells.get(name); + if (cell != null) + return parseIntegerValue(cell._cell); + return null; + } + + public static String maybeGetString(Map<String, XDGFCell> cells, String name) { + XDGFCell cell = cells.get(name); + if (cell != null) { + String v = cell._cell.getV(); + if (v.equals("Themed")) + return null; + return v; + } + return null; + } + + public static Double parseDoubleValue(CellType cell) { + try { + return Double.parseDouble(cell.getV()); + } catch (NumberFormatException e) { + if (cell.getV().equals("Themed")) + return null; + throw new POIXMLException("Invalid float value for '" + cell.getN() + + "': " + e); + } + } + + public static Integer parseIntegerValue(CellType cell) { + try { + return Integer.parseInt(cell.getV()); + } catch (NumberFormatException e) { + if (cell.getV().equals("Themed")) + return null; + throw new POIXMLException("Invalid integer value for '" + + cell.getN() + "': " + e); + } + } + + // returns a length, converts it to inches? + public static Double parseVLength(CellType cell) { + try { + return Double.parseDouble(cell.getV()); + } catch (NumberFormatException e) { + if (cell.getV().equals("Themed")) + return null; + throw new POIXMLException("Invalid float value for '" + cell.getN() + + "': " + e); + } + } + + CellType _cell; + + public XDGFCell(CellType cell) { + _cell = cell; + } + + @Internal + CellType getXmlObject() { + return _cell; + } + + /** + * Represents the name of the ShapeSheet cell. + */ + public String getName() { + return _cell.getN(); + } + + /** + * Represents the value of the cell. + */ + public String getValue() { + return _cell.getV(); + } + + /** + * Represents the element's formula. This attribute can contain one of the + * following strings: - '(some formula)' if the formula exists locally - No + * Formula if the formula is locally deleted or blocked - Inh if the formula + * is inherited. + */ + public String getFormula() { + return _cell.getF(); + } + + /* + * Indicates that the formula evaluates to an error. The value of E is the + * current value (an error message string); the value of the V attribute is + * the last valid value. + */ + public String getError() { + return _cell.getE(); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFConnection.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFConnection.java index 6e9f1085c3..94374c55cb 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFConnection.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFConnection.java @@ -21,114 +21,116 @@ import com.microsoft.schemas.office.visio.x2012.main.ConnectType; public class XDGFConnection { - // comments on frompart/topart taken from pkgVisio - - // https://msdn.microsoft.com/en-us/library/ms367611(v=office.12).aspx - - // The following constants declared by the Microsoft Office Visio type - // library show return values for the FromPart property. - // Constant Value - // visConnectFromError -1 - // visFromNone 0 - // visLeftEdge 1 - // visCenterEdge 2 - // visRightEdge 3 - // visBottomEdge 4 - // visMiddleEdge 5 - // visTopEdge 6 - // visBeginX 7 - // visBeginY 8 - // visBegin 9 - // visEndX 10 - // visEndY 11 - // visEnd 12 - // visFromAngle 13 - // visFromPin 14 - // visControlPoint 100 + zero-based row index (for example, visControlPoint = 100 if the control point is in row 0; visControlPoint = 101 if the control point is in row 1) - - public static final int visConnectFromError = -1; - public static final int visFromNone = 0; - public static final int visLeftEdge = 1; - public static final int visCenterEdge = 2; - public static final int visRightEdge = 3; - public static final int visBottomEdge = 4; - public static final int visMiddleEdge = 5; - public static final int visTopEdge = 6; - public static final int visBeginX = 7; - public static final int visBeginY = 8; - public static final int visBegin = 9; - public static final int visEndX = 10; - public static final int visEndY = 11; - public static final int visEnd = 12; - public static final int visFromAngle = 13; - public static final int visFromPin = 14; - - - // The ToPart property identifies the part of a shape to which another - // shape is glued, such as its begin point or endpoint, one of its edges, - // or a connection point. The following constants declared by the Visio type library in member VisToParts show possible return values for the ToPart property. - // Constant Value - // visConnectToError -1 - // visToNone 0 - // visGuideX 1 - // visGuideY 2 - // visWholeShape 3 - // visGuideIntersect 4 - // visToAngle 7 - // visConnectionPoint 100 + row index of connection point - - public static final int visConnectToError = -1; - public static final int visToNone = 0; - public static final int visGuideX = 1; - public static final int visGuideY = 2; - public static final int visWholeShape = 3; - public static final int visGuideIntersect = 4; - public static final int visToAngle = 7; - - private ConnectType _connect; - private XDGFShape _from; - private XDGFShape _to; - - - public XDGFConnection(ConnectType connect, XDGFShape from, XDGFShape to) { - _connect = connect; - _from = from; - _to = to; - } - - public XDGFShape getFromShape() { - return _from; - } - - public XDGFCell getFromCell() { - return _from.getCell(_connect.getFromCell()); - } - - public String getFromCellName() { - return _connect.getFromCell(); - } - - public XDGFShape getToShape() { - return _to; - } - - public String getToCellName() { - return _connect.getToCell(); - } - - // see constants above - public Integer getFromPart() { - if (_connect.isSetFromPart()) - return _connect.getFromPart(); - else - return null; - } - - // see constants above - public Integer getToPart() { - if (_connect.isSetToPart()) - return _connect.getToPart(); - else - return null; - } + // comments on frompart/topart taken from pkgVisio + + // https://msdn.microsoft.com/en-us/library/ms367611(v=office.12).aspx + + // The following constants declared by the Microsoft Office Visio type + // library show return values for the FromPart property. + // Constant Value + // visConnectFromError -1 + // visFromNone 0 + // visLeftEdge 1 + // visCenterEdge 2 + // visRightEdge 3 + // visBottomEdge 4 + // visMiddleEdge 5 + // visTopEdge 6 + // visBeginX 7 + // visBeginY 8 + // visBegin 9 + // visEndX 10 + // visEndY 11 + // visEnd 12 + // visFromAngle 13 + // visFromPin 14 + // visControlPoint 100 + zero-based row index (for example, visControlPoint + // = 100 if the control point is in row 0; visControlPoint = 101 if the + // control point is in row 1) + + public static final int visConnectFromError = -1; + public static final int visFromNone = 0; + public static final int visLeftEdge = 1; + public static final int visCenterEdge = 2; + public static final int visRightEdge = 3; + public static final int visBottomEdge = 4; + public static final int visMiddleEdge = 5; + public static final int visTopEdge = 6; + public static final int visBeginX = 7; + public static final int visBeginY = 8; + public static final int visBegin = 9; + public static final int visEndX = 10; + public static final int visEndY = 11; + public static final int visEnd = 12; + public static final int visFromAngle = 13; + public static final int visFromPin = 14; + + // The ToPart property identifies the part of a shape to which another + // shape is glued, such as its begin point or endpoint, one of its edges, + // or a connection point. The following constants declared by the Visio type + // library in member VisToParts show possible return values for the ToPart + // property. + // Constant Value + // visConnectToError -1 + // visToNone 0 + // visGuideX 1 + // visGuideY 2 + // visWholeShape 3 + // visGuideIntersect 4 + // visToAngle 7 + // visConnectionPoint 100 + row index of connection point + + public static final int visConnectToError = -1; + public static final int visToNone = 0; + public static final int visGuideX = 1; + public static final int visGuideY = 2; + public static final int visWholeShape = 3; + public static final int visGuideIntersect = 4; + public static final int visToAngle = 7; + + private ConnectType _connect; + private XDGFShape _from; + private XDGFShape _to; + + public XDGFConnection(ConnectType connect, XDGFShape from, XDGFShape to) { + _connect = connect; + _from = from; + _to = to; + } + + public XDGFShape getFromShape() { + return _from; + } + + public XDGFCell getFromCell() { + return _from.getCell(_connect.getFromCell()); + } + + public String getFromCellName() { + return _connect.getFromCell(); + } + + public XDGFShape getToShape() { + return _to; + } + + public String getToCellName() { + return _connect.getToCell(); + } + + // see constants above + public Integer getFromPart() { + if (_connect.isSetFromPart()) + return _connect.getFromPart(); + else + return null; + } + + // see constants above + public Integer getToPart() { + if (_connect.isSetToPart()) + return _connect.getToPart(); + else + return null; + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFDocument.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFDocument.java index b38c87960b..6f1dcbe1d0 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFDocument.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFDocument.java @@ -32,85 +32,85 @@ import com.microsoft.schemas.office.visio.x2012.main.VisioDocumentType; */ public class XDGFDocument { - protected VisioDocumentType _document; - - Map<Long, XDGFStyleSheet> _styleSheets = new HashMap<>(); - - // defaults - long _defaultFillStyle = 0; - long _defaultGuideStyle = 0; - long _defaultLineStyle = 0; - long _defaultTextStyle = 0; - - - public XDGFDocument(VisioDocumentType document) { - - _document = document; - - if (!_document.isSetDocumentSettings()) - throw new POIXMLException("Document settings not found"); - - DocumentSettingsType docSettings = _document.getDocumentSettings(); - - if (docSettings.isSetDefaultFillStyle()) - _defaultFillStyle = docSettings.getDefaultFillStyle(); - - if (docSettings.isSetDefaultGuideStyle()) - _defaultGuideStyle = docSettings.getDefaultGuideStyle(); - - if (docSettings.isSetDefaultLineStyle()) - _defaultLineStyle = docSettings.getDefaultLineStyle(); - - if (docSettings.isSetDefaultTextStyle()) - _defaultTextStyle = docSettings.getDefaultTextStyle(); - - if (_document.isSetStyleSheets()) { - - for (StyleSheetType styleSheet: _document.getStyleSheets().getStyleSheetArray()) { - _styleSheets.put(styleSheet.getID(), new XDGFStyleSheet(styleSheet, this)); - } - } - } - - - @Internal - public VisioDocumentType getXmlObject() { - return _document; - } - - - public XDGFStyleSheet getStyleById(long id) { - return _styleSheets.get(id); - } - - - public XDGFStyleSheet getDefaultFillStyle() { - XDGFStyleSheet style = getStyleById(_defaultFillStyle); - if (style == null) - throw new POIXMLException("No default fill style found!"); - return style; - } - - public XDGFStyleSheet getDefaultGuideStyle() { - XDGFStyleSheet style = getStyleById(_defaultGuideStyle); - if (style == null) - throw new POIXMLException("No default guide style found!"); - return style; - } - - public XDGFStyleSheet getDefaultLineStyle() { - XDGFStyleSheet style = getStyleById(_defaultLineStyle); - if (style == null) - throw new POIXMLException("No default line style found!"); - return style; - } - - public XDGFStyleSheet getDefaultTextStyle() { - XDGFStyleSheet style = getStyleById(_defaultTextStyle); - if (style == null) - throw new POIXMLException("No default text style found!"); - return style; - } - - + protected VisioDocumentType _document; + + Map<Long, XDGFStyleSheet> _styleSheets = new HashMap<Long, XDGFStyleSheet>(); + + // defaults + long _defaultFillStyle = 0; + long _defaultGuideStyle = 0; + long _defaultLineStyle = 0; + long _defaultTextStyle = 0; + + + public XDGFDocument(VisioDocumentType document) { + + _document = document; + + if (!_document.isSetDocumentSettings()) + throw new POIXMLException("Document settings not found"); + + DocumentSettingsType docSettings = _document.getDocumentSettings(); + + if (docSettings.isSetDefaultFillStyle()) + _defaultFillStyle = docSettings.getDefaultFillStyle(); + + if (docSettings.isSetDefaultGuideStyle()) + _defaultGuideStyle = docSettings.getDefaultGuideStyle(); + + if (docSettings.isSetDefaultLineStyle()) + _defaultLineStyle = docSettings.getDefaultLineStyle(); + + if (docSettings.isSetDefaultTextStyle()) + _defaultTextStyle = docSettings.getDefaultTextStyle(); + + if (_document.isSetStyleSheets()) { + + for (StyleSheetType styleSheet: _document.getStyleSheets().getStyleSheetArray()) { + _styleSheets.put(styleSheet.getID(), new XDGFStyleSheet(styleSheet, this)); + } + } + } + + + @Internal + public VisioDocumentType getXmlObject() { + return _document; + } + + + public XDGFStyleSheet getStyleById(long id) { + return _styleSheets.get(id); + } + + + public XDGFStyleSheet getDefaultFillStyle() { + XDGFStyleSheet style = getStyleById(_defaultFillStyle); + if (style == null) + throw new POIXMLException("No default fill style found!"); + return style; + } + + public XDGFStyleSheet getDefaultGuideStyle() { + XDGFStyleSheet style = getStyleById(_defaultGuideStyle); + if (style == null) + throw new POIXMLException("No default guide style found!"); + return style; + } + + public XDGFStyleSheet getDefaultLineStyle() { + XDGFStyleSheet style = getStyleById(_defaultLineStyle); + if (style == null) + throw new POIXMLException("No default line style found!"); + return style; + } + + public XDGFStyleSheet getDefaultTextStyle() { + XDGFStyleSheet style = getStyleById(_defaultTextStyle); + if (style == null) + throw new POIXMLException("No default text style found!"); + return style; + } + + } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFFactory.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFFactory.java index 80acd09dc3..6bfa0c50c3 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFFactory.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFFactory.java @@ -30,46 +30,57 @@ import org.apache.poi.util.POILogger; public class XDGFFactory extends POIXMLFactory { - private static final POILogger logger = POILogFactory.getLogger(XDGFFactory.class); - - private XDGFDocument _document; - - public XDGFFactory(XDGFDocument document){ - _document = document; + private static final POILogger logger = POILogFactory + .getLogger(XDGFFactory.class); + + private XDGFDocument _document; + + public XDGFFactory(XDGFDocument document) { + _document = document; } - - @Override - public POIXMLDocumentPart createDocumentPart(POIXMLDocumentPart parent, - PackageRelationship rel, PackagePart part) { - POIXMLRelation descriptor = XDGFRelation.getInstance(rel.getRelationshipType()); - if(descriptor == null || descriptor.getRelationClass() == null){ - logger.log(POILogger.DEBUG, "using default POIXMLDocumentPart for " + rel.getRelationshipType()); + + @Override + public POIXMLDocumentPart createDocumentPart(POIXMLDocumentPart parent, + PackageRelationship rel, PackagePart part) { + POIXMLRelation descriptor = XDGFRelation.getInstance(rel + .getRelationshipType()); + if (descriptor == null || descriptor.getRelationClass() == null) { + logger.log(POILogger.DEBUG, "using default POIXMLDocumentPart for " + + rel.getRelationshipType()); return new POIXMLDocumentPart(part, rel); } try { - Class<? extends POIXMLDocumentPart> cls = descriptor.getRelationClass(); + Class<? extends POIXMLDocumentPart> cls = descriptor + .getRelationClass(); try { - Constructor<? extends POIXMLDocumentPart> constructor = cls.getDeclaredConstructor(POIXMLDocumentPart.class, PackagePart.class, PackageRelationship.class, XDGFDocument.class); + Constructor<? extends POIXMLDocumentPart> constructor = cls + .getDeclaredConstructor(POIXMLDocumentPart.class, + PackagePart.class, PackageRelationship.class, + XDGFDocument.class); return constructor.newInstance(parent, part, rel, _document); } catch (NoSuchMethodException e) { - Constructor<? extends POIXMLDocumentPart> constructor = cls.getDeclaredConstructor(PackagePart.class, PackageRelationship.class, XDGFDocument.class); + Constructor<? extends POIXMLDocumentPart> constructor = cls + .getDeclaredConstructor(PackagePart.class, + PackageRelationship.class, XDGFDocument.class); return constructor.newInstance(part, rel, _document); } - } catch (Exception e){ + } catch (Exception e) { throw new POIXMLException(e); } - } + } - @Override - public POIXMLDocumentPart newDocumentPart(POIXMLRelation descriptor) { + @Override + public POIXMLDocumentPart newDocumentPart(POIXMLRelation descriptor) { try { - Class<? extends POIXMLDocumentPart> cls = descriptor.getRelationClass(); - Constructor<? extends POIXMLDocumentPart> constructor = cls.getDeclaredConstructor(); + Class<? extends POIXMLDocumentPart> cls = descriptor + .getRelationClass(); + Constructor<? extends POIXMLDocumentPart> constructor = cls + .getDeclaredConstructor(); return constructor.newInstance(); - } catch (Exception e){ + } catch (Exception e) { throw new POIXMLException(e); } - } + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFMaster.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFMaster.java index 17736f87d9..b238234a7d 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFMaster.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFMaster.java @@ -26,43 +26,44 @@ import com.microsoft.schemas.office.visio.x2012.main.MasterType; */ public class XDGFMaster { - private MasterType _master; - private XDGFMasterContents _content; - XDGFSheet _pageSheet = null; - - public XDGFMaster(MasterType master, XDGFMasterContents content, XDGFDocument document) { - _master = master; - _content = content; - content.setMaster(this); - - if (master.isSetPageSheet()) - _pageSheet = new XDGFPageSheet(master.getPageSheet(), document); - } - - @Internal - MasterType getXmlObject() { - return _master; - } - - @Override - public String toString() { - return "<Master ID=\"" + getID() + "\" " + _content + ">"; - } - - public long getID() { - return _master.getID(); - } - - public String getName() { - return _master.getName(); - } - - public XDGFMasterContents getContent() { - return _content; - } - - public XDGFSheet getPageSheet() { - return _pageSheet; - } - + private MasterType _master; + private XDGFMasterContents _content; + XDGFSheet _pageSheet = null; + + public XDGFMaster(MasterType master, XDGFMasterContents content, + XDGFDocument document) { + _master = master; + _content = content; + content.setMaster(this); + + if (master.isSetPageSheet()) + _pageSheet = new XDGFPageSheet(master.getPageSheet(), document); + } + + @Internal + MasterType getXmlObject() { + return _master; + } + + @Override + public String toString() { + return "<Master ID=\"" + getID() + "\" " + _content + ">"; + } + + public long getID() { + return _master.getID(); + } + + public String getName() { + return _master.getName(); + } + + public XDGFMasterContents getContent() { + return _content; + } + + public XDGFSheet getPageSheet() { + return _pageSheet; + } + } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFMasterContents.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFMasterContents.java index ddeaa8cbc1..d8054a8b2c 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFMasterContents.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFMasterContents.java @@ -29,36 +29,39 @@ import com.microsoft.schemas.office.visio.x2012.main.MasterContentsDocument; public class XDGFMasterContents extends XDGFBaseContents { - private XDGFMaster _master; - - public XDGFMasterContents(PackagePart part, PackageRelationship rel, XDGFDocument document) { - super(part, rel, document); - } - - @Override - protected void onDocumentRead() { - - try { - - try { - _pageContents = MasterContentsDocument.Factory.parse(getPackagePart().getInputStream()).getMasterContents(); - } catch (XmlException | IOException e) { - throw new POIXMLException(e); - } - - super.onDocumentRead(); - - } catch (POIXMLException e) { - throw XDGFException.wrap(this, e); - } - } - - public XDGFMaster getMaster() { - return _master; - } - - protected void setMaster(XDGFMaster master) { - _master = master; - } + private XDGFMaster _master; + + public XDGFMasterContents(PackagePart part, PackageRelationship rel, + XDGFDocument document) { + super(part, rel, document); + } + + @Override + protected void onDocumentRead() { + + try { + + try { + _pageContents = MasterContentsDocument.Factory.parse(getPackagePart().getInputStream()).getMasterContents(); + } catch (XmlException e) { + throw new POIXMLException(e); + } catch (IOException e) { + throw new POIXMLException(e); + } + + super.onDocumentRead(); + + } catch (POIXMLException e) { + throw XDGFException.wrap(this, e); + } + } + + public XDGFMaster getMaster() { + return _master; + } + + protected void setMaster(XDGFMaster master) { + _master = master; + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFMasters.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFMasters.java index ddfca1308f..88c5386ff4 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFMasters.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFMasters.java @@ -38,62 +38,64 @@ import com.microsoft.schemas.office.visio.x2012.main.MastersType; public class XDGFMasters extends XDGFXMLDocumentPart { - MastersType _mastersObject; - - // key: id of master - Map<Long, XDGFMaster> _masters = new HashMap<>(); - - public XDGFMasters(PackagePart part, PackageRelationship rel, XDGFDocument document) { - super(part, rel, document); - } - - @Internal - MastersType getXmlObject() { - return _mastersObject; - } - - @Override - protected void onDocumentRead() { - try { - try { - _mastersObject = MastersDocument.Factory.parse(getPackagePart().getInputStream()).getMasters(); - } catch (XmlException | IOException e) { - throw new POIXMLException(e); - } - - Map<String, MasterType> masterSettings = new HashMap<>(); - for (MasterType master: _mastersObject.getMasterArray()) { - masterSettings.put(master.getRel().getId(), master); - } - - // create the masters - for (POIXMLDocumentPart part: getRelations()) { - - String relId = part.getPackageRelationship().getId(); - MasterType settings = masterSettings.get(relId); - - if (settings == null) - throw new POIXMLException("Master relationship for " + relId + " not found"); - - if (!(part instanceof XDGFMasterContents)) - throw new POIXMLException("Unexpected masters relationship for " + relId + ": " + part); - - XDGFMasterContents contents = (XDGFMasterContents)part; - contents.onDocumentRead(); - - XDGFMaster master = new XDGFMaster(settings, contents, _document); - _masters.put(master.getID(), master); - } - } catch (POIXMLException e) { - throw XDGFException.wrap(this, e); - } - } - - public Collection<XDGFMaster> getMastersList() { - return Collections.unmodifiableCollection(_masters.values()); - } - - public XDGFMaster getMasterById(long masterId) { - return _masters.get(masterId); - } + MastersType _mastersObject; + + // key: id of master + Map<Long, XDGFMaster> _masters = new HashMap<Long, XDGFMaster>(); + + public XDGFMasters(PackagePart part, PackageRelationship rel, XDGFDocument document) { + super(part, rel, document); + } + + @Internal + MastersType getXmlObject() { + return _mastersObject; + } + + @Override + protected void onDocumentRead() { + try { + try { + _mastersObject = MastersDocument.Factory.parse(getPackagePart().getInputStream()).getMasters(); + } catch (XmlException e) { + throw new POIXMLException(e); + } catch (IOException e) { + throw new POIXMLException(e); + } + + Map<String, MasterType> masterSettings = new HashMap<String, MasterType>(); + for (MasterType master: _mastersObject.getMasterArray()) { + masterSettings.put(master.getRel().getId(), master); + } + + // create the masters + for (POIXMLDocumentPart part: getRelations()) { + + String relId = part.getPackageRelationship().getId(); + MasterType settings = masterSettings.get(relId); + + if (settings == null) + throw new POIXMLException("Master relationship for " + relId + " not found"); + + if (!(part instanceof XDGFMasterContents)) + throw new POIXMLException("Unexpected masters relationship for " + relId + ": " + part); + + XDGFMasterContents contents = (XDGFMasterContents)part; + contents.onDocumentRead(); + + XDGFMaster master = new XDGFMaster(settings, contents, _document); + _masters.put(master.getID(), master); + } + } catch (POIXMLException e) { + throw XDGFException.wrap(this, e); + } + } + + public Collection<XDGFMaster> getMastersList() { + return Collections.unmodifiableCollection(_masters.values()); + } + + public XDGFMaster getMasterById(long masterId) { + return _masters.get(masterId); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFPage.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFPage.java index 762c9631a2..3369187671 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFPage.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFPage.java @@ -31,83 +31,82 @@ import com.microsoft.schemas.office.visio.x2012.main.PageType; */ public class XDGFPage { - PageType _page; - XDGFPageContents _content; - XDGFPages _pages; - XDGFSheet _pageSheet = null; - - public XDGFPage(PageType page, XDGFPageContents content, XDGFDocument document, XDGFPages pages) { - _page = page; - _content = content; - _pages = pages; - content.setPage(this); - - if (page.isSetPageSheet()) - _pageSheet = new XDGFPageSheet(page.getPageSheet(), document); - } - - @Internal - PageType getXmlObject() { - return _page; - } - - public long getID() { - return _page.getID(); - } - - public String getName() { - return _page.getName(); - } - - public XDGFPageContents getContent() { - return _content; - } - - public XDGFSheet getPageSheet() { - return _pageSheet; - } - - public long getPageNumber() { - return _pages.getPageList().indexOf(this) + 1; - } - - // height/width of page - public Dimension2dDouble getPageSize() { - XDGFCell w = _pageSheet.getCell("PageWidth"); - XDGFCell h = _pageSheet.getCell("PageHeight"); - - if (w == null || h == null) - throw new POIXMLException("Cannot determine page size"); - - return new Dimension2dDouble(Double.parseDouble(w.getValue()), - Double.parseDouble(h.getValue())); - } - - // origin of coordinate system - public Point2D.Double getPageOffset() { - XDGFCell xoffcell = _pageSheet.getCell("XRulerOrigin"); - XDGFCell yoffcell = _pageSheet.getCell("YRulerOrigin"); - - double xoffset = 0; - double yoffset = 0; - - if (xoffcell != null) - xoffset = Double.parseDouble(xoffcell.getValue()); - - if (xoffcell != null) - yoffset = Double.parseDouble(yoffcell.getValue()); - - return new Point2D.Double(xoffset, yoffset); - } - - // bounding box of page - public Rectangle2D getBoundingBox() { - Dimension2dDouble sz = getPageSize(); - Point2D.Double offset = getPageOffset(); - - return new Rectangle2D.Double(-offset.getX(), - -offset.getY(), - sz.getWidth(), - sz.getHeight()); - } + PageType _page; + XDGFPageContents _content; + XDGFPages _pages; + XDGFSheet _pageSheet = null; + + public XDGFPage(PageType page, XDGFPageContents content, + XDGFDocument document, XDGFPages pages) { + _page = page; + _content = content; + _pages = pages; + content.setPage(this); + + if (page.isSetPageSheet()) + _pageSheet = new XDGFPageSheet(page.getPageSheet(), document); + } + + @Internal + PageType getXmlObject() { + return _page; + } + + public long getID() { + return _page.getID(); + } + + public String getName() { + return _page.getName(); + } + + public XDGFPageContents getContent() { + return _content; + } + + public XDGFSheet getPageSheet() { + return _pageSheet; + } + + public long getPageNumber() { + return _pages.getPageList().indexOf(this) + 1; + } + + // height/width of page + public Dimension2dDouble getPageSize() { + XDGFCell w = _pageSheet.getCell("PageWidth"); + XDGFCell h = _pageSheet.getCell("PageHeight"); + + if (w == null || h == null) + throw new POIXMLException("Cannot determine page size"); + + return new Dimension2dDouble(Double.parseDouble(w.getValue()), + Double.parseDouble(h.getValue())); + } + + // origin of coordinate system + public Point2D.Double getPageOffset() { + XDGFCell xoffcell = _pageSheet.getCell("XRulerOrigin"); + XDGFCell yoffcell = _pageSheet.getCell("YRulerOrigin"); + + double xoffset = 0; + double yoffset = 0; + + if (xoffcell != null) + xoffset = Double.parseDouble(xoffcell.getValue()); + + if (xoffcell != null) + yoffset = Double.parseDouble(yoffcell.getValue()); + + return new Point2D.Double(xoffset, yoffset); + } + + // bounding box of page + public Rectangle2D getBoundingBox() { + Dimension2dDouble sz = getPageSize(); + Point2D.Double offset = getPageOffset(); + + return new Rectangle2D.Double(-offset.getX(), -offset.getY(), + sz.getWidth(), sz.getHeight()); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFPageContents.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFPageContents.java index 392ec48629..9bcc60f1d7 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFPageContents.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFPageContents.java @@ -32,52 +32,54 @@ import com.microsoft.schemas.office.visio.x2012.main.PageContentsDocument; public class XDGFPageContents extends XDGFBaseContents { - Map<Long, XDGFMaster> _masters = new HashMap<>(); - XDGFPage _page; - - public XDGFPageContents(PackagePart part, PackageRelationship rel, XDGFDocument document) { - super(part, rel, document); - } - - @Override - protected void onDocumentRead() { - try { - try { - _pageContents = PageContentsDocument.Factory.parse(getPackagePart().getInputStream()).getPageContents(); - } catch (XmlException | IOException e) { - throw new POIXMLException(e); - } - - for (POIXMLDocumentPart part: getRelations()) { - if (!(part instanceof XDGFMasterContents)) - continue; - //throw new POIXMLException("Unexpected page relation: " + part); - - XDGFMaster master = ((XDGFMasterContents)part).getMaster(); - _masters.put(master.getID(), master); - } - - super.onDocumentRead(); - - for (XDGFShape shape: _shapes.values()) { - if (shape.isTopmost()) - shape.setupMaster(this, null); - } - - } catch (POIXMLException e) { - throw XDGFException.wrap(this, e); - } - } - - public XDGFPage getPage() { - return _page; - } - - protected void setPage(XDGFPage page) { - _page = page; - } - - public XDGFMaster getMasterById(long id) { - return _masters.get(id); - } + Map<Long, XDGFMaster> _masters = new HashMap<Long, XDGFMaster>(); + XDGFPage _page; + + public XDGFPageContents(PackagePart part, PackageRelationship rel, XDGFDocument document) { + super(part, rel, document); + } + + @Override + protected void onDocumentRead() { + try { + try { + _pageContents = PageContentsDocument.Factory.parse(getPackagePart().getInputStream()).getPageContents(); + } catch (XmlException e) { + throw new POIXMLException(e); + } catch (IOException e) { + throw new POIXMLException(e); + } + + for (POIXMLDocumentPart part: getRelations()) { + if (!(part instanceof XDGFMasterContents)) + continue; + //throw new POIXMLException("Unexpected page relation: " + part); + + XDGFMaster master = ((XDGFMasterContents)part).getMaster(); + _masters.put(master.getID(), master); + } + + super.onDocumentRead(); + + for (XDGFShape shape: _shapes.values()) { + if (shape.isTopmost()) + shape.setupMaster(this, null); + } + + } catch (POIXMLException e) { + throw XDGFException.wrap(this, e); + } + } + + public XDGFPage getPage() { + return _page; + } + + protected void setPage(XDGFPage page) { + _page = page; + } + + public XDGFMaster getMasterById(long id) { + return _masters.get(id); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFPageSheet.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFPageSheet.java index 2bf8324fca..1d27969fed 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFPageSheet.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFPageSheet.java @@ -21,16 +21,16 @@ import com.microsoft.schemas.office.visio.x2012.main.PageSheetType; public class XDGFPageSheet extends XDGFSheet { - PageSheetType _pageSheet; - - public XDGFPageSheet(PageSheetType sheet, XDGFDocument document) { - super(sheet, document); - _pageSheet = sheet; - } - - @Override - PageSheetType getXmlObject() { - return _pageSheet; - } + PageSheetType _pageSheet; + + public XDGFPageSheet(PageSheetType sheet, XDGFDocument document) { + super(sheet, document); + _pageSheet = sheet; + } + + @Override + PageSheetType getXmlObject() { + return _pageSheet; + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFPages.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFPages.java index c8447f57a7..16ab96157a 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFPages.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFPages.java @@ -40,56 +40,58 @@ import com.microsoft.schemas.office.visio.x2012.main.PagesType; */ public class XDGFPages extends XDGFXMLDocumentPart { - PagesType _pagesObject; - - // ordered by page number - List<XDGFPage> _pages = new ArrayList<>(); - - public XDGFPages(PackagePart part, PackageRelationship rel, XDGFDocument document) { - super(part, rel, document); - } - - @Internal - PagesType getXmlObject() { - return _pagesObject; - } - - @Override - protected void onDocumentRead() { - try { - try { - _pagesObject = PagesDocument.Factory.parse(getPackagePart().getInputStream()).getPages(); - } catch (XmlException | IOException e) { - throw new POIXMLException(e); - } - - // this iteration is ordered by page number - for (PageType pageSettings: _pagesObject.getPageArray()) { - - String relId = pageSettings.getRel().getId(); - - POIXMLDocumentPart pageContentsPart = getRelationById(relId); - if (pageContentsPart == null) - throw new POIXMLException("PageSettings relationship for " + relId + " not found"); - - if (!(pageContentsPart instanceof XDGFPageContents)) - throw new POIXMLException("Unexpected pages relationship for " + relId + ": " + pageContentsPart); - - XDGFPageContents contents = (XDGFPageContents)pageContentsPart; - XDGFPage page = new XDGFPage(pageSettings, contents, _document, this); - - contents.onDocumentRead(); - - _pages.add(page); - } - - } catch (POIXMLException e) { - throw XDGFException.wrap(this, e); - } - } - - // ordered by page number - public List<XDGFPage> getPageList() { - return Collections.unmodifiableList(_pages); - } + PagesType _pagesObject; + + // ordered by page number + List<XDGFPage> _pages = new ArrayList<XDGFPage>(); + + public XDGFPages(PackagePart part, PackageRelationship rel, XDGFDocument document) { + super(part, rel, document); + } + + @Internal + PagesType getXmlObject() { + return _pagesObject; + } + + @Override + protected void onDocumentRead() { + try { + try { + _pagesObject = PagesDocument.Factory.parse(getPackagePart().getInputStream()).getPages(); + } catch (XmlException e) { + throw new POIXMLException(e); + } catch (IOException e) { + throw new POIXMLException(e); + } + + // this iteration is ordered by page number + for (PageType pageSettings: _pagesObject.getPageArray()) { + + String relId = pageSettings.getRel().getId(); + + POIXMLDocumentPart pageContentsPart = getRelationById(relId); + if (pageContentsPart == null) + throw new POIXMLException("PageSettings relationship for " + relId + " not found"); + + if (!(pageContentsPart instanceof XDGFPageContents)) + throw new POIXMLException("Unexpected pages relationship for " + relId + ": " + pageContentsPart); + + XDGFPageContents contents = (XDGFPageContents)pageContentsPart; + XDGFPage page = new XDGFPage(pageSettings, contents, _document, this); + + contents.onDocumentRead(); + + _pages.add(page); + } + + } catch (POIXMLException e) { + throw XDGFException.wrap(this, e); + } + } + + // ordered by page number + public List<XDGFPage> getPageList() { + return Collections.unmodifiableList(_pages); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFRelation.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFRelation.java index 1090377fb9..ef3edefdbc 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFRelation.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFRelation.java @@ -25,8 +25,8 @@ import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; import org.apache.poi.xdgf.xml.XDGFXMLDocumentPart; public class XDGFRelation extends POIXMLRelation { - - /** + + /** * A map to lookup POIXMLRelation by its relation type */ protected static final Map<String, XDGFRelation> _table = new HashMap<String, XDGFRelation>(); @@ -34,62 +34,50 @@ public class XDGFRelation extends POIXMLRelation { public static final XDGFRelation DOCUMENT = new XDGFRelation( "application/vnd.ms-visio.drawing.main+xml", "http://schemas.microsoft.com/visio/2010/relationships/document", - "/visio/document.xml", - null - ); - + "/visio/document.xml", null); + public static final XDGFRelation MASTERS = new XDGFRelation( "application/vnd.ms-visio.masters+xml", "http://schemas.microsoft.com/visio/2010/relationships/masters", - "/visio/masters/masters.xml", - XDGFMasters.class - ); - + "/visio/masters/masters.xml", XDGFMasters.class); + public static final XDGFRelation MASTER = new XDGFRelation( "application/vnd.ms-visio.master+xml", "http://schemas.microsoft.com/visio/2010/relationships/master", - "/visio/masters/master#.xml", - XDGFMasterContents.class - ); - - public static final XDGFRelation IMAGES = new XDGFRelation( - null, - PackageRelationshipTypes.IMAGE_PART, - null, - null // XSSFPictureData.class - ); - + "/visio/masters/master#.xml", XDGFMasterContents.class); + + public static final XDGFRelation IMAGES = new XDGFRelation(null, + PackageRelationshipTypes.IMAGE_PART, null, null // XSSFPictureData.class + ); + public static final XDGFRelation PAGES = new XDGFRelation( "application/vnd.ms-visio.pages+xml", "http://schemas.microsoft.com/visio/2010/relationships/pages", - "/visio/pages/pages.xml", - XDGFPages.class - ); - + "/visio/pages/pages.xml", XDGFPages.class); + public static final XDGFRelation PAGE = new XDGFRelation( "application/vnd.ms-visio.page+xml", "http://schemas.microsoft.com/visio/2010/relationships/page", - "/visio/pages/page#.xml", - XDGFPageContents.class - ); - + "/visio/pages/page#.xml", XDGFPageContents.class); + public static final XDGFRelation WINDOW = new XDGFRelation( "application/vnd.ms-visio.windows+xml", "http://schemas.microsoft.com/visio/2010/relationships/windows", - "/visio/windows.xml", - null - ); - - private XDGFRelation(String type, String rel, String defaultName, Class<? extends XDGFXMLDocumentPart> cls) { + "/visio/windows.xml", null); + + private XDGFRelation(String type, String rel, String defaultName, + Class<? extends XDGFXMLDocumentPart> cls) { super(type, rel, defaultName, cls); - if (cls != null && !_table.containsKey(rel)) _table.put(rel, this); + if (cls != null && !_table.containsKey(rel)) + _table.put(rel, this); } /** * Get POIXMLRelation by relation type * - * @param rel relation type, for example, + * @param rel + * relation type, for example, * <code>http://schemas.openxmlformats.org/officeDocument/2006/relationships/image</code> * @return registered POIXMLRelation or null if not found */ diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFShape.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFShape.java index 493f049428..fb85dcc349 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFShape.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFShape.java @@ -41,903 +41,906 @@ import com.microsoft.schemas.office.visio.x2012.main.ShapeSheetType; import com.microsoft.schemas.office.visio.x2012.main.TextType; /** - * A shape is a collection of Geometry Visualization, Format, Text, Images, - * and Shape Data in a Drawing Page. + * A shape is a collection of Geometry Visualization, Format, Text, Images, and + * Shape Data in a Drawing Page. */ public class XDGFShape extends XDGFSheet { - XDGFBaseContents _parentPage; - XDGFShape _parent; // only non-null if a subshape - - XDGFMaster _master = null; - XDGFShape _masterShape = null; - - XDGFText _text = null; - - // subshapes if they exist - List<XDGFShape> _shapes = null; - - // properties specific to shapes - - // center of rotation relative to origin of parent - Double _pinX = null; - Double _pinY = null; - - Double _width = null; - Double _height = null; - - // center of rotation relative to self - Double _locPinX = null; - Double _locPinY = null; - - // start x coordinate, relative to parent - // -> one dimensional shapes only - Double _beginX = null; - Double _beginY = null; - - // end x coordinate, relative to parent - // -> one dimensional shapes only - Double _endX = null; - Double _endY = null; - - Double _angle = null; - Double _rotationXAngle = null; - Double _rotationYAngle = null; - Double _rotationZAngle = null; - - // end x coordinate, relative to parent - Boolean _flipX = null; - Boolean _flipY = null; - - // center of text relative to this shape - Double _txtPinX = null; - Double _txtPinY = null; - - // center of text relative to text block - Double _txtLocPinX = null; - Double _txtLocPinY = null; - - Double _txtAngle = null; - - Double _txtWidth = null; - Double _txtHeight = null; - - public XDGFShape(ShapeSheetType shapeSheet, XDGFBaseContents parentPage, XDGFDocument document) { - this(null, shapeSheet, parentPage, document); - } - - public XDGFShape(XDGFShape parent, ShapeSheetType shapeSheet, XDGFBaseContents parentPage, XDGFDocument document) { - - super(shapeSheet, document); - - _parent = parent; - _parentPage = parentPage; - - TextType text = shapeSheet.getText(); - if (text != null) - _text = new XDGFText(text, this); - - if (shapeSheet.isSetShapes()) { - _shapes = new ArrayList<XDGFShape>(); - for (ShapeSheetType shape: shapeSheet.getShapes().getShapeArray()) - _shapes.add(new XDGFShape(this, shape, parentPage, document)); - } - - readProperties(); - } - - @Override - public String toString() { - if (_parentPage instanceof XDGFMasterContents) - return _parentPage + ": <Shape ID=\"" + getID() + "\">"; - else - return "<Shape ID=\"" + getID() + "\">"; - } - - protected void readProperties() { - - _pinX = XDGFCell.maybeGetDouble(_cells, "PinX"); - _pinY = XDGFCell.maybeGetDouble(_cells, "PinY"); - _width = XDGFCell.maybeGetDouble(_cells, "Width"); - _height = XDGFCell.maybeGetDouble(_cells, "Height"); - _locPinX = XDGFCell.maybeGetDouble(_cells, "LocPinX"); - _locPinY = XDGFCell.maybeGetDouble(_cells, "LocPinY"); - _beginX = XDGFCell.maybeGetDouble(_cells, "BeginX"); - _beginY = XDGFCell.maybeGetDouble(_cells, "BeginY"); - _endX = XDGFCell.maybeGetDouble(_cells, "EndX"); - _endY = XDGFCell.maybeGetDouble(_cells, "EndY"); - - _angle = XDGFCell.maybeGetDouble(_cells, "Angle"); - _rotationXAngle = XDGFCell.maybeGetDouble(_cells, "RotationXAngle"); - _rotationYAngle = XDGFCell.maybeGetDouble(_cells, "RotationYAngle"); - _rotationZAngle = XDGFCell.maybeGetDouble(_cells, "RotationZAngle"); - - _flipX = XDGFCell.maybeGetBoolean(_cells, "FlipX"); - _flipY = XDGFCell.maybeGetBoolean(_cells, "FlipY"); - - _txtPinX = XDGFCell.maybeGetDouble(_cells, "TxtPinX"); - _txtPinY = XDGFCell.maybeGetDouble(_cells, "TxtPinY"); - _txtLocPinX = XDGFCell.maybeGetDouble(_cells, "TxtLocPinX"); - _txtLocPinY = XDGFCell.maybeGetDouble(_cells, "TxtLocPinY"); - _txtWidth = XDGFCell.maybeGetDouble(_cells, "TxtWidth"); - _txtHeight = XDGFCell.maybeGetDouble(_cells, "TxtHeight"); - - _txtAngle = XDGFCell.maybeGetDouble(_cells, "TxtAngle"); - } - - /** - * Setup top level shapes - * - * Shapes that have a 'Master' attribute refer to a specific master in - * the page, whereas shapes with a 'MasterShape' attribute refer to a - * subshape of a Master. - * - * - */ - protected void setupMaster(XDGFPageContents pageContents, XDGFMasterContents master) { - - ShapeSheetType obj = getXmlObject(); - - if (obj.isSetMaster()) { - _master = pageContents.getMasterById(obj.getMaster()); - if (_master == null) - throw XDGFException.error("refers to non-existant master " + obj.getMaster(), - this); - - /* - * If a master has one top-level shape, a shape that inherits from - * that master inherits the descendant elements of that master - * shape. If a master has more than one master shape, a shape that - * inherits from that master inherits those master shapes as - * subshapes. - */ - - Collection<XDGFShape> masterShapes = _master.getContent().getTopLevelShapes(); - - switch (masterShapes.size()) { - case 0: - throw XDGFException.error("Could not retrieve master shape from " + _master, this); - case 1: - _masterShape = masterShapes.iterator().next(); - break; - default: - break; - } - - } else if (obj.isSetMasterShape()) { - _masterShape = master.getShapeById(obj.getMasterShape()); - if (_masterShape == null) - throw XDGFException.error("refers to non-existant master shape " + obj.getMasterShape(), - this); - - } - - setupSectionMasters(); - - if (_shapes != null) { - for (XDGFShape shape: _shapes) { - shape.setupMaster(pageContents, - _master == null ? master : _master.getContent()); - } - } - } - - protected void setupSectionMasters() { - - if (_masterShape == null) - return; - - try { - for (Entry<String, XDGFSection> section: _sections.entrySet()) { - XDGFSection master = _masterShape.getSection(section.getKey()); - if (master != null) - section.getValue().setupMaster(master); - } - - for (Entry<Long, GeometrySection> section: _geometry.entrySet()) { - GeometrySection master = _masterShape.getGeometryByIdx(section.getKey()); - if (master != null) - section.getValue().setupMaster(master); - } - } catch (POIXMLException e) { - throw XDGFException.wrap(this.toString(), e); - } - } - - @Internal - public ShapeSheetType getXmlObject() { - return (ShapeSheetType)_sheet; - } - - public long getID() { - return getXmlObject().getID(); - } - - public String getType() { - return getXmlObject().getType(); - } - - public String getTextAsString() { - XDGFText text = getText(); - if (text == null) - return ""; - - return text.getTextContent(); - } - - public boolean hasText() { - return _text != null || (_masterShape != null && _masterShape._text != null); - } - - @Override - public XDGFCell getCell(String cellName) { - XDGFCell _cell = super.getCell(cellName); - - // if not found, ask the master - if (_cell == null && _masterShape != null) { - _cell = _masterShape.getCell(cellName); - } - - return _cell; - } - - public GeometrySection getGeometryByIdx(long idx) { - return _geometry.get(idx); - } - - // only available if this is a shape group - // -> May be null - public List<XDGFShape> getShapes() { - return _shapes; - } - - // unique to this shape on the page? - public String getName() { - String name = getXmlObject().getName(); - if (name == null) - return ""; - return name; - } - - // unique to this shape on the page? - public String getShapeType() { - String type = getXmlObject().getType(); - if (type == null) - return ""; - return type; - } - - // name of the symbol that this was derived from - public String getSymbolName() { - - if (_master == null) - return ""; - - String name = _master.getName(); - if (name == null) - return ""; - - return name; - } - - public XDGFShape getMasterShape() { - return _masterShape; - } - - // returns the parent shape of this shape, if its in a subshape - public XDGFShape getParentShape() { - return _parent; - } - - public XDGFShape getTopmostParentShape() { - XDGFShape top = null; - if (_parent != null) { - top = _parent.getTopmostParentShape(); - if (top == null) - top = _parent; - } - - return top; - } - - public boolean hasMaster() { - return _master != null; - } - - public boolean hasMasterShape() { - return _masterShape != null; - } - - public boolean hasParent() { - return _parent != null; - } - - public boolean hasShapes() { - return _shapes != null; - } - - public boolean isTopmost() { - return _parent == null; - } - - public boolean isShape1D() { - return getBeginX() != null; - } - - public boolean isDeleted() { - return getXmlObject().isSetDel() ? getXmlObject().getDel() : false; - } - - public XDGFText getText() { - if (_text == null && _masterShape != null) - return _masterShape.getText(); - - return _text; - } - - public Double getPinX() { - if (_pinX == null && _masterShape != null) - return _masterShape.getPinX(); - - if (_pinX == null) - throw XDGFException.error("PinX not set!", this); - - return _pinX; - } - - public Double getPinY() { - if (_pinY == null && _masterShape != null) - return _masterShape.getPinY(); - - if (_pinY == null) - throw XDGFException.error("PinY not specified!", this); - - return _pinY; - } - - public Double getWidth() { - if (_width == null && _masterShape != null) - return _masterShape.getWidth(); - - if (_width == null) - throw XDGFException.error("Width not specified!", this); - - return _width; - } - - public Double getHeight() { - if (_height == null && _masterShape != null) - return _masterShape.getHeight(); - - if (_height == null) - throw XDGFException.error("Height not specified!", this); - - return _height; - } - - public Double getLocPinX() { - if (_locPinX == null && _masterShape != null) - return _masterShape.getLocPinX(); - - if (_locPinX == null) - throw XDGFException.error("LocPinX not specified!", this); - - return _locPinX; - } - - public Double getLocPinY() { - if (_locPinY == null && _masterShape != null) - return _masterShape.getLocPinY(); - - if (_locPinY == null) - throw XDGFException.error("LocPinY not specified!", this); - - return _locPinY; - } - - public Double getBeginX() { - if (_beginX == null && _masterShape != null) - return _masterShape.getBeginX(); - - return _beginX; - } - - public Double getBeginY() { - if (_beginY == null && _masterShape != null) - return _masterShape.getBeginY(); - - return _beginY; - } - - public Double getEndX() { - if (_endX == null && _masterShape != null) - return _masterShape.getEndX(); - - return _endX; - } - - public Double getEndY() { - if (_endY == null && _masterShape != null) - return _masterShape.getEndY(); - - return _endY; - } - - public Double getAngle() { - if (_angle == null && _masterShape != null) - return _masterShape.getAngle(); - - return _angle; - } - - public Boolean getFlipX() { - if (_flipX == null && _masterShape != null) - return _masterShape.getFlipX(); - - return _flipX; - } - - public Boolean getFlipY() { - if (_flipY == null && _masterShape != null) - return _masterShape.getFlipY(); - - return _flipY; - } - + XDGFBaseContents _parentPage; + XDGFShape _parent; // only non-null if a subshape + + XDGFMaster _master = null; + XDGFShape _masterShape = null; + + XDGFText _text = null; + + // subshapes if they exist + List<XDGFShape> _shapes = null; + + // properties specific to shapes + + // center of rotation relative to origin of parent + Double _pinX = null; + Double _pinY = null; + + Double _width = null; + Double _height = null; + + // center of rotation relative to self + Double _locPinX = null; + Double _locPinY = null; + + // start x coordinate, relative to parent + // -> one dimensional shapes only + Double _beginX = null; + Double _beginY = null; + + // end x coordinate, relative to parent + // -> one dimensional shapes only + Double _endX = null; + Double _endY = null; + + Double _angle = null; + Double _rotationXAngle = null; + Double _rotationYAngle = null; + Double _rotationZAngle = null; + + // end x coordinate, relative to parent + Boolean _flipX = null; + Boolean _flipY = null; + + // center of text relative to this shape + Double _txtPinX = null; + Double _txtPinY = null; + + // center of text relative to text block + Double _txtLocPinX = null; + Double _txtLocPinY = null; + + Double _txtAngle = null; + + Double _txtWidth = null; + Double _txtHeight = null; + + public XDGFShape(ShapeSheetType shapeSheet, XDGFBaseContents parentPage, + XDGFDocument document) { + this(null, shapeSheet, parentPage, document); + } + + public XDGFShape(XDGFShape parent, ShapeSheetType shapeSheet, + XDGFBaseContents parentPage, XDGFDocument document) { + + super(shapeSheet, document); + + _parent = parent; + _parentPage = parentPage; + + TextType text = shapeSheet.getText(); + if (text != null) + _text = new XDGFText(text, this); + + if (shapeSheet.isSetShapes()) { + _shapes = new ArrayList<XDGFShape>(); + for (ShapeSheetType shape : shapeSheet.getShapes().getShapeArray()) + _shapes.add(new XDGFShape(this, shape, parentPage, document)); + } + + readProperties(); + } + + @Override + public String toString() { + if (_parentPage instanceof XDGFMasterContents) + return _parentPage + ": <Shape ID=\"" + getID() + "\">"; + else + return "<Shape ID=\"" + getID() + "\">"; + } + + protected void readProperties() { + + _pinX = XDGFCell.maybeGetDouble(_cells, "PinX"); + _pinY = XDGFCell.maybeGetDouble(_cells, "PinY"); + _width = XDGFCell.maybeGetDouble(_cells, "Width"); + _height = XDGFCell.maybeGetDouble(_cells, "Height"); + _locPinX = XDGFCell.maybeGetDouble(_cells, "LocPinX"); + _locPinY = XDGFCell.maybeGetDouble(_cells, "LocPinY"); + _beginX = XDGFCell.maybeGetDouble(_cells, "BeginX"); + _beginY = XDGFCell.maybeGetDouble(_cells, "BeginY"); + _endX = XDGFCell.maybeGetDouble(_cells, "EndX"); + _endY = XDGFCell.maybeGetDouble(_cells, "EndY"); + + _angle = XDGFCell.maybeGetDouble(_cells, "Angle"); + _rotationXAngle = XDGFCell.maybeGetDouble(_cells, "RotationXAngle"); + _rotationYAngle = XDGFCell.maybeGetDouble(_cells, "RotationYAngle"); + _rotationZAngle = XDGFCell.maybeGetDouble(_cells, "RotationZAngle"); + + _flipX = XDGFCell.maybeGetBoolean(_cells, "FlipX"); + _flipY = XDGFCell.maybeGetBoolean(_cells, "FlipY"); + + _txtPinX = XDGFCell.maybeGetDouble(_cells, "TxtPinX"); + _txtPinY = XDGFCell.maybeGetDouble(_cells, "TxtPinY"); + _txtLocPinX = XDGFCell.maybeGetDouble(_cells, "TxtLocPinX"); + _txtLocPinY = XDGFCell.maybeGetDouble(_cells, "TxtLocPinY"); + _txtWidth = XDGFCell.maybeGetDouble(_cells, "TxtWidth"); + _txtHeight = XDGFCell.maybeGetDouble(_cells, "TxtHeight"); + + _txtAngle = XDGFCell.maybeGetDouble(_cells, "TxtAngle"); + } + + /** + * Setup top level shapes + * + * Shapes that have a 'Master' attribute refer to a specific master in the + * page, whereas shapes with a 'MasterShape' attribute refer to a subshape + * of a Master. + * + * + */ + protected void setupMaster(XDGFPageContents pageContents, + XDGFMasterContents master) { + + ShapeSheetType obj = getXmlObject(); + + if (obj.isSetMaster()) { + _master = pageContents.getMasterById(obj.getMaster()); + if (_master == null) + throw XDGFException.error("refers to non-existant master " + + obj.getMaster(), this); + + /* + * If a master has one top-level shape, a shape that inherits from + * that master inherits the descendant elements of that master + * shape. If a master has more than one master shape, a shape that + * inherits from that master inherits those master shapes as + * subshapes. + */ + + Collection<XDGFShape> masterShapes = _master.getContent() + .getTopLevelShapes(); + + switch (masterShapes.size()) { + case 0: + throw XDGFException + .error("Could not retrieve master shape from " + + _master, this); + case 1: + _masterShape = masterShapes.iterator().next(); + break; + default: + break; + } + + } else if (obj.isSetMasterShape()) { + _masterShape = master.getShapeById(obj.getMasterShape()); + if (_masterShape == null) + throw XDGFException.error( + "refers to non-existant master shape " + + obj.getMasterShape(), this); + + } + + setupSectionMasters(); + + if (_shapes != null) { + for (XDGFShape shape : _shapes) { + shape.setupMaster(pageContents, _master == null ? master + : _master.getContent()); + } + } + } + + protected void setupSectionMasters() { + + if (_masterShape == null) + return; + + try { + for (Entry<String, XDGFSection> section : _sections.entrySet()) { + XDGFSection master = _masterShape.getSection(section.getKey()); + if (master != null) + section.getValue().setupMaster(master); + } + + for (Entry<Long, GeometrySection> section : _geometry.entrySet()) { + GeometrySection master = _masterShape.getGeometryByIdx(section + .getKey()); + if (master != null) + section.getValue().setupMaster(master); + } + } catch (POIXMLException e) { + throw XDGFException.wrap(this.toString(), e); + } + } + + @Override + @Internal + public ShapeSheetType getXmlObject() { + return (ShapeSheetType) _sheet; + } + + public long getID() { + return getXmlObject().getID(); + } + + public String getType() { + return getXmlObject().getType(); + } + + public String getTextAsString() { + XDGFText text = getText(); + if (text == null) + return ""; + + return text.getTextContent(); + } + + public boolean hasText() { + return _text != null + || (_masterShape != null && _masterShape._text != null); + } + + @Override + public XDGFCell getCell(String cellName) { + XDGFCell _cell = super.getCell(cellName); + + // if not found, ask the master + if (_cell == null && _masterShape != null) { + _cell = _masterShape.getCell(cellName); + } + + return _cell; + } + + public GeometrySection getGeometryByIdx(long idx) { + return _geometry.get(idx); + } + + // only available if this is a shape group + // -> May be null + public List<XDGFShape> getShapes() { + return _shapes; + } + + // unique to this shape on the page? + public String getName() { + String name = getXmlObject().getName(); + if (name == null) + return ""; + return name; + } + + // unique to this shape on the page? + public String getShapeType() { + String type = getXmlObject().getType(); + if (type == null) + return ""; + return type; + } + + // name of the symbol that this was derived from + public String getSymbolName() { + + if (_master == null) + return ""; + + String name = _master.getName(); + if (name == null) + return ""; + + return name; + } + + public XDGFShape getMasterShape() { + return _masterShape; + } + + // returns the parent shape of this shape, if its in a subshape + public XDGFShape getParentShape() { + return _parent; + } + + public XDGFShape getTopmostParentShape() { + XDGFShape top = null; + if (_parent != null) { + top = _parent.getTopmostParentShape(); + if (top == null) + top = _parent; + } + + return top; + } + + public boolean hasMaster() { + return _master != null; + } + + public boolean hasMasterShape() { + return _masterShape != null; + } + + public boolean hasParent() { + return _parent != null; + } + + public boolean hasShapes() { + return _shapes != null; + } + + public boolean isTopmost() { + return _parent == null; + } + + public boolean isShape1D() { + return getBeginX() != null; + } + + public boolean isDeleted() { + return getXmlObject().isSetDel() ? getXmlObject().getDel() : false; + } + + public XDGFText getText() { + if (_text == null && _masterShape != null) + return _masterShape.getText(); + + return _text; + } + + public Double getPinX() { + if (_pinX == null && _masterShape != null) + return _masterShape.getPinX(); + + if (_pinX == null) + throw XDGFException.error("PinX not set!", this); + + return _pinX; + } + + public Double getPinY() { + if (_pinY == null && _masterShape != null) + return _masterShape.getPinY(); + + if (_pinY == null) + throw XDGFException.error("PinY not specified!", this); + + return _pinY; + } + + public Double getWidth() { + if (_width == null && _masterShape != null) + return _masterShape.getWidth(); + + if (_width == null) + throw XDGFException.error("Width not specified!", this); + + return _width; + } + + public Double getHeight() { + if (_height == null && _masterShape != null) + return _masterShape.getHeight(); + + if (_height == null) + throw XDGFException.error("Height not specified!", this); + + return _height; + } + + public Double getLocPinX() { + if (_locPinX == null && _masterShape != null) + return _masterShape.getLocPinX(); + + if (_locPinX == null) + throw XDGFException.error("LocPinX not specified!", this); + + return _locPinX; + } + + public Double getLocPinY() { + if (_locPinY == null && _masterShape != null) + return _masterShape.getLocPinY(); + + if (_locPinY == null) + throw XDGFException.error("LocPinY not specified!", this); + + return _locPinY; + } + + public Double getBeginX() { + if (_beginX == null && _masterShape != null) + return _masterShape.getBeginX(); + + return _beginX; + } + + public Double getBeginY() { + if (_beginY == null && _masterShape != null) + return _masterShape.getBeginY(); + + return _beginY; + } + + public Double getEndX() { + if (_endX == null && _masterShape != null) + return _masterShape.getEndX(); + + return _endX; + } + + public Double getEndY() { + if (_endY == null && _masterShape != null) + return _masterShape.getEndY(); + + return _endY; + } + + public Double getAngle() { + if (_angle == null && _masterShape != null) + return _masterShape.getAngle(); + + return _angle; + } + + public Boolean getFlipX() { + if (_flipX == null && _masterShape != null) + return _masterShape.getFlipX(); + + return _flipX; + } + + public Boolean getFlipY() { + if (_flipY == null && _masterShape != null) + return _masterShape.getFlipY(); + + return _flipY; + } + public Double getTxtPinX() { - if (_txtPinX == null && - _masterShape != null && _masterShape._txtPinX != null) + if (_txtPinX == null && _masterShape != null + && _masterShape._txtPinX != null) return _masterShape._txtPinX; - + if (_txtPinX == null) - return getWidth()*0.5; - + return getWidth() * 0.5; + return _txtPinX; } - public Double getTxtPinY() { - if (_txtLocPinY == null && - _masterShape != null && _masterShape._txtLocPinY != null) + if (_txtLocPinY == null && _masterShape != null + && _masterShape._txtLocPinY != null) return _masterShape._txtLocPinY; - + if (_txtPinY == null) - return getHeight()*0.5; - + return getHeight() * 0.5; + return _txtPinY; } - public Double getTxtLocPinX() { - if (_txtLocPinX == null && - _masterShape != null && _masterShape._txtLocPinX != null) + if (_txtLocPinX == null && _masterShape != null + && _masterShape._txtLocPinX != null) return _masterShape._txtLocPinX; - + if (_txtLocPinX == null) - return getTxtWidth()*0.5; - + return getTxtWidth() * 0.5; + return _txtLocPinX; } - public Double getTxtLocPinY() { - if (_txtLocPinY == null && - _masterShape != null && _masterShape._txtLocPinY != null) + if (_txtLocPinY == null && _masterShape != null + && _masterShape._txtLocPinY != null) return _masterShape._txtLocPinY; - + if (_txtLocPinY == null) - return getTxtHeight()*0.5; - + return getTxtHeight() * 0.5; + return _txtLocPinY; } - + public Double getTxtAngle() { - if (_txtAngle == null && _masterShape != null) - return _masterShape.getTxtAngle(); - - return _txtAngle; - } - + if (_txtAngle == null && _masterShape != null) + return _masterShape.getTxtAngle(); + + return _txtAngle; + } + public Double getTxtWidth() { - if (_txtWidth == null && - _masterShape != null && _masterShape._txtWidth != null) + if (_txtWidth == null && _masterShape != null + && _masterShape._txtWidth != null) return _masterShape._txtWidth; - + if (_txtWidth == null) return getWidth(); - + return _txtWidth; } - public Double getTxtHeight() { - if (_txtHeight == null && - _masterShape != null && _masterShape._txtHeight != null) + if (_txtHeight == null && _masterShape != null + && _masterShape._txtHeight != null) return _masterShape._txtHeight; - + if (_txtHeight == null) return getHeight(); - + return _txtHeight; } - + + @Override + public Integer getLineCap() { + + Integer lineCap = super.getLineCap(); + if (lineCap != null) + return lineCap; + + // get from master + if (_masterShape != null) { + return _masterShape.getLineCap(); + } + + // get default + XDGFStyleSheet style = _document.getDefaultLineStyle(); + if (style != null) + return style.getLineCap(); + + return null; + } + @Override - public Integer getLineCap() { - - Integer lineCap = super.getLineCap(); - if (lineCap != null) - return lineCap; - - // get from master - if (_masterShape != null) { - return _masterShape.getLineCap(); - } - - // get default - XDGFStyleSheet style = _document.getDefaultLineStyle(); - if (style != null) - return style.getLineCap(); - - return null; - } - + public Color getLineColor() { + + Color lineColor = super.getLineColor(); + if (lineColor != null) + return lineColor; + + // get from master + if (_masterShape != null) { + return _masterShape.getLineColor(); + } + + // get default + XDGFStyleSheet style = _document.getDefaultLineStyle(); + if (style != null) + return style.getLineColor(); + + return null; + } + @Override - public Color getLineColor() { - - Color lineColor = super.getLineColor(); - if (lineColor != null) - return lineColor; - - // get from master - if (_masterShape != null) { - return _masterShape.getLineColor(); - } - - // get default - XDGFStyleSheet style = _document.getDefaultLineStyle(); - if (style != null) - return style.getLineColor(); - - return null; - } - + public Integer getLinePattern() { + + Integer linePattern = super.getLinePattern(); + if (linePattern != null) + return linePattern; + + // get from master + if (_masterShape != null) { + return _masterShape.getLinePattern(); + } + + // get default + XDGFStyleSheet style = _document.getDefaultLineStyle(); + if (style != null) + return style.getLinePattern(); + + return null; + } + @Override - public Integer getLinePattern() { - - Integer linePattern = super.getLinePattern(); - if (linePattern != null) - return linePattern; - - // get from master - if (_masterShape != null) { - return _masterShape.getLinePattern(); - } - - // get default - XDGFStyleSheet style = _document.getDefaultLineStyle(); - if (style != null) - return style.getLinePattern(); - - return null; - } - + public Double getLineWeight() { + + Double lineWeight = super.getLineWeight(); + if (lineWeight != null) + return lineWeight; + + // get from master + if (_masterShape != null) { + return _masterShape.getLineWeight(); + } + + // get default + XDGFStyleSheet style = _document.getDefaultLineStyle(); + if (style != null) + return style.getLineWeight(); + + return null; + } + @Override - public Double getLineWeight() { - - Double lineWeight = super.getLineWeight(); - if (lineWeight != null) - return lineWeight; - - // get from master - if (_masterShape != null) { - return _masterShape.getLineWeight(); - } - - // get default - XDGFStyleSheet style = _document.getDefaultLineStyle(); - if (style != null) - return style.getLineWeight(); - - return null; - } - public Color getFontColor() { - - Color fontColor = super.getFontColor(); - if (fontColor != null) - return fontColor; - - // get from master - if (_masterShape != null) { - return _masterShape.getFontColor(); - } - - // get default - XDGFStyleSheet style = _document.getDefaultTextStyle(); - if (style != null) - return style.getFontColor(); - - return null; - } - - public Double getFontSize() { - - Double fontSize = super.getFontSize(); - if (fontSize != null) - return fontSize; - - // get from master - if (_masterShape != null) { - return _masterShape.getFontSize(); - } - - // get default - XDGFStyleSheet style = _document.getDefaultTextStyle(); - if (style != null) - return style.getFontSize(); - - return null; - } - - public Stroke getStroke() { - - float lineWeight = getLineWeight().floatValue(); - int cap; - int join = BasicStroke.JOIN_MITER; - float miterlimit = 10.0f; - - switch (getLineCap()) { - case 0: - cap = BasicStroke.CAP_ROUND; - break; - case 1: - cap = BasicStroke.CAP_SQUARE; - break; - case 2: - cap = BasicStroke.CAP_BUTT; // TODO: what does extended mean? - break; - default: - throw new POIXMLException("Invalid line cap specified"); - } - - float[] dash = null; - - // these line patterns are just approximations - switch (getLinePattern()) { - case 0: // transparent - break; - case 1: // solid - break; - case 2: - dash = new float[]{5,3}; - break; - case 3: - dash = new float[]{1,4}; - break; - case 4: - dash = new float[]{6,3,1,3}; - break; - case 5: - dash = new float[]{6,3,1,3,1,3}; - break; - case 6: - dash = new float[]{1,3,6,3,6,3}; - break; - case 7: - dash = new float[]{15,3,6,3}; - break; - case 8: - dash = new float[]{6,3,6,3}; - break; - case 9: - dash = new float[]{3,2}; - break; - case 10: - dash = new float[]{1,2}; - break; - case 11: - dash = new float[]{3,2,1,2}; - break; - case 12: - dash = new float[]{3,2,1,2,1}; - break; - case 13: - dash = new float[]{1,2,3,2,3,2}; - break; - case 14: - dash = new float[]{3,2,7,2}; - break; - case 15: - dash = new float[]{7,2,3,2,3,2}; - break; - case 16: - dash = new float[]{12,6}; - break; - case 17: - dash = new float[]{1,6}; - break; - case 18: - dash = new float[]{1,6,12,6}; - break; - case 19: - dash = new float[]{1,6,1,6,12,6}; - break; - case 20: - dash = new float[]{1,6,12,6,12,6}; - break; - case 21: - dash = new float[]{30,6,12,6}; - break; - case 22: - dash = new float[]{30,6,12,6,12,6}; - break; - case 23: - dash = new float[]{1}; - break; - case 254: - throw new POIXMLException("Unsupported line pattern value"); - default: - throw new POIXMLException("Invalid line pattern value"); - } - - // dashes are in units of line width - if (dash != null) { - for (int i = 0; i < dash.length; i++) { - dash[i] *= lineWeight; - } - } - - return new BasicStroke(lineWeight, cap, join, miterlimit, dash, 0); - } - - - // - // Geometry - // - - public Iterable<GeometrySection> getGeometrySections() { - return new CombinedIterable<>(_geometry, - _masterShape != null ? _masterShape._geometry : null); - } - - - // returns a rectangle in local coordinates - public Rectangle2D.Double getBounds() { - return new Rectangle2D.Double(0, 0, getWidth(), - getHeight()); - } - - // returns bounds as a path in local coordinates - // -> useful if you need to transform to global coordinates - // -> Don't use for 1d objects, fails for infinite line objects - public Path2D.Double getBoundsAsPath() { - - Double w = getWidth(); - Double h = getHeight(); - - Path2D.Double bounds = new Path2D.Double(); - bounds.moveTo(0, 0); - bounds.lineTo(w, 0); - bounds.lineTo(w, h); - bounds.lineTo(0, h); - bounds.lineTo(0, 0); - - return bounds; - } - - // returns the path in local coordinates - public Path2D.Double getPath() { - for (GeometrySection geoSection: getGeometrySections()) { - if (geoSection.getNoShow() == true) - continue; - - return geoSection.getPath(this); - } - - return null; - } - - /* - * Returns true if the shape has a drawable geometry associated with it - */ - public boolean hasGeometry() { - for (GeometrySection geoSection: getGeometrySections()) { - if (geoSection.getNoShow() == false) - return true; - } - return false; - } - - /** - * Returns a transform that can translate shape-local coordinates - * to the coordinates of its parent shape - */ - protected AffineTransform getParentTransform() { - // TODO: There's probably a better way to do this - AffineTransform tr = new AffineTransform(); - - Double locX = getLocPinX(); - Double locY = getLocPinY(); - Boolean flipX = getFlipX(); - Boolean flipY = getFlipY(); - Double angle = getAngle(); - - tr.translate(-locX, -locY); - - tr.translate(getPinX(), getPinY()); - - // rotate about the origin - if (angle != null && Math.abs(angle) > 0.001) { - tr.rotate(angle, locX, locY); - } - - // flip if necessary - - if (flipX != null && flipX) { - tr.scale(-1, 1); - tr.translate(-getWidth(), 0); - } - - if (flipY != null && flipY) { - tr.scale(1, -1); - tr.translate(0, -getHeight()); - } - - return tr; - } - - + + Color fontColor = super.getFontColor(); + if (fontColor != null) + return fontColor; + + // get from master + if (_masterShape != null) { + return _masterShape.getFontColor(); + } + + // get default + XDGFStyleSheet style = _document.getDefaultTextStyle(); + if (style != null) + return style.getFontColor(); + + return null; + } + + @Override + public Double getFontSize() { + + Double fontSize = super.getFontSize(); + if (fontSize != null) + return fontSize; + + // get from master + if (_masterShape != null) { + return _masterShape.getFontSize(); + } + + // get default + XDGFStyleSheet style = _document.getDefaultTextStyle(); + if (style != null) + return style.getFontSize(); + + return null; + } + + public Stroke getStroke() { + + float lineWeight = getLineWeight().floatValue(); + int cap; + int join = BasicStroke.JOIN_MITER; + float miterlimit = 10.0f; + + switch (getLineCap()) { + case 0: + cap = BasicStroke.CAP_ROUND; + break; + case 1: + cap = BasicStroke.CAP_SQUARE; + break; + case 2: + cap = BasicStroke.CAP_BUTT; // TODO: what does extended mean? + break; + default: + throw new POIXMLException("Invalid line cap specified"); + } + + float[] dash = null; + + // these line patterns are just approximations + switch (getLinePattern()) { + case 0: // transparent + break; + case 1: // solid + break; + case 2: + dash = new float[] { 5, 3 }; + break; + case 3: + dash = new float[] { 1, 4 }; + break; + case 4: + dash = new float[] { 6, 3, 1, 3 }; + break; + case 5: + dash = new float[] { 6, 3, 1, 3, 1, 3 }; + break; + case 6: + dash = new float[] { 1, 3, 6, 3, 6, 3 }; + break; + case 7: + dash = new float[] { 15, 3, 6, 3 }; + break; + case 8: + dash = new float[] { 6, 3, 6, 3 }; + break; + case 9: + dash = new float[] { 3, 2 }; + break; + case 10: + dash = new float[] { 1, 2 }; + break; + case 11: + dash = new float[] { 3, 2, 1, 2 }; + break; + case 12: + dash = new float[] { 3, 2, 1, 2, 1 }; + break; + case 13: + dash = new float[] { 1, 2, 3, 2, 3, 2 }; + break; + case 14: + dash = new float[] { 3, 2, 7, 2 }; + break; + case 15: + dash = new float[] { 7, 2, 3, 2, 3, 2 }; + break; + case 16: + dash = new float[] { 12, 6 }; + break; + case 17: + dash = new float[] { 1, 6 }; + break; + case 18: + dash = new float[] { 1, 6, 12, 6 }; + break; + case 19: + dash = new float[] { 1, 6, 1, 6, 12, 6 }; + break; + case 20: + dash = new float[] { 1, 6, 12, 6, 12, 6 }; + break; + case 21: + dash = new float[] { 30, 6, 12, 6 }; + break; + case 22: + dash = new float[] { 30, 6, 12, 6, 12, 6 }; + break; + case 23: + dash = new float[] { 1 }; + break; + case 254: + throw new POIXMLException("Unsupported line pattern value"); + default: + throw new POIXMLException("Invalid line pattern value"); + } + + // dashes are in units of line width + if (dash != null) { + for (int i = 0; i < dash.length; i++) { + dash[i] *= lineWeight; + } + } + + return new BasicStroke(lineWeight, cap, join, miterlimit, dash, 0); + } + + // + // Geometry + // + + public Iterable<GeometrySection> getGeometrySections() { + return new CombinedIterable<GeometrySection>(_geometry, + _masterShape != null ? _masterShape._geometry : null); + } + + // returns a rectangle in local coordinates + public Rectangle2D.Double getBounds() { + return new Rectangle2D.Double(0, 0, getWidth(), getHeight()); + } + + // returns bounds as a path in local coordinates + // -> useful if you need to transform to global coordinates + // -> Don't use for 1d objects, fails for infinite line objects + public Path2D.Double getBoundsAsPath() { + + Double w = getWidth(); + Double h = getHeight(); + + Path2D.Double bounds = new Path2D.Double(); + bounds.moveTo(0, 0); + bounds.lineTo(w, 0); + bounds.lineTo(w, h); + bounds.lineTo(0, h); + bounds.lineTo(0, 0); + + return bounds; + } + + // returns the path in local coordinates + public Path2D.Double getPath() { + for (GeometrySection geoSection : getGeometrySections()) { + if (geoSection.getNoShow() == true) + continue; + + return geoSection.getPath(this); + } + + return null; + } + + /* + * Returns true if the shape has a drawable geometry associated with it + */ + public boolean hasGeometry() { + for (GeometrySection geoSection : getGeometrySections()) { + if (geoSection.getNoShow() == false) + return true; + } + return false; + } + + /** + * Returns a transform that can translate shape-local coordinates to the + * coordinates of its parent shape + */ + protected AffineTransform getParentTransform() { + // TODO: There's probably a better way to do this + AffineTransform tr = new AffineTransform(); + + Double locX = getLocPinX(); + Double locY = getLocPinY(); + Boolean flipX = getFlipX(); + Boolean flipY = getFlipY(); + Double angle = getAngle(); + + tr.translate(-locX, -locY); + + tr.translate(getPinX(), getPinY()); + + // rotate about the origin + if (angle != null && Math.abs(angle) > 0.001) { + tr.rotate(angle, locX, locY); + } + + // flip if necessary + + if (flipX != null && flipX) { + tr.scale(-1, 1); + tr.translate(-getWidth(), 0); + } + + if (flipY != null && flipY) { + tr.scale(1, -1); + tr.translate(0, -getHeight()); + } + + return tr; + } /** * The visitor will first visit this shape, then it's children - * + * * This is useful because exceptions will be marked with the shapes as it * propagates up the shape hierarchy. */ - public void visitShapes(ShapeVisitor visitor, AffineTransform tr, int level) { - - tr = (AffineTransform)tr.clone(); - tr.concatenate(getParentTransform()); - - try { - if (visitor.accept(this)) - visitor.visit(this, tr, level); - - if (_shapes != null) { - for (XDGFShape shape: _shapes) { - shape.visitShapes(visitor, tr, level + 1); - } - } - } catch (StopVisitingThisBranch e) { - // intentionally empty - } catch (POIXMLException e) { - throw XDGFException.wrap(this.toString(), e); - } - } - - /** - * The visitor will first visit this shape, then it's children. No transform + public void visitShapes(ShapeVisitor visitor, AffineTransform tr, int level) { + + tr = (AffineTransform) tr.clone(); + tr.concatenate(getParentTransform()); + + try { + if (visitor.accept(this)) + visitor.visit(this, tr, level); + + if (_shapes != null) { + for (XDGFShape shape : _shapes) { + shape.visitShapes(visitor, tr, level + 1); + } + } + } catch (StopVisitingThisBranch e) { + // intentionally empty + } catch (POIXMLException e) { + throw XDGFException.wrap(this.toString(), e); + } + } + + /** + * The visitor will first visit this shape, then it's children. No transform * is calculated for this visit - * + * * This is useful because exceptions will be marked with the shapes as it * propagates up the shape hierarchy. */ - public void visitShapes(ShapeVisitor visitor, int level) { - - try { - if (visitor.accept(this)) - visitor.visit(this, null, level); - - if (_shapes != null) { - for (XDGFShape shape: _shapes) { - shape.visitShapes(visitor, level + 1); - } - } - } catch (StopVisitingThisBranch e) { - // intentionally empty - } catch (POIXMLException e) { - throw XDGFException.wrap(this.toString(), e); - } - } - + public void visitShapes(ShapeVisitor visitor, int level) { + + try { + if (visitor.accept(this)) + visitor.visit(this, null, level); + + if (_shapes != null) { + for (XDGFShape shape : _shapes) { + shape.visitShapes(visitor, level + 1); + } + } + } catch (StopVisitingThisBranch e) { + // intentionally empty + } catch (POIXMLException e) { + throw XDGFException.wrap(this.toString(), e); + } + } + } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFSheet.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFSheet.java index f460319d2b..9032672833 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFSheet.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFSheet.java @@ -39,166 +39,166 @@ import com.microsoft.schemas.office.visio.x2012.main.SheetType; */ public abstract class XDGFSheet { - protected XDGFDocument _document; - protected SheetType _sheet; - - // cells - protected Map<String, XDGFCell> _cells = new HashMap<>(); - - // sections - protected Map<String, XDGFSection> _sections = new HashMap<>(); - - // special: geometry sections (key: index, value: section) - protected SortedMap<Long, GeometrySection> _geometry = new TreeMap<>(); - - // special: character section - protected CharacterSection _character = null; - - public XDGFSheet(SheetType sheet, XDGFDocument document) { - try { - _sheet = sheet; - _document = document; - - for (CellType cell: sheet.getCellArray()) { - if (_cells.containsKey(cell.getN())) - throw new POIXMLException("Unexpected duplicate cell " + cell.getN()); // this shouldn't happen - - _cells.put(cell.getN(), new XDGFCell(cell)); - } - - // only geometry sections can have duplicate names - // sections can be found in the master too, if there are no attributes here! - - // no idea if I have a master in this space. go figure. - - for (SectionType section: sheet.getSectionArray()) { - String name = section.getN(); - if (name.equals("Geometry")) { - _geometry.put(section.getIX(), new GeometrySection(section, this)); - } else if (name.equals("Character")) { - _character = new CharacterSection(section, this); - } else { - _sections.put(name, XDGFSection.load(section, this)); - } - } - } catch (POIXMLException e) { - throw XDGFException.wrap(this.toString(), e); - } - } - - abstract SheetType getXmlObject(); - - public XDGFDocument getDocument() { - return _document; - } - - // A cell is really just a setting - public XDGFCell getCell(String cellName) { - return _cells.get(cellName); - } - - public XDGFSection getSection(String sectionName) { - return _sections.get(sectionName); - } - - public XDGFStyleSheet getLineStyle() { - if (!_sheet.isSetLineStyle()) - return null; - - return _document.getStyleById(_sheet.getLineStyle()); - } - - public XDGFStyleSheet getFillStyle() { - if (!_sheet.isSetFillStyle()) - return null; - - return _document.getStyleById(_sheet.getFillStyle()); - } - - public XDGFStyleSheet getTextStyle() { - if (!_sheet.isSetTextStyle()) - return null; - - return _document.getStyleById(_sheet.getTextStyle()); - } - - public Color getFontColor() { - Color fontColor = null; - - if (_character != null) { - fontColor = _character.getFontColor(); - if (fontColor != null) - return fontColor; - } - - XDGFStyleSheet style = getTextStyle(); - if (style != null) - return style.getFontColor(); - - return null; - } - - public Double getFontSize() { - Double fontSize = null; - - if (_character != null) { - fontSize = _character.getFontSize(); - if (fontSize != null) - return fontSize; - } - - XDGFStyleSheet style = getTextStyle(); - if (style != null) - return style.getFontSize(); - - return null; - } - - public Integer getLineCap() { - Integer lineCap = XDGFCell.maybeGetInteger(_cells, "LineCap"); - if (lineCap != null) - return lineCap; - - XDGFStyleSheet style = getLineStyle(); - if (style != null) - return style.getLineCap(); - - return null; - } - - public Color getLineColor() { - String lineColor = XDGFCell.maybeGetString(_cells, "LineColor"); - if (lineColor != null) - return Color.decode(lineColor); - - XDGFStyleSheet style = getLineStyle(); - if (style != null) - return style.getLineColor(); - - return null; - } - - public Integer getLinePattern() { - Integer linePattern = XDGFCell.maybeGetInteger(_cells, "LinePattern"); - if (linePattern != null) - return linePattern; - - XDGFStyleSheet style = getLineStyle(); - if (style != null) - return style.getLinePattern(); - - return null; - } - - public Double getLineWeight() { - Double lineWeight = XDGFCell.maybeGetDouble(_cells, "LineWeight"); - if (lineWeight != null) - return lineWeight; - - XDGFStyleSheet style = getLineStyle(); - if (style != null) - return style.getLineWeight(); - - return null; - } + protected XDGFDocument _document; + protected SheetType _sheet; + + // cells + protected Map<String, XDGFCell> _cells = new HashMap<String, XDGFCell>(); + + // sections + protected Map<String, XDGFSection> _sections = new HashMap<String, XDGFSection>(); + + // special: geometry sections (key: index, value: section) + protected SortedMap<Long, GeometrySection> _geometry = new TreeMap<Long, GeometrySection>(); + + // special: character section + protected CharacterSection _character = null; + + public XDGFSheet(SheetType sheet, XDGFDocument document) { + try { + _sheet = sheet; + _document = document; + + for (CellType cell: sheet.getCellArray()) { + if (_cells.containsKey(cell.getN())) + throw new POIXMLException("Unexpected duplicate cell " + cell.getN()); // this shouldn't happen + + _cells.put(cell.getN(), new XDGFCell(cell)); + } + + // only geometry sections can have duplicate names + // sections can be found in the master too, if there are no attributes here! + + // no idea if I have a master in this space. go figure. + + for (SectionType section: sheet.getSectionArray()) { + String name = section.getN(); + if (name.equals("Geometry")) { + _geometry.put(section.getIX(), new GeometrySection(section, this)); + } else if (name.equals("Character")) { + _character = new CharacterSection(section, this); + } else { + _sections.put(name, XDGFSection.load(section, this)); + } + } + } catch (POIXMLException e) { + throw XDGFException.wrap(this.toString(), e); + } + } + + abstract SheetType getXmlObject(); + + public XDGFDocument getDocument() { + return _document; + } + + // A cell is really just a setting + public XDGFCell getCell(String cellName) { + return _cells.get(cellName); + } + + public XDGFSection getSection(String sectionName) { + return _sections.get(sectionName); + } + + public XDGFStyleSheet getLineStyle() { + if (!_sheet.isSetLineStyle()) + return null; + + return _document.getStyleById(_sheet.getLineStyle()); + } + + public XDGFStyleSheet getFillStyle() { + if (!_sheet.isSetFillStyle()) + return null; + + return _document.getStyleById(_sheet.getFillStyle()); + } + + public XDGFStyleSheet getTextStyle() { + if (!_sheet.isSetTextStyle()) + return null; + + return _document.getStyleById(_sheet.getTextStyle()); + } + + public Color getFontColor() { + Color fontColor = null; + + if (_character != null) { + fontColor = _character.getFontColor(); + if (fontColor != null) + return fontColor; + } + + XDGFStyleSheet style = getTextStyle(); + if (style != null) + return style.getFontColor(); + + return null; + } + + public Double getFontSize() { + Double fontSize = null; + + if (_character != null) { + fontSize = _character.getFontSize(); + if (fontSize != null) + return fontSize; + } + + XDGFStyleSheet style = getTextStyle(); + if (style != null) + return style.getFontSize(); + + return null; + } + + public Integer getLineCap() { + Integer lineCap = XDGFCell.maybeGetInteger(_cells, "LineCap"); + if (lineCap != null) + return lineCap; + + XDGFStyleSheet style = getLineStyle(); + if (style != null) + return style.getLineCap(); + + return null; + } + + public Color getLineColor() { + String lineColor = XDGFCell.maybeGetString(_cells, "LineColor"); + if (lineColor != null) + return Color.decode(lineColor); + + XDGFStyleSheet style = getLineStyle(); + if (style != null) + return style.getLineColor(); + + return null; + } + + public Integer getLinePattern() { + Integer linePattern = XDGFCell.maybeGetInteger(_cells, "LinePattern"); + if (linePattern != null) + return linePattern; + + XDGFStyleSheet style = getLineStyle(); + if (style != null) + return style.getLinePattern(); + + return null; + } + + public Double getLineWeight() { + Double lineWeight = XDGFCell.maybeGetDouble(_cells, "LineWeight"); + if (lineWeight != null) + return lineWeight; + + XDGFStyleSheet style = getLineStyle(); + if (style != null) + return style.getLineWeight(); + + return null; + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFStyleSheet.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFStyleSheet.java index 39df4a90ac..50f61842b0 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFStyleSheet.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFStyleSheet.java @@ -22,15 +22,15 @@ import org.apache.poi.util.Internal; import com.microsoft.schemas.office.visio.x2012.main.StyleSheetType; public class XDGFStyleSheet extends XDGFSheet { - - public XDGFStyleSheet(StyleSheetType styleSheet, XDGFDocument document) { - super(styleSheet, document); - } - - @Internal - public StyleSheetType getXmlObject() { - return (StyleSheetType)_sheet; - } - - + + public XDGFStyleSheet(StyleSheetType styleSheet, XDGFDocument document) { + super(styleSheet, document); + } + + @Override + @Internal + public StyleSheetType getXmlObject() { + return (StyleSheetType) _sheet; + } + } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFText.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFText.java index a5c89fca8a..b29e6a0b41 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFText.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFText.java @@ -33,118 +33,125 @@ import com.microsoft.schemas.office.visio.x2012.main.impl.TextTypeImpl; public class XDGFText { - TextType _text; - XDGFShape _parent; - - public XDGFText(TextType text, XDGFShape parent) { - _text = text; - _parent = parent; - } - - @Internal - TextType getXmlObject() { - return _text; - } - - public String getTextContent() { - // casting here is wrong, but there's no other way of getting the value, - // as it doesn't seem to be exposed by complex types (even though this - // is a mixed type) - return ((TextTypeImpl)_text).getStringValue(); - } - - // these are in the shape coordinate system - // -> See https://msdn.microsoft.com/en-us/library/hh644132(v=office.12).aspx - public Rectangle2D.Double getTextBounds() { - - double txtPinX = _parent.getTxtPinX(); - double txtPinY = _parent.getTxtPinY(); - - double txtLocPinX = _parent.getTxtLocPinX(); - double txtLocPinY = _parent.getTxtLocPinY(); - - double txtWidth = _parent.getTxtWidth(); - double txtHeight = _parent.getTxtHeight(); - - double x = txtPinX - txtLocPinX; - double y = txtPinY - txtLocPinY; - - return new Rectangle2D.Double(x, y, txtWidth, txtHeight); - } - - // returns bounds as a path in local coordinates - // -> useful if you need to transform to global coordinates - public Path2D.Double getBoundsAsPath() { - - Rectangle2D.Double rect = getTextBounds(); - Double w = rect.getWidth(); - Double h = rect.getHeight(); - - Path2D.Double bounds = new Path2D.Double(); - bounds.moveTo(0, 0); - bounds.lineTo(w, 0); - bounds.lineTo(w, h); - bounds.lineTo(0, h); - bounds.lineTo(0, 0); - - return bounds; - } - - // center of text in local coordinates - public Point2D.Double getTextCenter() { - return new Point2D.Double(_parent.getTxtLocPinX(), _parent.getTxtLocPinY()); - } - - // assumes graphics is set properly to draw in the right style - public void draw(Graphics2D graphics) { - - String textContent = getTextContent(); - if (textContent.length() == 0) - return; - - Rectangle2D.Double bounds = getTextBounds(); - - String[] lines = textContent.trim().split("\n"); - FontRenderContext frc = graphics.getFontRenderContext(); - Font font = graphics.getFont(); - - AffineTransform oldTr = graphics.getTransform(); - - // visio is in flipped coordinates, so translate the text to be in the right place - Boolean flipX = _parent.getFlipX(); - Boolean flipY = _parent.getFlipY(); - - if (flipY == null || !_parent.getFlipY()) { - graphics.translate(bounds.x, bounds.y); - graphics.scale(1, -1); - graphics.translate(0, -bounds.height + graphics.getFontMetrics().getMaxCharBounds(graphics).getHeight()); - } - - if (flipX != null && _parent.getFlipX()) { - graphics.scale(-1, 1); - graphics.translate(-bounds.width, 0); - } - - Double txtAngle = _parent.getTxtAngle(); - if (txtAngle != null && Math.abs(txtAngle) > 0.01) - graphics.rotate(txtAngle); - - float nextY = 0; - for (String line: lines) { - - if (line.length() == 0) - continue; - - TextLayout layout = new TextLayout(line, font, frc); - - if (layout.isLeftToRight()) - layout.draw(graphics, 0, nextY); - else - layout.draw(graphics, (float)(bounds.width - layout.getAdvance()), nextY); - - nextY += layout.getAscent() + layout.getDescent() + layout.getLeading(); - } - - graphics.setTransform(oldTr); - } + TextType _text; + XDGFShape _parent; + + public XDGFText(TextType text, XDGFShape parent) { + _text = text; + _parent = parent; + } + + @Internal + TextType getXmlObject() { + return _text; + } + + public String getTextContent() { + // casting here is wrong, but there's no other way of getting the value, + // as it doesn't seem to be exposed by complex types (even though this + // is a mixed type) + return ((TextTypeImpl) _text).getStringValue(); + } + + // these are in the shape coordinate system + // -> See + // https://msdn.microsoft.com/en-us/library/hh644132(v=office.12).aspx + public Rectangle2D.Double getTextBounds() { + + double txtPinX = _parent.getTxtPinX(); + double txtPinY = _parent.getTxtPinY(); + + double txtLocPinX = _parent.getTxtLocPinX(); + double txtLocPinY = _parent.getTxtLocPinY(); + + double txtWidth = _parent.getTxtWidth(); + double txtHeight = _parent.getTxtHeight(); + + double x = txtPinX - txtLocPinX; + double y = txtPinY - txtLocPinY; + + return new Rectangle2D.Double(x, y, txtWidth, txtHeight); + } + + // returns bounds as a path in local coordinates + // -> useful if you need to transform to global coordinates + public Path2D.Double getBoundsAsPath() { + + Rectangle2D.Double rect = getTextBounds(); + Double w = rect.getWidth(); + Double h = rect.getHeight(); + + Path2D.Double bounds = new Path2D.Double(); + bounds.moveTo(0, 0); + bounds.lineTo(w, 0); + bounds.lineTo(w, h); + bounds.lineTo(0, h); + bounds.lineTo(0, 0); + + return bounds; + } + + // center of text in local coordinates + public Point2D.Double getTextCenter() { + return new Point2D.Double(_parent.getTxtLocPinX(), + _parent.getTxtLocPinY()); + } + + // assumes graphics is set properly to draw in the right style + public void draw(Graphics2D graphics) { + + String textContent = getTextContent(); + if (textContent.length() == 0) + return; + + Rectangle2D.Double bounds = getTextBounds(); + + String[] lines = textContent.trim().split("\n"); + FontRenderContext frc = graphics.getFontRenderContext(); + Font font = graphics.getFont(); + + AffineTransform oldTr = graphics.getTransform(); + + // visio is in flipped coordinates, so translate the text to be in the + // right place + Boolean flipX = _parent.getFlipX(); + Boolean flipY = _parent.getFlipY(); + + if (flipY == null || !_parent.getFlipY()) { + graphics.translate(bounds.x, bounds.y); + graphics.scale(1, -1); + graphics.translate(0, -bounds.height + + graphics.getFontMetrics().getMaxCharBounds(graphics) + .getHeight()); + } + + if (flipX != null && _parent.getFlipX()) { + graphics.scale(-1, 1); + graphics.translate(-bounds.width, 0); + } + + Double txtAngle = _parent.getTxtAngle(); + if (txtAngle != null && Math.abs(txtAngle) > 0.01) + graphics.rotate(txtAngle); + + float nextY = 0; + for (String line : lines) { + + if (line.length() == 0) + continue; + + TextLayout layout = new TextLayout(line, font, frc); + + if (layout.isLeftToRight()) + layout.draw(graphics, 0, nextY); + else + layout.draw(graphics, + (float) (bounds.width - layout.getAdvance()), nextY); + + nextY += layout.getAscent() + layout.getDescent() + + layout.getLeading(); + } + + graphics.setTransform(oldTr); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XmlVisioDocument.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XmlVisioDocument.java index 83adc18a67..be5730e948 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XmlVisioDocument.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XmlVisioDocument.java @@ -36,78 +36,75 @@ import com.microsoft.schemas.office.visio.x2012.main.VisioDocumentType; public class XmlVisioDocument extends POIXMLDocument { - public static String CORE_DOCUMENT = "http://schemas.microsoft.com/visio/2010/relationships/document"; - - XDGFPages _pages; - XDGFMasters _masters; - XDGFDocument _document; - - - public XmlVisioDocument(OPCPackage pkg) throws IOException { - super(pkg, CORE_DOCUMENT); - - VisioDocumentType document; - - try { - document = VisioDocumentDocument1.Factory.parse(getPackagePart().getInputStream()).getVisioDocument(); - } catch (XmlException | IOException e) { - throw new POIXMLException(e); - } - - _document = new XDGFDocument(document); - - //build a tree of POIXMLDocumentParts, this document being the root + public static String CORE_DOCUMENT = "http://schemas.microsoft.com/visio/2010/relationships/document"; + + XDGFPages _pages; + XDGFMasters _masters; + XDGFDocument _document; + + public XmlVisioDocument(OPCPackage pkg) throws IOException { + super(pkg, CORE_DOCUMENT); + + VisioDocumentType document; + + try { + document = VisioDocumentDocument1.Factory.parse(getPackagePart().getInputStream()).getVisioDocument(); + } catch (XmlException e) { + throw new POIXMLException(e); + } catch (IOException e) { + throw new POIXMLException(e); + } + + _document = new XDGFDocument(document); + + //build a tree of POIXMLDocumentParts, this document being the root load(new XDGFFactory(_document)); - } - - public XmlVisioDocument(InputStream is) throws IOException { - this(PackageHelper.open(is)); - } - - - @Override + } + + public XmlVisioDocument(InputStream is) throws IOException { + this(PackageHelper.open(is)); + } + + @Override protected void onDocumentRead() throws IOException { - - // by the time this gets called, all other document parts should - // have been loaded, so it's safe to build the document structure - - // note that in other onDocumentRead(), relations/etc may not have - // loaded yet, so it's not quite safe - - for (POIXMLDocumentPart part: getRelations()) { - - // organize the document pieces - if (part instanceof XDGFPages) - _pages = (XDGFPages)part; - - else if (part instanceof XDGFMasters) - _masters = (XDGFMasters)part; - } - - if (_masters != null) - _masters.onDocumentRead(); - - _pages.onDocumentRead(); - } - - - - @Override - public List<PackagePart> getAllEmbedds() throws OpenXML4JException { - throw new UnsupportedOperationException("Not implemented"); - } - - // - // Useful public API goes here - // - - public Collection<XDGFPage> getPages() { - return _pages.getPageList(); - } - - - public XDGFStyleSheet getStyleById(long id) { - return _document.getStyleById(id); - } - + + // by the time this gets called, all other document parts should + // have been loaded, so it's safe to build the document structure + + // note that in other onDocumentRead(), relations/etc may not have + // loaded yet, so it's not quite safe + + for (POIXMLDocumentPart part : getRelations()) { + + // organize the document pieces + if (part instanceof XDGFPages) + _pages = (XDGFPages) part; + + else if (part instanceof XDGFMasters) + _masters = (XDGFMasters) part; + } + + if (_masters != null) + _masters.onDocumentRead(); + + _pages.onDocumentRead(); + } + + @Override + public List<PackagePart> getAllEmbedds() throws OpenXML4JException { + throw new UnsupportedOperationException("Not implemented"); + } + + // + // Useful public API goes here + // + + public Collection<XDGFPage> getPages() { + return _pages.getPageList(); + } + + public XDGFStyleSheet getStyleById(long id) { + return _document.getStyleById(id); + } + } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/CharacterSection.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/CharacterSection.java index b5407cb521..0d8fef0557 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/CharacterSection.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/CharacterSection.java @@ -29,43 +29,43 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType; import com.microsoft.schemas.office.visio.x2012.main.SectionType; public class CharacterSection extends XDGFSection { - - Double _fontSize = null; - Color _fontColor = null; - - Map<String, XDGFCell> _characterCells = new HashMap<>(); - - public CharacterSection(SectionType section, XDGFSheet containingSheet) { - super(section, containingSheet); - - // there aren't cells for this, just a single row - RowType row = section.getRowArray(0); - - for (CellType cell: row.getCellArray()) { - _characterCells.put(cell.getN(), new XDGFCell(cell)); - } - - if (row != null) { - _fontSize = XDGFCell.maybeGetDouble(_characterCells, "Size"); - - String tmpColor = XDGFCell.maybeGetString(_characterCells, "Color"); - if (tmpColor != null) - _fontColor = Color.decode(tmpColor); - } - } - - public Double getFontSize() { - return _fontSize; - } - - public Color getFontColor() { - return _fontColor; - } - - @Override - public void setupMaster(XDGFSection section) { - - } - + + Double _fontSize = null; + Color _fontColor = null; + + Map<String, XDGFCell> _characterCells = new HashMap<String, XDGFCell>(); + + public CharacterSection(SectionType section, XDGFSheet containingSheet) { + super(section, containingSheet); + + // there aren't cells for this, just a single row + RowType row = section.getRowArray(0); + + for (CellType cell: row.getCellArray()) { + _characterCells.put(cell.getN(), new XDGFCell(cell)); + } + + if (row != null) { + _fontSize = XDGFCell.maybeGetDouble(_characterCells, "Size"); + + String tmpColor = XDGFCell.maybeGetString(_characterCells, "Color"); + if (tmpColor != null) + _fontColor = Color.decode(tmpColor); + } + } + + public Double getFontSize() { + return _fontSize; + } + + public Color getFontColor() { + return _fontColor; + } + + @Override + public void setupMaster(XDGFSection section) { + + } + } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/CombinedIterable.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/CombinedIterable.java index b1fb4c652e..983ee2db77 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/CombinedIterable.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/CombinedIterable.java @@ -19,118 +19,119 @@ package org.apache.poi.xdgf.usermodel.section; import java.util.Collections; import java.util.Iterator; +import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.SortedMap; -import java.util.Map.Entry; // iterates over the base and master public class CombinedIterable<T> implements Iterable<T> { - final SortedMap<Long, T> _baseItems; - final SortedMap<Long, T> _masterItems; - - public CombinedIterable(SortedMap<Long, T> baseItems, - SortedMap<Long, T> masterItems) { - _baseItems = baseItems; - _masterItems = masterItems; - } - - @Override - public Iterator<T> iterator() { - - final Iterator<Entry<Long, T>> vmasterI; - - if (_masterItems != null) - vmasterI = _masterItems.entrySet().iterator(); - else - vmasterI = Collections.emptyIterator(); - - return new Iterator<T>() { - - Long lastI = Long.MIN_VALUE; - - Entry<Long, T> currentBase = null; - Entry<Long, T> currentMaster = null; - - // grab the iterator for both - Iterator<Entry<Long, T>> baseI = _baseItems.entrySet().iterator(); - Iterator<Entry<Long, T>> masterI = vmasterI; - - @Override - public boolean hasNext() { - return currentBase != null || currentMaster != null || baseI.hasNext() || masterI.hasNext(); - } - - @Override - public T next() { - - // TODO: This seems far more complex than it needs to be - - long baseIdx = Long.MAX_VALUE; - long masterIdx = Long.MAX_VALUE; - - if (currentBase == null) { - while (baseI.hasNext()) { - currentBase = baseI.next(); - if (currentBase.getKey() > lastI) { - baseIdx = currentBase.getKey(); - break; - } - } - } else { - baseIdx = currentBase.getKey(); - } - - if (currentMaster == null) { - while (masterI.hasNext()) { - currentMaster = masterI.next(); - if (currentMaster.getKey() > lastI) { - masterIdx = currentMaster.getKey(); - break; - } - } - } else { - masterIdx = currentMaster.getKey(); - } - - T val; - - if (currentBase != null) { - - if (baseIdx <= masterIdx) { - lastI = baseIdx; - val = currentBase.getValue(); - - // discard master if same as base - if (masterIdx == baseIdx) { - currentMaster = null; - } - - currentBase = null; - - } else { - lastI = masterIdx; - val = currentMaster.getValue(); - currentMaster = null; - } - - } else if (currentMaster != null) { - lastI = currentMaster.getKey(); - val = currentMaster.getValue(); - - currentMaster = null; - } else { - throw new NoSuchElementException(); - } - - return val; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } + final SortedMap<Long, T> _baseItems; + final SortedMap<Long, T> _masterItems; + + public CombinedIterable(SortedMap<Long, T> baseItems, + SortedMap<Long, T> masterItems) { + _baseItems = baseItems; + _masterItems = masterItems; + } + + @Override + public Iterator<T> iterator() { + + final Iterator<Entry<Long, T>> vmasterI; + + if (_masterItems != null) + vmasterI = _masterItems.entrySet().iterator(); + else + vmasterI = Collections.emptyIterator(); + + return new Iterator<T>() { + + Long lastI = Long.MIN_VALUE; + + Entry<Long, T> currentBase = null; + Entry<Long, T> currentMaster = null; + + // grab the iterator for both + Iterator<Entry<Long, T>> baseI = _baseItems.entrySet().iterator(); + Iterator<Entry<Long, T>> masterI = vmasterI; + + @Override + public boolean hasNext() { + return currentBase != null || currentMaster != null + || baseI.hasNext() || masterI.hasNext(); + } + + @Override + public T next() { + + // TODO: This seems far more complex than it needs to be + + long baseIdx = Long.MAX_VALUE; + long masterIdx = Long.MAX_VALUE; + + if (currentBase == null) { + while (baseI.hasNext()) { + currentBase = baseI.next(); + if (currentBase.getKey() > lastI) { + baseIdx = currentBase.getKey(); + break; + } + } + } else { + baseIdx = currentBase.getKey(); + } + + if (currentMaster == null) { + while (masterI.hasNext()) { + currentMaster = masterI.next(); + if (currentMaster.getKey() > lastI) { + masterIdx = currentMaster.getKey(); + break; + } + } + } else { + masterIdx = currentMaster.getKey(); + } + + T val; + + if (currentBase != null) { + + if (baseIdx <= masterIdx) { + lastI = baseIdx; + val = currentBase.getValue(); + + // discard master if same as base + if (masterIdx == baseIdx) { + currentMaster = null; + } + + currentBase = null; + + } else { + lastI = masterIdx; + val = currentMaster.getValue(); + currentMaster = null; + } + + } else if (currentMaster != null) { + lastI = currentMaster.getKey(); + val = currentMaster.getValue(); + + currentMaster = null; + } else { + throw new NoSuchElementException(); + } + + return val; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/GenericSection.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/GenericSection.java index 0a35fc0559..b0ecf2051e 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/GenericSection.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/GenericSection.java @@ -23,11 +23,11 @@ import com.microsoft.schemas.office.visio.x2012.main.SectionType; public class GenericSection extends XDGFSection { - public GenericSection(SectionType section, XDGFSheet containingSheet) { - super(section, containingSheet); - } + public GenericSection(SectionType section, XDGFSheet containingSheet) { + super(section, containingSheet); + } - @Override - public void setupMaster(XDGFSection section) { - } + @Override + public void setupMaster(XDGFSection section) { + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/GeometrySection.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/GeometrySection.java index 079b06e35b..bc7cdf60b4 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/GeometrySection.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/GeometrySection.java @@ -29,9 +29,9 @@ import org.apache.poi.xdgf.usermodel.XDGFCell; import org.apache.poi.xdgf.usermodel.XDGFShape; import org.apache.poi.xdgf.usermodel.XDGFSheet; import org.apache.poi.xdgf.usermodel.section.geometry.Ellipse; +import org.apache.poi.xdgf.usermodel.section.geometry.GeometryRow; import org.apache.poi.xdgf.usermodel.section.geometry.GeometryRowFactory; import org.apache.poi.xdgf.usermodel.section.geometry.InfiniteLine; -import org.apache.poi.xdgf.usermodel.section.geometry.GeometryRow; import org.apache.poi.xdgf.usermodel.section.geometry.SplineKnot; import org.apache.poi.xdgf.usermodel.section.geometry.SplineStart; @@ -40,116 +40,116 @@ import com.microsoft.schemas.office.visio.x2012.main.SectionType; public class GeometrySection extends XDGFSection { - GeometrySection _master = null; - - // rows - SortedMap<Long, GeometryRow> _rows = new TreeMap<>(); - - public GeometrySection(SectionType section, XDGFSheet containingSheet) { - super(section, containingSheet); - - for (RowType row: section.getRowArray()) { - if (_rows.containsKey(row.getIX())) - throw new POIXMLException("Index element '" + row.getIX() + "' already exists"); - - _rows.put(row.getIX(), GeometryRowFactory.load(row)); - } - } - - @Override - public void setupMaster(XDGFSection master) { - - _master = (GeometrySection)master; - - for (Entry<Long, GeometryRow> entry : _rows.entrySet()) { - GeometryRow masterRow = _master._rows.get(entry.getKey()); - if (masterRow != null) { - try { - entry.getValue().setupMaster(masterRow); - } catch (ClassCastException e) { - // this can happen when a dynamic connector overrides its master's geometry - // .. probably can happen elsewhere too, I imagine. - //throw XDGFException.error("Mismatched geometry section '" + entry.getKey() + "' in master", this, e); - } - } - } - } - - // returns True if this row shouldn't be displayed - public Boolean getNoShow() { - Boolean noShow = XDGFCell.maybeGetBoolean(_cells, "NoShow"); - if (noShow == null) { - if (_master != null) - return _master.getNoShow(); - - return false; - } - - return noShow; - } - - public Iterable<GeometryRow> getCombinedRows() { - return new CombinedIterable<>(_rows, - _master == null ? null : _master._rows); - } - - public Path2D.Double getPath(XDGFShape parent) { - - Iterator<GeometryRow> rows = getCombinedRows().iterator(); - - // special cases - GeometryRow first = rows.next(); - - if (first instanceof Ellipse) { - return ((Ellipse)first).getPath(); - } else if (first instanceof InfiniteLine) { - return ((InfiniteLine)first).getPath(); - } else if (first instanceof SplineStart) { - throw new POIXMLException("SplineStart must be preceded by another type"); - } else { - - // everything else is a path - Path2D.Double path = new Path2D.Double(); - - // dealing with splines makes this more complex - SplineCollector renderer = null; - GeometryRow row; - - while (true) { - - if (first != null) { - row = first; - first = null; - } else { - if (!rows.hasNext()) - break; - row = rows.next(); - } - - if (row instanceof SplineStart) { - if (renderer != null) - throw new POIXMLException("SplineStart found multiple times!"); - renderer = new SplineCollector((SplineStart) row); - } else if (row instanceof SplineKnot) { - if (renderer == null) - throw new POIXMLException("SplineKnot found without SplineStart!"); - renderer.addKnot((SplineKnot) row); - } else { - if (renderer != null) { - renderer.addToPath(path, parent); - renderer = null; - } - - row.addToPath(path, parent); - } - } - - // just in case we end iteration - if (renderer != null) - renderer.addToPath(path, parent); - - return path; - } - } - + GeometrySection _master = null; + + // rows + SortedMap<Long, GeometryRow> _rows = new TreeMap<Long, GeometryRow>(); + + public GeometrySection(SectionType section, XDGFSheet containingSheet) { + super(section, containingSheet); + + for (RowType row: section.getRowArray()) { + if (_rows.containsKey(row.getIX())) + throw new POIXMLException("Index element '" + row.getIX() + "' already exists"); + + _rows.put(row.getIX(), GeometryRowFactory.load(row)); + } + } + + @Override + public void setupMaster(XDGFSection master) { + + _master = (GeometrySection)master; + + for (Entry<Long, GeometryRow> entry : _rows.entrySet()) { + GeometryRow masterRow = _master._rows.get(entry.getKey()); + if (masterRow != null) { + try { + entry.getValue().setupMaster(masterRow); + } catch (ClassCastException e) { + // this can happen when a dynamic connector overrides its master's geometry + // .. probably can happen elsewhere too, I imagine. + //throw XDGFException.error("Mismatched geometry section '" + entry.getKey() + "' in master", this, e); + } + } + } + } + + // returns True if this row shouldn't be displayed + public Boolean getNoShow() { + Boolean noShow = XDGFCell.maybeGetBoolean(_cells, "NoShow"); + if (noShow == null) { + if (_master != null) + return _master.getNoShow(); + + return false; + } + + return noShow; + } + + public Iterable<GeometryRow> getCombinedRows() { + return new CombinedIterable<GeometryRow>(_rows, + _master == null ? null : _master._rows); + } + + public Path2D.Double getPath(XDGFShape parent) { + + Iterator<GeometryRow> rows = getCombinedRows().iterator(); + + // special cases + GeometryRow first = rows.next(); + + if (first instanceof Ellipse) { + return ((Ellipse)first).getPath(); + } else if (first instanceof InfiniteLine) { + return ((InfiniteLine)first).getPath(); + } else if (first instanceof SplineStart) { + throw new POIXMLException("SplineStart must be preceded by another type"); + } else { + + // everything else is a path + Path2D.Double path = new Path2D.Double(); + + // dealing with splines makes this more complex + SplineCollector renderer = null; + GeometryRow row; + + while (true) { + + if (first != null) { + row = first; + first = null; + } else { + if (!rows.hasNext()) + break; + row = rows.next(); + } + + if (row instanceof SplineStart) { + if (renderer != null) + throw new POIXMLException("SplineStart found multiple times!"); + renderer = new SplineCollector((SplineStart) row); + } else if (row instanceof SplineKnot) { + if (renderer == null) + throw new POIXMLException("SplineKnot found without SplineStart!"); + renderer.addKnot((SplineKnot) row); + } else { + if (renderer != null) { + renderer.addToPath(path, parent); + renderer = null; + } + + row.addToPath(path, parent); + } + } + + // just in case we end iteration + if (renderer != null) + renderer.addToPath(path, parent); + + return path; + } + } + } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/XDGFSection.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/XDGFSection.java index 835dade97b..1448a60ba9 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/XDGFSection.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/XDGFSection.java @@ -31,68 +31,70 @@ import com.microsoft.schemas.office.visio.x2012.main.SectionType; public abstract class XDGFSection { - static final ObjectFactory<XDGFSection, SectionType> _sectionTypes; - - static { - _sectionTypes = new ObjectFactory<>(); - try { - _sectionTypes.put("LineGradient", GenericSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("FillGradient", GenericSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("Character", CharacterSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("Paragraph", GenericSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("Tabs", GenericSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("Scratch", GenericSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("Connection", GenericSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("ConnectionABCD", GenericSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("Field", GenericSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("Control", GenericSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("Geometry", GeometrySection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("Actions", GenericSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("Layer", GenericSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("User", GenericSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("Property", GenericSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("Hyperlink", GenericSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("Reviewer", GenericSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("Annotation", GenericSection.class, SectionType.class, XDGFSheet.class); - _sectionTypes.put("ActionTag", GenericSection.class, SectionType.class, XDGFSheet.class); - } catch (NoSuchMethodException | SecurityException e) { - throw new POIXMLException("Internal error"); - } - - } - - public static XDGFSection load(SectionType section, XDGFSheet containingSheet) { - return _sectionTypes.load(section.getN(), section, containingSheet); - } - - - protected SectionType _section; - protected XDGFSheet _containingSheet; - - protected Map<String, XDGFCell> _cells = new HashMap<>(); - - - public XDGFSection(SectionType section, XDGFSheet containingSheet) { - _section = section; - _containingSheet = containingSheet; - - // only store cells in the base, not rows -- because rows are handled - // specially for geometry sections - for (CellType cell: section.getCellArray()) { - _cells.put(cell.getN(), new XDGFCell(cell)); - } - } - - @Internal - public SectionType getXmlObject() { - return _section; - } - - @Override - public String toString() { - return "<Section type=" + _section.getN() + " from " + _containingSheet + ">"; - } - - public abstract void setupMaster(XDGFSection section); - + static final ObjectFactory<XDGFSection, SectionType> _sectionTypes; + + static { + _sectionTypes = new ObjectFactory<XDGFSection, SectionType>(); + try { + _sectionTypes.put("LineGradient", GenericSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("FillGradient", GenericSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("Character", CharacterSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("Paragraph", GenericSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("Tabs", GenericSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("Scratch", GenericSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("Connection", GenericSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("ConnectionABCD", GenericSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("Field", GenericSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("Control", GenericSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("Geometry", GeometrySection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("Actions", GenericSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("Layer", GenericSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("User", GenericSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("Property", GenericSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("Hyperlink", GenericSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("Reviewer", GenericSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("Annotation", GenericSection.class, SectionType.class, XDGFSheet.class); + _sectionTypes.put("ActionTag", GenericSection.class, SectionType.class, XDGFSheet.class); + } catch (NoSuchMethodException e) { + throw new POIXMLException("Internal error"); + } catch (SecurityException e) { + throw new POIXMLException("Internal error"); + } + + } + + public static XDGFSection load(SectionType section, XDGFSheet containingSheet) { + return _sectionTypes.load(section.getN(), section, containingSheet); + } + + + protected SectionType _section; + protected XDGFSheet _containingSheet; + + protected Map<String, XDGFCell> _cells = new HashMap<String, XDGFCell>(); + + + public XDGFSection(SectionType section, XDGFSheet containingSheet) { + _section = section; + _containingSheet = containingSheet; + + // only store cells in the base, not rows -- because rows are handled + // specially for geometry sections + for (CellType cell: section.getCellArray()) { + _cells.put(cell.getN(), new XDGFCell(cell)); + } + } + + @Internal + public SectionType getXmlObject() { + return _section; + } + + @Override + public String toString() { + return "<Section type=" + _section.getN() + " from " + _containingSheet + ">"; + } + + public abstract void setupMaster(XDGFSection section); + } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/ArcTo.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/ArcTo.java index 243b3887b8..fdcce80560 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/ArcTo.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/ArcTo.java @@ -30,102 +30,105 @@ import com.microsoft.schemas.office.visio.x2012.main.CellType; import com.microsoft.schemas.office.visio.x2012.main.RowType; public class ArcTo implements GeometryRow { - - ArcTo _master = null; - - // The x-coordinate of the ending vertex of an arc. - Double x = null; - - // The y-coordinate of the ending vertex of an arc. - Double y = null; - - // The distance from the arc's midpoint to the midpoint of its chord. - Double a = null; - - Boolean deleted = null; - - // TODO: support formulas - - public ArcTo(RowType row) { - - if (row.isSetDel()) deleted = row.getDel(); - - for (CellType cell: row.getCellArray()) { - String cellName = cell.getN(); - - if (cellName.equals("X")) { - x = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("Y")) { - y = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("A")) { - a = XDGFCell.parseDoubleValue(cell); - } else { - throw new POIXMLException("Invalid cell '" + cellName + "' in ArcTo row"); - } - } - } - - public boolean getDel() { - if (deleted != null) - return deleted; - - if (_master != null) - return _master.getDel(); - - return false; - } - - public Double getX() { - return x == null ? _master.x : x; - } - - public Double getY() { - return y == null ? _master.y : y; - } - - public Double getA() { - return a == null ? _master.a : a; - } - - @Override - public void setupMaster(GeometryRow row) { - _master = (ArcTo) row; - } - - @Override - public void addToPath(Path2D.Double path, XDGFShape parent) { - - if (getDel()) return; - - Point2D last = path.getCurrentPoint(); - - // intentionally shadowing variables here - double x = getX(); - double y = getY(); - double a = getA(); - - if (a == 0) { - path.lineTo(x, y); - return; - } - - double x0 = last.getX(); - double y0 = last.getY(); - - double chordLength = Math.hypot(y - y0, x - x0); - double radius = (4 * a * a + chordLength * chordLength) / (8 * Math.abs(a)); - - // center point - double cx = x0 + (x - x0) / 2.0; - double cy = y0 + (y - y0) / 2.0; - - double rotate = Math.atan2(y - cy, x - cx); - - Arc2D arc = new Arc2D.Double(x0, y0 - radius, - chordLength, 2*radius, - 180, x0 < x ? 180 : -180, - Arc2D.OPEN); - - path.append(AffineTransform.getRotateInstance(rotate, x0, y0).createTransformedShape(arc), true); - } + + ArcTo _master = null; + + // The x-coordinate of the ending vertex of an arc. + Double x = null; + + // The y-coordinate of the ending vertex of an arc. + Double y = null; + + // The distance from the arc's midpoint to the midpoint of its chord. + Double a = null; + + Boolean deleted = null; + + // TODO: support formulas + + public ArcTo(RowType row) { + + if (row.isSetDel()) + deleted = row.getDel(); + + for (CellType cell : row.getCellArray()) { + String cellName = cell.getN(); + + if (cellName.equals("X")) { + x = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("Y")) { + y = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("A")) { + a = XDGFCell.parseDoubleValue(cell); + } else { + throw new POIXMLException("Invalid cell '" + cellName + + "' in ArcTo row"); + } + } + } + + public boolean getDel() { + if (deleted != null) + return deleted; + + if (_master != null) + return _master.getDel(); + + return false; + } + + public Double getX() { + return x == null ? _master.x : x; + } + + public Double getY() { + return y == null ? _master.y : y; + } + + public Double getA() { + return a == null ? _master.a : a; + } + + @Override + public void setupMaster(GeometryRow row) { + _master = (ArcTo) row; + } + + @Override + public void addToPath(Path2D.Double path, XDGFShape parent) { + + if (getDel()) + return; + + Point2D last = path.getCurrentPoint(); + + // intentionally shadowing variables here + double x = getX(); + double y = getY(); + double a = getA(); + + if (a == 0) { + path.lineTo(x, y); + return; + } + + double x0 = last.getX(); + double y0 = last.getY(); + + double chordLength = Math.hypot(y - y0, x - x0); + double radius = (4 * a * a + chordLength * chordLength) + / (8 * Math.abs(a)); + + // center point + double cx = x0 + (x - x0) / 2.0; + double cy = y0 + (y - y0) / 2.0; + + double rotate = Math.atan2(y - cy, x - cx); + + Arc2D arc = new Arc2D.Double(x0, y0 - radius, chordLength, 2 * radius, + 180, x0 < x ? 180 : -180, Arc2D.OPEN); + + path.append(AffineTransform.getRotateInstance(rotate, x0, y0) + .createTransformedShape(arc), true); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/Ellipse.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/Ellipse.java index 0e4124e9bb..01eecdd003 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/Ellipse.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/Ellipse.java @@ -29,128 +29,132 @@ import com.microsoft.schemas.office.visio.x2012.main.CellType; import com.microsoft.schemas.office.visio.x2012.main.RowType; public class Ellipse implements GeometryRow { - - Ellipse _master = null; - - // x coordinate of center point - Double x = null; - // y coordinate of center point - Double y = null; - - // x coordinate of first point on ellipse - Double a = null; - // y coordinate of first point on ellipse - Double b = null; - - // x coordinate of second point on ellipse - Double c = null; - // y coordinate of second point on ellipse - Double d = null; - - Boolean deleted = null; - - // TODO: support formulas - - public Ellipse(RowType row) { - - if (row.isSetDel()) deleted = row.getDel(); - - for (CellType cell: row.getCellArray()) { - String cellName = cell.getN(); - - if (cellName.equals("X")) { - x = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("Y")) { - y = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("A")) { - a = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("B")) { - b = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("C")) { - c = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("D")) { - d = XDGFCell.parseDoubleValue(cell); - } else { - throw new POIXMLException("Invalid cell '" + cellName + "' in Ellipse row"); - } - } - } - - public boolean getDel() { - if (deleted != null) - return deleted; - - if (_master != null) - return _master.getDel(); - - return false; - } - - public Double getX() { - return x == null ? _master.x : x; - } - - public Double getY() { - return y == null ? _master.y : y; - } - - public Double getA() { - return a == null ? _master.a : a; - } - - public Double getB() { - return b == null ? _master.b : b; - } - - public Double getC() { - return c == null ? _master.c : c; - } - - public Double getD() { - return d == null ? _master.d : d; - } - - @Override - public void setupMaster(GeometryRow row) { - _master = (Ellipse) row; - } - - public Path2D.Double getPath() { - - if (getDel()) return null; - - // intentionally shadowing variables here - double cx = getX(); // center - double cy = getY(); - double a = getA(); // left - double b = getB(); - double c = getC(); // top - double d = getD(); - - // compute radius - double rx = Math.hypot(a - cx, b - cy); - double ry = Math.hypot(c - cx, d - cy); - - // compute angle of ellipse - double angle = (2.0*Math.PI + (cy > b ? 1.0 : -1.0) * Math.acos((cx - a) / rx)) % (2.0*Math.PI); - - // create ellipse - Ellipse2D.Double ellipse = new Ellipse2D.Double(cx - rx, - cy - ry, - rx*2, ry*2); - - // create a path, rotate it about its center - Path2D.Double path = new Path2D.Double(ellipse); - - AffineTransform tr = new AffineTransform(); - tr.rotate(angle, cx, cy); - path.transform(tr); - - return path; - } - - @Override - public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { - throw new POIXMLException("Ellipse elements cannot be part of a path"); - } + + Ellipse _master = null; + + // x coordinate of center point + Double x = null; + // y coordinate of center point + Double y = null; + + // x coordinate of first point on ellipse + Double a = null; + // y coordinate of first point on ellipse + Double b = null; + + // x coordinate of second point on ellipse + Double c = null; + // y coordinate of second point on ellipse + Double d = null; + + Boolean deleted = null; + + // TODO: support formulas + + public Ellipse(RowType row) { + + if (row.isSetDel()) + deleted = row.getDel(); + + for (CellType cell : row.getCellArray()) { + String cellName = cell.getN(); + + if (cellName.equals("X")) { + x = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("Y")) { + y = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("A")) { + a = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("B")) { + b = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("C")) { + c = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("D")) { + d = XDGFCell.parseDoubleValue(cell); + } else { + throw new POIXMLException("Invalid cell '" + cellName + + "' in Ellipse row"); + } + } + } + + public boolean getDel() { + if (deleted != null) + return deleted; + + if (_master != null) + return _master.getDel(); + + return false; + } + + public Double getX() { + return x == null ? _master.x : x; + } + + public Double getY() { + return y == null ? _master.y : y; + } + + public Double getA() { + return a == null ? _master.a : a; + } + + public Double getB() { + return b == null ? _master.b : b; + } + + public Double getC() { + return c == null ? _master.c : c; + } + + public Double getD() { + return d == null ? _master.d : d; + } + + @Override + public void setupMaster(GeometryRow row) { + _master = (Ellipse) row; + } + + public Path2D.Double getPath() { + + if (getDel()) + return null; + + // intentionally shadowing variables here + double cx = getX(); // center + double cy = getY(); + double a = getA(); // left + double b = getB(); + double c = getC(); // top + double d = getD(); + + // compute radius + double rx = Math.hypot(a - cx, b - cy); + double ry = Math.hypot(c - cx, d - cy); + + // compute angle of ellipse + double angle = (2.0 * Math.PI + (cy > b ? 1.0 : -1.0) + * Math.acos((cx - a) / rx)) + % (2.0 * Math.PI); + + // create ellipse + Ellipse2D.Double ellipse = new Ellipse2D.Double(cx - rx, cy - ry, + rx * 2, ry * 2); + + // create a path, rotate it about its center + Path2D.Double path = new Path2D.Double(ellipse); + + AffineTransform tr = new AffineTransform(); + tr.rotate(angle, cx, cy); + path.transform(tr); + + return path; + } + + @Override + public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { + throw new POIXMLException("Ellipse elements cannot be part of a path"); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/EllipticalArcTo.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/EllipticalArcTo.java index f7b3bcadc1..02fc5aef40 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/EllipticalArcTo.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/EllipticalArcTo.java @@ -19,7 +19,6 @@ package org.apache.poi.xdgf.usermodel.section.geometry; import java.awt.geom.AffineTransform; import java.awt.geom.Arc2D; -import java.awt.geom.Path2D; import java.awt.geom.Point2D; import org.apache.poi.POIXMLException; @@ -30,202 +29,218 @@ import com.microsoft.schemas.office.visio.x2012.main.CellType; import com.microsoft.schemas.office.visio.x2012.main.RowType; public class EllipticalArcTo implements GeometryRow { - - EllipticalArcTo _master = null; - - // The x-coordinate of the ending vertex on an arc. - Double x = null; - - // The y-coordinate of the ending vertex on an arc. - Double y = null; - - // The x-coordinate of the arc's control point; a point on the arc. The - // control point is best located about halfway between the beginning and - // ending vertices of the arc. Otherwise, the arc may grow to an extreme - // size in order to pass through the control point, with unpredictable - // results. - Double a = null; - - // The y-coordinate of an arc's control point. - Double b = null; - - // The angle of an arc's major axis relative to the x-axis of its parent shape. - Double c = null; - - // The ratio of an arc's major axis to its minor axis. Despite the usual - // meaning of these words, the "major" axis does not have to be greater than - // the "minor" axis, so this ratio does not have to be greater than 1. - // Setting this cell to a value less than or equal to 0 or greater than 1000 - // can lead to unpredictable results. - Double d = null; - - Boolean deleted = null; - - // TODO: support formulas - - public EllipticalArcTo(RowType row) { - - if (row.isSetDel()) deleted = row.getDel(); - - for (CellType cell: row.getCellArray()) { - String cellName = cell.getN(); - - if (cellName.equals("X")) { - x = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("Y")) { - y = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("A")) { - a = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("B")) { - b = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("C")) { - c = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("D")) { - d = XDGFCell.parseDoubleValue(cell); - } else { - throw new POIXMLException("Invalid cell '" + cellName + "' in EllipticalArcTo row"); - } - } - } - - public boolean getDel() { - if (deleted != null) - return deleted; - - if (_master != null) - return _master.getDel(); - - return false; - } - - public Double getX() { - return x == null ? _master.x : x; - } - - public Double getY() { - return y == null ? _master.y : y; - } - - public Double getA() { - return a == null ? _master.a : a; - } - - public Double getB() { - return b == null ? _master.b : b; - } - - public Double getC() { - return c == null ? _master.c : c; - } - - public Double getD() { - return d == null ? _master.d : d; - } - - - @Override - public void setupMaster(GeometryRow row) { - _master = (EllipticalArcTo) row; - } - - public static int draw = 0; - - @Override - public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { - - if (getDel()) return; - - // intentionally shadowing variables here - double x = getX(); - double y = getY(); - double a = getA(); - double b = getB(); - double c = getC(); - double d = getD(); - - createEllipticalArc(x, y, a, b, c, d, path); - } - - public static void createEllipticalArc(double x, double y, double a, double b, - double c, double d, - java.awt.geom.Path2D.Double path) { - - // Formula for center of ellipse by Junichi Yoda & nashwaan: - // -> From http://visguy.com/vgforum/index.php?topic=2464.0 - // - // x1,y1 = start; x2,y2 = end; x3,y3 = control point - // - // x0 = ((x1-x2)*(x1+x2)*(y2-y3)-(x2-x3)*(x2+x3)*(y1-y2)+D^2*(y1-y2)*(y2-y3)*(y1-y3))/(2*((x1-x2)*(y2-y3)-(x2-x3)*(y1-y2))) - // y0 = ((x1-x2)*(x2-x3)*(x1-x3)/D^2+(x2-x3)*(y1-y2)*(y1+y2)-(x1-x2)*(y2-y3)*(y2+y3))/(2*((x2-x3)*(y1-y2)-(x1-x2)*(y2-y3))) - // radii along axis: a = sqrt{ (x1-x0)^2 + (y1-y0)^2 * D^2 } - // - - Point2D last = path.getCurrentPoint(); - double x0 = last.getX(); - double y0 = last.getY(); - - // translate all of the points to the same angle as the ellipse - AffineTransform at = AffineTransform.getRotateInstance(-c); - double[] pts = new double[]{x0, y0, x, y, a, b}; - at.transform(pts, 0, pts, 0, 3); - - - x0 = pts[0]; y0 = pts[1]; - x = pts[2]; y = pts[3]; - a = pts[4]; b = pts[5]; - - // nasty math time - - double d2 = d*d; - double cx = ((x0-x)*(x0+x)*(y-b)-(x-a)*(x+a)*(y0-y)+d2*(y0-y)*(y-b)*(y0-b))/(2.0*((x0-x)*(y-b)-(x-a)*(y0-y))); - double cy = ((x0-x)*(x-a)*(x0-a)/d2+(x-a)*(y0-y)*(y0+y)-(x0-x)*(y-b)*(y+b))/(2.0*((x-a)*(y0-y)-(x0-x)*(y-b))); - - // calculate radii of ellipse - double rx = Math.sqrt(Math.pow(x0-cx, 2) + Math.pow(y0-cy,2) * d2); - double ry = rx / d; - - // Arc2D requires us to draw an arc from one point to another, so we - // need to calculate the angle of the start point and end point along the ellipse - // - Derived from parametric form of ellipse: x = h + a*cos(t); y = k + b*sin(t) - - double ctrlAngle = Math.toDegrees(Math.atan2((b-cy)/ry, (a-cx)/rx)); - double startAngle = Math.toDegrees(Math.atan2((y0-cy)/ry, (x0-cx)/rx)); - double endAngle = Math.toDegrees(Math.atan2((y-cy)/ry, (x-cx)/rx)); - - double sweep = computeSweep(startAngle, endAngle, ctrlAngle); - - // Now we have enough information to go on. Create the arc. - Arc2D arc = new Arc2D.Double(cx-rx, cy-ry, - rx*2, ry*2, -startAngle, sweep, Arc2D.OPEN); - - // rotate the arc back to the original coordinate system - at.setToRotation(c); - path.append(at.createTransformedShape(arc), false); - } - - protected static double computeSweep(double startAngle, double endAngle, double ctrlAngle) { - double sweep; - - startAngle = (360.0 + startAngle) % 360.0; - endAngle = (360.0 + endAngle) % 360.0; - ctrlAngle = (360.0 + ctrlAngle) % 360.0; - - // different sweeps depending on where the control point is - - if (startAngle < endAngle) { - if (startAngle < ctrlAngle && ctrlAngle < endAngle) { - sweep = startAngle - endAngle; - } else { - sweep = 360 + (startAngle - endAngle); - } - } else { - if (endAngle < ctrlAngle && ctrlAngle < startAngle) { - sweep = startAngle - endAngle; - } else { - sweep = - (360 - (startAngle - endAngle)); - } - } - - return sweep; - } + + EllipticalArcTo _master = null; + + // The x-coordinate of the ending vertex on an arc. + Double x = null; + + // The y-coordinate of the ending vertex on an arc. + Double y = null; + + // The x-coordinate of the arc's control point; a point on the arc. The + // control point is best located about halfway between the beginning and + // ending vertices of the arc. Otherwise, the arc may grow to an extreme + // size in order to pass through the control point, with unpredictable + // results. + Double a = null; + + // The y-coordinate of an arc's control point. + Double b = null; + + // The angle of an arc's major axis relative to the x-axis of its parent + // shape. + Double c = null; + + // The ratio of an arc's major axis to its minor axis. Despite the usual + // meaning of these words, the "major" axis does not have to be greater than + // the "minor" axis, so this ratio does not have to be greater than 1. + // Setting this cell to a value less than or equal to 0 or greater than 1000 + // can lead to unpredictable results. + Double d = null; + + Boolean deleted = null; + + // TODO: support formulas + + public EllipticalArcTo(RowType row) { + + if (row.isSetDel()) + deleted = row.getDel(); + + for (CellType cell : row.getCellArray()) { + String cellName = cell.getN(); + + if (cellName.equals("X")) { + x = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("Y")) { + y = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("A")) { + a = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("B")) { + b = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("C")) { + c = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("D")) { + d = XDGFCell.parseDoubleValue(cell); + } else { + throw new POIXMLException("Invalid cell '" + cellName + + "' in EllipticalArcTo row"); + } + } + } + + public boolean getDel() { + if (deleted != null) + return deleted; + + if (_master != null) + return _master.getDel(); + + return false; + } + + public Double getX() { + return x == null ? _master.x : x; + } + + public Double getY() { + return y == null ? _master.y : y; + } + + public Double getA() { + return a == null ? _master.a : a; + } + + public Double getB() { + return b == null ? _master.b : b; + } + + public Double getC() { + return c == null ? _master.c : c; + } + + public Double getD() { + return d == null ? _master.d : d; + } + + @Override + public void setupMaster(GeometryRow row) { + _master = (EllipticalArcTo) row; + } + + public static int draw = 0; + + @Override + public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { + + if (getDel()) + return; + + // intentionally shadowing variables here + double x = getX(); + double y = getY(); + double a = getA(); + double b = getB(); + double c = getC(); + double d = getD(); + + createEllipticalArc(x, y, a, b, c, d, path); + } + + public static void createEllipticalArc(double x, double y, double a, + double b, double c, double d, java.awt.geom.Path2D.Double path) { + + // Formula for center of ellipse by Junichi Yoda & nashwaan: + // -> From http://visguy.com/vgforum/index.php?topic=2464.0 + // + // x1,y1 = start; x2,y2 = end; x3,y3 = control point + // + // x0 = + // ((x1-x2)*(x1+x2)*(y2-y3)-(x2-x3)*(x2+x3)*(y1-y2)+D^2*(y1-y2)*(y2-y3)*(y1-y3))/(2*((x1-x2)*(y2-y3)-(x2-x3)*(y1-y2))) + // y0 = + // ((x1-x2)*(x2-x3)*(x1-x3)/D^2+(x2-x3)*(y1-y2)*(y1+y2)-(x1-x2)*(y2-y3)*(y2+y3))/(2*((x2-x3)*(y1-y2)-(x1-x2)*(y2-y3))) + // radii along axis: a = sqrt{ (x1-x0)^2 + (y1-y0)^2 * D^2 } + // + + Point2D last = path.getCurrentPoint(); + double x0 = last.getX(); + double y0 = last.getY(); + + // translate all of the points to the same angle as the ellipse + AffineTransform at = AffineTransform.getRotateInstance(-c); + double[] pts = new double[] { x0, y0, x, y, a, b }; + at.transform(pts, 0, pts, 0, 3); + + x0 = pts[0]; + y0 = pts[1]; + x = pts[2]; + y = pts[3]; + a = pts[4]; + b = pts[5]; + + // nasty math time + + double d2 = d * d; + double cx = ((x0 - x) * (x0 + x) * (y - b) - (x - a) * (x + a) + * (y0 - y) + d2 * (y0 - y) * (y - b) * (y0 - b)) + / (2.0 * ((x0 - x) * (y - b) - (x - a) * (y0 - y))); + double cy = ((x0 - x) * (x - a) * (x0 - a) / d2 + (x - a) * (y0 - y) + * (y0 + y) - (x0 - x) * (y - b) * (y + b)) + / (2.0 * ((x - a) * (y0 - y) - (x0 - x) * (y - b))); + + // calculate radii of ellipse + double rx = Math.sqrt(Math.pow(x0 - cx, 2) + Math.pow(y0 - cy, 2) * d2); + double ry = rx / d; + + // Arc2D requires us to draw an arc from one point to another, so we + // need to calculate the angle of the start point and end point along + // the ellipse + // - Derived from parametric form of ellipse: x = h + a*cos(t); y = k + + // b*sin(t) + + double ctrlAngle = Math.toDegrees(Math.atan2((b - cy) / ry, (a - cx) + / rx)); + double startAngle = Math.toDegrees(Math.atan2((y0 - cy) / ry, (x0 - cx) + / rx)); + double endAngle = Math.toDegrees(Math.atan2((y - cy) / ry, (x - cx) + / rx)); + + double sweep = computeSweep(startAngle, endAngle, ctrlAngle); + + // Now we have enough information to go on. Create the arc. + Arc2D arc = new Arc2D.Double(cx - rx, cy - ry, rx * 2, ry * 2, + -startAngle, sweep, Arc2D.OPEN); + + // rotate the arc back to the original coordinate system + at.setToRotation(c); + path.append(at.createTransformedShape(arc), false); + } + + protected static double computeSweep(double startAngle, double endAngle, + double ctrlAngle) { + double sweep; + + startAngle = (360.0 + startAngle) % 360.0; + endAngle = (360.0 + endAngle) % 360.0; + ctrlAngle = (360.0 + ctrlAngle) % 360.0; + + // different sweeps depending on where the control point is + + if (startAngle < endAngle) { + if (startAngle < ctrlAngle && ctrlAngle < endAngle) { + sweep = startAngle - endAngle; + } else { + sweep = 360 + (startAngle - endAngle); + } + } else { + if (endAngle < ctrlAngle && ctrlAngle < startAngle) { + sweep = startAngle - endAngle; + } else { + sweep = -(360 - (startAngle - endAngle)); + } + } + + return sweep; + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/GeometryRow.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/GeometryRow.java index fcd488f3b7..8ffaef26f4 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/GeometryRow.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/GeometryRow.java @@ -21,11 +21,10 @@ import java.awt.geom.Path2D; import org.apache.poi.xdgf.usermodel.XDGFShape; - public interface GeometryRow { - - public void setupMaster(GeometryRow row); - public void addToPath(Path2D.Double path, XDGFShape parent); - + public void setupMaster(GeometryRow row); + + public void addToPath(Path2D.Double path, XDGFShape parent); + } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/GeometryRowFactory.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/GeometryRowFactory.java index 57e21d1907..50e85e878e 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/GeometryRowFactory.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/GeometryRowFactory.java @@ -24,34 +24,38 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType; public class GeometryRowFactory { - static final ObjectFactory<GeometryRow, RowType> _rowTypes; - - static { - _rowTypes = new ObjectFactory<>(); - try { - _rowTypes.put("ArcTo", ArcTo.class, RowType.class); - _rowTypes.put("Ellipse", Ellipse.class, RowType.class); - _rowTypes.put("EllipticalArcTo", EllipticalArcTo.class, RowType.class); - _rowTypes.put("InfiniteLine", InfiniteLine.class, RowType.class); - _rowTypes.put("LineTo", LineTo.class, RowType.class); - _rowTypes.put("MoveTo", MoveTo.class, RowType.class); - _rowTypes.put("NURBSTo", NURBSTo.class, RowType.class); - _rowTypes.put("PolyLineTo", PolyLineTo.class, RowType.class); - _rowTypes.put("RelCubBezTo", RelCubBezTo.class, RowType.class); - _rowTypes.put("RelEllipticalArcTo", RelEllipticalArcTo.class, RowType.class); - _rowTypes.put("RelLineTo", RelLineTo.class, RowType.class); - _rowTypes.put("RelMoveTo", RelMoveTo.class, RowType.class); - _rowTypes.put("RelQuadBezTo", RelQuadBezTo.class, RowType.class); - _rowTypes.put("SplineKnot", SplineKnot.class, RowType.class); - _rowTypes.put("SplineStart", SplineStart.class, RowType.class); - } catch (NoSuchMethodException | SecurityException e) { - throw new POIXMLException("Internal error", e); - } - - } - - public static GeometryRow load(RowType row) { - return _rowTypes.load(row.getT(), row); - } - + static final ObjectFactory<GeometryRow, RowType> _rowTypes; + + static { + _rowTypes = new ObjectFactory<GeometryRow, RowType>(); + try { + _rowTypes.put("ArcTo", ArcTo.class, RowType.class); + _rowTypes.put("Ellipse", Ellipse.class, RowType.class); + _rowTypes.put("EllipticalArcTo", EllipticalArcTo.class, + RowType.class); + _rowTypes.put("InfiniteLine", InfiniteLine.class, RowType.class); + _rowTypes.put("LineTo", LineTo.class, RowType.class); + _rowTypes.put("MoveTo", MoveTo.class, RowType.class); + _rowTypes.put("NURBSTo", NURBSTo.class, RowType.class); + _rowTypes.put("PolyLineTo", PolyLineTo.class, RowType.class); + _rowTypes.put("RelCubBezTo", RelCubBezTo.class, RowType.class); + _rowTypes.put("RelEllipticalArcTo", RelEllipticalArcTo.class, + RowType.class); + _rowTypes.put("RelLineTo", RelLineTo.class, RowType.class); + _rowTypes.put("RelMoveTo", RelMoveTo.class, RowType.class); + _rowTypes.put("RelQuadBezTo", RelQuadBezTo.class, RowType.class); + _rowTypes.put("SplineKnot", SplineKnot.class, RowType.class); + _rowTypes.put("SplineStart", SplineStart.class, RowType.class); + } catch (NoSuchMethodException e) { + throw new POIXMLException("Internal error", e); + } catch (SecurityException e) { + throw new POIXMLException("Internal error", e); + } + + } + + public static GeometryRow load(RowType row) { + return _rowTypes.load(row.getT(), row); + } + } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/InfiniteLine.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/InfiniteLine.java index 584acb8f50..6965c1b89f 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/InfiniteLine.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/InfiniteLine.java @@ -18,14 +18,9 @@ package org.apache.poi.xdgf.usermodel.section.geometry; import java.awt.geom.Path2D; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; import org.apache.poi.POIXMLException; -import org.apache.poi.xdgf.geom.Dimension2dDouble; import org.apache.poi.xdgf.usermodel.XDGFCell; -import org.apache.poi.xdgf.usermodel.XDGFDocument; -import org.apache.poi.xdgf.usermodel.XDGFPage; import org.apache.poi.xdgf.usermodel.XDGFShape; import com.microsoft.schemas.office.visio.x2012.main.CellType; @@ -35,117 +30,125 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType; * Contains the x- and y-coordinates of two points on an infinite line. */ public class InfiniteLine implements GeometryRow { - - InfiniteLine _master = null; - - // An x-coordinate of a point on the infinite line; paired with y-coordinate represented by the Y cell. - Double x = null; - - // A y-coordinate of a point on the infinite line; paired with x-coordinate represented by the X cell. - Double y = null; - - // An x-coordinate of a point on the infinite line; paired with y-coordinate represented by the B cell. - Double a = null; - - // A y-coordinate of a point on an infinite line; paired with x-coordinate represented by the A cell. - Double b = null; - - Boolean deleted = null; - - // TODO: support formulas - - public InfiniteLine(RowType row) { - - if (row.isSetDel()) deleted = row.getDel(); - - for (CellType cell: row.getCellArray()) { - String cellName = cell.getN(); - - if (cellName.equals("X")) { - x = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("Y")) { - y = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("A")) { - a = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("B")) { - b = XDGFCell.parseDoubleValue(cell); - } else { - throw new POIXMLException("Invalid cell '" + cellName + "' in InfiniteLine row"); - } - } - } - - public boolean getDel() { - if (deleted != null) - return deleted; - - if (_master != null) - return _master.getDel(); - - return false; - } - - public Double getX() { - return x == null ? _master.x : x; - } - - public Double getY() { - return y == null ? _master.y : y; - } - - public Double getA() { - return a == null ? _master.a : a; - } - - public Double getB() { - return b == null ? _master.b : b; - } - - @Override - public void setupMaster(GeometryRow row) { - _master = (InfiniteLine) row; - } - - @Override - public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { - - if (getDel()) return; - - throw new POIXMLException("InfiniteLine elements cannot be part of a path"); - } - - // returns this object as a line that extends between the boundaries of - // the document - public Path2D.Double getPath() { - Path2D.Double path = new Path2D.Double(); - - // this is a bit of a hack, but it works - double max_val = 100000; - - // compute slope.. - double x0 = getX(); - double y0 = getY(); - double x1 = getA(); // second x - double y1 = getB(); // second y - - if (x0 == x1) { - path.moveTo(x0, -max_val); - path.lineTo(x0, max_val); - } else if (y0 == y1) { - path.moveTo(-max_val, y0); - path.lineTo(max_val, y0); - } else { - - // normal case: compute slope/intercept - double m = (y1 - y0) / (x1 - x0); - double c = y0 - m*x0; - - // y = mx + c - - path.moveTo(max_val, m*max_val + c); - path.lineTo(max_val, (max_val - c)/m); - } - - return path; - } + + InfiniteLine _master = null; + + // An x-coordinate of a point on the infinite line; paired with y-coordinate + // represented by the Y cell. + Double x = null; + + // A y-coordinate of a point on the infinite line; paired with x-coordinate + // represented by the X cell. + Double y = null; + + // An x-coordinate of a point on the infinite line; paired with y-coordinate + // represented by the B cell. + Double a = null; + + // A y-coordinate of a point on an infinite line; paired with x-coordinate + // represented by the A cell. + Double b = null; + + Boolean deleted = null; + + // TODO: support formulas + + public InfiniteLine(RowType row) { + + if (row.isSetDel()) + deleted = row.getDel(); + + for (CellType cell : row.getCellArray()) { + String cellName = cell.getN(); + + if (cellName.equals("X")) { + x = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("Y")) { + y = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("A")) { + a = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("B")) { + b = XDGFCell.parseDoubleValue(cell); + } else { + throw new POIXMLException("Invalid cell '" + cellName + + "' in InfiniteLine row"); + } + } + } + + public boolean getDel() { + if (deleted != null) + return deleted; + + if (_master != null) + return _master.getDel(); + + return false; + } + + public Double getX() { + return x == null ? _master.x : x; + } + + public Double getY() { + return y == null ? _master.y : y; + } + + public Double getA() { + return a == null ? _master.a : a; + } + + public Double getB() { + return b == null ? _master.b : b; + } + + @Override + public void setupMaster(GeometryRow row) { + _master = (InfiniteLine) row; + } + + @Override + public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { + + if (getDel()) + return; + + throw new POIXMLException( + "InfiniteLine elements cannot be part of a path"); + } + + // returns this object as a line that extends between the boundaries of + // the document + public Path2D.Double getPath() { + Path2D.Double path = new Path2D.Double(); + + // this is a bit of a hack, but it works + double max_val = 100000; + + // compute slope.. + double x0 = getX(); + double y0 = getY(); + double x1 = getA(); // second x + double y1 = getB(); // second y + + if (x0 == x1) { + path.moveTo(x0, -max_val); + path.lineTo(x0, max_val); + } else if (y0 == y1) { + path.moveTo(-max_val, y0); + path.lineTo(max_val, y0); + } else { + + // normal case: compute slope/intercept + double m = (y1 - y0) / (x1 - x0); + double c = y0 - m * x0; + + // y = mx + c + + path.moveTo(max_val, m * max_val + c); + path.lineTo(max_val, (max_val - c) / m); + } + + return path; + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/LineTo.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/LineTo.java index e3bfe627bc..93857f09bd 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/LineTo.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/LineTo.java @@ -26,63 +26,66 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType; public class LineTo implements GeometryRow { - LineTo _master = null; - - Double x = null; - Double y = null; - - Boolean deleted = null; - - // TODO: support formulas - - public LineTo(RowType row) { - - if (row.isSetDel()) deleted = row.getDel(); - - for (CellType cell: row.getCellArray()) { - String cellName = cell.getN(); - - if (cellName.equals("X")) { - x = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("Y")) { - y = XDGFCell.parseDoubleValue(cell); - } else { - throw new POIXMLException("Invalid cell '" + cellName + "' in LineTo row"); - } - } - } - - @Override - public String toString() { - return "LineTo: x=" + getX() + "; y=" + getY(); - } - - public boolean getDel() { - if (deleted != null) - return deleted; - - if (_master != null) - return _master.getDel(); - - return false; - } - - public Double getX() { - return x == null ? _master.x : x; - } - - public Double getY() { - return y == null ? _master.y : y; - } - - @Override - public void setupMaster(GeometryRow row) { - _master = (LineTo) row; - } - - @Override - public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { - if (getDel()) return; - path.lineTo(getX(), getY()); - } + LineTo _master = null; + + Double x = null; + Double y = null; + + Boolean deleted = null; + + // TODO: support formulas + + public LineTo(RowType row) { + + if (row.isSetDel()) + deleted = row.getDel(); + + for (CellType cell : row.getCellArray()) { + String cellName = cell.getN(); + + if (cellName.equals("X")) { + x = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("Y")) { + y = XDGFCell.parseDoubleValue(cell); + } else { + throw new POIXMLException("Invalid cell '" + cellName + + "' in LineTo row"); + } + } + } + + @Override + public String toString() { + return "LineTo: x=" + getX() + "; y=" + getY(); + } + + public boolean getDel() { + if (deleted != null) + return deleted; + + if (_master != null) + return _master.getDel(); + + return false; + } + + public Double getX() { + return x == null ? _master.x : x; + } + + public Double getY() { + return y == null ? _master.y : y; + } + + @Override + public void setupMaster(GeometryRow row) { + _master = (LineTo) row; + } + + @Override + public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { + if (getDel()) + return; + path.lineTo(getX(), getY()); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/MoveTo.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/MoveTo.java index fa704c821e..6dca12b2be 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/MoveTo.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/MoveTo.java @@ -30,64 +30,67 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType; * the height and width of the shape. */ public class MoveTo implements GeometryRow { - - MoveTo _master = null; - - Double x = null; - Double y = null; - - Boolean deleted = null; - - // TODO: support formulas - - public MoveTo(RowType row) { - - if (row.isSetDel()) deleted = row.getDel(); - - for (CellType cell: row.getCellArray()) { - String cellName = cell.getN(); - - if (cellName.equals("X")) { - x = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("Y")) { - y = XDGFCell.parseDoubleValue(cell); - } else { - throw new POIXMLException("Invalid cell '" + cellName + "' in MoveTo row"); - } - } - } - - @Override - public String toString() { - return "MoveTo: x=" + getX() + "; y=" + getY(); - } - - public boolean getDel() { - if (deleted != null) - return deleted; - - if (_master != null) - return _master.getDel(); - - return false; - } - - public Double getX() { - return x == null ? _master.x : x; - } - - public Double getY() { - return y == null ? _master.y : y; - } - - @Override - public void setupMaster(GeometryRow row) { - _master = (MoveTo) row; - } - - @Override - public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { - if (getDel()) return; - path.moveTo(getX(), getY()); - } + + MoveTo _master = null; + + Double x = null; + Double y = null; + + Boolean deleted = null; + + // TODO: support formulas + + public MoveTo(RowType row) { + + if (row.isSetDel()) + deleted = row.getDel(); + + for (CellType cell : row.getCellArray()) { + String cellName = cell.getN(); + + if (cellName.equals("X")) { + x = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("Y")) { + y = XDGFCell.parseDoubleValue(cell); + } else { + throw new POIXMLException("Invalid cell '" + cellName + + "' in MoveTo row"); + } + } + } + + @Override + public String toString() { + return "MoveTo: x=" + getX() + "; y=" + getY(); + } + + public boolean getDel() { + if (deleted != null) + return deleted; + + if (_master != null) + return _master.getDel(); + + return false; + } + + public Double getX() { + return x == null ? _master.x : x; + } + + public Double getY() { + return y == null ? _master.y : y; + } + + @Override + public void setupMaster(GeometryRow row) { + _master = (MoveTo) row; + } + + @Override + public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { + if (getDel()) + return; + path.moveTo(getX(), getY()); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/NURBSTo.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/NURBSTo.java index 39165238e4..c235f4843b 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/NURBSTo.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/NURBSTo.java @@ -20,186 +20,192 @@ package org.apache.poi.xdgf.usermodel.section.geometry; import java.awt.geom.Point2D; import org.apache.poi.POIXMLException; +import org.apache.poi.ss.formula.functions.LookupUtils.ValueVector; import org.apache.poi.xdgf.geom.SplineRenderer; import org.apache.poi.xdgf.usermodel.XDGFCell; import org.apache.poi.xdgf.usermodel.XDGFShape; -import com.graphbuilder.curve.ControlPath; -import com.graphbuilder.curve.ShapeMultiPath; -import com.graphbuilder.curve.ValueVector; -import com.graphbuilder.geom.PointFactory; import com.microsoft.schemas.office.visio.x2012.main.CellType; import com.microsoft.schemas.office.visio.x2012.main.RowType; public class NURBSTo implements GeometryRow { - - NURBSTo _master = null; - - // The x-coordinate of the last control point of a NURBS. - Double x = null; - - // The y-coordinate of the last control point of a NURBS. - Double y = null; - - // The second to the last knot of the NURBS. - Double a = null; - - // The last weight of the NURBS. - Double b = null; - - // The first knot of the NURBS. - Double c = null; - - // The first weight of the NURBS. - Double d = null; - - // A NURBS formula. - String e = null; - - Boolean deleted = null; - - // TODO: support formulas - - public NURBSTo(RowType row) { - - if (row.isSetDel()) deleted = row.getDel(); - - for (CellType cell: row.getCellArray()) { - String cellName = cell.getN(); - - if (cellName.equals("X")) { - x = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("Y")) { - y = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("A")) { - a = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("B")) { - b = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("C")) { - c = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("D")) { - d = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("E")) { - e = cell.getV(); - } else { - throw new POIXMLException("Invalid cell '" + cellName + "' in NURBS row"); - } - } - } - - public boolean getDel() { - if (deleted != null) - return deleted; - - if (_master != null) - return _master.getDel(); - - return false; - } - - public Double getX() { - return x == null ? _master.x : x; - } - - public Double getY() { - return y == null ? _master.y : y; - } - - public Double getA() { - return a == null ? _master.a : a; - } - - public Double getB() { - return b == null ? _master.b : b; - } - - public Double getC() { - return c == null ? _master.c : c; - } - - public Double getD() { - return d == null ? _master.d : d; - } - - public String getE() { - return e == null ? _master.e : e; - } - - @Override - public void setupMaster(GeometryRow row) { - _master = (NURBSTo) row; - } - - @Override - public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { - if (getDel()) return; - - Point2D last = path.getCurrentPoint(); - - // A NURBS formula: knotLast, degree, xType, yType, x1, y1, knot1, weight1, .. - String formula = getE().trim(); - if (!formula.startsWith("NURBS(") || !formula.endsWith(")")) - throw new POIXMLException("Invalid NURBS formula: " + formula); - - String [] components = formula.substring(6, formula.length()-1).split(","); - - if (components.length < 8) - throw new POIXMLException("Invalid NURBS formula (not enough arguments)"); - - if ((components.length - 4) % 4 != 0) - throw new POIXMLException("Invalid NURBS formula -- need 4 + n*4 arguments, got " + components.length); - - double lastControlX = getX(); - double lastControlY = getY(); - double secondToLastKnot = getA(); - double lastWeight = getB(); - double firstKnot = getC(); - double firstWeight = getD(); - - double lastKnot = Double.parseDouble(components[0].trim()); - int degree = Integer.parseInt(components[1].trim()); - int xType = Integer.parseInt(components[2].trim()); - int yType = Integer.parseInt(components[3].trim()); - - double xScale = 1; - double yScale = 1; - - if (xType == 0) - xScale = parent.getWidth(); - if (yType == 0) - yScale = parent.getHeight(); - - // setup first knots/weights/control point - ControlPath controlPath = new ControlPath(); - ValueVector knots = new ValueVector(); - ValueVector weights = new ValueVector(); - - knots.add(firstKnot); - weights.add(firstWeight); - controlPath.addPoint(PointFactory.create(last.getX(), last.getY())); - - // iterate get knots/weights - int sets = (components.length - 4) / 4; - for (int i = 0; i < sets; i++) { - double x1 = Double.parseDouble(components[4 + i*4 + 0].trim()); - double y1 = Double.parseDouble(components[4 + i*4 + 1].trim()); - double k = Double.parseDouble(components[4 + i*4 + 2].trim()); - double w = Double.parseDouble(components[4 + i*4 + 3].trim()); - - controlPath.addPoint(PointFactory.create(x1*xScale, y1*yScale)); - knots.add(k); - weights.add(w); - } - - // last knots/weights/control point - knots.add(secondToLastKnot); - knots.add(lastKnot); - - weights.add(lastWeight); - - controlPath.addPoint(PointFactory.create(lastControlX, lastControlY)); - - ShapeMultiPath shape = SplineRenderer.createNurbsSpline(controlPath, knots, weights, degree); - path.append(shape, true); - } + + NURBSTo _master = null; + + // The x-coordinate of the last control point of a NURBS. + Double x = null; + + // The y-coordinate of the last control point of a NURBS. + Double y = null; + + // The second to the last knot of the NURBS. + Double a = null; + + // The last weight of the NURBS. + Double b = null; + + // The first knot of the NURBS. + Double c = null; + + // The first weight of the NURBS. + Double d = null; + + // A NURBS formula. + String e = null; + + Boolean deleted = null; + + // TODO: support formulas + + public NURBSTo(RowType row) { + + if (row.isSetDel()) + deleted = row.getDel(); + + for (CellType cell : row.getCellArray()) { + String cellName = cell.getN(); + + if (cellName.equals("X")) { + x = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("Y")) { + y = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("A")) { + a = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("B")) { + b = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("C")) { + c = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("D")) { + d = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("E")) { + e = cell.getV(); + } else { + throw new POIXMLException("Invalid cell '" + cellName + + "' in NURBS row"); + } + } + } + + public boolean getDel() { + if (deleted != null) + return deleted; + + if (_master != null) + return _master.getDel(); + + return false; + } + + public Double getX() { + return x == null ? _master.x : x; + } + + public Double getY() { + return y == null ? _master.y : y; + } + + public Double getA() { + return a == null ? _master.a : a; + } + + public Double getB() { + return b == null ? _master.b : b; + } + + public Double getC() { + return c == null ? _master.c : c; + } + + public Double getD() { + return d == null ? _master.d : d; + } + + public String getE() { + return e == null ? _master.e : e; + } + + @Override + public void setupMaster(GeometryRow row) { + _master = (NURBSTo) row; + } + + @Override + public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { + if (getDel()) + return; + + Point2D last = path.getCurrentPoint(); + + // A NURBS formula: knotLast, degree, xType, yType, x1, y1, knot1, + // weight1, .. + String formula = getE().trim(); + if (!formula.startsWith("NURBS(") || !formula.endsWith(")")) + throw new POIXMLException("Invalid NURBS formula: " + formula); + + String[] components = formula.substring(6, formula.length() - 1).split( + ","); + + if (components.length < 8) + throw new POIXMLException( + "Invalid NURBS formula (not enough arguments)"); + + if ((components.length - 4) % 4 != 0) + throw new POIXMLException( + "Invalid NURBS formula -- need 4 + n*4 arguments, got " + + components.length); + + double lastControlX = getX(); + double lastControlY = getY(); + double secondToLastKnot = getA(); + double lastWeight = getB(); + double firstKnot = getC(); + double firstWeight = getD(); + + double lastKnot = Double.parseDouble(components[0].trim()); + int degree = Integer.parseInt(components[1].trim()); + int xType = Integer.parseInt(components[2].trim()); + int yType = Integer.parseInt(components[3].trim()); + + double xScale = 1; + double yScale = 1; + + if (xType == 0) + xScale = parent.getWidth(); + if (yType == 0) + yScale = parent.getHeight(); + + // setup first knots/weights/control point + ControlPath controlPath = new ControlPath(); + ValueVector knots = new ValueVector(); + ValueVector weights = new ValueVector(); + + knots.add(firstKnot); + weights.add(firstWeight); + controlPath.addPoint(PointFactory.create(last.getX(), last.getY())); + + // iterate get knots/weights + int sets = (components.length - 4) / 4; + for (int i = 0; i < sets; i++) { + double x1 = Double.parseDouble(components[4 + i * 4 + 0].trim()); + double y1 = Double.parseDouble(components[4 + i * 4 + 1].trim()); + double k = Double.parseDouble(components[4 + i * 4 + 2].trim()); + double w = Double.parseDouble(components[4 + i * 4 + 3].trim()); + + controlPath.addPoint(PointFactory.create(x1 * xScale, y1 * yScale)); + knots.add(k); + weights.add(w); + } + + // last knots/weights/control point + knots.add(secondToLastKnot); + knots.add(lastKnot); + + weights.add(lastWeight); + + controlPath.addPoint(PointFactory.create(lastControlX, lastControlY)); + + ShapeMultiPath shape = SplineRenderer.createNurbsSpline(controlPath, + knots, weights, degree); + path.append(shape, true); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/PolyLineTo.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/PolyLineTo.java index 7ce70d5b8c..88f7327296 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/PolyLineTo.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/PolyLineTo.java @@ -25,71 +25,74 @@ import com.microsoft.schemas.office.visio.x2012.main.CellType; import com.microsoft.schemas.office.visio.x2012.main.RowType; public class PolyLineTo implements GeometryRow { - - PolyLineTo _master = null; - - // The x-coordinate of the ending vertex of a polyline. - Double x = null; - - // The y-coordinate of the ending vertex of a polyline. - Double y = null; - - // The polyline formula - String a = null; - - Boolean deleted = null; - - // TODO: support formulas - - public PolyLineTo(RowType row) { - - if (row.isSetDel()) deleted = row.getDel(); - - for (CellType cell: row.getCellArray()) { - String cellName = cell.getN(); - - if (cellName.equals("X")) { - x = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("Y")) { - y = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("A")) { - a = cell.getV(); - } else { - throw new POIXMLException("Invalid cell '" + cellName + "' in ArcTo row"); - } - } - } - - public boolean getDel() { - if (deleted != null) - return deleted; - - if (_master != null) - return _master.getDel(); - - return false; - } - - public Double getX() { - return x == null ? _master.x : x; - } - - public Double getY() { - return y == null ? _master.y : y; - } - - public String getA() { - return a == null ? _master.a : a; - } - - @Override - public void setupMaster(GeometryRow row) { - _master = (PolyLineTo) row; - } - - @Override - public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { - if (getDel()) return; - throw new POIXMLException("Polyline support not implemented"); - } + + PolyLineTo _master = null; + + // The x-coordinate of the ending vertex of a polyline. + Double x = null; + + // The y-coordinate of the ending vertex of a polyline. + Double y = null; + + // The polyline formula + String a = null; + + Boolean deleted = null; + + // TODO: support formulas + + public PolyLineTo(RowType row) { + + if (row.isSetDel()) + deleted = row.getDel(); + + for (CellType cell : row.getCellArray()) { + String cellName = cell.getN(); + + if (cellName.equals("X")) { + x = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("Y")) { + y = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("A")) { + a = cell.getV(); + } else { + throw new POIXMLException("Invalid cell '" + cellName + + "' in ArcTo row"); + } + } + } + + public boolean getDel() { + if (deleted != null) + return deleted; + + if (_master != null) + return _master.getDel(); + + return false; + } + + public Double getX() { + return x == null ? _master.x : x; + } + + public Double getY() { + return y == null ? _master.y : y; + } + + public String getA() { + return a == null ? _master.a : a; + } + + @Override + public void setupMaster(GeometryRow row) { + _master = (PolyLineTo) row; + } + + @Override + public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { + if (getDel()) + return; + throw new POIXMLException("Polyline support not implemented"); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelCubBezTo.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelCubBezTo.java index 4b0ad4781a..3a419bb506 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelCubBezTo.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelCubBezTo.java @@ -25,103 +25,115 @@ import com.microsoft.schemas.office.visio.x2012.main.CellType; import com.microsoft.schemas.office.visio.x2012.main.RowType; public class RelCubBezTo implements GeometryRow { - - RelCubBezTo _master = null; - - // The x-coordinate of the ending vertex of a cubic Bézier curve relative to the width of the shape. - Double x = null; - - // The y-coordinate of the ending vertex of a cubic Bézier curve relative to the height of the shape. - Double y = null; - - // The x-coordinate of the curve’s beginning control point relative to the shape’s width; a point on the arc. The control point is best located between the beginning and ending vertices of the arc. - Double a = null; - - // The y-coordinate of a curve’s beginning control point relative to the shape’s height. - Double b = null; - - // The x-coordinate of the curve’s ending control point relative to the shape’s width; a point on the arc. The control point is best located between the beginning control point and ending vertices of the arc. - Double c = null; - - // The y-coordinate of a curve's ending control point relative to the shape’s height. - Double d = null; - - Boolean deleted = null; - - // TODO: support formulas - - public RelCubBezTo(RowType row) { - - if (row.isSetDel()) deleted = row.getDel(); - - for (CellType cell: row.getCellArray()) { - String cellName = cell.getN(); - - if (cellName.equals("X")) { - x = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("Y")) { - y = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("A")) { - a = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("B")) { - b = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("C")) { - c = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("D")) { - d = XDGFCell.parseDoubleValue(cell); - } else { - throw new POIXMLException("Invalid cell '" + cellName + "' in RelCubBezTo row"); - } - } - } - - public boolean getDel() { - if (deleted != null) - return deleted; - - if (_master != null) - return _master.getDel(); - - return false; - } - - public Double getX() { - return x == null ? _master.x : x; - } - - public Double getY() { - return y == null ? _master.y : y; - } - - public Double getA() { - return a == null ? _master.a : a; - } - - public Double getB() { - return b == null ? _master.b : b; - } - - public Double getC() { - return c == null ? _master.c : c; - } - - public Double getD() { - return d == null ? _master.d : d; - } - - @Override - public void setupMaster(GeometryRow row) { - _master = (RelCubBezTo) row; - } - - @Override - public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { - - if (getDel()) return; - - double w = parent.getWidth(); - double h = parent.getHeight(); - - path.curveTo(getA()*w, getB()*h, getC()*w, getD()*h, getX()*w, getY()*h); - } + + RelCubBezTo _master = null; + + // The x-coordinate of the ending vertex of a cubic Bezier curve relative to + // the width of the shape. + Double x = null; + + // The y-coordinate of the ending vertex of a cubic Bezier curve relative to + // the height of the shape. + Double y = null; + + // The x-coordinate of the curve's beginning control point relative to the + // shape's width; a point on the arc. The control point is best located + // between the beginning and ending vertices of the arc. + Double a = null; + + // The y-coordinate of a curve's beginning control point relative to the + // shape's height. + Double b = null; + + // The x-coordinate of the curve's ending control point relative to the + // shape's width; a point on the arc. The control point is best located + // between the beginning control point and ending vertices of the arc. + Double c = null; + + // The y-coordinate of a curve's ending control point relative to the + // shape's height. + Double d = null; + + Boolean deleted = null; + + // TODO: support formulas + + public RelCubBezTo(RowType row) { + + if (row.isSetDel()) + deleted = row.getDel(); + + for (CellType cell : row.getCellArray()) { + String cellName = cell.getN(); + + if (cellName.equals("X")) { + x = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("Y")) { + y = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("A")) { + a = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("B")) { + b = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("C")) { + c = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("D")) { + d = XDGFCell.parseDoubleValue(cell); + } else { + throw new POIXMLException("Invalid cell '" + cellName + + "' in RelCubBezTo row"); + } + } + } + + public boolean getDel() { + if (deleted != null) + return deleted; + + if (_master != null) + return _master.getDel(); + + return false; + } + + public Double getX() { + return x == null ? _master.x : x; + } + + public Double getY() { + return y == null ? _master.y : y; + } + + public Double getA() { + return a == null ? _master.a : a; + } + + public Double getB() { + return b == null ? _master.b : b; + } + + public Double getC() { + return c == null ? _master.c : c; + } + + public Double getD() { + return d == null ? _master.d : d; + } + + @Override + public void setupMaster(GeometryRow row) { + _master = (RelCubBezTo) row; + } + + @Override + public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { + + if (getDel()) + return; + + double w = parent.getWidth(); + double h = parent.getHeight(); + + path.curveTo(getA() * w, getB() * h, getC() * w, getD() * h, + getX() * w, getY() * h); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelEllipticalArcTo.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelEllipticalArcTo.java index 99ae22b3e6..9b58406cdc 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelEllipticalArcTo.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelEllipticalArcTo.java @@ -25,117 +25,120 @@ import com.microsoft.schemas.office.visio.x2012.main.CellType; import com.microsoft.schemas.office.visio.x2012.main.RowType; public class RelEllipticalArcTo implements GeometryRow { - - RelEllipticalArcTo _master = null; - - // The x-coordinate of the ending vertex on an arc relative to the width of - // the shape. - Double x = null; - - // The y-coordinate of the ending vertex on an arc relative to the height of - // the shape. - Double y = null; - - // The x-coordinate of the arc's control point relative to the shape’s - // width; a point on the arc. - Double a = null; - - // The y-coordinate of an arc's control point relative to the shape’s width. - Double b = null; - - // The angle of an arc's major axis relative to the x-axis of its parent. - Double c = null; - - // The ratio of an arc's major axis to its minor axis. Despite the usual - // meaning of these words, the "major" axis does not have to be greater than - // the "minor" axis, so this ratio does not have to be greater than 1. - Double d = null; - - Boolean deleted = null; - - // TODO: support formulas - - public RelEllipticalArcTo(RowType row) { - - if (row.isSetDel()) deleted = row.getDel(); - - for (CellType cell: row.getCellArray()) { - String cellName = cell.getN(); - - if (cellName.equals("X")) { - x = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("Y")) { - y = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("A")) { - a = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("B")) { - b = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("C")) { - c = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("D")) { - d = XDGFCell.parseDoubleValue(cell); - } else { - throw new POIXMLException("Invalid cell '" + cellName + "' in RelEllipticalArcTo row"); - } - } - } - - public boolean getDel() { - if (deleted != null) - return deleted; - - if (_master != null) - return _master.getDel(); - - return false; - } - - public Double getX() { - return x == null ? _master.x : x; - } - - public Double getY() { - return y == null ? _master.y : y; - } - - public Double getA() { - return a == null ? _master.a : a; - } - - public Double getB() { - return b == null ? _master.b : b; - } - - public Double getC() { - return c == null ? _master.c : c; - } - - public Double getD() { - return d == null ? _master.d : d; - } - - @Override - public void setupMaster(GeometryRow row) { - _master = (RelEllipticalArcTo) row; - } - - @Override - public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { - - if (getDel()) return; - - double w = parent.getWidth(); - double h = parent.getHeight(); - - // intentionally shadowing variables here - double x = getX()*w; - double y = getY()*h; - double a = getA()*w; - double b = getB()*h; - double c = getC(); - double d = getD(); - - EllipticalArcTo.createEllipticalArc(x, y, a, b, c, d, path); - - } + + RelEllipticalArcTo _master = null; + + // The x-coordinate of the ending vertex on an arc relative to the width of + // the shape. + Double x = null; + + // The y-coordinate of the ending vertex on an arc relative to the height of + // the shape. + Double y = null; + + // The x-coordinate of the arc's control point relative to the shape's + // width; a point on the arc. + Double a = null; + + // The y-coordinate of an arc's control point relative to the shape's width. + Double b = null; + + // The angle of an arc's major axis relative to the x-axis of its parent. + Double c = null; + + // The ratio of an arc's major axis to its minor axis. Despite the usual + // meaning of these words, the "major" axis does not have to be greater than + // the "minor" axis, so this ratio does not have to be greater than 1. + Double d = null; + + Boolean deleted = null; + + // TODO: support formulas + + public RelEllipticalArcTo(RowType row) { + + if (row.isSetDel()) + deleted = row.getDel(); + + for (CellType cell : row.getCellArray()) { + String cellName = cell.getN(); + + if (cellName.equals("X")) { + x = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("Y")) { + y = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("A")) { + a = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("B")) { + b = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("C")) { + c = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("D")) { + d = XDGFCell.parseDoubleValue(cell); + } else { + throw new POIXMLException("Invalid cell '" + cellName + + "' in RelEllipticalArcTo row"); + } + } + } + + public boolean getDel() { + if (deleted != null) + return deleted; + + if (_master != null) + return _master.getDel(); + + return false; + } + + public Double getX() { + return x == null ? _master.x : x; + } + + public Double getY() { + return y == null ? _master.y : y; + } + + public Double getA() { + return a == null ? _master.a : a; + } + + public Double getB() { + return b == null ? _master.b : b; + } + + public Double getC() { + return c == null ? _master.c : c; + } + + public Double getD() { + return d == null ? _master.d : d; + } + + @Override + public void setupMaster(GeometryRow row) { + _master = (RelEllipticalArcTo) row; + } + + @Override + public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { + + if (getDel()) + return; + + double w = parent.getWidth(); + double h = parent.getHeight(); + + // intentionally shadowing variables here + double x = getX() * w; + double y = getY() * h; + double a = getA() * w; + double b = getB() * h; + double c = getC(); + double d = getD(); + + EllipticalArcTo.createEllipticalArc(x, y, a, b, c, d, path); + + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelLineTo.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelLineTo.java index e2cbeb4cdb..1886f20590 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelLineTo.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelLineTo.java @@ -26,65 +26,67 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType; /** * Contains x-and y-coordinates of the ending vertex of a straight line segment - * relative to a shape’s width and height. + * relative to a shape's width and height. */ public class RelLineTo implements GeometryRow { - - RelLineTo _master = null; - - Double x = null; - Double y = null; - - Boolean deleted = null; - - // TODO: support formulas - - public RelLineTo(RowType row) { - - if (row.isSetDel()) deleted = row.getDel(); - - for (CellType cell: row.getCellArray()) { - String cellName = cell.getN(); - - if (cellName.equals("X")) { - x = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("Y")) { - y = XDGFCell.parseDoubleValue(cell); - } else { - throw new POIXMLException("Invalid cell '" + cellName + "' in RelLineTo row"); - } - } - } - - public boolean getDel() { - if (deleted != null) - return deleted; - - if (_master != null) - return _master.getDel(); - - return false; - } - - public Double getX() { - return x == null ? _master.x : x; - } - - public Double getY() { - return y == null ? _master.y : y; - } - - @Override - public void setupMaster(GeometryRow row) { - _master = (RelLineTo) row; - } - - @Override - public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { - - if (getDel()) return; - - path.lineTo(getX()*parent.getWidth(), - getY()*parent.getHeight()); - } + + RelLineTo _master = null; + + Double x = null; + Double y = null; + + Boolean deleted = null; + + // TODO: support formulas + + public RelLineTo(RowType row) { + + if (row.isSetDel()) + deleted = row.getDel(); + + for (CellType cell : row.getCellArray()) { + String cellName = cell.getN(); + + if (cellName.equals("X")) { + x = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("Y")) { + y = XDGFCell.parseDoubleValue(cell); + } else { + throw new POIXMLException("Invalid cell '" + cellName + + "' in RelLineTo row"); + } + } + } + + public boolean getDel() { + if (deleted != null) + return deleted; + + if (_master != null) + return _master.getDel(); + + return false; + } + + public Double getX() { + return x == null ? _master.x : x; + } + + public Double getY() { + return y == null ? _master.y : y; + } + + @Override + public void setupMaster(GeometryRow row) { + _master = (RelLineTo) row; + } + + @Override + public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { + + if (getDel()) + return; + + path.lineTo(getX() * parent.getWidth(), getY() * parent.getHeight()); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelMoveTo.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelMoveTo.java index 5413e374a9..0b6f51c19c 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelMoveTo.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelMoveTo.java @@ -25,62 +25,64 @@ import com.microsoft.schemas.office.visio.x2012.main.CellType; import com.microsoft.schemas.office.visio.x2012.main.RowType; public class RelMoveTo implements GeometryRow { - - RelMoveTo _master = null; - - Double x = null; - Double y = null; - - Boolean deleted = null; - - // TODO: support formulas - - public RelMoveTo(RowType row) { - - if (row.isSetDel()) deleted = row.getDel(); - - for (CellType cell: row.getCellArray()) { - String cellName = cell.getN(); - - if (cellName.equals("X")) { - x = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("Y")) { - y = XDGFCell.parseDoubleValue(cell); - } else { - throw new POIXMLException("Invalid cell '" + cellName + "' in RelMoveTo row"); - } - } - } - - public boolean getDel() { - if (deleted != null) - return deleted; - - if (_master != null) - return _master.getDel(); - - return false; - } - - public Double getX() { - return x == null ? _master.x : x; - } - - public Double getY() { - return y == null ? _master.y : y; - } - - @Override - public void setupMaster(GeometryRow row) { - _master = (RelMoveTo) row; - } - - @Override - public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { - - if (getDel()) return; - - path.moveTo(getX()*parent.getWidth(), - getY()*parent.getHeight()); - } + + RelMoveTo _master = null; + + Double x = null; + Double y = null; + + Boolean deleted = null; + + // TODO: support formulas + + public RelMoveTo(RowType row) { + + if (row.isSetDel()) + deleted = row.getDel(); + + for (CellType cell : row.getCellArray()) { + String cellName = cell.getN(); + + if (cellName.equals("X")) { + x = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("Y")) { + y = XDGFCell.parseDoubleValue(cell); + } else { + throw new POIXMLException("Invalid cell '" + cellName + + "' in RelMoveTo row"); + } + } + } + + public boolean getDel() { + if (deleted != null) + return deleted; + + if (_master != null) + return _master.getDel(); + + return false; + } + + public Double getX() { + return x == null ? _master.x : x; + } + + public Double getY() { + return y == null ? _master.y : y; + } + + @Override + public void setupMaster(GeometryRow row) { + _master = (RelMoveTo) row; + } + + @Override + public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { + + if (getDel()) + return; + + path.moveTo(getX() * parent.getWidth(), getY() * parent.getHeight()); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelQuadBezTo.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelQuadBezTo.java index ba715b1294..ecb4a3a434 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelQuadBezTo.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/RelQuadBezTo.java @@ -25,90 +25,98 @@ import com.microsoft.schemas.office.visio.x2012.main.CellType; import com.microsoft.schemas.office.visio.x2012.main.RowType; /** - * Contains the x- and y-coordinates of the endpoint of a quadratic Bézier curve - * relative to the shape’s width and height and the x- and y-coordinates of the - * control point of the curve relative shape’s width and height. + * Contains the x- and y-coordinates of the endpoint of a quadratic Bezier curve + * relative to the shape's width and height and the x- and y-coordinates of the + * control point of the curve relative shape's width and height. */ public class RelQuadBezTo implements GeometryRow { - - RelQuadBezTo _master = null; - - // The x-coordinate of the ending vertex of a quadratic Bézier curve relative to the width of the shape. - Double x = null; - - // The y-coordinate of the ending vertex of a quadratic Bézier curve relative to the height of the shape. - Double y = null; - - // The x-coordinate of the curve’s control point relative to the shape’s width; a point on the arc. The control point is best located about halfway between the beginning and ending vertices of the arc. - Double a = null; - - // The y-coordinate of a curve’s control point relative to the shape’s height. - Double b = null; - - Boolean deleted = null; - - // TODO: support formulas - - public RelQuadBezTo(RowType row) { - - if (row.isSetDel()) deleted = row.getDel(); - - for (CellType cell: row.getCellArray()) { - String cellName = cell.getN(); - - if (cellName.equals("X")) { - x = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("Y")) { - y = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("A")) { - a = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("B")) { - b = XDGFCell.parseDoubleValue(cell); - } else { - throw new POIXMLException("Invalid cell '" + cellName + "' in RelQuadBezTo row"); - } - } - } - - public boolean getDel() { - if (deleted != null) - return deleted; - - if (_master != null) - return _master.getDel(); - - return false; - } - - public Double getX() { - return x == null ? _master.x : x; - } - - public Double getY() { - return y == null ? _master.y : y; - } - - public Double getA() { - return a == null ? _master.a : a; - } - - public Double getB() { - return b == null ? _master.b : b; - } - - @Override - public void setupMaster(GeometryRow row) { - _master = (RelQuadBezTo) row; - } - - @Override - public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { - - if (getDel()) return; - - double w = parent.getWidth(); - double h = parent.getHeight(); - - path.quadTo(getA()*w, getB()*h, getX()*w, getY()*h); - } + + RelQuadBezTo _master = null; + + // The x-coordinate of the ending vertex of a quadratic Bezier curve + // relative to the width of the shape. + Double x = null; + + // The y-coordinate of the ending vertex of a quadratic Bezier curve + // relative to the height of the shape. + Double y = null; + + // The x-coordinate of the curve's control point relative to the shape's + // width; a point on the arc. The control point is best located about + // halfway between the beginning and ending vertices of the arc. + Double a = null; + + // The y-coordinate of a curve's control point relative to the shape's + // height. + Double b = null; + + Boolean deleted = null; + + // TODO: support formulas + + public RelQuadBezTo(RowType row) { + + if (row.isSetDel()) + deleted = row.getDel(); + + for (CellType cell : row.getCellArray()) { + String cellName = cell.getN(); + + if (cellName.equals("X")) { + x = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("Y")) { + y = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("A")) { + a = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("B")) { + b = XDGFCell.parseDoubleValue(cell); + } else { + throw new POIXMLException("Invalid cell '" + cellName + + "' in RelQuadBezTo row"); + } + } + } + + public boolean getDel() { + if (deleted != null) + return deleted; + + if (_master != null) + return _master.getDel(); + + return false; + } + + public Double getX() { + return x == null ? _master.x : x; + } + + public Double getY() { + return y == null ? _master.y : y; + } + + public Double getA() { + return a == null ? _master.a : a; + } + + public Double getB() { + return b == null ? _master.b : b; + } + + @Override + public void setupMaster(GeometryRow row) { + _master = (RelQuadBezTo) row; + } + + @Override + public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { + + if (getDel()) + return; + + double w = parent.getWidth(); + double h = parent.getHeight(); + + path.quadTo(getA() * w, getB() * h, getX() * w, getY() * h); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/SplineKnot.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/SplineKnot.java index 254fae5649..f75490b073 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/SplineKnot.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/SplineKnot.java @@ -25,78 +25,82 @@ import com.microsoft.schemas.office.visio.x2012.main.CellType; import com.microsoft.schemas.office.visio.x2012.main.RowType; /** - * Contains x- and y-coordinates for a spline's control point and a spline's knot. + * Contains x- and y-coordinates for a spline's control point and a spline's + * knot. */ public class SplineKnot implements GeometryRow { - - SplineKnot _master = null; - - // The x-coordinate of a control point. - Double x = null; - - // The y-coordinate of a control point. - Double y = null; - - // One of the spline's knots (other than the last one or the first two). - Double a = null; - - Boolean deleted = null; - - // TODO: support formulas - - public SplineKnot(RowType row) { - - if (row.isSetDel()) deleted = row.getDel(); - - for (CellType cell: row.getCellArray()) { - String cellName = cell.getN(); - - if (cellName.equals("X")) { - x = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("Y")) { - y = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("A")) { - a = XDGFCell.parseDoubleValue(cell); - } else { - throw new POIXMLException("Invalid cell '" + cellName + "' in SplineKnot row"); - } - } - } - - public boolean getDel() { - if (deleted != null) - return deleted; - - if (_master != null) - return _master.getDel(); - - return false; - } - - public Double getX() { - return x == null ? _master.x : x; - } - - public Double getY() { - return y == null ? _master.y : y; - } - - public Double getA() { - return a == null ? _master.a : a; - } - - @Override - public void setupMaster(GeometryRow row) { - _master = (SplineKnot) row; - } - - @Override - public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { - throw new POIXMLException("Error: Use SplineRenderer!"); - } - - @Override - public String toString() { - return "{SplineKnot x=" + getX() + " y=" + getY() + " a=" + getA() + "}"; - } + + SplineKnot _master = null; + + // The x-coordinate of a control point. + Double x = null; + + // The y-coordinate of a control point. + Double y = null; + + // One of the spline's knots (other than the last one or the first two). + Double a = null; + + Boolean deleted = null; + + // TODO: support formulas + + public SplineKnot(RowType row) { + + if (row.isSetDel()) + deleted = row.getDel(); + + for (CellType cell : row.getCellArray()) { + String cellName = cell.getN(); + + if (cellName.equals("X")) { + x = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("Y")) { + y = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("A")) { + a = XDGFCell.parseDoubleValue(cell); + } else { + throw new POIXMLException("Invalid cell '" + cellName + + "' in SplineKnot row"); + } + } + } + + public boolean getDel() { + if (deleted != null) + return deleted; + + if (_master != null) + return _master.getDel(); + + return false; + } + + public Double getX() { + return x == null ? _master.x : x; + } + + public Double getY() { + return y == null ? _master.y : y; + } + + public Double getA() { + return a == null ? _master.a : a; + } + + @Override + public void setupMaster(GeometryRow row) { + _master = (SplineKnot) row; + } + + @Override + public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { + throw new POIXMLException("Error: Use SplineRenderer!"); + } + + @Override + public String toString() { + return "{SplineKnot x=" + getX() + " y=" + getY() + " a=" + getA() + + "}"; + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/SplineStart.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/SplineStart.java index b485eb7180..224a36c036 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/SplineStart.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/section/geometry/SplineStart.java @@ -28,105 +28,105 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType; * knot, its first knot, the last knot, and the degree of the spline. */ public class SplineStart implements GeometryRow { - - SplineStart _master = null; - - // The x-coordinate of a spline's second control point. - Double x = null; - - // The y-coordinate of a spline's second control point. - Double y = null; - - // The second knot of the spline. - Double a = null; - - // The first knot of a spline. - Double b = null; - - // The last knot of a spline. - Double c = null; - - // The degree of a spline (an integer from 1 to 25). - Integer d = null; - - Boolean deleted = null; - - // TODO: support formulas - - public SplineStart(RowType row) { - - if (row.isSetDel()) deleted = row.getDel(); - - for (CellType cell: row.getCellArray()) { - String cellName = cell.getN(); - - if (cellName.equals("X")) { - x = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("Y")) { - y = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("A")) { - a = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("B")) { - b = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("C")) { - c = XDGFCell.parseDoubleValue(cell); - } else if (cellName.equals("D")) { - d = XDGFCell.parseIntegerValue(cell); - } else { - throw new POIXMLException("Invalid cell '" + cellName + "' in SplineStart row"); - } - } - } - - public boolean getDel() { - if (deleted != null) - return deleted; - - if (_master != null) - return _master.getDel(); - - return false; - } - - public Double getX() { - return x == null ? _master.x : x; - } - - public Double getY() { - return y == null ? _master.y : y; - } - - public Double getA() { - return a == null ? _master.a : a; - } - - public Double getB() { - return b == null ? _master.b : b; - } - - public Double getC() { - return c == null ? _master.c : c; - } - - public Integer getD() { - return d == null ? _master.d : d; - } - - @Override - public void setupMaster(GeometryRow row) { - _master = (SplineStart) row; - } - - @Override - public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { - throw new POIXMLException("Error: Use SplineRenderer!"); - } - - @Override - public String toString() { - return "{SplineStart x=" + getX() + " y=" + getY() + - " a=" + getA() + " b=" + getB() + - " c=" + getC() + " d=" + getD() + - "}"; - } + + SplineStart _master = null; + + // The x-coordinate of a spline's second control point. + Double x = null; + + // The y-coordinate of a spline's second control point. + Double y = null; + + // The second knot of the spline. + Double a = null; + + // The first knot of a spline. + Double b = null; + + // The last knot of a spline. + Double c = null; + + // The degree of a spline (an integer from 1 to 25). + Integer d = null; + + Boolean deleted = null; + + // TODO: support formulas + + public SplineStart(RowType row) { + + if (row.isSetDel()) + deleted = row.getDel(); + + for (CellType cell : row.getCellArray()) { + String cellName = cell.getN(); + + if (cellName.equals("X")) { + x = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("Y")) { + y = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("A")) { + a = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("B")) { + b = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("C")) { + c = XDGFCell.parseDoubleValue(cell); + } else if (cellName.equals("D")) { + d = XDGFCell.parseIntegerValue(cell); + } else { + throw new POIXMLException("Invalid cell '" + cellName + + "' in SplineStart row"); + } + } + } + + public boolean getDel() { + if (deleted != null) + return deleted; + + if (_master != null) + return _master.getDel(); + + return false; + } + + public Double getX() { + return x == null ? _master.x : x; + } + + public Double getY() { + return y == null ? _master.y : y; + } + + public Double getA() { + return a == null ? _master.a : a; + } + + public Double getB() { + return b == null ? _master.b : b; + } + + public Double getC() { + return c == null ? _master.c : c; + } + + public Integer getD() { + return d == null ? _master.d : d; + } + + @Override + public void setupMaster(GeometryRow row) { + _master = (SplineStart) row; + } + + @Override + public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { + throw new POIXMLException("Error: Use SplineRenderer!"); + } + + @Override + public String toString() { + return "{SplineStart x=" + getX() + " y=" + getY() + " a=" + getA() + + " b=" + getB() + " c=" + getC() + " d=" + getD() + "}"; + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeDataAcceptor.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeDataAcceptor.java index 5090699783..57c9cdec93 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeDataAcceptor.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeDataAcceptor.java @@ -21,49 +21,45 @@ import org.apache.poi.xdgf.usermodel.XDGFShape; /** * This acceptor only allows traversal to shapes that have useful data - * associated with them, and tries to elide details that aren't useful - * when analyzing the content of a document. - * + * associated with them, and tries to elide details that aren't useful when + * analyzing the content of a document. + * * Useful is subjective of course, and is defined as any of: - * - * - Has non-empty text - * - Is a 1d shape, such as a line - * - User specified shapes - * - The outline of stencil objects - * - TODO + * + * - Has non-empty text - Is a 1d shape, such as a line - User specified shapes + * - The outline of stencil objects - TODO */ public class ShapeDataAcceptor implements ShapeVisitorAcceptor { - @Override - public boolean accept(XDGFShape shape) { - - if (shape.isDeleted()) - return false; - - // text is interesting - if (shape.hasText() && shape.getTextAsString().length() != 0) - return true; - - // 1d shapes are interesting, they create connections - if (shape.isShape1D()) - return true; - - // User specified shapes are interesting - if (!shape.hasMaster() && !shape.hasMasterShape()) - return true; - - if (shape.hasMaster() && !shape.hasMasterShape()) - return true; - - // include stencil content, but try to elide stencil interiors - //if (shape.getXmlObject().isSetMaster()) - // return true; - - if (shape.hasMasterShape() && shape.getMasterShape().isTopmost()) - return true; - - return false; - } - - + @Override + public boolean accept(XDGFShape shape) { + + if (shape.isDeleted()) + return false; + + // text is interesting + if (shape.hasText() && shape.getTextAsString().length() != 0) + return true; + + // 1d shapes are interesting, they create connections + if (shape.isShape1D()) + return true; + + // User specified shapes are interesting + if (!shape.hasMaster() && !shape.hasMasterShape()) + return true; + + if (shape.hasMaster() && !shape.hasMasterShape()) + return true; + + // include stencil content, but try to elide stencil interiors + // if (shape.getXmlObject().isSetMaster()) + // return true; + + if (shape.hasMasterShape() && shape.getMasterShape().isTopmost()) + return true; + + return false; + } + } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeDebuggerRenderer.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeDebuggerRenderer.java index 2f32337e96..d4a010ba26 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeDebuggerRenderer.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeDebuggerRenderer.java @@ -25,46 +25,45 @@ import org.apache.poi.xdgf.usermodel.XDGFShape; public class ShapeDebuggerRenderer extends ShapeRenderer { - ShapeVisitorAcceptor _debugAcceptor = null; - - public ShapeDebuggerRenderer() { - super(); - } - - public ShapeDebuggerRenderer(Graphics2D g) { - super(g); - } - - public void setDebugAcceptor(ShapeVisitorAcceptor acceptor) { - _debugAcceptor = acceptor; - } - - @Override - protected Path2D drawPath(XDGFShape shape){ - - Path2D path = super.drawPath(shape); - if (_debugAcceptor == null || _debugAcceptor.accept(shape)) { - - // show numbers to associate shapes with ids.. doesn't always work - Font f = _graphics.getFont(); - _graphics.scale(1, -1); - _graphics.setFont(f.deriveFont(0.05F)); - - String shapeId = "" + shape.getID(); - float shapeOffset = -0.1F; - - if (shape.hasMasterShape()) { - shapeId += " MS:" + shape.getMasterShape().getID(); - shapeOffset -= 0.15F; - } - - - _graphics.drawString(shapeId, shapeOffset, 0); - _graphics.setFont(f); - _graphics.scale(1, -1); - } - - return path; - } + ShapeVisitorAcceptor _debugAcceptor = null; + + public ShapeDebuggerRenderer() { + super(); + } + + public ShapeDebuggerRenderer(Graphics2D g) { + super(g); + } + + public void setDebugAcceptor(ShapeVisitorAcceptor acceptor) { + _debugAcceptor = acceptor; + } + + @Override + protected Path2D drawPath(XDGFShape shape) { + + Path2D path = super.drawPath(shape); + if (_debugAcceptor == null || _debugAcceptor.accept(shape)) { + + // show numbers to associate shapes with ids.. doesn't always work + Font f = _graphics.getFont(); + _graphics.scale(1, -1); + _graphics.setFont(f.deriveFont(0.05F)); + + String shapeId = "" + shape.getID(); + float shapeOffset = -0.1F; + + if (shape.hasMasterShape()) { + shapeId += " MS:" + shape.getMasterShape().getID(); + shapeOffset -= 0.15F; + } + + _graphics.drawString(shapeId, shapeOffset, 0); + _graphics.setFont(f); + _graphics.scale(1, -1); + } + + return path; + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeRenderer.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeRenderer.java index 1386368da7..a6a76642d9 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeRenderer.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeRenderer.java @@ -17,7 +17,6 @@ package org.apache.poi.xdgf.usermodel.shape; -import java.awt.BasicStroke; import java.awt.Font; import java.awt.Graphics2D; import java.awt.geom.AffineTransform; @@ -32,62 +31,64 @@ import org.apache.poi.xdgf.usermodel.XDGFText; */ public class ShapeRenderer extends ShapeVisitor { - protected Graphics2D _graphics; - - public ShapeRenderer() { - _graphics = null; - } - - public ShapeRenderer(Graphics2D g) { - _graphics = g; - } - - public void setGraphics(Graphics2D g) { - _graphics = g; - } - - @Override - public void visit(XDGFShape shape, AffineTransform globalTransform, int level) { - - AffineTransform savedTr = _graphics.getTransform(); - _graphics.transform(globalTransform); - - drawPath(shape); - drawText(shape); - - // we're done, undo the transforms - _graphics.setTransform(savedTr); - } - - protected Path2D drawPath(XDGFShape shape) { - Path2D.Double path = shape.getPath(); - if (path != null) { - - // setup the stroke for this line - - _graphics.setColor(shape.getLineColor()); - _graphics.setStroke(shape.getStroke()); - _graphics.draw(path); - } - - return path; - } - - protected void drawText(XDGFShape shape) { - XDGFText text = shape.getText(); - if (text != null) { - - if (text.getTextContent().equals("Header")) - text.getTextBounds(); - - Font oldFont = _graphics.getFont(); - - _graphics.setFont(oldFont.deriveFont(shape.getFontSize().floatValue())); - _graphics.setColor(shape.getFontColor()); - - text.draw(_graphics); - _graphics.setFont(oldFont); - } - } + protected Graphics2D _graphics; + + public ShapeRenderer() { + _graphics = null; + } + + public ShapeRenderer(Graphics2D g) { + _graphics = g; + } + + public void setGraphics(Graphics2D g) { + _graphics = g; + } + + @Override + public void visit(XDGFShape shape, AffineTransform globalTransform, + int level) { + + AffineTransform savedTr = _graphics.getTransform(); + _graphics.transform(globalTransform); + + drawPath(shape); + drawText(shape); + + // we're done, undo the transforms + _graphics.setTransform(savedTr); + } + + protected Path2D drawPath(XDGFShape shape) { + Path2D.Double path = shape.getPath(); + if (path != null) { + + // setup the stroke for this line + + _graphics.setColor(shape.getLineColor()); + _graphics.setStroke(shape.getStroke()); + _graphics.draw(path); + } + + return path; + } + + protected void drawText(XDGFShape shape) { + XDGFText text = shape.getText(); + if (text != null) { + + if (text.getTextContent().equals("Header")) + text.getTextBounds(); + + Font oldFont = _graphics.getFont(); + + _graphics.setFont(oldFont.deriveFont(shape.getFontSize() + .floatValue())); + _graphics.setColor(shape.getFontColor()); + + text.draw(_graphics); + _graphics.setFont(oldFont); + } + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeVisitor.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeVisitor.java index cf4eee15c5..8d8e6fc743 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeVisitor.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeVisitor.java @@ -23,46 +23,50 @@ import org.apache.poi.xdgf.usermodel.XDGFShape; /** * Used to iterate through shapes - * + * * To change the behavior of a particular visitor, you can override either * accept() or getAcceptor() [preferred] - * - * If accept() or visit() throw StopVisitingThisBranch, the iteration will - * not visit subshapes of the shape. + * + * If accept() or visit() throw StopVisitingThisBranch, the iteration will not + * visit subshapes of the shape. */ -public abstract class ShapeVisitor{ +public abstract class ShapeVisitor { + + ShapeVisitorAcceptor _acceptor; + + public ShapeVisitor() { + _acceptor = getAcceptor(); + } + + // is only called on construction of the visitor, allows + // mixing visitors and acceptors + public ShapeVisitorAcceptor getAcceptor() { + return new ShapeVisitorAcceptor() { + @Override + public boolean accept(XDGFShape shape) { + return !shape.isDeleted(); + } + }; + } + + public void setAcceptor(ShapeVisitorAcceptor acceptor) { + _acceptor = acceptor; + } + + public boolean accept(XDGFShape shape) { + return _acceptor.accept(shape); + } + + /** + * @param shape + * Current shape + * @param globalTransform + * A transform that can convert the shapes points to global + * coordinates + * @param level + * Level in the tree (0 is topmost, 1 is next level... + */ + public abstract void visit(XDGFShape shape, + AffineTransform globalTransform, int level); - ShapeVisitorAcceptor _acceptor; - - public ShapeVisitor() { - _acceptor = getAcceptor(); - } - - // is only called on construction of the visitor, allows - // mixing visitors and acceptors - public ShapeVisitorAcceptor getAcceptor() { - return new ShapeVisitorAcceptor() { - @Override - public boolean accept(XDGFShape shape) { - return !shape.isDeleted(); - } - }; - } - - public void setAcceptor(ShapeVisitorAcceptor acceptor) { - _acceptor = acceptor; - } - - - public boolean accept(XDGFShape shape) { - return _acceptor.accept(shape); - } - - /** - * @param shape Current shape - * @param globalTransform A transform that can convert the shapes points to global coordinates - * @param level Level in the tree (0 is topmost, 1 is next level... - */ - public abstract void visit(XDGFShape shape, AffineTransform globalTransform, int level); - } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeVisitorAcceptor.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeVisitorAcceptor.java index f9fb98271e..e50ce11eab 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeVisitorAcceptor.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/ShapeVisitorAcceptor.java @@ -21,6 +21,6 @@ import org.apache.poi.xdgf.usermodel.XDGFShape; public interface ShapeVisitorAcceptor { - public boolean accept(XDGFShape shape); - + public boolean accept(XDGFShape shape); + } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/exceptions/StopVisiting.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/exceptions/StopVisiting.java index 9a5d377b4e..2a33c43407 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/exceptions/StopVisiting.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/exceptions/StopVisiting.java @@ -19,6 +19,6 @@ package org.apache.poi.xdgf.usermodel.shape.exceptions; public class StopVisiting extends RuntimeException { - private static final long serialVersionUID = -4651207777092840750L; + private static final long serialVersionUID = -4651207777092840750L; } diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/exceptions/StopVisitingThisBranch.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/exceptions/StopVisitingThisBranch.java index 576e06276c..eb9e4a6203 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/exceptions/StopVisitingThisBranch.java +++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/shape/exceptions/StopVisitingThisBranch.java @@ -19,6 +19,6 @@ package org.apache.poi.xdgf.usermodel.shape.exceptions; public class StopVisitingThisBranch extends RuntimeException { - private static final long serialVersionUID = 5262319077534717862L; + private static final long serialVersionUID = 5262319077534717862L; } diff --git a/src/ooxml/java/org/apache/poi/xdgf/util/HierarchyPrinter.java b/src/ooxml/java/org/apache/poi/xdgf/util/HierarchyPrinter.java index ae48c211fd..8b7ed09629 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/util/HierarchyPrinter.java +++ b/src/ooxml/java/org/apache/poi/xdgf/util/HierarchyPrinter.java @@ -32,53 +32,60 @@ import org.apache.poi.xdgf.usermodel.shape.ShapeVisitor; public class HierarchyPrinter { - public static void printHierarchy(XDGFPage page, File outDir) throws FileNotFoundException { - - File pageFile = new File(outDir, "page" + page.getPageNumber() + "-" + Util.sanitizeFilename(page.getName()) + ".txt"); - - OutputStream os = new FileOutputStream(pageFile); - PrintStream pos = new PrintStream(os); - - printHierarchy(page, pos); - - pos.close(); - } - - public static void printHierarchy(XDGFPage page, final PrintStream os) { - - page.getContent().visitShapes(new ShapeVisitor() { - - @Override - public void visit(XDGFShape shape, AffineTransform globalTransform, int level) { - for (int i = 0; i < level; i++) { - os.append(" "); - } - // TODO: write text? - os.println(shape.toString() + " [" + shape.getShapeType() + ", " + shape.getSymbolName() + "] " + shape.getMasterShape() + " " + shape.getTextAsString().trim()); - } - }); - } - - public static void printHierarchy(XmlVisioDocument document, String outDirname) throws FileNotFoundException { - - File outDir = new File(outDirname); - - for (XDGFPage page: document.getPages()) { - printHierarchy(page, outDir); - } - } - - - public static void main(String [] args) throws Exception { - if (args.length != 2) { - System.err.println("Usage: in.vsdx outdir"); - System.exit(1); - } - - String inFilename = args[0]; - String outDir = args[1]; - - XmlVisioDocument doc = new XmlVisioDocument(new FileInputStream(inFilename)); - printHierarchy(doc, outDir); - } + public static void printHierarchy(XDGFPage page, File outDir) + throws FileNotFoundException { + + File pageFile = new File(outDir, "page" + page.getPageNumber() + "-" + + Util.sanitizeFilename(page.getName()) + ".txt"); + + OutputStream os = new FileOutputStream(pageFile); + PrintStream pos = new PrintStream(os); + + printHierarchy(page, pos); + + pos.close(); + } + + public static void printHierarchy(XDGFPage page, final PrintStream os) { + + page.getContent().visitShapes(new ShapeVisitor() { + + @Override + public void visit(XDGFShape shape, AffineTransform globalTransform, + int level) { + for (int i = 0; i < level; i++) { + os.append(" "); + } + // TODO: write text? + os.println(shape.toString() + " [" + shape.getShapeType() + + ", " + shape.getSymbolName() + "] " + + shape.getMasterShape() + " " + + shape.getTextAsString().trim()); + } + }); + } + + public static void printHierarchy(XmlVisioDocument document, + String outDirname) throws FileNotFoundException { + + File outDir = new File(outDirname); + + for (XDGFPage page : document.getPages()) { + printHierarchy(page, outDir); + } + } + + public static void main(String[] args) throws Exception { + if (args.length != 2) { + System.err.println("Usage: in.vsdx outdir"); + System.exit(1); + } + + String inFilename = args[0]; + String outDir = args[1]; + + XmlVisioDocument doc = new XmlVisioDocument(new FileInputStream( + inFilename)); + printHierarchy(doc, outDir); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/util/ObjectFactory.java b/src/ooxml/java/org/apache/poi/xdgf/util/ObjectFactory.java index 561e0c3c50..af0253f594 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/util/ObjectFactory.java +++ b/src/ooxml/java/org/apache/poi/xdgf/util/ObjectFactory.java @@ -27,31 +27,31 @@ import org.apache.xmlbeans.XmlObject; public class ObjectFactory<T, X extends XmlObject> { - - Map<String, Constructor<? extends T>> _types = new HashMap<>(); - - public void put(String typeName, Class<? extends T> cls, Class<?>... varargs) throws NoSuchMethodException, SecurityException { - _types.put(typeName, cls.getDeclaredConstructor(varargs)); - } - - public T load(String name, Object... varargs) { - Constructor<? extends T> constructor = _types.get(name); - if (constructor == null) { - - @SuppressWarnings("unchecked") - X xmlObject = (X) varargs[0]; - - String typeName = xmlObject.schemaType().getName().getLocalPart(); - throw new POIXMLException("Invalid '" + typeName + "' name '" + name + "'"); - } - - try { - return constructor.newInstance(varargs); - } catch (InvocationTargetException e) { - throw new POIXMLException(e.getCause()); - } catch (Exception e) { - throw new POIXMLException(e); - } - } - + + Map<String, Constructor<? extends T>> _types = new HashMap<String, Constructor<? extends T>>(); + + public void put(String typeName, Class<? extends T> cls, Class<?>... varargs) throws NoSuchMethodException, SecurityException { + _types.put(typeName, cls.getDeclaredConstructor(varargs)); + } + + public T load(String name, Object... varargs) { + Constructor<? extends T> constructor = _types.get(name); + if (constructor == null) { + + @SuppressWarnings("unchecked") + X xmlObject = (X) varargs[0]; + + String typeName = xmlObject.schemaType().getName().getLocalPart(); + throw new POIXMLException("Invalid '" + typeName + "' name '" + name + "'"); + } + + try { + return constructor.newInstance(varargs); + } catch (InvocationTargetException e) { + throw new POIXMLException(e.getCause()); + } catch (Exception e) { + throw new POIXMLException(e); + } + } + } diff --git a/src/ooxml/java/org/apache/poi/xdgf/util/Util.java b/src/ooxml/java/org/apache/poi/xdgf/util/Util.java index 3c6725343c..0e08294c8a 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/util/Util.java +++ b/src/ooxml/java/org/apache/poi/xdgf/util/Util.java @@ -18,20 +18,20 @@ package org.apache.poi.xdgf.util; public class Util { - - public static int countLines(String str) { - int lines = 1; - int pos = 0; - while ((pos = str.indexOf("\n", pos) + 1) != 0) { - lines++; - } - return lines; - } - - // this probably isn't 100% correct, so don't use it in security-sensitive - // applications! - // from: http://www.rgagnon.com/javadetails/java-0662.html - public static String sanitizeFilename(String name) { - return name.replaceAll("[:\\\\/*\"?|<>]", "_"); - } + + public static int countLines(String str) { + int lines = 1; + int pos = 0; + while ((pos = str.indexOf("\n", pos) + 1) != 0) { + lines++; + } + return lines; + } + + // this probably isn't 100% correct, so don't use it in security-sensitive + // applications! + // from: http://www.rgagnon.com/javadetails/java-0662.html + public static String sanitizeFilename(String name) { + return name.replaceAll("[:\\\\/*\"?|<>]", "_"); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/util/VsdxToPng.java b/src/ooxml/java/org/apache/poi/xdgf/util/VsdxToPng.java index 1bf6cf3e44..2b23755e25 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/util/VsdxToPng.java +++ b/src/ooxml/java/org/apache/poi/xdgf/util/VsdxToPng.java @@ -20,7 +20,6 @@ package org.apache.poi.xdgf.util; import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; -import java.awt.geom.Point2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; @@ -37,82 +36,93 @@ import org.apache.poi.xdgf.usermodel.shape.ShapeRenderer; public class VsdxToPng { - - public static void renderToPng(XDGFPage page, String outFilename, double scale, ShapeRenderer renderer) throws IOException { - renderToPng(page, new File(outFilename), scale, renderer); - } - - public static void renderToPngDir(XDGFPage page, File outDir, double scale, ShapeRenderer renderer) throws IOException { - - File pageFile = new File(outDir, "page" + page.getPageNumber() + "-" + Util.sanitizeFilename(page.getName()) + ".png"); - System.out.println("** Writing image to " + pageFile); - - renderToPng(page, pageFile, scale, renderer); - - } - - public static void renderToPng(XDGFPage page, File outFile, double scale, ShapeRenderer renderer) throws IOException { - - Dimension2dDouble sz = page.getPageSize(); - - int width = (int)(scale * sz.getWidth()); - int height = (int)(scale * sz.getHeight()); - - BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + public static void renderToPng(XDGFPage page, String outFilename, + double scale, ShapeRenderer renderer) throws IOException { + renderToPng(page, new File(outFilename), scale, renderer); + } + + public static void renderToPngDir(XDGFPage page, File outDir, double scale, + ShapeRenderer renderer) throws IOException { + + File pageFile = new File(outDir, "page" + page.getPageNumber() + "-" + + Util.sanitizeFilename(page.getName()) + ".png"); + System.out.println("** Writing image to " + pageFile); + + renderToPng(page, pageFile, scale, renderer); + + } + + public static void renderToPng(XDGFPage page, File outFile, double scale, + ShapeRenderer renderer) throws IOException { + + Dimension2dDouble sz = page.getPageSize(); + + int width = (int) (scale * sz.getWidth()); + int height = (int) (scale * sz.getHeight()); + + BufferedImage img = new BufferedImage(width, height, + BufferedImage.TYPE_INT_RGB); final Graphics2D graphics = img.createGraphics(); // default rendering options - graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + graphics.setRenderingHint(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_QUALITY); + graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BICUBIC); + graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, + RenderingHints.VALUE_FRACTIONALMETRICS_ON); graphics.setColor(Color.black); graphics.setBackground(Color.white); graphics.clearRect(0, 0, width, height); - + // Visio's coordinate system is flipped, so flip the image vertically - graphics.translate(0, img.getHeight()); + graphics.translate(0, img.getHeight()); graphics.scale(scale, -scale); - + // toplevel shapes only renderer.setGraphics(graphics); page.getContent().visitShapes(renderer); - + graphics.dispose(); - + FileOutputStream out = new FileOutputStream(outFile); ImageIO.write(img, "png", out); out.close(); - } - - public static void renderToPng(XmlVisioDocument document, String outDirname, double scale, ShapeRenderer renderer) throws IOException { - - File outDir = new File(outDirname); - - for (XDGFPage page: document.getPages()) { - renderToPngDir(page, outDir, scale, renderer); - } - } - - public static void main(String [] args) throws Exception { - if (args.length > 2) { - System.err.println("Usage: [--debug] in.vsdx outdir"); - System.exit(1); - } - - ShapeRenderer renderer = new ShapeRenderer(); - - String inFilename = args[0]; - String pngDir = args[1]; - - if (args[0].equals("--debug")) { - inFilename = args[1]; - pngDir = args[2]; - renderer = new ShapeDebuggerRenderer(); - } - - XmlVisioDocument doc = new XmlVisioDocument(new FileInputStream(inFilename)); - renderToPng(doc, pngDir, 2000/11.0, renderer); - } + } + + public static void renderToPng(XmlVisioDocument document, + String outDirname, double scale, ShapeRenderer renderer) + throws IOException { + + File outDir = new File(outDirname); + + for (XDGFPage page : document.getPages()) { + renderToPngDir(page, outDir, scale, renderer); + } + } + + public static void main(String[] args) throws Exception { + if (args.length > 2) { + System.err.println("Usage: [--debug] in.vsdx outdir"); + System.exit(1); + } + + ShapeRenderer renderer = new ShapeRenderer(); + + String inFilename = args[0]; + String pngDir = args[1]; + + if (args[0].equals("--debug")) { + inFilename = args[1]; + pngDir = args[2]; + renderer = new ShapeDebuggerRenderer(); + } + + XmlVisioDocument doc = new XmlVisioDocument(new FileInputStream( + inFilename)); + renderToPng(doc, pngDir, 2000 / 11.0, renderer); + } } diff --git a/src/ooxml/java/org/apache/poi/xdgf/xml/XDGFXMLDocumentPart.java b/src/ooxml/java/org/apache/poi/xdgf/xml/XDGFXMLDocumentPart.java index afe3489086..a8c70d84c7 100644 --- a/src/ooxml/java/org/apache/poi/xdgf/xml/XDGFXMLDocumentPart.java +++ b/src/ooxml/java/org/apache/poi/xdgf/xml/XDGFXMLDocumentPart.java @@ -23,11 +23,12 @@ import org.apache.poi.xdgf.usermodel.XDGFDocument; public class XDGFXMLDocumentPart extends POIXMLDocumentPart { - protected XDGFDocument _document; - - public XDGFXMLDocumentPart(PackagePart part, PackageRelationship rel, XDGFDocument document) { - super(part, rel); - _document = document; - } - + protected XDGFDocument _document; + + public XDGFXMLDocumentPart(PackagePart part, PackageRelationship rel, + XDGFDocument document) { + super(part, rel); + _document = document; + } + } diff --git a/src/ooxml/testcases/org/apache/poi/xdgf/usermodel/section/CombinedIteratorTest.java b/src/ooxml/testcases/org/apache/poi/xdgf/usermodel/section/CombinedIteratorTest.java index c48ab62c8e..e807c69d9d 100644 --- a/src/ooxml/testcases/org/apache/poi/xdgf/usermodel/section/CombinedIteratorTest.java +++ b/src/ooxml/testcases/org/apache/poi/xdgf/usermodel/section/CombinedIteratorTest.java @@ -26,134 +26,132 @@ import org.junit.Test; public class CombinedIteratorTest { - void testIteration(CombinedIterable<String> iterable, String... expected) { - - Iterator<String> iter = iterable.iterator(); - - for (int i = 0; i < expected.length; i++) { - Assert.assertEquals(true, iter.hasNext()); - Assert.assertEquals(expected[i], iter.next()); - } - - Assert.assertEquals(false, iter.hasNext()); - } - - @Test - public void testNullMaster() { - - SortedMap<Long, String> base = new TreeMap<>(); - base.put(1L, "B1"); - base.put(2L, "B2"); - base.put(3L, "B3"); - - testIteration(new CombinedIterable<>(base, null), - "B1", "B2", "B3"); - } - - @Test - public void testNoMatchesBaseFirst() { - - SortedMap<Long, String> base = new TreeMap<>(); - base.put(1L, "B1"); - base.put(2L, "B2"); - base.put(3L, "B3"); - - SortedMap<Long, String> master = new TreeMap<>(); - master.put(4L, "M4"); - master.put(5L, "M5"); - master.put(6L, "M6"); - - testIteration(new CombinedIterable<>(base, master), - "B1", "B2", "B3", "M4", "M5", "M6"); - } - - @Test - public void testNoMatchesMasterFirst() { - - SortedMap<Long, String> base = new TreeMap<>(); - base.put(4L, "B4"); - base.put(5L, "B5"); - base.put(6L, "B6"); - - SortedMap<Long, String> master = new TreeMap<>(); - master.put(1L, "M1"); - master.put(2L, "M2"); - master.put(3L, "M3"); - - testIteration(new CombinedIterable<>(base, master), - "M1", "M2", "M3", "B4", "B5", "B6"); - } - - @Test - public void testInterleaved1() { - - SortedMap<Long, String> base = new TreeMap<>(); - base.put(1L, "B1"); - base.put(3L, "B3"); - base.put(5L, "B5"); - - SortedMap<Long, String> master = new TreeMap<>(); - master.put(2L, "M2"); - master.put(4L, "M4"); - master.put(6L, "M6"); - - testIteration(new CombinedIterable<>(base, master), - "B1", "M2", "B3", "M4", "B5", "M6"); - } - - @Test - public void testInterleaved2() { - - SortedMap<Long, String> base = new TreeMap<>(); - base.put(1L, "B1"); - base.put(2L, "B2"); - base.put(5L, "B5"); - base.put(6L, "B6"); - - SortedMap<Long, String> master = new TreeMap<>(); - master.put(3L, "M3"); - master.put(4L, "M4"); - master.put(7L, "M7"); - master.put(8L, "M8"); - - testIteration(new CombinedIterable<>(base, master), - "B1", "B2", "M3", "M4", "B5", "B6", "M7", "M8"); - } - - @Test - public void testAllMatching() { - - SortedMap<Long, String> base = new TreeMap<>(); - base.put(1L, "B1"); - base.put(2L, "B2"); - base.put(3L, "B3"); - - SortedMap<Long, String> master = new TreeMap<>(); - master.put(1L, "M1"); - master.put(2L, "M2"); - master.put(3L, "M3"); - - testIteration(new CombinedIterable<>(base, master), - "B1", "B2", "B3"); - } - - @Test - public void testAllMatching2() { - - SortedMap<Long, String> base = new TreeMap<>(); - base.put(1L, "B1"); - base.put(2L, "B2"); - base.put(3L, "B3"); - - SortedMap<Long, String> master = new TreeMap<>(); - master.put(1L, "M1"); - master.put(2L, "M2"); - master.put(3L, "M3"); - master.put(4L, "M4"); - - testIteration(new CombinedIterable<>(base, master), - "B1", "B2", "B3", "M4"); - } - - + void testIteration(CombinedIterable<String> iterable, String... expected) { + + Iterator<String> iter = iterable.iterator(); + + for (int i = 0; i < expected.length; i++) { + Assert.assertEquals(true, iter.hasNext()); + Assert.assertEquals(expected[i], iter.next()); + } + + Assert.assertEquals(false, iter.hasNext()); + } + + @Test + public void testNullMaster() { + + SortedMap<Long, String> base = new TreeMap<Long, String>(); + base.put(1L, "B1"); + base.put(2L, "B2"); + base.put(3L, "B3"); + + testIteration(new CombinedIterable<String>(base, null), "B1", "B2", + "B3"); + } + + @Test + public void testNoMatchesBaseFirst() { + + SortedMap<Long, String> base = new TreeMap<Long, String>(); + base.put(1L, "B1"); + base.put(2L, "B2"); + base.put(3L, "B3"); + + SortedMap<Long, String> master = new TreeMap<Long, String>(); + master.put(4L, "M4"); + master.put(5L, "M5"); + master.put(6L, "M6"); + + testIteration(new CombinedIterable<String>(base, master), "B1", "B2", + "B3", "M4", "M5", "M6"); + } + + @Test + public void testNoMatchesMasterFirst() { + + SortedMap<Long, String> base = new TreeMap<Long, String>(); + base.put(4L, "B4"); + base.put(5L, "B5"); + base.put(6L, "B6"); + + SortedMap<Long, String> master = new TreeMap<Long, String>(); + master.put(1L, "M1"); + master.put(2L, "M2"); + master.put(3L, "M3"); + + testIteration(new CombinedIterable<String>(base, master), "M1", "M2", + "M3", "B4", "B5", "B6"); + } + + @Test + public void testInterleaved1() { + + SortedMap<Long, String> base = new TreeMap<Long, String>(); + base.put(1L, "B1"); + base.put(3L, "B3"); + base.put(5L, "B5"); + + SortedMap<Long, String> master = new TreeMap<Long, String>(); + master.put(2L, "M2"); + master.put(4L, "M4"); + master.put(6L, "M6"); + + testIteration(new CombinedIterable<String>(base, master), "B1", "M2", + "B3", "M4", "B5", "M6"); + } + + @Test + public void testInterleaved2() { + + SortedMap<Long, String> base = new TreeMap<Long, String>(); + base.put(1L, "B1"); + base.put(2L, "B2"); + base.put(5L, "B5"); + base.put(6L, "B6"); + + SortedMap<Long, String> master = new TreeMap<Long, String>(); + master.put(3L, "M3"); + master.put(4L, "M4"); + master.put(7L, "M7"); + master.put(8L, "M8"); + + testIteration(new CombinedIterable<String>(base, master), "B1", "B2", + "M3", "M4", "B5", "B6", "M7", "M8"); + } + + @Test + public void testAllMatching() { + + SortedMap<Long, String> base = new TreeMap<Long, String>(); + base.put(1L, "B1"); + base.put(2L, "B2"); + base.put(3L, "B3"); + + SortedMap<Long, String> master = new TreeMap<Long, String>(); + master.put(1L, "M1"); + master.put(2L, "M2"); + master.put(3L, "M3"); + + testIteration(new CombinedIterable<String>(base, master), "B1", "B2", + "B3"); + } + + @Test + public void testAllMatching2() { + + SortedMap<Long, String> base = new TreeMap<Long, String>(); + base.put(1L, "B1"); + base.put(2L, "B2"); + base.put(3L, "B3"); + + SortedMap<Long, String> master = new TreeMap<Long, String>(); + master.put(1L, "M1"); + master.put(2L, "M2"); + master.put(3L, "M3"); + master.put(4L, "M4"); + + testIteration(new CombinedIterable<String>(base, master), "B1", "B2", + "B3", "M4"); + } } |