2
* Copyright (c) 2005-2010 Substance Kirill Grouchnikov. All Rights Reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions are met:
7
* o Redistributions of source code must retain the above copyright notice,
8
* this list of conditions and the following disclaimer.
10
* o Redistributions in binary form must reproduce the above copyright notice,
11
* this list of conditions and the following disclaimer in the documentation
12
* and/or other materials provided with the distribution.
14
* o Neither the name of Substance Kirill Grouchnikov nor the names of
15
* its contributors may be used to endorse or promote products derived
16
* from this software without specific prior written permission.
18
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
package org.pushingpixels.substance.internal.fonts;
34
import java.util.regex.Pattern;
36
import javax.swing.UIDefaults;
38
import org.pushingpixels.substance.api.fonts.FontPolicy;
39
import org.pushingpixels.substance.api.fonts.FontSet;
42
* The default font policy for KDE desktops.
44
* @author <a href="mailto:paranoid.tiberiumlabs@gmail.com">Paranoid</a>
46
public class DefaultKDEFontPolicy implements FontPolicy {
49
* method to check if current user session is KDE
52
* if KDE session is currently running.
54
public static boolean isKDERunning() {
55
// KDE_FULL_SESSION=true
56
return "true".equals(System.getenv("KDE_FULL_SESSION"));
60
* Checks for KDE4 flags in current env. There are few possible flags:<br/>
61
* {@code KDE_SESSION_VERSION=4<br/> DESKTOP_SESSION=kde4<br/>} If distro
62
* for some readon don't set this flags - KDE3 is possibli
65
* There is one more way to determine current KDE version. We can run
66
* {@code "konsole --version"} command and parse output, but KDE3 don't have
67
* own env flags, so this command will run every time we using KDE3.
69
* @return {@code true} if KDE4 env flags found, {@code false} otherwise.
71
private static boolean isKDE4Running() {
72
if (!isKDERunning()) {
73
throw new IllegalStateException("KDE is not running");
75
return "4".equals(System.getenv("KDE_SESSION_VERSION"))
76
|| "kde4".equals(System.getenv("DESKTOP_SESSION"));
79
private static final String SANS_SERIF = "SansSerif";
80
private static FontSet fontSet = null;
83
public synchronized FontSet getFontSet(String lafName, UIDefaults table) {
84
if (fontSet == null) {
85
fontSet = getInternalFontSet(lafName, table);
90
private FontSet getInternalFontSet(String lafName, UIDefaults table) {
92
// size is the most important, then family and then style
96
int commonStyle = Font.PLAIN;
97
int menuStyle = Font.PLAIN;
98
int titleStyle = Font.BOLD;
99
String commonFamily = SANS_SERIF;
100
String menuFamily = SANS_SERIF;
101
String titleFamily = SANS_SERIF;
103
// size is the most important, then family and then style
106
* KDE4 can set common, menu, small and window title, while KDE3 can set
107
* only common, menu and window title. But in KDE4 config files small
108
* font is named "smallestReadableFont"
111
// <editor-fold defaultstate="collapsed" desc=" reading fonts ">
114
String kdeglobals = getFileContent("kdeglobals");
116
Pattern pattern = Pattern.compile(",");
120
String fontParam = getIniParam(kdeglobals, "[General]", "font");
121
String[] fontParams = pattern.split(fontParam);
122
commonFamily = fontParams[0];
123
commonSize = Integer.parseInt(fontParams[1]);
124
boolean bold = "75".equals(fontParams[4]);
125
boolean italic = "1".equals(fontParams[5]);
126
if (bold && italic) {
127
commonStyle = Font.BOLD + Font.ITALIC;
129
commonStyle = Font.ITALIC;
131
commonStyle = Font.BOLD;
133
commonStyle = Font.PLAIN;
136
} catch (Exception commonReadException) {
137
commonFamily = SANS_SERIF;
139
commonStyle = Font.PLAIN;
144
String menuFontParam = getIniParam(kdeglobals, "[General]",
146
String[] menuFontParams = pattern.split(menuFontParam);
147
menuFamily = menuFontParams[0];
148
menuSize = Integer.parseInt(menuFontParams[1]);
149
boolean bold = "75".equals(menuFontParams[4]);
150
boolean italic = "1".equals(menuFontParams[5]);
151
if (bold && italic) {
152
menuStyle = Font.BOLD + Font.ITALIC;
154
menuStyle = Font.ITALIC;
156
menuStyle = Font.BOLD;
158
menuStyle = Font.PLAIN;
161
} catch (Exception menuReadException) {
162
menuFamily = SANS_SERIF;
164
menuStyle = Font.PLAIN;
169
String activeFontParam = getIniParam(kdeglobals, "[WM]",
171
String[] activeFontParams = pattern.split(activeFontParam);
172
titleFamily = activeFontParams[0];
173
titleSize = Integer.parseInt(activeFontParams[1]);
174
boolean bold = "75".equals(activeFontParams[4]);
175
boolean italic = "1".equals(activeFontParams[5]);
176
if (bold && italic) {
177
titleStyle = Font.BOLD + Font.ITALIC;
179
titleStyle = Font.ITALIC;
181
titleStyle = Font.BOLD;
183
titleStyle = Font.PLAIN;
186
} catch (Exception titleReadException) {
187
titleFamily = SANS_SERIF;
189
titleStyle = Font.BOLD;
192
} catch (Exception kdeglobalsReadException) {
194
commonFamily = SANS_SERIF;
196
commonStyle = Font.PLAIN;
198
menuFamily = SANS_SERIF;
200
menuStyle = Font.PLAIN;
202
titleFamily = SANS_SERIF;
204
titleStyle = Font.BOLD;
210
// <editor-fold defaultstate="collapsed" desc=" dpi settings ">
212
double dcommonSize = commonSize;
213
double dmenuSize = menuSize;
214
double dtitleSize = titleSize;
218
String dpiParam = getIniParam(getFileContent("kcmfonts"),
219
"[General]", "forceFontDPI");
220
dpi = Integer.parseInt(dpiParam);
221
} catch (Exception dpiReadException) {
224
// kcmfonts common for both KDE3 and KDE4
231
dcommonSize = ((commonSize * dpi) / 72.0);
232
dmenuSize = ((menuSize * dpi) / 72.0);
233
dtitleSize = ((titleSize * dpi) / 72.0);
235
commonSize = (int) (dcommonSize + 0.5);
236
if (commonSize < 1) {
240
menuSize = (int) (dmenuSize + 0.5);
245
titleSize = (int) (dtitleSize + 0.5);
252
Font commonFont = new Font(commonFamily, commonStyle, commonSize);
253
Font menuFont = new Font(menuFamily, menuStyle, menuSize);
254
Font titleFont = new Font(titleFamily, titleStyle, titleSize);
256
return FontSets.createDefaultFontSet(commonFont, menuFont, commonFont,
257
commonFont, commonFont, titleFont);
260
private String getIniParam(String content, String category, String param)
262
// checking if our param in our category - we don't need same params
263
// from other categories
264
int categoryIndex = content.indexOf(category);
266
// fix for defect 483 - https://substance.dev.java.net/issues/show_bug.cgi?id=483
268
String lineSeparator = System.getProperty("line.separator");// JDK7: System.lineSeparator()
269
int nextCategoryIndex = content.indexOf(lineSeparator + '[', categoryIndex + 1);
271
if (nextCategoryIndex < 0) {
272
nextCategoryIndex = content.length();
274
int paramIndex = content.indexOf(param, categoryIndex);
275
if (paramIndex >= 0 && paramIndex < nextCategoryIndex) {
277
// now paramString contains full string of our parameter
278
int lineEnd = content.indexOf(lineSeparator,
281
lineEnd = content.length();
283
String paramString = content.substring(paramIndex, lineEnd);
285
// getting just our value, we don't need other symbols
286
int equalityIndex = paramString.indexOf('=');
288
* paramString.indexOf('#'); paramString.indexOf(';');
290
* don't know do we need to remove trailing comments after this
291
* symbols? have nothing similar in my system...
293
String result = paramString.substring(equalityIndex + 1).trim();
294
if (result.length() > 0) {
298
throw new Exception("No such param in current category");
301
private String getFileContent(String fileName) throws IOException {
304
* preparing KDE home folder. KDE4 may be stored in .kde4 folder, and
307
* we check for .kde4 folder, if it exists - we will use it. Otherwise
308
* we will left kdeHome empty, and it will be set to .kde in both cases
309
* of KDE3 and KDE4 with .kde folder.
311
String userHome = System.getProperty("user.home");
312
String kdeHome = null;
313
if (isKDE4Running()) {
314
File kdeHomeFolder = new File(userHome, ".kde4");
315
if (kdeHomeFolder.exists()) {
319
if (kdeHome == null) {
323
char fs = File.separatorChar;
324
fileName = userHome + fs + kdeHome + "/share/config/" + fileName;
326
fileName = fileName.replace('/', fs);
329
// creating file from user home, using system's file separator:
330
BufferedReader in = new BufferedReader(new FileReader(fileName));
331
StringBuilder sb = new StringBuilder();
332
// size same as inside BufferedReader code
333
char[] buffer = new char[8192];
335
while ((read = in.read(buffer)) >= 0) {
336
sb.append(buffer, 0, read);
340
return sb.toString();