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