1 /* 2 * Copyright (c) 2008, 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.scenario.effect; 27 28 import com.sun.javafx.geom.BaseBounds; 29 import com.sun.javafx.geom.DirtyRegionContainer; 30 import com.sun.javafx.geom.DirtyRegionPool; 31 import com.sun.javafx.geom.RectBounds; 32 import com.sun.javafx.geom.Rectangle; 33 import com.sun.javafx.geom.transform.BaseTransform; 34 import com.sun.scenario.effect.impl.Renderer; 35 import com.sun.scenario.effect.impl.state.LinearConvolveKernel; 36 import com.sun.scenario.effect.impl.state.MotionBlurState; 37 38 /** 39 * A motion blur effect using a Gaussian convolution kernel, with a 40 * configurable radius and angle. 41 */ 42 public class MotionBlur extends LinearConvolveCoreEffect { 43 44 private MotionBlurState state = new MotionBlurState(); 45 46 /** 47 * Constructs a new {@code MotionBlur} effect with the default radius 48 * (10.0) and default angle (0.0), using the default input for source 49 * data. 50 * This is a shorthand equivalent to: 51 * <pre> 52 * new MotionBlur(10f, 0f, DefaultInput) 53 * </pre> 54 */ 55 public MotionBlur() { 56 this(10f, 0f, DefaultInput); 57 } 58 59 /** 60 * Constructs a new {@code MotionBlur} effect with the given radius 61 * and angle, using the default input for source data. 62 * This is a shorthand equivalent to: 63 * <pre> 64 * new MotionBlur(radius, angle, DefaultInput) 65 * </pre> 66 * 67 * @param radius the radius of the Gaussian kernel 68 * @param angle the angle of the motion effect, in radians 69 * @throws IllegalArgumentException if {@code radius} is outside the 70 * allowable range 71 */ 72 public MotionBlur(float radius, float angle) { 73 this(radius, angle, DefaultInput); 74 } 75 76 /** 77 * Constructs a new {@code MotionBlur} effect with the given radius 78 * and angle. 79 * 80 * @param radius the radius of the Gaussian kernel 81 * @param angle the angle of the motion effect, in radians 82 * @param input the single input {@code Effect} 83 * @throws IllegalArgumentException if {@code radius} is outside the 84 * allowable range 85 */ 86 public MotionBlur(float radius, float angle, Effect input) { 87 super(input); 88 setRadius(radius); 89 setAngle(angle); 90 } 91 92 @Override 93 LinearConvolveKernel getState() { 94 return state; 95 } 96 97 @Override 98 public AccelType getAccelType(FilterContext fctx) { 99 return Renderer.getRenderer(fctx).getAccelType(); 100 } 101 102 /** 103 * Returns the input for this {@code Effect}. 104 * 105 * @return the input for this {@code Effect} 106 */ 107 public final Effect getInput() { 108 return getInputs().get(0); 109 } 110 111 /** 112 * Sets the input for this {@code Effect} to a specific {@code Effect} 113 * or to the default input if {@code input} is {@code null}. 114 * 115 * @param input the input for this {@code Effect} 116 */ 117 public void setInput(Effect input) { 118 setInput(0, input); 119 } 120 121 /** 122 * Returns the radius of the Gaussian kernel. 123 * 124 * @return the radius of the Gaussian kernel 125 */ 126 public float getRadius() { 127 return state.getRadius(); 128 } 129 130 /** 131 * Sets the radius of the Gaussian kernel. 132 * <pre> 133 * Min: 0.0 134 * Max: 63.0 135 * Default: 10.0 136 * Identity: 0.0 137 * </pre> 138 * 139 * @param radius the radius of the Gaussian kernel 140 * @throws IllegalArgumentException if {@code radius} is outside the 141 * allowable range 142 */ 143 public void setRadius(float radius) { 144 state.setRadius(radius); 145 } 146 147 /** 148 * Returns the angle of the motion effect, in radians. 149 * 150 * @return the angle of the motion effect, in radians 151 */ 152 public float getAngle() { 153 return state.getAngle(); 154 } 155 156 /** 157 * Sets the angle of the motion effect, in radians. 158 * <pre> 159 * Min: n/a 160 * Max: n/a 161 * Default: 0.0 162 * Identity: n/a 163 * </pre> 164 * 165 * @param angle the angle of the motion effect, in radians 166 */ 167 public void setAngle(float angle) { 168 state.setAngle(angle); 169 } 170 171 @Override 172 public BaseBounds getBounds(BaseTransform transform, Effect defaultInput) { 173 BaseBounds r = super.getBounds(null, defaultInput); 174 int hpad = state.getHPad(); 175 int vpad = state.getVPad(); 176 BaseBounds ret = new RectBounds(r.getMinX(), r.getMinY(), r.getMaxX(), r.getMaxY()); 177 ((RectBounds) ret).grow(hpad, vpad); 178 return transformBounds(transform, ret); 179 } 180 181 @Override 182 public Rectangle getResultBounds(BaseTransform transform, 183 Rectangle outputClip, 184 ImageData... inputDatas) 185 { 186 Rectangle r = super.getResultBounds(transform, outputClip, inputDatas); 187 int hpad = state.getHPad(); 188 int vpad = state.getVPad(); 189 Rectangle ret = new Rectangle(r); 190 ret.grow(hpad, vpad); 191 return ret; 192 } 193 194 @Override 195 public boolean reducesOpaquePixels() { 196 if (!state.isNop()) { 197 return true; 198 } 199 final Effect input = getInput(); 200 return input != null && input.reducesOpaquePixels(); 201 } 202 203 @Override 204 public DirtyRegionContainer getDirtyRegions(Effect defaultInput, DirtyRegionPool regionPool) { 205 Effect di = getDefaultedInput(0, defaultInput); 206 DirtyRegionContainer drc = di.getDirtyRegions(defaultInput, regionPool); 207 208 drc.grow(state.getHPad(), state.getVPad()); 209 210 return drc; 211 } 212 }