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