       1 /*
       2  * Copyright (c) 2011, 2013, 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.Utils;
      29 import com.sun.javafx.css.Size;
      30 import com.sun.javafx.css.StyleConverterImpl;
      31 import java.util.Locale;
      32 import java.util.Map;
      33 import java.util.Map.Entry;
      34 import javafx.css.CssMetaData;
      35 import javafx.css.ParsedValue;
      36 import javafx.css.StyleConverter;
      37 import javafx.css.Styleable;
      38 import javafx.scene.text.Font;
      39 import javafx.scene.text.FontPosture;
      40 import javafx.scene.text.FontWeight;
      41
      42 public final class FontConverter extends StyleConverterImpl<ParsedValue[], Font> {
      43
      44     // lazy, thread-safe instatiation
      45     private static class Holder {
      46         static FontConverter INSTANCE = new FontConverter();
      47     }
      48
      49     public static StyleConverter<ParsedValue[], Font> getInstance() {
      50         return Holder.INSTANCE;
      51     }
      52
      53     private FontConverter() {
      54         super();
      55     }
      56
      57     @Override
      58     public Font convert(ParsedValue<ParsedValue[], Font> value, Font font) {
      59         ParsedValue[] values = value.getValue();
      60         Font aFont = (font != null) ? font : Font.getDefault();
      61         String family = (values[0] != null) ? Utils.stripQuotes((String) values[0].convert(aFont)) : aFont.getFamily();
      62         // if font size is given in terms of percent, then we have to call
      63         // pixels directly in order to pass the multiplier.
      64         double fsize = aFont.getSize();
      65         if (values[1] != null) {
      66             ParsedValue<?, ?> pv = (ParsedValue<?, ?>) values[1].getValue();
      67             Size size = (Size) pv.convert(aFont);
      68             fsize = size.pixels(aFont.getSize(), aFont);
      69         }
      70         FontWeight weight = (values[2] != null) ? (FontWeight) values[2].convert(aFont) : FontWeight.NORMAL;
      71         FontPosture style = (values[3] != null) ? (FontPosture) values[3].convert(aFont) : FontPosture.REGULAR;
      72         Font f = Font.font(family, weight, style, fsize);
      73         return f;
      74     }
      75
      76     @Override
      77     public Font convert(Map<CssMetaData<? extends Styleable, ?>, Object> convertedValues) {
      78         Font font = Font.getDefault();
      79         double size = font.getSize();
      80         String family = font.getFamily();
      81         FontWeight weight = FontWeight.NORMAL;
      82         FontPosture style = FontPosture.REGULAR;
      83
      84         for (Entry<CssMetaData<? extends Styleable, ?>, Object> entry : convertedValues.entrySet()) {
      85
      86             Object value = entry.getValue();
      87             if (value == null) {
      88                 continue;
      89             }
      90             final String prop = entry.getKey().getProperty();
      91             if (prop.endsWith("font-size")) {
      92                 size = ((Number) value).doubleValue();
      93             } else if (prop.endsWith("font-family")) {
      94                 family = Utils.stripQuotes((String) value);
      95             } else if (prop.endsWith("font-weight")) {
      96                 weight = (FontWeight) value;
      97             } else if (prop.endsWith("font-style")) {
      98                 style = (FontPosture) value;
      99             }
     100         }
     101         final Font f = Font.font(family, weight, style, size);
     102         return f;
     103     }
     104
     105     @Override
     106     public String toString() {
     107         return "FontConverter";
     108     }
     109
     110     public static final class FontStyleConverter extends StyleConverterImpl<String, FontPosture> {
     111
     112         // lazy, thread-safe instatiation
     113         private static class Holder {
     114             static FontStyleConverter INSTANCE = new FontStyleConverter();
     115         }
     116
     117         public static FontStyleConverter getInstance() {
     118             return Holder.INSTANCE;
     119         }
     120
     121         private FontStyleConverter() {
     122             super();
     123         }
     124
     125         @Override
     126         public FontPosture convert(ParsedValue<String, FontPosture> value, Font font) {
     127
     128             // Testing for RT-31022 exposed a ClassCastException where value
     129             // wraps a String (e.g., "ITALIC", not a FontUnits.Style).
     130             final Object val = value.getValue();
     131
     132             FontPosture style = null;
     133
     134             if (val instanceof String) {
     135                 try {
     136                     String sval = ((String)val).toUpperCase(Locale.ROOT);
     137                     style = Enum.valueOf(FontPosture.class, sval);
     138                 } catch (IllegalArgumentException iae) {
     139                     style =  FontPosture.REGULAR;
     140                 } catch (NullPointerException npe) {
     141                     style =  FontPosture.REGULAR;
     142                 }
     143
     144             } else if (val instanceof FontPosture) {
     145                 style = (FontPosture)val;
     146             }
     147             return style;
     148         }
     149
     150         @Override
     151         public String toString() {
     152             return "FontConverter.StyleConverter";
     153         }
     154     }
     155
     156     public static final class FontWeightConverter extends StyleConverterImpl<String, FontWeight> {
     157
     158         // lazy, thread-safe instatiation
     159         private static class Holder {
     160             static FontWeightConverter INSTANCE = new FontWeightConverter();
     161         }
     162
     163         public static FontWeightConverter getInstance() {
     164             return Holder.INSTANCE;
     165         }
     166
     167         private FontWeightConverter() {
     168             super();
     169         }
     170
     171         @Override
     172         public FontWeight convert(ParsedValue<String, FontWeight> value, Font font) {
     173
     174             // Testing for RT-31022 exposed a ClassCastException where value
     175             // wraps a String (e.g., "ITALIC", not a FontUnits.Style).
     176             final Object val = value.getValue();
     177
     178             FontWeight weight = null;
     179
     180             if (val instanceof String) {
     181                 try {
     182                     String sval = ((String)val).toUpperCase(Locale.ROOT);
     183                     weight = Enum.valueOf(FontWeight.class, sval);
     184                 } catch (IllegalArgumentException iae) {
     185                     weight =  FontWeight.NORMAL;
     186                 } catch (NullPointerException npe) {
     187                     weight =  FontWeight.NORMAL;
     188                 }
     189
     190             } else if (val instanceof FontWeight) {
     191                 weight = (FontWeight)val;
     192             }
     193
     194             return weight;
     195         }
     196
     197         @Override
     198         public String toString() {
     199             return "FontConverter.WeightConverter";
     200         }
     201     }
     202
     203     public static final class FontSizeConverter extends StyleConverterImpl<ParsedValue<?, Size>, Number> {
     204
     205         // lazy, thread-safe instatiation
     206         private static class Holder {
     207             static FontSizeConverter INSTANCE = new FontSizeConverter();
     208         }
     209
     210         public static FontSizeConverter getInstance() {
     211             return Holder.INSTANCE;
     212         }
     213
     214         private FontSizeConverter() {
     215             super();
     216         }
     217
     218         @Override
     219         public Number convert(ParsedValue<ParsedValue<?, Size>, Number> value, Font font) {
     220             final ParsedValue<?, Size> size = value.getValue();
     221             return size.convert(font).pixels(font.getSize(), font);
     222         }
     223
     224         @Override
     225         public String toString() {
     226             return "FontConverter.FontSizeConverter";
     227         }
     228     }
     229
     230 }