1 /*
   2  * Copyright (c) 2011, 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 com.sun.javafx.css.*;
  29 
  30 import java.io.ByteArrayInputStream;
  31 import java.io.ByteArrayOutputStream;
  32 import java.io.DataInputStream;
  33 import java.io.DataOutputStream;
  34 import java.io.IOException;
  35 import java.util.Arrays;
  36 import java.util.List;
  37 import java.util.Map;
  38 import javafx.css.CssParser;
  39 import javafx.css.Declaration;
  40 import javafx.css.FontFace;
  41 
  42 import javafx.css.ParsedValue;
  43 import javafx.css.ParsedValue;
  44 import javafx.css.Rule;
  45 import javafx.css.RuleShim;
  46 import javafx.css.Stylesheet;
  47 import javafx.scene.paint.Color;
  48 import javafx.scene.paint.LinearGradient;
  49 import javafx.scene.paint.Paint;
  50 import javafx.scene.paint.Stop;
  51 import javafx.scene.text.Font;
  52 import javafx.util.Duration;
  53 import org.junit.Test;
  54 import static org.junit.Assert.*;
  55 
  56 
  57 public class CssParserTest {
  58 
  59     @Test
  60     public void testRT_16959() {
  61 
  62         CssParser instance = new CssParser();
  63 
  64         // RT-16959 is an infinite loop on incomplete linear gradient
  65         ParsedValue result = instance.parseExpr("-fx-background-color", "linear-gradient(from 0% 0% to 0% 100%, )");
  66         assertNull("parseExpr", result);
  67 
  68         // The bad syntax should be skipped. The stylesheet should have one
  69         // linear gradient with colors red, white, blue.
  70         Stylesheet ss = instance.parse(
  71             "* { "
  72             +   "-fx-background-color: linear-gradient(from 0% 0% to 0% 100%, ); "
  73             +   "-fx-background-color: linear-gradient(from 0% 0% to 0% 100%, red, white, blue); "
  74             + "}"
  75         );
  76 
  77         assertNotNull(ss);
  78         List<Rule> rules = ss.getRules();
  79         assertEquals(1,rules.size(),0);
  80         List<Declaration> decls = RuleShim.getUnobservedDeclarationList(ss.getRules().get(0));
  81         assertTrue(decls.size()==1);
  82         Declaration decl = decls.get(0);
  83         ParsedValue value = decl.getParsedValue();
  84         assertTrue(value != null);
  85 
  86         Paint[] layers = (Paint[])value.convert(null);
  87         assertTrue(layers.length == 1);
  88 
  89         LinearGradient lg = (LinearGradient)layers[0];
  90         List<Stop> stops = lg.getStops();
  91         assertTrue(stops.size()==3);
  92         assertEquals(Color.RED, stops.get(0).getColor());
  93         assertEquals(Color.WHITE, stops.get(1).getColor());
  94         assertEquals(Color.BLUE, stops.get(2).getColor());
  95 
  96     }
  97 
  98 
  99     @Test
 100     public void testRT_17770() {
 101 
 102         // RT-17770 is an infinite loop on a dangling comma.
 103         // Missing term should be ignored
 104         String stylesheetText =
 105             "* {"
 106             +   "-fx-background-color: linear-gradient( "
 107             +   "to right, "
 108             +   "rgba(141, 138, 125, 0.0), "
 109             +   "rgba(248, 248, 246, 0.3) 45%, "
 110             +   "rgba(248, 248, 246, 0.8) 50%, "
 111             +   "rgba(248, 248, 246, 0.3) 55%, "
 112             +   "rgba(141, 138, 125, 0.0), "
 113             +   "); "
 114             + "}";
 115 
 116         CssParser instance = new CssParser();
 117 
 118         Stylesheet ss = instance.parse(stylesheetText);
 119 
 120         assertNotNull(ss);
 121         List<Rule> rules = ss.getRules();
 122         assertEquals(1,rules.size(),0);
 123         List<Declaration> decls = RuleShim.getUnobservedDeclarationList(ss.getRules().get(0));
 124         assertTrue(decls.size()==1);
 125         Declaration decl = decls.get(0);
 126         ParsedValue value = decl.getParsedValue();
 127         assertTrue(value != null);
 128 
 129         Paint[] layers = (Paint[])value.convert(null);
 130         assertTrue(layers.length == 1);
 131 
 132         LinearGradient lg = (LinearGradient)layers[0];
 133         List<Stop> stops = lg.getStops();
 134         assertTrue(stops.size()==5);
 135         assertEquals(Color.rgb(141, 138, 125, 0.0), stops.get(0).getColor());
 136         assertEquals(Color.rgb(248, 248, 246, 0.3), stops.get(1).getColor());
 137         assertEquals(Color.rgb(248, 248, 246, 0.8), stops.get(2).getColor());
 138         assertEquals(Color.rgb(248, 248, 246, 0.3), stops.get(3).getColor());
 139         assertEquals(Color.rgb(141, 138, 125, 0.0), stops.get(4).getColor());
 140 
 141     }
 142 
 143     @Test
 144     public void testParseSizeWithInvalidDigits() {
 145 
 146         CssParser instance = new CssParser();
 147 
 148         // RT-16959 is an infinite loop on incomplete linear gradient
 149         ParsedValue result = instance.parseExpr("-fx-font-size", "10ptx");
 150         assertNull("parseExpr", result);
 151 
 152         // The bad syntax should be skipped.
 153         Stylesheet ss = instance.parse(
 154             "* {"
 155             +  "-fx-font-size: 10ptx; "
 156             +  "-fx-font-size: 12px; "
 157             + "}"
 158         );
 159 
 160         assertNotNull(ss);
 161         List<Rule> rules = ss.getRules();
 162         assertEquals(1,rules.size(),0);
 163         List<Declaration> decls = RuleShim.getUnobservedDeclarationList(ss.getRules().get(0));
 164         assertTrue(decls.size()==1);
 165         Declaration decl = decls.get(0);
 166         ParsedValue value = decl.getParsedValue();
 167         assertTrue(value != null);
 168 
 169         Double size = (Double)value.convert(Font.font("Amble", 12));
 170         assertTrue(Double.compare(size, 12) == 0);
 171     }
 172 
 173 
 174     @Test
 175     public void testRT_17830() {
 176 
 177         CssParser instance = new CssParser();
 178 
 179         // The empty declaration should be skipped. The stylesheet should have
 180         // two declarations.
 181         Stylesheet ss = instance.parse(".rt17830 {-fx-fill: red;; -fx-stroke: yellow; }");
 182 
 183         assertNotNull(ss);
 184         List<Rule> rules = ss.getRules();
 185         assertEquals(1,rules.size(),0);
 186         List<Declaration> decls = RuleShim.getUnobservedDeclarationList(ss.getRules().get(0));
 187         assertEquals(2,decls.size(),0);
 188 
 189         Declaration decl = decls.get(0);
 190         ParsedValue value = decl.getParsedValue();
 191         assertTrue(value != null);
 192         Paint paint = (Paint)value.convert(null);
 193         assertEquals(Color.RED, paint);
 194 
 195         decl = decls.get(1);
 196         value = decl.getParsedValue();
 197         assertTrue(value != null);
 198         paint = (Paint)value.convert(null);
 199         assertEquals(Color.YELLOW, paint);
 200     }
 201 
 202     @Test
 203     public void testRT_20311() {
 204 
 205         CssParser instance = new CssParser();
 206 
 207         try {
 208             instance.parse(".rt-20311 {  -fx-background-color:red\n-fx-border-color:black; }");
 209         } catch (Exception e) {
 210             fail(e.toString());
 211         }
 212 
 213     }
 214 
 215     @Test public void testFontFace() {
 216 
 217         // http://fonts.googleapis.com/css?family=Bree+Serif
 218         String css = "@font-face {\n" +
 219             "font-family: 'Bree Serif';\n" +
 220             "font-style: normal;\n" +
 221             "font-weight: 400;\n" +
 222             "src: local('Bree Serif'), local('BreeSerif-Regular'), url(http://themes.googleusercontent.com/static/fonts/breeserif/v2/LQ7WLTaITDg4OSRuOZCps73hpw3pgy2gAi-Ip7WPMi0.woff) format('woff');\n"+
 223         "}";
 224 
 225         Stylesheet stylesheet = new CssParser().parse(css);
 226 
 227         int nFontFaceSrcs = checkFontFace(stylesheet);
 228 
 229         assertEquals(3, nFontFaceSrcs);
 230     }
 231 
 232     @Test public void testFontFaceMoreThanOneSrc() {
 233 
 234         // http://fonts.googleapis.com/css?family=Bree+Serif
 235         String css = "@font-face {\n" +
 236                 "font-family: 'Bree Serif';\n" +
 237                 "font-style: normal;\n" +
 238                 "font-weight: 400;\n" +
 239                 "src: local('Bree Serif'), local('BreeSerif-Regular'), url(http://themes.googleusercontent.com/static/fonts/breeserif/v2/LQ7WLTaITDg4OSRuOZCps73hpw3pgy2gAi-Ip7WPMi0.woff) format('woff'),\n"+
 240                 "     local('Bree Serif'), local('BreeSerif-Regular'), url(http://themes.googleusercontent.com/static/fonts/breeserif/v2/LQ7WLTaITDg4OSRuOZCps73hpw3pgy2gAi-Ip7WPMi0.woff) format('woff');\n"+
 241                 "}";
 242 
 243         Stylesheet stylesheet = new CssParser().parse(css);
 244 
 245         int nFontFaceSrcs = checkFontFace(stylesheet);
 246         assertEquals(6, nFontFaceSrcs);
 247     }
 248 
 249     public static int checkFontFace(Stylesheet stylesheet) {
 250 
 251         List<FontFace> fontFaces = stylesheet.getFontFaces();
 252         assertNotNull(fontFaces);
 253         assertEquals(1, fontFaces.size());
 254 
 255         FontFaceImpl fontFace = (FontFaceImpl)fontFaces.get(0);
 256 
 257         Map<String,String> descriptors = fontFace.getDescriptors();
 258         assertEquals("'Bree Serif'", descriptors.get("font-family"));
 259         assertEquals("normal", descriptors.get("font-style"));
 260         assertEquals("400", descriptors.get("font-weight"));
 261 
 262         List<FontFaceImpl.FontFaceSrc> fontFaceSrcs = fontFace.getSources();
 263 
 264         int nFontFaceSrcs = fontFaceSrcs != null ? fontFaceSrcs.size() : 0;
 265 
 266         for(int n=0; n<nFontFaceSrcs; n++) {
 267             FontFaceImpl.FontFaceSrc fontFaceSrc = fontFaceSrcs.get(n);
 268             FontFaceImpl.FontFaceSrcType type = fontFaceSrc.getType();
 269             switch(type) {
 270                 case LOCAL: {
 271                     String src = fontFaceSrc.getSrc();
 272                     assertTrue("Bree Serif".equals(src) || "BreeSerif-Regular".equals(src));
 273                     assertNull(fontFaceSrc.getFormat());
 274                     break;
 275                 }
 276                 case URL: {
 277                     String src = fontFaceSrc.getSrc();
 278                     assertEquals(src, "http://themes.googleusercontent.com/static/fonts/breeserif/v2/LQ7WLTaITDg4OSRuOZCps73hpw3pgy2gAi-Ip7WPMi0.woff");
 279                     assertEquals(fontFaceSrc.getFormat(), "woff");
 280                     break;
 281                 }
 282                 case REFERENCE:
 283                 default:
 284                         fail();
 285             }
 286         }
 287 
 288         return nFontFaceSrcs;
 289     }
 290 
 291     @Test public void testRT_32522() {
 292 
 293         ParsedValue value = new CssParser().parseExpr("foo", "1 2em 3 4;");
 294         Object obj = value.convert(Font.font(13));
 295         assert obj instanceof Number[];
 296         assertArrayEquals(new Number[] {1d, 26d, 3d, 4d}, (Number[])obj);
 297 
 298         value = new CssParser().parseExpr("foo", "1;");
 299         obj = value.convert(null);
 300         assert obj instanceof Number;
 301         assertEquals(1d, (Number)obj);
 302 
 303     }
 304 
 305     @Test public void testRT_38483() {
 306 
 307         Duration expected = Duration.millis(42);
 308         ParsedValue value = new CssParser().parseExpr("foo", "42ms;");
 309         Object observed = value.convert(null);
 310         assertEquals(expected, observed);
 311 
 312         value = new CssParser().parseExpr("foo", "indefinite;");
 313         observed = value.convert(null);
 314         assertEquals(Duration.INDEFINITE, observed);
 315     }
 316 }