1 /*
   2  * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package test.com.sun.javafx.geom;
  27 
  28 import com.sun.javafx.geom.Arc2D;
  29 import com.sun.javafx.geom.CubicCurve2D;
  30 import com.sun.javafx.geom.Ellipse2D;
  31 import com.sun.javafx.geom.Line2D;
  32 import com.sun.javafx.geom.Path2D;
  33 import com.sun.javafx.geom.QuadCurve2D;
  34 import com.sun.javafx.geom.RoundRectangle2D;
  35 import com.sun.javafx.geom.Shape;
  36 import com.sun.javafx.geom.TransformedShape;
  37 import static junit.framework.Assert.assertEquals;
  38 import com.sun.javafx.geom.transform.BaseTransform;
  39 import org.junit.Test;
  40 
  41 /**
  42  *
  43  */
  44 public class TransformedShapeTest {
  45     // Avoid integer coordinates so that float->double->float roundoff errors
  46     // do not end up causing "failures of questionable value"
  47     static Shape testShapes[] = {
  48         new Arc2D(9.5f, 9.5f, 26.2f, 16.1f, 0, 270, Arc2D.PIE),
  49         new Arc2D(9.5f, 9.5f, 26.2f, 16.1f, 0, 270, Arc2D.OPEN),
  50         new Arc2D(9.5f, 9.5f, 26.2f, 16.1f, 0, 270, Arc2D.CHORD),
  51         new CubicCurve2D(9.5f, 9.5f, 40.5f, 9.5f, 9.5f, 40.5f, 40.5f, 40.5f),
  52         new Ellipse2D(9.5f, 9.5f, 21f, 16f),
  53         new Line2D(9.5f, 9.5f, 40.5f, 40.5f),
  54         makePath(Path2D.WIND_EVEN_ODD),
  55         makePath(Path2D.WIND_NON_ZERO),
  56         new QuadCurve2D(9.5f, 9.5f, 20.5f, 40.5f, 40.5f, 9.5f),
  57         new RoundRectangle2D(9.5f, 9.5f, 21f, 16f, 5f, 5f),
  58     };
  59 
  60     static Shape makePath(int rule) {
  61         Path2D p2d = new Path2D(rule);
  62         p2d.moveTo(9.5f, 9.5f);
  63         p2d.lineTo(20.5f, 9.5f);
  64         p2d.quadTo(20.5f, 30.5f, 40.5f, 40.5f);
  65         p2d.lineTo(9.5f, 40.5f);
  66         p2d.curveTo(30.5f, 30.5f, 20.5f, 10.5f, 40.5f, 10.5f);
  67         p2d.lineTo(9.5f, 20.5f);
  68         p2d.closePath();
  69         return p2d;
  70     }
  71 
  72     static BaseTransform testTransforms[] = {
  73         BaseTransform.getTranslateInstance(5.125, 5.75),
  74         BaseTransform.getRotateInstance(Math.toRadians(45), 25, 25),
  75         BaseTransform.getScaleInstance(0.5, 0.5),
  76         BaseTransform.getScaleInstance(1.75, 1.6),
  77     };
  78 
  79     public @Test void testTranslatedShapes() {
  80         for (Shape s : testShapes) {
  81             test(TransformedShape.translatedShape(s, 5.125, 8.25));
  82             test(TransformedShape.translatedShape(s, -5.25, 8.125));
  83             test(TransformedShape.translatedShape(s, 5.125, -8.25));
  84             test(TransformedShape.translatedShape(s, -5.25, -8.125));
  85         }
  86     }
  87 
  88     public @Test void testTransformedShapes() {
  89         BaseTransform combinedtx = BaseTransform.IDENTITY_TRANSFORM;
  90         for (BaseTransform tx : testTransforms) {
  91             test(tx);
  92             combinedtx = combinedtx.deriveWithConcatenation(tx);
  93             test(combinedtx);
  94         }
  95     }
  96 
  97     static void test(BaseTransform tx) {
  98         for (Shape s : testShapes) {
  99             test(TransformedShape.transformedShape(s, tx));
 100         }
 101     }
 102 
 103     // Number of ulp to hunt around for a good answer for fuzzy testing
 104     static final int FUZZY = 5;
 105 
 106     static void test(TransformedShape s1) {
 107         BaseTransform tx = s1.getTransformNoClone();
 108         Shape raws1 = s1.getDelegateNoClone();
 109         Shape s2 = tx.createTransformedShape(raws1);
 110         for (int y = 0; y < 50; y++) {
 111             for (int x = 0; x < 50; x++) {
 112                 boolean cp1 = s1.contains(x, y);
 113                 boolean cp2 = s2.contains(x, y);
 114                 boolean cr1 = s1.contains(x, y, 1, 1);
 115                 boolean cr2 = s2.contains(x, y, 1, 1);
 116                 boolean ir1 = s1.intersects(x, y, 1, 1);
 117                 boolean ir2 = s2.intersects(x, y, 1, 1);
 118                 boolean cpfail = (cp1 != cp2);
 119                 boolean crfail = (cr1 != cr2);
 120                 boolean irfail = (ir1 != ir2);
 121                 if (cpfail || crfail || irfail) {
 122                     Float ulpx = Math.ulp(x);
 123                     Float ulpy = Math.ulp(y);
 124                     for (int i = -FUZZY; i <= +FUZZY; i++) {
 125                         float fy = y + ulpy * i;
 126                         for (int j = -FUZZY; j <= +FUZZY; j++) {
 127                             float fx = x + ulpx * j;
 128                             cpfail = cpfail && (s1.contains(fx, fy) !=
 129                                                 s2.contains(fx, fy));
 130                             crfail = crfail && (s1.contains(fx, fy, 1, 1) !=
 131                                                 s2.contains(fx, fy, 1, 1));
 132                             irfail = irfail && (s1.intersects(fx, fy, 1, 1) !=
 133                                                 s2.intersects(fx, fy, 1, 1));
 134                         }
 135                     }
 136                     System.err.println("testing: "+raws1+" transformed by "+tx);
 137                          if (cpfail) { assertEquals(cp2, cp1); }
 138                     else if (crfail) { assertEquals(cr2, cr1); }
 139                     else if (irfail) { assertEquals(ir2, ir1); }
 140                     else {
 141                         System.err.println("fuzzy test required for ("+x+", "+y+")");
 142                     }
 143                 }
 144             }
 145         }
 146     }
 147 }