1 /*
   2  * Copyright (c) 2011, 2014, 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.css.converter;
  27 
  28 import javafx.css.Size;
  29 import javafx.css.ParsedValue;
  30 import javafx.css.StyleConverter;
  31 import javafx.scene.effect.BlurType;
  32 import javafx.scene.effect.DropShadow;
  33 import javafx.scene.effect.Effect;
  34 import javafx.scene.effect.InnerShadow;
  35 import javafx.scene.paint.Color;
  36 import javafx.scene.text.Font;
  37 
  38 import java.util.Map;
  39 
  40 /**
  41  * @since 9
  42  */
  43 public class EffectConverter extends StyleConverter<ParsedValue[], Effect> {
  44 
  45     // lazy, thread-safe instatiation
  46     private static class Holder {
  47         static final EffectConverter EFFECT_CONVERTER =
  48                 new EffectConverter();
  49         static final DropShadowConverter DROP_SHADOW_INSTANCE =
  50                 new DropShadowConverter();
  51         static final InnerShadowConverter INNER_SHADOW_INSTANCE =
  52                 new InnerShadowConverter();
  53     }
  54 
  55     public static StyleConverter<ParsedValue[], Effect> getInstance() {
  56         return Holder.EFFECT_CONVERTER;
  57     }
  58     
  59     @Override
  60     public Effect convert(ParsedValue<ParsedValue[], Effect> value, Font font) {
  61         throw new IllegalArgumentException("Parsed value is not an Effect");
  62     }    
  63 
  64     protected EffectConverter() {
  65         super();
  66     }
  67 
  68     @Override
  69     public String toString() {
  70         return "EffectConverter";
  71     }
  72 
  73     public static final class DropShadowConverter extends EffectConverter {
  74 
  75         public static DropShadowConverter getInstance() {
  76             return Holder.DROP_SHADOW_INSTANCE;
  77         }
  78 
  79         private DropShadowConverter() {
  80             super();
  81         }
  82 
  83         // dropshadow( <blur-type> , <color> , <number> , <number> , <number> , <number> )
  84         // <blur-type> = [      gaussian | one-pass-box | three-pass-box | two-pass-box ]
  85         // <color> The shadow Color.
  86         // <number> The radius of the shadow blur kernel. In the range
  87         //          [0.0 ... 127.0], typical value 10.
  88         // <number> he spread of the shadow. The spread is the portion of
  89         //          the radius where the contribution of the source material
  90         //          will be 100%. The remaining portion of the radius will
  91         //          have a contribution controlled by the blur kernel. A
  92         //          spread of 0.0 will result in a distribution of the shadow
  93         //          determined entirely by the blur algorithm. A spread of
  94         //          1.0 will result in a solid growth outward of the source
  95         //          material opacity to the limit of the radius with a very
  96         //          sharp cutoff to transparency at the radius. In the range
  97         //          [0.0 ... 1.0] a value of 0.0 is no spread.
  98         // <number> The shadow offset in the x direction, in pixels.
  99         // <number> The shadow offset in the y direction, in pixels.
 100         @Override
 101         public Effect convert(ParsedValue<ParsedValue[], Effect> value, Font font) {
 102 
 103             Effect effect = super.getCachedValue(value);
 104             if (effect != null) return effect;
 105 
 106             final ParsedValue[] values = value.getValue();
 107             final BlurType blurType = (BlurType) values[0].convert(font);
 108             final Color color = (Color) values[1].convert(font);
 109             final Double radius = ((Size) values[2].convert(font)).pixels(font);
 110             final Double spread = ((Size) values[3].convert(font)).pixels(font);
 111             final Double offsetX = ((Size) values[4].convert(font)).pixels(font);
 112             final Double offsetY = ((Size) values[5].convert(font)).pixels(font);
 113             DropShadow dropShadow = new DropShadow();
 114             if (blurType != null) {
 115                 dropShadow.setBlurType(blurType);
 116             }
 117             if (color != null) {
 118                 dropShadow.setColor(color);
 119             }
 120             if (spread != null) {
 121                 dropShadow.setSpread(spread);
 122             }
 123             if (radius != null) {
 124                 dropShadow.setRadius(radius);
 125             }
 126             if (offsetX != null) {
 127                 dropShadow.setOffsetX(offsetX);
 128             }
 129             if (offsetY != null) {
 130                 dropShadow.setOffsetY(offsetY);
 131             }
 132 
 133             super.cacheValue(value, dropShadow);
 134 
 135             return dropShadow;
 136         }
 137 
 138         @Override
 139         public String toString() {
 140             return "DropShadowConverter";
 141         }
 142     }
 143 
 144     public static final class InnerShadowConverter extends EffectConverter {
 145 
 146         public static InnerShadowConverter getInstance() {
 147             return Holder.INNER_SHADOW_INSTANCE;
 148         }
 149 
 150         private InnerShadowConverter() {
 151             super();
 152         }
 153 
 154         // innershadow( <blur-type> , <color> , <number> , <number> , <number> , <number> )
 155         // <blur-type> = [      gaussian | one-pass-box | three-pass-box | two-pass-box ]
 156         // <color> The shadow Color.
 157         // <number> The radius of the shadow blur kernel. In the range
 158         //          [0.0 ... 127.0], typical value 10.
 159         // <number> The choke of the shadow. The choke is the portion of the
 160         //          radius where the contribution of the source material will
 161         //          be 100%. The remaining portion of the radius will have a
 162         //          contribution controlled by the blur kernel. A choke of 0.0
 163         //          will result in a distribution of the shadow determined
 164         //          entirely by the blur algorithm. A choke of 1.0 will result
 165         //          in a solid growth inward of the shadow from the edges to
 166         //          the limit of the radius with a very sharp cutoff to
 167         //          transparency inside the radius. In the range [0.0 ... 1.0]
 168         //          a value of 0.0 is no spread.
 169         // <number> The shadow offset in the x direction, in pixels.
 170         // <number> The shadow offset in the y direction, in pixels.
 171         @Override
 172         public Effect convert(ParsedValue<ParsedValue[], Effect> value, Font font) {
 173 
 174             Effect effect = super.getCachedValue(value);
 175             if (effect != null) return effect;
 176 
 177             final ParsedValue[] values = value.getValue();
 178             final BlurType blurType = (BlurType) values[0].convert(font);
 179             final Color color = (Color) values[1].convert(font);
 180             final Double radius = ((Size) values[2].convert(font)).pixels(font);
 181             final Double choke = ((Size) values[3].convert(font)).pixels(font);
 182             final Double offsetX = ((Size) values[4].convert(font)).pixels(font);
 183             final Double offsetY = ((Size) values[5].convert(font)).pixels(font);
 184             InnerShadow innerShadow = new InnerShadow();
 185             if (blurType != null) {
 186                 innerShadow.setBlurType(blurType);
 187             }
 188             if (color != null) {
 189                 innerShadow.setColor(color);
 190             }
 191             if (radius != null) {
 192                 innerShadow.setRadius(radius);
 193             }
 194             if (choke != null) {
 195                 innerShadow.setChoke(choke);
 196             }
 197             if (offsetX != null) {
 198                 innerShadow.setOffsetX(offsetX);
 199             }
 200             if (offsetY != null) {
 201                 innerShadow.setOffsetY(offsetY);
 202             }
 203 
 204             super.cacheValue(value, innerShadow);
 205 
 206             return innerShadow;
 207         }
 208 
 209         @Override
 210         public String toString() {
 211             return "InnerShadowConverter";
 212         }
 213     }
 214 
 215     private static Map<ParsedValue<ParsedValue[], Effect>, Effect> cache;
 216 
 217     public static void clearCache() { if (cache != null) cache.clear(); }
 218 
 219 }
 220