1 /*
2  * Zed Attack Proxy (ZAP) and its related class files.
3  *
4  * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5  *
6  * Copyright 2015 The ZAP Development Team
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 package org.zaproxy.zap.utils;
21 
22 import java.awt.Font;
23 import java.awt.FontFormatException;
24 import java.awt.GraphicsEnvironment;
25 import java.io.IOException;
26 import java.util.EnumMap;
27 import javax.swing.JLabel;
28 import javax.swing.UIManager;
29 
30 public class FontUtils {
31 
32     public static enum Size {
33         smallest,
34         much_smaller,
35         smaller,
36         standard,
37         larger,
38         much_larger,
39         huge
40     }
41 
42     public static enum FontType {
43         general,
44         workPanels
45     }
46 
47     private static float scale = -1;
48     private static EnumMap<FontType, Font> defaultFonts = new EnumMap<>(FontType.class);
49     private static EnumMap<FontType, Boolean> defaultFontSets = new EnumMap<>(FontType.class);
50 
51     private static Font systemDefaultFont;
52     private static Font quicksandBoldFont;
53 
getSystemDefaultFont()54     public static Font getSystemDefaultFont() {
55         if (systemDefaultFont == null) {
56             systemDefaultFont = (Font) UIManager.getLookAndFeelDefaults().get("defaultFont");
57 
58             if (systemDefaultFont == null) {
59                 systemDefaultFont = new JLabel("").getFont();
60             }
61         }
62 
63         return systemDefaultFont;
64     }
65 
66     /**
67      * Returns the Quicksand Bold font -
68      * https://fonts.google.com/specimen/Quicksand?selection.family=Quicksand
69      *
70      * @since 2.7.0
71      * @return the Quicksand Bold font
72      */
getQuicksandBoldFont()73     public static Font getQuicksandBoldFont() {
74         if (quicksandBoldFont == null) {
75             try {
76                 quicksandBoldFont =
77                         Font.createFont(
78                                 Font.TRUETYPE_FONT,
79                                 FontUtils.class.getResourceAsStream(
80                                         "/resource/Quicksand-Bold.ttf"));
81                 GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(quicksandBoldFont);
82                 // Ensure its scaled properly - only need to do this when its first loaded
83                 quicksandBoldFont =
84                         quicksandBoldFont.deriveFont((float) getDefaultFont().getSize());
85             } catch (IOException | FontFormatException e) {
86                 quicksandBoldFont = defaultFonts.get(FontType.general);
87             }
88         }
89         return quicksandBoldFont;
90     }
91 
canChangeSize()92     public static boolean canChangeSize() {
93         return UIManager.getLookAndFeelDefaults().get("defaultFont") != null;
94     }
95 
setDefaultFont(FontType fontType, Font font)96     public static void setDefaultFont(FontType fontType, Font font) {
97         if (canChangeSize()) {
98             getSystemDefaultFont(); // Make sure the system default font is saved first
99             defaultFonts.put(fontType, font);
100             scale = -1; // force it to be recalculated
101             if (fontType == FontType.general) {
102                 UIManager.getLookAndFeelDefaults().put("defaultFont", font);
103             }
104         }
105     }
106 
setDefaultFont(FontType fontType, String name, int size)107     public static void setDefaultFont(FontType fontType, String name, int size) {
108         // A blank font name works fine.
109         // For some reason getting the default font name doesn't work - it doesn't seem to get
110         // applied everywhere
111         // No ideas why :/
112         if (size <= 5) {
113             size = getDefaultFont().getSize();
114         }
115 
116         defaultFontSets.put(fontType, (name != null && !name.isEmpty()));
117         setDefaultFont(fontType, new Font(name, Font.PLAIN, size));
118     }
119 
getDefaultFont()120     private static Font getDefaultFont() {
121         return getDefaultFont(FontType.general);
122     }
123 
getDefaultFont(FontType fontType)124     private static Font getDefaultFont(FontType fontType) {
125         if (defaultFonts.get(fontType) == null) {
126             defaultFonts.put(fontType, Font.getFont("defaultFont"));
127             if (defaultFonts.get(fontType) == null) {
128                 defaultFonts.put(fontType, new JLabel("").getFont());
129             }
130         }
131         return defaultFonts.get(fontType);
132     }
133 
134     /**
135      * Gets the named font, correctly scaled
136      *
137      * @param name
138      * @return the named font, correctly scaled
139      */
getFont(String name)140     public static Font getFont(String name) {
141         return getFont(name, Font.PLAIN);
142     }
143 
144     /**
145      * Gets the default font with the specified style, correctly scaled
146      *
147      * @param style
148      * @return the default font with the specified style, correctly scaled
149      */
getFont(int style)150     public static Font getFont(int style) {
151         return getDefaultFont().deriveFont(style);
152     }
153 
154     /**
155      * Gets the font for the give {@link FontType}
156      *
157      * @param fontType the {@code FontType} for which the font should be returned
158      * @return font
159      */
getFont(FontType fontType)160     public static Font getFont(FontType fontType) {
161         return getDefaultFont(fontType);
162     }
163 
164     /**
165      * Gets font for the given {@link FontType} or the fallback font with the given name if no font
166      * is set for the given {@code FontType}
167      *
168      * @param fontType the {@code FontType} for which the font should be returned
169      * @param fallbackFontName the name ({@code String}) of the font which will be returned of no
170      *     font is set for the given {@code FontType}
171      * @return work panels font or fallback font
172      */
getFontWithFallback(FontType fontType, String fallbackFontName)173     public static Font getFontWithFallback(FontType fontType, String fallbackFontName) {
174         if (isDefaultFontSet(fontType)) {
175             return getFont(fontType);
176         } else {
177             return getFont(fallbackFontName);
178         }
179     }
180 
181     /**
182      * Gets the named font with the specified style, correctly scaled
183      *
184      * @param name
185      * @param style
186      * @return the named font with the specified style, correctly scaled
187      */
getFont(String name, int style)188     public static Font getFont(String name, int style) {
189         return new Font(name, style, getDefaultFont().getSize());
190     }
191 
192     /**
193      * Gets the default font with the specified style and size, correctly scaled
194      *
195      * @param style
196      * @param size
197      * @return
198      */
getFont(int style, Size size)199     public static Font getFont(int style, Size size) {
200         return getFont(getDefaultFont(), size).deriveFont(style);
201     }
202 
203     /**
204      * Gets the specified font with the specified style and size, correctly scaled
205      *
206      * @param style
207      * @param size
208      * @since 2.7.0
209      * @return
210      */
getFont(Font font, int style, Size size)211     public static Font getFont(Font font, int style, Size size) {
212         return getFont(font, size).deriveFont(style);
213     }
214 
215     /**
216      * Gets the default font with the specified size, correctly scaled
217      *
218      * @param size
219      * @return the default font with the specified size, correctly scaled
220      */
getFont(Size size)221     public static Font getFont(Size size) {
222         return getFont(getDefaultFont(), size);
223     }
224 
225     /**
226      * Gets the specified font with the specified size, correctly scaled
227      *
228      * @param font
229      * @param size
230      * @since 2.7.0
231      * @return the specified font with the specified size, correctly scaled
232      */
getFont(Font font, Size size)233     public static Font getFont(Font font, Size size) {
234         float s;
235         switch (size) {
236             case smallest:
237                 s = (float) (font.getSize() * 0.5);
238                 break;
239             case much_smaller:
240                 s = (float) (font.getSize() * 0.7);
241                 break;
242             case smaller:
243                 s = (float) (font.getSize() * 0.8);
244                 break;
245             case standard:
246                 s = (float) font.getSize();
247                 break;
248             case larger:
249                 s = (float) (font.getSize() * 1.5);
250                 break;
251             case much_larger:
252                 s = (float) (font.getSize() * 3);
253                 break;
254             case huge:
255                 s = (float) (font.getSize() * 4);
256                 break;
257             default:
258                 s = (float) (font.getSize());
259                 break;
260         }
261         return font.deriveFont(s);
262     }
263 
getScale()264     public static float getScale() {
265         if (scale == -1) {
266             scale = getDefaultFont().getSize2D() / getSystemDefaultFont().getSize2D();
267         }
268         return scale;
269     }
270 
271     /**
272      * Tells whether or not a custom default font was set.
273      *
274      * <p>If no custom font was set it's used the system default font.
275      *
276      * @return {@code true} if a custom font was set, {@code false} otherwise.
277      * @since 2.7.0
278      * @see #getSystemDefaultFont()
279      */
isDefaultFontSet()280     public static boolean isDefaultFontSet() {
281         return defaultFontSets.get(FontType.general);
282     }
283 
284     /**
285      * Tells whether or not a custom default font was set for the given {@link FontType}.
286      *
287      * @return {@code true} if a custom font was set, {@code false} otherwise.
288      * @since 2.8.0
289      * @see #getSystemDefaultFont()
290      */
isDefaultFontSet(FontType fontType)291     public static boolean isDefaultFontSet(FontType fontType) {
292         return defaultFontSets.get(fontType);
293     }
294 }
295