Import poi-visio codebase

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1709354 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Dustin Spicuzza 2015-10-19 05:52:35 +00:00
parent 3a8f40db7c
commit 3bd2011924
58 changed files with 6437 additions and 0 deletions

View File

@ -0,0 +1,50 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.exceptions;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.POIXMLException;
public class XDGFException {
/**
* Creates an error message to be thrown
*/
public static POIXMLException error(String message, Object o) {
return new POIXMLException(o.toString() + ": " + message);
}
public static POIXMLException error(String message, Object o, Throwable t) {
return new POIXMLException(o.toString() + ": " + message, t);
}
//
// Use these to wrap error messages coming up so that we have at least
// some idea where the error was located
//
public static POIXMLException wrap(POIXMLDocumentPart part, POIXMLException e) {
return new POIXMLException(part.getPackagePart().getPartName().toString() + ": " + e.getMessage(),
e.getCause() == null ? e : e.getCause());
}
public static POIXMLException wrap(String where, POIXMLException e) {
return new POIXMLException(where + ": " + e.getMessage(),
e.getCause() == null ? e : e.getCause());
}
}

View File

@ -0,0 +1,73 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.geom;
import java.awt.geom.Dimension2D;
public class Dimension2dDouble extends Dimension2D {
double width;
double height;
public Dimension2dDouble() {
width = 0d;
height = 0d;
}
public Dimension2dDouble(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double getWidth() {
return width;
}
@Override
public double getHeight() {
return height;
}
@Override
public void setSize(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Dimension2dDouble) {
Dimension2dDouble other = (Dimension2dDouble)obj;
return width == other.width && height == other.height;
}
return false;
}
@Override
public int hashCode() {
double sum = width + height;
return (int)Math.ceil(sum * (sum + 1)/2 + width);
}
@Override
public String toString() {
return "Dimension2dDouble[" + width + ", " + height + "]";
}
}

View File

@ -0,0 +1,79 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.geom;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import org.apache.poi.xdgf.usermodel.section.geometry.SplineKnot;
import org.apache.poi.xdgf.usermodel.section.geometry.SplineStart;
import com.graphbuilder.curve.ControlPath;
import com.graphbuilder.curve.ShapeMultiPath;
import com.graphbuilder.curve.ValueVector;
import com.graphbuilder.geom.PointFactory;
public class SplineCollector {
SplineStart _start;
ArrayList<SplineKnot> _knots = new ArrayList<>();
public SplineCollector(SplineStart start) {
_start = start;
}
public void addKnot(SplineKnot knot) {
if (!knot.getDel())
_knots.add(knot);
}
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
// ok, we have the start, and all knots... do something with this
Point2D last = path.getCurrentPoint();
// create a control path and knots
ControlPath controlPath = new ControlPath();
ValueVector knots = new ValueVector(_knots.size() + 3);
double firstKnot = _start.getB();
double lastKnot = _start.getC();
int degree = _start.getD();
// first/second knot
knots.add(firstKnot);
knots.add(_start.getA());
// first/second control point
controlPath.addPoint(PointFactory.create(last.getX(), last.getY()));
controlPath.addPoint(PointFactory.create(_start.getX(), _start.getY()));
// middle knots/control points
for (SplineKnot knot: _knots) {
knots.add(knot.getA());
controlPath.addPoint(PointFactory.create(knot.getX(), knot.getY()));
}
// last knot
knots.add(lastKnot);
ShapeMultiPath shape = SplineRenderer.createNurbsSpline(controlPath, knots, null, degree);
path.append(shape, true);
}
}

View File

@ -0,0 +1,68 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.geom;
import com.graphbuilder.curve.ControlPath;
import com.graphbuilder.curve.GroupIterator;
import com.graphbuilder.curve.NURBSpline;
import com.graphbuilder.curve.ShapeMultiPath;
import com.graphbuilder.curve.ValueVector;
public class SplineRenderer {
public static ShapeMultiPath createNurbsSpline(ControlPath controlPoints,
ValueVector knots,
ValueVector weights,
int degree) {
double firstKnot = knots.get(0);
double lastKnot = knots.get(knots.size()-1);
// scale knots to [0, 1] based on first/last knots
for (int i = 0; i < knots.size(); i++) {
knots.set((knots.get(i) - firstKnot)/lastKnot, i);
}
// if we don't have enough knots, duplicate the last knot until we do
for (int i = knots.size(); i < controlPoints.numPoints() + degree + 1; i++) {
knots.add(1);
}
GroupIterator gi = new GroupIterator("0:n-1", controlPoints.numPoints());
NURBSpline spline = new NURBSpline(controlPoints, gi);
spline.setDegree(degree);
spline.setKnotVectorType(NURBSpline.NON_UNIFORM);
spline.setKnotVector(knots);
if (weights == null) {
spline.setUseWeightVector(false);
} else {
spline.setWeightVector(weights);
}
// now that this is done, add it to the path
ShapeMultiPath shape = new ShapeMultiPath();
shape.setFlatness(0.01);
spline.appendTo(shape);
return shape;
}
}

View File

@ -0,0 +1,159 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.POIXMLException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.util.Internal;
import org.apache.poi.xdgf.exceptions.XDGFException;
import org.apache.poi.xdgf.usermodel.shape.ShapeRenderer;
import org.apache.poi.xdgf.usermodel.shape.ShapeVisitor;
import org.apache.poi.xdgf.usermodel.shape.exceptions.StopVisiting;
import org.apache.poi.xdgf.xml.XDGFXMLDocumentPart;
import com.microsoft.schemas.office.visio.x2012.main.ConnectType;
import com.microsoft.schemas.office.visio.x2012.main.PageContentsType;
import com.microsoft.schemas.office.visio.x2012.main.ShapeSheetType;
/**
* Container of shapes for a page in a visio document
*/
public class XDGFBaseContents extends XDGFXMLDocumentPart {
protected PageContentsType _pageContents;
// shapes without parents
protected List<XDGFShape> _toplevelShapes = new ArrayList<>();
protected Map<Long, XDGFShape> _shapes = new HashMap<>();
protected List<XDGFConnection> _connections = new ArrayList<>();
public XDGFBaseContents(PackagePart part, PackageRelationship rel, XDGFDocument document) {
super(part, rel, document);
}
@Internal
public PageContentsType getXmlObject() {
return _pageContents;
}
@Override
protected void onDocumentRead() {
if (_pageContents.isSetShapes()) {
for (ShapeSheetType shapeSheet: _pageContents.getShapes().getShapeArray()) {
XDGFShape shape = new XDGFShape(shapeSheet, this, _document);
_toplevelShapes.add(shape);
addToShapeIndex(shape);
}
}
if (_pageContents.isSetConnects()) {
for (ConnectType connect: _pageContents.getConnects().getConnectArray()) {
XDGFShape from = _shapes.get(connect.getFromSheet());
XDGFShape to = _shapes.get(connect.getToSheet());
if (from == null)
throw new POIXMLException(this.toString() + "; Connect; Invalid from id: " + connect.getFromSheet());
if (to == null)
throw new POIXMLException(this.toString() + "; Connect; Invalid to id: " + connect.getToSheet());
_connections.add(new XDGFConnection(connect, from, to));
}
}
}
protected void addToShapeIndex(XDGFShape shape) {
_shapes.put(shape.getID(), shape);
List<XDGFShape> shapes = shape.getShapes();
if (shapes == null)
return;
for (XDGFShape subshape: shapes)
addToShapeIndex(subshape);
}
//
// API
//
/**
*
* @param graphics
*/
public void draw(Graphics2D graphics) {
visitShapes(new ShapeRenderer(graphics));
}
public XDGFShape getShapeById(long id) {
return _shapes.get(id);
}
public Map<Long, XDGFShape> getShapesMap() {
return Collections.unmodifiableMap(_shapes);
}
public Collection<XDGFShape> getShapes() {
return _shapes.values();
}
public List<XDGFShape> getTopLevelShapes() {
return Collections.unmodifiableList(_toplevelShapes);
}
// get connections
public List<XDGFConnection> getConnections() {
return Collections.unmodifiableList(_connections);
}
@Override
public String toString() {
return getPackagePart().getPartName().toString();
}
/**
* Provides iteration over the shapes using the visitor pattern, and provides
* an easy way to convert shape coordinates into global coordinates
*/
public void visitShapes(ShapeVisitor visitor) {
try {
for (XDGFShape shape: _toplevelShapes) {
shape.visitShapes(visitor, new AffineTransform(), 0);
}
} catch (StopVisiting e) {
// intentionally empty
} catch (POIXMLException e) {
throw XDGFException.wrap(this, e);
}
}
}

View File

@ -0,0 +1,150 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import java.util.Map;
import org.apache.poi.POIXMLException;
import org.apache.poi.util.Internal;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
/**
* There are a lot of different cell types. Cell is really just an attribute
* of the thing that it's attached to. Will probably refactor this once I
* figure out a better way to use them
*
* The various attributes of a Cell are constrained, and are better defined
* in the XSD 1.1 visio schema
*/
public class XDGFCell {
public static Boolean maybeGetBoolean(Map<String, XDGFCell> cells, String name) {
XDGFCell cell = cells.get(name);
if (cell == null)
return null;
if (cell.getValue().equals("0"))
return false;
if (cell.getValue().equals("1"))
return true;
throw new POIXMLException("Invalid boolean value for '" + cell.getName() + "'");
}
public static Double maybeGetDouble(Map<String, XDGFCell> cells, String name) {
XDGFCell cell = cells.get(name);
if (cell != null)
return parseDoubleValue(cell._cell);
return null;
}
public static Integer maybeGetInteger(Map<String, XDGFCell> cells, String name) {
XDGFCell cell = cells.get(name);
if (cell != null)
return parseIntegerValue(cell._cell);
return null;
}
public static String maybeGetString(Map<String, XDGFCell> cells, String name) {
XDGFCell cell = cells.get(name);
if (cell != null) {
String v = cell._cell.getV();
if (v.equals("Themed"))
return null;
return v;
}
return null;
}
public static Double parseDoubleValue(CellType cell) {
try {
return Double.parseDouble(cell.getV());
} catch (NumberFormatException e) {
if (cell.getV().equals("Themed"))
return null;
throw new POIXMLException("Invalid float value for '" + cell.getN() + "': " + e);
}
}
public static Integer parseIntegerValue(CellType cell) {
try {
return Integer.parseInt(cell.getV());
} catch (NumberFormatException e) {
if (cell.getV().equals("Themed"))
return null;
throw new POIXMLException("Invalid integer value for '" + cell.getN() + "': " + e);
}
}
// returns a length, converts it to inches?
public static Double parseVLength(CellType cell) {
try {
return Double.parseDouble(cell.getV());
} catch (NumberFormatException e) {
if (cell.getV().equals("Themed"))
return null;
throw new POIXMLException("Invalid float value for '" + cell.getN() + "': " + e);
}
}
CellType _cell;
public XDGFCell(CellType cell) {
_cell = cell;
}
@Internal
CellType getXmlObject() {
return _cell;
}
/**
* Represents the name of the ShapeSheet cell.
*/
public String getName() {
return _cell.getN();
}
/**
* Represents the value of the cell.
*/
public String getValue() {
return _cell.getV();
}
/**
* Represents the elements formula. This attribute can contain one of the following strings:
* - (some formula) if the formula exists locally
* - No Formula if the formula is locally deleted or blocked
* - Inh if the formula is inherited.
*/
public String getFormula() {
return _cell.getF();
}
/*
* Indicates that the formula evaluates to an error. The value of E is the
* current value (an error message string); the value of the V attribute is
* the last valid value.
*/
public String getError() {
return _cell.getE();
}
}

View File

@ -0,0 +1,134 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import com.microsoft.schemas.office.visio.x2012.main.ConnectType;
public class XDGFConnection {
// comments on frompart/topart taken from pkgVisio
// https://msdn.microsoft.com/en-us/library/ms367611(v=office.12).aspx
// The following constants declared by the Microsoft Office Visio type
// library show return values for the FromPart property.
// Constant Value
// visConnectFromError -1
// visFromNone 0
// visLeftEdge 1
// visCenterEdge 2
// visRightEdge 3
// visBottomEdge 4
// visMiddleEdge 5
// visTopEdge 6
// visBeginX 7
// visBeginY 8
// visBegin 9
// visEndX 10
// visEndY 11
// visEnd 12
// visFromAngle 13
// visFromPin 14
// visControlPoint 100 + zero-based row index (for example, visControlPoint = 100 if the control point is in row 0; visControlPoint = 101 if the control point is in row 1)
public static final int visConnectFromError = -1;
public static final int visFromNone = 0;
public static final int visLeftEdge = 1;
public static final int visCenterEdge = 2;
public static final int visRightEdge = 3;
public static final int visBottomEdge = 4;
public static final int visMiddleEdge = 5;
public static final int visTopEdge = 6;
public static final int visBeginX = 7;
public static final int visBeginY = 8;
public static final int visBegin = 9;
public static final int visEndX = 10;
public static final int visEndY = 11;
public static final int visEnd = 12;
public static final int visFromAngle = 13;
public static final int visFromPin = 14;
// The ToPart property identifies the part of a shape to which another
// shape is glued, such as its begin point or endpoint, one of its edges,
// or a connection point. The following constants declared by the Visio type library in member VisToParts show possible return values for the ToPart property.
// Constant Value
// visConnectToError -1
// visToNone 0
// visGuideX 1
// visGuideY 2
// visWholeShape 3
// visGuideIntersect 4
// visToAngle 7
// visConnectionPoint 100 + row index of connection point
public static final int visConnectToError = -1;
public static final int visToNone = 0;
public static final int visGuideX = 1;
public static final int visGuideY = 2;
public static final int visWholeShape = 3;
public static final int visGuideIntersect = 4;
public static final int visToAngle = 7;
private ConnectType _connect;
private XDGFShape _from;
private XDGFShape _to;
public XDGFConnection(ConnectType connect, XDGFShape from, XDGFShape to) {
_connect = connect;
_from = from;
_to = to;
}
public XDGFShape getFromShape() {
return _from;
}
public XDGFCell getFromCell() {
return _from.getCell(_connect.getFromCell());
}
public String getFromCellName() {
return _connect.getFromCell();
}
public XDGFShape getToShape() {
return _to;
}
public String getToCellName() {
return _connect.getToCell();
}
// see constants above
public Integer getFromPart() {
if (_connect.isSetFromPart())
return _connect.getFromPart();
else
return null;
}
// see constants above
public Integer getToPart() {
if (_connect.isSetToPart())
return _connect.getToPart();
else
return null;
}
}

View File

@ -0,0 +1,116 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.POIXMLException;
import org.apache.poi.util.Internal;
import com.microsoft.schemas.office.visio.x2012.main.DocumentSettingsType;
import com.microsoft.schemas.office.visio.x2012.main.StyleSheetType;
import com.microsoft.schemas.office.visio.x2012.main.VisioDocumentType;
/**
* Represents the root document: /visio/document.xml
*/
public class XDGFDocument {
protected VisioDocumentType _document;
Map<Long, XDGFStyleSheet> _styleSheets = new HashMap<>();
// defaults
long _defaultFillStyle = 0;
long _defaultGuideStyle = 0;
long _defaultLineStyle = 0;
long _defaultTextStyle = 0;
public XDGFDocument(VisioDocumentType document) {
_document = document;
if (!_document.isSetDocumentSettings())
throw new POIXMLException("Document settings not found");
DocumentSettingsType docSettings = _document.getDocumentSettings();
if (docSettings.isSetDefaultFillStyle())
_defaultFillStyle = docSettings.getDefaultFillStyle();
if (docSettings.isSetDefaultGuideStyle())
_defaultGuideStyle = docSettings.getDefaultGuideStyle();
if (docSettings.isSetDefaultLineStyle())
_defaultLineStyle = docSettings.getDefaultLineStyle();
if (docSettings.isSetDefaultTextStyle())
_defaultTextStyle = docSettings.getDefaultTextStyle();
if (_document.isSetStyleSheets()) {
for (StyleSheetType styleSheet: _document.getStyleSheets().getStyleSheetArray()) {
_styleSheets.put(styleSheet.getID(), new XDGFStyleSheet(styleSheet, this));
}
}
}
@Internal
public VisioDocumentType getXmlObject() {
return _document;
}
public XDGFStyleSheet getStyleById(long id) {
return _styleSheets.get(id);
}
public XDGFStyleSheet getDefaultFillStyle() {
XDGFStyleSheet style = getStyleById(_defaultFillStyle);
if (style == null)
throw new POIXMLException("No default fill style found!");
return style;
}
public XDGFStyleSheet getDefaultGuideStyle() {
XDGFStyleSheet style = getStyleById(_defaultGuideStyle);
if (style == null)
throw new POIXMLException("No default guide style found!");
return style;
}
public XDGFStyleSheet getDefaultLineStyle() {
XDGFStyleSheet style = getStyleById(_defaultLineStyle);
if (style == null)
throw new POIXMLException("No default line style found!");
return style;
}
public XDGFStyleSheet getDefaultTextStyle() {
XDGFStyleSheet style = getStyleById(_defaultTextStyle);
if (style == null)
throw new POIXMLException("No default text style found!");
return style;
}
}

View File

@ -0,0 +1,75 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import java.lang.reflect.Constructor;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.POIXMLException;
import org.apache.poi.POIXMLFactory;
import org.apache.poi.POIXMLRelation;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
public class XDGFFactory extends POIXMLFactory {
private static final POILogger logger = POILogFactory.getLogger(XDGFFactory.class);
private XDGFDocument _document;
public XDGFFactory(XDGFDocument document){
_document = document;
}
@Override
public POIXMLDocumentPart createDocumentPart(POIXMLDocumentPart parent,
PackageRelationship rel, PackagePart part) {
POIXMLRelation descriptor = XDGFRelation.getInstance(rel.getRelationshipType());
if(descriptor == null || descriptor.getRelationClass() == null){
logger.log(POILogger.DEBUG, "using default POIXMLDocumentPart for " + rel.getRelationshipType());
return new POIXMLDocumentPart(part, rel);
}
try {
Class<? extends POIXMLDocumentPart> cls = descriptor.getRelationClass();
try {
Constructor<? extends POIXMLDocumentPart> constructor = cls.getDeclaredConstructor(POIXMLDocumentPart.class, PackagePart.class, PackageRelationship.class, XDGFDocument.class);
return constructor.newInstance(parent, part, rel, _document);
} catch (NoSuchMethodException e) {
Constructor<? extends POIXMLDocumentPart> constructor = cls.getDeclaredConstructor(PackagePart.class, PackageRelationship.class, XDGFDocument.class);
return constructor.newInstance(part, rel, _document);
}
} catch (Exception e){
throw new POIXMLException(e);
}
}
@Override
public POIXMLDocumentPart newDocumentPart(POIXMLRelation descriptor) {
try {
Class<? extends POIXMLDocumentPart> cls = descriptor.getRelationClass();
Constructor<? extends POIXMLDocumentPart> constructor = cls.getDeclaredConstructor();
return constructor.newInstance();
} catch (Exception e){
throw new POIXMLException(e);
}
}
}

View File

@ -0,0 +1,68 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import org.apache.poi.util.Internal;
import com.microsoft.schemas.office.visio.x2012.main.MasterType;
/**
* Provides the API to work with an underlying master
*/
public class XDGFMaster {
private MasterType _master;
private XDGFMasterContents _content;
XDGFSheet _pageSheet = null;
public XDGFMaster(MasterType master, XDGFMasterContents content, XDGFDocument document) {
_master = master;
_content = content;
content.setMaster(this);
if (master.isSetPageSheet())
_pageSheet = new XDGFPageSheet(master.getPageSheet(), document);
}
@Internal
MasterType getXmlObject() {
return _master;
}
@Override
public String toString() {
return "<Master ID=\"" + getID() + "\" " + _content + ">";
}
public long getID() {
return _master.getID();
}
public String getName() {
return _master.getName();
}
public XDGFMasterContents getContent() {
return _content;
}
public XDGFSheet getPageSheet() {
return _pageSheet;
}
}

View File

@ -0,0 +1,64 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import java.io.IOException;
import org.apache.poi.POIXMLException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.xdgf.exceptions.XDGFException;
import org.apache.xmlbeans.XmlException;
import com.microsoft.schemas.office.visio.x2012.main.MasterContentsDocument;
public class XDGFMasterContents extends XDGFBaseContents {
private XDGFMaster _master;
public XDGFMasterContents(PackagePart part, PackageRelationship rel, XDGFDocument document) {
super(part, rel, document);
}
@Override
protected void onDocumentRead() {
try {
try {
_pageContents = MasterContentsDocument.Factory.parse(getPackagePart().getInputStream()).getMasterContents();
} catch (XmlException | IOException e) {
throw new POIXMLException(e);
}
super.onDocumentRead();
} catch (POIXMLException e) {
throw XDGFException.wrap(this, e);
}
}
public XDGFMaster getMaster() {
return _master;
}
protected void setMaster(XDGFMaster master) {
_master = master;
}
}

View File

@ -0,0 +1,99 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.POIXMLException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.util.Internal;
import org.apache.poi.xdgf.exceptions.XDGFException;
import org.apache.poi.xdgf.xml.XDGFXMLDocumentPart;
import org.apache.xmlbeans.XmlException;
import com.microsoft.schemas.office.visio.x2012.main.MasterType;
import com.microsoft.schemas.office.visio.x2012.main.MastersDocument;
import com.microsoft.schemas.office.visio.x2012.main.MastersType;
public class XDGFMasters extends XDGFXMLDocumentPart {
MastersType _mastersObject;
// key: id of master
Map<Long, XDGFMaster> _masters = new HashMap<>();
public XDGFMasters(PackagePart part, PackageRelationship rel, XDGFDocument document) {
super(part, rel, document);
}
@Internal
MastersType getXmlObject() {
return _mastersObject;
}
@Override
protected void onDocumentRead() {
try {
try {
_mastersObject = MastersDocument.Factory.parse(getPackagePart().getInputStream()).getMasters();
} catch (XmlException | IOException e) {
throw new POIXMLException(e);
}
Map<String, MasterType> masterSettings = new HashMap<>();
for (MasterType master: _mastersObject.getMasterArray()) {
masterSettings.put(master.getRel().getId(), master);
}
// create the masters
for (POIXMLDocumentPart part: getRelations()) {
String relId = part.getPackageRelationship().getId();
MasterType settings = masterSettings.get(relId);
if (settings == null)
throw new POIXMLException("Master relationship for " + relId + " not found");
if (!(part instanceof XDGFMasterContents))
throw new POIXMLException("Unexpected masters relationship for " + relId + ": " + part);
XDGFMasterContents contents = (XDGFMasterContents)part;
contents.onDocumentRead();
XDGFMaster master = new XDGFMaster(settings, contents, _document);
_masters.put(master.getID(), master);
}
} catch (POIXMLException e) {
throw XDGFException.wrap(this, e);
}
}
public Collection<XDGFMaster> getMastersList() {
return Collections.unmodifiableCollection(_masters.values());
}
public XDGFMaster getMasterById(long masterId) {
return _masters.get(masterId);
}
}

View File

@ -0,0 +1,113 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.apache.poi.POIXMLException;
import org.apache.poi.util.Internal;
import org.apache.poi.xdgf.geom.Dimension2dDouble;
import com.microsoft.schemas.office.visio.x2012.main.PageType;
/**
* Provides the API to work with an underlying page
*/
public class XDGFPage {
PageType _page;
XDGFPageContents _content;
XDGFPages _pages;
XDGFSheet _pageSheet = null;
public XDGFPage(PageType page, XDGFPageContents content, XDGFDocument document, XDGFPages pages) {
_page = page;
_content = content;
_pages = pages;
content.setPage(this);
if (page.isSetPageSheet())
_pageSheet = new XDGFPageSheet(page.getPageSheet(), document);
}
@Internal
PageType getXmlObject() {
return _page;
}
public long getID() {
return _page.getID();
}
public String getName() {
return _page.getName();
}
public XDGFPageContents getContent() {
return _content;
}
public XDGFSheet getPageSheet() {
return _pageSheet;
}
public long getPageNumber() {
return _pages.getPageList().indexOf(this) + 1;
}
// height/width of page
public Dimension2dDouble getPageSize() {
XDGFCell w = _pageSheet.getCell("PageWidth");
XDGFCell h = _pageSheet.getCell("PageHeight");
if (w == null || h == null)
throw new POIXMLException("Cannot determine page size");
return new Dimension2dDouble(Double.parseDouble(w.getValue()),
Double.parseDouble(h.getValue()));
}
// origin of coordinate system
public Point2D.Double getPageOffset() {
XDGFCell xoffcell = _pageSheet.getCell("XRulerOrigin");
XDGFCell yoffcell = _pageSheet.getCell("YRulerOrigin");
double xoffset = 0;
double yoffset = 0;
if (xoffcell != null)
xoffset = Double.parseDouble(xoffcell.getValue());
if (xoffcell != null)
yoffset = Double.parseDouble(yoffcell.getValue());
return new Point2D.Double(xoffset, yoffset);
}
// bounding box of page
public Rectangle2D getBoundingBox() {
Dimension2dDouble sz = getPageSize();
Point2D.Double offset = getPageOffset();
return new Rectangle2D.Double(-offset.getX(),
-offset.getY(),
sz.getWidth(),
sz.getHeight());
}
}

View File

@ -0,0 +1,83 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.POIXMLException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.xdgf.exceptions.XDGFException;
import org.apache.xmlbeans.XmlException;
import com.microsoft.schemas.office.visio.x2012.main.PageContentsDocument;
public class XDGFPageContents extends XDGFBaseContents {
Map<Long, XDGFMaster> _masters = new HashMap<>();
XDGFPage _page;
public XDGFPageContents(PackagePart part, PackageRelationship rel, XDGFDocument document) {
super(part, rel, document);
}
@Override
protected void onDocumentRead() {
try {
try {
_pageContents = PageContentsDocument.Factory.parse(getPackagePart().getInputStream()).getPageContents();
} catch (XmlException | IOException e) {
throw new POIXMLException(e);
}
for (POIXMLDocumentPart part: getRelations()) {
if (!(part instanceof XDGFMasterContents))
continue;
//throw new POIXMLException("Unexpected page relation: " + part);
XDGFMaster master = ((XDGFMasterContents)part).getMaster();
_masters.put(master.getID(), master);
}
super.onDocumentRead();
for (XDGFShape shape: _shapes.values()) {
if (shape.isTopmost())
shape.setupMaster(this, null);
}
} catch (POIXMLException e) {
throw XDGFException.wrap(this, e);
}
}
public XDGFPage getPage() {
return _page;
}
protected void setPage(XDGFPage page) {
_page = page;
}
public XDGFMaster getMasterById(long id) {
return _masters.get(id);
}
}

View File

@ -0,0 +1,36 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import com.microsoft.schemas.office.visio.x2012.main.PageSheetType;
public class XDGFPageSheet extends XDGFSheet {
PageSheetType _pageSheet;
public XDGFPageSheet(PageSheetType sheet, XDGFDocument document) {
super(sheet, document);
_pageSheet = sheet;
}
@Override
PageSheetType getXmlObject() {
return _pageSheet;
}
}

View File

@ -0,0 +1,95 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.POIXMLException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.util.Internal;
import org.apache.poi.xdgf.exceptions.XDGFException;
import org.apache.poi.xdgf.xml.XDGFXMLDocumentPart;
import org.apache.xmlbeans.XmlException;
import com.microsoft.schemas.office.visio.x2012.main.PageType;
import com.microsoft.schemas.office.visio.x2012.main.PagesDocument;
import com.microsoft.schemas.office.visio.x2012.main.PagesType;
/**
* Contains a list of Page objects (not page content!)
*/
public class XDGFPages extends XDGFXMLDocumentPart {
PagesType _pagesObject;
// ordered by page number
List<XDGFPage> _pages = new ArrayList<>();
public XDGFPages(PackagePart part, PackageRelationship rel, XDGFDocument document) {
super(part, rel, document);
}
@Internal
PagesType getXmlObject() {
return _pagesObject;
}
@Override
protected void onDocumentRead() {
try {
try {
_pagesObject = PagesDocument.Factory.parse(getPackagePart().getInputStream()).getPages();
} catch (XmlException | IOException e) {
throw new POIXMLException(e);
}
// this iteration is ordered by page number
for (PageType pageSettings: _pagesObject.getPageArray()) {
String relId = pageSettings.getRel().getId();
POIXMLDocumentPart pageContentsPart = getRelationById(relId);
if (pageContentsPart == null)
throw new POIXMLException("PageSettings relationship for " + relId + " not found");
if (!(pageContentsPart instanceof XDGFPageContents))
throw new POIXMLException("Unexpected pages relationship for " + relId + ": " + pageContentsPart);
XDGFPageContents contents = (XDGFPageContents)pageContentsPart;
XDGFPage page = new XDGFPage(pageSettings, contents, _document, this);
contents.onDocumentRead();
_pages.add(page);
}
} catch (POIXMLException e) {
throw XDGFException.wrap(this, e);
}
}
// ordered by page number
public List<XDGFPage> getPageList() {
return Collections.unmodifiableList(_pages);
}
}

View File

@ -0,0 +1,99 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.POIXMLRelation;
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
import org.apache.poi.xdgf.xml.XDGFXMLDocumentPart;
public class XDGFRelation extends POIXMLRelation {
/**
* A map to lookup POIXMLRelation by its relation type
*/
protected static final Map<String, XDGFRelation> _table = new HashMap<String, XDGFRelation>();
public static final XDGFRelation DOCUMENT = new XDGFRelation(
"application/vnd.ms-visio.drawing.main+xml",
"http://schemas.microsoft.com/visio/2010/relationships/document",
"/visio/document.xml",
null
);
public static final XDGFRelation MASTERS = new XDGFRelation(
"application/vnd.ms-visio.masters+xml",
"http://schemas.microsoft.com/visio/2010/relationships/masters",
"/visio/masters/masters.xml",
XDGFMasters.class
);
public static final XDGFRelation MASTER = new XDGFRelation(
"application/vnd.ms-visio.master+xml",
"http://schemas.microsoft.com/visio/2010/relationships/master",
"/visio/masters/master#.xml",
XDGFMasterContents.class
);
public static final XDGFRelation IMAGES = new XDGFRelation(
null,
PackageRelationshipTypes.IMAGE_PART,
null,
null // XSSFPictureData.class
);
public static final XDGFRelation PAGES = new XDGFRelation(
"application/vnd.ms-visio.pages+xml",
"http://schemas.microsoft.com/visio/2010/relationships/pages",
"/visio/pages/pages.xml",
XDGFPages.class
);
public static final XDGFRelation PAGE = new XDGFRelation(
"application/vnd.ms-visio.page+xml",
"http://schemas.microsoft.com/visio/2010/relationships/page",
"/visio/pages/page#.xml",
XDGFPageContents.class
);
public static final XDGFRelation WINDOW = new XDGFRelation(
"application/vnd.ms-visio.windows+xml",
"http://schemas.microsoft.com/visio/2010/relationships/windows",
"/visio/windows.xml",
null
);
private XDGFRelation(String type, String rel, String defaultName, Class<? extends XDGFXMLDocumentPart> cls) {
super(type, rel, defaultName, cls);
if (cls != null && !_table.containsKey(rel)) _table.put(rel, this);
}
/**
* Get POIXMLRelation by relation type
*
* @param rel relation type, for example,
* <code>http://schemas.openxmlformats.org/officeDocument/2006/relationships/image</code>
* @return registered POIXMLRelation or null if not found
*/
public static XDGFRelation getInstance(String rel) {
return _table.get(rel);
}
}

View File

@ -0,0 +1,943 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import org.apache.poi.POIXMLException;
import org.apache.poi.util.Internal;
import org.apache.poi.xdgf.exceptions.XDGFException;
import org.apache.poi.xdgf.usermodel.section.CombinedIterable;
import org.apache.poi.xdgf.usermodel.section.GeometrySection;
import org.apache.poi.xdgf.usermodel.section.XDGFSection;
import org.apache.poi.xdgf.usermodel.shape.ShapeVisitor;
import org.apache.poi.xdgf.usermodel.shape.exceptions.StopVisitingThisBranch;
import com.microsoft.schemas.office.visio.x2012.main.ShapeSheetType;
import com.microsoft.schemas.office.visio.x2012.main.TextType;
/**
* A shape is a collection of Geometry Visualization, Format, Text, Images,
* and Shape Data in a Drawing Page.
*/
public class XDGFShape extends XDGFSheet {
XDGFBaseContents _parentPage;
XDGFShape _parent; // only non-null if a subshape
XDGFMaster _master = null;
XDGFShape _masterShape = null;
XDGFText _text = null;
// subshapes if they exist
List<XDGFShape> _shapes = null;
// properties specific to shapes
// center of rotation relative to origin of parent
Double _pinX = null;
Double _pinY = null;
Double _width = null;
Double _height = null;
// center of rotation relative to self
Double _locPinX = null;
Double _locPinY = null;
// start x coordinate, relative to parent
// -> one dimensional shapes only
Double _beginX = null;
Double _beginY = null;
// end x coordinate, relative to parent
// -> one dimensional shapes only
Double _endX = null;
Double _endY = null;
Double _angle = null;
Double _rotationXAngle = null;
Double _rotationYAngle = null;
Double _rotationZAngle = null;
// end x coordinate, relative to parent
Boolean _flipX = null;
Boolean _flipY = null;
// center of text relative to this shape
Double _txtPinX = null;
Double _txtPinY = null;
// center of text relative to text block
Double _txtLocPinX = null;
Double _txtLocPinY = null;
Double _txtAngle = null;
Double _txtWidth = null;
Double _txtHeight = null;
public XDGFShape(ShapeSheetType shapeSheet, XDGFBaseContents parentPage, XDGFDocument document) {
this(null, shapeSheet, parentPage, document);
}
public XDGFShape(XDGFShape parent, ShapeSheetType shapeSheet, XDGFBaseContents parentPage, XDGFDocument document) {
super(shapeSheet, document);
_parent = parent;
_parentPage = parentPage;
TextType text = shapeSheet.getText();
if (text != null)
_text = new XDGFText(text, this);
if (shapeSheet.isSetShapes()) {
_shapes = new ArrayList<XDGFShape>();
for (ShapeSheetType shape: shapeSheet.getShapes().getShapeArray())
_shapes.add(new XDGFShape(this, shape, parentPage, document));
}
readProperties();
}
@Override
public String toString() {
if (_parentPage instanceof XDGFMasterContents)
return _parentPage + ": <Shape ID=\"" + getID() + "\">";
else
return "<Shape ID=\"" + getID() + "\">";
}
protected void readProperties() {
_pinX = XDGFCell.maybeGetDouble(_cells, "PinX");
_pinY = XDGFCell.maybeGetDouble(_cells, "PinY");
_width = XDGFCell.maybeGetDouble(_cells, "Width");
_height = XDGFCell.maybeGetDouble(_cells, "Height");
_locPinX = XDGFCell.maybeGetDouble(_cells, "LocPinX");
_locPinY = XDGFCell.maybeGetDouble(_cells, "LocPinY");
_beginX = XDGFCell.maybeGetDouble(_cells, "BeginX");
_beginY = XDGFCell.maybeGetDouble(_cells, "BeginY");
_endX = XDGFCell.maybeGetDouble(_cells, "EndX");
_endY = XDGFCell.maybeGetDouble(_cells, "EndY");
_angle = XDGFCell.maybeGetDouble(_cells, "Angle");
_rotationXAngle = XDGFCell.maybeGetDouble(_cells, "RotationXAngle");
_rotationYAngle = XDGFCell.maybeGetDouble(_cells, "RotationYAngle");
_rotationZAngle = XDGFCell.maybeGetDouble(_cells, "RotationZAngle");
_flipX = XDGFCell.maybeGetBoolean(_cells, "FlipX");
_flipY = XDGFCell.maybeGetBoolean(_cells, "FlipY");
_txtPinX = XDGFCell.maybeGetDouble(_cells, "TxtPinX");
_txtPinY = XDGFCell.maybeGetDouble(_cells, "TxtPinY");
_txtLocPinX = XDGFCell.maybeGetDouble(_cells, "TxtLocPinX");
_txtLocPinY = XDGFCell.maybeGetDouble(_cells, "TxtLocPinY");
_txtWidth = XDGFCell.maybeGetDouble(_cells, "TxtWidth");
_txtHeight = XDGFCell.maybeGetDouble(_cells, "TxtHeight");
_txtAngle = XDGFCell.maybeGetDouble(_cells, "TxtAngle");
}
/**
* Setup top level shapes
*
* Shapes that have a 'Master' attribute refer to a specific master in
* the page, whereas shapes with a 'MasterShape' attribute refer to a
* subshape of a Master.
*
*
*/
protected void setupMaster(XDGFPageContents pageContents, XDGFMasterContents master) {
ShapeSheetType obj = getXmlObject();
if (obj.isSetMaster()) {
_master = pageContents.getMasterById(obj.getMaster());
if (_master == null)
throw XDGFException.error("refers to non-existant master " + obj.getMaster(),
this);
/*
* If a master has one top-level shape, a shape that inherits from
* that master inherits the descendant elements of that master
* shape. If a master has more than one master shape, a shape that
* inherits from that master inherits those master shapes as
* subshapes.
*/
Collection<XDGFShape> masterShapes = _master.getContent().getTopLevelShapes();
switch (masterShapes.size()) {
case 0:
throw XDGFException.error("Could not retrieve master shape from " + _master, this);
case 1:
_masterShape = masterShapes.iterator().next();
break;
default:
break;
}
} else if (obj.isSetMasterShape()) {
_masterShape = master.getShapeById(obj.getMasterShape());
if (_masterShape == null)
throw XDGFException.error("refers to non-existant master shape " + obj.getMasterShape(),
this);
}
setupSectionMasters();
if (_shapes != null) {
for (XDGFShape shape: _shapes) {
shape.setupMaster(pageContents,
_master == null ? master : _master.getContent());
}
}
}
protected void setupSectionMasters() {
if (_masterShape == null)
return;
try {
for (Entry<String, XDGFSection> section: _sections.entrySet()) {
XDGFSection master = _masterShape.getSection(section.getKey());
if (master != null)
section.getValue().setupMaster(master);
}
for (Entry<Long, GeometrySection> section: _geometry.entrySet()) {
GeometrySection master = _masterShape.getGeometryByIdx(section.getKey());
if (master != null)
section.getValue().setupMaster(master);
}
} catch (POIXMLException e) {
throw XDGFException.wrap(this.toString(), e);
}
}
@Internal
public ShapeSheetType getXmlObject() {
return (ShapeSheetType)_sheet;
}
public long getID() {
return getXmlObject().getID();
}
public String getType() {
return getXmlObject().getType();
}
public String getTextAsString() {
XDGFText text = getText();
if (text == null)
return "";
return text.getTextContent();
}
public boolean hasText() {
return _text != null || (_masterShape != null && _masterShape._text != null);
}
@Override
public XDGFCell getCell(String cellName) {
XDGFCell _cell = super.getCell(cellName);
// if not found, ask the master
if (_cell == null && _masterShape != null) {
_cell = _masterShape.getCell(cellName);
}
return _cell;
}
public GeometrySection getGeometryByIdx(long idx) {
return _geometry.get(idx);
}
// only available if this is a shape group
// -> May be null
public List<XDGFShape> getShapes() {
return _shapes;
}
// unique to this shape on the page?
public String getName() {
String name = getXmlObject().getName();
if (name == null)
return "";
return name;
}
// unique to this shape on the page?
public String getShapeType() {
String type = getXmlObject().getType();
if (type == null)
return "";
return type;
}
// name of the symbol that this was derived from
public String getSymbolName() {
if (_master == null)
return "";
String name = _master.getName();
if (name == null)
return "";
return name;
}
public XDGFShape getMasterShape() {
return _masterShape;
}
// returns the parent shape of this shape, if its in a subshape
public XDGFShape getParentShape() {
return _parent;
}
public XDGFShape getTopmostParentShape() {
XDGFShape top = null;
if (_parent != null) {
top = _parent.getTopmostParentShape();
if (top == null)
top = _parent;
}
return top;
}
public boolean hasMaster() {
return _master != null;
}
public boolean hasMasterShape() {
return _masterShape != null;
}
public boolean hasParent() {
return _parent != null;
}
public boolean hasShapes() {
return _shapes != null;
}
public boolean isTopmost() {
return _parent == null;
}
public boolean isShape1D() {
return getBeginX() != null;
}
public boolean isDeleted() {
return getXmlObject().isSetDel() ? getXmlObject().getDel() : false;
}
public XDGFText getText() {
if (_text == null && _masterShape != null)
return _masterShape.getText();
return _text;
}
public Double getPinX() {
if (_pinX == null && _masterShape != null)
return _masterShape.getPinX();
if (_pinX == null)
throw XDGFException.error("PinX not set!", this);
return _pinX;
}
public Double getPinY() {
if (_pinY == null && _masterShape != null)
return _masterShape.getPinY();
if (_pinY == null)
throw XDGFException.error("PinY not specified!", this);
return _pinY;
}
public Double getWidth() {
if (_width == null && _masterShape != null)
return _masterShape.getWidth();
if (_width == null)
throw XDGFException.error("Width not specified!", this);
return _width;
}
public Double getHeight() {
if (_height == null && _masterShape != null)
return _masterShape.getHeight();
if (_height == null)
throw XDGFException.error("Height not specified!", this);
return _height;
}
public Double getLocPinX() {
if (_locPinX == null && _masterShape != null)
return _masterShape.getLocPinX();
if (_locPinX == null)
throw XDGFException.error("LocPinX not specified!", this);
return _locPinX;
}
public Double getLocPinY() {
if (_locPinY == null && _masterShape != null)
return _masterShape.getLocPinY();
if (_locPinY == null)
throw XDGFException.error("LocPinY not specified!", this);
return _locPinY;
}
public Double getBeginX() {
if (_beginX == null && _masterShape != null)
return _masterShape.getBeginX();
return _beginX;
}
public Double getBeginY() {
if (_beginY == null && _masterShape != null)
return _masterShape.getBeginY();
return _beginY;
}
public Double getEndX() {
if (_endX == null && _masterShape != null)
return _masterShape.getEndX();
return _endX;
}
public Double getEndY() {
if (_endY == null && _masterShape != null)
return _masterShape.getEndY();
return _endY;
}
public Double getAngle() {
if (_angle == null && _masterShape != null)
return _masterShape.getAngle();
return _angle;
}
public Boolean getFlipX() {
if (_flipX == null && _masterShape != null)
return _masterShape.getFlipX();
return _flipX;
}
public Boolean getFlipY() {
if (_flipY == null && _masterShape != null)
return _masterShape.getFlipY();
return _flipY;
}
public Double getTxtPinX() {
if (_txtPinX == null &&
_masterShape != null && _masterShape._txtPinX != null)
return _masterShape._txtPinX;
if (_txtPinX == null)
return getWidth()*0.5;
return _txtPinX;
}
public Double getTxtPinY() {
if (_txtLocPinY == null &&
_masterShape != null && _masterShape._txtLocPinY != null)
return _masterShape._txtLocPinY;
if (_txtPinY == null)
return getHeight()*0.5;
return _txtPinY;
}
public Double getTxtLocPinX() {
if (_txtLocPinX == null &&
_masterShape != null && _masterShape._txtLocPinX != null)
return _masterShape._txtLocPinX;
if (_txtLocPinX == null)
return getTxtWidth()*0.5;
return _txtLocPinX;
}
public Double getTxtLocPinY() {
if (_txtLocPinY == null &&
_masterShape != null && _masterShape._txtLocPinY != null)
return _masterShape._txtLocPinY;
if (_txtLocPinY == null)
return getTxtHeight()*0.5;
return _txtLocPinY;
}
public Double getTxtAngle() {
if (_txtAngle == null && _masterShape != null)
return _masterShape.getTxtAngle();
return _txtAngle;
}
public Double getTxtWidth() {
if (_txtWidth == null &&
_masterShape != null && _masterShape._txtWidth != null)
return _masterShape._txtWidth;
if (_txtWidth == null)
return getWidth();
return _txtWidth;
}
public Double getTxtHeight() {
if (_txtHeight == null &&
_masterShape != null && _masterShape._txtHeight != null)
return _masterShape._txtHeight;
if (_txtHeight == null)
return getHeight();
return _txtHeight;
}
@Override
public Integer getLineCap() {
Integer lineCap = super.getLineCap();
if (lineCap != null)
return lineCap;
// get from master
if (_masterShape != null) {
return _masterShape.getLineCap();
}
// get default
XDGFStyleSheet style = _document.getDefaultLineStyle();
if (style != null)
return style.getLineCap();
return null;
}
@Override
public Color getLineColor() {
Color lineColor = super.getLineColor();
if (lineColor != null)
return lineColor;
// get from master
if (_masterShape != null) {
return _masterShape.getLineColor();
}
// get default
XDGFStyleSheet style = _document.getDefaultLineStyle();
if (style != null)
return style.getLineColor();
return null;
}
@Override
public Integer getLinePattern() {
Integer linePattern = super.getLinePattern();
if (linePattern != null)
return linePattern;
// get from master
if (_masterShape != null) {
return _masterShape.getLinePattern();
}
// get default
XDGFStyleSheet style = _document.getDefaultLineStyle();
if (style != null)
return style.getLinePattern();
return null;
}
@Override
public Double getLineWeight() {
Double lineWeight = super.getLineWeight();
if (lineWeight != null)
return lineWeight;
// get from master
if (_masterShape != null) {
return _masterShape.getLineWeight();
}
// get default
XDGFStyleSheet style = _document.getDefaultLineStyle();
if (style != null)
return style.getLineWeight();
return null;
}
public Color getFontColor() {
Color fontColor = super.getFontColor();
if (fontColor != null)
return fontColor;
// get from master
if (_masterShape != null) {
return _masterShape.getFontColor();
}
// get default
XDGFStyleSheet style = _document.getDefaultTextStyle();
if (style != null)
return style.getFontColor();
return null;
}
public Double getFontSize() {
Double fontSize = super.getFontSize();
if (fontSize != null)
return fontSize;
// get from master
if (_masterShape != null) {
return _masterShape.getFontSize();
}
// get default
XDGFStyleSheet style = _document.getDefaultTextStyle();
if (style != null)
return style.getFontSize();
return null;
}
public Stroke getStroke() {
float lineWeight = getLineWeight().floatValue();
int cap;
int join = BasicStroke.JOIN_MITER;
float miterlimit = 10.0f;
switch (getLineCap()) {
case 0:
cap = BasicStroke.CAP_ROUND;
break;
case 1:
cap = BasicStroke.CAP_SQUARE;
break;
case 2:
cap = BasicStroke.CAP_BUTT; // TODO: what does extended mean?
break;
default:
throw new POIXMLException("Invalid line cap specified");
}
float[] dash = null;
// these line patterns are just approximations
switch (getLinePattern()) {
case 0: // transparent
break;
case 1: // solid
break;
case 2:
dash = new float[]{5,3};
break;
case 3:
dash = new float[]{1,4};
break;
case 4:
dash = new float[]{6,3,1,3};
break;
case 5:
dash = new float[]{6,3,1,3,1,3};
break;
case 6:
dash = new float[]{1,3,6,3,6,3};
break;
case 7:
dash = new float[]{15,3,6,3};
break;
case 8:
dash = new float[]{6,3,6,3};
break;
case 9:
dash = new float[]{3,2};
break;
case 10:
dash = new float[]{1,2};
break;
case 11:
dash = new float[]{3,2,1,2};
break;
case 12:
dash = new float[]{3,2,1,2,1};
break;
case 13:
dash = new float[]{1,2,3,2,3,2};
break;
case 14:
dash = new float[]{3,2,7,2};
break;
case 15:
dash = new float[]{7,2,3,2,3,2};
break;
case 16:
dash = new float[]{12,6};
break;
case 17:
dash = new float[]{1,6};
break;
case 18:
dash = new float[]{1,6,12,6};
break;
case 19:
dash = new float[]{1,6,1,6,12,6};
break;
case 20:
dash = new float[]{1,6,12,6,12,6};
break;
case 21:
dash = new float[]{30,6,12,6};
break;
case 22:
dash = new float[]{30,6,12,6,12,6};
break;
case 23:
dash = new float[]{1};
break;
case 254:
throw new POIXMLException("Unsupported line pattern value");
default:
throw new POIXMLException("Invalid line pattern value");
}
// dashes are in units of line width
if (dash != null) {
for (int i = 0; i < dash.length; i++) {
dash[i] *= lineWeight;
}
}
return new BasicStroke(lineWeight, cap, join, miterlimit, dash, 0);
}
//
// Geometry
//
public Iterable<GeometrySection> getGeometrySections() {
return new CombinedIterable<>(_geometry,
_masterShape != null ? _masterShape._geometry : null);
}
// returns a rectangle in local coordinates
public Rectangle2D.Double getBounds() {
return new Rectangle2D.Double(0, 0, getWidth(),
getHeight());
}
// returns bounds as a path in local coordinates
// -> useful if you need to transform to global coordinates
// -> Don't use for 1d objects, fails for infinite line objects
public Path2D.Double getBoundsAsPath() {
Double w = getWidth();
Double h = getHeight();
Path2D.Double bounds = new Path2D.Double();
bounds.moveTo(0, 0);
bounds.lineTo(w, 0);
bounds.lineTo(w, h);
bounds.lineTo(0, h);
bounds.lineTo(0, 0);
return bounds;
}
// returns the path in local coordinates
public Path2D.Double getPath() {
for (GeometrySection geoSection: getGeometrySections()) {
if (geoSection.getNoShow() == true)
continue;
return geoSection.getPath(this);
}
return null;
}
/*
* Returns true if the shape has a drawable geometry associated with it
*/
public boolean hasGeometry() {
for (GeometrySection geoSection: getGeometrySections()) {
if (geoSection.getNoShow() == false)
return true;
}
return false;
}
/**
* Returns a transform that can translate shape-local coordinates
* to the coordinates of its parent shape
*/
protected AffineTransform getParentTransform() {
// TODO: There's probably a better way to do this
AffineTransform tr = new AffineTransform();
Double locX = getLocPinX();
Double locY = getLocPinY();
Boolean flipX = getFlipX();
Boolean flipY = getFlipY();
Double angle = getAngle();
tr.translate(-locX, -locY);
tr.translate(getPinX(), getPinY());
// rotate about the origin
if (angle != null && Math.abs(angle) > 0.001) {
tr.rotate(angle, locX, locY);
}
// flip if necessary
if (flipX != null && flipX) {
tr.scale(-1, 1);
tr.translate(-getWidth(), 0);
}
if (flipY != null && flipY) {
tr.scale(1, -1);
tr.translate(0, -getHeight());
}
return tr;
}
/**
* The visitor will first visit this shape, then it's children
*
* This is useful because exceptions will be marked with the shapes as it
* propagates up the shape hierarchy.
*/
public void visitShapes(ShapeVisitor visitor, AffineTransform tr, int level) {
tr = (AffineTransform)tr.clone();
tr.concatenate(getParentTransform());
try {
if (visitor.accept(this))
visitor.visit(this, tr, level);
if (_shapes != null) {
for (XDGFShape shape: _shapes) {
shape.visitShapes(visitor, tr, level + 1);
}
}
} catch (StopVisitingThisBranch e) {
// intentionally empty
} catch (POIXMLException e) {
throw XDGFException.wrap(this.toString(), e);
}
}
/**
* The visitor will first visit this shape, then it's children. No transform
* is calculated for this visit
*
* This is useful because exceptions will be marked with the shapes as it
* propagates up the shape hierarchy.
*/
public void visitShapes(ShapeVisitor visitor, int level) {
try {
if (visitor.accept(this))
visitor.visit(this, null, level);
if (_shapes != null) {
for (XDGFShape shape: _shapes) {
shape.visitShapes(visitor, level + 1);
}
}
} catch (StopVisitingThisBranch e) {
// intentionally empty
} catch (POIXMLException e) {
throw XDGFException.wrap(this.toString(), e);
}
}
}

View File

@ -0,0 +1,204 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import java.awt.Color;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.exceptions.XDGFException;
import org.apache.poi.xdgf.usermodel.section.CharacterSection;
import org.apache.poi.xdgf.usermodel.section.GeometrySection;
import org.apache.poi.xdgf.usermodel.section.XDGFSection;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.SectionType;
import com.microsoft.schemas.office.visio.x2012.main.SheetType;
/**
* A sheet is a collection of properties that specify information for a shape,
* master, drawing page, style, or web drawing.
*/
public abstract class XDGFSheet {
protected XDGFDocument _document;
protected SheetType _sheet;
// cells
protected Map<String, XDGFCell> _cells = new HashMap<>();
// sections
protected Map<String, XDGFSection> _sections = new HashMap<>();
// special: geometry sections (key: index, value: section)
protected SortedMap<Long, GeometrySection> _geometry = new TreeMap<>();
// special: character section
protected CharacterSection _character = null;
public XDGFSheet(SheetType sheet, XDGFDocument document) {
try {
_sheet = sheet;
_document = document;
for (CellType cell: sheet.getCellArray()) {
if (_cells.containsKey(cell.getN()))
throw new POIXMLException("Unexpected duplicate cell " + cell.getN()); // this shouldn't happen
_cells.put(cell.getN(), new XDGFCell(cell));
}
// only geometry sections can have duplicate names
// sections can be found in the master too, if there are no attributes here!
// no idea if I have a master in this space. go figure.
for (SectionType section: sheet.getSectionArray()) {
String name = section.getN();
if (name.equals("Geometry")) {
_geometry.put(section.getIX(), new GeometrySection(section, this));
} else if (name.equals("Character")) {
_character = new CharacterSection(section, this);
} else {
_sections.put(name, XDGFSection.load(section, this));
}
}
} catch (POIXMLException e) {
throw XDGFException.wrap(this.toString(), e);
}
}
abstract SheetType getXmlObject();
public XDGFDocument getDocument() {
return _document;
}
// A cell is really just a setting
public XDGFCell getCell(String cellName) {
return _cells.get(cellName);
}
public XDGFSection getSection(String sectionName) {
return _sections.get(sectionName);
}
public XDGFStyleSheet getLineStyle() {
if (!_sheet.isSetLineStyle())
return null;
return _document.getStyleById(_sheet.getLineStyle());
}
public XDGFStyleSheet getFillStyle() {
if (!_sheet.isSetFillStyle())
return null;
return _document.getStyleById(_sheet.getFillStyle());
}
public XDGFStyleSheet getTextStyle() {
if (!_sheet.isSetTextStyle())
return null;
return _document.getStyleById(_sheet.getTextStyle());
}
public Color getFontColor() {
Color fontColor = null;
if (_character != null) {
fontColor = _character.getFontColor();
if (fontColor != null)
return fontColor;
}
XDGFStyleSheet style = getTextStyle();
if (style != null)
return style.getFontColor();
return null;
}
public Double getFontSize() {
Double fontSize = null;
if (_character != null) {
fontSize = _character.getFontSize();
if (fontSize != null)
return fontSize;
}
XDGFStyleSheet style = getTextStyle();
if (style != null)
return style.getFontSize();
return null;
}
public Integer getLineCap() {
Integer lineCap = XDGFCell.maybeGetInteger(_cells, "LineCap");
if (lineCap != null)
return lineCap;
XDGFStyleSheet style = getLineStyle();
if (style != null)
return style.getLineCap();
return null;
}
public Color getLineColor() {
String lineColor = XDGFCell.maybeGetString(_cells, "LineColor");
if (lineColor != null)
return Color.decode(lineColor);
XDGFStyleSheet style = getLineStyle();
if (style != null)
return style.getLineColor();
return null;
}
public Integer getLinePattern() {
Integer linePattern = XDGFCell.maybeGetInteger(_cells, "LinePattern");
if (linePattern != null)
return linePattern;
XDGFStyleSheet style = getLineStyle();
if (style != null)
return style.getLinePattern();
return null;
}
public Double getLineWeight() {
Double lineWeight = XDGFCell.maybeGetDouble(_cells, "LineWeight");
if (lineWeight != null)
return lineWeight;
XDGFStyleSheet style = getLineStyle();
if (style != null)
return style.getLineWeight();
return null;
}
}

View File

@ -0,0 +1,36 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import org.apache.poi.util.Internal;
import com.microsoft.schemas.office.visio.x2012.main.StyleSheetType;
public class XDGFStyleSheet extends XDGFSheet {
public XDGFStyleSheet(StyleSheetType styleSheet, XDGFDocument document) {
super(styleSheet, document);
}
@Internal
public StyleSheetType getXmlObject() {
return (StyleSheetType)_sheet;
}
}

View File

@ -0,0 +1,150 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.apache.poi.util.Internal;
import com.microsoft.schemas.office.visio.x2012.main.TextType;
import com.microsoft.schemas.office.visio.x2012.main.impl.TextTypeImpl;
public class XDGFText {
TextType _text;
XDGFShape _parent;
public XDGFText(TextType text, XDGFShape parent) {
_text = text;
_parent = parent;
}
@Internal
TextType getXmlObject() {
return _text;
}
public String getTextContent() {
// casting here is wrong, but there's no other way of getting the value,
// as it doesn't seem to be exposed by complex types (even though this
// is a mixed type)
return ((TextTypeImpl)_text).getStringValue();
}
// these are in the shape coordinate system
// -> See https://msdn.microsoft.com/en-us/library/hh644132(v=office.12).aspx
public Rectangle2D.Double getTextBounds() {
double txtPinX = _parent.getTxtPinX();
double txtPinY = _parent.getTxtPinY();
double txtLocPinX = _parent.getTxtLocPinX();
double txtLocPinY = _parent.getTxtLocPinY();
double txtWidth = _parent.getTxtWidth();
double txtHeight = _parent.getTxtHeight();
double x = txtPinX - txtLocPinX;
double y = txtPinY - txtLocPinY;
return new Rectangle2D.Double(x, y, txtWidth, txtHeight);
}
// returns bounds as a path in local coordinates
// -> useful if you need to transform to global coordinates
public Path2D.Double getBoundsAsPath() {
Rectangle2D.Double rect = getTextBounds();
Double w = rect.getWidth();
Double h = rect.getHeight();
Path2D.Double bounds = new Path2D.Double();
bounds.moveTo(0, 0);
bounds.lineTo(w, 0);
bounds.lineTo(w, h);
bounds.lineTo(0, h);
bounds.lineTo(0, 0);
return bounds;
}
// center of text in local coordinates
public Point2D.Double getTextCenter() {
return new Point2D.Double(_parent.getTxtLocPinX(), _parent.getTxtLocPinY());
}
// assumes graphics is set properly to draw in the right style
public void draw(Graphics2D graphics) {
String textContent = getTextContent();
if (textContent.length() == 0)
return;
Rectangle2D.Double bounds = getTextBounds();
String[] lines = textContent.trim().split("\n");
FontRenderContext frc = graphics.getFontRenderContext();
Font font = graphics.getFont();
AffineTransform oldTr = graphics.getTransform();
// visio is in flipped coordinates, so translate the text to be in the right place
Boolean flipX = _parent.getFlipX();
Boolean flipY = _parent.getFlipY();
if (flipY == null || !_parent.getFlipY()) {
graphics.translate(bounds.x, bounds.y);
graphics.scale(1, -1);
graphics.translate(0, -bounds.height + graphics.getFontMetrics().getMaxCharBounds(graphics).getHeight());
}
if (flipX != null && _parent.getFlipX()) {
graphics.scale(-1, 1);
graphics.translate(-bounds.width, 0);
}
Double txtAngle = _parent.getTxtAngle();
if (txtAngle != null && Math.abs(txtAngle) > 0.01)
graphics.rotate(txtAngle);
float nextY = 0;
for (String line: lines) {
if (line.length() == 0)
continue;
TextLayout layout = new TextLayout(line, font, frc);
if (layout.isLeftToRight())
layout.draw(graphics, 0, nextY);
else
layout.draw(graphics, (float)(bounds.width - layout.getAdvance()), nextY);
nextY += layout.getAscent() + layout.getDescent() + layout.getLeading();
}
graphics.setTransform(oldTr);
}
}

View File

@ -0,0 +1,113 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.POIXMLException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.util.PackageHelper;
import org.apache.xmlbeans.XmlException;
import com.microsoft.schemas.office.visio.x2012.main.VisioDocumentDocument1;
import com.microsoft.schemas.office.visio.x2012.main.VisioDocumentType;
public class XmlVisioDocument extends POIXMLDocument {
public static String CORE_DOCUMENT = "http://schemas.microsoft.com/visio/2010/relationships/document";
XDGFPages _pages;
XDGFMasters _masters;
XDGFDocument _document;
public XmlVisioDocument(OPCPackage pkg) throws IOException {
super(pkg, CORE_DOCUMENT);
VisioDocumentType document;
try {
document = VisioDocumentDocument1.Factory.parse(getPackagePart().getInputStream()).getVisioDocument();
} catch (XmlException | IOException e) {
throw new POIXMLException(e);
}
_document = new XDGFDocument(document);
//build a tree of POIXMLDocumentParts, this document being the root
load(new XDGFFactory(_document));
}
public XmlVisioDocument(InputStream is) throws IOException {
this(PackageHelper.open(is));
}
@Override
protected void onDocumentRead() throws IOException {
// by the time this gets called, all other document parts should
// have been loaded, so it's safe to build the document structure
// note that in other onDocumentRead(), relations/etc may not have
// loaded yet, so it's not quite safe
for (POIXMLDocumentPart part: getRelations()) {
// organize the document pieces
if (part instanceof XDGFPages)
_pages = (XDGFPages)part;
else if (part instanceof XDGFMasters)
_masters = (XDGFMasters)part;
}
if (_masters != null)
_masters.onDocumentRead();
_pages.onDocumentRead();
}
@Override
public List<PackagePart> getAllEmbedds() throws OpenXML4JException {
throw new UnsupportedOperationException("Not implemented");
}
//
// Useful public API goes here
//
public Collection<XDGFPage> getPages() {
return _pages.getPageList();
}
public XDGFStyleSheet getStyleById(long id) {
return _document.getStyleById(id);
}
}

View File

@ -0,0 +1,71 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section;
import java.awt.Color;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFSheet;
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.SectionType;
public class CharacterSection extends XDGFSection {
Double _fontSize = null;
Color _fontColor = null;
Map<String, XDGFCell> _characterCells = new HashMap<>();
public CharacterSection(SectionType section, XDGFSheet containingSheet) {
super(section, containingSheet);
// there aren't cells for this, just a single row
RowType row = section.getRowArray(0);
for (CellType cell: row.getCellArray()) {
_characterCells.put(cell.getN(), new XDGFCell(cell));
}
if (row != null) {
_fontSize = XDGFCell.maybeGetDouble(_characterCells, "Size");
String tmpColor = XDGFCell.maybeGetString(_characterCells, "Color");
if (tmpColor != null)
_fontColor = Color.decode(tmpColor);
}
}
public Double getFontSize() {
return _fontSize;
}
public Color getFontColor() {
return _fontColor;
}
@Override
public void setupMaster(XDGFSection section) {
}
}

View File

@ -0,0 +1,136 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section;
import java.util.Collections;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.SortedMap;
import java.util.Map.Entry;
// iterates over the base and master
public class CombinedIterable<T> implements Iterable<T> {
final SortedMap<Long, T> _baseItems;
final SortedMap<Long, T> _masterItems;
public CombinedIterable(SortedMap<Long, T> baseItems,
SortedMap<Long, T> masterItems) {
_baseItems = baseItems;
_masterItems = masterItems;
}
@Override
public Iterator<T> iterator() {
final Iterator<Entry<Long, T>> vmasterI;
if (_masterItems != null)
vmasterI = _masterItems.entrySet().iterator();
else
vmasterI = Collections.emptyIterator();
return new Iterator<T>() {
Long lastI = Long.MIN_VALUE;
Entry<Long, T> currentBase = null;
Entry<Long, T> currentMaster = null;
// grab the iterator for both
Iterator<Entry<Long, T>> baseI = _baseItems.entrySet().iterator();
Iterator<Entry<Long, T>> masterI = vmasterI;
@Override
public boolean hasNext() {
return currentBase != null || currentMaster != null || baseI.hasNext() || masterI.hasNext();
}
@Override
public T next() {
// TODO: This seems far more complex than it needs to be
long baseIdx = Long.MAX_VALUE;
long masterIdx = Long.MAX_VALUE;
if (currentBase == null) {
while (baseI.hasNext()) {
currentBase = baseI.next();
if (currentBase.getKey() > lastI) {
baseIdx = currentBase.getKey();
break;
}
}
} else {
baseIdx = currentBase.getKey();
}
if (currentMaster == null) {
while (masterI.hasNext()) {
currentMaster = masterI.next();
if (currentMaster.getKey() > lastI) {
masterIdx = currentMaster.getKey();
break;
}
}
} else {
masterIdx = currentMaster.getKey();
}
T val;
if (currentBase != null) {
if (baseIdx <= masterIdx) {
lastI = baseIdx;
val = currentBase.getValue();
// discard master if same as base
if (masterIdx == baseIdx) {
currentMaster = null;
}
currentBase = null;
} else {
lastI = masterIdx;
val = currentMaster.getValue();
currentMaster = null;
}
} else if (currentMaster != null) {
lastI = currentMaster.getKey();
val = currentMaster.getValue();
currentMaster = null;
} else {
throw new NoSuchElementException();
}
return val;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}

View File

@ -0,0 +1,33 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section;
import org.apache.poi.xdgf.usermodel.XDGFSheet;
import com.microsoft.schemas.office.visio.x2012.main.SectionType;
public class GenericSection extends XDGFSection {
public GenericSection(SectionType section, XDGFSheet containingSheet) {
super(section, containingSheet);
}
@Override
public void setupMaster(XDGFSection section) {
}
}

View File

@ -0,0 +1,155 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section;
import java.awt.geom.Path2D;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.geom.SplineCollector;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import org.apache.poi.xdgf.usermodel.XDGFSheet;
import org.apache.poi.xdgf.usermodel.section.geometry.Ellipse;
import org.apache.poi.xdgf.usermodel.section.geometry.GeometryRowFactory;
import org.apache.poi.xdgf.usermodel.section.geometry.InfiniteLine;
import org.apache.poi.xdgf.usermodel.section.geometry.GeometryRow;
import org.apache.poi.xdgf.usermodel.section.geometry.SplineKnot;
import org.apache.poi.xdgf.usermodel.section.geometry.SplineStart;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
import com.microsoft.schemas.office.visio.x2012.main.SectionType;
public class GeometrySection extends XDGFSection {
GeometrySection _master = null;
// rows
SortedMap<Long, GeometryRow> _rows = new TreeMap<>();
public GeometrySection(SectionType section, XDGFSheet containingSheet) {
super(section, containingSheet);
for (RowType row: section.getRowArray()) {
if (_rows.containsKey(row.getIX()))
throw new POIXMLException("Index element '" + row.getIX() + "' already exists");
_rows.put(row.getIX(), GeometryRowFactory.load(row));
}
}
@Override
public void setupMaster(XDGFSection master) {
_master = (GeometrySection)master;
for (Entry<Long, GeometryRow> entry : _rows.entrySet()) {
GeometryRow masterRow = _master._rows.get(entry.getKey());
if (masterRow != null) {
try {
entry.getValue().setupMaster(masterRow);
} catch (ClassCastException e) {
// this can happen when a dynamic connector overrides its master's geometry
// .. probably can happen elsewhere too, I imagine.
//throw XDGFException.error("Mismatched geometry section '" + entry.getKey() + "' in master", this, e);
}
}
}
}
// returns True if this row shouldn't be displayed
public Boolean getNoShow() {
Boolean noShow = XDGFCell.maybeGetBoolean(_cells, "NoShow");
if (noShow == null) {
if (_master != null)
return _master.getNoShow();
return false;
}
return noShow;
}
public Iterable<GeometryRow> getCombinedRows() {
return new CombinedIterable<>(_rows,
_master == null ? null : _master._rows);
}
public Path2D.Double getPath(XDGFShape parent) {
Iterator<GeometryRow> rows = getCombinedRows().iterator();
// special cases
GeometryRow first = rows.next();
if (first instanceof Ellipse) {
return ((Ellipse)first).getPath();
} else if (first instanceof InfiniteLine) {
return ((InfiniteLine)first).getPath();
} else if (first instanceof SplineStart) {
throw new POIXMLException("SplineStart must be preceded by another type");
} else {
// everything else is a path
Path2D.Double path = new Path2D.Double();
// dealing with splines makes this more complex
SplineCollector renderer = null;
GeometryRow row;
while (true) {
if (first != null) {
row = first;
first = null;
} else {
if (!rows.hasNext())
break;
row = rows.next();
}
if (row instanceof SplineStart) {
if (renderer != null)
throw new POIXMLException("SplineStart found multiple times!");
renderer = new SplineCollector((SplineStart) row);
} else if (row instanceof SplineKnot) {
if (renderer == null)
throw new POIXMLException("SplineKnot found without SplineStart!");
renderer.addKnot((SplineKnot) row);
} else {
if (renderer != null) {
renderer.addToPath(path, parent);
renderer = null;
}
row.addToPath(path, parent);
}
}
// just in case we end iteration
if (renderer != null)
renderer.addToPath(path, parent);
return path;
}
}
}

View File

@ -0,0 +1,98 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.POIXMLException;
import org.apache.poi.util.Internal;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFSheet;
import org.apache.poi.xdgf.util.ObjectFactory;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.SectionType;
public abstract class XDGFSection {
static final ObjectFactory<XDGFSection, SectionType> _sectionTypes;
static {
_sectionTypes = new ObjectFactory<>();
try {
_sectionTypes.put("LineGradient", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("FillGradient", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Character", CharacterSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Paragraph", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Tabs", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Scratch", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Connection", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("ConnectionABCD", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Field", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Control", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Geometry", GeometrySection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Actions", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Layer", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("User", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Property", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Hyperlink", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Reviewer", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("Annotation", GenericSection.class, SectionType.class, XDGFSheet.class);
_sectionTypes.put("ActionTag", GenericSection.class, SectionType.class, XDGFSheet.class);
} catch (NoSuchMethodException | SecurityException e) {
throw new POIXMLException("Internal error");
}
}
public static XDGFSection load(SectionType section, XDGFSheet containingSheet) {
return _sectionTypes.load(section.getN(), section, containingSheet);
}
protected SectionType _section;
protected XDGFSheet _containingSheet;
protected Map<String, XDGFCell> _cells = new HashMap<>();
public XDGFSection(SectionType section, XDGFSheet containingSheet) {
_section = section;
_containingSheet = containingSheet;
// only store cells in the base, not rows -- because rows are handled
// specially for geometry sections
for (CellType cell: section.getCellArray()) {
_cells.put(cell.getN(), new XDGFCell(cell));
}
}
@Internal
public SectionType getXmlObject() {
return _section;
}
@Override
public String toString() {
return "<Section type=" + _section.getN() + " from " + _containingSheet + ">";
}
public abstract void setupMaster(XDGFSection section);
}

View File

@ -0,0 +1,131 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class ArcTo implements GeometryRow {
ArcTo _master = null;
// The x-coordinate of the ending vertex of an arc.
Double x = null;
// The y-coordinate of the ending vertex of an arc.
Double y = null;
// The distance from the arc's midpoint to the midpoint of its chord.
Double a = null;
Boolean deleted = null;
// TODO: support formulas
public ArcTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel();
for (CellType cell: row.getCellArray()) {
String cellName = cell.getN();
if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell);
} else {
throw new POIXMLException("Invalid cell '" + cellName + "' in ArcTo row");
}
}
}
public boolean getDel() {
if (deleted != null)
return deleted;
if (_master != null)
return _master.getDel();
return false;
}
public Double getX() {
return x == null ? _master.x : x;
}
public Double getY() {
return y == null ? _master.y : y;
}
public Double getA() {
return a == null ? _master.a : a;
}
@Override
public void setupMaster(GeometryRow row) {
_master = (ArcTo) row;
}
@Override
public void addToPath(Path2D.Double path, XDGFShape parent) {
if (getDel()) return;
Point2D last = path.getCurrentPoint();
// intentionally shadowing variables here
double x = getX();
double y = getY();
double a = getA();
if (a == 0) {
path.lineTo(x, y);
return;
}
double x0 = last.getX();
double y0 = last.getY();
double chordLength = Math.hypot(y - y0, x - x0);
double radius = (4 * a * a + chordLength * chordLength) / (8 * Math.abs(a));
// center point
double cx = x0 + (x - x0) / 2.0;
double cy = y0 + (y - y0) / 2.0;
double rotate = Math.atan2(y - cy, x - cx);
Arc2D arc = new Arc2D.Double(x0, y0 - radius,
chordLength, 2*radius,
180, x0 < x ? 180 : -180,
Arc2D.OPEN);
path.append(AffineTransform.getRotateInstance(rotate, x0, y0).createTransformedShape(arc), true);
}
}

View File

@ -0,0 +1,156 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class Ellipse implements GeometryRow {
Ellipse _master = null;
// x coordinate of center point
Double x = null;
// y coordinate of center point
Double y = null;
// x coordinate of first point on ellipse
Double a = null;
// y coordinate of first point on ellipse
Double b = null;
// x coordinate of second point on ellipse
Double c = null;
// y coordinate of second point on ellipse
Double d = null;
Boolean deleted = null;
// TODO: support formulas
public Ellipse(RowType row) {
if (row.isSetDel()) deleted = row.getDel();
for (CellType cell: row.getCellArray()) {
String cellName = cell.getN();
if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("B")) {
b = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("C")) {
c = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("D")) {
d = XDGFCell.parseDoubleValue(cell);
} else {
throw new POIXMLException("Invalid cell '" + cellName + "' in Ellipse row");
}
}
}
public boolean getDel() {
if (deleted != null)
return deleted;
if (_master != null)
return _master.getDel();
return false;
}
public Double getX() {
return x == null ? _master.x : x;
}
public Double getY() {
return y == null ? _master.y : y;
}
public Double getA() {
return a == null ? _master.a : a;
}
public Double getB() {
return b == null ? _master.b : b;
}
public Double getC() {
return c == null ? _master.c : c;
}
public Double getD() {
return d == null ? _master.d : d;
}
@Override
public void setupMaster(GeometryRow row) {
_master = (Ellipse) row;
}
public Path2D.Double getPath() {
if (getDel()) return null;
// intentionally shadowing variables here
double cx = getX(); // center
double cy = getY();
double a = getA(); // left
double b = getB();
double c = getC(); // top
double d = getD();
// compute radius
double rx = Math.hypot(a - cx, b - cy);
double ry = Math.hypot(c - cx, d - cy);
// compute angle of ellipse
double angle = (2.0*Math.PI + (cy > b ? 1.0 : -1.0) * Math.acos((cx - a) / rx)) % (2.0*Math.PI);
// create ellipse
Ellipse2D.Double ellipse = new Ellipse2D.Double(cx - rx,
cy - ry,
rx*2, ry*2);
// create a path, rotate it about its center
Path2D.Double path = new Path2D.Double(ellipse);
AffineTransform tr = new AffineTransform();
tr.rotate(angle, cx, cy);
path.transform(tr);
return path;
}
@Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
throw new POIXMLException("Ellipse elements cannot be part of a path");
}
}

View File

@ -0,0 +1,231 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class EllipticalArcTo implements GeometryRow {
EllipticalArcTo _master = null;
// The x-coordinate of the ending vertex on an arc.
Double x = null;
// The y-coordinate of the ending vertex on an arc.
Double y = null;
// The x-coordinate of the arc's control point; a point on the arc. The
// control point is best located about halfway between the beginning and
// ending vertices of the arc. Otherwise, the arc may grow to an extreme
// size in order to pass through the control point, with unpredictable
// results.
Double a = null;
// The y-coordinate of an arc's control point.
Double b = null;
// The angle of an arc's major axis relative to the x-axis of its parent shape.
Double c = null;
// The ratio of an arc's major axis to its minor axis. Despite the usual
// meaning of these words, the "major" axis does not have to be greater than
// the "minor" axis, so this ratio does not have to be greater than 1.
// Setting this cell to a value less than or equal to 0 or greater than 1000
// can lead to unpredictable results.
Double d = null;
Boolean deleted = null;
// TODO: support formulas
public EllipticalArcTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel();
for (CellType cell: row.getCellArray()) {
String cellName = cell.getN();
if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("B")) {
b = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("C")) {
c = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("D")) {
d = XDGFCell.parseDoubleValue(cell);
} else {
throw new POIXMLException("Invalid cell '" + cellName + "' in EllipticalArcTo row");
}
}
}
public boolean getDel() {
if (deleted != null)
return deleted;
if (_master != null)
return _master.getDel();
return false;
}
public Double getX() {
return x == null ? _master.x : x;
}
public Double getY() {
return y == null ? _master.y : y;
}
public Double getA() {
return a == null ? _master.a : a;
}
public Double getB() {
return b == null ? _master.b : b;
}
public Double getC() {
return c == null ? _master.c : c;
}
public Double getD() {
return d == null ? _master.d : d;
}
@Override
public void setupMaster(GeometryRow row) {
_master = (EllipticalArcTo) row;
}
public static int draw = 0;
@Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return;
// intentionally shadowing variables here
double x = getX();
double y = getY();
double a = getA();
double b = getB();
double c = getC();
double d = getD();
createEllipticalArc(x, y, a, b, c, d, path);
}
public static void createEllipticalArc(double x, double y, double a, double b,
double c, double d,
java.awt.geom.Path2D.Double path) {
// Formula for center of ellipse by Junichi Yoda & nashwaan:
// -> From http://visguy.com/vgforum/index.php?topic=2464.0
//
// x1,y1 = start; x2,y2 = end; x3,y3 = control point
//
// x0 = ((x1-x2)*(x1+x2)*(y2-y3)-(x2-x3)*(x2+x3)*(y1-y2)+D^2*(y1-y2)*(y2-y3)*(y1-y3))/(2*((x1-x2)*(y2-y3)-(x2-x3)*(y1-y2)))
// y0 = ((x1-x2)*(x2-x3)*(x1-x3)/D^2+(x2-x3)*(y1-y2)*(y1+y2)-(x1-x2)*(y2-y3)*(y2+y3))/(2*((x2-x3)*(y1-y2)-(x1-x2)*(y2-y3)))
// radii along axis: a = sqrt{ (x1-x0)^2 + (y1-y0)^2 * D^2 }
//
Point2D last = path.getCurrentPoint();
double x0 = last.getX();
double y0 = last.getY();
// translate all of the points to the same angle as the ellipse
AffineTransform at = AffineTransform.getRotateInstance(-c);
double[] pts = new double[]{x0, y0, x, y, a, b};
at.transform(pts, 0, pts, 0, 3);
x0 = pts[0]; y0 = pts[1];
x = pts[2]; y = pts[3];
a = pts[4]; b = pts[5];
// nasty math time
double d2 = d*d;
double cx = ((x0-x)*(x0+x)*(y-b)-(x-a)*(x+a)*(y0-y)+d2*(y0-y)*(y-b)*(y0-b))/(2.0*((x0-x)*(y-b)-(x-a)*(y0-y)));
double cy = ((x0-x)*(x-a)*(x0-a)/d2+(x-a)*(y0-y)*(y0+y)-(x0-x)*(y-b)*(y+b))/(2.0*((x-a)*(y0-y)-(x0-x)*(y-b)));
// calculate radii of ellipse
double rx = Math.sqrt(Math.pow(x0-cx, 2) + Math.pow(y0-cy,2) * d2);
double ry = rx / d;
// Arc2D requires us to draw an arc from one point to another, so we
// need to calculate the angle of the start point and end point along the ellipse
// - Derived from parametric form of ellipse: x = h + a*cos(t); y = k + b*sin(t)
double ctrlAngle = Math.toDegrees(Math.atan2((b-cy)/ry, (a-cx)/rx));
double startAngle = Math.toDegrees(Math.atan2((y0-cy)/ry, (x0-cx)/rx));
double endAngle = Math.toDegrees(Math.atan2((y-cy)/ry, (x-cx)/rx));
double sweep = computeSweep(startAngle, endAngle, ctrlAngle);
// Now we have enough information to go on. Create the arc.
Arc2D arc = new Arc2D.Double(cx-rx, cy-ry,
rx*2, ry*2, -startAngle, sweep, Arc2D.OPEN);
// rotate the arc back to the original coordinate system
at.setToRotation(c);
path.append(at.createTransformedShape(arc), false);
}
protected static double computeSweep(double startAngle, double endAngle, double ctrlAngle) {
double sweep;
startAngle = (360.0 + startAngle) % 360.0;
endAngle = (360.0 + endAngle) % 360.0;
ctrlAngle = (360.0 + ctrlAngle) % 360.0;
// different sweeps depending on where the control point is
if (startAngle < endAngle) {
if (startAngle < ctrlAngle && ctrlAngle < endAngle) {
sweep = startAngle - endAngle;
} else {
sweep = 360 + (startAngle - endAngle);
}
} else {
if (endAngle < ctrlAngle && ctrlAngle < startAngle) {
sweep = startAngle - endAngle;
} else {
sweep = - (360 - (startAngle - endAngle));
}
}
return sweep;
}
}

View File

@ -0,0 +1,31 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import java.awt.geom.Path2D;
import org.apache.poi.xdgf.usermodel.XDGFShape;
public interface GeometryRow {
public void setupMaster(GeometryRow row);
public void addToPath(Path2D.Double path, XDGFShape parent);
}

View File

@ -0,0 +1,57 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.util.ObjectFactory;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class GeometryRowFactory {
static final ObjectFactory<GeometryRow, RowType> _rowTypes;
static {
_rowTypes = new ObjectFactory<>();
try {
_rowTypes.put("ArcTo", ArcTo.class, RowType.class);
_rowTypes.put("Ellipse", Ellipse.class, RowType.class);
_rowTypes.put("EllipticalArcTo", EllipticalArcTo.class, RowType.class);
_rowTypes.put("InfiniteLine", InfiniteLine.class, RowType.class);
_rowTypes.put("LineTo", LineTo.class, RowType.class);
_rowTypes.put("MoveTo", MoveTo.class, RowType.class);
_rowTypes.put("NURBSTo", NURBSTo.class, RowType.class);
_rowTypes.put("PolyLineTo", PolyLineTo.class, RowType.class);
_rowTypes.put("RelCubBezTo", RelCubBezTo.class, RowType.class);
_rowTypes.put("RelEllipticalArcTo", RelEllipticalArcTo.class, RowType.class);
_rowTypes.put("RelLineTo", RelLineTo.class, RowType.class);
_rowTypes.put("RelMoveTo", RelMoveTo.class, RowType.class);
_rowTypes.put("RelQuadBezTo", RelQuadBezTo.class, RowType.class);
_rowTypes.put("SplineKnot", SplineKnot.class, RowType.class);
_rowTypes.put("SplineStart", SplineStart.class, RowType.class);
} catch (NoSuchMethodException | SecurityException e) {
throw new POIXMLException("Internal error", e);
}
}
public static GeometryRow load(RowType row) {
return _rowTypes.load(row.getT(), row);
}
}

View File

@ -0,0 +1,151 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.geom.Dimension2dDouble;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFDocument;
import org.apache.poi.xdgf.usermodel.XDGFPage;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
/**
* Contains the x- and y-coordinates of two points on an infinite line.
*/
public class InfiniteLine implements GeometryRow {
InfiniteLine _master = null;
// An x-coordinate of a point on the infinite line; paired with y-coordinate represented by the Y cell.
Double x = null;
// A y-coordinate of a point on the infinite line; paired with x-coordinate represented by the X cell.
Double y = null;
// An x-coordinate of a point on the infinite line; paired with y-coordinate represented by the B cell.
Double a = null;
// A y-coordinate of a point on an infinite line; paired with x-coordinate represented by the A cell.
Double b = null;
Boolean deleted = null;
// TODO: support formulas
public InfiniteLine(RowType row) {
if (row.isSetDel()) deleted = row.getDel();
for (CellType cell: row.getCellArray()) {
String cellName = cell.getN();
if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("B")) {
b = XDGFCell.parseDoubleValue(cell);
} else {
throw new POIXMLException("Invalid cell '" + cellName + "' in InfiniteLine row");
}
}
}
public boolean getDel() {
if (deleted != null)
return deleted;
if (_master != null)
return _master.getDel();
return false;
}
public Double getX() {
return x == null ? _master.x : x;
}
public Double getY() {
return y == null ? _master.y : y;
}
public Double getA() {
return a == null ? _master.a : a;
}
public Double getB() {
return b == null ? _master.b : b;
}
@Override
public void setupMaster(GeometryRow row) {
_master = (InfiniteLine) row;
}
@Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return;
throw new POIXMLException("InfiniteLine elements cannot be part of a path");
}
// returns this object as a line that extends between the boundaries of
// the document
public Path2D.Double getPath() {
Path2D.Double path = new Path2D.Double();
// this is a bit of a hack, but it works
double max_val = 100000;
// compute slope..
double x0 = getX();
double y0 = getY();
double x1 = getA(); // second x
double y1 = getB(); // second y
if (x0 == x1) {
path.moveTo(x0, -max_val);
path.lineTo(x0, max_val);
} else if (y0 == y1) {
path.moveTo(-max_val, y0);
path.lineTo(max_val, y0);
} else {
// normal case: compute slope/intercept
double m = (y1 - y0) / (x1 - x0);
double c = y0 - m*x0;
// y = mx + c
path.moveTo(max_val, m*max_val + c);
path.lineTo(max_val, (max_val - c)/m);
}
return path;
}
}

View File

@ -0,0 +1,88 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class LineTo implements GeometryRow {
LineTo _master = null;
Double x = null;
Double y = null;
Boolean deleted = null;
// TODO: support formulas
public LineTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel();
for (CellType cell: row.getCellArray()) {
String cellName = cell.getN();
if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell);
} else {
throw new POIXMLException("Invalid cell '" + cellName + "' in LineTo row");
}
}
}
@Override
public String toString() {
return "LineTo: x=" + getX() + "; y=" + getY();
}
public boolean getDel() {
if (deleted != null)
return deleted;
if (_master != null)
return _master.getDel();
return false;
}
public Double getX() {
return x == null ? _master.x : x;
}
public Double getY() {
return y == null ? _master.y : y;
}
@Override
public void setupMaster(GeometryRow row) {
_master = (LineTo) row;
}
@Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return;
path.lineTo(getX(), getY());
}
}

View File

@ -0,0 +1,93 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
/**
* Contains the x- and y-coordinates of the first vertex of a shape or the x-
* and y-coordinates of the first vertex after a break in a path, relative to
* the height and width of the shape.
*/
public class MoveTo implements GeometryRow {
MoveTo _master = null;
Double x = null;
Double y = null;
Boolean deleted = null;
// TODO: support formulas
public MoveTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel();
for (CellType cell: row.getCellArray()) {
String cellName = cell.getN();
if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell);
} else {
throw new POIXMLException("Invalid cell '" + cellName + "' in MoveTo row");
}
}
}
@Override
public String toString() {
return "MoveTo: x=" + getX() + "; y=" + getY();
}
public boolean getDel() {
if (deleted != null)
return deleted;
if (_master != null)
return _master.getDel();
return false;
}
public Double getX() {
return x == null ? _master.x : x;
}
public Double getY() {
return y == null ? _master.y : y;
}
@Override
public void setupMaster(GeometryRow row) {
_master = (MoveTo) row;
}
@Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return;
path.moveTo(getX(), getY());
}
}

View File

@ -0,0 +1,205 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import java.awt.geom.Point2D;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.geom.SplineRenderer;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import com.graphbuilder.curve.ControlPath;
import com.graphbuilder.curve.ShapeMultiPath;
import com.graphbuilder.curve.ValueVector;
import com.graphbuilder.geom.PointFactory;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class NURBSTo implements GeometryRow {
NURBSTo _master = null;
// The x-coordinate of the last control point of a NURBS.
Double x = null;
// The y-coordinate of the last control point of a NURBS.
Double y = null;
// The second to the last knot of the NURBS.
Double a = null;
// The last weight of the NURBS.
Double b = null;
// The first knot of the NURBS.
Double c = null;
// The first weight of the NURBS.
Double d = null;
// A NURBS formula.
String e = null;
Boolean deleted = null;
// TODO: support formulas
public NURBSTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel();
for (CellType cell: row.getCellArray()) {
String cellName = cell.getN();
if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("B")) {
b = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("C")) {
c = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("D")) {
d = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("E")) {
e = cell.getV();
} else {
throw new POIXMLException("Invalid cell '" + cellName + "' in NURBS row");
}
}
}
public boolean getDel() {
if (deleted != null)
return deleted;
if (_master != null)
return _master.getDel();
return false;
}
public Double getX() {
return x == null ? _master.x : x;
}
public Double getY() {
return y == null ? _master.y : y;
}
public Double getA() {
return a == null ? _master.a : a;
}
public Double getB() {
return b == null ? _master.b : b;
}
public Double getC() {
return c == null ? _master.c : c;
}
public Double getD() {
return d == null ? _master.d : d;
}
public String getE() {
return e == null ? _master.e : e;
}
@Override
public void setupMaster(GeometryRow row) {
_master = (NURBSTo) row;
}
@Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return;
Point2D last = path.getCurrentPoint();
// A NURBS formula: knotLast, degree, xType, yType, x1, y1, knot1, weight1, ..
String formula = getE().trim();
if (!formula.startsWith("NURBS(") || !formula.endsWith(")"))
throw new POIXMLException("Invalid NURBS formula: " + formula);
String [] components = formula.substring(6, formula.length()-1).split(",");
if (components.length < 8)
throw new POIXMLException("Invalid NURBS formula (not enough arguments)");
if ((components.length - 4) % 4 != 0)
throw new POIXMLException("Invalid NURBS formula -- need 4 + n*4 arguments, got " + components.length);
double lastControlX = getX();
double lastControlY = getY();
double secondToLastKnot = getA();
double lastWeight = getB();
double firstKnot = getC();
double firstWeight = getD();
double lastKnot = Double.parseDouble(components[0].trim());
int degree = Integer.parseInt(components[1].trim());
int xType = Integer.parseInt(components[2].trim());
int yType = Integer.parseInt(components[3].trim());
double xScale = 1;
double yScale = 1;
if (xType == 0)
xScale = parent.getWidth();
if (yType == 0)
yScale = parent.getHeight();
// setup first knots/weights/control point
ControlPath controlPath = new ControlPath();
ValueVector knots = new ValueVector();
ValueVector weights = new ValueVector();
knots.add(firstKnot);
weights.add(firstWeight);
controlPath.addPoint(PointFactory.create(last.getX(), last.getY()));
// iterate get knots/weights
int sets = (components.length - 4) / 4;
for (int i = 0; i < sets; i++) {
double x1 = Double.parseDouble(components[4 + i*4 + 0].trim());
double y1 = Double.parseDouble(components[4 + i*4 + 1].trim());
double k = Double.parseDouble(components[4 + i*4 + 2].trim());
double w = Double.parseDouble(components[4 + i*4 + 3].trim());
controlPath.addPoint(PointFactory.create(x1*xScale, y1*yScale));
knots.add(k);
weights.add(w);
}
// last knots/weights/control point
knots.add(secondToLastKnot);
knots.add(lastKnot);
weights.add(lastWeight);
controlPath.addPoint(PointFactory.create(lastControlX, lastControlY));
ShapeMultiPath shape = SplineRenderer.createNurbsSpline(controlPath, knots, weights, degree);
path.append(shape, true);
}
}

View File

@ -0,0 +1,95 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class PolyLineTo implements GeometryRow {
PolyLineTo _master = null;
// The x-coordinate of the ending vertex of a polyline.
Double x = null;
// The y-coordinate of the ending vertex of a polyline.
Double y = null;
// The polyline formula
String a = null;
Boolean deleted = null;
// TODO: support formulas
public PolyLineTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel();
for (CellType cell: row.getCellArray()) {
String cellName = cell.getN();
if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) {
a = cell.getV();
} else {
throw new POIXMLException("Invalid cell '" + cellName + "' in ArcTo row");
}
}
}
public boolean getDel() {
if (deleted != null)
return deleted;
if (_master != null)
return _master.getDel();
return false;
}
public Double getX() {
return x == null ? _master.x : x;
}
public Double getY() {
return y == null ? _master.y : y;
}
public String getA() {
return a == null ? _master.a : a;
}
@Override
public void setupMaster(GeometryRow row) {
_master = (PolyLineTo) row;
}
@Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return;
throw new POIXMLException("Polyline support not implemented");
}
}

View File

@ -0,0 +1,127 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class RelCubBezTo implements GeometryRow {
RelCubBezTo _master = null;
// The x-coordinate of the ending vertex of a cubic Bézier curve relative to the width of the shape.
Double x = null;
// The y-coordinate of the ending vertex of a cubic Bézier curve relative to the height of the shape.
Double y = null;
// The x-coordinate of the 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.
Double a = null;
// The y-coordinate of a curves beginning control point relative to the shapes 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.
Double c = null;
// The y-coordinate of a curve's ending control point relative to the shapes height.
Double d = null;
Boolean deleted = null;
// TODO: support formulas
public RelCubBezTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel();
for (CellType cell: row.getCellArray()) {
String cellName = cell.getN();
if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("B")) {
b = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("C")) {
c = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("D")) {
d = XDGFCell.parseDoubleValue(cell);
} else {
throw new POIXMLException("Invalid cell '" + cellName + "' in RelCubBezTo row");
}
}
}
public boolean getDel() {
if (deleted != null)
return deleted;
if (_master != null)
return _master.getDel();
return false;
}
public Double getX() {
return x == null ? _master.x : x;
}
public Double getY() {
return y == null ? _master.y : y;
}
public Double getA() {
return a == null ? _master.a : a;
}
public Double getB() {
return b == null ? _master.b : b;
}
public Double getC() {
return c == null ? _master.c : c;
}
public Double getD() {
return d == null ? _master.d : d;
}
@Override
public void setupMaster(GeometryRow row) {
_master = (RelCubBezTo) row;
}
@Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return;
double w = parent.getWidth();
double h = parent.getHeight();
path.curveTo(getA()*w, getB()*h, getC()*w, getD()*h, getX()*w, getY()*h);
}
}

View File

@ -0,0 +1,141 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class RelEllipticalArcTo implements GeometryRow {
RelEllipticalArcTo _master = null;
// The x-coordinate of the ending vertex on an arc relative to the width of
// the shape.
Double x = null;
// The y-coordinate of the ending vertex on an arc relative to the height of
// the shape.
Double y = null;
// The x-coordinate of the arc's control point relative to the shapes
// width; a point on the arc.
Double a = null;
// The y-coordinate of an arc's control point relative to the shapes width.
Double b = null;
// The angle of an arc's major axis relative to the x-axis of its parent.
Double c = null;
// The ratio of an arc's major axis to its minor axis. Despite the usual
// meaning of these words, the "major" axis does not have to be greater than
// the "minor" axis, so this ratio does not have to be greater than 1.
Double d = null;
Boolean deleted = null;
// TODO: support formulas
public RelEllipticalArcTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel();
for (CellType cell: row.getCellArray()) {
String cellName = cell.getN();
if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("B")) {
b = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("C")) {
c = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("D")) {
d = XDGFCell.parseDoubleValue(cell);
} else {
throw new POIXMLException("Invalid cell '" + cellName + "' in RelEllipticalArcTo row");
}
}
}
public boolean getDel() {
if (deleted != null)
return deleted;
if (_master != null)
return _master.getDel();
return false;
}
public Double getX() {
return x == null ? _master.x : x;
}
public Double getY() {
return y == null ? _master.y : y;
}
public Double getA() {
return a == null ? _master.a : a;
}
public Double getB() {
return b == null ? _master.b : b;
}
public Double getC() {
return c == null ? _master.c : c;
}
public Double getD() {
return d == null ? _master.d : d;
}
@Override
public void setupMaster(GeometryRow row) {
_master = (RelEllipticalArcTo) row;
}
@Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return;
double w = parent.getWidth();
double h = parent.getHeight();
// intentionally shadowing variables here
double x = getX()*w;
double y = getY()*h;
double a = getA()*w;
double b = getB()*h;
double c = getC();
double d = getD();
EllipticalArcTo.createEllipticalArc(x, y, a, b, c, d, path);
}
}

View File

@ -0,0 +1,90 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
/**
* Contains x-and y-coordinates of the ending vertex of a straight line segment
* relative to a shapes width and height.
*/
public class RelLineTo implements GeometryRow {
RelLineTo _master = null;
Double x = null;
Double y = null;
Boolean deleted = null;
// TODO: support formulas
public RelLineTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel();
for (CellType cell: row.getCellArray()) {
String cellName = cell.getN();
if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell);
} else {
throw new POIXMLException("Invalid cell '" + cellName + "' in RelLineTo row");
}
}
}
public boolean getDel() {
if (deleted != null)
return deleted;
if (_master != null)
return _master.getDel();
return false;
}
public Double getX() {
return x == null ? _master.x : x;
}
public Double getY() {
return y == null ? _master.y : y;
}
@Override
public void setupMaster(GeometryRow row) {
_master = (RelLineTo) row;
}
@Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return;
path.lineTo(getX()*parent.getWidth(),
getY()*parent.getHeight());
}
}

View File

@ -0,0 +1,86 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
public class RelMoveTo implements GeometryRow {
RelMoveTo _master = null;
Double x = null;
Double y = null;
Boolean deleted = null;
// TODO: support formulas
public RelMoveTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel();
for (CellType cell: row.getCellArray()) {
String cellName = cell.getN();
if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell);
} else {
throw new POIXMLException("Invalid cell '" + cellName + "' in RelMoveTo row");
}
}
}
public boolean getDel() {
if (deleted != null)
return deleted;
if (_master != null)
return _master.getDel();
return false;
}
public Double getX() {
return x == null ? _master.x : x;
}
public Double getY() {
return y == null ? _master.y : y;
}
@Override
public void setupMaster(GeometryRow row) {
_master = (RelMoveTo) row;
}
@Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return;
path.moveTo(getX()*parent.getWidth(),
getY()*parent.getHeight());
}
}

View File

@ -0,0 +1,114 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
/**
* Contains the x- and y-coordinates of the endpoint of a quadratic Bézier curve
* relative to the shapes width and height and the x- and y-coordinates of the
* control point of the curve relative shapes width and height.
*/
public class RelQuadBezTo implements GeometryRow {
RelQuadBezTo _master = null;
// The x-coordinate of the ending vertex of a quadratic Bézier curve relative to the width of the shape.
Double x = null;
// The y-coordinate of the ending vertex of a quadratic Bézier curve relative to the height of the shape.
Double y = null;
// The x-coordinate of the 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.
Double a = null;
// The y-coordinate of a curves control point relative to the shapes height.
Double b = null;
Boolean deleted = null;
// TODO: support formulas
public RelQuadBezTo(RowType row) {
if (row.isSetDel()) deleted = row.getDel();
for (CellType cell: row.getCellArray()) {
String cellName = cell.getN();
if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("B")) {
b = XDGFCell.parseDoubleValue(cell);
} else {
throw new POIXMLException("Invalid cell '" + cellName + "' in RelQuadBezTo row");
}
}
}
public boolean getDel() {
if (deleted != null)
return deleted;
if (_master != null)
return _master.getDel();
return false;
}
public Double getX() {
return x == null ? _master.x : x;
}
public Double getY() {
return y == null ? _master.y : y;
}
public Double getA() {
return a == null ? _master.a : a;
}
public Double getB() {
return b == null ? _master.b : b;
}
@Override
public void setupMaster(GeometryRow row) {
_master = (RelQuadBezTo) row;
}
@Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
if (getDel()) return;
double w = parent.getWidth();
double h = parent.getHeight();
path.quadTo(getA()*w, getB()*h, getX()*w, getY()*h);
}
}

View File

@ -0,0 +1,102 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
/**
* Contains x- and y-coordinates for a spline's control point and a spline's knot.
*/
public class SplineKnot implements GeometryRow {
SplineKnot _master = null;
// The x-coordinate of a control point.
Double x = null;
// The y-coordinate of a control point.
Double y = null;
// One of the spline's knots (other than the last one or the first two).
Double a = null;
Boolean deleted = null;
// TODO: support formulas
public SplineKnot(RowType row) {
if (row.isSetDel()) deleted = row.getDel();
for (CellType cell: row.getCellArray()) {
String cellName = cell.getN();
if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell);
} else {
throw new POIXMLException("Invalid cell '" + cellName + "' in SplineKnot row");
}
}
}
public boolean getDel() {
if (deleted != null)
return deleted;
if (_master != null)
return _master.getDel();
return false;
}
public Double getX() {
return x == null ? _master.x : x;
}
public Double getY() {
return y == null ? _master.y : y;
}
public Double getA() {
return a == null ? _master.a : a;
}
@Override
public void setupMaster(GeometryRow row) {
_master = (SplineKnot) row;
}
@Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
throw new POIXMLException("Error: Use SplineRenderer!");
}
@Override
public String toString() {
return "{SplineKnot x=" + getX() + " y=" + getY() + " a=" + getA() + "}";
}
}

View File

@ -0,0 +1,132 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section.geometry;
import org.apache.poi.POIXMLException;
import org.apache.poi.xdgf.usermodel.XDGFCell;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.microsoft.schemas.office.visio.x2012.main.RowType;
/**
* Contains x- and y-coordinates for a spline's second control point, its second
* knot, its first knot, the last knot, and the degree of the spline.
*/
public class SplineStart implements GeometryRow {
SplineStart _master = null;
// The x-coordinate of a spline's second control point.
Double x = null;
// The y-coordinate of a spline's second control point.
Double y = null;
// The second knot of the spline.
Double a = null;
// The first knot of a spline.
Double b = null;
// The last knot of a spline.
Double c = null;
// The degree of a spline (an integer from 1 to 25).
Integer d = null;
Boolean deleted = null;
// TODO: support formulas
public SplineStart(RowType row) {
if (row.isSetDel()) deleted = row.getDel();
for (CellType cell: row.getCellArray()) {
String cellName = cell.getN();
if (cellName.equals("X")) {
x = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("Y")) {
y = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("A")) {
a = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("B")) {
b = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("C")) {
c = XDGFCell.parseDoubleValue(cell);
} else if (cellName.equals("D")) {
d = XDGFCell.parseIntegerValue(cell);
} else {
throw new POIXMLException("Invalid cell '" + cellName + "' in SplineStart row");
}
}
}
public boolean getDel() {
if (deleted != null)
return deleted;
if (_master != null)
return _master.getDel();
return false;
}
public Double getX() {
return x == null ? _master.x : x;
}
public Double getY() {
return y == null ? _master.y : y;
}
public Double getA() {
return a == null ? _master.a : a;
}
public Double getB() {
return b == null ? _master.b : b;
}
public Double getC() {
return c == null ? _master.c : c;
}
public Integer getD() {
return d == null ? _master.d : d;
}
@Override
public void setupMaster(GeometryRow row) {
_master = (SplineStart) row;
}
@Override
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
throw new POIXMLException("Error: Use SplineRenderer!");
}
@Override
public String toString() {
return "{SplineStart x=" + getX() + " y=" + getY() +
" a=" + getA() + " b=" + getB() +
" c=" + getC() + " d=" + getD() +
"}";
}
}

View File

@ -0,0 +1,69 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.shape;
import org.apache.poi.xdgf.usermodel.XDGFShape;
/**
* This acceptor only allows traversal to shapes that have useful data
* associated with them, and tries to elide details that aren't useful
* when analyzing the content of a document.
*
* Useful is subjective of course, and is defined as any of:
*
* - Has non-empty text
* - Is a 1d shape, such as a line
* - User specified shapes
* - The outline of stencil objects
* - TODO
*/
public class ShapeDataAcceptor implements ShapeVisitorAcceptor {
@Override
public boolean accept(XDGFShape shape) {
if (shape.isDeleted())
return false;
// text is interesting
if (shape.hasText() && shape.getTextAsString().length() != 0)
return true;
// 1d shapes are interesting, they create connections
if (shape.isShape1D())
return true;
// User specified shapes are interesting
if (!shape.hasMaster() && !shape.hasMasterShape())
return true;
if (shape.hasMaster() && !shape.hasMasterShape())
return true;
// include stencil content, but try to elide stencil interiors
//if (shape.getXmlObject().isSetMaster())
// return true;
if (shape.hasMasterShape() && shape.getMasterShape().isTopmost())
return true;
return false;
}
}

View File

@ -0,0 +1,70 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.shape;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.geom.Path2D;
import org.apache.poi.xdgf.usermodel.XDGFShape;
public class ShapeDebuggerRenderer extends ShapeRenderer {
ShapeVisitorAcceptor _debugAcceptor = null;
public ShapeDebuggerRenderer() {
super();
}
public ShapeDebuggerRenderer(Graphics2D g) {
super(g);
}
public void setDebugAcceptor(ShapeVisitorAcceptor acceptor) {
_debugAcceptor = acceptor;
}
@Override
protected Path2D drawPath(XDGFShape shape){
Path2D path = super.drawPath(shape);
if (_debugAcceptor == null || _debugAcceptor.accept(shape)) {
// show numbers to associate shapes with ids.. doesn't always work
Font f = _graphics.getFont();
_graphics.scale(1, -1);
_graphics.setFont(f.deriveFont(0.05F));
String shapeId = "" + shape.getID();
float shapeOffset = -0.1F;
if (shape.hasMasterShape()) {
shapeId += " MS:" + shape.getMasterShape().getID();
shapeOffset -= 0.15F;
}
_graphics.drawString(shapeId, shapeOffset, 0);
_graphics.setFont(f);
_graphics.scale(1, -1);
}
return path;
}
}

View File

@ -0,0 +1,93 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.shape;
import java.awt.BasicStroke;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import org.apache.poi.xdgf.usermodel.XDGFText;
/**
* To use this to render only particular shapes, override it and provide an
* appropriate implementation of getAcceptor() or accept()
*/
public class ShapeRenderer extends ShapeVisitor {
protected Graphics2D _graphics;
public ShapeRenderer() {
_graphics = null;
}
public ShapeRenderer(Graphics2D g) {
_graphics = g;
}
public void setGraphics(Graphics2D g) {
_graphics = g;
}
@Override
public void visit(XDGFShape shape, AffineTransform globalTransform, int level) {
AffineTransform savedTr = _graphics.getTransform();
_graphics.transform(globalTransform);
drawPath(shape);
drawText(shape);
// we're done, undo the transforms
_graphics.setTransform(savedTr);
}
protected Path2D drawPath(XDGFShape shape) {
Path2D.Double path = shape.getPath();
if (path != null) {
// setup the stroke for this line
_graphics.setColor(shape.getLineColor());
_graphics.setStroke(shape.getStroke());
_graphics.draw(path);
}
return path;
}
protected void drawText(XDGFShape shape) {
XDGFText text = shape.getText();
if (text != null) {
if (text.getTextContent().equals("Header"))
text.getTextBounds();
Font oldFont = _graphics.getFont();
_graphics.setFont(oldFont.deriveFont(shape.getFontSize().floatValue()));
_graphics.setColor(shape.getFontColor());
text.draw(_graphics);
_graphics.setFont(oldFont);
}
}
}

View File

@ -0,0 +1,68 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.shape;
import java.awt.geom.AffineTransform;
import org.apache.poi.xdgf.usermodel.XDGFShape;
/**
* Used to iterate through shapes
*
* To change the behavior of a particular visitor, you can override either
* accept() or getAcceptor() [preferred]
*
* If accept() or visit() throw StopVisitingThisBranch, the iteration will
* not visit subshapes of the shape.
*/
public abstract class ShapeVisitor{
ShapeVisitorAcceptor _acceptor;
public ShapeVisitor() {
_acceptor = getAcceptor();
}
// is only called on construction of the visitor, allows
// mixing visitors and acceptors
public ShapeVisitorAcceptor getAcceptor() {
return new ShapeVisitorAcceptor() {
@Override
public boolean accept(XDGFShape shape) {
return !shape.isDeleted();
}
};
}
public void setAcceptor(ShapeVisitorAcceptor acceptor) {
_acceptor = acceptor;
}
public boolean accept(XDGFShape shape) {
return _acceptor.accept(shape);
}
/**
* @param shape Current shape
* @param globalTransform A transform that can convert the shapes points to global coordinates
* @param level Level in the tree (0 is topmost, 1 is next level...
*/
public abstract void visit(XDGFShape shape, AffineTransform globalTransform, int level);
}

View File

@ -0,0 +1,26 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.shape;
import org.apache.poi.xdgf.usermodel.XDGFShape;
public interface ShapeVisitorAcceptor {
public boolean accept(XDGFShape shape);
}

View File

@ -0,0 +1,24 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.shape.exceptions;
public class StopVisiting extends RuntimeException {
private static final long serialVersionUID = -4651207777092840750L;
}

View File

@ -0,0 +1,24 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.shape.exceptions;
public class StopVisitingThisBranch extends RuntimeException {
private static final long serialVersionUID = 5262319077534717862L;
}

View File

@ -0,0 +1,84 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.util;
import java.awt.geom.AffineTransform;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import org.apache.poi.xdgf.usermodel.XDGFPage;
import org.apache.poi.xdgf.usermodel.XDGFShape;
import org.apache.poi.xdgf.usermodel.XmlVisioDocument;
import org.apache.poi.xdgf.usermodel.shape.ShapeVisitor;
public class HierarchyPrinter {
public static void printHierarchy(XDGFPage page, File outDir) throws FileNotFoundException {
File pageFile = new File(outDir, "page" + page.getPageNumber() + "-" + Util.sanitizeFilename(page.getName()) + ".txt");
OutputStream os = new FileOutputStream(pageFile);
PrintStream pos = new PrintStream(os);
printHierarchy(page, pos);
pos.close();
}
public static void printHierarchy(XDGFPage page, final PrintStream os) {
page.getContent().visitShapes(new ShapeVisitor() {
@Override
public void visit(XDGFShape shape, AffineTransform globalTransform, int level) {
for (int i = 0; i < level; i++) {
os.append(" ");
}
// TODO: write text?
os.println(shape.toString() + " [" + shape.getShapeType() + ", " + shape.getSymbolName() + "] " + shape.getMasterShape() + " " + shape.getTextAsString().trim());
}
});
}
public static void printHierarchy(XmlVisioDocument document, String outDirname) throws FileNotFoundException {
File outDir = new File(outDirname);
for (XDGFPage page: document.getPages()) {
printHierarchy(page, outDir);
}
}
public static void main(String [] args) throws Exception {
if (args.length != 2) {
System.err.println("Usage: in.vsdx outdir");
System.exit(1);
}
String inFilename = args[0];
String outDir = args[1];
XmlVisioDocument doc = new XmlVisioDocument(new FileInputStream(inFilename));
printHierarchy(doc, outDir);
}
}

View File

@ -0,0 +1,57 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.POIXMLException;
import org.apache.xmlbeans.XmlObject;
public class ObjectFactory<T, X extends XmlObject> {
Map<String, Constructor<? extends T>> _types = new HashMap<>();
public void put(String typeName, Class<? extends T> cls, Class<?>... varargs) throws NoSuchMethodException, SecurityException {
_types.put(typeName, cls.getDeclaredConstructor(varargs));
}
public T load(String name, Object... varargs) {
Constructor<? extends T> constructor = _types.get(name);
if (constructor == null) {
@SuppressWarnings("unchecked")
X xmlObject = (X) varargs[0];
String typeName = xmlObject.schemaType().getName().getLocalPart();
throw new POIXMLException("Invalid '" + typeName + "' name '" + name + "'");
}
try {
return constructor.newInstance(varargs);
} catch (InvocationTargetException e) {
throw new POIXMLException(e.getCause());
} catch (Exception e) {
throw new POIXMLException(e);
}
}
}

View File

@ -0,0 +1,37 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.util;
public class Util {
public static int countLines(String str) {
int lines = 1;
int pos = 0;
while ((pos = str.indexOf("\n", pos) + 1) != 0) {
lines++;
}
return lines;
}
// this probably isn't 100% correct, so don't use it in security-sensitive
// applications!
// from: http://www.rgagnon.com/javadetails/java-0662.html
public static String sanitizeFilename(String name) {
return name.replaceAll("[:\\\\/*\"?|<>]", "_");
}
}

View File

@ -0,0 +1,118 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.util;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.apache.poi.xdgf.geom.Dimension2dDouble;
import org.apache.poi.xdgf.usermodel.XDGFPage;
import org.apache.poi.xdgf.usermodel.XmlVisioDocument;
import org.apache.poi.xdgf.usermodel.shape.ShapeDebuggerRenderer;
import org.apache.poi.xdgf.usermodel.shape.ShapeRenderer;
public class VsdxToPng {
public static void renderToPng(XDGFPage page, String outFilename, double scale, ShapeRenderer renderer) throws IOException {
renderToPng(page, new File(outFilename), scale, renderer);
}
public static void renderToPngDir(XDGFPage page, File outDir, double scale, ShapeRenderer renderer) throws IOException {
File pageFile = new File(outDir, "page" + page.getPageNumber() + "-" + Util.sanitizeFilename(page.getName()) + ".png");
System.out.println("** Writing image to " + pageFile);
renderToPng(page, pageFile, scale, renderer);
}
public static void renderToPng(XDGFPage page, File outFile, double scale, ShapeRenderer renderer) throws IOException {
Dimension2dDouble sz = page.getPageSize();
int width = (int)(scale * sz.getWidth());
int height = (int)(scale * sz.getHeight());
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
final Graphics2D graphics = img.createGraphics();
// default rendering options
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
graphics.setColor(Color.black);
graphics.setBackground(Color.white);
graphics.clearRect(0, 0, width, height);
// Visio's coordinate system is flipped, so flip the image vertically
graphics.translate(0, img.getHeight());
graphics.scale(scale, -scale);
// toplevel shapes only
renderer.setGraphics(graphics);
page.getContent().visitShapes(renderer);
graphics.dispose();
FileOutputStream out = new FileOutputStream(outFile);
ImageIO.write(img, "png", out);
out.close();
}
public static void renderToPng(XmlVisioDocument document, String outDirname, double scale, ShapeRenderer renderer) throws IOException {
File outDir = new File(outDirname);
for (XDGFPage page: document.getPages()) {
renderToPngDir(page, outDir, scale, renderer);
}
}
public static void main(String [] args) throws Exception {
if (args.length > 2) {
System.err.println("Usage: [--debug] in.vsdx outdir");
System.exit(1);
}
ShapeRenderer renderer = new ShapeRenderer();
String inFilename = args[0];
String pngDir = args[1];
if (args[0].equals("--debug")) {
inFilename = args[1];
pngDir = args[2];
renderer = new ShapeDebuggerRenderer();
}
XmlVisioDocument doc = new XmlVisioDocument(new FileInputStream(inFilename));
renderToPng(doc, pngDir, 2000/11.0, renderer);
}
}

View File

@ -0,0 +1,33 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.xml;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.xdgf.usermodel.XDGFDocument;
public class XDGFXMLDocumentPart extends POIXMLDocumentPart {
protected XDGFDocument _document;
public XDGFXMLDocumentPart(PackagePart part, PackageRelationship rel, XDGFDocument document) {
super(part, rel);
_document = document;
}
}

View File

@ -0,0 +1,159 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xdgf.usermodel.section;
import java.util.Iterator;
import java.util.SortedMap;
import java.util.TreeMap;
import org.junit.Assert;
import org.junit.Test;
public class CombinedIteratorTest {
void testIteration(CombinedIterable<String> iterable, String... expected) {
Iterator<String> iter = iterable.iterator();
for (int i = 0; i < expected.length; i++) {
Assert.assertEquals(true, iter.hasNext());
Assert.assertEquals(expected[i], iter.next());
}
Assert.assertEquals(false, iter.hasNext());
}
@Test
public void testNullMaster() {
SortedMap<Long, String> base = new TreeMap<>();
base.put(1L, "B1");
base.put(2L, "B2");
base.put(3L, "B3");
testIteration(new CombinedIterable<>(base, null),
"B1", "B2", "B3");
}
@Test
public void testNoMatchesBaseFirst() {
SortedMap<Long, String> base = new TreeMap<>();
base.put(1L, "B1");
base.put(2L, "B2");
base.put(3L, "B3");
SortedMap<Long, String> master = new TreeMap<>();
master.put(4L, "M4");
master.put(5L, "M5");
master.put(6L, "M6");
testIteration(new CombinedIterable<>(base, master),
"B1", "B2", "B3", "M4", "M5", "M6");
}
@Test
public void testNoMatchesMasterFirst() {
SortedMap<Long, String> base = new TreeMap<>();
base.put(4L, "B4");
base.put(5L, "B5");
base.put(6L, "B6");
SortedMap<Long, String> master = new TreeMap<>();
master.put(1L, "M1");
master.put(2L, "M2");
master.put(3L, "M3");
testIteration(new CombinedIterable<>(base, master),
"M1", "M2", "M3", "B4", "B5", "B6");
}
@Test
public void testInterleaved1() {
SortedMap<Long, String> base = new TreeMap<>();
base.put(1L, "B1");
base.put(3L, "B3");
base.put(5L, "B5");
SortedMap<Long, String> master = new TreeMap<>();
master.put(2L, "M2");
master.put(4L, "M4");
master.put(6L, "M6");
testIteration(new CombinedIterable<>(base, master),
"B1", "M2", "B3", "M4", "B5", "M6");
}
@Test
public void testInterleaved2() {
SortedMap<Long, String> base = new TreeMap<>();
base.put(1L, "B1");
base.put(2L, "B2");
base.put(5L, "B5");
base.put(6L, "B6");
SortedMap<Long, String> master = new TreeMap<>();
master.put(3L, "M3");
master.put(4L, "M4");
master.put(7L, "M7");
master.put(8L, "M8");
testIteration(new CombinedIterable<>(base, master),
"B1", "B2", "M3", "M4", "B5", "B6", "M7", "M8");
}
@Test
public void testAllMatching() {
SortedMap<Long, String> base = new TreeMap<>();
base.put(1L, "B1");
base.put(2L, "B2");
base.put(3L, "B3");
SortedMap<Long, String> master = new TreeMap<>();
master.put(1L, "M1");
master.put(2L, "M2");
master.put(3L, "M3");
testIteration(new CombinedIterable<>(base, master),
"B1", "B2", "B3");
}
@Test
public void testAllMatching2() {
SortedMap<Long, String> base = new TreeMap<>();
base.put(1L, "B1");
base.put(2L, "B2");
base.put(3L, "B3");
SortedMap<Long, String> master = new TreeMap<>();
master.put(1L, "M1");
master.put(2L, "M2");
master.put(3L, "M3");
master.put(4L, "M4");
testIteration(new CombinedIterable<>(base, master),
"B1", "B2", "B3", "M4");
}
}

View File

@ -0,0 +1,45 @@
#!/bin/bash -e
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# basename it
FILENAME="$1"
BASENAME="${FILENAME##*/}"
OUTDIR="${BASENAME%.*}"
if [ ! -f "$FILENAME" ]; then
echo "File $FILENAME does not exist"
exit 1
fi
# if dir exists, fail
if [ -d "$OUTDIR" ]; then
echo "Directory '$OUTDIR' already exists!"
exit 1
fi
mkdir "$OUTDIR"
unzip -d "$OUTDIR" "$FILENAME"
pushd "$OUTDIR"
find . -type f \( -iname "*.xml" -or -iname "*.rels" \) -exec python -c "import os, sys, xml.dom.minidom
with open('{}', 'r') as fp:
s = fp.read()
with open('{}.bak', 'w') as fp:
fp.write(xml.dom.minidom.parseString(s).toprettyxml().encode('utf-8'))
os.rename('{}.bak', '{}')" \;