From a3145d1d8e46d0917453d0598c22717c8b54569e Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Wed, 26 Oct 2011 10:10:05 +0000 Subject: [PATCH] support for preset shape geometries in xslf git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1189105 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/xslf/model/geom/AbsExpression.java | 41 ++ .../xslf/model/geom/AddDivideExpression.java | 45 ++ .../model/geom/AddSubtractExpression.java | 45 ++ .../poi/xslf/model/geom/AdjustValue.java | 45 ++ .../poi/xslf/model/geom/ArcTanExpression.java | 43 ++ .../poi/xslf/model/geom/ArcToCommand.java | 72 ++ .../poi/xslf/model/geom/ClosePathCommand.java | 37 + .../apache/poi/xslf/model/geom/Context.java | 72 ++ .../poi/xslf/model/geom/CosExpression.java | 43 ++ .../model/geom/CosineArcTanExpression.java | 45 ++ .../poi/xslf/model/geom/CurveToCommand.java | 52 ++ .../poi/xslf/model/geom/CustomGeometry.java | 61 ++ .../poi/xslf/model/geom/Expression.java | 31 + .../poi/xslf/model/geom/ExpressionParser.java | 69 ++ .../apache/poi/xslf/model/geom/Formula.java | 385 +++++++++++ .../org/apache/poi/xslf/model/geom/Guide.java | 58 ++ .../poi/xslf/model/geom/IAdjustableShape.java | 44 ++ .../poi/xslf/model/geom/IfElseExpression.java | 50 ++ .../poi/xslf/model/geom/LineToCommand.java | 44 ++ .../model/geom/LiteralValueExpression.java | 40 ++ .../poi/xslf/model/geom/MaxExpression.java | 43 ++ .../poi/xslf/model/geom/MinExpression.java | 43 ++ .../poi/xslf/model/geom/ModExpression.java | 49 ++ .../poi/xslf/model/geom/MoveToCommand.java | 44 ++ .../model/geom/MultiplyDivideExpression.java | 45 ++ .../org/apache/poi/xslf/model/geom/Path.java | 91 +++ .../poi/xslf/model/geom/PathCommand.java | 45 ++ .../poi/xslf/model/geom/PinExpression.java | 54 ++ .../poi/xslf/model/geom/PresetGeometries.java | 64 ++ .../poi/xslf/model/geom/QuadToCommand.java | 48 ++ .../xslf/model/geom/SinArcTanExpression.java | 51 ++ .../poi/xslf/model/geom/SinExpression.java | 49 ++ .../poi/xslf/model/geom/SqrtExpression.java | 46 ++ .../poi/xslf/model/geom/TanExpression.java | 50 ++ .../poi/xslf/usermodel/XSLFAutoShape.java | 40 +- .../xslf/usermodel/XSLFConnectorShape.java | 17 +- .../xslf/usermodel/XSLFPresetGeometry.java | 637 ------------------ .../poi/xslf/usermodel/XSLFSimpleShape.java | 74 +- .../poi/xslf/usermodel/XSLFTextShape.java | 9 +- .../poi/xslf/geom/TestFormulaParser.java | 40 ++ .../poi/xslf/geom/TestPresetGeometries.java | 39 ++ .../xslf/usermodel/presetShapeDefinitions.xml | 4 +- 42 files changed, 2195 insertions(+), 709 deletions(-) create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/AbsExpression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/AddDivideExpression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/AddSubtractExpression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/AdjustValue.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/ArcTanExpression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/ArcToCommand.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/ClosePathCommand.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/Context.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/CosExpression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/CosineArcTanExpression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/CurveToCommand.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/CustomGeometry.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/Expression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/ExpressionParser.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/Formula.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/Guide.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/IAdjustableShape.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/IfElseExpression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/LineToCommand.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/LiteralValueExpression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/MaxExpression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/MinExpression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/ModExpression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/MoveToCommand.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/MultiplyDivideExpression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/Path.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/PathCommand.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/PinExpression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/PresetGeometries.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/QuadToCommand.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/SinArcTanExpression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/SinExpression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/SqrtExpression.java create mode 100644 src/ooxml/java/org/apache/poi/xslf/model/geom/TanExpression.java delete mode 100644 src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPresetGeometry.java create mode 100644 src/ooxml/testcases/org/apache/poi/xslf/geom/TestFormulaParser.java create mode 100644 src/ooxml/testcases/org/apache/poi/xslf/geom/TestPresetGeometries.java diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/AbsExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/AbsExpression.java new file mode 100644 index 0000000000..5790e5383a --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/AbsExpression.java @@ -0,0 +1,41 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * Absolute Value Formula + * + * @author Yegor Kozlov + */ +public class AbsExpression implements Expression { + private String arg; + + AbsExpression(Matcher m){ + arg = m.group(1); + } + + public double evaluate(Context ctx){ + double val = ctx.getValue(arg); + return Math.abs(val); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/AddDivideExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/AddDivideExpression.java new file mode 100644 index 0000000000..7fe14e8b1d --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/AddDivideExpression.java @@ -0,0 +1,45 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * Add Divide Formula + * + * @author Yegor Kozlov + */ +public class AddDivideExpression implements Expression { + private String arg1, arg2, arg3; + + AddDivideExpression(Matcher m){ + arg1 = m.group(1); + arg2 = m.group(2); + arg3 = m.group(3); + } + + public double evaluate(Context ctx){ + double x = ctx.getValue(arg1); + double y = ctx.getValue(arg2); + double z = ctx.getValue(arg3); + return (x + y ) / z; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/AddSubtractExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/AddSubtractExpression.java new file mode 100644 index 0000000000..bd7e47e16d --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/AddSubtractExpression.java @@ -0,0 +1,45 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * Add Subtract Formula + * + * @author Yegor Kozlov + */ +public class AddSubtractExpression implements Expression { + private String arg1, arg2, arg3; + + AddSubtractExpression(Matcher m){ + arg1 = m.group(1); + arg2 = m.group(2); + arg3 = m.group(3); + } + + public double evaluate(Context ctx){ + double x = ctx.getValue(arg1); + double y = ctx.getValue(arg2); + double z = ctx.getValue(arg3); + return (x + y ) - z; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/AdjustValue.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/AdjustValue.java new file mode 100644 index 0000000000..8df1d6f875 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/AdjustValue.java @@ -0,0 +1,45 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuide; + +/** + * Represents a shape adjust values (see section 20.1.9.5 in the spec) + * + * @author Yegor Kozlov + */ +public class AdjustValue extends Guide { + + public AdjustValue(CTGeomGuide gd) { + super(gd.getName(), gd.getFmla()); + } + + @Override + public double evaluate(Context ctx){ + String name = getName(); + Guide adj = ctx.getAdjustValue(name); + if(adj != null) { + return adj.evaluate(ctx); + } + return super.evaluate(ctx); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/ArcTanExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/ArcTanExpression.java new file mode 100644 index 0000000000..252c0fc62c --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/ArcTanExpression.java @@ -0,0 +1,43 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * Date: 10/24/11 + * + * @author Yegor Kozlov + */ +public class ArcTanExpression implements Expression { + private String arg1, arg2; + + ArcTanExpression(Matcher m){ + arg1 = m.group(1); + arg2 = m.group(2); + } + + public double evaluate(Context ctx){ + double x = ctx.getValue(arg1); + double y = ctx.getValue(arg2); + return Math.atan(y / x); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/ArcToCommand.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/ArcToCommand.java new file mode 100644 index 0000000000..9b2e1bcf31 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/ArcToCommand.java @@ -0,0 +1,72 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DArcTo; + +import java.awt.geom.Arc2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; + +/** + * ArcTo command within a shape path in DrawingML: + * + * + * + * Where wr and wh are the height and width radiuses + * of the supposed circle being used to draw the arc. This gives the circle + * a total height of (2 * hR) and a total width of (2 * wR) + * + * stAng is the start angle and swAng is the swing angle + * + * @author Yegor Kozlov + */ +public class ArcToCommand implements PathCommand { + private String hr, wr, stAng, swAng; + + ArcToCommand(CTPath2DArcTo arc){ + hr = arc.getHR().toString(); + wr = arc.getWR().toString(); + stAng = arc.getStAng().toString(); + swAng = arc.getSwAng().toString(); + } + + public void execute(GeneralPath path, Context ctx){ + double rx = ctx.getValue(wr); + double ry = ctx.getValue(hr); + double start = ctx.getValue(stAng) / 60000; + double extent = ctx.getValue(swAng) / 60000; + Point2D pt = path.getCurrentPoint(); + double x0 = pt.getX() - rx - rx * Math.cos(Math.toRadians(start)); + double y0 = pt.getY() - ry - ry * Math.sin(Math.toRadians(start)); + + if(start == 180 && extent == 180) { + x0 -= rx*2; //YK: TODO revisit the code and get rid of this hack + } + + Arc2D arc = new Arc2D.Double( + x0, + y0, + 2 * rx, 2 * ry, + -start, -extent, // negate angles because DrawingML rotates counter-clockwise + Arc2D.OPEN); + path.append(arc, true); + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/ClosePathCommand.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/ClosePathCommand.java new file mode 100644 index 0000000000..b9a95404e1 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/ClosePathCommand.java @@ -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.xslf.model.geom; + +import java.awt.geom.GeneralPath; + +/** + * Date: 10/25/11 + * + * @author Yegor Kozlov + */ +public class ClosePathCommand implements PathCommand { + + ClosePathCommand(){ + } + + public void execute(GeneralPath path, Context ctx){ + path.closePath(); + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/Context.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/Context.java new file mode 100644 index 0000000000..230524cfde --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/Context.java @@ -0,0 +1,72 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.awt.geom.Rectangle2D; +import java.util.HashMap; +import java.util.Map; + +/** + * Date: 10/24/11 + * + * @author Yegor Kozlov + */ +public class Context { + Map _ctx = new HashMap(); + IAdjustableShape _props; + + public Context(CustomGeometry geom, IAdjustableShape props){ + _props = props; + for(Guide gd : geom.adjusts) evaluate(gd); + for(Guide gd : geom.guides) evaluate(gd); + } + + public Rectangle2D getShapeAnchor(){ + return _props.getAnchor(); + } + + public Guide getAdjustValue(String name){ + return _props.getAdjustValue(name); + } + + public double getValue(String key){ + if(key.matches("(\\+|-)?\\d+")){ + return Double.parseDouble(key); + } + + Formula builtIn = Formula.builtInFormulas.get(key); + if(builtIn != null){ + return builtIn.evaluate(this); + } + + if(!_ctx.containsKey(key)) { + throw new RuntimeException("undefined variable: " + key); + } + + return _ctx.get(key); + } + + public double evaluate(Formula fmla){ + double result = fmla.evaluate(this); + String key = fmla.getName(); + if(key != null) _ctx.put(key, result); + return result; + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/CosExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/CosExpression.java new file mode 100644 index 0000000000..47e38f162b --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/CosExpression.java @@ -0,0 +1,43 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * Date: 10/24/11 + * + * @author Yegor Kozlov + */ +public class CosExpression implements Expression { + private String arg1, arg2; + + CosExpression(Matcher m){ + arg1 = m.group(1); + arg2 = m.group(2); + } + + public double evaluate(Context ctx){ + double x = ctx.getValue(arg1); + double y = ctx.getValue(arg2)/ 60000; + return x * Math.cos(Math.toRadians(y)); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/CosineArcTanExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/CosineArcTanExpression.java new file mode 100644 index 0000000000..cb9928b223 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/CosineArcTanExpression.java @@ -0,0 +1,45 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * Date: 10/24/11 + * + * @author Yegor Kozlov + */ +public class CosineArcTanExpression implements Expression { + private String arg1, arg2, arg3; + + CosineArcTanExpression(Matcher m){ + arg1 = m.group(1); + arg2 = m.group(2); + arg3 = m.group(3); + } + + public double evaluate(Context ctx){ + double x = ctx.getValue(arg1); + double y = ctx.getValue(arg2); + double z = ctx.getValue(arg3); + return x*Math.cos(Math.atan(z / y)); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/CurveToCommand.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/CurveToCommand.java new file mode 100644 index 0000000000..dcfde7e18f --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/CurveToCommand.java @@ -0,0 +1,52 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import org.openxmlformats.schemas.drawingml.x2006.main.CTAdjPoint2D; + +import java.awt.geom.GeneralPath; + +/** + * Date: 10/25/11 + * + * @author Yegor Kozlov + */ +public class CurveToCommand implements PathCommand { + private String arg1, arg2, arg3, arg4, arg5, arg6; + + CurveToCommand(CTAdjPoint2D pt1, CTAdjPoint2D pt2, CTAdjPoint2D pt3){ + arg1 = pt1.getX().toString(); + arg2 = pt1.getY().toString(); + arg3 = pt2.getX().toString(); + arg4 = pt2.getY().toString(); + arg5 = pt3.getX().toString(); + arg6 = pt3.getY().toString(); + } + + public void execute(GeneralPath path, Context ctx){ + double x1 = ctx.getValue(arg1); + double y1 = ctx.getValue(arg2); + double x2 = ctx.getValue(arg3); + double y2 = ctx.getValue(arg4); + double x3 = ctx.getValue(arg5); + double y3 = ctx.getValue(arg6); + path.curveTo(x1, y1, x2, y2, x3, y3); + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/CustomGeometry.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/CustomGeometry.java new file mode 100644 index 0000000000..7507f55b21 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/CustomGeometry.java @@ -0,0 +1,61 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import org.openxmlformats.schemas.drawingml.x2006.main.*; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Definition of a custom geometric shape + * + * @author Yegor Kozlov + */ +public class CustomGeometry implements Iterable{ + List adjusts = new ArrayList(); + List guides = new ArrayList(); + List paths = new ArrayList(); + + public CustomGeometry(CTCustomGeometry2D geom){ + CTGeomGuideList avLst = geom.getAvLst(); + if(avLst != null) for(CTGeomGuide gd : avLst.getGdList()){ + adjusts.add(new AdjustValue(gd)); + } + + CTGeomGuideList gdLst = geom.getGdLst(); + if(gdLst != null) for(CTGeomGuide gd : gdLst.getGdList()){ + guides.add(new Guide(gd)); + } + + CTPath2DList pathLst = geom.getPathLst(); + if(pathLst != null) for(CTPath2D spPath : pathLst.getPathList()){ + paths.add(new Path(spPath)); + } + } + + + + public Iterator iterator() { + return paths.iterator(); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/Expression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/Expression.java new file mode 100644 index 0000000000..2b0f751f36 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/Expression.java @@ -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.xslf.model.geom; + +/** + * Date: 10/24/11 + * + * @author Yegor Kozlov + */ +public interface Expression { + + double evaluate(Context ctx); + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/ExpressionParser.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/ExpressionParser.java new file mode 100644 index 0000000000..699f995eab --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/ExpressionParser.java @@ -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.xslf.model.geom; + +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A simple regexp-based parser of shape guide formulas in DrawingML + * + * @author Yegor Kozlov + */ +public class ExpressionParser { + static final HashMap impls = new HashMap(); + static { + impls.put("\\*/ +([\\-\\w]+) +([\\-\\w]+) +([\\-\\w]+)", MultiplyDivideExpression.class); + impls.put("\\+- +([\\-\\w]+) +([\\-\\w]+) +([\\-\\w]+)( 0)?", AddSubtractExpression.class); + impls.put("\\+/ +([\\-\\w]+) +([\\-\\w]+) +([\\-\\w]+)", AddDivideExpression.class); + impls.put("\\?: +([\\-\\w]+) +([\\-\\w]+) +([\\-\\w]+)", IfElseExpression.class); + impls.put("val +([\\-\\w]+)", LiteralValueExpression.class); + impls.put("abs +([\\-\\w]+)", AbsExpression.class); + impls.put("sqrt +([\\-\\w]+)", SqrtExpression.class); + impls.put("max +([\\-\\w]+) +([\\-\\w]+)", MaxExpression.class); + impls.put("min +([\\-\\w]+) +([\\-\\w]+)", MinExpression.class); + impls.put("at2 +([\\-\\w]+) +([\\-\\w]+)", ArcTanExpression.class); + impls.put("sin +([\\-\\w]+) +([\\-\\w]+)", SinExpression.class); + impls.put("cos +([\\-\\w]+) +([\\-\\w]+)", CosExpression.class); + impls.put("tan +([\\-\\w]+) +([\\-\\w]+)", TanExpression.class); + impls.put("cat2 +([\\-\\w]+) +([\\-\\w]+) +([\\-\\w]+)", CosineArcTanExpression.class); + impls.put("sat2 +([\\-\\w]+) +([\\-\\w]+) +([\\-\\w]+)", SinArcTanExpression.class); + impls.put("pin +([\\-\\w]+) +([\\-\\w]+) +([\\-\\w]+)", PinExpression.class); + impls.put("mod +([\\-\\w]+) +([\\-\\w]+) +([\\-\\w]+)", ModExpression.class); + + } + + public static Expression parse(String str){ + for(String regexp : impls.keySet()) { + Pattern ptrn = Pattern.compile(regexp); + Matcher m = ptrn.matcher(str); + if(m.matches()) { + Class c = impls.get(regexp); + try { + return (Expression)c.getDeclaredConstructor(Matcher.class).newInstance(m); + } catch (Exception e){ + throw new RuntimeException(e); + } + } + } + throw new RuntimeException("Unsupported formula: " + str); + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/Formula.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/Formula.java new file mode 100644 index 0000000000..a0ba201166 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/Formula.java @@ -0,0 +1,385 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.awt.geom.Rectangle2D; +import java.util.HashMap; +import java.util.Map; + +/** + * A guide formula in DrawingML. + * This is a base class for adjust values, geometric guides and bilt-in guides + * + * @author Yegor Kozlov + */ +public abstract class Formula { + + String getName(){ + return null; + } + + abstract double evaluate(Context ctx); + + static Map builtInFormulas = new HashMap(); + static { + // 3 x 360¡ / 4 = 270¡ + builtInFormulas.put("3cd4", new Formula(){ + @Override + double evaluate(Context ctx){ + return 270 * 60000; + } + + }); + + // 3 x 360¡ / 8 = 135¡ + builtInFormulas.put("3cd8", new Formula(){ + @Override + double evaluate(Context ctx){ + return 135 * 60000; + } + + }); + + // 5 x 360¡ / 8 = 225¡ + builtInFormulas.put("5cd8", new Formula(){ + @Override + double evaluate(Context ctx){ + return 270 * 60000; + } + + }); + + // 7 x 360¡ / 8 = 315¡ + builtInFormulas.put("7cd8", new Formula(){ + @Override + double evaluate(Context ctx){ + return 270 * 60000; + } + + }); + + // bottom + builtInFormulas.put("b", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + return anchor.getY() + anchor.getHeight(); + } + + }); + + // 360¡ / 2 = 180¡ + builtInFormulas.put("cd2", new Formula(){ + @Override + double evaluate(Context ctx){ + return 180 * 60000; + } + + }); + + // 360¡ / 4 = 90¡ + builtInFormulas.put("cd4", new Formula(){ + @Override + double evaluate(Context ctx){ + return 90 * 60000; + } + + }); + + // 360¡ / 8 = 45¡ + builtInFormulas.put("cd8", new Formula(){ + @Override + double evaluate(Context ctx){ + return 45 * 60000; + } + + }); + + // horizontal center + builtInFormulas.put("hc", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + return anchor.getX() + anchor.getWidth()/2; + } + + }); + + // height + builtInFormulas.put("h", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + return anchor.getHeight(); + } + + }); + + // height / 2 + builtInFormulas.put("hd2", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + return anchor.getHeight()/2; + } + + }); + + // height / 3 + builtInFormulas.put("hd3", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + return anchor.getHeight()/3; + } + + }); + + // height / 4 + builtInFormulas.put("hd4", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + return anchor.getHeight()/4; + } + + }); + + // height / 5 + builtInFormulas.put("hd5", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + return anchor.getHeight()/5; + } + + }); + + // height / 6 + builtInFormulas.put("hd6", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + return anchor.getHeight()/6; + } + + }); + + // height / 8 + builtInFormulas.put("hd8", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + return anchor.getHeight()/8; + } + + }); + + // left + builtInFormulas.put("l", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + return anchor.getX(); + } + + }); + + // long side + builtInFormulas.put("ls", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + return Math.max(anchor.getWidth(), anchor.getHeight()); + } + + }); + + // right + builtInFormulas.put("r", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + return anchor.getX() + anchor.getWidth(); + } + + }); + + // short side + builtInFormulas.put("ss", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + return Math.min(anchor.getWidth(), anchor.getHeight()); + } + + }); + + // short side / 2 + builtInFormulas.put("ssd2", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + double ss = Math.min(anchor.getWidth(), anchor.getHeight()); + return ss / 2; + } + }); + + // short side / 4 + builtInFormulas.put("ssd4", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + double ss = Math.min(anchor.getWidth(), anchor.getHeight()); + return ss / 4; + } + }); + + // short side / 6 + builtInFormulas.put("ssd6", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + double ss = Math.min(anchor.getWidth(), anchor.getHeight()); + return ss / 6; + } + }); + + // short side / 8 + builtInFormulas.put("ssd8", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + double ss = Math.min(anchor.getWidth(), anchor.getHeight()); + return ss / 8; + } + }); + + // short side / 16 + builtInFormulas.put("ssd16", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + double ss = Math.min(anchor.getWidth(), anchor.getHeight()); + return ss / 16; + } + }); + + // short side / 32 + builtInFormulas.put("ssd32", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + double ss = Math.min(anchor.getWidth(), anchor.getHeight()); + return ss / 32; + } + }); + + // top + builtInFormulas.put("t", new Formula(){ + @Override + double evaluate(Context ctx){ + return ctx.getShapeAnchor().getY(); + } + }); + + // vertical center + builtInFormulas.put("vc", new Formula(){ + @Override + double evaluate(Context ctx){ + Rectangle2D anchor = ctx.getShapeAnchor(); + return anchor.getY() + anchor.getHeight()/2; + } + }); + + // width + builtInFormulas.put("w", new Formula(){ + @Override + double evaluate(Context ctx){ + return ctx.getShapeAnchor().getWidth(); + } + }); + + // width / 2 + builtInFormulas.put("wd2", new Formula(){ + @Override + double evaluate(Context ctx){ + return ctx.getShapeAnchor().getWidth()/2; + } + }); + + // width / 3 + builtInFormulas.put("wd3", new Formula(){ + @Override + double evaluate(Context ctx){ + return ctx.getShapeAnchor().getWidth()/3; + } + }); + + // width / 4 + builtInFormulas.put("wd4", new Formula(){ + @Override + double evaluate(Context ctx){ + return ctx.getShapeAnchor().getWidth()/4; + } + }); + + // width / 5 + builtInFormulas.put("wd5", new Formula(){ + @Override + double evaluate(Context ctx){ + return ctx.getShapeAnchor().getWidth()/5; + } + }); + + // width / 6 + builtInFormulas.put("wd6", new Formula(){ + @Override + double evaluate(Context ctx){ + return ctx.getShapeAnchor().getWidth()/6; + } + }); + + // width / 8 + builtInFormulas.put("wd8", new Formula(){ + @Override + double evaluate(Context ctx){ + return ctx.getShapeAnchor().getWidth()/8; + } + }); + + // width / 10 + builtInFormulas.put("wd10", new Formula(){ + @Override + double evaluate(Context ctx){ + return ctx.getShapeAnchor().getWidth()/10; + } + }); + + // width / 32 + builtInFormulas.put("wd32", new Formula(){ + @Override + double evaluate(Context ctx){ + return ctx.getShapeAnchor().getWidth()/32; + } + }); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/Guide.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/Guide.java new file mode 100644 index 0000000000..584e22483d --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/Guide.java @@ -0,0 +1,58 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuide; + +/** + * Date: 10/24/11 + * + * @author Yegor Kozlov + */ +public class Guide extends Formula { + private String name, fmla; + private Expression expr; + + public Guide(CTGeomGuide gd) { + this(gd.getName(), gd.getFmla()); + } + + public Guide(String nm, String fm){ + name = nm; + fmla = fm; + expr = ExpressionParser.parse(fm); + } + + + String getName(){ + return name; + } + + String getFormula(){ + return fmla; + } + + @Override + public double evaluate(Context ctx){ + return expr.evaluate(ctx); + } + + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/IAdjustableShape.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/IAdjustableShape.java new file mode 100644 index 0000000000..174af3d34c --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/IAdjustableShape.java @@ -0,0 +1,44 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.awt.geom.Rectangle2D; + +/** + * A bridge to the consumer application. + * + * To get a shape geometry one needs to pass shape bounds and adjust values. + * + * @author Yegor Kozlov + */ +public interface IAdjustableShape { + /** + * + * @return bounds of the shape + */ + Rectangle2D getAnchor(); + + /** + * + * @param name name of a adjust value, e.g. adj1 + * @return adjust guide defined in the shape or null + */ + Guide getAdjustValue(String name); +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/IfElseExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/IfElseExpression.java new file mode 100644 index 0000000000..3e16645f5a --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/IfElseExpression.java @@ -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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * If Else Formula: + *

+ * Arguments: 3 (fmla="?: x y z") + * Usage: "?: x y z" = if (x > 0), then y = value of this guide, + * else z = value of this guide + *

+ * + * @author Yegor Kozlov + */ +public class IfElseExpression implements Expression { + private String arg1, arg2, arg3; + + IfElseExpression(Matcher m){ + arg1 = m.group(1); + arg2 = m.group(2); + arg3 = m.group(3); + } + + public double evaluate(Context ctx){ + double x = ctx.getValue(arg1); + double y = ctx.getValue(arg2); + double z = ctx.getValue(arg3); + return x > 0 ? y : z; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/LineToCommand.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/LineToCommand.java new file mode 100644 index 0000000000..730636284a --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/LineToCommand.java @@ -0,0 +1,44 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import org.openxmlformats.schemas.drawingml.x2006.main.CTAdjPoint2D; + +import java.awt.geom.GeneralPath; + +/** + * Date: 10/25/11 + * + * @author Yegor Kozlov + */ +public class LineToCommand implements PathCommand { + private String arg1, arg2; + + LineToCommand(CTAdjPoint2D pt){ + arg1 = pt.getX().toString(); + arg2 = pt.getY().toString(); + } + + public void execute(GeneralPath path, Context ctx){ + double x = ctx.getValue(arg1); + double y = ctx.getValue(arg2); + path.lineTo(x, y); + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/LiteralValueExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/LiteralValueExpression.java new file mode 100644 index 0000000000..f84483cd55 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/LiteralValueExpression.java @@ -0,0 +1,40 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * Date: 10/24/11 + * + * @author Yegor Kozlov + */ +public class LiteralValueExpression implements Expression { + private String arg; + + LiteralValueExpression(Matcher m){ + arg = m.group(1); + } + + public double evaluate(Context ctx){ + return ctx.getValue(arg); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/MaxExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/MaxExpression.java new file mode 100644 index 0000000000..0c7ac3ecbe --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/MaxExpression.java @@ -0,0 +1,43 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * Maximum Value Formula + * + * @author Yegor Kozlov + */ +public class MaxExpression implements Expression { + private String arg1, arg2; + + MaxExpression(Matcher m){ + arg1 = m.group(1); + arg2 = m.group(2); + } + + public double evaluate(Context ctx){ + double x = ctx.getValue(arg1); + double y = ctx.getValue(arg2); + return Math.max(x, y); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/MinExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/MinExpression.java new file mode 100644 index 0000000000..3e28cdd822 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/MinExpression.java @@ -0,0 +1,43 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * Minimum Value Formula + * + * @author Yegor Kozlov + */ +public class MinExpression implements Expression { + private String arg1, arg2; + + MinExpression(Matcher m){ + arg1 = m.group(1); + arg2 = m.group(2); + } + + public double evaluate(Context ctx){ + double x = ctx.getValue(arg1); + double y = ctx.getValue(arg2); + return Math.min(x, y); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/ModExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/ModExpression.java new file mode 100644 index 0000000000..cf17f0564e --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/ModExpression.java @@ -0,0 +1,49 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * Modulo Formula: + *

+ * Arguments: 3 (fmla="mod x y z") + * Usage: "mod x y z" = sqrt(x^2 + b^2 + c^2) = value of this guide + *

+ * + * @author Yegor Kozlov + */ +public class ModExpression implements Expression { + private String arg1, arg2, arg3; + + ModExpression(Matcher m){ + arg1 = m.group(1); + arg2 = m.group(2); + arg3 = m.group(3); + } + + public double evaluate(Context ctx){ + double x = ctx.getValue(arg1); + double y = ctx.getValue(arg2); + double z = ctx.getValue(arg3); + return Math.sqrt(x*x + y*y + z*z); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/MoveToCommand.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/MoveToCommand.java new file mode 100644 index 0000000000..534534dd57 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/MoveToCommand.java @@ -0,0 +1,44 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import org.openxmlformats.schemas.drawingml.x2006.main.CTAdjPoint2D; + +import java.awt.geom.GeneralPath; + +/** + * Date: 10/25/11 + * + * @author Yegor Kozlov + */ +public class MoveToCommand implements PathCommand { + private String arg1, arg2; + + MoveToCommand(CTAdjPoint2D pt){ + arg1 = pt.getX().toString(); + arg2 = pt.getY().toString(); + } + + public void execute(GeneralPath path, Context ctx){ + double x = ctx.getValue(arg1); + double y = ctx.getValue(arg2); + path.moveTo(x, y); + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/MultiplyDivideExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/MultiplyDivideExpression.java new file mode 100644 index 0000000000..17aca48d15 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/MultiplyDivideExpression.java @@ -0,0 +1,45 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * Multiply Divide Formula + * + * @author Yegor Kozlov + */ +public class MultiplyDivideExpression implements Expression { + private String arg1, arg2, arg3; + + MultiplyDivideExpression(Matcher m){ + arg1 = m.group(1); + arg2 = m.group(2); + arg3 = m.group(3); + } + + public double evaluate(Context ctx){ + double x = ctx.getValue(arg1); + double y = ctx.getValue(arg2); + double z = ctx.getValue(arg3); + return (x * y ) / z; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/Path.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/Path.java new file mode 100644 index 0000000000..9d5e9f71d3 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/Path.java @@ -0,0 +1,91 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import org.apache.poi.util.Units; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.*; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.List; + +/** + * Specifies a creation path consisting of a series of moves, lines and curves + * that when combined forms a geometric shape + * + * @author Yegor Kozlov + */ +public class Path { + private final List commands; + boolean _fill, _stroke; + + public Path(CTPath2D spPath){ + _fill = spPath.getFill() != STPathFillMode.NONE; + _stroke = spPath.getStroke(); + + commands = new ArrayList(); + for(XmlObject ch : spPath.selectPath("*")){ + if(ch instanceof CTPath2DMoveTo){ + CTAdjPoint2D pt = ((CTPath2DMoveTo)ch).getPt(); + commands.add(new MoveToCommand(pt)); + } else if (ch instanceof CTPath2DLineTo){ + CTAdjPoint2D pt = ((CTPath2DLineTo)ch).getPt(); + commands.add(new LineToCommand(pt)); + } else if (ch instanceof CTPath2DArcTo){ + CTPath2DArcTo arc = (CTPath2DArcTo)ch; + commands.add(new ArcToCommand(arc)); + } else if (ch instanceof CTPath2DQuadBezierTo){ + CTPath2DQuadBezierTo bez = ((CTPath2DQuadBezierTo)ch); + CTAdjPoint2D pt1 = bez.getPtArray(0); + CTAdjPoint2D pt2 = bez.getPtArray(1); + commands.add(new QuadToCommand(pt1, pt2)); + } else if (ch instanceof CTPath2DCubicBezierTo){ + CTPath2DCubicBezierTo bez = ((CTPath2DCubicBezierTo)ch); + CTAdjPoint2D pt1 = bez.getPtArray(0); + CTAdjPoint2D pt2 = bez.getPtArray(1); + CTAdjPoint2D pt3 = bez.getPtArray(2); + commands.add(new CurveToCommand(pt1, pt2, pt3)); + } else if (ch instanceof CTPath2DClose){ + commands.add(new ClosePathCommand()); + } else { + throw new IllegalStateException("Unsupported path segment: " + ch); + } + } + } + + public GeneralPath getPath(Context ctx) { + GeneralPath path = new GeneralPath(); + for(PathCommand cmd : commands) + cmd.execute(path, ctx); + return path; + } + + public boolean isStroked(){ + return _stroke; + } + + public boolean isFilled(){ + return _fill; + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/PathCommand.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/PathCommand.java new file mode 100644 index 0000000000..7b3ec49379 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/PathCommand.java @@ -0,0 +1,45 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.awt.geom.GeneralPath; + +/** + * A path command in DrawingML. One of: + * + * - arcTo + * - moveTo + * - lineTo + * - cubicBezTo + * - quadBezTo + * - close + * + * + * @author Yegor Kozlov + */ +public interface PathCommand { + /** + * Execute the command an append a segment to the specified path + * + * @param path the path to append the result to + * @param ctx the context to lookup variables + */ + void execute(GeneralPath path, Context ctx); +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/PinExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/PinExpression.java new file mode 100644 index 0000000000..c1b7fe4466 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/PinExpression.java @@ -0,0 +1,54 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * Pin To Formula: + * + * + *

+ * Usage: "pin x y z" = if (y < x), then x = value of this guide + * else if (y > z), then z = value of this guide + * else y = value of this guide + *

+ * + * @author Yegor Kozlov + */ +public class PinExpression implements Expression { + private String arg1, arg2, arg3; + + PinExpression(Matcher m){ + arg1 = m.group(1); + arg2 = m.group(2); + arg3 = m.group(3); + } + + public double evaluate(Context ctx){ + double x = ctx.getValue(arg1); + double y = ctx.getValue(arg2); + double z = ctx.getValue(arg3); + if(y < x) return x; + else if (y > z) return z; + else return y; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/PresetGeometries.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/PresetGeometries.java new file mode 100644 index 0000000000..433c0cbe2f --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/PresetGeometries.java @@ -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.xslf.model.geom; + +import org.apache.poi.xslf.usermodel.XMLSlideShow; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTCustomGeometry2D; + +import java.io.InputStream; +import java.util.LinkedHashMap; + +/** + * Date: 10/25/11 + * + * @author Yegor Kozlov + */ +public class PresetGeometries extends LinkedHashMap { + private static PresetGeometries _inst; + + private PresetGeometries(){ + try { + InputStream is = + XMLSlideShow.class.getResourceAsStream("presetShapeDefinitions.xml"); + read(is); + } catch (Exception e){ + throw new RuntimeException(e); + } + } + + private void read(InputStream is) throws Exception { + XmlObject obj = XmlObject.Factory.parse(is); + for (XmlObject def : obj.selectPath("*/*")) { + + String name = def.getDomNode().getLocalName(); + CTCustomGeometry2D geom = CTCustomGeometry2D.Factory.parse(def.toString()); + + put(name, new CustomGeometry(geom)); + } + } + + public static PresetGeometries getInstance(){ + if(_inst == null) _inst = new PresetGeometries(); + + return _inst; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/QuadToCommand.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/QuadToCommand.java new file mode 100644 index 0000000000..9a0f2407fa --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/QuadToCommand.java @@ -0,0 +1,48 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import org.openxmlformats.schemas.drawingml.x2006.main.CTAdjPoint2D; + +import java.awt.geom.GeneralPath; + +/** + * Date: 10/25/11 + * + * @author Yegor Kozlov + */ +public class QuadToCommand implements PathCommand { + private String arg1, arg2, arg3, arg4; + + QuadToCommand(CTAdjPoint2D pt1, CTAdjPoint2D pt2){ + arg1 = pt1.getX().toString(); + arg2 = pt1.getY().toString(); + arg3 = pt2.getX().toString(); + arg4 = pt2.getY().toString(); + } + + public void execute(GeneralPath path, Context ctx){ + double x1 = ctx.getValue(arg1); + double y1 = ctx.getValue(arg2); + double x2 = ctx.getValue(arg3); + double y2 = ctx.getValue(arg4); + path.quadTo(x1, y1, x2, y2); + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/SinArcTanExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/SinArcTanExpression.java new file mode 100644 index 0000000000..8ac68e0c63 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/SinArcTanExpression.java @@ -0,0 +1,51 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * Sine ArcTan Formula: + * + * + *

+ * Arguments: 3 (fmla="sat2 x y z") + * Usage: "sat2 x y z" = (x*sin(arctan(z / y))) = value of this guide + *

+ * + * @author Yegor Kozlov + */ +public class SinArcTanExpression implements Expression { + private String arg1, arg2, arg3; + + SinArcTanExpression(Matcher m){ + arg1 = m.group(1); + arg2 = m.group(2); + arg3 = m.group(3); + } + + public double evaluate(Context ctx){ + double x = ctx.getValue(arg1); + double y = ctx.getValue(arg2); + double z = ctx.getValue(arg3); + return x*Math.sin(Math.atan(z / y)); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/SinExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/SinExpression.java new file mode 100644 index 0000000000..9e82f5abda --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/SinExpression.java @@ -0,0 +1,49 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * Sine Formula: + * + * + *

+ * Arguments: 2 (fmla="sin x y") + * Usage: "sin x y" = (x * sin( y )) = value of this guide + *

+ * + * @author Yegor Kozlov + */ +public class SinExpression implements Expression { + private String arg1, arg2; + + SinExpression(Matcher m){ + arg1 = m.group(1); + arg2 = m.group(2); + } + + public double evaluate(Context ctx){ + double x = ctx.getValue(arg1); + double y = ctx.getValue(arg2) / 60000; + return x * Math.sin(Math.toRadians(y)); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/SqrtExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/SqrtExpression.java new file mode 100644 index 0000000000..d798e93a13 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/SqrtExpression.java @@ -0,0 +1,46 @@ +/* + * ==================================================================== + * 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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * Square Root Formula: + * + * + *

+ * Arguments: 1 (fmla="sqrt x") + * Usage: "sqrt x" = sqrt(x) = value of this guide + *

+ * @author Yegor Kozlov + */ +public class SqrtExpression implements Expression { + private String arg; + + SqrtExpression(Matcher m){ + arg =m.group(1); + } + + public double evaluate(Context ctx){ + double val = ctx.getValue(arg); + return Math.sqrt(val); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/geom/TanExpression.java b/src/ooxml/java/org/apache/poi/xslf/model/geom/TanExpression.java new file mode 100644 index 0000000000..3435f35603 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/model/geom/TanExpression.java @@ -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.xslf.model.geom; + +import java.util.regex.Matcher; + +/** + * Tangent Formula: + * + * + * + *

+ * Arguments: 2 (fmla="tan x y") + * Usage: "tan x y" = (x * tan( y )) = value of this guide + *

+ * + * @author Yegor Kozlov + */ +public class TanExpression implements Expression { + private String arg1, arg2; + + TanExpression(Matcher m){ + arg1 = m.group(1); + arg2 = m.group(2); + } + + public double evaluate(Context ctx){ + double x = ctx.getValue(arg1); + double y = ctx.getValue(arg2); + return x * Math.tan(Math.toRadians(y / 60000)); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java index e37259459f..193e5f023f 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java @@ -21,6 +21,10 @@ package org.apache.poi.xslf.usermodel; import org.apache.poi.util.Beta; import org.apache.poi.util.Units; +import org.apache.poi.xslf.model.geom.Context; +import org.apache.poi.xslf.model.geom.CustomGeometry; +import org.apache.poi.xslf.model.geom.Path; +import org.apache.poi.xslf.model.geom.PresetGeometries; import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuide; import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuideList; import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; @@ -42,6 +46,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; import java.awt.*; import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.List; @@ -100,39 +105,4 @@ public class XSLFAutoShape extends XSLFTextShape { } return txBody; } - - int getAdjustValue(String name, int defaultValue){ - /* - CTShape shape = (CTShape) getXmlObject(); - CTGeomGuideList av = shape.getSpPr().getPrstGeom().getAvLst(); - if(av != null){ - for(CTGeomGuide gd : av.getGdList()){ - if(gd.getName().equals(name)) { - String fmla = gd.getFmla(); - Matcher m = adjPtrn.matcher(fmla); - if(m.matches()){ - int val = Integer.parseInt(m.group(1)); - return 21600*val/100000; - } - } - } - } - */ - return defaultValue; - } - - @Override - protected java.awt.Shape getOutline(){ - java.awt.Shape outline = XSLFPresetGeometry.getOutline(this); - Rectangle2D anchor = getAnchor(); - - AffineTransform at = new AffineTransform(); - at.translate(anchor.getX(), anchor.getY()); - at.scale( - 1.0f/21600*anchor.getWidth(), - 1.0f/21600*anchor.getHeight() - ); - return outline == null ? anchor : at.createTransformedShape(outline); - } - } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java index beb23bdec0..cc16d26ebc 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java @@ -223,18 +223,6 @@ public class XSLFConnectorShape extends XSLFSimpleShape { } } - @Override - protected java.awt.Shape getOutline() { - Rectangle2D anchor = getAnchor(); - double x1 = anchor.getX(), - y1 = anchor.getY(), - x2 = anchor.getX() + anchor.getWidth(), - y2 = anchor.getY() + anchor.getHeight(); - - - return new Line2D.Double(x1, y1, x2, y2); - } - Shape getTailDecoration() { LineEndLength tailLength = getLineTailLength(); LineEndWidth tailWidth = getLineTailWidth(); @@ -307,9 +295,10 @@ public class XSLFConnectorShape extends XSLFSimpleShape { double scaleX = 1; switch (getLineHeadDecoration()) { case OVAL: - scaleY = Math.pow(2, headWidth.ordinal()); - scaleX = Math.pow(2, headLength.ordinal()); shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY); + bounds = shape.getBounds2D(); + at.translate(x1 - bounds.getWidth() / 2, y1 - bounds.getHeight() / 2); + at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2); break; case STEALTH: case ARROW: diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPresetGeometry.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPresetGeometry.java deleted file mode 100644 index dcd4910b8b..0000000000 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPresetGeometry.java +++ /dev/null @@ -1,637 +0,0 @@ -/* - * ==================================================================== - * 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.xslf.usermodel; - -import java.awt.*; -import java.awt.geom.*; - -/** - * TODO: re-write and initialize from presetShapeDefinitions.xml - * - * @author Yegor Kozlov - */ -public class XSLFPresetGeometry { - public static final int LINE = 1; - public static final int LINE_INV = 2; - public static final int TRIANGLE = 3; - public static final int RT_TRIANGLE = 4; - public static final int RECT = 5; - public static final int DIAMOND = 6; - public static final int PARALLELOGRAM = 7; - public static final int TRAPEZOID = 8; - public static final int NON_ISOSCELES_TRAPEZOID = 9; - public static final int PENTAGON = 10; - public static final int HEXAGON = 11; - public static final int HEPTAGON = 12; - public static final int OCTAGON = 13; - public static final int DECAGON = 14; - public static final int DODECAGON = 15; - public static final int STAR_4 = 16; - public static final int STAR_5 = 17; - public static final int STAR_6 = 18; - public static final int STAR_7 = 19; - public static final int STAR_8 = 20; - public static final int STAR_10 = 21; - public static final int STAR_12 = 22; - public static final int STAR_16 = 23; - public static final int STAR_24 = 24; - public static final int STAR_32 = 25; - public static final int ROUND_RECT = 26; - public static final int ROUND_1_RECT = 27; - public static final int ROUND_2_SAME_RECT = 28; - public static final int ROUND_2_DIAG_RECT = 29; - public static final int SNIP_ROUND_RECT = 30; - public static final int SNIP_1_RECT = 31; - public static final int SNIP_2_SAME_RECT = 32; - public static final int SNIP_2_DIAG_RECT = 33; - public static final int PLAQUE = 34; - public static final int ELLIPSE = 35; - public static final int TEARDROP = 36; - public static final int HOME_PLATE = 37; - public static final int CHEVRON = 38; - public static final int PIE_WEDGE = 39; - public static final int PIE = 40; - public static final int BLOCK_ARC = 41; - public static final int DONUT = 42; - public static final int NO_SMOKING = 43; - public static final int RIGHT_ARROW = 44; - public static final int LEFT_ARROW = 45; - public static final int UP_ARROW = 46; - public static final int DOWN_ARROW = 47; - public static final int STRIPED_RIGHT_ARROW = 48; - public static final int NOTCHED_RIGHT_ARROW = 49; - public static final int BENT_UP_ARROW = 50; - public static final int LEFT_RIGHT_ARROW = 51; - public static final int UP_DOWN_ARROW = 52; - public static final int LEFT_UP_ARROW = 53; - public static final int LEFT_RIGHT_UP_ARROW = 54; - public static final int QUAD_ARROW = 55; - public static final int LEFT_ARROW_CALLOUT = 56; - public static final int RIGHT_ARROW_CALLOUT = 57; - public static final int UP_ARROW_CALLOUT = 58; - public static final int DOWN_ARROW_CALLOUT = 59; - public static final int LEFT_RIGHT_ARROW_CALLOUT = 60; - public static final int UP_DOWN_ARROW_CALLOUT = 61; - public static final int QUAD_ARROW_CALLOUT = 62; - public static final int BENT_ARROW = 63; - public static final int UTURN_ARROW = 64; - public static final int CIRCULAR_ARROW = 65; - public static final int LEFT_CIRCULAR_ARROW = 66; - public static final int LEFT_RIGHT_CIRCULAR_ARROW = 67; - public static final int CURVED_RIGHT_ARROW = 68; - public static final int CURVED_LEFT_ARROW = 69; - public static final int CURVED_UP_ARROW = 70; - public static final int CURVED_DOWN_ARROW = 71; - public static final int SWOOSH_ARROW = 72; - public static final int CUBE = 73; - public static final int CAN = 74; - public static final int LIGHTNING_BOLT = 75; - public static final int HEART = 76; - public static final int SUN = 77; - public static final int MOON = 78; - public static final int SMILEY_FACE = 79; - public static final int IRREGULAR_SEAL_1 = 80; - public static final int IRREGULAR_SEAL_2 = 81; - public static final int FOLDED_CORNER = 82; - public static final int BEVEL = 83; - public static final int FRAME = 84; - public static final int HALF_FRAME = 85; - public static final int CORNER = 86; - public static final int DIAG_STRIPE = 87; - public static final int CHORD = 88; - public static final int ARC = 89; - public static final int LEFT_BRACKET = 90; - public static final int RIGHT_BRACKET = 91; - public static final int LEFT_BRACE = 92; - public static final int RIGHT_BRACE = 93; - public static final int BRACKET_PAIR = 94; - public static final int BRACE_PAIR = 95; - public static final int STRAIGHT_CONNECTOR_1 = 96; - public static final int BENT_CONNECTOR_2 = 97; - public static final int BENT_CONNECTOR_3 = 98; - public static final int BENT_CONNECTOR_4 = 99; - public static final int BENT_CONNECTOR_5 = 100; - public static final int CURVED_CONNECTOR_2 = 101; - public static final int CURVED_CONNECTOR_3 = 102; - public static final int CURVED_CONNECTOR_4 = 103; - public static final int CURVED_CONNECTOR_5 = 104; - public static final int CALLOUT_1 = 105; - public static final int CALLOUT_2 = 106; - public static final int CALLOUT_3 = 107; - public static final int ACCENT_CALLOUT_1 = 108; - public static final int ACCENT_CALLOUT_2 = 109; - public static final int ACCENT_CALLOUT_3 = 110; - public static final int BORDER_CALLOUT_1 = 111; - public static final int BORDER_CALLOUT_2 = 112; - public static final int BORDER_CALLOUT_3 = 113; - public static final int ACCENT_BORDER_CALLOUT_1 = 114; - public static final int ACCENT_BORDER_CALLOUT_2 = 115; - public static final int ACCENT_BORDER_CALLOUT_3 = 116; - public static final int WEDGE_RECT_CALLOUT = 117; - public static final int WEDGE_ROUND_RECT_CALLOUT = 118; - public static final int WEDGE_ELLIPSE_CALLOUT = 119; - public static final int CLOUD_CALLOUT = 120; - public static final int CLOUD = 121; - public static final int RIBBON = 122; - public static final int RIBBON_2 = 123; - public static final int ELLIPSE_RIBBON = 124; - public static final int ELLIPSE_RIBBON_2 = 125; - public static final int LEFT_RIGHT_RIBBON = 126; - public static final int VERTICAL_SCROLL = 127; - public static final int HORIZONTAL_SCROLL = 128; - public static final int WAVE = 129; - public static final int DOUBLE_WAVE = 130; - public static final int PLUS = 131; - public static final int FLOW_CHART_PROCESS = 132; - public static final int FLOW_CHART_DECISION = 133; - public static final int FLOW_CHART_INPUT_OUTPUT = 134; - public static final int FLOW_CHART_PREDEFINED_PROCESS = 135; - public static final int FLOW_CHART_INTERNAL_STORAGE = 136; - public static final int FLOW_CHART_DOCUMENT = 137; - public static final int FLOW_CHART_MULTIDOCUMENT = 138; - public static final int FLOW_CHART_TERMINATOR = 139; - public static final int FLOW_CHART_PREPARATION = 140; - public static final int FLOW_CHART_MANUAL_INPUT = 141; - public static final int FLOW_CHART_MANUAL_OPERATION = 142; - public static final int FLOW_CHART_CONNECTOR = 143; - public static final int FLOW_CHART_PUNCHED_CARD = 144; - public static final int FLOW_CHART_PUNCHED_TAPE = 145; - public static final int FLOW_CHART_SUMMING_JUNCTION = 146; - public static final int FLOW_CHART_OR = 147; - public static final int FLOW_CHART_COLLATE = 148; - public static final int FLOW_CHART_SORT = 149; - public static final int FLOW_CHART_EXTRACT = 150; - public static final int FLOW_CHART_MERGE = 151; - public static final int FLOW_CHART_OFFLINE_STORAGE = 152; - public static final int FLOW_CHART_ONLINE_STORAGE = 153; - public static final int FLOW_CHART_MAGNETIC_TAPE = 154; - public static final int FLOW_CHART_MAGNETIC_DISK = 155; - public static final int FLOW_CHART_MAGNETIC_DRUM = 156; - public static final int FLOW_CHART_DISPLAY = 157; - public static final int FLOW_CHART_DELAY = 158; - public static final int FLOW_CHART_ALTERNATE_PROCESS = 159; - public static final int FLOW_CHART_OFFPAGE_CONNECTOR = 160; - public static final int ACTION_BUTTON_BLANK = 161; - public static final int ACTION_BUTTON_HOME = 162; - public static final int ACTION_BUTTON_HELP = 163; - public static final int ACTION_BUTTON_INFORMATION = 164; - public static final int ACTION_BUTTON_FORWARD_NEXT = 165; - public static final int ACTION_BUTTON_BACK_PREVIOUS = 166; - public static final int ACTION_BUTTON_END = 167; - public static final int ACTION_BUTTON_BEGINNING = 168; - public static final int ACTION_BUTTON_RETURN = 169; - public static final int ACTION_BUTTON_DOCUMENT = 170; - public static final int ACTION_BUTTON_SOUND = 171; - public static final int ACTION_BUTTON_MOVIE = 172; - public static final int GEAR_6 = 173; - public static final int GEAR_9 = 174; - public static final int FUNNEL = 175; - public static final int MATH_PLUS = 176; - public static final int MATH_MINUS = 177; - public static final int MATH_MULTIPLY = 178; - public static final int MATH_DIVIDE = 179; - public static final int MATH_EQUAL = 180; - public static final int MATH_NOT_EQUAL = 181; - public static final int CORNER_TABS = 182; - public static final int SQUARE_TABS = 183; - public static final int PLAQUE_TABS = 184; - public static final int CHART_X = 185; - public static final int CHART_STAR = 186; - public static final int CHART_PLUS = 187; - - private static interface ShapeOutline { - java.awt.Shape getOutline(XSLFAutoShape shape); - } - - - static ShapeOutline[] shapes; - static { - shapes = new ShapeOutline[255]; - - shapes[RECT] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - Rectangle2D path = new Rectangle2D.Float(0, 0, 21600, 21600); - return path; - } - }; - - shapes[ROUND_RECT] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - int adjval = shape.getAdjustValue("adj1", 5400); - RoundRectangle2D path = new RoundRectangle2D.Float(0, 0, 21600, 21600, adjval, adjval); - return path; - } - }; - - shapes[ELLIPSE] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - Ellipse2D path = new Ellipse2D.Float(0, 0, 21600, 21600); - return path; - } - }; - - shapes[DIAMOND] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - GeneralPath path = new GeneralPath(); - path.moveTo(10800, 0); - path.lineTo(21600, 10800); - path.lineTo(10800, 21600); - path.lineTo(0, 10800); - path.closePath(); - return path; - } - }; - - //m@0,l,21600r21600 - shapes[TRIANGLE] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - int adjval = shape.getAdjustValue("adj1", 5400); - GeneralPath path = new GeneralPath(); - path.moveTo(adjval, 0); - path.lineTo(0, 21600); - path.lineTo(21600, 21600); - path.closePath(); - return path; - } - }; - - shapes[RT_TRIANGLE] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - GeneralPath path = new GeneralPath(); - path.moveTo(0, 0); - path.lineTo(21600, 21600); - path.lineTo(0, 21600); - path.closePath(); - return path; - } - }; - - shapes[PARALLELOGRAM] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - int adjval = shape.getAdjustValue("adj1", 5400); - - GeneralPath path = new GeneralPath(); - path.moveTo(adjval, 0); - path.lineTo(21600, 0); - path.lineTo(21600 - adjval, 21600); - path.lineTo(0, 21600); - path.closePath(); - return path; - } - }; - - shapes[TRAPEZOID] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - int adjval = shape.getAdjustValue("adj1", 5400); - - GeneralPath path = new GeneralPath(); - path.moveTo(0, 0); - path.lineTo(adjval, 21600); - path.lineTo(21600 - adjval, 21600); - path.lineTo(21600, 0); - path.closePath(); - return path; - } - }; - - shapes[HEXAGON] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - int adjval = shape.getAdjustValue("adj1", 5400); - - GeneralPath path = new GeneralPath(); - path.moveTo(adjval, 0); - path.lineTo(21600 - adjval, 0); - path.lineTo(21600, 10800); - path.lineTo(21600 - adjval, 21600); - path.lineTo(adjval, 21600); - path.lineTo(0, 10800); - path.closePath(); - return path; - } - }; - - shapes[OCTAGON] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - int adjval = shape.getAdjustValue("adj1", 6324); - - GeneralPath path = new GeneralPath(); - path.moveTo(adjval, 0); - path.lineTo(21600 - adjval, 0); - path.lineTo(21600, adjval); - path.lineTo(21600, 21600-adjval); - path.lineTo(21600-adjval, 21600); - path.lineTo(adjval, 21600); - path.lineTo(0, 21600-adjval); - path.lineTo(0, adjval); - path.closePath(); - return path; - } - }; - - shapes[PLUS] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - int adjval = shape.getAdjustValue("adj1", 5400); - - GeneralPath path = new GeneralPath(); - path.moveTo(adjval, 0); - path.lineTo(21600 - adjval, 0); - path.lineTo(21600 - adjval, adjval); - path.lineTo(21600, adjval); - path.lineTo(21600, 21600-adjval); - path.lineTo(21600-adjval, 21600-adjval); - path.lineTo(21600-adjval, 21600); - path.lineTo(adjval, 21600); - path.lineTo(adjval, 21600-adjval); - path.lineTo(0, 21600-adjval); - path.lineTo(0, adjval); - path.lineTo(adjval, adjval); - path.closePath(); - return path; - } - }; - - shapes[PENTAGON] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - - GeneralPath path = new GeneralPath(); - path.moveTo(10800, 0); - path.lineTo(21600, 8259); - path.lineTo(21600 - 4200, 21600); - path.lineTo(4200, 21600); - path.lineTo(0, 8259); - path.closePath(); - return path; - } - }; - - shapes[HOME_PLATE] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - - GeneralPath path = new GeneralPath(); - int adjval = shape.getAdjustValue("adj1", 16200); - path.moveTo(0, 0); - path.lineTo(adjval, 0 ); - path.lineTo(21600, 10800); - path.lineTo(adjval, 21600); - path.lineTo(0, 21600); - path.closePath(); - return path; - } - }; - - shapes[CHEVRON] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - GeneralPath path = new GeneralPath(); - int adjval = shape.getAdjustValue("adj1", 16200); - path.moveTo(0, 0); - path.lineTo(adjval, 0 ); - path.lineTo(21600, 10800); - path.lineTo(adjval, 21600); - path.lineTo(0, 21600); - path.lineTo(21600 - adjval, 10800); - path.closePath(); - return path; - } - }; - - shapes[CAN] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - int adjval = shape.getAdjustValue("adj1", 5400); - GeneralPath path = new GeneralPath(); - path.moveTo(0, 0); - path.lineTo(21600, 0); - path.lineTo(21600, 21600); - path.lineTo(0, 21600); - - //path.lineTo(21600, adjval); - - path.closePath(); - path.moveTo(10800, 0); - //path.append(new Arc2D.Float(10800, 0, 10800, adjval, 0, 90, Arc2D.OPEN), true); - path.moveTo(10800, adjval/2); - path.append(new Arc2D.Float(10800, adjval/2, 10800, adjval, 90, 180, Arc2D.OPEN), true); - //path.append(new Arc2D.Float(0, adjval/2, 10800, adjval, 180, 270, Arc2D.OPEN), true); - //path.append(new Arc2D.Float(0, 0, 10800, adjval, 270, 360, Arc2D.OPEN), true); - return path; - } - }; - - shapes[DOWN_ARROW] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - //m0@0 l@1@0 @1,0 @2,0 @2@0,21600@0,10800,21600xe - int adjval = shape.getAdjustValue("adj1", 16200); - int adjval2 = shape.getAdjustValue("adj2", 5400); - GeneralPath path = new GeneralPath(); - path.moveTo(0, adjval); - path.lineTo(adjval2, adjval); - path.lineTo(adjval2, 0); - path.lineTo(21600-adjval2, 0); - path.lineTo(21600-adjval2, adjval); - path.lineTo(21600, adjval); - path.lineTo(10800, 21600); - path.closePath(); - return path; - } - }; - - shapes[UP_ARROW] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - //m0@0 l@1@0 @1,21600@2,21600@2@0,21600@0,10800,xe - int adjval = shape.getAdjustValue("adj1", 5400); - int adjval2 = shape.getAdjustValue("adj2", 5400); - GeneralPath path = new GeneralPath(); - path.moveTo(0, adjval); - path.lineTo(adjval2, adjval); - path.lineTo(adjval2, 21600); - path.lineTo(21600-adjval2, 21600); - path.lineTo(21600-adjval2, adjval); - path.lineTo(21600, adjval); - path.lineTo(10800, 0); - path.closePath(); - return path; - } - }; - - shapes[RIGHT_ARROW] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - //m@0, l@0@1 ,0@1,0@2@0@2@0,21600,21600,10800xe - int adjval = shape.getAdjustValue("adj1", 16200); - int adjval2 = shape.getAdjustValue("adj2", 5400); - GeneralPath path = new GeneralPath(); - path.moveTo(adjval, 0); - path.lineTo(adjval, adjval2); - path.lineTo(0, adjval2); - path.lineTo(0, 21600-adjval2); - path.lineTo(adjval, 21600-adjval2); - path.lineTo(adjval, 21600); - path.lineTo(21600, 10800); - path.closePath(); - return path; - } - }; - - shapes[LEFT_ARROW] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - //m@0, l@0@1,21600@1,21600@2@0@2@0,21600,,10800xe - int adjval = shape.getAdjustValue("adj1", 5400); - int adjval2 = shape.getAdjustValue("adj2", 5400); - GeneralPath path = new GeneralPath(); - path.moveTo(adjval, 0); - path.lineTo(adjval, adjval2); - path.lineTo(21600, adjval2); - path.lineTo(21600, 21600-adjval2); - path.lineTo(adjval, 21600-adjval2); - path.lineTo(adjval, 21600); - path.lineTo(0, 10800); - path.closePath(); - return path; - } - }; - shapes[LEFT_BRACE] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - //m21600,qx10800@0l10800@2qy0@11,10800@3l10800@1qy21600,21600e - int adjval = shape.getAdjustValue("adj1", 1800); - int adjval2 = shape.getAdjustValue("adj2", 10800); - - GeneralPath path = new GeneralPath(); - path.moveTo(21600, 0); - - path.append(new Arc2D.Float(10800, 0, 21600, adjval*2, 90, 90, Arc2D.OPEN), false); - path.moveTo(10800, adjval); - - path.lineTo(10800, adjval2 - adjval); - - path.append(new Arc2D.Float(-10800, adjval2 - 2*adjval, 21600, adjval*2, 270, 90, Arc2D.OPEN), false); - path.moveTo(0, adjval2); - - path.append(new Arc2D.Float(-10800, adjval2, 21600, adjval*2, 0, 90, Arc2D.OPEN), false); - path.moveTo(10800, adjval2 + adjval); - - path.lineTo(10800, 21600 - adjval); - - path.append(new Arc2D.Float(10800, 21600 - 2*adjval, 21600, adjval*2, 180, 90, Arc2D.OPEN), false); - - return path; - } - }; - - shapes[RIGHT_BRACE] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - //m,qx10800@0 l10800@2qy21600@11,10800@3l10800@1qy,21600e - int adjval = shape.getAdjustValue("adj1", 1800); - int adjval2 = shape.getAdjustValue("adj2", 10800); - - GeneralPath path = new GeneralPath(); - path.moveTo(0, 0); - - path.append(new Arc2D.Float(-10800, 0, 21600, adjval*2, 0, 90, Arc2D.OPEN), false); - path.moveTo(10800, adjval); - - path.lineTo(10800, adjval2 - adjval); - - path.append(new Arc2D.Float(10800, adjval2 - 2*adjval, 21600, adjval*2, 180, 90, Arc2D.OPEN), false); - path.moveTo(21600, adjval2); - - path.append(new Arc2D.Float(10800, adjval2, 21600, adjval*2, 90, 90, Arc2D.OPEN), false); - path.moveTo(10800, adjval2 + adjval); - - path.lineTo(10800, 21600 - adjval); - - path.append(new Arc2D.Float(-10800, 21600 - 2*adjval, 21600, adjval*2, 270, 90, Arc2D.OPEN), false); - - return path; - } - }; - - - shapes[LEFT_RIGHT_ARROW] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - //m,10800l@0,21600@0@3@2@3@2,21600,21600,10800@2,0@2@1@0@1@0,xe - int adjval = shape.getAdjustValue("adj1", 4320); - int adjval2 = shape.getAdjustValue("adj2", 5400); - - GeneralPath path = new GeneralPath(); - path.moveTo(0, 10800); - path.lineTo(adjval, 0); - path.lineTo(adjval, adjval2); - path.lineTo(21600 - adjval, adjval2); - path.lineTo(21600 - adjval, 0); - path.lineTo(21600, 10800); - path.lineTo(21600 - adjval, 21600); - path.lineTo(21600 - adjval, 21600 - adjval2); - path.lineTo(adjval, 21600 - adjval2); - path.lineTo(adjval, 21600); - path.closePath(); - return path; - } - }; - - shapes[UP_DOWN_ARROW] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - //m10800,l21600@0@3@0@3@2,21600@2,10800,21600,0@2@1@2@1@0,0@0xe - int adjval1 = shape.getAdjustValue("adj1", 5400); - int adjval2 = shape.getAdjustValue("adj2", 4320); - - GeneralPath path = new GeneralPath(); - path.moveTo(10800, 0); - path.lineTo(21600, adjval2); - path.lineTo(21600 - adjval1, adjval2); - path.lineTo(21600 - adjval1, 21600 - adjval2); - path.lineTo(21600, 21600 - adjval2); - - path.lineTo(10800, 21600); - path.lineTo(0, 21600 - adjval2); - path.lineTo(adjval1, 21600 - adjval2); - path.lineTo(adjval1, adjval2); - path.lineTo(0, adjval2); - - path.closePath(); - return path; - } - }; - - shapes[NOTCHED_RIGHT_ARROW] = new ShapeOutline(){ - public java.awt.Shape getOutline(XSLFAutoShape shape){ - //m@0,l@0@1,0@1@5,10800,0@2@0@2@0,21600,21600,10800xe - int adjval1 = shape.getAdjustValue("adj1", 16200); - int adjval2 = shape.getAdjustValue("adj2", 5400); - - GeneralPath path = new GeneralPath(); - path.moveTo(adjval1, 0); - path.lineTo(adjval1, adjval2); - path.lineTo(0, adjval2); - //The notch at the end stays adjusted so that it matches the shape of the arrowhead. - int notch = (21600-2*adjval2)*(21600-adjval1)/21600; - path.lineTo(notch, 10800); - path.lineTo(0, 21600 - adjval2); - path.lineTo(adjval1, 21600 - adjval2); - path.lineTo(adjval1, 21600); - path.lineTo(21600, 10800); - path.closePath(); - return path; - } - }; - } - - static Shape getOutline(XSLFAutoShape shape){ - ShapeOutline outline = shapes[shape.getShapeType()]; - return outline == null ? null : outline.getOutline(shape); - } -} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java index c7efb5ff51..049a2d321e 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java @@ -19,35 +19,22 @@ package org.apache.poi.xslf.usermodel; +import org.apache.poi.xslf.model.geom.*; import org.apache.poi.xslf.usermodel.LineCap; import org.apache.poi.xslf.usermodel.LineDash; import org.apache.poi.xslf.model.PropertyFetcher; import org.apache.poi.util.Beta; import org.apache.poi.util.Units; import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetLineDashProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; -import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap; -import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal; -import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; -import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect; -import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem; +import org.openxmlformats.schemas.drawingml.x2006.main.*; import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; import java.awt.geom.Rectangle2D; +import java.util.ArrayList; /** * @author Yegor Kozlov @@ -674,4 +661,55 @@ public abstract class XSLFSimpleShape extends XSLFShape { return ok; } + + @Override + protected java.awt.Shape getOutline(){ + PresetGeometries dict = PresetGeometries.getInstance(); + String name = getSpPr().getPrstGeom().getPrst().toString(); + CustomGeometry geom = dict.get(name); + Rectangle2D anchor = getAnchor(); + if(geom != null) { + // the guides in the shape definitions are all defined relative to each other, + // so we build the path starting from (0,0). + final Rectangle2D anchorEmu = new Rectangle2D.Double( + 0, + 0, + Units.toEMU(anchor.getWidth()), + Units.toEMU(anchor.getHeight()) + ); + + GeneralPath path = new GeneralPath(); + Context ctx = new Context(geom, new IAdjustableShape() { + public Rectangle2D getAnchor() { + return anchorEmu; + } + + public Guide getAdjustValue(String name) { + CTPresetGeometry2D prst = getSpPr().getPrstGeom(); + if(prst.isSetAvLst()) { + for(CTGeomGuide g : prst.getAvLst().getGdList()){ + if(g.getName().equals(name)) { + return new Guide(g); + } + } + } + return null; + } + }); + + for(Path p : geom){ + path.append( p.getPath(ctx) , false); + } + + // translate the result to the canvas coordinates in points + AffineTransform at = new AffineTransform(); + at.scale( + 1.0/Units.EMU_PER_POINT, 1.0/Units.EMU_PER_POINT); + at.translate(Units.toEMU(anchor.getX()), Units.toEMU(anchor.getY())); + return at.createTransformedShape(path); + } else { + return anchor; + } + } + } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java index d17f1ce759..c925922d5b 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java @@ -23,6 +23,9 @@ import org.apache.poi.util.Beta; import org.apache.poi.util.Units; import org.apache.poi.xslf.model.PropertyFetcher; import org.apache.poi.xslf.model.TextBodyPropertyFetcher; +import org.apache.poi.xslf.model.geom.Context; +import org.apache.poi.xslf.model.geom.CustomGeometry; +import org.apache.poi.xslf.model.geom.Path; import org.apache.xmlbeans.XmlObject; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties; @@ -33,6 +36,7 @@ import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType; import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; import java.awt.*; +import java.awt.geom.GeneralPath; import java.awt.image.BufferedImage; import java.awt.geom.Rectangle2D; import java.util.ArrayList; @@ -391,15 +395,14 @@ public abstract class XSLFTextShape extends XSLFSimpleShape { Color fillColor = getFillColor(); Color lineColor = getLineColor(); if(shadow != null) { - shadow.draw(graphics); + //shadow.draw(graphics); } - if (fillColor != null) { graphics.setColor(fillColor); applyFill(graphics); graphics.fill(outline); } - + if (lineColor != null){ graphics.setColor(lineColor); applyStroke(graphics); diff --git a/src/ooxml/testcases/org/apache/poi/xslf/geom/TestFormulaParser.java b/src/ooxml/testcases/org/apache/poi/xslf/geom/TestFormulaParser.java new file mode 100644 index 0000000000..b9f15139d5 --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xslf/geom/TestFormulaParser.java @@ -0,0 +1,40 @@ +package org.apache.poi.xslf.geom; + +import junit.framework.TestCase; +import org.apache.poi.xslf.model.geom.*; +import org.openxmlformats.schemas.drawingml.x2006.main.CTCustomGeometry2D; + +/** + * Date: 10/24/11 + * + * @author Yegor Kozlov + */ +public class TestFormulaParser extends TestCase { + public void testParse(){ + + Formula[] ops = { + new Guide("adj1", "val 100"), + new Guide("adj2", "val 200"), + new Guide("adj3", "val -1"), + new Guide("a1", "*/ adj1 2 adj2"), // a1 = 100*2 / 200 + new Guide("a2", "+- adj2 a1 adj1"), // a2 = 200 + a1 - 100 + new Guide("a3", "+/ adj1 adj2 adj2"), // a3 = (100 + 200) / 200 + new Guide("a4", "?: adj3 adj1 adj2"), // a4 = adj3 > 0 ? adj1 : adj2 + new Guide("a5", "abs -2"), + }; + + CustomGeometry geom = new CustomGeometry(CTCustomGeometry2D.Factory.newInstance()); + Context ctx = new Context(geom, null); + for(Formula fmla : ops) { + ctx.evaluate(fmla); + } + + assertEquals(100.0, ctx.getValue("adj1")); + assertEquals(200.0, ctx.getValue("adj2")); + assertEquals(1.0, ctx.getValue("a1")); + assertEquals(101.0, ctx.getValue("a2")); + assertEquals(1.5, ctx.getValue("a3")); + assertEquals(200.0, ctx.getValue("a4")); + assertEquals(2.0, ctx.getValue("a5")); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xslf/geom/TestPresetGeometries.java b/src/ooxml/testcases/org/apache/poi/xslf/geom/TestPresetGeometries.java new file mode 100644 index 0000000000..5c19b4e53e --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xslf/geom/TestPresetGeometries.java @@ -0,0 +1,39 @@ +package org.apache.poi.xslf.geom; + +import junit.framework.TestCase; +import org.apache.poi.xslf.model.geom.*; + +import java.awt.geom.GeneralPath; +import java.awt.geom.Rectangle2D; +import java.util.Map; + +/** + * Date: 10/24/11 + * + * @author Yegor Kozlov + */ +public class TestPresetGeometries extends TestCase { + public void testRead(){ + + Map shapes = PresetGeometries.getInstance(); + assertEquals(186, shapes.size()); + + + for(String name : shapes.keySet()) { + CustomGeometry geom = shapes.get(name); + Context ctx = new Context(geom, new IAdjustableShape() { + public Rectangle2D getAnchor() { + return new Rectangle2D.Double(0, 0, 100, 100); + } + + public Guide getAdjustValue(String name) { + return null; + } + }); + for(Path p : geom){ + GeneralPath path = p.getPath(ctx); + assertNotNull(path); + } + } + } +} diff --git a/src/resources/scratchpad/org/apache/poi/xslf/usermodel/presetShapeDefinitions.xml b/src/resources/scratchpad/org/apache/poi/xslf/usermodel/presetShapeDefinitions.xml index d65e93595b..f5fead717f 100755 --- a/src/resources/scratchpad/org/apache/poi/xslf/usermodel/presetShapeDefinitions.xml +++ b/src/resources/scratchpad/org/apache/poi/xslf/usermodel/presetShapeDefinitions.xml @@ -10875,7 +10875,7 @@ - + @@ -19912,4 +19912,4 @@
- \ No newline at end of file + -- 2.39.5