mirror of https://github.com/apache/poi.git
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:
parent
2afe977622
commit
8a41cf7c40
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 + "]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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 element’s formula. This attribute can contain one of the following strings:
|
||||||
|
* - ‘(some formula)’ if the formula exists locally
|
||||||
|
* - No Formula if the formula is locally deleted or blocked
|
||||||
|
* - Inh if the formula is inherited.
|
||||||
|
*/
|
||||||
|
public String getFormula() {
|
||||||
|
return _cell.getF();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Indicates that the formula evaluates to an error. The value of E is the
|
||||||
|
* current value (an error message string); the value of the V attribute is
|
||||||
|
* the last valid value.
|
||||||
|
*/
|
||||||
|
public String getError() {
|
||||||
|
return _cell.getE();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 curve’s beginning control point relative to the shape’s width; a point on the arc. The control point is best located between the beginning and ending vertices of the arc.
|
||||||
|
Double a = null;
|
||||||
|
|
||||||
|
// The y-coordinate of a curve’s beginning control point relative to the shape’s height.
|
||||||
|
Double b = null;
|
||||||
|
|
||||||
|
// The x-coordinate of the curve’s ending control point relative to the shape’s width; a point on the arc. The control point is best located between the beginning control point and ending vertices of the arc.
|
||||||
|
Double c = null;
|
||||||
|
|
||||||
|
// The y-coordinate of a curve's ending control point relative to the shape’s height.
|
||||||
|
Double d = null;
|
||||||
|
|
||||||
|
Boolean deleted = null;
|
||||||
|
|
||||||
|
// TODO: support formulas
|
||||||
|
|
||||||
|
public RelCubBezTo(RowType row) {
|
||||||
|
|
||||||
|
if (row.isSetDel()) deleted = row.getDel();
|
||||||
|
|
||||||
|
for (CellType cell: row.getCellArray()) {
|
||||||
|
String cellName = cell.getN();
|
||||||
|
|
||||||
|
if (cellName.equals("X")) {
|
||||||
|
x = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else if (cellName.equals("Y")) {
|
||||||
|
y = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else if (cellName.equals("A")) {
|
||||||
|
a = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else if (cellName.equals("B")) {
|
||||||
|
b = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else if (cellName.equals("C")) {
|
||||||
|
c = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else if (cellName.equals("D")) {
|
||||||
|
d = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else {
|
||||||
|
throw new POIXMLException("Invalid cell '" + cellName + "' in RelCubBezTo row");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getDel() {
|
||||||
|
if (deleted != null)
|
||||||
|
return deleted;
|
||||||
|
|
||||||
|
if (_master != null)
|
||||||
|
return _master.getDel();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getX() {
|
||||||
|
return x == null ? _master.x : x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getY() {
|
||||||
|
return y == null ? _master.y : y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getA() {
|
||||||
|
return a == null ? _master.a : a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getB() {
|
||||||
|
return b == null ? _master.b : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getC() {
|
||||||
|
return c == null ? _master.c : c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getD() {
|
||||||
|
return d == null ? _master.d : d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setupMaster(GeometryRow row) {
|
||||||
|
_master = (RelCubBezTo) row;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
|
||||||
|
|
||||||
|
if (getDel()) return;
|
||||||
|
|
||||||
|
double w = parent.getWidth();
|
||||||
|
double h = parent.getHeight();
|
||||||
|
|
||||||
|
path.curveTo(getA()*w, getB()*h, getC()*w, getD()*h, getX()*w, getY()*h);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 shape’s
|
||||||
|
// width; a point on the arc.
|
||||||
|
Double a = null;
|
||||||
|
|
||||||
|
// The y-coordinate of an arc's control point relative to the shape’s width.
|
||||||
|
Double b = null;
|
||||||
|
|
||||||
|
// The angle of an arc's major axis relative to the x-axis of its parent.
|
||||||
|
Double c = null;
|
||||||
|
|
||||||
|
// The ratio of an arc's major axis to its minor axis. Despite the usual
|
||||||
|
// meaning of these words, the "major" axis does not have to be greater than
|
||||||
|
// the "minor" axis, so this ratio does not have to be greater than 1.
|
||||||
|
Double d = null;
|
||||||
|
|
||||||
|
Boolean deleted = null;
|
||||||
|
|
||||||
|
// TODO: support formulas
|
||||||
|
|
||||||
|
public RelEllipticalArcTo(RowType row) {
|
||||||
|
|
||||||
|
if (row.isSetDel()) deleted = row.getDel();
|
||||||
|
|
||||||
|
for (CellType cell: row.getCellArray()) {
|
||||||
|
String cellName = cell.getN();
|
||||||
|
|
||||||
|
if (cellName.equals("X")) {
|
||||||
|
x = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else if (cellName.equals("Y")) {
|
||||||
|
y = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else if (cellName.equals("A")) {
|
||||||
|
a = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else if (cellName.equals("B")) {
|
||||||
|
b = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else if (cellName.equals("C")) {
|
||||||
|
c = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else if (cellName.equals("D")) {
|
||||||
|
d = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else {
|
||||||
|
throw new POIXMLException("Invalid cell '" + cellName + "' in RelEllipticalArcTo row");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getDel() {
|
||||||
|
if (deleted != null)
|
||||||
|
return deleted;
|
||||||
|
|
||||||
|
if (_master != null)
|
||||||
|
return _master.getDel();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getX() {
|
||||||
|
return x == null ? _master.x : x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getY() {
|
||||||
|
return y == null ? _master.y : y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getA() {
|
||||||
|
return a == null ? _master.a : a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getB() {
|
||||||
|
return b == null ? _master.b : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getC() {
|
||||||
|
return c == null ? _master.c : c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getD() {
|
||||||
|
return d == null ? _master.d : d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setupMaster(GeometryRow row) {
|
||||||
|
_master = (RelEllipticalArcTo) row;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
|
||||||
|
|
||||||
|
if (getDel()) return;
|
||||||
|
|
||||||
|
double w = parent.getWidth();
|
||||||
|
double h = parent.getHeight();
|
||||||
|
|
||||||
|
// intentionally shadowing variables here
|
||||||
|
double x = getX()*w;
|
||||||
|
double y = getY()*h;
|
||||||
|
double a = getA()*w;
|
||||||
|
double b = getB()*h;
|
||||||
|
double c = getC();
|
||||||
|
double d = getD();
|
||||||
|
|
||||||
|
EllipticalArcTo.createEllipticalArc(x, y, a, b, c, d, path);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 shape’s width and height.
|
||||||
|
*/
|
||||||
|
public class RelLineTo implements GeometryRow {
|
||||||
|
|
||||||
|
RelLineTo _master = null;
|
||||||
|
|
||||||
|
Double x = null;
|
||||||
|
Double y = null;
|
||||||
|
|
||||||
|
Boolean deleted = null;
|
||||||
|
|
||||||
|
// TODO: support formulas
|
||||||
|
|
||||||
|
public RelLineTo(RowType row) {
|
||||||
|
|
||||||
|
if (row.isSetDel()) deleted = row.getDel();
|
||||||
|
|
||||||
|
for (CellType cell: row.getCellArray()) {
|
||||||
|
String cellName = cell.getN();
|
||||||
|
|
||||||
|
if (cellName.equals("X")) {
|
||||||
|
x = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else if (cellName.equals("Y")) {
|
||||||
|
y = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else {
|
||||||
|
throw new POIXMLException("Invalid cell '" + cellName + "' in RelLineTo row");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getDel() {
|
||||||
|
if (deleted != null)
|
||||||
|
return deleted;
|
||||||
|
|
||||||
|
if (_master != null)
|
||||||
|
return _master.getDel();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getX() {
|
||||||
|
return x == null ? _master.x : x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getY() {
|
||||||
|
return y == null ? _master.y : y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setupMaster(GeometryRow row) {
|
||||||
|
_master = (RelLineTo) row;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
|
||||||
|
|
||||||
|
if (getDel()) return;
|
||||||
|
|
||||||
|
path.lineTo(getX()*parent.getWidth(),
|
||||||
|
getY()*parent.getHeight());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 shape’s width and height and the x- and y-coordinates of the
|
||||||
|
* control point of the curve relative shape’s width and height.
|
||||||
|
*/
|
||||||
|
public class RelQuadBezTo implements GeometryRow {
|
||||||
|
|
||||||
|
RelQuadBezTo _master = null;
|
||||||
|
|
||||||
|
// The x-coordinate of the ending vertex of a quadratic Bézier curve relative to the width of the shape.
|
||||||
|
Double x = null;
|
||||||
|
|
||||||
|
// The y-coordinate of the ending vertex of a quadratic Bézier curve relative to the height of the shape.
|
||||||
|
Double y = null;
|
||||||
|
|
||||||
|
// The x-coordinate of the curve’s control point relative to the shape’s width; a point on the arc. The control point is best located about halfway between the beginning and ending vertices of the arc.
|
||||||
|
Double a = null;
|
||||||
|
|
||||||
|
// The y-coordinate of a curve’s control point relative to the shape’s height.
|
||||||
|
Double b = null;
|
||||||
|
|
||||||
|
Boolean deleted = null;
|
||||||
|
|
||||||
|
// TODO: support formulas
|
||||||
|
|
||||||
|
public RelQuadBezTo(RowType row) {
|
||||||
|
|
||||||
|
if (row.isSetDel()) deleted = row.getDel();
|
||||||
|
|
||||||
|
for (CellType cell: row.getCellArray()) {
|
||||||
|
String cellName = cell.getN();
|
||||||
|
|
||||||
|
if (cellName.equals("X")) {
|
||||||
|
x = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else if (cellName.equals("Y")) {
|
||||||
|
y = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else if (cellName.equals("A")) {
|
||||||
|
a = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else if (cellName.equals("B")) {
|
||||||
|
b = XDGFCell.parseDoubleValue(cell);
|
||||||
|
} else {
|
||||||
|
throw new POIXMLException("Invalid cell '" + cellName + "' in RelQuadBezTo row");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getDel() {
|
||||||
|
if (deleted != null)
|
||||||
|
return deleted;
|
||||||
|
|
||||||
|
if (_master != null)
|
||||||
|
return _master.getDel();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getX() {
|
||||||
|
return x == null ? _master.x : x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getY() {
|
||||||
|
return y == null ? _master.y : y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getA() {
|
||||||
|
return a == null ? _master.a : a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getB() {
|
||||||
|
return b == null ? _master.b : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setupMaster(GeometryRow row) {
|
||||||
|
_master = (RelQuadBezTo) row;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToPath(java.awt.geom.Path2D.Double path, XDGFShape parent) {
|
||||||
|
|
||||||
|
if (getDel()) return;
|
||||||
|
|
||||||
|
double w = parent.getWidth();
|
||||||
|
double h = parent.getHeight();
|
||||||
|
|
||||||
|
path.quadTo(getA()*w, getB()*h, getX()*w, getY()*h);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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() + "}";
|
||||||
|
}
|
||||||
|
}
|
|
@ -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() +
|
||||||
|
"}";
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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("[:\\\\/*\"?|<>]", "_");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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', '{}')" \;
|
Loading…
Reference in New Issue