Author: kiwiwings
Date: Tue May 30 09:33:28 2017
New Revision: 1796823

URL: http://svn.apache.org/viewvc?rev=1796823&view=rev
Log:
Bug 61119 - Fix preset shape rendering and shading

- Fixed conversion of ooxml to awt angle
- replace subclasses and reflection calls with enums
- implemented tinting/shading of preset shapes

Added:
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/BuiltInGuide.java   (with 
props)
Removed:
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/AbsExpression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/AddDivideExpression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/AddSubtractExpression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/ArcTanExpression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/CosExpression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/CosineArcTanExpression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/Expression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/ExpressionParser.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/IfElseExpression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/LiteralValueExpression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/MaxExpression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/MinExpression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/ModExpression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/MultiplyDivideExpression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/PinExpression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/SinArcTanExpression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/SinExpression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/SqrtExpression.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/TanExpression.java
Modified:
    poi/site/src/documentation/content/xdocs/status.xml
    poi/trunk/src/java/org/apache/poi/sl/draw/DrawPaint.java
    poi/trunk/src/java/org/apache/poi/sl/draw/DrawShape.java
    poi/trunk/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/AdjustValue.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/ArcToCommand.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/ClosePathCommand.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/Context.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/CurveToCommand.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/CustomGeometry.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/Formula.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/Guide.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/IAdjustableShape.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/LineToCommand.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/MoveToCommand.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/Outline.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/Path.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/PathCommand.java
    poi/trunk/src/java/org/apache/poi/sl/draw/geom/QuadToCommand.java
    poi/trunk/src/java/org/apache/poi/sl/usermodel/FillStyle.java
    poi/trunk/src/java/org/apache/poi/sl/usermodel/PaintStyle.java
    poi/trunk/src/java/org/apache/poi/sl/usermodel/StrokeStyle.java
    
poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java
    
poi/trunk/src/resources/main/org/apache/poi/sl/draw/geom/presetShapeDefinitions.xml

Modified: poi/site/src/documentation/content/xdocs/status.xml
URL: 
http://svn.apache.org/viewvc/poi/site/src/documentation/content/xdocs/status.xml?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/site/src/documentation/content/xdocs/status.xml (original)
+++ poi/site/src/documentation/content/xdocs/status.xml Tue May 30 09:33:28 2017
@@ -58,6 +58,7 @@
 
     <release version="3.17-beta1" date="2017-07-??">
       <actions>
+        <action dev="PD" type="fix" fixes-bug="61119" module="SL Common">Fix 
preset shape rendering and shading</action>
         <action dev="PD" type="fix" fixes-bug="61059" module="HSSF">Allow 
workbooks to contain more than 32k names</action>
         <action dev="PD" type="fix" fixes-bug="github-55" module="XSSF">Allow 
XSSFNames set with a long name that looks similar to a cell address</action>
         <action dev="PD" type="add" fixes-bug="github-25" module="SXSSF">Add 
lock/unlock sheet protection and tab colors</action>

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/DrawPaint.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/DrawPaint.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/DrawPaint.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/DrawPaint.java Tue May 30 
09:33:28 2017
@@ -33,6 +33,7 @@ import java.io.InputStream;
 import org.apache.poi.sl.usermodel.ColorStyle;
 import org.apache.poi.sl.usermodel.PaintStyle;
 import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint;
+import org.apache.poi.sl.usermodel.PaintStyle.PaintModifier;
 import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
 import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;
 import org.apache.poi.sl.usermodel.PlaceableShape;
@@ -113,8 +114,15 @@ public class DrawPaint {
     }
 
     public Paint getPaint(Graphics2D graphics, PaintStyle paint) {
+        return getPaint(graphics, paint, PaintModifier.NORM);
+    }
+
+    public Paint getPaint(Graphics2D graphics, PaintStyle paint, PaintModifier 
modifier) {
+        if (modifier == PaintModifier.NONE) {
+            return null;
+        }
         if (paint instanceof SolidPaint) {
-            return getSolidPaint((SolidPaint)paint, graphics);
+            return getSolidPaint((SolidPaint)paint, graphics, modifier);
         } else if (paint instanceof GradientPaint) {
             return getGradientPaint((GradientPaint)paint, graphics);
         } else if (paint instanceof TexturePaint) {
@@ -123,8 +131,77 @@ public class DrawPaint {
         return null;
     }
 
-    protected Paint getSolidPaint(SolidPaint fill, Graphics2D graphics) {
-        return applyColorTransform(fill.getSolidColor());
+    protected Paint getSolidPaint(SolidPaint fill, Graphics2D graphics, final 
PaintModifier modifier) {
+        final ColorStyle orig = fill.getSolidColor();
+        ColorStyle cs = new ColorStyle() {
+            @Override
+            public Color getColor() {
+                return orig.getColor();
+            }
+
+            @Override
+            public int getAlpha() {
+                return orig.getAlpha();
+            }
+
+            @Override
+            public int getHueOff() {
+                return orig.getHueOff();
+            }
+
+            @Override
+            public int getHueMod() {
+                return orig.getHueMod();
+            }
+
+            @Override
+            public int getSatOff() {
+                return orig.getSatOff();
+            }
+
+            @Override
+            public int getSatMod() {
+                return orig.getSatMod();
+            }
+
+            @Override
+            public int getLumOff() {
+                return orig.getLumOff();
+            }
+
+            @Override
+            public int getLumMod() {
+                return orig.getLumMod();
+            }
+
+            @Override
+            public int getShade() {
+                int shade = orig.getShade();
+                switch (modifier) {
+                    case DARKEN:
+                        return Math.min(100000, Math.max(0,shade)+40000);
+                    case DARKEN_LESS:
+                        return Math.min(100000, Math.max(0,shade)+20000);
+                    default:
+                        return shade;
+                }
+            }
+
+            @Override
+            public int getTint() {
+                int tint = orig.getTint();
+                switch (modifier) {
+                    case LIGHTEN:
+                        return Math.min(100000, Math.max(0,tint)+40000);
+                    case LIGHTEN_LESS:
+                        return Math.min(100000, Math.max(0,tint)+20000);
+                    default:
+                        return tint;
+                }
+            }
+        };
+
+        return applyColorTransform(cs);
     }
 
     protected Paint getGradientPaint(GradientPaint fill, Graphics2D graphics) {
@@ -272,9 +349,9 @@ public class DrawPaint {
             return;
         }
 
-        double fshade = shade / 100000.d;
+        double shadePct = shade / 100000.;
 
-        hsl[2] *= fshade;
+        hsl[2] *= 1. - shadePct;
     }
 
     /**
@@ -289,16 +366,16 @@ public class DrawPaint {
             return;
         }
 
-        double ftint = tint / 100000.f;
-
-        hsl[2] = hsl[2] * ftint + (100 - ftint*100.);
+        // see 18.8.19 fgColor (Foreground Color)
+        double tintPct = tint / 100000.;
+        hsl[2] = hsl[2]*(1.-tintPct) + (100.-100.*(1.-tintPct));
     }
 
     protected Paint createLinearGradientPaint(GradientPaint fill, Graphics2D 
graphics) {
         // TODO: we need to find the two points for gradient - the problem is, 
which point at the outline
         // do you take? My solution would be to apply the gradient rotation to 
the shape in reverse
         // and then scan the shape for the largest possible horizontal distance
-        
+
         double angle = fill.getGradientAngle();
         if (!fill.isRotatedWithShape()) {
             angle -= shape.getRotation();

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/DrawShape.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/DrawShape.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/DrawShape.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/DrawShape.java Tue May 30 
09:33:28 2017
@@ -48,7 +48,7 @@ public class DrawShape implements Drawab
     protected static boolean isHSLF(Shape<?,?> shape) {
         return 
shape.getClass().getCanonicalName().toLowerCase(Locale.ROOT).contains("hslf");
     }
-    
+
     /**
      * Apply 2-D transforms before drawing this shape. This includes rotation 
and flipping.
      *
@@ -184,16 +184,16 @@ public class DrawShape implements Drawab
         }
 
         AffineTransform tx = 
(AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM);
-        if(tx != null) {
+        if(tx != null && !tx.isIdentity()) {
             anchor = tx.createTransformedShape(anchor).getBounds2D();
         }
         return anchor;
     }
-    
+
     protected Shape<?,?> getShape() {
         return shape;
     }
-    
+
     protected static BasicStroke getStroke(StrokeStyle strokeStyle) {
         float lineWidth = (float) strokeStyle.getLineWidth();
         if (lineWidth == 0.0f) {

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java Tue May 30 
09:33:28 2017
@@ -57,7 +57,7 @@ import org.apache.poi.util.Units;
 
 
 public class DrawSimpleShape extends DrawShape {
-    
+
     private static final double DECO_SIZE_POW = 1.5d;
 
     public DrawSimpleShape(SimpleShape<?,?> shape) {
@@ -79,12 +79,15 @@ public class DrawSimpleShape extends Dra
 
         // then fill the shape interior
         if (fill != null) {
-            graphics.setPaint(fill);
             for (Outline o : elems) {
                 if (o.getPath().isFilled()){
-                    java.awt.Shape s = o.getOutline();
-                    graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s);
-                    graphics.fill(s);
+                    Paint fillMod = drawPaint.getPaint(graphics, 
getShape().getFillStyle().getPaint(), o.getPath().getFill());
+                    if (fillMod != null) {
+                        graphics.setPaint(fillMod);
+                        java.awt.Shape s = o.getOutline();
+                        graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s);
+                        graphics.fill(s);
+                    }
                 }
             }
         }
@@ -105,7 +108,7 @@ public class DrawSimpleShape extends Dra
             }
         }
 
-        // draw line decorations
+               // draw line decorations
         drawDecoration(graphics, line, stroke);
     }
 
@@ -378,7 +381,7 @@ public class DrawSimpleShape extends Dra
 
                     presets.put(cusName, new CustomGeometry(cusGeom));
                 }
-                
+
                 staxFiltRd.close();
                 staxReader.close();
             } catch (Exception e) {
@@ -392,43 +395,40 @@ public class DrawSimpleShape extends Dra
     }
 
     protected Collection<Outline> computeOutlines(Graphics2D graphics) {
+        final SimpleShape<?,?> sh = getShape();
 
         List<Outline> lst = new ArrayList<Outline>();
-        CustomGeometry geom = getShape().getGeometry();
+        CustomGeometry geom = sh.getGeometry();
         if(geom == null) {
             return lst;
         }
 
-        Rectangle2D anchor = getAnchor(graphics, getShape());
+        Rectangle2D anchor = getAnchor(graphics, sh);
         for (Path p : geom) {
 
-            double w = p.getW() == -1 ? anchor.getWidth() * 
Units.EMU_PER_POINT : p.getW();
-            double h = p.getH() == -1 ? anchor.getHeight() * 
Units.EMU_PER_POINT : p.getH();
+            double w = p.getW(), h = p.getH(), scaleX = Units.toPoints(1), 
scaleY = scaleX;
+            if (w == -1) {
+                w = Units.toEMU(anchor.getWidth());
+            } else {
+                scaleX = anchor.getWidth() / w;
+            }
+            if (h == -1) {
+                h = Units.toEMU(anchor.getHeight());
+            } else {
+                scaleY = anchor.getHeight() / h;
+            }
 
             // the guides in the shape definitions are all defined relative to 
each other,
             // so we build the path starting from (0,0).
             final Rectangle2D pathAnchor = new Rectangle2D.Double(0,0,w,h);
 
-            Context ctx = new Context(geom, pathAnchor, getShape());
+            Context ctx = new Context(geom, pathAnchor, sh);
 
             java.awt.Shape gp = p.getPath(ctx);
 
             // translate the result to the canvas coordinates in points
             AffineTransform at = new AffineTransform();
             at.translate(anchor.getX(), anchor.getY());
-
-            double scaleX, scaleY;
-            if (p.getW() != -1) {
-                scaleX = anchor.getWidth() / p.getW();
-            } else {
-                scaleX = 1.0 / Units.EMU_PER_POINT;
-            }
-            if (p.getH() != -1) {
-                scaleY = anchor.getHeight() / p.getH();
-            } else {
-                scaleY = 1.0 / Units.EMU_PER_POINT;
-            }
-
             at.scale(scaleX, scaleY);
 
             java.awt.Shape canvasShape = at.createTransformedShape(gp);

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/geom/AdjustValue.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/geom/AdjustValue.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/geom/AdjustValue.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/geom/AdjustValue.java Tue May 30 
09:33:28 2017
@@ -23,8 +23,6 @@ import org.apache.poi.sl.draw.binding.CT
 
 /**
  * Represents a shape adjust values (see section 20.1.9.5 in the spec)
- *
- * @author Yegor Kozlov
  */
 public class AdjustValue extends Guide {
 
@@ -36,10 +34,6 @@ public class AdjustValue extends Guide {
     public double evaluate(Context ctx){
         String name = getName();
         Guide adj = ctx.getAdjustValue(name);
-        if(adj != null) {
-            return adj.evaluate(ctx);
-        }
-        return super.evaluate(ctx);
+        return (adj != null) ? adj.evaluate(ctx) : super.evaluate(ctx);
     }
-
 }

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/geom/ArcToCommand.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/geom/ArcToCommand.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/geom/ArcToCommand.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/geom/ArcToCommand.java Tue May 30 
09:33:28 2017
@@ -19,6 +19,8 @@
 
 package org.apache.poi.sl.draw.geom;
 
+import static org.apache.poi.sl.draw.geom.Formula.OOXML_DEGREE;
+
 import java.awt.geom.Arc2D;
 import java.awt.geom.Path2D;
 import java.awt.geom.Point2D;
@@ -27,42 +29,114 @@ import org.apache.poi.sl.draw.binding.CT
 
 /**
  * ArcTo command within a shape path in DrawingML:
+ * {@code &lt;arcTo wR="wr" hR="hr" stAng="stAng" swAng="swAng"/&gt;}<p>
  *
- * <arcTo wR="wr" hR="hr" stAng="stAng" swAng="swAng"/>
- *
- * Where <code>wr</code> and <code>wh</code> are the height and width radiuses
+ * Where {@code wr} and {@code 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 <code>start</code> angle and <code></>swAng</code> is the 
swing angle
- *
- * @author Yegor Kozlov
+ * stAng is the {@code start} angle and {@code swAng} is the swing angle
  */
 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();
+        hr = arc.getHR();
+        wr = arc.getWR();
+        stAng = arc.getStAng();
+        swAng = arc.getSwAng();
     }
 
+    @Override
     public void execute(Path2D.Double 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;
+        double ooStart = ctx.getValue(stAng) / OOXML_DEGREE;
+        double ooExtent = ctx.getValue(swAng) / OOXML_DEGREE;
+
+        // skew the angles for AWT output
+        double awtStart = convertOoxml2AwtAngle(ooStart, rx, ry);
+        double awtSweep = convertOoxml2AwtAngle(ooStart+ooExtent, rx, 
ry)-awtStart;
+
+        // calculate the inverse angle - taken from the (reversed) preset 
definition
+        double radStart = Math.toRadians(ooStart);
+        double invStart = Math.atan2(rx * Math.sin(radStart), ry * 
Math.cos(radStart));
+
         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));
+        // calculate top/left corner
+        double x0 = pt.getX() - rx * Math.cos(invStart) - rx;
+        double y0 = pt.getY() - ry * Math.sin(invStart) - ry;
 
-        Arc2D arc = new Arc2D.Double(
-                         x0,
-                         y0,
-                         2 * rx, 2 * ry,
-                         -start, -extent, 
-                         Arc2D.OPEN);
+        Arc2D arc = new Arc2D.Double(x0, y0, 2 * rx, 2 * ry, awtStart, 
awtSweep, Arc2D.OPEN);
                path.append(arc, true);
     }
+
+    /**
+     * Arc2D angles are skewed, OOXML aren't ... so we need to unskew them<p>
+     *
+     * Furthermore ooxml angle starts at the X-axis and increases clock-wise,
+     * where as Arc2D api states
+     * "45 degrees always falls on the line from the center of the ellipse to
+     * the upper right corner of the framing rectangle"
+     * so we need to reverse it
+     *
+     * <pre>
+     * AWT:                      OOXML:
+     *            |90/-270                     |270/-90 (16200000)
+     *            |                            |
+     * +/-180-----------0           +/-180-----------0
+     *            |               (10800000)   |
+     *            |270/-90                     |90/-270 (5400000)
+     * </pre>
+     *
+     * @param ooAngle the angle in OOXML units
+     * @param width the half width of the bounding box
+     * @param height the half height of the bounding box
+     *
+     * @return the angle in degrees
+     *
+     * @see <a 
href="http://www.onlinemathe.de/forum/Problem-bei-Winkelberechnungen-einer-Ellipse";>unskew
 angle</a>
+     **/
+    private double convertOoxml2AwtAngle(double ooAngle, double width, double 
height) {
+        double aspect = (height / width);
+        // reverse angle for awt
+        double awtAngle = -ooAngle;
+        // normalize angle, in case it's < -360 or > 360 degrees
+        double awtAngle2 = awtAngle%360.;
+        double awtAngle3 = awtAngle-awtAngle2;
+        // because of tangens nature, the values left [90°-270°] and right 
[270°-90°] of the axis are mirrored/the same
+        // and the result of atan2 need to be justified
+        switch ((int)(awtAngle2 / 90)) {
+            case -3:
+                // -270 to -360
+                awtAngle3 -= 360;
+                awtAngle2 += 360;
+                break;
+            case -2:
+            case -1:
+                // -90 to -270
+                awtAngle3 -= 180;
+                awtAngle2 += 180;
+                break;
+            default:
+            case 0:
+                // -90 to 90
+                break;
+            case 2:
+            case 1:
+                // 90 to 270
+                awtAngle3 += 180;
+                awtAngle2 -= 180;
+                break;
+            case 3:
+                // 270 to 360
+                awtAngle3 += 360;
+                awtAngle2 -= 360;
+                break;
+        }
+
+        // skew
+        awtAngle = 
Math.toDegrees(Math.atan2(Math.tan(Math.toRadians(awtAngle2)), aspect)) + 
awtAngle3;
+        return awtAngle;
+    }
 }

Added: poi/trunk/src/java/org/apache/poi/sl/draw/geom/BuiltInGuide.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/geom/BuiltInGuide.java?rev=1796823&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/geom/BuiltInGuide.java (added)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/geom/BuiltInGuide.java Tue May 30 
09:33:28 2017
@@ -0,0 +1,153 @@
+/*
+ *  ====================================================================
+ *    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.sl.draw.geom;
+
+import java.awt.geom.Rectangle2D;
+
+/* package */ enum BuiltInGuide implements Formula {
+    _3cd4, _3cd8, _5cd8, _7cd8, _b, _cd2, _cd4, _cd8, _hc, _h, _hd2, _hd3, 
_hd4, _hd5, _hd6, _hd8,
+    _l, _ls, _r, _ss, _ssd2, _ssd4, _ssd6, _ssd8, _ssd16, _ssd32, _t, _vc,
+    _w, _wd2, _wd3, _wd4, _wd5, _wd6, _wd8, _wd10, _wd32;
+    
+    public String getName() {
+        return name().substring(1);
+    }
+    
+    @Override
+    public double evaluate(Context ctx) {
+        Rectangle2D anchor = ctx.getShapeAnchor();
+        double height = anchor.getHeight(), width = anchor.getWidth(), ss = 
Math.min(width, height);
+        switch (this) {
+            case _3cd4:
+                // 3 circles div 4: 3 x 360 / 4 = 270
+                return 270 * OOXML_DEGREE;
+            case _3cd8:
+                // 3 circles div 8: 3 x 360 / 8 = 135
+                return 135 * OOXML_DEGREE;
+            case _5cd8:
+                // 5 circles div 8: 5 x 360 / 8 = 225
+                return 225 * OOXML_DEGREE;
+            case _7cd8:
+                // 7 circles div 8: 7 x 360 / 8 = 315
+                return 315 * OOXML_DEGREE;
+            case _t:
+                // top
+                return anchor.getY();
+            case _b:
+                // bottom
+                return anchor.getMaxY();
+            case _l:
+                // left
+                return anchor.getX();
+            case _r:
+                // right
+                return anchor.getMaxX();
+            case _cd2:
+                // circle div 2: 360 / 2 = 180
+                return 180 * OOXML_DEGREE;
+            case _cd4:
+                // circle div 4: 360 / 4 = 90
+                return 90 * OOXML_DEGREE;
+            case _cd8:
+                // circle div 8: 360 / 8 = 45
+                return 45 * OOXML_DEGREE;
+            case _hc:
+                // horizontal center
+                return anchor.getCenterX();
+            case _h:
+                // height
+                return height;
+            case _hd2:
+                // height div 2
+                return height / 2.;
+            case _hd3:
+                // height div 3
+                return height / 3.;
+            case _hd4:
+                // height div 4
+                return height / 4.;
+            case _hd5:
+                // height div 5
+                return height / 5.;
+            case _hd6:
+                // height div 6
+                return height / 6.;
+            case _hd8:
+                // height div 8
+                return height / 8.;
+            case _ls:
+                // long side
+                return Math.max(width, height);
+            case _ss:
+                // short side
+                return ss;
+            case _ssd2:
+                // short side div 2
+                return ss / 2.;
+            case _ssd4:
+                // short side div 4
+                return ss / 4.;
+            case _ssd6:
+                // short side div 6
+                return ss / 6.;
+            case _ssd8:
+                // short side div 8
+                return ss / 8.;
+            case _ssd16:
+                // short side div 16
+                return ss / 16.;
+            case _ssd32:
+                // short side div 32
+                return ss / 32.;
+            case _vc:
+                // vertical center
+                return anchor.getCenterY();
+            case _w:
+                // width
+                return width;
+            case _wd2:
+                // width div 2
+                return width / 2.;
+            case _wd3:
+                // width div 3
+                return width / 3.;
+            case _wd4:
+                // width div 4
+                return width / 4.;
+            case _wd5:
+                // width div 5
+                return width / 5.;
+            case _wd6:
+                // width div 6
+                return width / 6.;
+            case _wd8:
+                // width div 8
+                return width / 8.;
+            case _wd10:
+                // width div 10
+                return width / 10.;
+            case _wd32:
+                // width div 32
+                return width / 32.;
+            default:
+                return 0;
+        }
+    }
+}
\ No newline at end of file

Propchange: poi/trunk/src/java/org/apache/poi/sl/draw/geom/BuiltInGuide.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/geom/ClosePathCommand.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/geom/ClosePathCommand.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/geom/ClosePathCommand.java 
(original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/geom/ClosePathCommand.java Tue 
May 30 09:33:28 2017
@@ -21,16 +21,12 @@ package org.apache.poi.sl.draw.geom;
 
 import java.awt.geom.Path2D;
 
-/**
- * Date: 10/25/11
- *
- * @author Yegor Kozlov
- */
 public class ClosePathCommand implements PathCommand {
 
     ClosePathCommand(){
     }
 
+    @Override
     public void execute(Path2D.Double path, Context ctx){
         path.closePath();
     }

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/geom/Context.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/geom/Context.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/geom/Context.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/geom/Context.java Tue May 30 
09:33:28 2017
@@ -23,11 +23,6 @@ import java.awt.geom.Rectangle2D;
 import java.util.HashMap;
 import java.util.Map;
 
-/**
- * Date: 10/24/11
- *
- * @author Yegor Kozlov
- */
 public class Context {
     final Map<String, Double> _ctx = new HashMap<String, Double>();
     final IAdjustableShape _props;
@@ -36,8 +31,12 @@ public class Context {
     public Context(CustomGeometry geom, Rectangle2D anchor, IAdjustableShape 
props){
         _props = props;
         _anchor = anchor;
-        for(Guide gd : geom.adjusts) evaluate(gd);
-        for(Guide gd : geom.guides) evaluate(gd);
+        for(Guide gd : geom.adjusts) {
+            evaluate(gd);
+        }
+        for(Guide gd : geom.guides) {
+            evaluate(gd);
+        }
     }
 
     public Rectangle2D getShapeAnchor(){
@@ -53,22 +52,19 @@ public class Context {
             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);
+        Double val = _ctx.get(key);
+        // BuiltInGuide throws IllegalArgumentException if key is not defined
+        return (val != null) ? val : evaluate(BuiltInGuide.valueOf("_"+key));
     }
 
     public double evaluate(Formula fmla){
         double result = fmla.evaluate(this);
-        String key = fmla.getName();
-        if(key != null) _ctx.put(key, result);
+        if (fmla instanceof Guide) {
+            String key = ((Guide)fmla).getName();
+            if (key != null) {
+                _ctx.put(key, result);
+            }
+        }
         return result;
     }
 }

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/geom/CurveToCommand.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/geom/CurveToCommand.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/geom/CurveToCommand.java 
(original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/geom/CurveToCommand.java Tue May 
30 09:33:28 2017
@@ -23,23 +23,19 @@ import java.awt.geom.Path2D;
 
 import org.apache.poi.sl.draw.binding.CTAdjPoint2D;
 
-/**
- * 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();
+        arg1 = pt1.getX();
+        arg2 = pt1.getY();
+        arg3 = pt2.getX();
+        arg4 = pt2.getY();
+        arg5 = pt3.getX();
+        arg6 = pt3.getY();
     }
 
+    @Override
     public void execute(Path2D.Double path, Context ctx){
         double x1 = ctx.getValue(arg1);
         double y1 = ctx.getValue(arg2);

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/geom/CustomGeometry.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/geom/CustomGeometry.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/geom/CustomGeometry.java 
(original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/geom/CustomGeometry.java Tue May 
30 09:33:28 2017
@@ -19,19 +19,24 @@
 
 package org.apache.poi.sl.draw.geom;
 
-import java.util.*;
-
-import org.apache.poi.sl.draw.binding.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.poi.sl.draw.binding.CTCustomGeometry2D;
+import org.apache.poi.sl.draw.binding.CTGeomGuide;
+import org.apache.poi.sl.draw.binding.CTGeomGuideList;
+import org.apache.poi.sl.draw.binding.CTGeomRect;
+import org.apache.poi.sl.draw.binding.CTPath2D;
+import org.apache.poi.sl.draw.binding.CTPath2DList;
 
 /**
  * Definition of a custom geometric shape
- *
- * @author Yegor Kozlov
  */
 public class CustomGeometry implements Iterable<Path>{
-    List<Guide> adjusts = new ArrayList<Guide>();
-    List<Guide> guides = new ArrayList<Guide>();
-    List<Path> paths = new ArrayList<Path>();
+    final List<Guide> adjusts = new ArrayList<Guide>();
+    final List<Guide> guides = new ArrayList<Guide>();
+    final List<Path> paths = new ArrayList<Path>();
     Path textBounds;
 
     public CustomGeometry(CTCustomGeometry2D geom) {
@@ -59,24 +64,20 @@ public class CustomGeometry implements I
         CTGeomRect rect = geom.getRect();
         if(rect != null) {
             textBounds = new Path();
-            textBounds.addCommand(
-                    new MoveToCommand(rect.getL().toString(), 
rect.getT().toString()));
-            textBounds.addCommand(
-                    new LineToCommand(rect.getR().toString(), 
rect.getT().toString()));
-            textBounds.addCommand(
-                    new LineToCommand(rect.getR().toString(), 
rect.getB().toString()));
-            textBounds.addCommand(
-                    new LineToCommand(rect.getL().toString(), 
rect.getB().toString()));
-            textBounds.addCommand(
-                    new ClosePathCommand());
+            textBounds.addCommand(new MoveToCommand(rect.getL(), rect.getT()));
+            textBounds.addCommand(new LineToCommand(rect.getR(), rect.getT()));
+            textBounds.addCommand(new LineToCommand(rect.getR(), rect.getB()));
+            textBounds.addCommand(new LineToCommand(rect.getL(), rect.getB()));
+            textBounds.addCommand(new ClosePathCommand());
         }
     }
-    
+
+    @Override
     public Iterator<Path> iterator() {
         return paths.iterator();
     }
 
     public Path getTextBounds(){
-        return textBounds;        
+        return textBounds;
     }
 }

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/geom/Formula.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/geom/Formula.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/geom/Formula.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/geom/Formula.java Tue May 30 
09:33:28 2017
@@ -19,367 +19,16 @@
 
 package org.apache.poi.sl.draw.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
+ * A guide formula in DrawingML.<p>
  *
- * @author Yegor Kozlov
+ * This is a base interface for adjust values, geometric guides and built-in 
guides
  */
-public abstract class Formula {
-
-    String getName(){
-        return null;
-    }
-
-    abstract double evaluate(Context ctx);
-
-    static Map<String, Formula> builtInFormulas = new HashMap<String, 
Formula>();
-    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.;
-            }
-         });
-    }
+public interface Formula {
+    /**
+     * OOXML units are 60000ths of a degree 
+     */
+    double OOXML_DEGREE = 60000;
 
+    double evaluate(Context ctx);
 }

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/geom/Guide.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/geom/Guide.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/geom/Guide.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/geom/Guide.java Tue May 30 
09:33:28 2017
@@ -19,16 +19,31 @@
 
 package org.apache.poi.sl.draw.geom;
 
+import static java.lang.Math.abs;
+import static java.lang.Math.atan2;
+import static java.lang.Math.cos;
+import static java.lang.Math.max;
+import static java.lang.Math.min;
+import static java.lang.Math.sin;
+import static java.lang.Math.sqrt;
+import static java.lang.Math.tan;
+import static java.lang.Math.toDegrees;
+import static java.lang.Math.toRadians;
+
 import org.apache.poi.sl.draw.binding.CTGeomGuide;
 
 /**
- * Date: 10/24/11
- *
- * @author Yegor Kozlov
+ * A simple pattern parser of shape guide formulas in DrawingML
  */
-public class Guide extends Formula {
-    private String name, fmla;
-    private Expression expr;
+public class Guide implements Formula {
+    enum Op {
+        
muldiv,addsub,adddiv,ifelse,val,abs,sqrt,max,min,at2,sin,cos,tan,cat2,sat2,pin,mod;
+    }
+
+    private final String name, fmla;
+    private final Op op;
+    private final String[] operands;
+
 
     public Guide(CTGeomGuide gd) {
         this(gd.getName(), gd.getFmla());
@@ -37,11 +52,11 @@ public class Guide extends Formula {
     public Guide(String nm, String fm){
         name = nm;
         fmla = fm;
-        expr = ExpressionParser.parse(fm);
+        operands = fm.split("\\s+");
+        op = Op.valueOf(operands[0].replace("*", "mul").replace("/", 
"div").replace("+", "add").replace("-", "sub").replace("?:", "ifelse"));
     }
 
-
-    String getName(){
+    public String getName(){
         return name;
     }
 
@@ -50,9 +65,73 @@ public class Guide extends Formula {
     }
 
     @Override
-    public double evaluate(Context ctx){
-        return expr.evaluate(ctx);
+    public double evaluate(Context ctx) {
+        double x = (operands.length > 1) ? ctx.getValue(operands[1]) : 0;
+        double y = (operands.length > 2) ? ctx.getValue(operands[2]) : 0;
+        double z = (operands.length > 3) ? ctx.getValue(operands[3]) : 0;
+        switch (op) {
+            case abs:
+                // Absolute Value Formula
+                return abs(x);
+            case adddiv:
+                // Add Divide Formula
+                return (x + y) / z;
+            case addsub:
+                // Add Subtract Formula
+                return (x + y) - z;
+            case at2:
+                // ArcTan Formula: "at2 x y" = arctan( y / z ) = value of this 
guide
+                return toDegrees(atan2(y, x)) * OOXML_DEGREE;
+            case cos:
+                // Cosine Formula: "cos x y" = (x * cos( y )) = value of this 
guide
+                return x * cos(toRadians(y / OOXML_DEGREE));
+            case cat2:
+                // Cosine ArcTan Formula: "cat2 x y z" = (x * cos(arctan(z / 
y) )) = value of this guide
+                return x*cos(atan2(z, y));
+            case ifelse:
+                // If Else Formula: "?: x y z" = if (x > 0), then y = value of 
this guide,
+                // else z = value of this guide
+                return x > 0 ? y : z;
+            case val:
+                // Literal Value Expression
+                return x;
+            case max:
+                // Maximum Value Formula
+                return max(x, y);
+            case min:
+                // Minimum Value Formula
+                return min(x, y);
+            case mod:
+                // Modulo Formula: "mod x y z" = sqrt(x^2 + b^2 + c^2) = value 
of this guide
+                return sqrt(x*x + y*y + z*z);
+            case muldiv:
+                // Multiply Divide Formula
+                return (x * y) / z;
+            case pin:
+                // Pin To Formula: "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
+                if(y < x) {
+                    return x;
+                } else if (y > z) {
+                    return z;
+                } else {
+                    return y;
+                }
+            case sat2:
+                // Sine ArcTan Formula: "sat2 x y z" = (x*sin(arctan(z / y))) 
= value of this guide
+                return x*sin(atan2(z, y));
+            case sin:
+                // Sine Formula: "sin x y" = (x * sin( y )) = value of this 
guide
+                return x * sin(toRadians(y / OOXML_DEGREE));
+            case sqrt:
+                // Square Root Formula: "sqrt x" = sqrt(x) = value of this 
guide
+                return sqrt(x);
+            case tan:
+                // Tangent Formula: "tan x y" = (x * tan( y )) = value of this 
guide
+                return x * tan(toRadians(y / OOXML_DEGREE));
+            default:
+                return 0;
+        }
     }
-
-
 }

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/geom/IAdjustableShape.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/geom/IAdjustableShape.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/geom/IAdjustableShape.java 
(original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/geom/IAdjustableShape.java Tue 
May 30 09:33:28 2017
@@ -21,11 +21,9 @@ package org.apache.poi.sl.draw.geom;
 
 
 /**
- * A bridge to the consumer application.
+ * A bridge to the consumer application.<p>
  *
  * To get a shape geometry one needs to pass shape bounds and adjust values.
- *
- * @author Yegor Kozlov
  */
 public interface IAdjustableShape {
     /**

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/geom/LineToCommand.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/geom/LineToCommand.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/geom/LineToCommand.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/geom/LineToCommand.java Tue May 
30 09:33:28 2017
@@ -23,17 +23,12 @@ import java.awt.geom.Path2D;
 
 import org.apache.poi.sl.draw.binding.CTAdjPoint2D;
 
-/**
- * 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();
+        arg1 = pt.getX();
+        arg2 = pt.getY();
     }
 
     LineToCommand(String s1, String s2){
@@ -41,6 +36,7 @@ public class LineToCommand implements Pa
         arg2 = s2;
     }
 
+    @Override
     public void execute(Path2D.Double path, Context ctx){
         double x = ctx.getValue(arg1);
         double y = ctx.getValue(arg2);

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/geom/MoveToCommand.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/geom/MoveToCommand.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/geom/MoveToCommand.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/geom/MoveToCommand.java Tue May 
30 09:33:28 2017
@@ -23,17 +23,12 @@ import java.awt.geom.Path2D;
 
 import org.apache.poi.sl.draw.binding.CTAdjPoint2D;
 
-/**
- * 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();
+        arg1 = pt.getX();
+        arg2 = pt.getY();
     }
 
     MoveToCommand(String s1, String s2){
@@ -41,6 +36,7 @@ public class MoveToCommand implements Pa
         arg2 = s2;
     }
 
+    @Override
     public void execute(Path2D.Double path, Context ctx){
         double x = ctx.getValue(arg1);
         double y = ctx.getValue(arg2);

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/geom/Outline.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/geom/Outline.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/geom/Outline.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/geom/Outline.java Tue May 30 
09:33:28 2017
@@ -21,11 +21,6 @@ package org.apache.poi.sl.draw.geom;
 
 import java.awt.Shape;
 
-/**
-* Date: 11/6/11
-*
-* @author Yegor Kozlov
-*/
 public class Outline {
     private Shape shape;
     private Path path;

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/geom/Path.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/geom/Path.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/geom/Path.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/geom/Path.java Tue May 30 
09:33:28 2017
@@ -31,17 +31,17 @@ import org.apache.poi.sl.draw.binding.CT
 import org.apache.poi.sl.draw.binding.CTPath2DLineTo;
 import org.apache.poi.sl.draw.binding.CTPath2DMoveTo;
 import org.apache.poi.sl.draw.binding.CTPath2DQuadBezierTo;
-import org.apache.poi.sl.draw.binding.STPathFillMode;
+import org.apache.poi.sl.usermodel.PaintStyle.PaintModifier;
 
 /**
  * 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<PathCommand> commands;
-    boolean _fill, _stroke;
+    PaintModifier _fill;
+    boolean _stroke;
     long _w, _h;
 
     public Path(){
@@ -52,18 +52,26 @@ public class Path {
         commands = new ArrayList<PathCommand>();
         _w = -1;
         _h = -1;
-        _fill = fill;
+        _fill = (fill) ? PaintModifier.NORM : PaintModifier.NONE;
         _stroke = stroke;
     }
 
     public Path(CTPath2D spPath){
-        _fill = spPath.getFill() != STPathFillMode.NONE;
+        switch (spPath.getFill()) {
+            case NONE: _fill = PaintModifier.NONE; break;
+            case DARKEN: _fill = PaintModifier.DARKEN; break;
+            case DARKEN_LESS: _fill = PaintModifier.DARKEN_LESS; break;
+            case LIGHTEN: _fill = PaintModifier.LIGHTEN; break;
+            case LIGHTEN_LESS: _fill = PaintModifier.LIGHTEN_LESS; break;
+            default:
+            case NORM: _fill = PaintModifier.NORM; break;
+        }
         _stroke = spPath.isStroke();
-        _w = spPath.isSetW() ? spPath.getW() : -1;     
-        _h = spPath.isSetH() ? spPath.getH() : -1;     
-        
+        _w = spPath.isSetW() ? spPath.getW() : -1;
+        _h = spPath.isSetH() ? spPath.getH() : -1;
+
         commands = new ArrayList<PathCommand>();
-        
+
         for(Object ch : spPath.getCloseOrMoveToOrLnTo()){
             if(ch instanceof CTPath2DMoveTo){
                 CTAdjPoint2D pt = ((CTPath2DMoveTo)ch).getPt();
@@ -102,8 +110,9 @@ public class Path {
      */
     public Path2D.Double getPath(Context ctx) {
         Path2D.Double path = new Path2D.Double();
-        for(PathCommand cmd : commands)
+        for(PathCommand cmd : commands) {
             cmd.execute(path, ctx);
+        }
         return path;
     }
 
@@ -112,9 +121,13 @@ public class Path {
     }
 
     public boolean isFilled(){
+        return _fill != PaintModifier.NONE;
+    }
+
+    public PaintModifier getFill() {
         return _fill;
     }
-    
+
     public long getW(){
        return _w;
     }

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/geom/PathCommand.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/geom/PathCommand.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/geom/PathCommand.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/geom/PathCommand.java Tue May 30 
09:33:28 2017
@@ -24,15 +24,12 @@ import java.awt.geom.Path2D;
 /**
  * A path command in DrawingML. One of:
  *
- *  - arcTo
- *  - moveTo
- *  - lineTo
- *  - cubicBezTo
- *  - quadBezTo
- *  - close
- *
- *
- * @author Yegor Kozlov
+ * <li>arcTo
+ * <li>moveTo
+ * <li>lineTo
+ * <li>cubicBezTo
+ * <li>quadBezTo
+ * <li>close
  */
 public interface PathCommand {
     /**

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/geom/QuadToCommand.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/geom/QuadToCommand.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/geom/QuadToCommand.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/geom/QuadToCommand.java Tue May 
30 09:33:28 2017
@@ -23,21 +23,17 @@ import java.awt.geom.Path2D;
 
 import org.apache.poi.sl.draw.binding.CTAdjPoint2D;
 
-/**
- * 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();
+        arg1 = pt1.getX();
+        arg2 = pt1.getY();
+        arg3 = pt2.getX();
+        arg4 = pt2.getY();
     }
 
+    @Override
     public void execute(Path2D.Double path, Context ctx){
         double x1 = ctx.getValue(arg1);
         double y1 = ctx.getValue(arg2);

Modified: poi/trunk/src/java/org/apache/poi/sl/usermodel/FillStyle.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/usermodel/FillStyle.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/usermodel/FillStyle.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/usermodel/FillStyle.java Tue May 30 
09:33:28 2017
@@ -17,6 +17,9 @@
 
 package org.apache.poi.sl.usermodel;
 
+/**
+ * This interface is the counterpart to {@link StrokeStyle} - it's specifies 
the filling of a shape
+ */
 public interface FillStyle {
     PaintStyle getPaint();
 }

Modified: poi/trunk/src/java/org/apache/poi/sl/usermodel/PaintStyle.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/usermodel/PaintStyle.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/usermodel/PaintStyle.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/usermodel/PaintStyle.java Tue May 30 
09:33:28 2017
@@ -22,12 +22,30 @@ import java.io.InputStream;
 
 
 public interface PaintStyle {
+    /**
+     * The PaintStyle can be modified by secondary sources, e.g. the 
attributes in the preset shapes.
+     * These modifications need to be taken into account when the final color 
is determined.
+     */
+    enum PaintModifier {
+        /** don't use any paint/fill */
+        NONE,
+        /** use the paint/filling as-is */
+        NORM,
+        /** lighten the paint/filling */
+        LIGHTEN,
+        /** lighten (... a bit less) the paint/filling */
+        LIGHTEN_LESS,
+        /** darken the paint/filling */
+        DARKEN,
+        /** darken (... a bit less) the paint/filling */
+        DARKEN_LESS;
+    }
 
-    public interface SolidPaint extends PaintStyle {
+    interface SolidPaint extends PaintStyle {
         ColorStyle getSolidColor();
     }
 
-    public interface GradientPaint extends PaintStyle {
+    interface GradientPaint extends PaintStyle {
         enum GradientType { linear, circular, shape }
         
         /**
@@ -40,7 +58,7 @@ public interface PaintStyle {
         GradientType getGradientType();
     }    
     
-    public interface TexturePaint extends PaintStyle {
+    interface TexturePaint extends PaintStyle {
         /**
          * @return the raw image stream
          */

Modified: poi/trunk/src/java/org/apache/poi/sl/usermodel/StrokeStyle.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/usermodel/StrokeStyle.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/usermodel/StrokeStyle.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/usermodel/StrokeStyle.java Tue May 30 
09:33:28 2017
@@ -17,6 +17,9 @@
 
 package org.apache.poi.sl.usermodel;
 
+/**
+ * This interface specifies the line style of a shape
+ */
 public interface StrokeStyle {
     enum LineCap {
         /** Rounded ends */

Modified: 
poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java?rev=1796823&r1=1796822&r2=1796823&view=diff
==============================================================================
--- 
poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java
 (original)
+++ 
poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java
 Tue May 30 09:33:28 2017
@@ -632,8 +632,8 @@ public class TestXSLFTextShape {
         assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign());
         assertEquals("Calibri", r1.getFontFamily());
         assertEquals(12.0, r1.getFontSize(), 0);
-        // TODO calculation of tint is incorrect
-        assertTrue(sameColor(new Color(64,64,64), r1.getFontColor()));
+        // TODO calculation of tint might be incorrect
+        assertTrue(sameColor(new Color(191,191,191), r1.getFontColor()));
 
         XSLFTextShape dt = 
(XSLFTextShape)slide.getPlaceholderByType(STPlaceholderType.INT_DT);
         assertEquals("Friday, October 21, 2011", dt.getText());



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to