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.beans.property.ObjectPropertyBase; 032import javafx.scene.Node; 033 034import com.sun.javafx.Utils; 035import com.sun.javafx.effect.EffectDirtyBits; 036import com.sun.javafx.effect.EffectUtils; 037import com.sun.javafx.geom.BaseBounds; 038import com.sun.javafx.geom.RectBounds; 039import com.sun.javafx.geom.transform.BaseTransform; 040import com.sun.javafx.scene.BoundsAccessor; 041import com.sun.scenario.effect.Blend.Mode; 042 043 044/** 045 * An effect that blends the two inputs together using one of the 046 * pre-defined {@link BlendMode}s. 047 * 048 * <p> 049 * Example: 050 * <pre><code> 051 * Blend blend = new Blend(); 052 * blend.setMode(BlendMode.COLOR_BURN); 053 * 054 * ColorInput colorInput = new ColorInput(); 055 * colorInput.setPaint(Color.STEELBLUE); 056 * colorInput.setX(10); 057 * colorInput.setY(10); 058 * colorInput.setWidth(100); 059 * colorInput.setHeight(180); 060 * 061 * blend.setTopInput(colorInput); 062 * 063 * Rectangle rect = new Rectangle(); 064 * rect.setWidth(220); 065 * rect.setHeight(100); 066 * Stop[] stops = new Stop[]{new Stop(0, Color.LIGHTSTEELBLUE), new Stop(1, Color.PALEGREEN)}; 067 * LinearGradient lg = new LinearGradient(0, 0, 0.25, 0.25, true, CycleMethod.REFLECT, stops); 068 * rect.setFill(lg); 069 * 070 * Text text = new Text(); 071 * text.setX(15); 072 * text.setY(65); 073 * text.setFill(Color.PALEVIOLETRED); 074 * text.setText("COLOR_BURN"); 075 * text.setFont(Font.font(null, FontWeight.BOLD, 30)); 076 * 077 * Group g = new Group(); 078 * g.setEffect(blend); 079 * g.getChildren().addAll(rect, text); 080 * </pre></code> 081 * 082 * <p> The code above produces the following: </p> 083 * <p> <img src="doc-files/blend.png"/> </p> 084 */ 085public class Blend extends Effect { 086 087 static private Mode toPGMode(BlendMode mode) { 088 if (mode == null) { 089 return Mode.SRC_OVER; // Default value 090 } else if (mode == BlendMode.SRC_OVER) { 091 return Mode.SRC_OVER; 092 } else if (mode == BlendMode.SRC_ATOP) { 093 return Mode.SRC_ATOP; 094 } else if (mode == BlendMode.ADD) { 095 return Mode.ADD; 096 } else if (mode == BlendMode.MULTIPLY) { 097 return Mode.MULTIPLY; 098 } else if (mode == BlendMode.SCREEN) { 099 return Mode.SCREEN; 100 } else if (mode == BlendMode.OVERLAY) { 101 return Mode.OVERLAY; 102 } else if (mode == BlendMode.DARKEN) { 103 return Mode.DARKEN; 104 } else if (mode == BlendMode.LIGHTEN) { 105 return Mode.LIGHTEN; 106 } else if (mode == BlendMode.COLOR_DODGE) { 107 return Mode.COLOR_DODGE; 108 } else if (mode == BlendMode.COLOR_BURN) { 109 return Mode.COLOR_BURN; 110 } else if (mode == BlendMode.HARD_LIGHT) { 111 return Mode.HARD_LIGHT; 112 } else if (mode == BlendMode.SOFT_LIGHT) { 113 return Mode.SOFT_LIGHT; 114 } else if (mode == BlendMode.DIFFERENCE) { 115 return Mode.DIFFERENCE; 116 } else if (mode == BlendMode.EXCLUSION) { 117 return Mode.EXCLUSION; 118 } else if (mode == BlendMode.RED) { 119 return Mode.RED; 120 } else if (mode == BlendMode.GREEN) { 121 return Mode.GREEN; 122 } else if (mode == BlendMode.BLUE) { 123 return Mode.BLUE; 124 } else { 125 throw new java.lang.AssertionError("Unrecognized blend mode: {mode}"); 126 } 127 } 128 129 /** 130 * Used by Group to convert the FX BlendMode enum value into a Decora value. 131 * @treatAsPrivate implementation detail 132 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 133 */ 134 @Deprecated 135 public static Mode impl_getToolkitMode(BlendMode mode) { 136 return toPGMode(mode); 137 } 138 139 /** 140 * Creates a new instance of Blend with default parameters. 141 */ 142 public Blend() {} 143 144 /** 145 * Creates a new instance of Blend with the specified mode. 146 * @param mode the {@code BlendMode} used to blend the two inputs together 147 */ 148 public Blend(BlendMode mode) { 149 setMode(mode); 150 } 151 152 /** 153 * Creates a new instance of Blend with the specified mode and bottom 154 * and top inputs. 155 * @param mode the {@code BlendMode} used to blend the two inputs together 156 * @param bottomInput the bottom input for this {@code Blend} operation 157 * @param topInput the top input for this {@code Blend} operation 158 */ 159 public Blend(BlendMode mode, Effect bottomInput, Effect topInput) { 160 setMode(mode); 161 setBottomInput(bottomInput); 162 setTopInput(topInput); 163 } 164 165 @Override 166 com.sun.scenario.effect.Blend impl_createImpl() { 167 return new com.sun.scenario.effect.Blend( 168 toPGMode(BlendMode.SRC_OVER), 169 com.sun.scenario.effect.Effect.DefaultInput, 170 com.sun.scenario.effect.Effect.DefaultInput); 171 } 172 173 /** 174 * The {@code BlendMode} used to blend the two inputs together. 175 * <pre> 176 * Min: n/a 177 * Max: n/a 178 * Default: BlendMode.SRC_OVER 179 * Identity: n/a 180 * </pre> 181 * @defaultValue SRC_OVER 182 */ 183 private ObjectProperty<BlendMode> mode; 184 185 186 public final void setMode(BlendMode value) { 187 modeProperty().set(value); 188 } 189 190 public final BlendMode getMode() { 191 return mode == null ? BlendMode.SRC_OVER : mode.get(); 192 } 193 194 public final ObjectProperty<BlendMode> modeProperty() { 195 if (mode == null) { 196 mode = new ObjectPropertyBase<BlendMode>(BlendMode.SRC_OVER) { 197 198 @Override 199 public void invalidated() { 200 markDirty(EffectDirtyBits.EFFECT_DIRTY); 201 } 202 203 @Override 204 public Object getBean() { 205 return Blend.this; 206 } 207 208 @Override 209 public String getName() { 210 return "mode"; 211 } 212 }; 213 } 214 return mode; 215 } 216 217 /** 218 * The opacity value, which is modulated with the top input prior 219 * to blending. 220 * <pre> 221 * Min: 0.0 222 * Max: 1.0 223 * Default: 1.0 224 * Identity: 1.0 225 * </pre> 226 * @defaultValue 1.0 227 */ 228 private DoubleProperty opacity; 229 230 231 public final void setOpacity(double value) { 232 opacityProperty().set(value); 233 } 234 235 public final double getOpacity() { 236 return opacity == null ? 1 : opacity.get(); 237 } 238 239 public final DoubleProperty opacityProperty() { 240 if (opacity == null) { 241 opacity = new DoublePropertyBase(1) { 242 243 @Override 244 public void invalidated() { 245 markDirty(EffectDirtyBits.EFFECT_DIRTY); 246 } 247 248 @Override 249 public Object getBean() { 250 return Blend.this; 251 } 252 253 @Override 254 public String getName() { 255 return "opacity"; 256 } 257 }; 258 } 259 return opacity; 260 } 261 262 /** 263 * The bottom input for this {@code Blend} operation. 264 * If set to {@code null}, or left unspecified, a graphical image of 265 * the {@code Node} to which the {@code Effect} is attached will be 266 * used as the input. 267 * @defaultValue null 268 */ 269 private ObjectProperty<Effect> bottomInput; 270 271 272 public final void setBottomInput(Effect value) { 273 bottomInputProperty().set(value); 274 } 275 276 public final Effect getBottomInput() { 277 return bottomInput == null ? null : bottomInput.get(); 278 } 279 280 public final ObjectProperty<Effect> bottomInputProperty() { 281 if (bottomInput == null) { 282 bottomInput = new EffectInputProperty("bottomInput"); 283 } 284 return bottomInput; 285 } 286 287 /** 288 * The top input for this {@code Blend} operation. 289 * If set to {@code null}, or left unspecified, a graphical image of 290 * the {@code Node} to which the {@code Effect} is attached will be 291 * used as the input. 292 * @defaultValue null 293 */ 294 private ObjectProperty<Effect> topInput; 295 296 297 public final void setTopInput(Effect value) { 298 topInputProperty().set(value); 299 } 300 301 public final Effect getTopInput() { 302 return topInput == null ? null : topInput.get(); 303 } 304 305 public final ObjectProperty<Effect> topInputProperty() { 306 if (topInput == null) { 307 topInput = new EffectInputProperty("topInput"); 308 } 309 return topInput; 310 } 311 312 @Override 313 boolean impl_checkChainContains(Effect e) { 314 Effect localTopInput = getTopInput(); 315 Effect localBottomInput = getBottomInput(); 316 if (localTopInput == e || localBottomInput == e) 317 return true; 318 if (localTopInput != null && localTopInput.impl_checkChainContains(e)) 319 return true; 320 if (localBottomInput != null && localBottomInput.impl_checkChainContains(e)) 321 return true; 322 323 return false; 324 } 325 326 @Override 327 void impl_update() { 328 Effect localBottomInput = getBottomInput(); 329 Effect localTopInput = getTopInput(); 330 331 if (localTopInput != null) { 332 localTopInput.impl_sync(); 333 } 334 if (localBottomInput != null) { 335 localBottomInput.impl_sync(); 336 } 337 338 com.sun.scenario.effect.Blend peer = 339 (com.sun.scenario.effect.Blend) impl_getImpl(); 340 peer.setTopInput(localTopInput == null ? null : localTopInput.impl_getImpl()); 341 peer.setBottomInput(localBottomInput == null ? null : localBottomInput.impl_getImpl()); 342 peer.setOpacity((float)Utils.clamp(0, getOpacity(), 1)); 343 peer.setMode(toPGMode(getMode())); 344 } 345 346 /** 347 * @treatAsPrivate implementation detail 348 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 349 */ 350 @Deprecated 351 @Override 352 public BaseBounds impl_getBounds(BaseBounds bounds, 353 BaseTransform tx, 354 Node node, 355 BoundsAccessor boundsAccessor) { 356 BaseBounds topBounds = new RectBounds(); 357 BaseBounds bottomBounds = new RectBounds(); 358 bottomBounds = EffectUtils.getInputBounds(bottomBounds, tx, 359 node, boundsAccessor, 360 getBottomInput()); 361 topBounds = EffectUtils.getInputBounds(topBounds, tx, 362 node, boundsAccessor, 363 getTopInput()); 364 BaseBounds ret = topBounds.deriveWithUnion(bottomBounds); 365 return ret; 366 } 367 368 /** 369 * 370 * @treatAsPrivate implementation detail 371 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 372 */ 373 @Deprecated 374 @Override 375 public Effect impl_copy() { 376 return new Blend(this.getMode(), this.getBottomInput(), this.getTopInput()); 377 } 378}