1 /*
   2  * Copyright (c) 2010, 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;
  27 
  28 import javafx.scene.paint.Color;
  29 import javafx.scene.paint.CycleMethod;
  30 import javafx.scene.paint.LinearGradient;
  31 import javafx.scene.paint.Paint;
  32 import javafx.scene.paint.RadialGradient;
  33 import javafx.scene.paint.Stop;
  34 import javafx.scene.text.Font;
  35 import com.sun.javafx.css.ParsedValueImpl;
  36 import javafx.css.converter.PaintConverter;
  37 import javafx.css.converter.StopConverter;
  38 import org.junit.Test;
  39 import static org.junit.Assert.assertEquals;
  40 
  41 
  42 public class PaintTypeTest {
  43 
  44     public PaintTypeTest() {
  45     }
  46 
  47     final Stop[] stops = new Stop[] {
  48         new Stop(0.0f, Color.WHITE),
  49         new Stop(1.0f, Color.BLACK)
  50     };
  51 
  52     final Paint[] paints = new Paint[] {
  53         Color.rgb(0, 128, 255),
  54         new LinearGradient(0.0f, 0.0f, 1.0f, 1.0f, true, CycleMethod.NO_CYCLE, stops),
  55         new RadialGradient(225, 0.28, 1f, 1f, 5.0f, false, CycleMethod.NO_CYCLE, stops)
  56     };
  57 
  58     ParsedValue<?,Size> sizeVal(float value) {
  59         return new ParsedValueImpl<Size,Size>(new Size(value*100, SizeUnits.PERCENT), null);
  60     }
  61 
  62     ParsedValue<ParsedValue[],Stop> stopValue(Stop stop) {
  63         ParsedValue<?,Size> offset = sizeVal((float)stop.getOffset());
  64         ParsedValue<Color,Color> color = new ParsedValueImpl<Color,Color>(stop.getColor(), null);
  65         ParsedValue[] values = new ParsedValue[] { offset, color };
  66         return new ParsedValueImpl<ParsedValue[],Stop>(values, StopConverter.getInstance());
  67     };
  68 
  69     ParsedValue<ParsedValue[],Paint> linearGradientValues(LinearGradient lg) {
  70         ParsedValue[] values = new ParsedValue[7];
  71         int v = 0;
  72         values[v++] = sizeVal((float) lg.getStartX());
  73         values[v++] = sizeVal((float) lg.getStartY());
  74         values[v++] = sizeVal((float) lg.getEndX());
  75         values[v++] = sizeVal((float) lg.getEndY());
  76         values[v++] = new ParsedValueImpl<CycleMethod,CycleMethod>(lg.getCycleMethod(),null);
  77         values[v++] = stopValue(stops[0]);
  78         values[v++] = stopValue(stops[1]);
  79         return new ParsedValueImpl<ParsedValue[],Paint>(values, PaintConverter.LinearGradientConverter.getInstance());
  80     }
  81 
  82     ParsedValue<ParsedValue[],Paint> radialGradientValues(RadialGradient rg) {
  83         ParsedValue[] values = new ParsedValue[8];
  84         int v = 0;
  85         values[v++] = new ParsedValueImpl<Size,Size>(new Size(rg.getFocusAngle(), SizeUnits.PX), null);
  86         values[v++] = new ParsedValueImpl<Size,Size>(new Size(rg.getFocusDistance(), SizeUnits.PX), null);
  87         values[v++] = sizeVal((float) rg.getCenterX());
  88         values[v++] = sizeVal((float) rg.getCenterY());
  89         values[v++] = new ParsedValueImpl<Size,Size>(new Size(rg.getRadius(), SizeUnits.PX), null);
  90         values[v++] = new ParsedValueImpl<CycleMethod,CycleMethod>(rg.getCycleMethod(),null);
  91         values[v++] = stopValue(stops[0]);
  92         values[v++] = stopValue(stops[1]);
  93         return new ParsedValueImpl<ParsedValue[],Paint>(values, PaintConverter.RadialGradientConverter.getInstance());
  94     }
  95 
  96     final ParsedValue[] paintValues = new ParsedValue[] {
  97         new ParsedValueImpl<Paint,Paint>(paints[0], null),
  98         linearGradientValues((LinearGradient)paints[1]),
  99         radialGradientValues((RadialGradient)paints[2])
 100     };
 101 
 102     /**
 103      * Paint is layered (one value per layer).  &lt;paint&gt; [, &lt;paint&gt;]*.
 104      * In the convert function, the ParsedValue is a ParsedValue for each layer.
 105      * That is, value.getValue() returns a ParsedValue[].
 106      */
 107     ParsedValue<ParsedValue<?,Paint>[],Paint[]> getValue(int nLayers) {
 108         ParsedValue<Paint,Paint>[] layers = new ParsedValue[nLayers];
 109         for (int l=0; l<nLayers; l++) {
 110             layers[l] = paintValues[l % paintValues.length];
 111         }
 112         return new ParsedValueImpl<ParsedValue<?,Paint>[],Paint[]>(layers, PaintConverter.SequenceConverter.getInstance());
 113     }
 114     /**
 115      * Test of convert method, of class PaintType.
 116      */
 117     @Test
 118     public void testConvert() {
 119         //System.out.println("convert");
 120         int nValues = paints.length;
 121         ParsedValue<ParsedValue<?,Paint>[],Paint[]> value = getValue(nValues);
 122         Font font = null;
 123         Paint[] result = value.convert(font);
 124         assertEquals(nValues, result.length);
 125         for(int r=0; r<result.length; r++) {
 126             Paint expResult = paints[r % paints.length];
 127             assertEquals(expResult, result[r]);
 128         }
 129     }
 130 
 131     String[] css;
 132 
 133     Paint[][] expResults;
 134 
 135     // values for top, right, bottom, left
 136     final String[][][] svals = new String[][][] {
 137         { {"#ff0000"} },
 138         { {"#ff0000"}, {"#00ff00"}, {"#0000ff"}, {"#ffffff"} }
 139     };
 140 
 141     public void setup() {
 142         css = new String[svals.length];
 143         expResults = new Paint[svals.length][];
 144         for (int i=0; i<svals.length; i++) {
 145             StringBuilder sbuf = new StringBuilder();
 146             expResults[i] = new Paint[svals[i].length];
 147             for (int j=0; j<svals[i].length; j++) {
 148                 for (int k=0; k<svals[i][j].length; k++) {
 149                     expResults[i][j] = Color.web(svals[i][j][k]);
 150                     sbuf.append(svals[i][j][k]);
 151                     if (k+1 < svals[i][j].length) sbuf.append(' ');
 152                 }
 153 
 154                 if (j+1 < svals[i].length) sbuf.append(", ");
 155             }
 156             css[i] = sbuf.toString();
 157         }
 158     }
 159 
 160     @Test
 161     public void testPaintTypeWithCSS() {
 162         setup();
 163 
 164         for (int i=0; i<css.length; i++) {
 165 
 166             Stylesheet stylesheet =
 167                 new CssParser().parse("* { -fx-border-color: " + css[i] + "; }");
 168 
 169             ParsedValue value = TypeTest.getValueFor(stylesheet, "-fx-border-color");
 170 
 171             Paint[][] paints = (Paint[][])value.convert(Font.getDefault());
 172 
 173             //assertEquals(expResults[i].length,paints.length);
 174 
 175             for(int j=0; j<paints.length; j++) {
 176                 String msg = Integer.toString(i) + "." + Integer.toString(j);
 177                 assertEquals(msg, expResults[i][j], paints[j][0]);
 178             }
 179         }
 180 
 181     }
 182 
 183     @Test
 184     public void testParseRadialGradient() {
 185 
 186         // <radial-gradient> = radial-gradient(
 187         //        [ focus-angle <angle>, ]?
 188         //        [ focus-distance <percentage>, ]?
 189         //        [ center <point>, ]?
 190         //        radius <length>,
 191         //        [ [ repeat | reflect ] ,]?
 192         //        <color-stop>[, <color-stop>]+ )
 193         ParsedValue value = new CssParser().parseExpr("-fx-background-color",
 194                 "radial-gradient(focus-angle 90deg, focus-distance 50%, radius 50, red, green, blue)");
 195         RadialGradient result = (RadialGradient)((Paint[])value.convert(null))[0];
 196         RadialGradient expected = new RadialGradient(90, .5, 0, 0, 50,
 197                 false, CycleMethod.NO_CYCLE,
 198                 new Stop(0, Color.RED),
 199                 new Stop(.5, Color.GREEN),
 200                 new Stop(1.0,Color.BLUE));
 201         assertEquals(expected,result);
 202 
 203         value = new CssParser().parseExpr("-fx-background-color",
 204                 "radial-gradient(focus-angle 1.5708rad, focus-distance 50%, radius 50, red, green, blue)");
 205         result = (RadialGradient)((Paint[])value.convert(null))[0];
 206         assertEquals(expected,result);
 207 
 208         value = new CssParser().parseExpr("-fx-background-color",
 209                 "radial-gradient(center 0% 10%, radius 50%, reflect, red, green, blue)");
 210         result = (RadialGradient)((Paint[])value.convert(null))[0];
 211         expected = new RadialGradient(0, 0, 0, .1, .5,
 212                 true, CycleMethod.REFLECT,
 213                 new Stop(0, Color.RED),
 214                 new Stop(.5, Color.GREEN),
 215                 new Stop(1.0,Color.BLUE));
 216         assertEquals(expected,result);
 217     }
 218 
 219     @Test
 220     public void testParseLinearGradient() {
 221 
 222         // <linear-gradient> = linear-gradient(
 223         //        [ [from <point> to <point>] | [ to <side-or-corner> ] ] ,]? [ [ repeat | reflect ] ,]?
 224         //        <color-stop>[, <color-stop>]+
 225         // )
 226         //
 227         ParsedValue value = new CssParser().parseExpr("-fx-background-color",
 228                 "linear-gradient(to top, red, green, blue)");
 229         LinearGradient result = (LinearGradient)((Paint[])value.convert(null))[0];
 230         LinearGradient expected = new LinearGradient(0, 1, 0, 0,
 231                 true, CycleMethod.NO_CYCLE,
 232                 new Stop(0, Color.RED),
 233                 new Stop(.5, Color.GREEN),
 234                 new Stop(1.0, Color.BLUE));
 235         assertEquals(expected,result);
 236 
 237         value = new CssParser().parseExpr("-fx-background-color",
 238                 "linear-gradient(to bottom, red, green, blue)");
 239         result = (LinearGradient)((Paint[])value.convert(null))[0];
 240         expected = new LinearGradient(0, 0, 0, 1,
 241                 true, CycleMethod.NO_CYCLE,
 242                 new Stop(0, Color.RED),
 243                 new Stop(.5, Color.GREEN),
 244                 new Stop(1.0, Color.BLUE));
 245         assertEquals(expected,result);
 246 
 247         value = new CssParser().parseExpr("-fx-background-color",
 248                 "linear-gradient(to left, red, green, blue)");
 249         result = (LinearGradient)((Paint[])value.convert(null))[0];
 250         expected = new LinearGradient(1, 0, 0, 0,
 251                 true, CycleMethod.NO_CYCLE,
 252                 new Stop(0, Color.RED),
 253                 new Stop(.5, Color.GREEN),
 254                 new Stop(1.0, Color.BLUE));
 255         assertEquals(expected,result);
 256 
 257         value = new CssParser().parseExpr("-fx-background-color",
 258                 "linear-gradient(to right, red, green, blue)");
 259         result = (LinearGradient)((Paint[])value.convert(null))[0];
 260         expected = new LinearGradient(0, 0, 1, 0,
 261                 true, CycleMethod.NO_CYCLE,
 262                 new Stop(0, Color.RED),
 263                 new Stop(.5, Color.GREEN),
 264                 new Stop(1.0, Color.BLUE));
 265         assertEquals(expected,result);
 266 
 267         value = new CssParser().parseExpr("-fx-background-color",
 268                 "linear-gradient(to bottom left, red, green, blue)");
 269         result = (LinearGradient)((Paint[])value.convert(null))[0];
 270         expected = new LinearGradient(1, 0, 0, 1,
 271                 true, CycleMethod.NO_CYCLE,
 272                 new Stop(0, Color.RED),
 273                 new Stop(.5, Color.GREEN),
 274                 new Stop(1.0, Color.BLUE));
 275         assertEquals(expected,result);
 276 
 277         value = new CssParser().parseExpr("-fx-background-color",
 278                 "linear-gradient(to bottom right, red, green, blue)");
 279         result = (LinearGradient)((Paint[])value.convert(null))[0];
 280         expected = new LinearGradient(0, 0, 1, 1,
 281                 true, CycleMethod.NO_CYCLE,
 282                 new Stop(0, Color.RED),
 283                 new Stop(.5, Color.GREEN),
 284                 new Stop(1.0, Color.BLUE));
 285         assertEquals(expected,result);
 286 
 287         value = new CssParser().parseExpr("-fx-background-color",
 288                 "linear-gradient(to top left, red, green, blue)");
 289         result = (LinearGradient)((Paint[])value.convert(null))[0];
 290         expected = new LinearGradient(1, 1, 0, 0,
 291                 true, CycleMethod.NO_CYCLE,
 292                 new Stop(0, Color.RED),
 293                 new Stop(.5, Color.GREEN),
 294                 new Stop(1.0, Color.BLUE));
 295         assertEquals(expected,result);
 296 
 297         value = new CssParser().parseExpr("-fx-background-color",
 298                 "linear-gradient(to top right, red, green, blue)");
 299         result = (LinearGradient)((Paint[])value.convert(null))[0];
 300         expected = new LinearGradient(0, 1, 1, 0,
 301                 true, CycleMethod.NO_CYCLE,
 302                 new Stop(0, Color.RED),
 303                 new Stop(.5, Color.GREEN),
 304                 new Stop(1.0, Color.BLUE));
 305         assertEquals(expected,result);
 306 
 307         value = new CssParser().parseExpr("-fx-background-color",
 308                 "linear-gradient(from 10% 10% to 90% 90%, reflect, red, green, blue)");
 309         result = (LinearGradient)((Paint[])value.convert(null))[0];
 310         expected = new LinearGradient(.1, .1, .9, .9,
 311                 true, CycleMethod.REFLECT,
 312                 new Stop(0, Color.RED),
 313                 new Stop(.5, Color.GREEN),
 314                 new Stop(1.0, Color.BLUE));
 315         assertEquals(expected,result);
 316   }
 317 
 318 }