1 /*
   2  * Copyright (c) 2010, 2015, 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 javafx.scene.effect;
  27 
  28 import javafx.beans.property.DoubleProperty;
  29 import javafx.beans.property.DoublePropertyBase;
  30 import javafx.beans.property.ObjectProperty;
  31 import javafx.scene.Node;
  32 
  33 import com.sun.javafx.util.Utils;
  34 import com.sun.javafx.effect.EffectDirtyBits;
  35 import com.sun.javafx.geom.BaseBounds;
  36 import com.sun.javafx.geom.transform.BaseTransform;
  37 import com.sun.javafx.scene.BoundsAccessor;
  38 
  39 
  40 /**
  41  * A high-level effect that makes brighter portions of the input image
  42  * appear to glow, based on a configurable threshold.
  43  *
  44  * <p>
  45  * Example:
  46  * <pre><code>
  47  * Bloom bloom = new Bloom();
  48  * bloom.setThreshold(0.1);
  49  *
  50  * Rectangle rect = new Rectangle();
  51  * rect.setX(10);
  52  * rect.setY(10);
  53  * rect.setWidth(160);
  54  * rect.setHeight(80);
  55  * rect.setFill(Color.DARKSLATEBLUE);
  56  *
  57  * Text text = new Text();
  58  * text.setText("Bloom!");
  59  * text.setFill(Color.ALICEBLUE);
  60  * text.setFont(Font.font(null, FontWeight.BOLD, 40));
  61  * text.setX(25);
  62  * text.setY(65);
  63  * text.setEffect(bloom);
  64  * </pre></code>
  65  *
  66  * <p> The code above produces the following: </p>
  67  * <p>
  68  * <img src="doc-files/bloom.png"/>
  69  * </p>
  70  * @since JavaFX 2.0
  71  */
  72 public class Bloom extends Effect {
  73     /**
  74      * Creates a new instance of Bloom with default parameters.
  75      */
  76     public Bloom() {}
  77 
  78     /**
  79      * Creates a new instance of Bloom with the specified threshold.
  80      * @param threshold the threshold value for the bloom effect
  81      * @since JavaFX 2.1
  82      */
  83     public Bloom(double threshold) {
  84         setThreshold(threshold);
  85     }
  86 
  87     @Override
  88     com.sun.scenario.effect.Bloom impl_createImpl() {
  89         return new com.sun.scenario.effect.Bloom();
  90     };
  91     /**
  92      * The input for this {@code Effect}.
  93      * If set to {@code null}, or left unspecified, a graphical image of
  94      * the {@code Node} to which the {@code Effect} is attached will be
  95      * used as the input.
  96      * @defaultValue null
  97      */
  98     private ObjectProperty<Effect> input;
  99 
 100     public final void setInput(Effect value) {
 101         inputProperty().set(value);
 102     }
 103 
 104     public final Effect getInput() {
 105         return input == null ? null : input.get();
 106     }
 107 
 108     public final ObjectProperty<Effect> inputProperty() {
 109         if (input == null) {
 110             input = new EffectInputProperty("input");
 111         }
 112         return input;
 113     }
 114 
 115     @Override
 116     boolean impl_checkChainContains(Effect e) {
 117         Effect localInput = getInput();
 118         if (localInput == null)
 119             return false;
 120         if (localInput == e)
 121             return true;
 122         return localInput.impl_checkChainContains(e);
 123     }
 124 
 125     /**
 126      * The threshold value controls the minimum luminosity value of
 127      * the pixels that will be made to glow.
 128      * <pre>
 129      *       Min: 0.0
 130      *       Max: 1.0
 131      *   Default: 0.3
 132      *  Identity: n/a
 133      * </pre>
 134      * @defaultValue 0.3
 135      */
 136     private DoubleProperty threshold;
 137 
 138 
 139     public final void setThreshold(double value) {
 140         thresholdProperty().set(value);
 141     }
 142 
 143     public final double getThreshold() {
 144         return threshold == null ? 0.3 : threshold.get();
 145     }
 146 
 147     public final DoubleProperty thresholdProperty() {
 148         if (threshold == null) {
 149             threshold = new DoublePropertyBase(0.3) {
 150 
 151                 @Override
 152                 public void invalidated() {
 153                     markDirty(EffectDirtyBits.EFFECT_DIRTY);
 154                 }
 155 
 156                 @Override
 157                 public Object getBean() {
 158                     return Bloom.this;
 159                 }
 160 
 161                 @Override
 162                 public String getName() {
 163                     return "threshold";
 164                 }
 165             };
 166         }
 167         return threshold;
 168     }
 169 
 170     @Override
 171     void impl_update() {
 172         Effect localInput = getInput();
 173         if (localInput != null) {
 174             localInput.impl_sync();
 175         }
 176 
 177         com.sun.scenario.effect.Bloom peer =
 178                 (com.sun.scenario.effect.Bloom) impl_getImpl();
 179         peer.setInput(localInput == null ? null : localInput.impl_getImpl());
 180         peer.setThreshold((float)Utils.clamp(0, getThreshold(), 1));
 181     }
 182 
 183     /**
 184      * @treatAsPrivate implementation detail
 185      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 186      */
 187     @Deprecated
 188     @Override
 189     public BaseBounds impl_getBounds(BaseBounds bounds,
 190                                      BaseTransform tx,
 191                                      Node node,
 192                                      BoundsAccessor boundsAccessor) {
 193         return getInputBounds(bounds, tx,node, boundsAccessor, getInput());
 194     }
 195 
 196     /**
 197      * @treatAsPrivate implementation detail
 198      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 199      */
 200     @Deprecated
 201     @Override
 202     public Effect impl_copy() {
 203         Bloom b = new Bloom(this.getThreshold());
 204         b.setInput(this.getInput());
 205         return b;
 206     }
 207 }