1 /*
2  * Copyright 2008-2019 by Emeric Vernat
3  *
4  *     This file is part of Java Melody.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18 package net.bull.javamelody.internal.web.pdf;
19
20 import java.awt.Color;
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.lang.reflect.Field;
25 import java.util.Locale;
26 import java.util.Properties;
27
28 import com.lowagie.text.DocumentException;
29 import com.lowagie.text.Font;
30 import com.lowagie.text.FontFactory;
31 import com.lowagie.text.pdf.BaseFont;
32
33 import net.bull.javamelody.internal.common.I18N;
34 import net.bull.javamelody.internal.common.InputOutput;
35 import net.bull.javamelody.internal.common.Parameters;
36
37 /**
38  * Enumération des fontes pour les documents pdf.
39  * @author Emeric Vernat
40  */

41 enum PdfFonts {
42     NORMAL(getFont(8f, Font.NORMAL)),
43     BOLD(getFont(8f, Font.BOLD)),
44     PARAGRAPH_TITLE(getFont(10f, Font.BOLD)),
45     TABLE_CELL(getFont(5.5f, Font.NORMAL)),
46     BOLD_CELL(getFont(5.5f, Font.BOLD)),
47     BLUE(getFont(5.5f, Font.NORMAL)),
48     INFO_CELL(getFont(5.5f, Font.NORMAL)),
49     WARNING_CELL(getFont(5.5f, Font.BOLD)),
50     SEVERE_CELL(getFont(5.5f, Font.BOLD)),
51     TABLE_HEADER(getFont(5.5f, Font.BOLD));
52
53     private static final String UKRAINIAN_LANGUAGE = "uk";
54     private static final String CZECH_LANGUAGE = "cs";
55
56     static {
57         BLUE.font.setColor(Color.BLUE);
58         INFO_CELL.font.setColor(Color.GREEN.darker());
59         WARNING_CELL.font.setColor(Color.ORANGE);
60         SEVERE_CELL.font.setColor(Color.RED);
61     }
62
63     private static BaseFont chineseBaseFont;
64     private static BaseFont dejaVuSansBaseFont;
65     private final transient Font font;
66     private transient Font chineseFont;
67     private transient Font dejaVuSansFont;
68
69     PdfFonts(Font font) {
70         this.font = font;
71     }
72
73     Font getFont() {
74         final String language = I18N.getResourceBundle().getLocale().getLanguage();
75         if (Locale.CHINESE.getLanguage().equals(language)) {
76             return getChineseFont();
77         } else if (UKRAINIAN_LANGUAGE.equals(language) || CZECH_LANGUAGE.equals(language)) {
78             return getDejaVuSansFont();
79         }
80         return font;
81     }
82
83     private static Font getFont(float size, int style) {
84         return FontFactory.getFont(FontFactory.HELVETICA, size, style);
85     }
86
87     private Font getChineseFont() {
88         if (chineseFont == null) {
89             final BaseFont bfChinese = getChineseBaseFont();
90             chineseFont = new Font(bfChinese, font.getSize(), font.getStyle());
91         }
92         return chineseFont;
93     }
94
95     private static synchronized BaseFont getChineseBaseFont() {
96         if (chineseBaseFont == null) {
97             try {
98                 try {
99                     chineseBaseFont = BaseFont.createFont("STSong-Light""UniGB-UCS2-H",
100                             BaseFont.NOT_EMBEDDED);
101                 } catch (final DocumentException e) {
102                     // now CJKFont.propertiesLoaded==true, load properties renamed (cf issue 258)
103                     loadCJKFonts();
104                     chineseBaseFont = BaseFont.createFont("STSong-Light""UniGB-UCS2-H",
105                             BaseFont.NOT_EMBEDDED);
106                 }
107             } catch (final DocumentException | IOException e) {
108                 throw new IllegalStateException(e);
109             }
110         }
111         return chineseBaseFont;
112     }
113
114     /**
115      * Chargement des cjkfonts et cjkencodings. <br/>
116      * Les fichiers cjkfonts.properties et cjkencoding.properties ont été renommés <br/>
117      * pour que FlyingSaucer ne croit pas qu'iTextAsian.jar est présent (issue 258). <br/>
118      * Cette méthode se charge de charger quand même les fichiers renommés pour la fonte en langue chinoise.
119      */

120     private static void loadCJKFonts() {
121         try {
122             final Class<?> cjkFontClass = Class.forName("com.lowagie.text.pdf.CJKFont");
123             final Field cjkFontsField = cjkFontClass.getDeclaredField("cjkFonts");
124             final Field cjkEncodingsField = cjkFontClass.getDeclaredField("cjkEncodings");
125             cjkFontsField.setAccessible(true);
126             cjkEncodingsField.setAccessible(true);
127             final Properties cjkFonts = (Properties) cjkFontsField.get(null);
128             final Properties cjkEncodings = (Properties) cjkEncodingsField.get(null);
129
130             if (cjkFonts.isEmpty()) {
131                 try (InputStream is = BaseFont.getResourceStream(
132                         BaseFont.RESOURCE_PATH + "cjkfonts.properties.renamedForIssue258")) {
133                     cjkFonts.load(is);
134                 }
135             }
136             if (cjkEncodings.isEmpty()) {
137                 try (InputStream is = BaseFont.getResourceStream(
138                         BaseFont.RESOURCE_PATH + "cjkencodings.properties.renamedForIssue258")) {
139                     cjkEncodings.load(is);
140                 }
141             }
142         } catch (final Exception e) {
143             throw new IllegalStateException(e);
144         }
145     }
146
147     private Font getDejaVuSansFont() {
148         if (dejaVuSansFont == null) {
149             final BaseFont bfDejaVuSans = getDejaVuSansBaseFont();
150             dejaVuSansFont = new Font(bfDejaVuSans, font.getSize(), font.getStyle());
151         }
152         return dejaVuSansFont;
153     }
154
155     private static synchronized BaseFont getDejaVuSansBaseFont() {
156         if (dejaVuSansBaseFont == null) {
157             final InputStream input = PdfFonts.class.getResourceAsStream("/DejaVuSans-Bold.ttf");
158             // input may be null if the jrobin jar file is not the 1.5.9 from Maven central or ...
159             if (input != null) {
160                 try {
161                     try {
162                         final File file = new File(Parameters.TEMPORARY_DIRECTORY,
163                                 "javamelody-ukrainian.ttf");
164                         InputOutput.pumpToFile(input, file);
165                         dejaVuSansBaseFont = BaseFont.createFont(file.getPath(),
166                                 BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
167                     } finally {
168                         input.close();
169                     }
170                 } catch (final IOException | DocumentException e) {
171                     throw new IllegalStateException(e);
172                 }
173             }
174         }
175         return dejaVuSansBaseFont;
176     }
177
178     static boolean shouldUseEnglishInsteadOfUkrainian() {
179         return UKRAINIAN_LANGUAGE.equals(I18N.getResourceBundle().getLocale().getLanguage())
180                 && getDejaVuSansBaseFont() == null;
181     }
182 }
183