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.ObjectProperty; 031import javafx.scene.Node; 032 033import com.sun.javafx.Utils; 034import com.sun.javafx.effect.EffectDirtyBits; 035import com.sun.javafx.effect.EffectUtils; 036import com.sun.javafx.geom.BaseBounds; 037import com.sun.javafx.geom.transform.BaseTransform; 038import com.sun.javafx.scene.BoundsAccessor; 039 040 041/** 042 * A motion blur effect using a Gaussian convolution kernel, with a 043 * configurable radius and angle. 044 * 045 * <p> 046 * Example: 047 * <pre><code> 048 * MotionBlur motionBlur = new MotionBlur(); 049 * motionBlur.setRadius(30); 050 * motionBlur.setAngle(-15.0); 051 * 052 * Text text = new Text(); 053 * text.setX(20.0); 054 * text.setY(100.0); 055 * text.setText("Motion!"); 056 * text.setFill(Color.web("0x3b596d")); 057 * text.setFont(Font.font(null, FontWeight.BOLD, 60)); 058 * text.setEffect(motionBlur); 059 * </pre></code> 060 * <p> 061 * The code above produces the following: 062 * </p> 063 * <p> 064 * <img src="doc-files/motionblur.png"/> 065 * </p> 066 */ 067public class MotionBlur extends Effect { 068 /** 069 * Creates a new instance of MotionBlur with default parameters. 070 */ 071 public MotionBlur() {} 072 073 /** 074 * Creates a new instance of MotionBlur with the specified angle and radius. 075 * @param angle the angle of the motion effect, in degrees 076 * @param radius the radius of the blur kernel 077 */ 078 public MotionBlur(double angle, double radius) { 079 setAngle(angle); 080 setRadius(radius); 081 } 082 083 @Override 084 com.sun.scenario.effect.MotionBlur impl_createImpl() { 085 return new com.sun.scenario.effect.MotionBlur(); 086 }; 087 /** 088 * The input for this {@code Effect}. 089 * If set to {@code null}, or left unspecified, a graphical image of 090 * the {@code Node} to which the {@code Effect} is attached will be 091 * used as the input. 092 * @defaultValue null 093 */ 094 private ObjectProperty<Effect> input; 095 096 097 public final void setInput(Effect value) { 098 inputProperty().set(value); 099 } 100 101 public final Effect getInput() { 102 return input == null ? null : input.get(); 103 } 104 105 public final ObjectProperty<Effect> inputProperty() { 106 if (input == null) { 107 input = new EffectInputProperty("input"); 108 } 109 return input; 110 } 111 112 @Override 113 boolean impl_checkChainContains(Effect e) { 114 Effect localInput = getInput(); 115 if (localInput == null) 116 return false; 117 if (localInput == e) 118 return true; 119 return localInput.impl_checkChainContains(e); 120 } 121 122 /** 123 * The radius of the blur kernel. 124 * <pre> 125 * Min: 0.0 126 * Max: 63.0 127 * Default: 10.0 128 * Identity: 0.0 129 * </pre> 130 * @defaultValue 10.0 131 */ 132 private DoubleProperty radius; 133 134 135 public final void setRadius(double value) { 136 radiusProperty().set(value); 137 } 138 139 public final double getRadius() { 140 return radius == null ? 10 : radius.get(); 141 } 142 143 public final DoubleProperty radiusProperty() { 144 if (radius == null) { 145 radius = new DoublePropertyBase(10) { 146 147 @Override 148 public void invalidated() { 149 markDirty(EffectDirtyBits.EFFECT_DIRTY); 150 effectBoundsChanged(); 151 } 152 153 @Override 154 public Object getBean() { 155 return MotionBlur.this; 156 } 157 158 @Override 159 public String getName() { 160 return "radius"; 161 } 162 }; 163 } 164 return radius; 165 } 166 167 /** 168 * The angle of the motion effect, in degrees. 169 * <pre> 170 * Min: n/a 171 * Max: n/a 172 * Default: 0.0 173 * Identity: n/a 174 * </pre> 175 * @defaultValue 0.0 176 */ 177 private DoubleProperty angle; 178 179 180 public final void setAngle(double value) { 181 angleProperty().set(value); 182 } 183 184 public final double getAngle() { 185 return angle == null ? 0 : angle.get(); 186 } 187 188 public final DoubleProperty angleProperty() { 189 if (angle == null) { 190 angle = new DoublePropertyBase() { 191 192 @Override 193 public void invalidated() { 194 markDirty(EffectDirtyBits.EFFECT_DIRTY); 195 effectBoundsChanged(); 196 } 197 198 @Override 199 public Object getBean() { 200 return MotionBlur.this; 201 } 202 203 @Override 204 public String getName() { 205 return "angle"; 206 } 207 }; 208 } 209 return angle; 210 } 211 212 private float getClampedRadius() { 213 return (float)Utils.clamp(0, getRadius(), 63); 214 } 215 216 @Override 217 void impl_update() { 218 Effect localInput = getInput(); 219 if (localInput != null) { 220 localInput.impl_sync(); 221 } 222 223 com.sun.scenario.effect.MotionBlur peer = 224 (com.sun.scenario.effect.MotionBlur) impl_getImpl(); 225 peer.setInput(localInput == null ? null : localInput.impl_getImpl()); 226 peer.setRadius(getClampedRadius()); 227 peer.setAngle((float)Math.toRadians(getAngle())); 228 } 229 230 private int getHPad() { 231 return (int) Math.ceil(Math.abs(Math.cos(Math.toRadians(getAngle()))) 232 * getClampedRadius()); 233 } 234 235 private int getVPad() { 236 return (int) Math.ceil(Math.abs(Math.sin(Math.toRadians(getAngle()))) 237 * getClampedRadius()); 238 } 239 240 /** 241 * @treatAsPrivate implementation detail 242 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 243 */ 244 @Deprecated 245 @Override 246 public BaseBounds impl_getBounds(BaseBounds bounds, 247 BaseTransform tx, 248 Node node, 249 BoundsAccessor boundsAccessor) { 250 bounds = EffectUtils.getInputBounds(bounds, 251 BaseTransform.IDENTITY_TRANSFORM, 252 node, boundsAccessor, 253 getInput()); 254 255 int hpad = getHPad(); 256 int vpad = getVPad(); 257 bounds = bounds.deriveWithPadding(hpad, vpad, 0); 258 259 return EffectUtils.transformBounds(tx, bounds); 260 } 261 262 /** 263 * 264 * @treatAsPrivate implementation detail 265 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 266 */ 267 @Deprecated 268 @Override 269 public Effect impl_copy() { 270 MotionBlur mb = new MotionBlur(this.getAngle(), this.getRadius()); 271 mb.setInput(mb.getInput()); 272 return mb; 273 274 } 275}