Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.scene.effect; 027 028import javafx.beans.property.DoubleProperty; 029import javafx.beans.property.DoublePropertyBase; 030import javafx.beans.property.IntegerProperty; 031import javafx.beans.property.IntegerPropertyBase; 032import javafx.beans.property.ObjectProperty; 033import javafx.scene.Node; 034 035import com.sun.javafx.Utils; 036import com.sun.javafx.effect.EffectDirtyBits; 037import com.sun.javafx.effect.EffectUtils; 038import com.sun.javafx.geom.BaseBounds; 039import com.sun.javafx.geom.transform.BaseTransform; 040import com.sun.javafx.scene.BoundsAccessor; 041 042 043/** 044 * A blur effect using a simple box filter kernel, with separately 045 * configurable sizes in both dimensions, and an iteration parameter 046 * that controls the quality of the resulting blur. 047 * 048 * <p> 049 * Example: 050 * <pre><code> 051 * BoxBlur boxBlur = new BoxBlur(); 052 * boxBlur.setWidth(10); 053 * boxBlur.setHeight(3); 054 * boxBlur.setIterations(3); 055 * 056 * Text text = new Text(); 057 * text.setText("Blurry Text!"); 058 * text.setFill(Color.web("0x3b596d")); 059 * text.setFont(Font.font(null, FontWeight.BOLD, 50)); 060 * text.setX(10); 061 * text.setY(50); 062 * text.setEffect(boxBlur); 063 * </pre></code> 064 * <p> 065 * The code above produces the following: 066 * </p> 067 * <p> 068 * <img src="doc-files/boxblur.png"/> 069 * </p> 070 */ 071public class BoxBlur extends Effect { 072 073 /** 074 * Creates a new instance of BoxBlur with default parameters. 075 */ 076 public BoxBlur() {} 077 078 /** 079 * Creates a new instance of BoxBlur with specified width, height and 080 * iterations. 081 * @param width the horizontal dimension of the blur effect 082 * @param height the vertical dimension of the blur effect 083 * @param iterations the number of times to iterate the blur effect to 084 * improve its "quality" or "smoothness" 085 */ 086 public BoxBlur(double width, double height, int iterations) { 087 setWidth(width); 088 setHeight(height); 089 setIterations(iterations); 090 } 091 092 @Override 093 com.sun.scenario.effect.BoxBlur impl_createImpl() { 094 return new com.sun.scenario.effect.BoxBlur(); 095 }; 096 /** 097 * The input for this {@code Effect}. 098 * If set to {@code null}, or left unspecified, a graphical image of 099 * the {@code Node} to which the {@code Effect} is attached will be 100 * used as the input. 101 * @defaultValue null 102 */ 103 private ObjectProperty<Effect> input; 104 105 106 public final void setInput(Effect value) { 107 inputProperty().set(value); 108 } 109 110 public final Effect getInput() { 111 return input == null ? null : input.get(); 112 } 113 114 public final ObjectProperty<Effect> inputProperty() { 115 if (input == null) { 116 input = new EffectInputProperty("input"); 117 } 118 return input; 119 } 120 121 @Override 122 boolean impl_checkChainContains(Effect e) { 123 Effect localInput = getInput(); 124 if (localInput == null) 125 return false; 126 if (localInput == e) 127 return true; 128 return localInput.impl_checkChainContains(e); 129 } 130 131 /** 132 * The horizontal dimension of the blur effect. 133 * The color information for a given pixel will be spread across 134 * a Box of the indicated width centered over the pixel. 135 * Values less than or equal to 1 will not spread the color data 136 * beyond the pixel where it originated from and so will have 137 * no effect. 138 * <pre> 139 * Min: 0.0 140 * Max: 255.0 141 * Default: 5.0 142 * Identity: <1.0 143 * </pre> 144 * @defaultValue 5.0 145 */ 146 private DoubleProperty width; 147 148 149 public final void setWidth(double value) { 150 widthProperty().set(value); 151 } 152 153 public final double getWidth() { 154 return width == null ? 5 : width.get(); 155 } 156 157 public final DoubleProperty widthProperty() { 158 if (width == null) { 159 width = new DoublePropertyBase(5) { 160 161 @Override 162 public void invalidated() { 163 markDirty(EffectDirtyBits.EFFECT_DIRTY); 164 effectBoundsChanged(); 165 } 166 167 @Override 168 public Object getBean() { 169 return BoxBlur.this; 170 } 171 172 @Override 173 public String getName() { 174 return "width"; 175 } 176 }; 177 } 178 return width; 179 } 180 181 /** 182 * The vertical dimension of the blur effect. 183 * The color information for a given pixel will be spread across 184 * a Box of the indicated height centered over the pixel. 185 * Values less than or equal to 1 will not spread the color data 186 * beyond the pixel where it originated from and so will have 187 * no effect. 188 * <pre> 189 * Min: 0.0 190 * Max: 255.0 191 * Default: 5.0 192 * Identity: <1.0 193 * </pre> 194 * @defaultValue 5.0 195 */ 196 private DoubleProperty height; 197 198 199 public final void setHeight(double value) { 200 heightProperty().set(value); 201 } 202 203 public final double getHeight() { 204 return height == null ? 5 : height.get(); 205 } 206 207 public final DoubleProperty heightProperty() { 208 if (height == null) { 209 height = new DoublePropertyBase(5) { 210 211 @Override 212 public void invalidated() { 213 markDirty(EffectDirtyBits.EFFECT_DIRTY); 214 effectBoundsChanged(); 215 } 216 217 @Override 218 public Object getBean() { 219 return BoxBlur.this; 220 } 221 222 @Override 223 public String getName() { 224 return "height"; 225 } 226 }; 227 } 228 return height; 229 } 230 231 /** 232 * The number of times to iterate the blur effect to improve its 233 * "quality" or "smoothness". 234 * Iterating the effect 3 times approximates the quality of a 235 * Gaussian Blur to within 3%. 236 * <pre> 237 * Min: 0 238 * Max: 3 239 * Default: 1 240 * Identity: 0 241 * </pre> 242 * @defaultValue 1 243 */ 244 private IntegerProperty iterations; 245 246 247 public final void setIterations(int value) { 248 iterationsProperty().set(value); 249 } 250 251 public final int getIterations() { 252 return iterations == null ? 1 : iterations.get(); 253 } 254 255 public final IntegerProperty iterationsProperty() { 256 if (iterations == null) { 257 iterations = new IntegerPropertyBase(1) { 258 259 @Override 260 public void invalidated() { 261 markDirty(EffectDirtyBits.EFFECT_DIRTY); 262 effectBoundsChanged(); 263 } 264 265 @Override 266 public Object getBean() { 267 return BoxBlur.this; 268 } 269 270 @Override 271 public String getName() { 272 return "iterations"; 273 } 274 }; 275 } 276 return iterations; 277 } 278 279 private int getClampedWidth() { 280 return Utils.clamp(0, (int) getWidth(), 255); 281 } 282 283 private int getClampedHeight() { 284 return Utils.clamp(0, (int) getHeight(), 255); 285 } 286 287 private int getClampedIterations() { 288 return Utils.clamp(0, getIterations(), 3); 289 } 290 291 @Override 292 void impl_update() { 293 Effect localInput = getInput(); 294 if (localInput != null) { 295 localInput.impl_sync(); 296 } 297 298 com.sun.scenario.effect.BoxBlur peer = 299 (com.sun.scenario.effect.BoxBlur) impl_getImpl(); 300 peer.setInput(localInput == null ? null : localInput.impl_getImpl()); 301 peer.setHorizontalSize(getClampedWidth()); 302 peer.setVerticalSize(getClampedHeight()); 303 peer.setPasses(getClampedIterations()); 304 } 305 306 /** 307 * @treatAsPrivate implementation detail 308 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 309 */ 310 @Deprecated 311 @Override 312 public BaseBounds impl_getBounds(BaseBounds bounds, 313 BaseTransform tx, 314 Node node, 315 BoundsAccessor boundsAccessor) { 316 bounds = EffectUtils.getInputBounds(bounds, 317 BaseTransform.IDENTITY_TRANSFORM, 318 node, boundsAccessor, 319 getInput()); 320 321 int localIterations = getClampedIterations(); 322 323 int hgrow = EffectUtils.getKernelSize(getClampedWidth(), localIterations); 324 int vgrow = EffectUtils.getKernelSize(getClampedHeight(), localIterations); 325 326 bounds = bounds.deriveWithPadding(hgrow, vgrow, 0); 327 328 return EffectUtils.transformBounds(tx, bounds); 329 } 330 331 /** 332 * 333 * @treatAsPrivate implementation detail 334 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 335 */ 336 @Deprecated 337 @Override 338 public Effect impl_copy() { 339 BoxBlur bb = new BoxBlur(this.getWidth(), this.getHeight(), this.getIterations()); 340 bb.setInput(this.getInput()); 341 return bb; 342 } 343}