1 /*
   2  * Copyright (c) 2011, 2016, 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.sg.prism;
  27 
  28 import javafx.scene.Group;
  29 import javafx.scene.Node;
  30 import javafx.scene.Scene;
  31 import javafx.scene.shape.Rectangle;
  32 import com.sun.javafx.geom.BaseBounds;
  33 import com.sun.javafx.geom.DirtyRegionContainer;
  34 import com.sun.javafx.geom.DirtyRegionPool;
  35 import com.sun.javafx.geom.RectBounds;
  36 import com.sun.javafx.geom.transform.BaseTransform;
  37 import com.sun.javafx.scene.SceneHelper;
  38 import com.sun.javafx.sg.prism.NGNode;
  39 import com.sun.javafx.sg.prism.NGNode;
  40 import com.sun.scenario.effect.Blend;
  41 import com.sun.scenario.effect.Bloom;
  42 import com.sun.scenario.effect.BoxBlur;
  43 import com.sun.scenario.effect.BoxShadow;
  44 import com.sun.scenario.effect.ColorAdjust;
  45 import com.sun.scenario.effect.Crop;
  46 import com.sun.scenario.effect.DropShadow;
  47 import com.sun.scenario.effect.Effect;
  48 import com.sun.scenario.effect.GaussianBlur;
  49 import com.sun.scenario.effect.GeneralShadow;
  50 import com.sun.scenario.effect.Glow;
  51 import com.sun.scenario.effect.InnerShadow;
  52 import com.sun.scenario.effect.MotionBlur;
  53 import com.sun.scenario.effect.Offset;
  54 import com.sun.scenario.effect.SepiaTone;
  55 import junit.framework.Assert;
  56 import org.junit.Test;
  57 
  58 public class EffectDirtyRegionTest {
  59 
  60     DirtyRegionContainer drc;
  61     DirtyRegionContainer drcExpected;
  62     DirtyRegionPool drp;
  63     Effect effect;
  64     NGNode g1bn;
  65     NGNode gbn;
  66 
  67     @Test
  68     public void dropShadowTest() {
  69         setupTest();
  70 
  71         effect = new DropShadow();
  72 
  73         drc.deriveWithNewRegions(new RectBounds[]
  74             {
  75                 new RectBounds(50, 50, 60, 60)
  76             });
  77         g1bn.setEffect(effect);
  78         g1bn.applyEffect(g1bn.getEffectFilter(), drc, drp);
  79         drcExpected.deriveWithNewRegions(new RectBounds[]
  80             {
  81                 new RectBounds(40, 40, 70, 70)
  82             });
  83         compareResult(drcExpected, drc);
  84 
  85         drc.addDirtyRegion(new RectBounds(70, 70, 80, 80));
  86         gbn.setEffect(effect);
  87         gbn.applyEffect(gbn.getEffectFilter(), drc, drp);
  88         drcExpected.deriveWithNewRegions(new RectBounds[]
  89             {
  90                 new RectBounds(30, 30, 90, 90)
  91             });
  92         compareResult(drcExpected, drc);
  93     }
  94 
  95     @Test
  96     public void colorAdjustTest() {
  97         setupTest();
  98 
  99         effect = new ColorAdjust();
 100 
 101         drc.deriveWithNewRegions(new RectBounds[]
 102             {
 103                 new RectBounds(50, 50, 60, 60)
 104             });
 105         g1bn.setEffect(effect);
 106         g1bn.applyEffect(g1bn.getEffectFilter(), drc, drp);
 107         drcExpected.deriveWithNewRegions(new RectBounds[]
 108             {
 109                 new RectBounds(50, 50, 60, 60)
 110             });
 111         compareResult(drcExpected, drc);
 112 
 113         drc.addDirtyRegion(new RectBounds(70, 70, 80, 80));
 114         gbn.setEffect(effect);
 115         gbn.applyEffect(gbn.getEffectFilter(), drc, drp);
 116         drcExpected.deriveWithNewRegions(new RectBounds[]
 117             {
 118                 new RectBounds(50, 50, 60, 60),
 119                 new RectBounds(70, 70, 80, 80)
 120             });
 121         compareResult(drcExpected, drc);
 122     }
 123 
 124     @Test
 125     public void bloomTest() {
 126         setupTest();
 127 
 128         effect = new Bloom();
 129 
 130         drc.deriveWithNewRegions(new RectBounds[]
 131             {
 132                 new RectBounds(50, 50, 60, 60)
 133             });
 134         g1bn.setEffect(effect);
 135         g1bn.applyEffect(g1bn.getEffectFilter(), drc, drp);
 136         drcExpected.deriveWithNewRegions(new RectBounds[]
 137             {
 138                 new RectBounds(50, 50, 60, 60)
 139             });
 140         compareResult(drcExpected, drc);
 141 
 142         drc.addDirtyRegion(new RectBounds(70, 70, 80, 80));
 143         gbn.setEffect(effect);
 144         gbn.applyEffect(gbn.getEffectFilter(), drc, drp);
 145         drcExpected.deriveWithNewRegions(new RectBounds[]
 146             {
 147                 new RectBounds(50, 50, 80, 80)
 148             });
 149         compareResult(drcExpected, drc);
 150     }
 151 
 152     @Test
 153     public void blendTest() {
 154         setupTest();
 155 
 156         effect = new Blend(Blend.Mode.ADD, new DropShadow(), new ColorAdjust());
 157 
 158         drc.deriveWithNewRegions(new RectBounds[]
 159             {
 160                 new RectBounds(50, 50, 60, 60)
 161             });
 162         g1bn.setEffect(effect);
 163         g1bn.applyEffect(g1bn.getEffectFilter(), drc, drp);
 164         drcExpected.deriveWithNewRegions(new RectBounds[]
 165             {
 166                 new RectBounds(40, 40, 70, 70)
 167             });
 168         compareResult(drcExpected, drc);
 169 
 170         drc.addDirtyRegion(new RectBounds(70, 70, 80, 80));
 171         gbn.setEffect(effect);
 172         gbn.applyEffect(gbn.getEffectFilter(), drc, drp);
 173         drcExpected.deriveWithNewRegions(new RectBounds[]
 174             {
 175                 new RectBounds(30, 30, 90, 90)
 176             });
 177         compareResult(drcExpected, drc);
 178     }
 179 
 180     @Test
 181     public void boxBlurTest() {
 182         setupTest();
 183 
 184         effect = new BoxBlur(10, 5, 3);
 185 
 186         drc.deriveWithNewRegions(new RectBounds[]
 187             {
 188                 new RectBounds(50, 50, 60, 60)
 189             });
 190         g1bn.setEffect(effect);
 191         g1bn.applyEffect(g1bn.getEffectFilter(), drc, drp);
 192         drcExpected.deriveWithNewRegions(new RectBounds[]
 193             {
 194                 new RectBounds(36, 44, 74, 66)
 195             });
 196         compareResult(drcExpected, drc);
 197 
 198         drc.addDirtyRegion(new RectBounds(70, 70, 80, 80));
 199         gbn.setEffect(effect);
 200         gbn.applyEffect(gbn.getEffectFilter(), drc, drp);
 201         drcExpected.deriveWithNewRegions(new RectBounds[]
 202             {
 203                 new RectBounds(22, 38, 88, 72),
 204                 new RectBounds(56, 64, 94, 86)
 205             });
 206         compareResult(drcExpected, drc);
 207     }
 208 
 209     @Test
 210     public void gausianBlurTest() {
 211         setupTest();
 212 
 213         effect = new GaussianBlur(5);
 214 
 215         drc.deriveWithNewRegions(new RectBounds[]
 216             {
 217                 new RectBounds(50, 50, 60, 60)
 218             });
 219         g1bn.setEffect(effect);
 220         g1bn.applyEffect(g1bn.getEffectFilter(), drc, drp);
 221         drcExpected.deriveWithNewRegions(new RectBounds[]
 222             {
 223                 new RectBounds(45, 45, 65, 65)
 224             });
 225         compareResult(drcExpected, drc);
 226 
 227         ((GaussianBlur)effect).setRadius(2);
 228         drc.addDirtyRegion(new RectBounds(70, 70, 80, 80));
 229         gbn.setEffect(effect);
 230         gbn.applyEffect(gbn.getEffectFilter(), drc, drp);
 231         drcExpected.deriveWithNewRegions(new RectBounds[]
 232             {
 233                 new RectBounds(43, 43, 67, 67),
 234                 new RectBounds(68, 68, 82, 82)
 235             });
 236         compareResult(drcExpected, drc);
 237     }
 238 
 239     @Test
 240     public void glowTest() {
 241         setupTest();
 242 
 243         effect = new Glow();
 244 
 245         drc.deriveWithNewRegions(new RectBounds[]
 246             {
 247                 new RectBounds(50, 50, 60, 60)
 248             });
 249         g1bn.setEffect(effect);
 250         g1bn.applyEffect(g1bn.getEffectFilter(), drc, drp);
 251         drcExpected.deriveWithNewRegions(new RectBounds[]
 252             {
 253                 new RectBounds(50, 50, 60, 60)
 254             });
 255         compareResult(drcExpected, drc);
 256 
 257         drc.addDirtyRegion(new RectBounds(70, 70, 80, 80));
 258         gbn.setEffect(effect);
 259         gbn.applyEffect(gbn.getEffectFilter(), drc, drp);
 260         drcExpected.deriveWithNewRegions(new RectBounds[]
 261             {
 262                 new RectBounds(50, 50, 80, 80)
 263             });
 264         compareResult(drcExpected, drc);
 265     }
 266 
 267     @Test
 268     public void innerShadowTest() {
 269         setupTest();
 270 
 271         effect = new InnerShadow();
 272 
 273         drc.deriveWithNewRegions(new RectBounds[]
 274             {
 275                 new RectBounds(50, 50, 60, 60)
 276             });
 277         g1bn.setEffect(effect);
 278         g1bn.applyEffect(g1bn.getEffectFilter(), drc, drp);
 279         drcExpected.deriveWithNewRegions(new RectBounds[]
 280             {
 281                 new RectBounds(40, 40, 70, 70)
 282             });
 283         compareResult(drcExpected, drc);
 284 
 285         drc.addDirtyRegion(new RectBounds(70, 70, 80, 80));
 286         gbn.setEffect(effect);
 287         gbn.applyEffect(gbn.getEffectFilter(), drc, drp);
 288         drcExpected.deriveWithNewRegions(new RectBounds[]
 289             {
 290                 new RectBounds(30, 30, 90, 90)
 291             });
 292         compareResult(drcExpected, drc);
 293     }
 294 
 295     @Test
 296     public void motionBlurTest() {
 297         setupTest();
 298 
 299         effect = new MotionBlur();
 300 
 301         drc.deriveWithNewRegions(new RectBounds[]
 302             {
 303                 new RectBounds(50, 50, 60, 60)
 304             });
 305         g1bn.setEffect(effect);
 306         g1bn.applyEffect(g1bn.getEffectFilter(), drc, drp);
 307         drcExpected.deriveWithNewRegions(new RectBounds[]
 308             {
 309                 new RectBounds(40, 50, 70, 60)
 310             });
 311         compareResult(drcExpected, drc);
 312 
 313         ((MotionBlur)effect).setAngle((float) Math.toRadians(90));
 314         drc.addDirtyRegion(new RectBounds(70, 70, 80, 80));
 315         gbn.setEffect(effect);
 316         gbn.applyEffect(gbn.getEffectFilter(), drc, drp);
 317         drcExpected.deriveWithNewRegions(new RectBounds[]
 318             {
 319                 new RectBounds(39, 40, 71, 70),
 320                 new RectBounds(69, 60, 81, 90)
 321             });
 322         compareResult(drcExpected, drc);
 323     }
 324 
 325     @Test
 326     public void sepiaToneTest() {
 327         setupTest();
 328 
 329         effect = new SepiaTone();
 330 
 331         drc.deriveWithNewRegions(new RectBounds[]
 332             {
 333                 new RectBounds(50, 50, 60, 60)
 334             });
 335         g1bn.setEffect(effect);
 336         g1bn.applyEffect(g1bn.getEffectFilter(), drc, drp);
 337         drcExpected.deriveWithNewRegions(new RectBounds[]
 338             {
 339                 new RectBounds(50, 50, 60, 60)
 340             });
 341         compareResult(drcExpected, drc);
 342 
 343         drc.addDirtyRegion(new RectBounds(70, 70, 80, 80));
 344         gbn.setEffect(effect);
 345         gbn.applyEffect(gbn.getEffectFilter(), drc, drp);
 346         drcExpected.deriveWithNewRegions(new RectBounds[]
 347             {
 348                 new RectBounds(50, 50, 60, 60),
 349                 new RectBounds(70, 70, 80, 80)
 350             });
 351         compareResult(drcExpected, drc);
 352     }
 353 
 354     @Test
 355     public void boxShadowTest() {
 356         setupTest();
 357 
 358         effect = new BoxShadow();
 359         ((BoxShadow) effect).setHorizontalSize(10);
 360 
 361         drc.deriveWithNewRegions(new RectBounds[]
 362             {
 363                 new RectBounds(50, 50, 60, 60)
 364             });
 365         g1bn.setEffect(effect);
 366         g1bn.applyEffect(g1bn.getEffectFilter(), drc, drp);
 367         drcExpected.deriveWithNewRegions(new RectBounds[]
 368             {
 369                 new RectBounds(45, 50, 65, 60)
 370             });
 371         compareResult(drcExpected, drc);
 372 
 373         ((BoxShadow) effect).setHorizontalSize(0);
 374         ((BoxShadow) effect).setVerticalSize(10);
 375         drc.addDirtyRegion(new RectBounds(70, 70, 80, 80));
 376         gbn.setEffect(effect);
 377         gbn.applyEffect(gbn.getEffectFilter(), drc, drp);
 378         drcExpected.deriveWithNewRegions(new RectBounds[]
 379             {
 380                 new RectBounds(45, 45, 65, 65),
 381                 new RectBounds(70, 65, 80, 85)
 382             });
 383         compareResult(drcExpected, drc);
 384     }
 385 
 386     @Test
 387     public void generalShadowTest() {
 388         setupTest();
 389 
 390         effect = new GeneralShadow();
 391 
 392         drc.deriveWithNewRegions(new RectBounds[]
 393             {
 394                 new RectBounds(50, 50, 60, 60)
 395             });
 396         g1bn.setEffect(effect);
 397         g1bn.applyEffect(g1bn.getEffectFilter(), drc, drp);
 398         drcExpected.deriveWithNewRegions(new RectBounds[]
 399             {
 400                 new RectBounds(40, 40, 70, 70)
 401             });
 402         compareResult(drcExpected, drc);
 403 
 404         drc.addDirtyRegion(new RectBounds(70, 70, 80, 80));
 405         gbn.setEffect(effect);
 406         gbn.applyEffect(gbn.getEffectFilter(), drc, drp);
 407         drcExpected.deriveWithNewRegions(new RectBounds[]
 408             {
 409                 new RectBounds(30, 30, 90, 90)
 410             });
 411         compareResult(drcExpected, drc);
 412     }
 413 
 414     @Test
 415     public void cropTest() {
 416         setupTest();
 417 
 418         effect = new Crop(new DropShadow());
 419 
 420         drc.deriveWithNewRegions(new RectBounds[]
 421             {
 422                 new RectBounds(50, 50, 60, 60)
 423             });
 424         g1bn.setEffect(effect);
 425         g1bn.applyEffect(g1bn.getEffectFilter(), drc, drp);
 426         drcExpected.deriveWithNewRegions(new RectBounds[]
 427             {
 428                 new RectBounds(50, 50, 60, 60)
 429             });
 430         compareResult(drcExpected, drc);
 431 
 432         drc.addDirtyRegion(new RectBounds(70, 70, 80, 80));
 433         gbn.setEffect(effect);
 434         gbn.applyEffect(gbn.getEffectFilter(), drc, drp);
 435         drcExpected.deriveWithNewRegions(new RectBounds[]
 436             {
 437                 new RectBounds(50, 50, 80, 80)
 438             });
 439         compareResult(drcExpected, drc);
 440     }
 441 
 442     @Test
 443     public void offsetTest() {
 444         setupTest();
 445 
 446         effect = new Offset(10, -10, new DropShadow());
 447 
 448         drc.deriveWithNewRegions(new RectBounds[]
 449             {
 450                 new RectBounds(50, 50, 60, 60)
 451             });
 452         g1bn.setEffect(effect);
 453         g1bn.applyEffect(g1bn.getEffectFilter(), drc, drp);
 454         drcExpected.deriveWithNewRegions(new RectBounds[]
 455             {
 456                 new RectBounds(50, 30, 80, 60)
 457             });
 458         compareResult(drcExpected, drc);
 459 
 460         drc.addDirtyRegion(new RectBounds(70, 70, 80, 80));
 461         gbn.setEffect(effect);
 462         gbn.applyEffect(gbn.getEffectFilter(), drc, drp);
 463         drcExpected.deriveWithNewRegions(new RectBounds[]
 464             {
 465                 new RectBounds(50, 10, 100, 80)
 466             });
 467         compareResult(drcExpected, drc);
 468     }
 469 
 470     private void setupTest() {
 471         drc = new DirtyRegionContainer(6);
 472         drcExpected = new DirtyRegionContainer(6);
 473         drp = new DirtyRegionPool(4);
 474 
 475         Node g1 = group(new Rectangle(50, 50, 10, 10));
 476         g1bn = getBaseNode(g1);
 477         Node g = group(g1, new Rectangle(70, 70, 10, 10));
 478         gbn = getBaseNode(g);
 479     }
 480 
 481     private void compareResult(DirtyRegionContainer expected, DirtyRegionContainer computed) {
 482         for (int i = 0; i < computed.size(); i++) {
 483             Assert.assertEquals(expected.getDirtyRegion(i), computed.getDirtyRegion(i));
 484         }
 485     }
 486 
 487     public static NGNode getBaseNode(Node n) {
 488         SceneHelper.setAllowPGAccess(true);
 489         // Eeek, this is gross! I have to use reflection to invoke this
 490         // method so that bounds are updated...
 491         try {
 492             java.lang.reflect.Method method = Node.class.getDeclaredMethod("updateBounds");
 493             method.setAccessible(true);
 494             method.invoke(n);
 495         } catch (Exception e) {
 496             throw new RuntimeException("Failed to update bounds", e);
 497         }
 498         n.impl_updatePeer();
 499         NGNode bn = n.impl_getPeer();
 500         SceneHelper.setAllowPGAccess(false);
 501         return bn;
 502     }
 503 
 504     public static Node group(Node... n) {
 505         Group g = new Group(n);
 506         return g;
 507     }
 508 
 509     public static BaseBounds getBounds(Node n, BaseTransform tx) {
 510         NGNode pgn = getBaseNode(n);
 511         return pgn.getContentBounds(new RectBounds(), tx);
 512     }
 513 }