poi-visio import: reformat code to fit project standards, remove JRE 7isms

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1709355 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Dustin Spicuzza 2015-10-19 05:59:37 +00:00
parent 3bd2011924
commit d70b8e8b88
57 changed files with 4526 additions and 4418 deletions

View File

@ -22,29 +22,32 @@ import org.apache.poi.POIXMLException;
public class XDGFException { public class XDGFException {
/** /**
* Creates an error message to be thrown * Creates an error message to be thrown
*/ */
public static POIXMLException error(String message, Object o) { public static POIXMLException error(String message, Object o) {
return new POIXMLException(o.toString() + ": " + message); return new POIXMLException(o.toString() + ": " + message);
} }
public static POIXMLException error(String message, Object o, Throwable t) { public static POIXMLException error(String message, Object o, Throwable t) {
return new POIXMLException(o.toString() + ": " + message, t); return new POIXMLException(o.toString() + ": " + message, t);
} }
// //
// Use these to wrap error messages coming up so that we have at least // Use these to wrap error messages coming up so that we have at least
// some idea where the error was located // some idea where the error was located
// //
public static POIXMLException wrap(POIXMLDocumentPart part, POIXMLException e) { public static POIXMLException wrap(POIXMLDocumentPart part,
return new POIXMLException(part.getPackagePart().getPartName().toString() + ": " + e.getMessage(), POIXMLException e) {
e.getCause() == null ? e : e.getCause()); return new POIXMLException(part.getPackagePart().getPartName()
} .toString()
+ ": " + e.getMessage(), e.getCause() == null ? e
: e.getCause());
}
public static POIXMLException wrap(String where, POIXMLException e) { public static POIXMLException wrap(String where, POIXMLException e) {
return new POIXMLException(where + ": " + e.getMessage(), return new POIXMLException(where + ": " + e.getMessage(),
e.getCause() == null ? e : e.getCause()); e.getCause() == null ? e : e.getCause());
} }
} }

View File

@ -21,53 +21,53 @@ import java.awt.geom.Dimension2D;
public class Dimension2dDouble extends Dimension2D { public class Dimension2dDouble extends Dimension2D {
double width; double width;
double height; double height;
public Dimension2dDouble() { public Dimension2dDouble() {
width = 0d; width = 0d;
height = 0d; height = 0d;
} }
public Dimension2dDouble(double width, double height) { public Dimension2dDouble(double width, double height) {
this.width = width; this.width = width;
this.height = height; this.height = height;
} }
@Override @Override
public double getWidth() { public double getWidth() {
return width; return width;
} }
@Override @Override
public double getHeight() { public double getHeight() {
return height; return height;
} }
@Override @Override
public void setSize(double width, double height) { public void setSize(double width, double height) {
this.width = width; this.width = width;
this.height = height; this.height = height;
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj instanceof Dimension2dDouble) { if (obj instanceof Dimension2dDouble) {
Dimension2dDouble other = (Dimension2dDouble)obj; Dimension2dDouble other = (Dimension2dDouble) obj;
return width == other.width && height == other.height; return width == other.width && height == other.height;
} }
return false; return false;
} }
@Override @Override
public int hashCode() { public int hashCode() {
double sum = width + height; double sum = width + height;
return (int)Math.ceil(sum * (sum + 1)/2 + width); return (int) Math.ceil(sum * (sum + 1) / 2 + width);
} }
@Override @Override
public String toString() { public String toString() {
return "Dimension2dDouble[" + width + ", " + height + "]"; return "Dimension2dDouble[" + width + ", " + height + "]";
} }
} }

View File

@ -20,60 +20,56 @@ package org.apache.poi.xdgf.geom;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.util.ArrayList; 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.XDGFShape;
import org.apache.poi.xdgf.usermodel.section.geometry.SplineKnot; import org.apache.poi.xdgf.usermodel.section.geometry.SplineKnot;
import org.apache.poi.xdgf.usermodel.section.geometry.SplineStart; 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 { public class SplineCollector {
SplineStart _start; SplineStart _start;
ArrayList<SplineKnot> _knots = new ArrayList<>(); ArrayList<SplineKnot> _knots = new ArrayList<SplineKnot>();
public SplineCollector(SplineStart start) { public SplineCollector(SplineStart start) {
_start = start; _start = start;
} }
public void addKnot(SplineKnot knot) { public void addKnot(SplineKnot knot) {
if (!knot.getDel()) if (!knot.getDel())
_knots.add(knot); _knots.add(knot);
} }
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
// ok, we have the start, and all knots... do something with this // ok, we have the start, and all knots... do something with this
Point2D last = path.getCurrentPoint(); Point2D last = path.getCurrentPoint();
// create a control path and knots // create a control path and knots
ControlPath controlPath = new ControlPath(); ControlPath controlPath = new ControlPath();
ValueVector knots = new ValueVector(_knots.size() + 3); ValueVector knots = new ValueVector(_knots.size() + 3);
double firstKnot = _start.getB(); double firstKnot = _start.getB();
double lastKnot = _start.getC(); double lastKnot = _start.getC();
int degree = _start.getD(); int degree = _start.getD();
// first/second knot // first/second knot
knots.add(firstKnot); knots.add(firstKnot);
knots.add(_start.getA()); knots.add(_start.getA());
// first/second control point // first/second control point
controlPath.addPoint(PointFactory.create(last.getX(), last.getY())); controlPath.addPoint(PointFactory.create(last.getX(), last.getY()));
controlPath.addPoint(PointFactory.create(_start.getX(), _start.getY())); controlPath.addPoint(PointFactory.create(_start.getX(), _start.getY()));
// middle knots/control points // middle knots/control points
for (SplineKnot knot: _knots) { for (SplineKnot knot: _knots) {
knots.add(knot.getA()); knots.add(knot.getA());
controlPath.addPoint(PointFactory.create(knot.getX(), knot.getY())); controlPath.addPoint(PointFactory.create(knot.getX(), knot.getY()));
} }
// last knot // last knot
knots.add(lastKnot); knots.add(lastKnot);
ShapeMultiPath shape = SplineRenderer.createNurbsSpline(controlPath, knots, null, degree); ShapeMultiPath shape = SplineRenderer.createNurbsSpline(controlPath, knots, null, degree);
path.append(shape, true); path.append(shape, true);
} }
} }

View File

@ -17,52 +17,46 @@
package org.apache.poi.xdgf.geom; package org.apache.poi.xdgf.geom;
import com.graphbuilder.curve.ControlPath; import org.apache.poi.ss.formula.functions.LookupUtils.ValueVector;
import com.graphbuilder.curve.GroupIterator;
import com.graphbuilder.curve.NURBSpline;
import com.graphbuilder.curve.ShapeMultiPath;
import com.graphbuilder.curve.ValueVector;
public class SplineRenderer { public class SplineRenderer {
public static ShapeMultiPath createNurbsSpline(ControlPath controlPoints, public static ShapeMultiPath createNurbsSpline(ControlPath controlPoints,
ValueVector knots, ValueVector knots, ValueVector weights, int degree) {
ValueVector weights,
int degree) {
double firstKnot = knots.get(0); double firstKnot = knots.get(0);
double lastKnot = knots.get(knots.size()-1); double lastKnot = knots.get(knots.size() - 1);
// scale knots to [0, 1] based on first/last knots // scale knots to [0, 1] based on first/last knots
for (int i = 0; i < knots.size(); i++) { for (int i = 0; i < knots.size(); i++) {
knots.set((knots.get(i) - firstKnot)/lastKnot, i); knots.set((knots.get(i) - firstKnot) / lastKnot, i);
} }
// if we don't have enough knots, duplicate the last knot until we do // 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++) { for (int i = knots.size(); i < controlPoints.numPoints() + degree + 1; i++) {
knots.add(1); knots.add(1);
} }
GroupIterator gi = new GroupIterator("0:n-1", controlPoints.numPoints()); GroupIterator gi = new GroupIterator("0:n-1", controlPoints.numPoints());
NURBSpline spline = new NURBSpline(controlPoints, gi); NURBSpline spline = new NURBSpline(controlPoints, gi);
spline.setDegree(degree); spline.setDegree(degree);
spline.setKnotVectorType(NURBSpline.NON_UNIFORM); spline.setKnotVectorType(NURBSpline.NON_UNIFORM);
spline.setKnotVector(knots); spline.setKnotVector(knots);
if (weights == null) { if (weights == null) {
spline.setUseWeightVector(false); spline.setUseWeightVector(false);
} else { } else {
spline.setWeightVector(weights); spline.setWeightVector(weights);
} }
// now that this is done, add it to the path // now that this is done, add it to the path
ShapeMultiPath shape = new ShapeMultiPath(); ShapeMultiPath shape = new ShapeMultiPath();
shape.setFlatness(0.01); shape.setFlatness(0.01);
spline.appendTo(shape); spline.appendTo(shape);
return shape; return shape;
} }
} }

View File

@ -44,116 +44,116 @@ import com.microsoft.schemas.office.visio.x2012.main.ShapeSheetType;
*/ */
public class XDGFBaseContents extends XDGFXMLDocumentPart { public class XDGFBaseContents extends XDGFXMLDocumentPart {
protected PageContentsType _pageContents; protected PageContentsType _pageContents;
// shapes without parents // shapes without parents
protected List<XDGFShape> _toplevelShapes = new ArrayList<>(); protected List<XDGFShape> _toplevelShapes = new ArrayList<XDGFShape>();
protected Map<Long, XDGFShape> _shapes = new HashMap<>(); protected Map<Long, XDGFShape> _shapes = new HashMap<Long, XDGFShape>();
protected List<XDGFConnection> _connections = new ArrayList<>(); protected List<XDGFConnection> _connections = new ArrayList<XDGFConnection>();
public XDGFBaseContents(PackagePart part, PackageRelationship rel, XDGFDocument document) { public XDGFBaseContents(PackagePart part, PackageRelationship rel, XDGFDocument document) {
super(part, rel, document); super(part, rel, document);
} }
@Internal @Internal
public PageContentsType getXmlObject() { public PageContentsType getXmlObject() {
return _pageContents; return _pageContents;
} }
@Override @Override
protected void onDocumentRead() { protected void onDocumentRead() {
if (_pageContents.isSetShapes()) { if (_pageContents.isSetShapes()) {
for (ShapeSheetType shapeSheet: _pageContents.getShapes().getShapeArray()) { for (ShapeSheetType shapeSheet: _pageContents.getShapes().getShapeArray()) {
XDGFShape shape = new XDGFShape(shapeSheet, this, _document); XDGFShape shape = new XDGFShape(shapeSheet, this, _document);
_toplevelShapes.add(shape); _toplevelShapes.add(shape);
addToShapeIndex(shape); addToShapeIndex(shape);
} }
} }
if (_pageContents.isSetConnects()) { if (_pageContents.isSetConnects()) {
for (ConnectType connect: _pageContents.getConnects().getConnectArray()) { for (ConnectType connect: _pageContents.getConnects().getConnectArray()) {
XDGFShape from = _shapes.get(connect.getFromSheet()); XDGFShape from = _shapes.get(connect.getFromSheet());
XDGFShape to = _shapes.get(connect.getToSheet()); XDGFShape to = _shapes.get(connect.getToSheet());
if (from == null) if (from == null)
throw new POIXMLException(this.toString() + "; Connect; Invalid from id: " + connect.getFromSheet()); throw new POIXMLException(this.toString() + "; Connect; Invalid from id: " + connect.getFromSheet());
if (to == null) if (to == null)
throw new POIXMLException(this.toString() + "; Connect; Invalid to id: " + connect.getToSheet()); throw new POIXMLException(this.toString() + "; Connect; Invalid to id: " + connect.getToSheet());
_connections.add(new XDGFConnection(connect, from, to)); _connections.add(new XDGFConnection(connect, from, to));
} }
} }
} }
protected void addToShapeIndex(XDGFShape shape) { protected void addToShapeIndex(XDGFShape shape) {
_shapes.put(shape.getID(), shape); _shapes.put(shape.getID(), shape);
List<XDGFShape> shapes = shape.getShapes(); List<XDGFShape> shapes = shape.getShapes();
if (shapes == null) if (shapes == null)
return; return;
for (XDGFShape subshape: shapes) for (XDGFShape subshape: shapes)
addToShapeIndex(subshape); addToShapeIndex(subshape);
} }
// //
// API // API
// //
/** /**
* *
* @param graphics * @param graphics
*/ */
public void draw(Graphics2D graphics) { public void draw(Graphics2D graphics) {
visitShapes(new ShapeRenderer(graphics)); visitShapes(new ShapeRenderer(graphics));
} }
public XDGFShape getShapeById(long id) { public XDGFShape getShapeById(long id) {
return _shapes.get(id); return _shapes.get(id);
} }
public Map<Long, XDGFShape> getShapesMap() { public Map<Long, XDGFShape> getShapesMap() {
return Collections.unmodifiableMap(_shapes); return Collections.unmodifiableMap(_shapes);
} }
public Collection<XDGFShape> getShapes() { public Collection<XDGFShape> getShapes() {
return _shapes.values(); return _shapes.values();
} }
public List<XDGFShape> getTopLevelShapes() { public List<XDGFShape> getTopLevelShapes() {
return Collections.unmodifiableList(_toplevelShapes); return Collections.unmodifiableList(_toplevelShapes);
} }
// get connections // get connections
public List<XDGFConnection> getConnections() { public List<XDGFConnection> getConnections() {
return Collections.unmodifiableList(_connections); return Collections.unmodifiableList(_connections);
} }
@Override @Override
public String toString() { public String toString() {
return getPackagePart().getPartName().toString(); return getPackagePart().getPartName().toString();
} }
/** /**
* Provides iteration over the shapes using the visitor pattern, and provides * Provides iteration over the shapes using the visitor pattern, and provides
* an easy way to convert shape coordinates into global coordinates * an easy way to convert shape coordinates into global coordinates
*/ */
public void visitShapes(ShapeVisitor visitor) { public void visitShapes(ShapeVisitor visitor) {
try { try {
for (XDGFShape shape: _toplevelShapes) { for (XDGFShape shape: _toplevelShapes) {
shape.visitShapes(visitor, new AffineTransform(), 0); shape.visitShapes(visitor, new AffineTransform(), 0);
} }
} catch (StopVisiting e) { } catch (StopVisiting e) {
// intentionally empty // intentionally empty
} catch (POIXMLException e) { } catch (POIXMLException e) {
throw XDGFException.wrap(this, e); throw XDGFException.wrap(this, e);
} }
} }
} }

View File

@ -25,126 +25,131 @@ import org.apache.poi.util.Internal;
import com.microsoft.schemas.office.visio.x2012.main.CellType; import com.microsoft.schemas.office.visio.x2012.main.CellType;
/** /**
* There are a lot of different cell types. Cell is really just an attribute * There are a lot of different cell types. Cell is really just an attribute of
* of the thing that it's attached to. Will probably refactor this once I * the thing that it's attached to. Will probably refactor this once I figure
* figure out a better way to use them * out a better way to use them
* *
* The various attributes of a Cell are constrained, and are better defined * The various attributes of a Cell are constrained, and are better defined in
* in the XSD 1.1 visio schema * the XSD 1.1 visio schema
*/ */
public class XDGFCell { public class XDGFCell {
public static Boolean maybeGetBoolean(Map<String, XDGFCell> cells, String name) { public static Boolean maybeGetBoolean(Map<String, XDGFCell> cells,
XDGFCell cell = cells.get(name); String name) {
if (cell == null) XDGFCell cell = cells.get(name);
return null; if (cell == null)
return null;
if (cell.getValue().equals("0")) if (cell.getValue().equals("0"))
return false; return false;
if (cell.getValue().equals("1")) if (cell.getValue().equals("1"))
return true; return true;
throw new POIXMLException("Invalid boolean value for '" + cell.getName() + "'"); throw new POIXMLException("Invalid boolean value for '"
} + cell.getName() + "'");
}
public static Double maybeGetDouble(Map<String, XDGFCell> cells, String name) { public static Double maybeGetDouble(Map<String, XDGFCell> cells, String name) {
XDGFCell cell = cells.get(name); XDGFCell cell = cells.get(name);
if (cell != null) if (cell != null)
return parseDoubleValue(cell._cell); return parseDoubleValue(cell._cell);
return null; return null;
} }
public static Integer maybeGetInteger(Map<String, XDGFCell> cells, String name) { public static Integer maybeGetInteger(Map<String, XDGFCell> cells,
XDGFCell cell = cells.get(name); String name) {
if (cell != null) XDGFCell cell = cells.get(name);
return parseIntegerValue(cell._cell); if (cell != null)
return null; return parseIntegerValue(cell._cell);
} return null;
}
public static String maybeGetString(Map<String, XDGFCell> cells, String name) { public static String maybeGetString(Map<String, XDGFCell> cells, String name) {
XDGFCell cell = cells.get(name); XDGFCell cell = cells.get(name);
if (cell != null) { if (cell != null) {
String v = cell._cell.getV(); String v = cell._cell.getV();
if (v.equals("Themed")) if (v.equals("Themed"))
return null; return null;
return v; return v;
} }
return null; return null;
} }
public static Double parseDoubleValue(CellType cell) { public static Double parseDoubleValue(CellType cell) {
try { try {
return Double.parseDouble(cell.getV()); return Double.parseDouble(cell.getV());
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
if (cell.getV().equals("Themed")) if (cell.getV().equals("Themed"))
return null; return null;
throw new POIXMLException("Invalid float value for '" + cell.getN() + "': " + e); throw new POIXMLException("Invalid float value for '" + cell.getN()
} + "': " + e);
} }
}
public static Integer parseIntegerValue(CellType cell) { public static Integer parseIntegerValue(CellType cell) {
try { try {
return Integer.parseInt(cell.getV()); return Integer.parseInt(cell.getV());
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
if (cell.getV().equals("Themed")) if (cell.getV().equals("Themed"))
return null; return null;
throw new POIXMLException("Invalid integer value for '" + cell.getN() + "': " + e); throw new POIXMLException("Invalid integer value for '"
} + cell.getN() + "': " + e);
} }
}
// returns a length, converts it to inches? // returns a length, converts it to inches?
public static Double parseVLength(CellType cell) { public static Double parseVLength(CellType cell) {
try { try {
return Double.parseDouble(cell.getV()); return Double.parseDouble(cell.getV());
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
if (cell.getV().equals("Themed")) if (cell.getV().equals("Themed"))
return null; return null;
throw new POIXMLException("Invalid float value for '" + cell.getN() + "': " + e); throw new POIXMLException("Invalid float value for '" + cell.getN()
} + "': " + e);
} }
}
CellType _cell;
CellType _cell; public XDGFCell(CellType cell) {
_cell = cell;
}
public XDGFCell(CellType cell) { @Internal
_cell = cell; CellType getXmlObject() {
} return _cell;
}
@Internal /**
CellType getXmlObject() { * Represents the name of the ShapeSheet cell.
return _cell; */
} public String getName() {
return _cell.getN();
}
/** /**
* Represents the name of the ShapeSheet cell. * Represents the value of the cell.
*/ */
public String getName() { public String getValue() {
return _cell.getN(); return _cell.getV();
} }
/** /**
* Represents the value of the cell. * Represents the element's formula. This attribute can contain one of the
*/ * following strings: - '(some formula)' if the formula exists locally - No
public String getValue() { * Formula if the formula is locally deleted or blocked - Inh if the formula
return _cell.getV(); * is inherited.
} */
public String getFormula() {
return _cell.getF();
}
/** /*
* Represents the elements formula. This attribute can contain one of the following strings: * Indicates that the formula evaluates to an error. The value of E is the
* - (some formula) if the formula exists locally * current value (an error message string); the value of the V attribute is
* - No Formula if the formula is locally deleted or blocked * the last valid value.
* - Inh if the formula is inherited. */
*/ public String getError() {
public String getFormula() { return _cell.getE();
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();
}
} }

View File

@ -21,114 +21,116 @@ import com.microsoft.schemas.office.visio.x2012.main.ConnectType;
public class XDGFConnection { public class XDGFConnection {
// comments on frompart/topart taken from pkgVisio // comments on frompart/topart taken from pkgVisio
// https://msdn.microsoft.com/en-us/library/ms367611(v=office.12).aspx // https://msdn.microsoft.com/en-us/library/ms367611(v=office.12).aspx
// The following constants declared by the Microsoft Office Visio type // The following constants declared by the Microsoft Office Visio type
// library show return values for the FromPart property. // library show return values for the FromPart property.
// Constant Value // Constant Value
// visConnectFromError -1 // visConnectFromError -1
// visFromNone 0 // visFromNone 0
// visLeftEdge 1 // visLeftEdge 1
// visCenterEdge 2 // visCenterEdge 2
// visRightEdge 3 // visRightEdge 3
// visBottomEdge 4 // visBottomEdge 4
// visMiddleEdge 5 // visMiddleEdge 5
// visTopEdge 6 // visTopEdge 6
// visBeginX 7 // visBeginX 7
// visBeginY 8 // visBeginY 8
// visBegin 9 // visBegin 9
// visEndX 10 // visEndX 10
// visEndY 11 // visEndY 11
// visEnd 12 // visEnd 12
// visFromAngle 13 // visFromAngle 13
// visFromPin 14 // 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) // 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 visConnectFromError = -1;
public static final int visFromNone = 0; public static final int visFromNone = 0;
public static final int visLeftEdge = 1; public static final int visLeftEdge = 1;
public static final int visCenterEdge = 2; public static final int visCenterEdge = 2;
public static final int visRightEdge = 3; public static final int visRightEdge = 3;
public static final int visBottomEdge = 4; public static final int visBottomEdge = 4;
public static final int visMiddleEdge = 5; public static final int visMiddleEdge = 5;
public static final int visTopEdge = 6; public static final int visTopEdge = 6;
public static final int visBeginX = 7; public static final int visBeginX = 7;
public static final int visBeginY = 8; public static final int visBeginY = 8;
public static final int visBegin = 9; public static final int visBegin = 9;
public static final int visEndX = 10; public static final int visEndX = 10;
public static final int visEndY = 11; public static final int visEndY = 11;
public static final int visEnd = 12; public static final int visEnd = 12;
public static final int visFromAngle = 13; public static final int visFromAngle = 13;
public static final int visFromPin = 14; 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
// The ToPart property identifies the part of a shape to which another public static final int visConnectToError = -1;
// shape is glued, such as its begin point or endpoint, one of its edges, public static final int visToNone = 0;
// or a connection point. The following constants declared by the Visio type library in member VisToParts show possible return values for the ToPart property. public static final int visGuideX = 1;
// Constant Value public static final int visGuideY = 2;
// visConnectToError -1 public static final int visWholeShape = 3;
// visToNone 0 public static final int visGuideIntersect = 4;
// visGuideX 1 public static final int visToAngle = 7;
// visGuideY 2
// visWholeShape 3
// visGuideIntersect 4
// visToAngle 7
// visConnectionPoint 100 + row index of connection point
public static final int visConnectToError = -1; private ConnectType _connect;
public static final int visToNone = 0; private XDGFShape _from;
public static final int visGuideX = 1; private XDGFShape _to;
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; public XDGFConnection(ConnectType connect, XDGFShape from, XDGFShape to) {
private XDGFShape _from; _connect = connect;
private XDGFShape _to; _from = from;
_to = to;
}
public XDGFShape getFromShape() {
return _from;
}
public XDGFConnection(ConnectType connect, XDGFShape from, XDGFShape to) { public XDGFCell getFromCell() {
_connect = connect; return _from.getCell(_connect.getFromCell());
_from = from; }
_to = to;
}
public XDGFShape getFromShape() { public String getFromCellName() {
return _from; return _connect.getFromCell();
} }
public XDGFCell getFromCell() { public XDGFShape getToShape() {
return _from.getCell(_connect.getFromCell()); return _to;
} }
public String getFromCellName() { public String getToCellName() {
return _connect.getFromCell(); return _connect.getToCell();
} }
public XDGFShape getToShape() { // see constants above
return _to; public Integer getFromPart() {
} if (_connect.isSetFromPart())
return _connect.getFromPart();
else
return null;
}
public String getToCellName() { // see constants above
return _connect.getToCell(); public Integer getToPart() {
} if (_connect.isSetToPart())
return _connect.getToPart();
// see constants above else
public Integer getFromPart() { return null;
if (_connect.isSetFromPart()) }
return _connect.getFromPart();
else
return null;
}
// see constants above
public Integer getToPart() {
if (_connect.isSetToPart())
return _connect.getToPart();
else
return null;
}
} }

View File

@ -32,85 +32,85 @@ import com.microsoft.schemas.office.visio.x2012.main.VisioDocumentType;
*/ */
public class XDGFDocument { public class XDGFDocument {
protected VisioDocumentType _document; protected VisioDocumentType _document;
Map<Long, XDGFStyleSheet> _styleSheets = new HashMap<>(); Map<Long, XDGFStyleSheet> _styleSheets = new HashMap<Long, XDGFStyleSheet>();
// defaults // defaults
long _defaultFillStyle = 0; long _defaultFillStyle = 0;
long _defaultGuideStyle = 0; long _defaultGuideStyle = 0;
long _defaultLineStyle = 0; long _defaultLineStyle = 0;
long _defaultTextStyle = 0; long _defaultTextStyle = 0;
public XDGFDocument(VisioDocumentType document) { public XDGFDocument(VisioDocumentType document) {
_document = document; _document = document;
if (!_document.isSetDocumentSettings()) if (!_document.isSetDocumentSettings())
throw new POIXMLException("Document settings not found"); throw new POIXMLException("Document settings not found");
DocumentSettingsType docSettings = _document.getDocumentSettings(); DocumentSettingsType docSettings = _document.getDocumentSettings();
if (docSettings.isSetDefaultFillStyle()) if (docSettings.isSetDefaultFillStyle())
_defaultFillStyle = docSettings.getDefaultFillStyle(); _defaultFillStyle = docSettings.getDefaultFillStyle();
if (docSettings.isSetDefaultGuideStyle()) if (docSettings.isSetDefaultGuideStyle())
_defaultGuideStyle = docSettings.getDefaultGuideStyle(); _defaultGuideStyle = docSettings.getDefaultGuideStyle();
if (docSettings.isSetDefaultLineStyle()) if (docSettings.isSetDefaultLineStyle())
_defaultLineStyle = docSettings.getDefaultLineStyle(); _defaultLineStyle = docSettings.getDefaultLineStyle();
if (docSettings.isSetDefaultTextStyle()) if (docSettings.isSetDefaultTextStyle())
_defaultTextStyle = docSettings.getDefaultTextStyle(); _defaultTextStyle = docSettings.getDefaultTextStyle();
if (_document.isSetStyleSheets()) { if (_document.isSetStyleSheets()) {
for (StyleSheetType styleSheet: _document.getStyleSheets().getStyleSheetArray()) { for (StyleSheetType styleSheet: _document.getStyleSheets().getStyleSheetArray()) {
_styleSheets.put(styleSheet.getID(), new XDGFStyleSheet(styleSheet, this)); _styleSheets.put(styleSheet.getID(), new XDGFStyleSheet(styleSheet, this));
} }
} }
} }
@Internal @Internal
public VisioDocumentType getXmlObject() { public VisioDocumentType getXmlObject() {
return _document; return _document;
} }
public XDGFStyleSheet getStyleById(long id) { public XDGFStyleSheet getStyleById(long id) {
return _styleSheets.get(id); return _styleSheets.get(id);
} }
public XDGFStyleSheet getDefaultFillStyle() { public XDGFStyleSheet getDefaultFillStyle() {
XDGFStyleSheet style = getStyleById(_defaultFillStyle); XDGFStyleSheet style = getStyleById(_defaultFillStyle);
if (style == null) if (style == null)
throw new POIXMLException("No default fill style found!"); throw new POIXMLException("No default fill style found!");
return style; return style;
} }
public XDGFStyleSheet getDefaultGuideStyle() { public XDGFStyleSheet getDefaultGuideStyle() {
XDGFStyleSheet style = getStyleById(_defaultGuideStyle); XDGFStyleSheet style = getStyleById(_defaultGuideStyle);
if (style == null) if (style == null)
throw new POIXMLException("No default guide style found!"); throw new POIXMLException("No default guide style found!");
return style; return style;
} }
public XDGFStyleSheet getDefaultLineStyle() { public XDGFStyleSheet getDefaultLineStyle() {
XDGFStyleSheet style = getStyleById(_defaultLineStyle); XDGFStyleSheet style = getStyleById(_defaultLineStyle);
if (style == null) if (style == null)
throw new POIXMLException("No default line style found!"); throw new POIXMLException("No default line style found!");
return style; return style;
} }
public XDGFStyleSheet getDefaultTextStyle() { public XDGFStyleSheet getDefaultTextStyle() {
XDGFStyleSheet style = getStyleById(_defaultTextStyle); XDGFStyleSheet style = getStyleById(_defaultTextStyle);
if (style == null) if (style == null)
throw new POIXMLException("No default text style found!"); throw new POIXMLException("No default text style found!");
return style; return style;
} }
} }

View File

@ -30,46 +30,57 @@ import org.apache.poi.util.POILogger;
public class XDGFFactory extends POIXMLFactory { public class XDGFFactory extends POIXMLFactory {
private static final POILogger logger = POILogFactory.getLogger(XDGFFactory.class); private static final POILogger logger = POILogFactory
.getLogger(XDGFFactory.class);
private XDGFDocument _document; private XDGFDocument _document;
public XDGFFactory(XDGFDocument document){ public XDGFFactory(XDGFDocument document) {
_document = document; _document = document;
} }
@Override @Override
public POIXMLDocumentPart createDocumentPart(POIXMLDocumentPart parent, public POIXMLDocumentPart createDocumentPart(POIXMLDocumentPart parent,
PackageRelationship rel, PackagePart part) { PackageRelationship rel, PackagePart part) {
POIXMLRelation descriptor = XDGFRelation.getInstance(rel.getRelationshipType()); POIXMLRelation descriptor = XDGFRelation.getInstance(rel
if(descriptor == null || descriptor.getRelationClass() == null){ .getRelationshipType());
logger.log(POILogger.DEBUG, "using default POIXMLDocumentPart for " + rel.getRelationshipType()); if (descriptor == null || descriptor.getRelationClass() == null) {
logger.log(POILogger.DEBUG, "using default POIXMLDocumentPart for "
+ rel.getRelationshipType());
return new POIXMLDocumentPart(part, rel); return new POIXMLDocumentPart(part, rel);
} }
try { try {
Class<? extends POIXMLDocumentPart> cls = descriptor.getRelationClass(); Class<? extends POIXMLDocumentPart> cls = descriptor
.getRelationClass();
try { 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); return constructor.newInstance(parent, part, rel, _document);
} catch (NoSuchMethodException e) { } 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); return constructor.newInstance(part, rel, _document);
} }
} catch (Exception e){ } catch (Exception e) {
throw new POIXMLException(e); throw new POIXMLException(e);
} }
} }
@Override @Override
public POIXMLDocumentPart newDocumentPart(POIXMLRelation descriptor) { public POIXMLDocumentPart newDocumentPart(POIXMLRelation descriptor) {
try { try {
Class<? extends POIXMLDocumentPart> cls = descriptor.getRelationClass(); Class<? extends POIXMLDocumentPart> cls = descriptor
Constructor<? extends POIXMLDocumentPart> constructor = cls.getDeclaredConstructor(); .getRelationClass();
Constructor<? extends POIXMLDocumentPart> constructor = cls
.getDeclaredConstructor();
return constructor.newInstance(); return constructor.newInstance();
} catch (Exception e){ } catch (Exception e) {
throw new POIXMLException(e); throw new POIXMLException(e);
} }
} }
} }

View File

@ -26,43 +26,44 @@ import com.microsoft.schemas.office.visio.x2012.main.MasterType;
*/ */
public class XDGFMaster { public class XDGFMaster {
private MasterType _master; private MasterType _master;
private XDGFMasterContents _content; private XDGFMasterContents _content;
XDGFSheet _pageSheet = null; XDGFSheet _pageSheet = null;
public XDGFMaster(MasterType master, XDGFMasterContents content, XDGFDocument document) { public XDGFMaster(MasterType master, XDGFMasterContents content,
_master = master; XDGFDocument document) {
_content = content; _master = master;
content.setMaster(this); _content = content;
content.setMaster(this);
if (master.isSetPageSheet()) if (master.isSetPageSheet())
_pageSheet = new XDGFPageSheet(master.getPageSheet(), document); _pageSheet = new XDGFPageSheet(master.getPageSheet(), document);
} }
@Internal @Internal
MasterType getXmlObject() { MasterType getXmlObject() {
return _master; return _master;
} }
@Override @Override
public String toString() { public String toString() {
return "<Master ID=\"" + getID() + "\" " + _content + ">"; return "<Master ID=\"" + getID() + "\" " + _content + ">";
} }
public long getID() { public long getID() {
return _master.getID(); return _master.getID();
} }
public String getName() { public String getName() {
return _master.getName(); return _master.getName();
} }
public XDGFMasterContents getContent() { public XDGFMasterContents getContent() {
return _content; return _content;
} }
public XDGFSheet getPageSheet() { public XDGFSheet getPageSheet() {
return _pageSheet; return _pageSheet;
} }
} }

View File

@ -29,36 +29,39 @@ import com.microsoft.schemas.office.visio.x2012.main.MasterContentsDocument;
public class XDGFMasterContents extends XDGFBaseContents { public class XDGFMasterContents extends XDGFBaseContents {
private XDGFMaster _master; private XDGFMaster _master;
public XDGFMasterContents(PackagePart part, PackageRelationship rel, XDGFDocument document) { public XDGFMasterContents(PackagePart part, PackageRelationship rel,
super(part, rel, document); XDGFDocument document) {
} super(part, rel, document);
}
@Override @Override
protected void onDocumentRead() { protected void onDocumentRead() {
try { try {
try { try {
_pageContents = MasterContentsDocument.Factory.parse(getPackagePart().getInputStream()).getMasterContents(); _pageContents = MasterContentsDocument.Factory.parse(getPackagePart().getInputStream()).getMasterContents();
} catch (XmlException | IOException e) { } catch (XmlException e) {
throw new POIXMLException(e); throw new POIXMLException(e);
} } catch (IOException e) {
throw new POIXMLException(e);
}
super.onDocumentRead(); super.onDocumentRead();
} catch (POIXMLException e) { } catch (POIXMLException e) {
throw XDGFException.wrap(this, e); throw XDGFException.wrap(this, e);
} }
} }
public XDGFMaster getMaster() { public XDGFMaster getMaster() {
return _master; return _master;
} }
protected void setMaster(XDGFMaster master) { protected void setMaster(XDGFMaster master) {
_master = master; _master = master;
} }
} }

View File

@ -38,62 +38,64 @@ import com.microsoft.schemas.office.visio.x2012.main.MastersType;
public class XDGFMasters extends XDGFXMLDocumentPart { public class XDGFMasters extends XDGFXMLDocumentPart {
MastersType _mastersObject; MastersType _mastersObject;
// key: id of master // key: id of master
Map<Long, XDGFMaster> _masters = new HashMap<>(); Map<Long, XDGFMaster> _masters = new HashMap<Long, XDGFMaster>();
public XDGFMasters(PackagePart part, PackageRelationship rel, XDGFDocument document) { public XDGFMasters(PackagePart part, PackageRelationship rel, XDGFDocument document) {
super(part, rel, document); super(part, rel, document);
} }
@Internal @Internal
MastersType getXmlObject() { MastersType getXmlObject() {
return _mastersObject; return _mastersObject;
} }
@Override @Override
protected void onDocumentRead() { protected void onDocumentRead() {
try { try {
try { try {
_mastersObject = MastersDocument.Factory.parse(getPackagePart().getInputStream()).getMasters(); _mastersObject = MastersDocument.Factory.parse(getPackagePart().getInputStream()).getMasters();
} catch (XmlException | IOException e) { } catch (XmlException e) {
throw new POIXMLException(e); throw new POIXMLException(e);
} } catch (IOException e) {
throw new POIXMLException(e);
}
Map<String, MasterType> masterSettings = new HashMap<>(); Map<String, MasterType> masterSettings = new HashMap<String, MasterType>();
for (MasterType master: _mastersObject.getMasterArray()) { for (MasterType master: _mastersObject.getMasterArray()) {
masterSettings.put(master.getRel().getId(), master); masterSettings.put(master.getRel().getId(), master);
} }
// create the masters // create the masters
for (POIXMLDocumentPart part: getRelations()) { for (POIXMLDocumentPart part: getRelations()) {
String relId = part.getPackageRelationship().getId(); String relId = part.getPackageRelationship().getId();
MasterType settings = masterSettings.get(relId); MasterType settings = masterSettings.get(relId);
if (settings == null) if (settings == null)
throw new POIXMLException("Master relationship for " + relId + " not found"); throw new POIXMLException("Master relationship for " + relId + " not found");
if (!(part instanceof XDGFMasterContents)) if (!(part instanceof XDGFMasterContents))
throw new POIXMLException("Unexpected masters relationship for " + relId + ": " + part); throw new POIXMLException("Unexpected masters relationship for " + relId + ": " + part);
XDGFMasterContents contents = (XDGFMasterContents)part; XDGFMasterContents contents = (XDGFMasterContents)part;
contents.onDocumentRead(); contents.onDocumentRead();
XDGFMaster master = new XDGFMaster(settings, contents, _document); XDGFMaster master = new XDGFMaster(settings, contents, _document);
_masters.put(master.getID(), master); _masters.put(master.getID(), master);
} }
} catch (POIXMLException e) { } catch (POIXMLException e) {
throw XDGFException.wrap(this, e); throw XDGFException.wrap(this, e);
} }
} }
public Collection<XDGFMaster> getMastersList() { public Collection<XDGFMaster> getMastersList() {
return Collections.unmodifiableCollection(_masters.values()); return Collections.unmodifiableCollection(_masters.values());
} }
public XDGFMaster getMasterById(long masterId) { public XDGFMaster getMasterById(long masterId) {
return _masters.get(masterId); return _masters.get(masterId);
} }
} }

View File

@ -31,83 +31,82 @@ import com.microsoft.schemas.office.visio.x2012.main.PageType;
*/ */
public class XDGFPage { public class XDGFPage {
PageType _page; PageType _page;
XDGFPageContents _content; XDGFPageContents _content;
XDGFPages _pages; XDGFPages _pages;
XDGFSheet _pageSheet = null; XDGFSheet _pageSheet = null;
public XDGFPage(PageType page, XDGFPageContents content, XDGFDocument document, XDGFPages pages) { public XDGFPage(PageType page, XDGFPageContents content,
_page = page; XDGFDocument document, XDGFPages pages) {
_content = content; _page = page;
_pages = pages; _content = content;
content.setPage(this); _pages = pages;
content.setPage(this);
if (page.isSetPageSheet()) if (page.isSetPageSheet())
_pageSheet = new XDGFPageSheet(page.getPageSheet(), document); _pageSheet = new XDGFPageSheet(page.getPageSheet(), document);
} }
@Internal @Internal
PageType getXmlObject() { PageType getXmlObject() {
return _page; return _page;
} }
public long getID() { public long getID() {
return _page.getID(); return _page.getID();
} }
public String getName() { public String getName() {
return _page.getName(); return _page.getName();
} }
public XDGFPageContents getContent() { public XDGFPageContents getContent() {
return _content; return _content;
} }
public XDGFSheet getPageSheet() { public XDGFSheet getPageSheet() {
return _pageSheet; return _pageSheet;
} }
public long getPageNumber() { public long getPageNumber() {
return _pages.getPageList().indexOf(this) + 1; return _pages.getPageList().indexOf(this) + 1;
} }
// height/width of page // height/width of page
public Dimension2dDouble getPageSize() { public Dimension2dDouble getPageSize() {
XDGFCell w = _pageSheet.getCell("PageWidth"); XDGFCell w = _pageSheet.getCell("PageWidth");
XDGFCell h = _pageSheet.getCell("PageHeight"); XDGFCell h = _pageSheet.getCell("PageHeight");
if (w == null || h == null) if (w == null || h == null)
throw new POIXMLException("Cannot determine page size"); throw new POIXMLException("Cannot determine page size");
return new Dimension2dDouble(Double.parseDouble(w.getValue()), return new Dimension2dDouble(Double.parseDouble(w.getValue()),
Double.parseDouble(h.getValue())); Double.parseDouble(h.getValue()));
} }
// origin of coordinate system // origin of coordinate system
public Point2D.Double getPageOffset() { public Point2D.Double getPageOffset() {
XDGFCell xoffcell = _pageSheet.getCell("XRulerOrigin"); XDGFCell xoffcell = _pageSheet.getCell("XRulerOrigin");
XDGFCell yoffcell = _pageSheet.getCell("YRulerOrigin"); XDGFCell yoffcell = _pageSheet.getCell("YRulerOrigin");
double xoffset = 0; double xoffset = 0;
double yoffset = 0; double yoffset = 0;
if (xoffcell != null) if (xoffcell != null)
xoffset = Double.parseDouble(xoffcell.getValue()); xoffset = Double.parseDouble(xoffcell.getValue());
if (xoffcell != null) if (xoffcell != null)
yoffset = Double.parseDouble(yoffcell.getValue()); yoffset = Double.parseDouble(yoffcell.getValue());
return new Point2D.Double(xoffset, yoffset); return new Point2D.Double(xoffset, yoffset);
} }
// bounding box of page // bounding box of page
public Rectangle2D getBoundingBox() { public Rectangle2D getBoundingBox() {
Dimension2dDouble sz = getPageSize(); Dimension2dDouble sz = getPageSize();
Point2D.Double offset = getPageOffset(); Point2D.Double offset = getPageOffset();
return new Rectangle2D.Double(-offset.getX(), return new Rectangle2D.Double(-offset.getX(), -offset.getY(),
-offset.getY(), sz.getWidth(), sz.getHeight());
sz.getWidth(), }
sz.getHeight());
}
} }

View File

@ -32,52 +32,54 @@ import com.microsoft.schemas.office.visio.x2012.main.PageContentsDocument;
public class XDGFPageContents extends XDGFBaseContents { public class XDGFPageContents extends XDGFBaseContents {
Map<Long, XDGFMaster> _masters = new HashMap<>(); Map<Long, XDGFMaster> _masters = new HashMap<Long, XDGFMaster>();
XDGFPage _page; XDGFPage _page;
public XDGFPageContents(PackagePart part, PackageRelationship rel, XDGFDocument document) { public XDGFPageContents(PackagePart part, PackageRelationship rel, XDGFDocument document) {
super(part, rel, document); super(part, rel, document);
} }
@Override @Override
protected void onDocumentRead() { protected void onDocumentRead() {
try { try {
try { try {
_pageContents = PageContentsDocument.Factory.parse(getPackagePart().getInputStream()).getPageContents(); _pageContents = PageContentsDocument.Factory.parse(getPackagePart().getInputStream()).getPageContents();
} catch (XmlException | IOException e) { } catch (XmlException e) {
throw new POIXMLException(e); throw new POIXMLException(e);
} } catch (IOException e) {
throw new POIXMLException(e);
}
for (POIXMLDocumentPart part: getRelations()) { for (POIXMLDocumentPart part: getRelations()) {
if (!(part instanceof XDGFMasterContents)) if (!(part instanceof XDGFMasterContents))
continue; continue;
//throw new POIXMLException("Unexpected page relation: " + part); //throw new POIXMLException("Unexpected page relation: " + part);
XDGFMaster master = ((XDGFMasterContents)part).getMaster(); XDGFMaster master = ((XDGFMasterContents)part).getMaster();
_masters.put(master.getID(), master); _masters.put(master.getID(), master);
} }
super.onDocumentRead(); super.onDocumentRead();
for (XDGFShape shape: _shapes.values()) { for (XDGFShape shape: _shapes.values()) {
if (shape.isTopmost()) if (shape.isTopmost())
shape.setupMaster(this, null); shape.setupMaster(this, null);
} }
} catch (POIXMLException e) { } catch (POIXMLException e) {
throw XDGFException.wrap(this, e); throw XDGFException.wrap(this, e);
} }
} }
public XDGFPage getPage() { public XDGFPage getPage() {
return _page; return _page;
} }
protected void setPage(XDGFPage page) { protected void setPage(XDGFPage page) {
_page = page; _page = page;
} }
public XDGFMaster getMasterById(long id) { public XDGFMaster getMasterById(long id) {
return _masters.get(id); return _masters.get(id);
} }
} }

View File

@ -21,16 +21,16 @@ import com.microsoft.schemas.office.visio.x2012.main.PageSheetType;
public class XDGFPageSheet extends XDGFSheet { public class XDGFPageSheet extends XDGFSheet {
PageSheetType _pageSheet; PageSheetType _pageSheet;
public XDGFPageSheet(PageSheetType sheet, XDGFDocument document) { public XDGFPageSheet(PageSheetType sheet, XDGFDocument document) {
super(sheet, document); super(sheet, document);
_pageSheet = sheet; _pageSheet = sheet;
} }
@Override @Override
PageSheetType getXmlObject() { PageSheetType getXmlObject() {
return _pageSheet; return _pageSheet;
} }
} }

View File

@ -40,56 +40,58 @@ import com.microsoft.schemas.office.visio.x2012.main.PagesType;
*/ */
public class XDGFPages extends XDGFXMLDocumentPart { public class XDGFPages extends XDGFXMLDocumentPart {
PagesType _pagesObject; PagesType _pagesObject;
// ordered by page number // ordered by page number
List<XDGFPage> _pages = new ArrayList<>(); List<XDGFPage> _pages = new ArrayList<XDGFPage>();
public XDGFPages(PackagePart part, PackageRelationship rel, XDGFDocument document) { public XDGFPages(PackagePart part, PackageRelationship rel, XDGFDocument document) {
super(part, rel, document); super(part, rel, document);
} }
@Internal @Internal
PagesType getXmlObject() { PagesType getXmlObject() {
return _pagesObject; return _pagesObject;
} }
@Override @Override
protected void onDocumentRead() { protected void onDocumentRead() {
try { try {
try { try {
_pagesObject = PagesDocument.Factory.parse(getPackagePart().getInputStream()).getPages(); _pagesObject = PagesDocument.Factory.parse(getPackagePart().getInputStream()).getPages();
} catch (XmlException | IOException e) { } catch (XmlException e) {
throw new POIXMLException(e); throw new POIXMLException(e);
} } catch (IOException e) {
throw new POIXMLException(e);
}
// this iteration is ordered by page number // this iteration is ordered by page number
for (PageType pageSettings: _pagesObject.getPageArray()) { for (PageType pageSettings: _pagesObject.getPageArray()) {
String relId = pageSettings.getRel().getId(); String relId = pageSettings.getRel().getId();
POIXMLDocumentPart pageContentsPart = getRelationById(relId); POIXMLDocumentPart pageContentsPart = getRelationById(relId);
if (pageContentsPart == null) if (pageContentsPart == null)
throw new POIXMLException("PageSettings relationship for " + relId + " not found"); throw new POIXMLException("PageSettings relationship for " + relId + " not found");
if (!(pageContentsPart instanceof XDGFPageContents)) if (!(pageContentsPart instanceof XDGFPageContents))
throw new POIXMLException("Unexpected pages relationship for " + relId + ": " + pageContentsPart); throw new POIXMLException("Unexpected pages relationship for " + relId + ": " + pageContentsPart);
XDGFPageContents contents = (XDGFPageContents)pageContentsPart; XDGFPageContents contents = (XDGFPageContents)pageContentsPart;
XDGFPage page = new XDGFPage(pageSettings, contents, _document, this); XDGFPage page = new XDGFPage(pageSettings, contents, _document, this);
contents.onDocumentRead(); contents.onDocumentRead();
_pages.add(page); _pages.add(page);
} }
} catch (POIXMLException e) { } catch (POIXMLException e) {
throw XDGFException.wrap(this, e); throw XDGFException.wrap(this, e);
} }
} }
// ordered by page number // ordered by page number
public List<XDGFPage> getPageList() { public List<XDGFPage> getPageList() {
return Collections.unmodifiableList(_pages); return Collections.unmodifiableList(_pages);
} }
} }

View File

@ -26,7 +26,7 @@ import org.apache.poi.xdgf.xml.XDGFXMLDocumentPart;
public class XDGFRelation extends POIXMLRelation { public class XDGFRelation extends POIXMLRelation {
/** /**
* A map to lookup POIXMLRelation by its relation type * A map to lookup POIXMLRelation by its relation type
*/ */
protected static final Map<String, XDGFRelation> _table = new HashMap<String, XDGFRelation>(); 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( public static final XDGFRelation DOCUMENT = new XDGFRelation(
"application/vnd.ms-visio.drawing.main+xml", "application/vnd.ms-visio.drawing.main+xml",
"http://schemas.microsoft.com/visio/2010/relationships/document", "http://schemas.microsoft.com/visio/2010/relationships/document",
"/visio/document.xml", "/visio/document.xml", null);
null
);
public static final XDGFRelation MASTERS = new XDGFRelation( public static final XDGFRelation MASTERS = new XDGFRelation(
"application/vnd.ms-visio.masters+xml", "application/vnd.ms-visio.masters+xml",
"http://schemas.microsoft.com/visio/2010/relationships/masters", "http://schemas.microsoft.com/visio/2010/relationships/masters",
"/visio/masters/masters.xml", "/visio/masters/masters.xml", XDGFMasters.class);
XDGFMasters.class
);
public static final XDGFRelation MASTER = new XDGFRelation( public static final XDGFRelation MASTER = new XDGFRelation(
"application/vnd.ms-visio.master+xml", "application/vnd.ms-visio.master+xml",
"http://schemas.microsoft.com/visio/2010/relationships/master", "http://schemas.microsoft.com/visio/2010/relationships/master",
"/visio/masters/master#.xml", "/visio/masters/master#.xml", XDGFMasterContents.class);
XDGFMasterContents.class
);
public static final XDGFRelation IMAGES = new XDGFRelation( public static final XDGFRelation IMAGES = new XDGFRelation(null,
null, PackageRelationshipTypes.IMAGE_PART, null, null // XSSFPictureData.class
PackageRelationshipTypes.IMAGE_PART, );
null,
null // XSSFPictureData.class
);
public static final XDGFRelation PAGES = new XDGFRelation( public static final XDGFRelation PAGES = new XDGFRelation(
"application/vnd.ms-visio.pages+xml", "application/vnd.ms-visio.pages+xml",
"http://schemas.microsoft.com/visio/2010/relationships/pages", "http://schemas.microsoft.com/visio/2010/relationships/pages",
"/visio/pages/pages.xml", "/visio/pages/pages.xml", XDGFPages.class);
XDGFPages.class
);
public static final XDGFRelation PAGE = new XDGFRelation( public static final XDGFRelation PAGE = new XDGFRelation(
"application/vnd.ms-visio.page+xml", "application/vnd.ms-visio.page+xml",
"http://schemas.microsoft.com/visio/2010/relationships/page", "http://schemas.microsoft.com/visio/2010/relationships/page",
"/visio/pages/page#.xml", "/visio/pages/page#.xml", XDGFPageContents.class);
XDGFPageContents.class
);
public static final XDGFRelation WINDOW = new XDGFRelation( public static final XDGFRelation WINDOW = new XDGFRelation(
"application/vnd.ms-visio.windows+xml", "application/vnd.ms-visio.windows+xml",
"http://schemas.microsoft.com/visio/2010/relationships/windows", "http://schemas.microsoft.com/visio/2010/relationships/windows",
"/visio/windows.xml", "/visio/windows.xml", null);
null
);
private XDGFRelation(String type, String rel, String defaultName, Class<? extends XDGFXMLDocumentPart> cls) { private XDGFRelation(String type, String rel, String defaultName,
Class<? extends XDGFXMLDocumentPart> cls) {
super(type, rel, defaultName, 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 * 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> * <code>http://schemas.openxmlformats.org/officeDocument/2006/relationships/image</code>
* @return registered POIXMLRelation or null if not found * @return registered POIXMLRelation or null if not found
*/ */

File diff suppressed because it is too large Load Diff

View File

@ -39,166 +39,166 @@ import com.microsoft.schemas.office.visio.x2012.main.SheetType;
*/ */
public abstract class XDGFSheet { public abstract class XDGFSheet {
protected XDGFDocument _document; protected XDGFDocument _document;
protected SheetType _sheet; protected SheetType _sheet;
// cells // cells
protected Map<String, XDGFCell> _cells = new HashMap<>(); protected Map<String, XDGFCell> _cells = new HashMap<String, XDGFCell>();
// sections // sections
protected Map<String, XDGFSection> _sections = new HashMap<>(); protected Map<String, XDGFSection> _sections = new HashMap<String, XDGFSection>();
// special: geometry sections (key: index, value: section) // special: geometry sections (key: index, value: section)
protected SortedMap<Long, GeometrySection> _geometry = new TreeMap<>(); protected SortedMap<Long, GeometrySection> _geometry = new TreeMap<Long, GeometrySection>();
// special: character section // special: character section
protected CharacterSection _character = null; protected CharacterSection _character = null;
public XDGFSheet(SheetType sheet, XDGFDocument document) { public XDGFSheet(SheetType sheet, XDGFDocument document) {
try { try {
_sheet = sheet; _sheet = sheet;
_document = document; _document = document;
for (CellType cell: sheet.getCellArray()) { for (CellType cell: sheet.getCellArray()) {
if (_cells.containsKey(cell.getN())) if (_cells.containsKey(cell.getN()))
throw new POIXMLException("Unexpected duplicate cell " + cell.getN()); // this shouldn't happen throw new POIXMLException("Unexpected duplicate cell " + cell.getN()); // this shouldn't happen
_cells.put(cell.getN(), new XDGFCell(cell)); _cells.put(cell.getN(), new XDGFCell(cell));
} }
// only geometry sections can have duplicate names // only geometry sections can have duplicate names
// sections can be found in the master too, if there are no attributes here! // 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. // no idea if I have a master in this space. go figure.
for (SectionType section: sheet.getSectionArray()) { for (SectionType section: sheet.getSectionArray()) {
String name = section.getN(); String name = section.getN();
if (name.equals("Geometry")) { if (name.equals("Geometry")) {
_geometry.put(section.getIX(), new GeometrySection(section, this)); _geometry.put(section.getIX(), new GeometrySection(section, this));
} else if (name.equals("Character")) { } else if (name.equals("Character")) {
_character = new CharacterSection(section, this); _character = new CharacterSection(section, this);
} else { } else {
_sections.put(name, XDGFSection.load(section, this)); _sections.put(name, XDGFSection.load(section, this));
} }
} }
} catch (POIXMLException e) { } catch (POIXMLException e) {
throw XDGFException.wrap(this.toString(), e); throw XDGFException.wrap(this.toString(), e);
} }
} }
abstract SheetType getXmlObject(); abstract SheetType getXmlObject();
public XDGFDocument getDocument() { public XDGFDocument getDocument() {
return _document; return _document;
} }
// A cell is really just a setting // A cell is really just a setting
public XDGFCell getCell(String cellName) { public XDGFCell getCell(String cellName) {
return _cells.get(cellName); return _cells.get(cellName);
} }
public XDGFSection getSection(String sectionName) { public XDGFSection getSection(String sectionName) {
return _sections.get(sectionName); return _sections.get(sectionName);
} }
public XDGFStyleSheet getLineStyle() { public XDGFStyleSheet getLineStyle() {
if (!_sheet.isSetLineStyle()) if (!_sheet.isSetLineStyle())
return null; return null;
return _document.getStyleById(_sheet.getLineStyle()); return _document.getStyleById(_sheet.getLineStyle());
} }
public XDGFStyleSheet getFillStyle() { public XDGFStyleSheet getFillStyle() {
if (!_sheet.isSetFillStyle()) if (!_sheet.isSetFillStyle())
return null; return null;
return _document.getStyleById(_sheet.getFillStyle()); return _document.getStyleById(_sheet.getFillStyle());
} }
public XDGFStyleSheet getTextStyle() { public XDGFStyleSheet getTextStyle() {
if (!_sheet.isSetTextStyle()) if (!_sheet.isSetTextStyle())
return null; return null;
return _document.getStyleById(_sheet.getTextStyle()); return _document.getStyleById(_sheet.getTextStyle());
} }
public Color getFontColor() { public Color getFontColor() {
Color fontColor = null; Color fontColor = null;
if (_character != null) { if (_character != null) {
fontColor = _character.getFontColor(); fontColor = _character.getFontColor();
if (fontColor != null) if (fontColor != null)
return fontColor; return fontColor;
} }
XDGFStyleSheet style = getTextStyle(); XDGFStyleSheet style = getTextStyle();
if (style != null) if (style != null)
return style.getFontColor(); return style.getFontColor();
return null; return null;
} }
public Double getFontSize() { public Double getFontSize() {
Double fontSize = null; Double fontSize = null;
if (_character != null) { if (_character != null) {
fontSize = _character.getFontSize(); fontSize = _character.getFontSize();
if (fontSize != null) if (fontSize != null)
return fontSize; return fontSize;
} }
XDGFStyleSheet style = getTextStyle(); XDGFStyleSheet style = getTextStyle();
if (style != null) if (style != null)
return style.getFontSize(); return style.getFontSize();
return null; return null;
} }
public Integer getLineCap() { public Integer getLineCap() {
Integer lineCap = XDGFCell.maybeGetInteger(_cells, "LineCap"); Integer lineCap = XDGFCell.maybeGetInteger(_cells, "LineCap");
if (lineCap != null) if (lineCap != null)
return lineCap; return lineCap;
XDGFStyleSheet style = getLineStyle(); XDGFStyleSheet style = getLineStyle();
if (style != null) if (style != null)
return style.getLineCap(); return style.getLineCap();
return null; return null;
} }
public Color getLineColor() { public Color getLineColor() {
String lineColor = XDGFCell.maybeGetString(_cells, "LineColor"); String lineColor = XDGFCell.maybeGetString(_cells, "LineColor");
if (lineColor != null) if (lineColor != null)
return Color.decode(lineColor); return Color.decode(lineColor);
XDGFStyleSheet style = getLineStyle(); XDGFStyleSheet style = getLineStyle();
if (style != null) if (style != null)
return style.getLineColor(); return style.getLineColor();
return null; return null;
} }
public Integer getLinePattern() { public Integer getLinePattern() {
Integer linePattern = XDGFCell.maybeGetInteger(_cells, "LinePattern"); Integer linePattern = XDGFCell.maybeGetInteger(_cells, "LinePattern");
if (linePattern != null) if (linePattern != null)
return linePattern; return linePattern;
XDGFStyleSheet style = getLineStyle(); XDGFStyleSheet style = getLineStyle();
if (style != null) if (style != null)
return style.getLinePattern(); return style.getLinePattern();
return null; return null;
} }
public Double getLineWeight() { public Double getLineWeight() {
Double lineWeight = XDGFCell.maybeGetDouble(_cells, "LineWeight"); Double lineWeight = XDGFCell.maybeGetDouble(_cells, "LineWeight");
if (lineWeight != null) if (lineWeight != null)
return lineWeight; return lineWeight;
XDGFStyleSheet style = getLineStyle(); XDGFStyleSheet style = getLineStyle();
if (style != null) if (style != null)
return style.getLineWeight(); return style.getLineWeight();
return null; return null;
} }
} }

View File

@ -23,14 +23,14 @@ import com.microsoft.schemas.office.visio.x2012.main.StyleSheetType;
public class XDGFStyleSheet extends XDGFSheet { public class XDGFStyleSheet extends XDGFSheet {
public XDGFStyleSheet(StyleSheetType styleSheet, XDGFDocument document) { public XDGFStyleSheet(StyleSheetType styleSheet, XDGFDocument document) {
super(styleSheet, document); super(styleSheet, document);
} }
@Internal
public StyleSheetType getXmlObject() {
return (StyleSheetType)_sheet;
}
@Override
@Internal
public StyleSheetType getXmlObject() {
return (StyleSheetType) _sheet;
}
} }

View File

@ -33,118 +33,125 @@ import com.microsoft.schemas.office.visio.x2012.main.impl.TextTypeImpl;
public class XDGFText { public class XDGFText {
TextType _text; TextType _text;
XDGFShape _parent; XDGFShape _parent;
public XDGFText(TextType text, XDGFShape parent) { public XDGFText(TextType text, XDGFShape parent) {
_text = text; _text = text;
_parent = parent; _parent = parent;
} }
@Internal @Internal
TextType getXmlObject() { TextType getXmlObject() {
return _text; return _text;
} }
public String getTextContent() { public String getTextContent() {
// casting here is wrong, but there's no other way of getting the value, // 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 // as it doesn't seem to be exposed by complex types (even though this
// is a mixed type) // is a mixed type)
return ((TextTypeImpl)_text).getStringValue(); return ((TextTypeImpl) _text).getStringValue();
} }
// these are in the shape coordinate system // these are in the shape coordinate system
// -> See https://msdn.microsoft.com/en-us/library/hh644132(v=office.12).aspx // -> See
public Rectangle2D.Double getTextBounds() { // https://msdn.microsoft.com/en-us/library/hh644132(v=office.12).aspx
public Rectangle2D.Double getTextBounds() {
double txtPinX = _parent.getTxtPinX(); double txtPinX = _parent.getTxtPinX();
double txtPinY = _parent.getTxtPinY(); double txtPinY = _parent.getTxtPinY();
double txtLocPinX = _parent.getTxtLocPinX(); double txtLocPinX = _parent.getTxtLocPinX();
double txtLocPinY = _parent.getTxtLocPinY(); double txtLocPinY = _parent.getTxtLocPinY();
double txtWidth = _parent.getTxtWidth(); double txtWidth = _parent.getTxtWidth();
double txtHeight = _parent.getTxtHeight(); double txtHeight = _parent.getTxtHeight();
double x = txtPinX - txtLocPinX; double x = txtPinX - txtLocPinX;
double y = txtPinY - txtLocPinY; double y = txtPinY - txtLocPinY;
return new Rectangle2D.Double(x, y, txtWidth, txtHeight); return new Rectangle2D.Double(x, y, txtWidth, txtHeight);
} }
// returns bounds as a path in local coordinates // returns bounds as a path in local coordinates
// -> useful if you need to transform to global coordinates // -> useful if you need to transform to global coordinates
public Path2D.Double getBoundsAsPath() { public Path2D.Double getBoundsAsPath() {
Rectangle2D.Double rect = getTextBounds(); Rectangle2D.Double rect = getTextBounds();
Double w = rect.getWidth(); Double w = rect.getWidth();
Double h = rect.getHeight(); Double h = rect.getHeight();
Path2D.Double bounds = new Path2D.Double(); Path2D.Double bounds = new Path2D.Double();
bounds.moveTo(0, 0); bounds.moveTo(0, 0);
bounds.lineTo(w, 0); bounds.lineTo(w, 0);
bounds.lineTo(w, h); bounds.lineTo(w, h);
bounds.lineTo(0, h); bounds.lineTo(0, h);
bounds.lineTo(0, 0); bounds.lineTo(0, 0);
return bounds; return bounds;
} }
// center of text in local coordinates // center of text in local coordinates
public Point2D.Double getTextCenter() { public Point2D.Double getTextCenter() {
return new Point2D.Double(_parent.getTxtLocPinX(), _parent.getTxtLocPinY()); return new Point2D.Double(_parent.getTxtLocPinX(),
} _parent.getTxtLocPinY());
}
// assumes graphics is set properly to draw in the right style // assumes graphics is set properly to draw in the right style
public void draw(Graphics2D graphics) { public void draw(Graphics2D graphics) {
String textContent = getTextContent(); String textContent = getTextContent();
if (textContent.length() == 0) if (textContent.length() == 0)
return; return;
Rectangle2D.Double bounds = getTextBounds(); Rectangle2D.Double bounds = getTextBounds();
String[] lines = textContent.trim().split("\n"); String[] lines = textContent.trim().split("\n");
FontRenderContext frc = graphics.getFontRenderContext(); FontRenderContext frc = graphics.getFontRenderContext();
Font font = graphics.getFont(); Font font = graphics.getFont();
AffineTransform oldTr = graphics.getTransform(); AffineTransform oldTr = graphics.getTransform();
// visio is in flipped coordinates, so translate the text to be in the right place // visio is in flipped coordinates, so translate the text to be in the
Boolean flipX = _parent.getFlipX(); // right place
Boolean flipY = _parent.getFlipY(); Boolean flipX = _parent.getFlipX();
Boolean flipY = _parent.getFlipY();
if (flipY == null || !_parent.getFlipY()) { if (flipY == null || !_parent.getFlipY()) {
graphics.translate(bounds.x, bounds.y); graphics.translate(bounds.x, bounds.y);
graphics.scale(1, -1); graphics.scale(1, -1);
graphics.translate(0, -bounds.height + graphics.getFontMetrics().getMaxCharBounds(graphics).getHeight()); graphics.translate(0, -bounds.height
} + graphics.getFontMetrics().getMaxCharBounds(graphics)
.getHeight());
}
if (flipX != null && _parent.getFlipX()) { if (flipX != null && _parent.getFlipX()) {
graphics.scale(-1, 1); graphics.scale(-1, 1);
graphics.translate(-bounds.width, 0); graphics.translate(-bounds.width, 0);
} }
Double txtAngle = _parent.getTxtAngle(); Double txtAngle = _parent.getTxtAngle();
if (txtAngle != null && Math.abs(txtAngle) > 0.01) if (txtAngle != null && Math.abs(txtAngle) > 0.01)
graphics.rotate(txtAngle); graphics.rotate(txtAngle);
float nextY = 0; float nextY = 0;
for (String line: lines) { for (String line : lines) {
if (line.length() == 0) if (line.length() == 0)
continue; continue;
TextLayout layout = new TextLayout(line, font, frc); TextLayout layout = new TextLayout(line, font, frc);
if (layout.isLeftToRight()) if (layout.isLeftToRight())
layout.draw(graphics, 0, nextY); layout.draw(graphics, 0, nextY);
else else
layout.draw(graphics, (float)(bounds.width - layout.getAdvance()), nextY); layout.draw(graphics,
(float) (bounds.width - layout.getAdvance()), nextY);
nextY += layout.getAscent() + layout.getDescent() + layout.getLeading(); nextY += layout.getAscent() + layout.getDescent()
} + layout.getLeading();
}
graphics.setTransform(oldTr); graphics.setTransform(oldTr);
} }
} }

View File

@ -36,78 +36,75 @@ import com.microsoft.schemas.office.visio.x2012.main.VisioDocumentType;
public class XmlVisioDocument extends POIXMLDocument { public class XmlVisioDocument extends POIXMLDocument {
public static String CORE_DOCUMENT = "http://schemas.microsoft.com/visio/2010/relationships/document"; public static String CORE_DOCUMENT = "http://schemas.microsoft.com/visio/2010/relationships/document";
XDGFPages _pages; XDGFPages _pages;
XDGFMasters _masters; XDGFMasters _masters;
XDGFDocument _document; XDGFDocument _document;
public XmlVisioDocument(OPCPackage pkg) throws IOException {
super(pkg, CORE_DOCUMENT);
public XmlVisioDocument(OPCPackage pkg) throws IOException { VisioDocumentType document;
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);
}
try { _document = new XDGFDocument(document);
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
//build a tree of POIXMLDocumentParts, this document being the root
load(new XDGFFactory(_document)); load(new XDGFFactory(_document));
} }
public XmlVisioDocument(InputStream is) throws IOException { public XmlVisioDocument(InputStream is) throws IOException {
this(PackageHelper.open(is)); this(PackageHelper.open(is));
} }
@Override
@Override
protected void onDocumentRead() throws IOException { protected void onDocumentRead() throws IOException {
// by the time this gets called, all other document parts should // by the time this gets called, all other document parts should
// have been loaded, so it's safe to build the document structure // have been loaded, so it's safe to build the document structure
// note that in other onDocumentRead(), relations/etc may not have // note that in other onDocumentRead(), relations/etc may not have
// loaded yet, so it's not quite safe // loaded yet, so it's not quite safe
for (POIXMLDocumentPart part: getRelations()) { for (POIXMLDocumentPart part : getRelations()) {
// organize the document pieces // organize the document pieces
if (part instanceof XDGFPages) if (part instanceof XDGFPages)
_pages = (XDGFPages)part; _pages = (XDGFPages) part;
else if (part instanceof XDGFMasters) else if (part instanceof XDGFMasters)
_masters = (XDGFMasters)part; _masters = (XDGFMasters) part;
} }
if (_masters != null) if (_masters != null)
_masters.onDocumentRead(); _masters.onDocumentRead();
_pages.onDocumentRead(); _pages.onDocumentRead();
} }
@Override
public List<PackagePart> getAllEmbedds() throws OpenXML4JException {
throw new UnsupportedOperationException("Not implemented");
}
//
// Useful public API goes here
//
@Override public Collection<XDGFPage> getPages() {
public List<PackagePart> getAllEmbedds() throws OpenXML4JException { return _pages.getPageList();
throw new UnsupportedOperationException("Not implemented"); }
}
// public XDGFStyleSheet getStyleById(long id) {
// Useful public API goes here return _document.getStyleById(id);
// }
public Collection<XDGFPage> getPages() {
return _pages.getPageList();
}
public XDGFStyleSheet getStyleById(long id) {
return _document.getStyleById(id);
}
} }

View File

@ -30,42 +30,42 @@ import com.microsoft.schemas.office.visio.x2012.main.SectionType;
public class CharacterSection extends XDGFSection { public class CharacterSection extends XDGFSection {
Double _fontSize = null; Double _fontSize = null;
Color _fontColor = null; Color _fontColor = null;
Map<String, XDGFCell> _characterCells = new HashMap<>(); Map<String, XDGFCell> _characterCells = new HashMap<String, XDGFCell>();
public CharacterSection(SectionType section, XDGFSheet containingSheet) { public CharacterSection(SectionType section, XDGFSheet containingSheet) {
super(section, containingSheet); super(section, containingSheet);
// there aren't cells for this, just a single row // there aren't cells for this, just a single row
RowType row = section.getRowArray(0); RowType row = section.getRowArray(0);
for (CellType cell: row.getCellArray()) { for (CellType cell: row.getCellArray()) {
_characterCells.put(cell.getN(), new XDGFCell(cell)); _characterCells.put(cell.getN(), new XDGFCell(cell));
} }
if (row != null) { if (row != null) {
_fontSize = XDGFCell.maybeGetDouble(_characterCells, "Size"); _fontSize = XDGFCell.maybeGetDouble(_characterCells, "Size");
String tmpColor = XDGFCell.maybeGetString(_characterCells, "Color"); String tmpColor = XDGFCell.maybeGetString(_characterCells, "Color");
if (tmpColor != null) if (tmpColor != null)
_fontColor = Color.decode(tmpColor); _fontColor = Color.decode(tmpColor);
} }
} }
public Double getFontSize() { public Double getFontSize() {
return _fontSize; return _fontSize;
} }
public Color getFontColor() { public Color getFontColor() {
return _fontColor; return _fontColor;
} }
@Override @Override
public void setupMaster(XDGFSection section) { public void setupMaster(XDGFSection section) {
} }
} }

View File

@ -19,118 +19,119 @@ package org.apache.poi.xdgf.usermodel.section;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map.Entry;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.SortedMap; import java.util.SortedMap;
import java.util.Map.Entry;
// iterates over the base and master // iterates over the base and master
public class CombinedIterable<T> implements Iterable<T> { public class CombinedIterable<T> implements Iterable<T> {
final SortedMap<Long, T> _baseItems; final SortedMap<Long, T> _baseItems;
final SortedMap<Long, T> _masterItems; final SortedMap<Long, T> _masterItems;
public CombinedIterable(SortedMap<Long, T> baseItems, public CombinedIterable(SortedMap<Long, T> baseItems,
SortedMap<Long, T> masterItems) { SortedMap<Long, T> masterItems) {
_baseItems = baseItems; _baseItems = baseItems;
_masterItems = masterItems; _masterItems = masterItems;
} }
@Override @Override
public Iterator<T> iterator() { public Iterator<T> iterator() {
final Iterator<Entry<Long, T>> vmasterI; final Iterator<Entry<Long, T>> vmasterI;
if (_masterItems != null) if (_masterItems != null)
vmasterI = _masterItems.entrySet().iterator(); vmasterI = _masterItems.entrySet().iterator();
else else
vmasterI = Collections.emptyIterator(); vmasterI = Collections.emptyIterator();
return new Iterator<T>() { return new Iterator<T>() {
Long lastI = Long.MIN_VALUE; Long lastI = Long.MIN_VALUE;
Entry<Long, T> currentBase = null; Entry<Long, T> currentBase = null;
Entry<Long, T> currentMaster = null; Entry<Long, T> currentMaster = null;
// grab the iterator for both // grab the iterator for both
Iterator<Entry<Long, T>> baseI = _baseItems.entrySet().iterator(); Iterator<Entry<Long, T>> baseI = _baseItems.entrySet().iterator();
Iterator<Entry<Long, T>> masterI = vmasterI; Iterator<Entry<Long, T>> masterI = vmasterI;
@Override @Override
public boolean hasNext() { public boolean hasNext() {
return currentBase != null || currentMaster != null || baseI.hasNext() || masterI.hasNext(); return currentBase != null || currentMaster != null
} || baseI.hasNext() || masterI.hasNext();
}
@Override @Override
public T next() { public T next() {
// TODO: This seems far more complex than it needs to be // TODO: This seems far more complex than it needs to be
long baseIdx = Long.MAX_VALUE; long baseIdx = Long.MAX_VALUE;
long masterIdx = Long.MAX_VALUE; long masterIdx = Long.MAX_VALUE;
if (currentBase == null) { if (currentBase == null) {
while (baseI.hasNext()) { while (baseI.hasNext()) {
currentBase = baseI.next(); currentBase = baseI.next();
if (currentBase.getKey() > lastI) { if (currentBase.getKey() > lastI) {
baseIdx = currentBase.getKey(); baseIdx = currentBase.getKey();
break; break;
} }
} }
} else { } else {
baseIdx = currentBase.getKey(); baseIdx = currentBase.getKey();
} }
if (currentMaster == null) { if (currentMaster == null) {
while (masterI.hasNext()) { while (masterI.hasNext()) {
currentMaster = masterI.next(); currentMaster = masterI.next();
if (currentMaster.getKey() > lastI) { if (currentMaster.getKey() > lastI) {
masterIdx = currentMaster.getKey(); masterIdx = currentMaster.getKey();
break; break;
} }
} }
} else { } else {
masterIdx = currentMaster.getKey(); masterIdx = currentMaster.getKey();
} }
T val; T val;
if (currentBase != null) { if (currentBase != null) {
if (baseIdx <= masterIdx) { if (baseIdx <= masterIdx) {
lastI = baseIdx; lastI = baseIdx;
val = currentBase.getValue(); val = currentBase.getValue();
// discard master if same as base // discard master if same as base
if (masterIdx == baseIdx) { if (masterIdx == baseIdx) {
currentMaster = null; currentMaster = null;
} }
currentBase = null; currentBase = null;
} else { } else {
lastI = masterIdx; lastI = masterIdx;
val = currentMaster.getValue(); val = currentMaster.getValue();
currentMaster = null; currentMaster = null;
} }
} else if (currentMaster != null) { } else if (currentMaster != null) {
lastI = currentMaster.getKey(); lastI = currentMaster.getKey();
val = currentMaster.getValue(); val = currentMaster.getValue();
currentMaster = null; currentMaster = null;
} else { } else {
throw new NoSuchElementException(); throw new NoSuchElementException();
} }
return val; return val;
} }
@Override @Override
public void remove() { public void remove() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
}; };
} }
} }

View File

@ -23,11 +23,11 @@ import com.microsoft.schemas.office.visio.x2012.main.SectionType;
public class GenericSection extends XDGFSection { public class GenericSection extends XDGFSection {
public GenericSection(SectionType section, XDGFSheet containingSheet) { public GenericSection(SectionType section, XDGFSheet containingSheet) {
super(section, containingSheet); super(section, containingSheet);
} }
@Override @Override
public void setupMaster(XDGFSection section) { public void setupMaster(XDGFSection section) {
} }
} }

View File

@ -29,9 +29,9 @@ import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape; import org.apache.poi.xdgf.usermodel.XDGFShape;
import org.apache.poi.xdgf.usermodel.XDGFSheet; import org.apache.poi.xdgf.usermodel.XDGFSheet;
import org.apache.poi.xdgf.usermodel.section.geometry.Ellipse; 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.GeometryRowFactory;
import org.apache.poi.xdgf.usermodel.section.geometry.InfiniteLine; 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.SplineKnot;
import org.apache.poi.xdgf.usermodel.section.geometry.SplineStart; 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 { public class GeometrySection extends XDGFSection {
GeometrySection _master = null; GeometrySection _master = null;
// rows // rows
SortedMap<Long, GeometryRow> _rows = new TreeMap<>(); SortedMap<Long, GeometryRow> _rows = new TreeMap<Long, GeometryRow>();
public GeometrySection(SectionType section, XDGFSheet containingSheet) { public GeometrySection(SectionType section, XDGFSheet containingSheet) {
super(section, containingSheet); super(section, containingSheet);
for (RowType row: section.getRowArray()) { for (RowType row: section.getRowArray()) {
if (_rows.containsKey(row.getIX())) if (_rows.containsKey(row.getIX()))
throw new POIXMLException("Index element '" + row.getIX() + "' already exists"); throw new POIXMLException("Index element '" + row.getIX() + "' already exists");
_rows.put(row.getIX(), GeometryRowFactory.load(row)); _rows.put(row.getIX(), GeometryRowFactory.load(row));
} }
} }
@Override @Override
public void setupMaster(XDGFSection master) { public void setupMaster(XDGFSection master) {
_master = (GeometrySection)master; _master = (GeometrySection)master;
for (Entry<Long, GeometryRow> entry : _rows.entrySet()) { for (Entry<Long, GeometryRow> entry : _rows.entrySet()) {
GeometryRow masterRow = _master._rows.get(entry.getKey()); GeometryRow masterRow = _master._rows.get(entry.getKey());
if (masterRow != null) { if (masterRow != null) {
try { try {
entry.getValue().setupMaster(masterRow); entry.getValue().setupMaster(masterRow);
} catch (ClassCastException e) { } catch (ClassCastException e) {
// this can happen when a dynamic connector overrides its master's geometry // this can happen when a dynamic connector overrides its master's geometry
// .. probably can happen elsewhere too, I imagine. // .. probably can happen elsewhere too, I imagine.
//throw XDGFException.error("Mismatched geometry section '" + entry.getKey() + "' in master", this, e); //throw XDGFException.error("Mismatched geometry section '" + entry.getKey() + "' in master", this, e);
} }
} }
} }
} }
// returns True if this row shouldn't be displayed // returns True if this row shouldn't be displayed
public Boolean getNoShow() { public Boolean getNoShow() {
Boolean noShow = XDGFCell.maybeGetBoolean(_cells, "NoShow"); Boolean noShow = XDGFCell.maybeGetBoolean(_cells, "NoShow");
if (noShow == null) { if (noShow == null) {
if (_master != null) if (_master != null)
return _master.getNoShow(); return _master.getNoShow();
return false; return false;
} }
return noShow; return noShow;
} }
public Iterable<GeometryRow> getCombinedRows() { public Iterable<GeometryRow> getCombinedRows() {
return new CombinedIterable<>(_rows, return new CombinedIterable<GeometryRow>(_rows,
_master == null ? null : _master._rows); _master == null ? null : _master._rows);
} }
public Path2D.Double getPath(XDGFShape parent) { public Path2D.Double getPath(XDGFShape parent) {
Iterator<GeometryRow> rows = getCombinedRows().iterator(); Iterator<GeometryRow> rows = getCombinedRows().iterator();
// special cases // special cases
GeometryRow first = rows.next(); GeometryRow first = rows.next();
if (first instanceof Ellipse) { if (first instanceof Ellipse) {
return ((Ellipse)first).getPath(); return ((Ellipse)first).getPath();
} else if (first instanceof InfiniteLine) { } else if (first instanceof InfiniteLine) {
return ((InfiniteLine)first).getPath(); return ((InfiniteLine)first).getPath();
} else if (first instanceof SplineStart) { } else if (first instanceof SplineStart) {
throw new POIXMLException("SplineStart must be preceded by another type"); throw new POIXMLException("SplineStart must be preceded by another type");
} else { } else {
// everything else is a path // everything else is a path
Path2D.Double path = new Path2D.Double(); Path2D.Double path = new Path2D.Double();
// dealing with splines makes this more complex // dealing with splines makes this more complex
SplineCollector renderer = null; SplineCollector renderer = null;
GeometryRow row; GeometryRow row;
while (true) { while (true) {
if (first != null) { if (first != null) {
row = first; row = first;
first = null; first = null;
} else { } else {
if (!rows.hasNext()) if (!rows.hasNext())
break; break;
row = rows.next(); row = rows.next();
} }
if (row instanceof SplineStart) { if (row instanceof SplineStart) {
if (renderer != null) if (renderer != null)
throw new POIXMLException("SplineStart found multiple times!"); throw new POIXMLException("SplineStart found multiple times!");
renderer = new SplineCollector((SplineStart) row); renderer = new SplineCollector((SplineStart) row);
} else if (row instanceof SplineKnot) { } else if (row instanceof SplineKnot) {
if (renderer == null) if (renderer == null)
throw new POIXMLException("SplineKnot found without SplineStart!"); throw new POIXMLException("SplineKnot found without SplineStart!");
renderer.addKnot((SplineKnot) row); renderer.addKnot((SplineKnot) row);
} else { } else {
if (renderer != null) { if (renderer != null) {
renderer.addToPath(path, parent); renderer.addToPath(path, parent);
renderer = null; renderer = null;
} }
row.addToPath(path, parent); row.addToPath(path, parent);
} }
} }
// just in case we end iteration // just in case we end iteration
if (renderer != null) if (renderer != null)
renderer.addToPath(path, parent); renderer.addToPath(path, parent);
return path; return path;
} }
} }
} }

View File

@ -31,68 +31,70 @@ import com.microsoft.schemas.office.visio.x2012.main.SectionType;
public abstract class XDGFSection { public abstract class XDGFSection {
static final ObjectFactory<XDGFSection, SectionType> _sectionTypes; static final ObjectFactory<XDGFSection, SectionType> _sectionTypes;
static { static {
_sectionTypes = new ObjectFactory<>(); _sectionTypes = new ObjectFactory<XDGFSection, SectionType>();
try { try {
_sectionTypes.put("LineGradient", GenericSection.class, SectionType.class, XDGFSheet.class); _sectionTypes.put("LineGradient", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("FillGradient", 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("Character", CharacterSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Paragraph", GenericSection.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("Tabs", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Scratch", 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("Connection", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("ConnectionABCD", 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("Field", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Control", 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("Geometry", GeometrySection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Actions", GenericSection.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("Layer", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("User", 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("Property", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Hyperlink", 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("Reviewer", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Annotation", GenericSection.class, SectionType.class, XDGFSheet.class); _sectionTypes.put("Annotation", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("ActionTag", GenericSection.class, SectionType.class, XDGFSheet.class); _sectionTypes.put("ActionTag", GenericSection.class, SectionType.class, XDGFSheet.class);
} catch (NoSuchMethodException | SecurityException e) { } catch (NoSuchMethodException e) {
throw new POIXMLException("Internal error"); throw new POIXMLException("Internal error");
} } catch (SecurityException e) {
throw new POIXMLException("Internal error");
}
} }
public static XDGFSection load(SectionType section, XDGFSheet containingSheet) { public static XDGFSection load(SectionType section, XDGFSheet containingSheet) {
return _sectionTypes.load(section.getN(), section, containingSheet); return _sectionTypes.load(section.getN(), section, containingSheet);
} }
protected SectionType _section; protected SectionType _section;
protected XDGFSheet _containingSheet; protected XDGFSheet _containingSheet;
protected Map<String, XDGFCell> _cells = new HashMap<>(); protected Map<String, XDGFCell> _cells = new HashMap<String, XDGFCell>();
public XDGFSection(SectionType section, XDGFSheet containingSheet) { public XDGFSection(SectionType section, XDGFSheet containingSheet) {
_section = section; _section = section;
_containingSheet = containingSheet; _containingSheet = containingSheet;
// only store cells in the base, not rows -- because rows are handled // only store cells in the base, not rows -- because rows are handled
// specially for geometry sections // specially for geometry sections
for (CellType cell: section.getCellArray()) { for (CellType cell: section.getCellArray()) {
_cells.put(cell.getN(), new XDGFCell(cell)); _cells.put(cell.getN(), new XDGFCell(cell));
} }
} }
@Internal @Internal
public SectionType getXmlObject() { public SectionType getXmlObject() {
return _section; return _section;
} }
@Override @Override
public String toString() { public String toString() {
return "<Section type=" + _section.getN() + " from " + _containingSheet + ">"; return "<Section type=" + _section.getN() + " from " + _containingSheet + ">";
} }
public abstract void setupMaster(XDGFSection section); public abstract void setupMaster(XDGFSection section);
} }

View File

@ -31,101 +31,104 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class ArcTo implements GeometryRow { public class ArcTo implements GeometryRow {
ArcTo _master = null; ArcTo _master = null;
// The x-coordinate of the ending vertex of an arc. // The x-coordinate of the ending vertex of an arc.
Double x = null; Double x = null;
// The y-coordinate of the ending vertex of an arc. // The y-coordinate of the ending vertex of an arc.
Double y = null; Double y = null;
// The distance from the arc's midpoint to the midpoint of its chord. // The distance from the arc's midpoint to the midpoint of its chord.
Double a = null; Double a = null;
Boolean deleted = null; Boolean deleted = null;
// TODO: support formulas // TODO: support formulas
public ArcTo(RowType row) { public ArcTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel(); if (row.isSetDel())
deleted = row.getDel();
for (CellType cell: row.getCellArray()) { for (CellType cell : row.getCellArray()) {
String cellName = cell.getN(); String cellName = cell.getN();
if (cellName.equals("X")) { if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell); x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) { } else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell); y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) { } else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell); a = XDGFCell.parseDoubleValue(cell);
} else { } else {
throw new POIXMLException("Invalid cell '" + cellName + "' in ArcTo row"); throw new POIXMLException("Invalid cell '" + cellName
} + "' in ArcTo row");
} }
} }
}
public boolean getDel() { public boolean getDel() {
if (deleted != null) if (deleted != null)
return deleted; return deleted;
if (_master != null) if (_master != null)
return _master.getDel(); return _master.getDel();
return false; return false;
} }
public Double getX() { public Double getX() {
return x == null ? _master.x : x; return x == null ? _master.x : x;
} }
public Double getY() { public Double getY() {
return y == null ? _master.y : y; return y == null ? _master.y : y;
} }
public Double getA() { public Double getA() {
return a == null ? _master.a : a; return a == null ? _master.a : a;
} }
@Override @Override
public void setupMaster(GeometryRow row) { public void setupMaster(GeometryRow row) {
_master = (ArcTo) row; _master = (ArcTo) row;
} }
@Override @Override
public void addToPath(Path2D.Double path, XDGFShape parent) { public void addToPath(Path2D.Double path, XDGFShape parent) {
if (getDel()) return; if (getDel())
return;
Point2D last = path.getCurrentPoint(); Point2D last = path.getCurrentPoint();
// intentionally shadowing variables here // intentionally shadowing variables here
double x = getX(); double x = getX();
double y = getY(); double y = getY();
double a = getA(); double a = getA();
if (a == 0) { if (a == 0) {
path.lineTo(x, y); path.lineTo(x, y);
return; return;
} }
double x0 = last.getX(); double x0 = last.getX();
double y0 = last.getY(); double y0 = last.getY();
double chordLength = Math.hypot(y - y0, x - x0); double chordLength = Math.hypot(y - y0, x - x0);
double radius = (4 * a * a + chordLength * chordLength) / (8 * Math.abs(a)); double radius = (4 * a * a + chordLength * chordLength)
/ (8 * Math.abs(a));
// center point // center point
double cx = x0 + (x - x0) / 2.0; double cx = x0 + (x - x0) / 2.0;
double cy = y0 + (y - y0) / 2.0; double cy = y0 + (y - y0) / 2.0;
double rotate = Math.atan2(y - cy, x - cx); double rotate = Math.atan2(y - cy, x - cx);
Arc2D arc = new Arc2D.Double(x0, y0 - radius, Arc2D arc = new Arc2D.Double(x0, y0 - radius, chordLength, 2 * radius,
chordLength, 2*radius, 180, x0 < x ? 180 : -180, Arc2D.OPEN);
180, x0 < x ? 180 : -180,
Arc2D.OPEN);
path.append(AffineTransform.getRotateInstance(rotate, x0, y0).createTransformedShape(arc), true); path.append(AffineTransform.getRotateInstance(rotate, x0, y0)
} .createTransformedShape(arc), true);
}
} }

View File

@ -30,127 +30,131 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class Ellipse implements GeometryRow { public class Ellipse implements GeometryRow {
Ellipse _master = null; Ellipse _master = null;
// x coordinate of center point // x coordinate of center point
Double x = null; Double x = null;
// y coordinate of center point // y coordinate of center point
Double y = null; Double y = null;
// x coordinate of first point on ellipse // x coordinate of first point on ellipse
Double a = null; Double a = null;
// y coordinate of first point on ellipse // y coordinate of first point on ellipse
Double b = null; Double b = null;
// x coordinate of second point on ellipse // x coordinate of second point on ellipse
Double c = null; Double c = null;
// y coordinate of second point on ellipse // y coordinate of second point on ellipse
Double d = null; Double d = null;
Boolean deleted = null; Boolean deleted = null;
// TODO: support formulas // TODO: support formulas
public Ellipse(RowType row) { public Ellipse(RowType row) {
if (row.isSetDel()) deleted = row.getDel(); if (row.isSetDel())
deleted = row.getDel();
for (CellType cell: row.getCellArray()) { for (CellType cell : row.getCellArray()) {
String cellName = cell.getN(); String cellName = cell.getN();
if (cellName.equals("X")) { if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell); x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) { } else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell); y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) { } else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell); a = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("B")) { } else if (cellName.equals("B")) {
b = XDGFCell.parseDoubleValue(cell); b = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("C")) { } else if (cellName.equals("C")) {
c = XDGFCell.parseDoubleValue(cell); c = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("D")) { } else if (cellName.equals("D")) {
d = XDGFCell.parseDoubleValue(cell); d = XDGFCell.parseDoubleValue(cell);
} else { } else {
throw new POIXMLException("Invalid cell '" + cellName + "' in Ellipse row"); throw new POIXMLException("Invalid cell '" + cellName
} + "' in Ellipse row");
} }
} }
}
public boolean getDel() { public boolean getDel() {
if (deleted != null) if (deleted != null)
return deleted; return deleted;
if (_master != null) if (_master != null)
return _master.getDel(); return _master.getDel();
return false; return false;
} }
public Double getX() { public Double getX() {
return x == null ? _master.x : x; return x == null ? _master.x : x;
} }
public Double getY() { public Double getY() {
return y == null ? _master.y : y; return y == null ? _master.y : y;
} }
public Double getA() { public Double getA() {
return a == null ? _master.a : a; return a == null ? _master.a : a;
} }
public Double getB() { public Double getB() {
return b == null ? _master.b : b; return b == null ? _master.b : b;
} }
public Double getC() { public Double getC() {
return c == null ? _master.c : c; return c == null ? _master.c : c;
} }
public Double getD() { public Double getD() {
return d == null ? _master.d : d; return d == null ? _master.d : d;
} }
@Override @Override
public void setupMaster(GeometryRow row) { public void setupMaster(GeometryRow row) {
_master = (Ellipse) row; _master = (Ellipse) row;
} }
public Path2D.Double getPath() { public Path2D.Double getPath() {
if (getDel()) return null; if (getDel())
return null;
// intentionally shadowing variables here // intentionally shadowing variables here
double cx = getX(); // center double cx = getX(); // center
double cy = getY(); double cy = getY();
double a = getA(); // left double a = getA(); // left
double b = getB(); double b = getB();
double c = getC(); // top double c = getC(); // top
double d = getD(); double d = getD();
// compute radius // compute radius
double rx = Math.hypot(a - cx, b - cy); double rx = Math.hypot(a - cx, b - cy);
double ry = Math.hypot(c - cx, d - cy); double ry = Math.hypot(c - cx, d - cy);
// compute angle of ellipse // 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); double angle = (2.0 * Math.PI + (cy > b ? 1.0 : -1.0)
* Math.acos((cx - a) / rx))
% (2.0 * Math.PI);
// create ellipse // create ellipse
Ellipse2D.Double ellipse = new Ellipse2D.Double(cx - rx, Ellipse2D.Double ellipse = new Ellipse2D.Double(cx - rx, cy - ry,
cy - ry, rx * 2, ry * 2);
rx*2, ry*2);
// create a path, rotate it about its center // create a path, rotate it about its center
Path2D.Double path = new Path2D.Double(ellipse); Path2D.Double path = new Path2D.Double(ellipse);
AffineTransform tr = new AffineTransform(); AffineTransform tr = new AffineTransform();
tr.rotate(angle, cx, cy); tr.rotate(angle, cx, cy);
path.transform(tr); path.transform(tr);
return path; return path;
} }
@Override @Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
throw new POIXMLException("Ellipse elements cannot be part of a path"); throw new POIXMLException("Ellipse elements cannot be part of a path");
} }
} }

View File

@ -19,7 +19,6 @@ package org.apache.poi.xdgf.usermodel.section.geometry;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D; import java.awt.geom.Arc2D;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import org.apache.poi.POIXMLException; import org.apache.poi.POIXMLException;
@ -31,201 +30,217 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class EllipticalArcTo implements GeometryRow { public class EllipticalArcTo implements GeometryRow {
EllipticalArcTo _master = null; EllipticalArcTo _master = null;
// The x-coordinate of the ending vertex on an arc. // The x-coordinate of the ending vertex on an arc.
Double x = null; Double x = null;
// The y-coordinate of the ending vertex on an arc. // The y-coordinate of the ending vertex on an arc.
Double y = null; Double y = null;
// The x-coordinate of the arc's control point; a point on the arc. The // 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 // control point is best located about halfway between the beginning and
// ending vertices of the arc. Otherwise, the arc may grow to an extreme // ending vertices of the arc. Otherwise, the arc may grow to an extreme
// size in order to pass through the control point, with unpredictable // size in order to pass through the control point, with unpredictable
// results. // results.
Double a = null; Double a = null;
// The y-coordinate of an arc's control point. // The y-coordinate of an arc's control point.
Double b = null; Double b = null;
// The angle of an arc's major axis relative to the x-axis of its parent shape. // The angle of an arc's major axis relative to the x-axis of its parent
Double c = null; // shape.
Double c = null;
// The ratio of an arc's major axis to its minor axis. Despite the usual // 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 // 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. // 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 // Setting this cell to a value less than or equal to 0 or greater than 1000
// can lead to unpredictable results. // can lead to unpredictable results.
Double d = null; Double d = null;
Boolean deleted = null; Boolean deleted = null;
// TODO: support formulas // TODO: support formulas
public EllipticalArcTo(RowType row) { public EllipticalArcTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel(); if (row.isSetDel())
deleted = row.getDel();
for (CellType cell: row.getCellArray()) { for (CellType cell : row.getCellArray()) {
String cellName = cell.getN(); String cellName = cell.getN();
if (cellName.equals("X")) { if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell); x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) { } else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell); y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) { } else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell); a = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("B")) { } else if (cellName.equals("B")) {
b = XDGFCell.parseDoubleValue(cell); b = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("C")) { } else if (cellName.equals("C")) {
c = XDGFCell.parseDoubleValue(cell); c = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("D")) { } else if (cellName.equals("D")) {
d = XDGFCell.parseDoubleValue(cell); d = XDGFCell.parseDoubleValue(cell);
} else { } else {
throw new POIXMLException("Invalid cell '" + cellName + "' in EllipticalArcTo row"); throw new POIXMLException("Invalid cell '" + cellName
} + "' in EllipticalArcTo row");
} }
} }
}
public boolean getDel() { public boolean getDel() {
if (deleted != null) if (deleted != null)
return deleted; return deleted;
if (_master != null) if (_master != null)
return _master.getDel(); return _master.getDel();
return false; return false;
} }
public Double getX() { public Double getX() {
return x == null ? _master.x : x; return x == null ? _master.x : x;
} }
public Double getY() { public Double getY() {
return y == null ? _master.y : y; return y == null ? _master.y : y;
} }
public Double getA() { public Double getA() {
return a == null ? _master.a : a; return a == null ? _master.a : a;
} }
public Double getB() { public Double getB() {
return b == null ? _master.b : b; return b == null ? _master.b : b;
} }
public Double getC() { public Double getC() {
return c == null ? _master.c : c; return c == null ? _master.c : c;
} }
public Double getD() { public Double getD() {
return d == null ? _master.d : d; return d == null ? _master.d : d;
} }
@Override
public void setupMaster(GeometryRow row) {
_master = (EllipticalArcTo) row;
}
@Override public static int draw = 0;
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) {
@Override if (getDel())
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { return;
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();
// intentionally shadowing variables here createEllipticalArc(x, y, a, b, c, d, path);
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) {
public static void createEllipticalArc(double x, double y, double a, double b, // Formula for center of ellipse by Junichi Yoda & nashwaan:
double c, double d, // -> From http://visguy.com/vgforum/index.php?topic=2464.0
java.awt.geom.Path2D.Double path) { //
// 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 }
//
// Formula for center of ellipse by Junichi Yoda & nashwaan: Point2D last = path.getCurrentPoint();
// -> From http://visguy.com/vgforum/index.php?topic=2464.0 double x0 = last.getX();
// double y0 = last.getY();
// 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(); // translate all of the points to the same angle as the ellipse
double x0 = last.getX(); AffineTransform at = AffineTransform.getRotateInstance(-c);
double y0 = last.getY(); double[] pts = new double[] { x0, y0, x, y, a, b };
at.transform(pts, 0, pts, 0, 3);
// translate all of the points to the same angle as the ellipse x0 = pts[0];
AffineTransform at = AffineTransform.getRotateInstance(-c); y0 = pts[1];
double[] pts = new double[]{x0, y0, x, y, a, b}; x = pts[2];
at.transform(pts, 0, pts, 0, 3); y = pts[3];
a = pts[4];
b = pts[5];
// nasty math time
x0 = pts[0]; y0 = pts[1]; double d2 = d * d;
x = pts[2]; y = pts[3]; double cx = ((x0 - x) * (x0 + x) * (y - b) - (x - a) * (x + a)
a = pts[4]; b = pts[5]; * (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)));
// nasty math time // calculate radii of ellipse
double rx = Math.sqrt(Math.pow(x0 - cx, 2) + Math.pow(y0 - cy, 2) * d2);
double ry = rx / d;
double d2 = d*d; // Arc2D requires us to draw an arc from one point to another, so we
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))); // need to calculate the angle of the start point and end point along
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))); // the ellipse
// - Derived from parametric form of ellipse: x = h + a*cos(t); y = k +
// b*sin(t)
// calculate radii of ellipse double ctrlAngle = Math.toDegrees(Math.atan2((b - cy) / ry, (a - cx)
double rx = Math.sqrt(Math.pow(x0-cx, 2) + Math.pow(y0-cy,2) * d2); / rx));
double ry = rx / d; double startAngle = Math.toDegrees(Math.atan2((y0 - cy) / ry, (x0 - cx)
/ rx));
double endAngle = Math.toDegrees(Math.atan2((y - cy) / ry, (x - cx)
/ rx));
// Arc2D requires us to draw an arc from one point to another, so we double sweep = computeSweep(startAngle, endAngle, ctrlAngle);
// 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)); // Now we have enough information to go on. Create the arc.
double startAngle = Math.toDegrees(Math.atan2((y0-cy)/ry, (x0-cx)/rx)); Arc2D arc = new Arc2D.Double(cx - rx, cy - ry, rx * 2, ry * 2,
double endAngle = Math.toDegrees(Math.atan2((y-cy)/ry, (x-cx)/rx)); -startAngle, sweep, Arc2D.OPEN);
double sweep = computeSweep(startAngle, endAngle, ctrlAngle); // rotate the arc back to the original coordinate system
at.setToRotation(c);
path.append(at.createTransformedShape(arc), false);
}
// Now we have enough information to go on. Create the arc. protected static double computeSweep(double startAngle, double endAngle,
Arc2D arc = new Arc2D.Double(cx-rx, cy-ry, double ctrlAngle) {
rx*2, ry*2, -startAngle, sweep, Arc2D.OPEN); double sweep;
// rotate the arc back to the original coordinate system startAngle = (360.0 + startAngle) % 360.0;
at.setToRotation(c); endAngle = (360.0 + endAngle) % 360.0;
path.append(at.createTransformedShape(arc), false); ctrlAngle = (360.0 + ctrlAngle) % 360.0;
}
protected static double computeSweep(double startAngle, double endAngle, double ctrlAngle) { // different sweeps depending on where the control point is
double sweep;
startAngle = (360.0 + startAngle) % 360.0; if (startAngle < endAngle) {
endAngle = (360.0 + endAngle) % 360.0; if (startAngle < ctrlAngle && ctrlAngle < endAngle) {
ctrlAngle = (360.0 + ctrlAngle) % 360.0; sweep = startAngle - endAngle;
} else {
sweep = 360 + (startAngle - endAngle);
}
} else {
if (endAngle < ctrlAngle && ctrlAngle < startAngle) {
sweep = startAngle - endAngle;
} else {
sweep = -(360 - (startAngle - endAngle));
}
}
// different sweeps depending on where the control point is return sweep;
}
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;
}
} }

View File

@ -21,11 +21,10 @@ import java.awt.geom.Path2D;
import org.apache.poi.xdgf.usermodel.XDGFShape; import org.apache.poi.xdgf.usermodel.XDGFShape;
public interface GeometryRow { public interface GeometryRow {
public void setupMaster(GeometryRow row); public void setupMaster(GeometryRow row);
public void addToPath(Path2D.Double path, XDGFShape parent); public void addToPath(Path2D.Double path, XDGFShape parent);
} }

View File

@ -24,34 +24,38 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class GeometryRowFactory { public class GeometryRowFactory {
static final ObjectFactory<GeometryRow, RowType> _rowTypes; static final ObjectFactory<GeometryRow, RowType> _rowTypes;
static { static {
_rowTypes = new ObjectFactory<>(); _rowTypes = new ObjectFactory<GeometryRow, RowType>();
try { try {
_rowTypes.put("ArcTo", ArcTo.class, RowType.class); _rowTypes.put("ArcTo", ArcTo.class, RowType.class);
_rowTypes.put("Ellipse", Ellipse.class, RowType.class); _rowTypes.put("Ellipse", Ellipse.class, RowType.class);
_rowTypes.put("EllipticalArcTo", EllipticalArcTo.class, RowType.class); _rowTypes.put("EllipticalArcTo", EllipticalArcTo.class,
_rowTypes.put("InfiniteLine", InfiniteLine.class, RowType.class); RowType.class);
_rowTypes.put("LineTo", LineTo.class, RowType.class); _rowTypes.put("InfiniteLine", InfiniteLine.class, RowType.class);
_rowTypes.put("MoveTo", MoveTo.class, RowType.class); _rowTypes.put("LineTo", LineTo.class, RowType.class);
_rowTypes.put("NURBSTo", NURBSTo.class, RowType.class); _rowTypes.put("MoveTo", MoveTo.class, RowType.class);
_rowTypes.put("PolyLineTo", PolyLineTo.class, RowType.class); _rowTypes.put("NURBSTo", NURBSTo.class, RowType.class);
_rowTypes.put("RelCubBezTo", RelCubBezTo.class, RowType.class); _rowTypes.put("PolyLineTo", PolyLineTo.class, RowType.class);
_rowTypes.put("RelEllipticalArcTo", RelEllipticalArcTo.class, RowType.class); _rowTypes.put("RelCubBezTo", RelCubBezTo.class, RowType.class);
_rowTypes.put("RelLineTo", RelLineTo.class, RowType.class); _rowTypes.put("RelEllipticalArcTo", RelEllipticalArcTo.class,
_rowTypes.put("RelMoveTo", RelMoveTo.class, RowType.class); RowType.class);
_rowTypes.put("RelQuadBezTo", RelQuadBezTo.class, RowType.class); _rowTypes.put("RelLineTo", RelLineTo.class, RowType.class);
_rowTypes.put("SplineKnot", SplineKnot.class, RowType.class); _rowTypes.put("RelMoveTo", RelMoveTo.class, RowType.class);
_rowTypes.put("SplineStart", SplineStart.class, RowType.class); _rowTypes.put("RelQuadBezTo", RelQuadBezTo.class, RowType.class);
} catch (NoSuchMethodException | SecurityException e) { _rowTypes.put("SplineKnot", SplineKnot.class, RowType.class);
throw new POIXMLException("Internal error", e); _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) { public static GeometryRow load(RowType row) {
return _rowTypes.load(row.getT(), row); return _rowTypes.load(row.getT(), row);
} }
} }

View File

@ -18,14 +18,9 @@
package org.apache.poi.xdgf.usermodel.section.geometry; package org.apache.poi.xdgf.usermodel.section.geometry;
import java.awt.geom.Path2D; import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.apache.poi.POIXMLException; 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.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFDocument;
import org.apache.poi.xdgf.usermodel.XDGFPage;
import org.apache.poi.xdgf.usermodel.XDGFShape; import org.apache.poi.xdgf.usermodel.XDGFShape;
import com.microsoft.schemas.office.visio.x2012.main.CellType; import com.microsoft.schemas.office.visio.x2012.main.CellType;
@ -36,116 +31,124 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType;
*/ */
public class InfiniteLine implements GeometryRow { public class InfiniteLine implements GeometryRow {
InfiniteLine _master = null; InfiniteLine _master = null;
// An x-coordinate of a point on the infinite line; paired with y-coordinate represented by the Y cell. // An x-coordinate of a point on the infinite line; paired with y-coordinate
Double x = null; // 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. // A y-coordinate of a point on the infinite line; paired with x-coordinate
Double y = null; // 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. // An x-coordinate of a point on the infinite line; paired with y-coordinate
Double a = null; // 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. // A y-coordinate of a point on an infinite line; paired with x-coordinate
Double b = null; // represented by the A cell.
Double b = null;
Boolean deleted = null; Boolean deleted = null;
// TODO: support formulas // TODO: support formulas
public InfiniteLine(RowType row) { public InfiniteLine(RowType row) {
if (row.isSetDel()) deleted = row.getDel(); if (row.isSetDel())
deleted = row.getDel();
for (CellType cell: row.getCellArray()) { for (CellType cell : row.getCellArray()) {
String cellName = cell.getN(); String cellName = cell.getN();
if (cellName.equals("X")) { if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell); x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) { } else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell); y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) { } else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell); a = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("B")) { } else if (cellName.equals("B")) {
b = XDGFCell.parseDoubleValue(cell); b = XDGFCell.parseDoubleValue(cell);
} else { } else {
throw new POIXMLException("Invalid cell '" + cellName + "' in InfiniteLine row"); throw new POIXMLException("Invalid cell '" + cellName
} + "' in InfiniteLine row");
} }
} }
}
public boolean getDel() { public boolean getDel() {
if (deleted != null) if (deleted != null)
return deleted; return deleted;
if (_master != null) if (_master != null)
return _master.getDel(); return _master.getDel();
return false; return false;
} }
public Double getX() { public Double getX() {
return x == null ? _master.x : x; return x == null ? _master.x : x;
} }
public Double getY() { public Double getY() {
return y == null ? _master.y : y; return y == null ? _master.y : y;
} }
public Double getA() { public Double getA() {
return a == null ? _master.a : a; return a == null ? _master.a : a;
} }
public Double getB() { public Double getB() {
return b == null ? _master.b : b; return b == null ? _master.b : b;
} }
@Override @Override
public void setupMaster(GeometryRow row) { public void setupMaster(GeometryRow row) {
_master = (InfiniteLine) row; _master = (InfiniteLine) row;
} }
@Override @Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return; if (getDel())
return;
throw new POIXMLException("InfiniteLine elements cannot be part of a path"); throw new POIXMLException(
} "InfiniteLine elements cannot be part of a path");
}
// returns this object as a line that extends between the boundaries of // returns this object as a line that extends between the boundaries of
// the document // the document
public Path2D.Double getPath() { public Path2D.Double getPath() {
Path2D.Double path = new Path2D.Double(); Path2D.Double path = new Path2D.Double();
// this is a bit of a hack, but it works // this is a bit of a hack, but it works
double max_val = 100000; double max_val = 100000;
// compute slope.. // compute slope..
double x0 = getX(); double x0 = getX();
double y0 = getY(); double y0 = getY();
double x1 = getA(); // second x double x1 = getA(); // second x
double y1 = getB(); // second y double y1 = getB(); // second y
if (x0 == x1) { if (x0 == x1) {
path.moveTo(x0, -max_val); path.moveTo(x0, -max_val);
path.lineTo(x0, max_val); path.lineTo(x0, max_val);
} else if (y0 == y1) { } else if (y0 == y1) {
path.moveTo(-max_val, y0); path.moveTo(-max_val, y0);
path.lineTo(max_val, y0); path.lineTo(max_val, y0);
} else { } else {
// normal case: compute slope/intercept // normal case: compute slope/intercept
double m = (y1 - y0) / (x1 - x0); double m = (y1 - y0) / (x1 - x0);
double c = y0 - m*x0; double c = y0 - m * x0;
// y = mx + c // y = mx + c
path.moveTo(max_val, m*max_val + c); path.moveTo(max_val, m * max_val + c);
path.lineTo(max_val, (max_val - c)/m); path.lineTo(max_val, (max_val - c) / m);
} }
return path; return path;
} }
} }

View File

@ -26,63 +26,66 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class LineTo implements GeometryRow { public class LineTo implements GeometryRow {
LineTo _master = null; LineTo _master = null;
Double x = null; Double x = null;
Double y = null; Double y = null;
Boolean deleted = null; Boolean deleted = null;
// TODO: support formulas // TODO: support formulas
public LineTo(RowType row) { public LineTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel(); if (row.isSetDel())
deleted = row.getDel();
for (CellType cell: row.getCellArray()) { for (CellType cell : row.getCellArray()) {
String cellName = cell.getN(); String cellName = cell.getN();
if (cellName.equals("X")) { if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell); x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) { } else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell); y = XDGFCell.parseDoubleValue(cell);
} else { } else {
throw new POIXMLException("Invalid cell '" + cellName + "' in LineTo row"); throw new POIXMLException("Invalid cell '" + cellName
} + "' in LineTo row");
} }
} }
}
@Override @Override
public String toString() { public String toString() {
return "LineTo: x=" + getX() + "; y=" + getY(); return "LineTo: x=" + getX() + "; y=" + getY();
} }
public boolean getDel() { public boolean getDel() {
if (deleted != null) if (deleted != null)
return deleted; return deleted;
if (_master != null) if (_master != null)
return _master.getDel(); return _master.getDel();
return false; return false;
} }
public Double getX() { public Double getX() {
return x == null ? _master.x : x; return x == null ? _master.x : x;
} }
public Double getY() { public Double getY() {
return y == null ? _master.y : y; return y == null ? _master.y : y;
} }
@Override @Override
public void setupMaster(GeometryRow row) { public void setupMaster(GeometryRow row) {
_master = (LineTo) row; _master = (LineTo) row;
} }
@Override @Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return; if (getDel())
path.lineTo(getX(), getY()); return;
} path.lineTo(getX(), getY());
}
} }

View File

@ -31,63 +31,66 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType;
*/ */
public class MoveTo implements GeometryRow { public class MoveTo implements GeometryRow {
MoveTo _master = null; MoveTo _master = null;
Double x = null; Double x = null;
Double y = null; Double y = null;
Boolean deleted = null; Boolean deleted = null;
// TODO: support formulas // TODO: support formulas
public MoveTo(RowType row) { public MoveTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel(); if (row.isSetDel())
deleted = row.getDel();
for (CellType cell: row.getCellArray()) { for (CellType cell : row.getCellArray()) {
String cellName = cell.getN(); String cellName = cell.getN();
if (cellName.equals("X")) { if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell); x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) { } else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell); y = XDGFCell.parseDoubleValue(cell);
} else { } else {
throw new POIXMLException("Invalid cell '" + cellName + "' in MoveTo row"); throw new POIXMLException("Invalid cell '" + cellName
} + "' in MoveTo row");
} }
} }
}
@Override @Override
public String toString() { public String toString() {
return "MoveTo: x=" + getX() + "; y=" + getY(); return "MoveTo: x=" + getX() + "; y=" + getY();
} }
public boolean getDel() { public boolean getDel() {
if (deleted != null) if (deleted != null)
return deleted; return deleted;
if (_master != null) if (_master != null)
return _master.getDel(); return _master.getDel();
return false; return false;
} }
public Double getX() { public Double getX() {
return x == null ? _master.x : x; return x == null ? _master.x : x;
} }
public Double getY() { public Double getY() {
return y == null ? _master.y : y; return y == null ? _master.y : y;
} }
@Override @Override
public void setupMaster(GeometryRow row) { public void setupMaster(GeometryRow row) {
_master = (MoveTo) row; _master = (MoveTo) row;
} }
@Override @Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return; if (getDel())
path.moveTo(getX(), getY()); return;
} path.moveTo(getX(), getY());
}
} }

View File

@ -20,186 +20,192 @@ package org.apache.poi.xdgf.usermodel.section.geometry;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import org.apache.poi.POIXMLException; 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.geom.SplineRenderer;
import org.apache.poi.xdgf.usermodel.XDGFCell; import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape; 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.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType; import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class NURBSTo implements GeometryRow { public class NURBSTo implements GeometryRow {
NURBSTo _master = null; NURBSTo _master = null;
// The x-coordinate of the last control point of a NURBS. // The x-coordinate of the last control point of a NURBS.
Double x = null; Double x = null;
// The y-coordinate of the last control point of a NURBS. // The y-coordinate of the last control point of a NURBS.
Double y = null; Double y = null;
// The second to the last knot of the NURBS. // The second to the last knot of the NURBS.
Double a = null; Double a = null;
// The last weight of the NURBS. // The last weight of the NURBS.
Double b = null; Double b = null;
// The first knot of the NURBS. // The first knot of the NURBS.
Double c = null; Double c = null;
// The first weight of the NURBS. // The first weight of the NURBS.
Double d = null; Double d = null;
// A NURBS formula. // A NURBS formula.
String e = null; String e = null;
Boolean deleted = null; Boolean deleted = null;
// TODO: support formulas // TODO: support formulas
public NURBSTo(RowType row) { public NURBSTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel(); if (row.isSetDel())
deleted = row.getDel();
for (CellType cell: row.getCellArray()) { for (CellType cell : row.getCellArray()) {
String cellName = cell.getN(); String cellName = cell.getN();
if (cellName.equals("X")) { if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell); x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) { } else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell); y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) { } else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell); a = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("B")) { } else if (cellName.equals("B")) {
b = XDGFCell.parseDoubleValue(cell); b = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("C")) { } else if (cellName.equals("C")) {
c = XDGFCell.parseDoubleValue(cell); c = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("D")) { } else if (cellName.equals("D")) {
d = XDGFCell.parseDoubleValue(cell); d = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("E")) { } else if (cellName.equals("E")) {
e = cell.getV(); e = cell.getV();
} else { } else {
throw new POIXMLException("Invalid cell '" + cellName + "' in NURBS row"); throw new POIXMLException("Invalid cell '" + cellName
} + "' in NURBS row");
} }
} }
}
public boolean getDel() { public boolean getDel() {
if (deleted != null) if (deleted != null)
return deleted; return deleted;
if (_master != null) if (_master != null)
return _master.getDel(); return _master.getDel();
return false; return false;
} }
public Double getX() { public Double getX() {
return x == null ? _master.x : x; return x == null ? _master.x : x;
} }
public Double getY() { public Double getY() {
return y == null ? _master.y : y; return y == null ? _master.y : y;
} }
public Double getA() { public Double getA() {
return a == null ? _master.a : a; return a == null ? _master.a : a;
} }
public Double getB() { public Double getB() {
return b == null ? _master.b : b; return b == null ? _master.b : b;
} }
public Double getC() { public Double getC() {
return c == null ? _master.c : c; return c == null ? _master.c : c;
} }
public Double getD() { public Double getD() {
return d == null ? _master.d : d; return d == null ? _master.d : d;
} }
public String getE() { public String getE() {
return e == null ? _master.e : e; return e == null ? _master.e : e;
} }
@Override @Override
public void setupMaster(GeometryRow row) { public void setupMaster(GeometryRow row) {
_master = (NURBSTo) row; _master = (NURBSTo) row;
} }
@Override @Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return; if (getDel())
return;
Point2D last = path.getCurrentPoint(); Point2D last = path.getCurrentPoint();
// A NURBS formula: knotLast, degree, xType, yType, x1, y1, knot1, weight1, .. // A NURBS formula: knotLast, degree, xType, yType, x1, y1, knot1,
String formula = getE().trim(); // weight1, ..
if (!formula.startsWith("NURBS(") || !formula.endsWith(")")) String formula = getE().trim();
throw new POIXMLException("Invalid NURBS formula: " + formula); if (!formula.startsWith("NURBS(") || !formula.endsWith(")"))
throw new POIXMLException("Invalid NURBS formula: " + formula);
String [] components = formula.substring(6, formula.length()-1).split(","); String[] components = formula.substring(6, formula.length() - 1).split(
",");
if (components.length < 8) if (components.length < 8)
throw new POIXMLException("Invalid NURBS formula (not enough arguments)"); throw new POIXMLException(
"Invalid NURBS formula (not enough arguments)");
if ((components.length - 4) % 4 != 0) if ((components.length - 4) % 4 != 0)
throw new POIXMLException("Invalid NURBS formula -- need 4 + n*4 arguments, got " + components.length); throw new POIXMLException(
"Invalid NURBS formula -- need 4 + n*4 arguments, got "
+ components.length);
double lastControlX = getX(); double lastControlX = getX();
double lastControlY = getY(); double lastControlY = getY();
double secondToLastKnot = getA(); double secondToLastKnot = getA();
double lastWeight = getB(); double lastWeight = getB();
double firstKnot = getC(); double firstKnot = getC();
double firstWeight = getD(); double firstWeight = getD();
double lastKnot = Double.parseDouble(components[0].trim()); double lastKnot = Double.parseDouble(components[0].trim());
int degree = Integer.parseInt(components[1].trim()); int degree = Integer.parseInt(components[1].trim());
int xType = Integer.parseInt(components[2].trim()); int xType = Integer.parseInt(components[2].trim());
int yType = Integer.parseInt(components[3].trim()); int yType = Integer.parseInt(components[3].trim());
double xScale = 1; double xScale = 1;
double yScale = 1; double yScale = 1;
if (xType == 0) if (xType == 0)
xScale = parent.getWidth(); xScale = parent.getWidth();
if (yType == 0) if (yType == 0)
yScale = parent.getHeight(); yScale = parent.getHeight();
// setup first knots/weights/control point // setup first knots/weights/control point
ControlPath controlPath = new ControlPath(); ControlPath controlPath = new ControlPath();
ValueVector knots = new ValueVector(); ValueVector knots = new ValueVector();
ValueVector weights = new ValueVector(); ValueVector weights = new ValueVector();
knots.add(firstKnot); knots.add(firstKnot);
weights.add(firstWeight); weights.add(firstWeight);
controlPath.addPoint(PointFactory.create(last.getX(), last.getY())); controlPath.addPoint(PointFactory.create(last.getX(), last.getY()));
// iterate get knots/weights // iterate get knots/weights
int sets = (components.length - 4) / 4; int sets = (components.length - 4) / 4;
for (int i = 0; i < sets; i++) { for (int i = 0; i < sets; i++) {
double x1 = Double.parseDouble(components[4 + i*4 + 0].trim()); double x1 = Double.parseDouble(components[4 + i * 4 + 0].trim());
double y1 = Double.parseDouble(components[4 + i*4 + 1].trim()); double y1 = Double.parseDouble(components[4 + i * 4 + 1].trim());
double k = Double.parseDouble(components[4 + i*4 + 2].trim()); double k = Double.parseDouble(components[4 + i * 4 + 2].trim());
double w = Double.parseDouble(components[4 + i*4 + 3].trim()); double w = Double.parseDouble(components[4 + i * 4 + 3].trim());
controlPath.addPoint(PointFactory.create(x1*xScale, y1*yScale)); controlPath.addPoint(PointFactory.create(x1 * xScale, y1 * yScale));
knots.add(k); knots.add(k);
weights.add(w); weights.add(w);
} }
// last knots/weights/control point // last knots/weights/control point
knots.add(secondToLastKnot); knots.add(secondToLastKnot);
knots.add(lastKnot); knots.add(lastKnot);
weights.add(lastWeight); weights.add(lastWeight);
controlPath.addPoint(PointFactory.create(lastControlX, lastControlY)); controlPath.addPoint(PointFactory.create(lastControlX, lastControlY));
ShapeMultiPath shape = SplineRenderer.createNurbsSpline(controlPath, knots, weights, degree); ShapeMultiPath shape = SplineRenderer.createNurbsSpline(controlPath,
path.append(shape, true); knots, weights, degree);
} path.append(shape, true);
}
} }

View File

@ -26,70 +26,73 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class PolyLineTo implements GeometryRow { public class PolyLineTo implements GeometryRow {
PolyLineTo _master = null; PolyLineTo _master = null;
// The x-coordinate of the ending vertex of a polyline. // The x-coordinate of the ending vertex of a polyline.
Double x = null; Double x = null;
// The y-coordinate of the ending vertex of a polyline. // The y-coordinate of the ending vertex of a polyline.
Double y = null; Double y = null;
// The polyline formula // The polyline formula
String a = null; String a = null;
Boolean deleted = null; Boolean deleted = null;
// TODO: support formulas // TODO: support formulas
public PolyLineTo(RowType row) { public PolyLineTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel(); if (row.isSetDel())
deleted = row.getDel();
for (CellType cell: row.getCellArray()) { for (CellType cell : row.getCellArray()) {
String cellName = cell.getN(); String cellName = cell.getN();
if (cellName.equals("X")) { if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell); x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) { } else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell); y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) { } else if (cellName.equals("A")) {
a = cell.getV(); a = cell.getV();
} else { } else {
throw new POIXMLException("Invalid cell '" + cellName + "' in ArcTo row"); throw new POIXMLException("Invalid cell '" + cellName
} + "' in ArcTo row");
} }
} }
}
public boolean getDel() { public boolean getDel() {
if (deleted != null) if (deleted != null)
return deleted; return deleted;
if (_master != null) if (_master != null)
return _master.getDel(); return _master.getDel();
return false; return false;
} }
public Double getX() { public Double getX() {
return x == null ? _master.x : x; return x == null ? _master.x : x;
} }
public Double getY() { public Double getY() {
return y == null ? _master.y : y; return y == null ? _master.y : y;
} }
public String getA() { public String getA() {
return a == null ? _master.a : a; return a == null ? _master.a : a;
} }
@Override @Override
public void setupMaster(GeometryRow row) { public void setupMaster(GeometryRow row) {
_master = (PolyLineTo) row; _master = (PolyLineTo) row;
} }
@Override @Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return; if (getDel())
throw new POIXMLException("Polyline support not implemented"); return;
} throw new POIXMLException("Polyline support not implemented");
}
} }

View File

@ -26,102 +26,114 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class RelCubBezTo implements GeometryRow { public class RelCubBezTo implements GeometryRow {
RelCubBezTo _master = null; RelCubBezTo _master = null;
// The x-coordinate of the ending vertex of a cubic Bézier curve relative to the width of the shape. // The x-coordinate of the ending vertex of a cubic Bezier curve relative to
Double x = null; // 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. // The y-coordinate of the ending vertex of a cubic Bezier curve relative to
Double y = null; // the height of the shape.
Double y = null;
// The x-coordinate of the curves beginning control point relative to the shapes width; a point on the arc. The control point is best located between the beginning and ending vertices of the arc. // The x-coordinate of the curve's beginning control point relative to the
Double a = null; // 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 curves beginning control point relative to the shapes height. // The y-coordinate of a curve's beginning control point relative to the
Double b = null; // shape's height.
Double b = null;
// The x-coordinate of the curves ending control point relative to the shapes width; a point on the arc. The control point is best located between the beginning control point and ending vertices of the arc. // The x-coordinate of the curve's ending control point relative to the
Double c = null; // 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 shapes height. // The y-coordinate of a curve's ending control point relative to the
Double d = null; // shape's height.
Double d = null;
Boolean deleted = null; Boolean deleted = null;
// TODO: support formulas // TODO: support formulas
public RelCubBezTo(RowType row) { public RelCubBezTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel(); if (row.isSetDel())
deleted = row.getDel();
for (CellType cell: row.getCellArray()) { for (CellType cell : row.getCellArray()) {
String cellName = cell.getN(); String cellName = cell.getN();
if (cellName.equals("X")) { if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell); x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) { } else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell); y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) { } else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell); a = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("B")) { } else if (cellName.equals("B")) {
b = XDGFCell.parseDoubleValue(cell); b = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("C")) { } else if (cellName.equals("C")) {
c = XDGFCell.parseDoubleValue(cell); c = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("D")) { } else if (cellName.equals("D")) {
d = XDGFCell.parseDoubleValue(cell); d = XDGFCell.parseDoubleValue(cell);
} else { } else {
throw new POIXMLException("Invalid cell '" + cellName + "' in RelCubBezTo row"); throw new POIXMLException("Invalid cell '" + cellName
} + "' in RelCubBezTo row");
} }
} }
}
public boolean getDel() { public boolean getDel() {
if (deleted != null) if (deleted != null)
return deleted; return deleted;
if (_master != null) if (_master != null)
return _master.getDel(); return _master.getDel();
return false; return false;
} }
public Double getX() { public Double getX() {
return x == null ? _master.x : x; return x == null ? _master.x : x;
} }
public Double getY() { public Double getY() {
return y == null ? _master.y : y; return y == null ? _master.y : y;
} }
public Double getA() { public Double getA() {
return a == null ? _master.a : a; return a == null ? _master.a : a;
} }
public Double getB() { public Double getB() {
return b == null ? _master.b : b; return b == null ? _master.b : b;
} }
public Double getC() { public Double getC() {
return c == null ? _master.c : c; return c == null ? _master.c : c;
} }
public Double getD() { public Double getD() {
return d == null ? _master.d : d; return d == null ? _master.d : d;
} }
@Override @Override
public void setupMaster(GeometryRow row) { public void setupMaster(GeometryRow row) {
_master = (RelCubBezTo) row; _master = (RelCubBezTo) row;
} }
@Override @Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return; if (getDel())
return;
double w = parent.getWidth(); double w = parent.getWidth();
double h = parent.getHeight(); double h = parent.getHeight();
path.curveTo(getA()*w, getB()*h, getC()*w, getD()*h, getX()*w, getY()*h); path.curveTo(getA() * w, getB() * h, getC() * w, getD() * h,
} getX() * w, getY() * h);
}
} }

View File

@ -26,116 +26,119 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class RelEllipticalArcTo implements GeometryRow { public class RelEllipticalArcTo implements GeometryRow {
RelEllipticalArcTo _master = null; RelEllipticalArcTo _master = null;
// The x-coordinate of the ending vertex on an arc relative to the width of // The x-coordinate of the ending vertex on an arc relative to the width of
// the shape. // the shape.
Double x = null; Double x = null;
// The y-coordinate of the ending vertex on an arc relative to the height of // The y-coordinate of the ending vertex on an arc relative to the height of
// the shape. // the shape.
Double y = null; Double y = null;
// The x-coordinate of the arc's control point relative to the shapes // The x-coordinate of the arc's control point relative to the shape's
// width; a point on the arc. // width; a point on the arc.
Double a = null; Double a = null;
// The y-coordinate of an arc's control point relative to the shapes width. // The y-coordinate of an arc's control point relative to the shape's width.
Double b = null; Double b = null;
// The angle of an arc's major axis relative to the x-axis of its parent. // The angle of an arc's major axis relative to the x-axis of its parent.
Double c = null; Double c = null;
// The ratio of an arc's major axis to its minor axis. Despite the usual // 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 // 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. // the "minor" axis, so this ratio does not have to be greater than 1.
Double d = null; Double d = null;
Boolean deleted = null; Boolean deleted = null;
// TODO: support formulas // TODO: support formulas
public RelEllipticalArcTo(RowType row) { public RelEllipticalArcTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel(); if (row.isSetDel())
deleted = row.getDel();
for (CellType cell: row.getCellArray()) { for (CellType cell : row.getCellArray()) {
String cellName = cell.getN(); String cellName = cell.getN();
if (cellName.equals("X")) { if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell); x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) { } else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell); y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) { } else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell); a = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("B")) { } else if (cellName.equals("B")) {
b = XDGFCell.parseDoubleValue(cell); b = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("C")) { } else if (cellName.equals("C")) {
c = XDGFCell.parseDoubleValue(cell); c = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("D")) { } else if (cellName.equals("D")) {
d = XDGFCell.parseDoubleValue(cell); d = XDGFCell.parseDoubleValue(cell);
} else { } else {
throw new POIXMLException("Invalid cell '" + cellName + "' in RelEllipticalArcTo row"); throw new POIXMLException("Invalid cell '" + cellName
} + "' in RelEllipticalArcTo row");
} }
} }
}
public boolean getDel() { public boolean getDel() {
if (deleted != null) if (deleted != null)
return deleted; return deleted;
if (_master != null) if (_master != null)
return _master.getDel(); return _master.getDel();
return false; return false;
} }
public Double getX() { public Double getX() {
return x == null ? _master.x : x; return x == null ? _master.x : x;
} }
public Double getY() { public Double getY() {
return y == null ? _master.y : y; return y == null ? _master.y : y;
} }
public Double getA() { public Double getA() {
return a == null ? _master.a : a; return a == null ? _master.a : a;
} }
public Double getB() { public Double getB() {
return b == null ? _master.b : b; return b == null ? _master.b : b;
} }
public Double getC() { public Double getC() {
return c == null ? _master.c : c; return c == null ? _master.c : c;
} }
public Double getD() { public Double getD() {
return d == null ? _master.d : d; return d == null ? _master.d : d;
} }
@Override @Override
public void setupMaster(GeometryRow row) { public void setupMaster(GeometryRow row) {
_master = (RelEllipticalArcTo) row; _master = (RelEllipticalArcTo) row;
} }
@Override @Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return; if (getDel())
return;
double w = parent.getWidth(); double w = parent.getWidth();
double h = parent.getHeight(); double h = parent.getHeight();
// intentionally shadowing variables here // intentionally shadowing variables here
double x = getX()*w; double x = getX() * w;
double y = getY()*h; double y = getY() * h;
double a = getA()*w; double a = getA() * w;
double b = getB()*h; double b = getB() * h;
double c = getC(); double c = getC();
double d = getD(); double d = getD();
EllipticalArcTo.createEllipticalArc(x, y, a, b, c, d, path); EllipticalArcTo.createEllipticalArc(x, y, a, b, c, d, path);
} }
} }

View File

@ -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 * Contains x-and y-coordinates of the ending vertex of a straight line segment
* relative to a shapes width and height. * relative to a shape's width and height.
*/ */
public class RelLineTo implements GeometryRow { public class RelLineTo implements GeometryRow {
RelLineTo _master = null; RelLineTo _master = null;
Double x = null; Double x = null;
Double y = null; Double y = null;
Boolean deleted = null; Boolean deleted = null;
// TODO: support formulas // TODO: support formulas
public RelLineTo(RowType row) { public RelLineTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel(); if (row.isSetDel())
deleted = row.getDel();
for (CellType cell: row.getCellArray()) { for (CellType cell : row.getCellArray()) {
String cellName = cell.getN(); String cellName = cell.getN();
if (cellName.equals("X")) { if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell); x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) { } else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell); y = XDGFCell.parseDoubleValue(cell);
} else { } else {
throw new POIXMLException("Invalid cell '" + cellName + "' in RelLineTo row"); throw new POIXMLException("Invalid cell '" + cellName
} + "' in RelLineTo row");
} }
} }
}
public boolean getDel() { public boolean getDel() {
if (deleted != null) if (deleted != null)
return deleted; return deleted;
if (_master != null) if (_master != null)
return _master.getDel(); return _master.getDel();
return false; return false;
} }
public Double getX() { public Double getX() {
return x == null ? _master.x : x; return x == null ? _master.x : x;
} }
public Double getY() { public Double getY() {
return y == null ? _master.y : y; return y == null ? _master.y : y;
} }
@Override @Override
public void setupMaster(GeometryRow row) { public void setupMaster(GeometryRow row) {
_master = (RelLineTo) row; _master = (RelLineTo) row;
} }
@Override @Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return; if (getDel())
return;
path.lineTo(getX()*parent.getWidth(), path.lineTo(getX() * parent.getWidth(), getY() * parent.getHeight());
getY()*parent.getHeight()); }
}
} }

View File

@ -26,61 +26,63 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class RelMoveTo implements GeometryRow { public class RelMoveTo implements GeometryRow {
RelMoveTo _master = null; RelMoveTo _master = null;
Double x = null; Double x = null;
Double y = null; Double y = null;
Boolean deleted = null; Boolean deleted = null;
// TODO: support formulas // TODO: support formulas
public RelMoveTo(RowType row) { public RelMoveTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel(); if (row.isSetDel())
deleted = row.getDel();
for (CellType cell: row.getCellArray()) { for (CellType cell : row.getCellArray()) {
String cellName = cell.getN(); String cellName = cell.getN();
if (cellName.equals("X")) { if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell); x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) { } else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell); y = XDGFCell.parseDoubleValue(cell);
} else { } else {
throw new POIXMLException("Invalid cell '" + cellName + "' in RelMoveTo row"); throw new POIXMLException("Invalid cell '" + cellName
} + "' in RelMoveTo row");
} }
} }
}
public boolean getDel() { public boolean getDel() {
if (deleted != null) if (deleted != null)
return deleted; return deleted;
if (_master != null) if (_master != null)
return _master.getDel(); return _master.getDel();
return false; return false;
} }
public Double getX() { public Double getX() {
return x == null ? _master.x : x; return x == null ? _master.x : x;
} }
public Double getY() { public Double getY() {
return y == null ? _master.y : y; return y == null ? _master.y : y;
} }
@Override @Override
public void setupMaster(GeometryRow row) { public void setupMaster(GeometryRow row) {
_master = (RelMoveTo) row; _master = (RelMoveTo) row;
} }
@Override @Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return; if (getDel())
return;
path.moveTo(getX()*parent.getWidth(), path.moveTo(getX() * parent.getWidth(), getY() * parent.getHeight());
getY()*parent.getHeight()); }
}
} }

View File

@ -25,90 +25,98 @@ import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType; import com.microsoft.schemas.office.visio.x2012.main.RowType;
/** /**
* Contains the x- and y-coordinates of the endpoint of a quadratic Bézier curve * Contains the x- and y-coordinates of the endpoint of a quadratic Bezier curve
* relative to the shapes width and height and the x- and y-coordinates of the * relative to the shape's width and height and the x- and y-coordinates of the
* control point of the curve relative shapes width and height. * control point of the curve relative shape's width and height.
*/ */
public class RelQuadBezTo implements GeometryRow { public class RelQuadBezTo implements GeometryRow {
RelQuadBezTo _master = null; RelQuadBezTo _master = null;
// The x-coordinate of the ending vertex of a quadratic Bézier curve relative to the width of the shape. // The x-coordinate of the ending vertex of a quadratic Bezier curve
Double x = null; // 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. // The y-coordinate of the ending vertex of a quadratic Bezier curve
Double y = null; // relative to the height of the shape.
Double y = null;
// The x-coordinate of the curves control point relative to the shapes width; a point on the arc. The control point is best located about halfway between the beginning and ending vertices of the arc. // The x-coordinate of the curve's control point relative to the shape's
Double a = null; // 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 curves control point relative to the shapes height. // The y-coordinate of a curve's control point relative to the shape's
Double b = null; // height.
Double b = null;
Boolean deleted = null; Boolean deleted = null;
// TODO: support formulas // TODO: support formulas
public RelQuadBezTo(RowType row) { public RelQuadBezTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel(); if (row.isSetDel())
deleted = row.getDel();
for (CellType cell: row.getCellArray()) { for (CellType cell : row.getCellArray()) {
String cellName = cell.getN(); String cellName = cell.getN();
if (cellName.equals("X")) { if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell); x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) { } else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell); y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) { } else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell); a = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("B")) { } else if (cellName.equals("B")) {
b = XDGFCell.parseDoubleValue(cell); b = XDGFCell.parseDoubleValue(cell);
} else { } else {
throw new POIXMLException("Invalid cell '" + cellName + "' in RelQuadBezTo row"); throw new POIXMLException("Invalid cell '" + cellName
} + "' in RelQuadBezTo row");
} }
} }
}
public boolean getDel() { public boolean getDel() {
if (deleted != null) if (deleted != null)
return deleted; return deleted;
if (_master != null) if (_master != null)
return _master.getDel(); return _master.getDel();
return false; return false;
} }
public Double getX() { public Double getX() {
return x == null ? _master.x : x; return x == null ? _master.x : x;
} }
public Double getY() { public Double getY() {
return y == null ? _master.y : y; return y == null ? _master.y : y;
} }
public Double getA() { public Double getA() {
return a == null ? _master.a : a; return a == null ? _master.a : a;
} }
public Double getB() { public Double getB() {
return b == null ? _master.b : b; return b == null ? _master.b : b;
} }
@Override @Override
public void setupMaster(GeometryRow row) { public void setupMaster(GeometryRow row) {
_master = (RelQuadBezTo) row; _master = (RelQuadBezTo) row;
} }
@Override @Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return; if (getDel())
return;
double w = parent.getWidth(); double w = parent.getWidth();
double h = parent.getHeight(); double h = parent.getHeight();
path.quadTo(getA()*w, getB()*h, getX()*w, getY()*h); path.quadTo(getA() * w, getB() * h, getX() * w, getY() * h);
} }
} }

View File

@ -25,78 +25,82 @@ import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType; 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 { public class SplineKnot implements GeometryRow {
SplineKnot _master = null; SplineKnot _master = null;
// The x-coordinate of a control point. // The x-coordinate of a control point.
Double x = null; Double x = null;
// The y-coordinate of a control point. // The y-coordinate of a control point.
Double y = null; Double y = null;
// One of the spline's knots (other than the last one or the first two). // One of the spline's knots (other than the last one or the first two).
Double a = null; Double a = null;
Boolean deleted = null; Boolean deleted = null;
// TODO: support formulas // TODO: support formulas
public SplineKnot(RowType row) { public SplineKnot(RowType row) {
if (row.isSetDel()) deleted = row.getDel(); if (row.isSetDel())
deleted = row.getDel();
for (CellType cell: row.getCellArray()) { for (CellType cell : row.getCellArray()) {
String cellName = cell.getN(); String cellName = cell.getN();
if (cellName.equals("X")) { if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell); x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) { } else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell); y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) { } else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell); a = XDGFCell.parseDoubleValue(cell);
} else { } else {
throw new POIXMLException("Invalid cell '" + cellName + "' in SplineKnot row"); throw new POIXMLException("Invalid cell '" + cellName
} + "' in SplineKnot row");
} }
} }
}
public boolean getDel() { public boolean getDel() {
if (deleted != null) if (deleted != null)
return deleted; return deleted;
if (_master != null) if (_master != null)
return _master.getDel(); return _master.getDel();
return false; return false;
} }
public Double getX() { public Double getX() {
return x == null ? _master.x : x; return x == null ? _master.x : x;
} }
public Double getY() { public Double getY() {
return y == null ? _master.y : y; return y == null ? _master.y : y;
} }
public Double getA() { public Double getA() {
return a == null ? _master.a : a; return a == null ? _master.a : a;
} }
@Override @Override
public void setupMaster(GeometryRow row) { public void setupMaster(GeometryRow row) {
_master = (SplineKnot) row; _master = (SplineKnot) row;
} }
@Override @Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
throw new POIXMLException("Error: Use SplineRenderer!"); throw new POIXMLException("Error: Use SplineRenderer!");
} }
@Override @Override
public String toString() { public String toString() {
return "{SplineKnot x=" + getX() + " y=" + getY() + " a=" + getA() + "}"; return "{SplineKnot x=" + getX() + " y=" + getY() + " a=" + getA()
} + "}";
}
} }

View File

@ -29,104 +29,104 @@ import com.microsoft.schemas.office.visio.x2012.main.RowType;
*/ */
public class SplineStart implements GeometryRow { public class SplineStart implements GeometryRow {
SplineStart _master = null; SplineStart _master = null;
// The x-coordinate of a spline's second control point. // The x-coordinate of a spline's second control point.
Double x = null; Double x = null;
// The y-coordinate of a spline's second control point. // The y-coordinate of a spline's second control point.
Double y = null; Double y = null;
// The second knot of the spline. // The second knot of the spline.
Double a = null; Double a = null;
// The first knot of a spline. // The first knot of a spline.
Double b = null; Double b = null;
// The last knot of a spline. // The last knot of a spline.
Double c = null; Double c = null;
// The degree of a spline (an integer from 1 to 25). // The degree of a spline (an integer from 1 to 25).
Integer d = null; Integer d = null;
Boolean deleted = null; Boolean deleted = null;
// TODO: support formulas // TODO: support formulas
public SplineStart(RowType row) { public SplineStart(RowType row) {
if (row.isSetDel()) deleted = row.getDel(); if (row.isSetDel())
deleted = row.getDel();
for (CellType cell: row.getCellArray()) { for (CellType cell : row.getCellArray()) {
String cellName = cell.getN(); String cellName = cell.getN();
if (cellName.equals("X")) { if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell); x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) { } else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell); y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) { } else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell); a = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("B")) { } else if (cellName.equals("B")) {
b = XDGFCell.parseDoubleValue(cell); b = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("C")) { } else if (cellName.equals("C")) {
c = XDGFCell.parseDoubleValue(cell); c = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("D")) { } else if (cellName.equals("D")) {
d = XDGFCell.parseIntegerValue(cell); d = XDGFCell.parseIntegerValue(cell);
} else { } else {
throw new POIXMLException("Invalid cell '" + cellName + "' in SplineStart row"); throw new POIXMLException("Invalid cell '" + cellName
} + "' in SplineStart row");
} }
} }
}
public boolean getDel() { public boolean getDel() {
if (deleted != null) if (deleted != null)
return deleted; return deleted;
if (_master != null) if (_master != null)
return _master.getDel(); return _master.getDel();
return false; return false;
} }
public Double getX() { public Double getX() {
return x == null ? _master.x : x; return x == null ? _master.x : x;
} }
public Double getY() { public Double getY() {
return y == null ? _master.y : y; return y == null ? _master.y : y;
} }
public Double getA() { public Double getA() {
return a == null ? _master.a : a; return a == null ? _master.a : a;
} }
public Double getB() { public Double getB() {
return b == null ? _master.b : b; return b == null ? _master.b : b;
} }
public Double getC() { public Double getC() {
return c == null ? _master.c : c; return c == null ? _master.c : c;
} }
public Integer getD() { public Integer getD() {
return d == null ? _master.d : d; return d == null ? _master.d : d;
} }
@Override @Override
public void setupMaster(GeometryRow row) { public void setupMaster(GeometryRow row) {
_master = (SplineStart) row; _master = (SplineStart) row;
} }
@Override @Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) { public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
throw new POIXMLException("Error: Use SplineRenderer!"); throw new POIXMLException("Error: Use SplineRenderer!");
} }
@Override @Override
public String toString() { public String toString() {
return "{SplineStart x=" + getX() + " y=" + getY() + return "{SplineStart x=" + getX() + " y=" + getY() + " a=" + getA()
" a=" + getA() + " b=" + getB() + + " b=" + getB() + " c=" + getC() + " d=" + getD() + "}";
" c=" + getC() + " d=" + getD() + }
"}";
}
} }

View File

@ -21,49 +21,45 @@ import org.apache.poi.xdgf.usermodel.XDGFShape;
/** /**
* This acceptor only allows traversal to shapes that have useful data * This acceptor only allows traversal to shapes that have useful data
* associated with them, and tries to elide details that aren't useful * associated with them, and tries to elide details that aren't useful when
* when analyzing the content of a document. * analyzing the content of a document.
* *
* Useful is subjective of course, and is defined as any of: * Useful is subjective of course, and is defined as any of:
* *
* - Has non-empty text * - Has non-empty text - Is a 1d shape, such as a line - User specified shapes
* - Is a 1d shape, such as a line * - The outline of stencil objects - TODO
* - User specified shapes
* - The outline of stencil objects
* - TODO
*/ */
public class ShapeDataAcceptor implements ShapeVisitorAcceptor { public class ShapeDataAcceptor implements ShapeVisitorAcceptor {
@Override @Override
public boolean accept(XDGFShape shape) { public boolean accept(XDGFShape shape) {
if (shape.isDeleted()) if (shape.isDeleted())
return false; return false;
// text is interesting // text is interesting
if (shape.hasText() && shape.getTextAsString().length() != 0) if (shape.hasText() && shape.getTextAsString().length() != 0)
return true; return true;
// 1d shapes are interesting, they create connections // 1d shapes are interesting, they create connections
if (shape.isShape1D()) if (shape.isShape1D())
return true; return true;
// User specified shapes are interesting // User specified shapes are interesting
if (!shape.hasMaster() && !shape.hasMasterShape()) if (!shape.hasMaster() && !shape.hasMasterShape())
return true; return true;
if (shape.hasMaster() && !shape.hasMasterShape()) if (shape.hasMaster() && !shape.hasMasterShape())
return true; return true;
// include stencil content, but try to elide stencil interiors // include stencil content, but try to elide stencil interiors
//if (shape.getXmlObject().isSetMaster()) // if (shape.getXmlObject().isSetMaster())
// return true; // return true;
if (shape.hasMasterShape() && shape.getMasterShape().isTopmost()) if (shape.hasMasterShape() && shape.getMasterShape().isTopmost())
return true; return true;
return false;
}
return false;
}
} }

View File

@ -25,46 +25,45 @@ import org.apache.poi.xdgf.usermodel.XDGFShape;
public class ShapeDebuggerRenderer extends ShapeRenderer { public class ShapeDebuggerRenderer extends ShapeRenderer {
ShapeVisitorAcceptor _debugAcceptor = null; ShapeVisitorAcceptor _debugAcceptor = null;
public ShapeDebuggerRenderer() { public ShapeDebuggerRenderer() {
super(); super();
} }
public ShapeDebuggerRenderer(Graphics2D g) { public ShapeDebuggerRenderer(Graphics2D g) {
super(g); super(g);
} }
public void setDebugAcceptor(ShapeVisitorAcceptor acceptor) { public void setDebugAcceptor(ShapeVisitorAcceptor acceptor) {
_debugAcceptor = acceptor; _debugAcceptor = acceptor;
} }
@Override @Override
protected Path2D drawPath(XDGFShape shape){ protected Path2D drawPath(XDGFShape shape) {
Path2D path = super.drawPath(shape); Path2D path = super.drawPath(shape);
if (_debugAcceptor == null || _debugAcceptor.accept(shape)) { if (_debugAcceptor == null || _debugAcceptor.accept(shape)) {
// show numbers to associate shapes with ids.. doesn't always work // show numbers to associate shapes with ids.. doesn't always work
Font f = _graphics.getFont(); Font f = _graphics.getFont();
_graphics.scale(1, -1); _graphics.scale(1, -1);
_graphics.setFont(f.deriveFont(0.05F)); _graphics.setFont(f.deriveFont(0.05F));
String shapeId = "" + shape.getID(); String shapeId = "" + shape.getID();
float shapeOffset = -0.1F; float shapeOffset = -0.1F;
if (shape.hasMasterShape()) { if (shape.hasMasterShape()) {
shapeId += " MS:" + shape.getMasterShape().getID(); shapeId += " MS:" + shape.getMasterShape().getID();
shapeOffset -= 0.15F; shapeOffset -= 0.15F;
} }
_graphics.drawString(shapeId, shapeOffset, 0);
_graphics.setFont(f);
_graphics.scale(1, -1);
}
_graphics.drawString(shapeId, shapeOffset, 0); return path;
_graphics.setFont(f); }
_graphics.scale(1, -1);
}
return path;
}
} }

View File

@ -17,7 +17,6 @@
package org.apache.poi.xdgf.usermodel.shape; package org.apache.poi.xdgf.usermodel.shape;
import java.awt.BasicStroke;
import java.awt.Font; import java.awt.Font;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
@ -32,62 +31,64 @@ import org.apache.poi.xdgf.usermodel.XDGFText;
*/ */
public class ShapeRenderer extends ShapeVisitor { public class ShapeRenderer extends ShapeVisitor {
protected Graphics2D _graphics; protected Graphics2D _graphics;
public ShapeRenderer() { public ShapeRenderer() {
_graphics = null; _graphics = null;
} }
public ShapeRenderer(Graphics2D g) { public ShapeRenderer(Graphics2D g) {
_graphics = g; _graphics = g;
} }
public void setGraphics(Graphics2D g) { public void setGraphics(Graphics2D g) {
_graphics = g; _graphics = g;
} }
@Override @Override
public void visit(XDGFShape shape, AffineTransform globalTransform, int level) { public void visit(XDGFShape shape, AffineTransform globalTransform,
int level) {
AffineTransform savedTr = _graphics.getTransform(); AffineTransform savedTr = _graphics.getTransform();
_graphics.transform(globalTransform); _graphics.transform(globalTransform);
drawPath(shape); drawPath(shape);
drawText(shape); drawText(shape);
// we're done, undo the transforms // we're done, undo the transforms
_graphics.setTransform(savedTr); _graphics.setTransform(savedTr);
} }
protected Path2D drawPath(XDGFShape shape) { protected Path2D drawPath(XDGFShape shape) {
Path2D.Double path = shape.getPath(); Path2D.Double path = shape.getPath();
if (path != null) { if (path != null) {
// setup the stroke for this line // setup the stroke for this line
_graphics.setColor(shape.getLineColor()); _graphics.setColor(shape.getLineColor());
_graphics.setStroke(shape.getStroke()); _graphics.setStroke(shape.getStroke());
_graphics.draw(path); _graphics.draw(path);
} }
return path; return path;
} }
protected void drawText(XDGFShape shape) { protected void drawText(XDGFShape shape) {
XDGFText text = shape.getText(); XDGFText text = shape.getText();
if (text != null) { if (text != null) {
if (text.getTextContent().equals("Header")) if (text.getTextContent().equals("Header"))
text.getTextBounds(); text.getTextBounds();
Font oldFont = _graphics.getFont(); Font oldFont = _graphics.getFont();
_graphics.setFont(oldFont.deriveFont(shape.getFontSize().floatValue())); _graphics.setFont(oldFont.deriveFont(shape.getFontSize()
_graphics.setColor(shape.getFontColor()); .floatValue()));
_graphics.setColor(shape.getFontColor());
text.draw(_graphics); text.draw(_graphics);
_graphics.setFont(oldFont); _graphics.setFont(oldFont);
} }
} }
} }

View File

@ -27,42 +27,46 @@ import org.apache.poi.xdgf.usermodel.XDGFShape;
* To change the behavior of a particular visitor, you can override either * To change the behavior of a particular visitor, you can override either
* accept() or getAcceptor() [preferred] * accept() or getAcceptor() [preferred]
* *
* If accept() or visit() throw StopVisitingThisBranch, the iteration will * If accept() or visit() throw StopVisitingThisBranch, the iteration will not
* not visit subshapes of the shape. * visit subshapes of the shape.
*/ */
public abstract class ShapeVisitor{ public abstract class ShapeVisitor {
ShapeVisitorAcceptor _acceptor; ShapeVisitorAcceptor _acceptor;
public ShapeVisitor() { public ShapeVisitor() {
_acceptor = getAcceptor(); _acceptor = getAcceptor();
} }
// is only called on construction of the visitor, allows // is only called on construction of the visitor, allows
// mixing visitors and acceptors // mixing visitors and acceptors
public ShapeVisitorAcceptor getAcceptor() { public ShapeVisitorAcceptor getAcceptor() {
return new ShapeVisitorAcceptor() { return new ShapeVisitorAcceptor() {
@Override @Override
public boolean accept(XDGFShape shape) { public boolean accept(XDGFShape shape) {
return !shape.isDeleted(); return !shape.isDeleted();
} }
}; };
} }
public void setAcceptor(ShapeVisitorAcceptor acceptor) { public void setAcceptor(ShapeVisitorAcceptor acceptor) {
_acceptor = acceptor; _acceptor = acceptor;
} }
public boolean accept(XDGFShape shape) {
return _acceptor.accept(shape);
}
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
* @param shape Current shape * coordinates
* @param globalTransform A transform that can convert the shapes points to global coordinates * @param level
* @param level Level in the tree (0 is topmost, 1 is next level... * Level in the tree (0 is topmost, 1 is next level...
*/ */
public abstract void visit(XDGFShape shape, AffineTransform globalTransform, int level); public abstract void visit(XDGFShape shape,
AffineTransform globalTransform, int level);
} }

View File

@ -21,6 +21,6 @@ import org.apache.poi.xdgf.usermodel.XDGFShape;
public interface ShapeVisitorAcceptor { public interface ShapeVisitorAcceptor {
public boolean accept(XDGFShape shape); public boolean accept(XDGFShape shape);
} }

View File

@ -19,6 +19,6 @@ package org.apache.poi.xdgf.usermodel.shape.exceptions;
public class StopVisiting extends RuntimeException { public class StopVisiting extends RuntimeException {
private static final long serialVersionUID = -4651207777092840750L; private static final long serialVersionUID = -4651207777092840750L;
} }

View File

@ -19,6 +19,6 @@ package org.apache.poi.xdgf.usermodel.shape.exceptions;
public class StopVisitingThisBranch extends RuntimeException { public class StopVisitingThisBranch extends RuntimeException {
private static final long serialVersionUID = 5262319077534717862L; private static final long serialVersionUID = 5262319077534717862L;
} }

View File

@ -32,53 +32,60 @@ import org.apache.poi.xdgf.usermodel.shape.ShapeVisitor;
public class HierarchyPrinter { public class HierarchyPrinter {
public static void printHierarchy(XDGFPage page, File outDir) throws FileNotFoundException { public static void printHierarchy(XDGFPage page, File outDir)
throws FileNotFoundException {
File pageFile = new File(outDir, "page" + page.getPageNumber() + "-" + Util.sanitizeFilename(page.getName()) + ".txt"); File pageFile = new File(outDir, "page" + page.getPageNumber() + "-"
+ Util.sanitizeFilename(page.getName()) + ".txt");
OutputStream os = new FileOutputStream(pageFile); OutputStream os = new FileOutputStream(pageFile);
PrintStream pos = new PrintStream(os); PrintStream pos = new PrintStream(os);
printHierarchy(page, pos); printHierarchy(page, pos);
pos.close(); pos.close();
} }
public static void printHierarchy(XDGFPage page, final PrintStream os) { public static void printHierarchy(XDGFPage page, final PrintStream os) {
page.getContent().visitShapes(new ShapeVisitor() { page.getContent().visitShapes(new ShapeVisitor() {
@Override @Override
public void visit(XDGFShape shape, AffineTransform globalTransform, int level) { public void visit(XDGFShape shape, AffineTransform globalTransform,
for (int i = 0; i < level; i++) { int level) {
os.append(" "); 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()); // 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 { public static void printHierarchy(XmlVisioDocument document,
String outDirname) throws FileNotFoundException {
File outDir = new File(outDirname); File outDir = new File(outDirname);
for (XDGFPage page: document.getPages()) { for (XDGFPage page : document.getPages()) {
printHierarchy(page, outDir); 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);
}
public static void main(String [] args) throws Exception { String inFilename = args[0];
if (args.length != 2) { String outDir = args[1];
System.err.println("Usage: in.vsdx outdir");
System.exit(1);
}
String inFilename = args[0]; XmlVisioDocument doc = new XmlVisioDocument(new FileInputStream(
String outDir = args[1]; inFilename));
printHierarchy(doc, outDir);
XmlVisioDocument doc = new XmlVisioDocument(new FileInputStream(inFilename)); }
printHierarchy(doc, outDir);
}
} }

View File

@ -28,30 +28,30 @@ import org.apache.xmlbeans.XmlObject;
public class ObjectFactory<T, X extends XmlObject> { public class ObjectFactory<T, X extends XmlObject> {
Map<String, Constructor<? extends T>> _types = new HashMap<>(); 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 { public void put(String typeName, Class<? extends T> cls, Class<?>... varargs) throws NoSuchMethodException, SecurityException {
_types.put(typeName, cls.getDeclaredConstructor(varargs)); _types.put(typeName, cls.getDeclaredConstructor(varargs));
} }
public T load(String name, Object... varargs) { public T load(String name, Object... varargs) {
Constructor<? extends T> constructor = _types.get(name); Constructor<? extends T> constructor = _types.get(name);
if (constructor == null) { if (constructor == null) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
X xmlObject = (X) varargs[0]; X xmlObject = (X) varargs[0];
String typeName = xmlObject.schemaType().getName().getLocalPart(); String typeName = xmlObject.schemaType().getName().getLocalPart();
throw new POIXMLException("Invalid '" + typeName + "' name '" + name + "'"); throw new POIXMLException("Invalid '" + typeName + "' name '" + name + "'");
} }
try { try {
return constructor.newInstance(varargs); return constructor.newInstance(varargs);
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
throw new POIXMLException(e.getCause()); throw new POIXMLException(e.getCause());
} catch (Exception e) { } catch (Exception e) {
throw new POIXMLException(e); throw new POIXMLException(e);
} }
} }
} }

View File

@ -19,19 +19,19 @@ package org.apache.poi.xdgf.util;
public class Util { public class Util {
public static int countLines(String str) { public static int countLines(String str) {
int lines = 1; int lines = 1;
int pos = 0; int pos = 0;
while ((pos = str.indexOf("\n", pos) + 1) != 0) { while ((pos = str.indexOf("\n", pos) + 1) != 0) {
lines++; lines++;
} }
return lines; return lines;
} }
// this probably isn't 100% correct, so don't use it in security-sensitive // this probably isn't 100% correct, so don't use it in security-sensitive
// applications! // applications!
// from: http://www.rgagnon.com/javadetails/java-0662.html // from: http://www.rgagnon.com/javadetails/java-0662.html
public static String sanitizeFilename(String name) { public static String sanitizeFilename(String name) {
return name.replaceAll("[:\\\\/*\"?|<>]", "_"); return name.replaceAll("[:\\\\/*\"?|<>]", "_");
} }
} }

View File

@ -20,7 +20,6 @@ package org.apache.poi.xdgf.util;
import java.awt.Color; import java.awt.Color;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.RenderingHints; import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -37,42 +36,50 @@ import org.apache.poi.xdgf.usermodel.shape.ShapeRenderer;
public class VsdxToPng { 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 renderToPng(XDGFPage page, String outFilename, double scale, ShapeRenderer renderer) throws IOException { public static void renderToPngDir(XDGFPage page, File outDir, double scale,
renderToPng(page, new File(outFilename), scale, renderer); ShapeRenderer renderer) throws IOException {
}
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);
File pageFile = new File(outDir, "page" + page.getPageNumber() + "-" + Util.sanitizeFilename(page.getName()) + ".png"); renderToPng(page, pageFile, scale, renderer);
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 {
public static void renderToPng(XDGFPage page, File outFile, double scale, ShapeRenderer renderer) throws IOException { Dimension2dDouble sz = page.getPageSize();
Dimension2dDouble sz = page.getPageSize(); int width = (int) (scale * sz.getWidth());
int height = (int) (scale * sz.getHeight());
int width = (int)(scale * sz.getWidth()); BufferedImage img = new BufferedImage(width, height,
int height = (int)(scale * sz.getHeight()); BufferedImage.TYPE_INT_RGB);
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
final Graphics2D graphics = img.createGraphics(); final Graphics2D graphics = img.createGraphics();
// default rendering options // default rendering options
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); graphics.setRenderingHint(RenderingHints.KEY_RENDERING,
graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); 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.setColor(Color.black);
graphics.setBackground(Color.white); graphics.setBackground(Color.white);
graphics.clearRect(0, 0, width, height); graphics.clearRect(0, 0, width, height);
// Visio's coordinate system is flipped, so flip the image vertically // 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); graphics.scale(scale, -scale);
// toplevel shapes only // toplevel shapes only
@ -84,35 +91,38 @@ public class VsdxToPng {
FileOutputStream out = new FileOutputStream(outFile); FileOutputStream out = new FileOutputStream(outFile);
ImageIO.write(img, "png", out); ImageIO.write(img, "png", out);
out.close(); out.close();
} }
public static void renderToPng(XmlVisioDocument document, String outDirname, double scale, ShapeRenderer renderer) throws IOException { public static void renderToPng(XmlVisioDocument document,
String outDirname, double scale, ShapeRenderer renderer)
throws IOException {
File outDir = new File(outDirname); File outDir = new File(outDirname);
for (XDGFPage page: document.getPages()) { for (XDGFPage page : document.getPages()) {
renderToPngDir(page, outDir, scale, renderer); renderToPngDir(page, outDir, scale, renderer);
} }
} }
public static void main(String [] args) throws Exception { public static void main(String[] args) throws Exception {
if (args.length > 2) { if (args.length > 2) {
System.err.println("Usage: [--debug] in.vsdx outdir"); System.err.println("Usage: [--debug] in.vsdx outdir");
System.exit(1); System.exit(1);
} }
ShapeRenderer renderer = new ShapeRenderer(); ShapeRenderer renderer = new ShapeRenderer();
String inFilename = args[0]; String inFilename = args[0];
String pngDir = args[1]; String pngDir = args[1];
if (args[0].equals("--debug")) { if (args[0].equals("--debug")) {
inFilename = args[1]; inFilename = args[1];
pngDir = args[2]; pngDir = args[2];
renderer = new ShapeDebuggerRenderer(); renderer = new ShapeDebuggerRenderer();
} }
XmlVisioDocument doc = new XmlVisioDocument(new FileInputStream(inFilename)); XmlVisioDocument doc = new XmlVisioDocument(new FileInputStream(
renderToPng(doc, pngDir, 2000/11.0, renderer); inFilename));
} renderToPng(doc, pngDir, 2000 / 11.0, renderer);
}
} }

View File

@ -23,11 +23,12 @@ import org.apache.poi.xdgf.usermodel.XDGFDocument;
public class XDGFXMLDocumentPart extends POIXMLDocumentPart { public class XDGFXMLDocumentPart extends POIXMLDocumentPart {
protected XDGFDocument _document; protected XDGFDocument _document;
public XDGFXMLDocumentPart(PackagePart part, PackageRelationship rel, XDGFDocument document) { public XDGFXMLDocumentPart(PackagePart part, PackageRelationship rel,
super(part, rel); XDGFDocument document) {
_document = document; super(part, rel);
} _document = document;
}
} }

View File

@ -26,134 +26,132 @@ import org.junit.Test;
public class CombinedIteratorTest { public class CombinedIteratorTest {
void testIteration(CombinedIterable<String> iterable, String... expected) { void testIteration(CombinedIterable<String> iterable, String... expected) {
Iterator<String> iter = iterable.iterator(); Iterator<String> iter = iterable.iterator();
for (int i = 0; i < expected.length; i++) { for (int i = 0; i < expected.length; i++) {
Assert.assertEquals(true, iter.hasNext()); Assert.assertEquals(true, iter.hasNext());
Assert.assertEquals(expected[i], iter.next()); Assert.assertEquals(expected[i], iter.next());
} }
Assert.assertEquals(false, iter.hasNext()); Assert.assertEquals(false, iter.hasNext());
} }
@Test @Test
public void testNullMaster() { public void testNullMaster() {
SortedMap<Long, String> base = new TreeMap<>(); SortedMap<Long, String> base = new TreeMap<Long, String>();
base.put(1L, "B1"); base.put(1L, "B1");
base.put(2L, "B2"); base.put(2L, "B2");
base.put(3L, "B3"); base.put(3L, "B3");
testIteration(new CombinedIterable<>(base, null), testIteration(new CombinedIterable<String>(base, null), "B1", "B2",
"B1", "B2", "B3"); "B3");
} }
@Test @Test
public void testNoMatchesBaseFirst() { public void testNoMatchesBaseFirst() {
SortedMap<Long, String> base = new TreeMap<>(); SortedMap<Long, String> base = new TreeMap<Long, String>();
base.put(1L, "B1"); base.put(1L, "B1");
base.put(2L, "B2"); base.put(2L, "B2");
base.put(3L, "B3"); base.put(3L, "B3");
SortedMap<Long, String> master = new TreeMap<>(); SortedMap<Long, String> master = new TreeMap<Long, String>();
master.put(4L, "M4"); master.put(4L, "M4");
master.put(5L, "M5"); master.put(5L, "M5");
master.put(6L, "M6"); master.put(6L, "M6");
testIteration(new CombinedIterable<>(base, master), testIteration(new CombinedIterable<String>(base, master), "B1", "B2",
"B1", "B2", "B3", "M4", "M5", "M6"); "B3", "M4", "M5", "M6");
} }
@Test @Test
public void testNoMatchesMasterFirst() { public void testNoMatchesMasterFirst() {
SortedMap<Long, String> base = new TreeMap<>(); SortedMap<Long, String> base = new TreeMap<Long, String>();
base.put(4L, "B4"); base.put(4L, "B4");
base.put(5L, "B5"); base.put(5L, "B5");
base.put(6L, "B6"); base.put(6L, "B6");
SortedMap<Long, String> master = new TreeMap<>(); SortedMap<Long, String> master = new TreeMap<Long, String>();
master.put(1L, "M1"); master.put(1L, "M1");
master.put(2L, "M2"); master.put(2L, "M2");
master.put(3L, "M3"); master.put(3L, "M3");
testIteration(new CombinedIterable<>(base, master), testIteration(new CombinedIterable<String>(base, master), "M1", "M2",
"M1", "M2", "M3", "B4", "B5", "B6"); "M3", "B4", "B5", "B6");
} }
@Test @Test
public void testInterleaved1() { public void testInterleaved1() {
SortedMap<Long, String> base = new TreeMap<>(); SortedMap<Long, String> base = new TreeMap<Long, String>();
base.put(1L, "B1"); base.put(1L, "B1");
base.put(3L, "B3"); base.put(3L, "B3");
base.put(5L, "B5"); base.put(5L, "B5");
SortedMap<Long, String> master = new TreeMap<>(); SortedMap<Long, String> master = new TreeMap<Long, String>();
master.put(2L, "M2"); master.put(2L, "M2");
master.put(4L, "M4"); master.put(4L, "M4");
master.put(6L, "M6"); master.put(6L, "M6");
testIteration(new CombinedIterable<>(base, master), testIteration(new CombinedIterable<String>(base, master), "B1", "M2",
"B1", "M2", "B3", "M4", "B5", "M6"); "B3", "M4", "B5", "M6");
} }
@Test @Test
public void testInterleaved2() { public void testInterleaved2() {
SortedMap<Long, String> base = new TreeMap<>(); SortedMap<Long, String> base = new TreeMap<Long, String>();
base.put(1L, "B1"); base.put(1L, "B1");
base.put(2L, "B2"); base.put(2L, "B2");
base.put(5L, "B5"); base.put(5L, "B5");
base.put(6L, "B6"); base.put(6L, "B6");
SortedMap<Long, String> master = new TreeMap<>(); SortedMap<Long, String> master = new TreeMap<Long, String>();
master.put(3L, "M3"); master.put(3L, "M3");
master.put(4L, "M4"); master.put(4L, "M4");
master.put(7L, "M7"); master.put(7L, "M7");
master.put(8L, "M8"); master.put(8L, "M8");
testIteration(new CombinedIterable<>(base, master), testIteration(new CombinedIterable<String>(base, master), "B1", "B2",
"B1", "B2", "M3", "M4", "B5", "B6", "M7", "M8"); "M3", "M4", "B5", "B6", "M7", "M8");
} }
@Test @Test
public void testAllMatching() { public void testAllMatching() {
SortedMap<Long, String> base = new TreeMap<>(); SortedMap<Long, String> base = new TreeMap<Long, String>();
base.put(1L, "B1"); base.put(1L, "B1");
base.put(2L, "B2"); base.put(2L, "B2");
base.put(3L, "B3"); base.put(3L, "B3");
SortedMap<Long, String> master = new TreeMap<>(); SortedMap<Long, String> master = new TreeMap<Long, String>();
master.put(1L, "M1"); master.put(1L, "M1");
master.put(2L, "M2"); master.put(2L, "M2");
master.put(3L, "M3"); master.put(3L, "M3");
testIteration(new CombinedIterable<>(base, master), testIteration(new CombinedIterable<String>(base, master), "B1", "B2",
"B1", "B2", "B3"); "B3");
} }
@Test @Test
public void testAllMatching2() { public void testAllMatching2() {
SortedMap<Long, String> base = new TreeMap<>(); SortedMap<Long, String> base = new TreeMap<Long, String>();
base.put(1L, "B1"); base.put(1L, "B1");
base.put(2L, "B2"); base.put(2L, "B2");
base.put(3L, "B3"); 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");
}
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");
}
} }