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