-
Notifications
You must be signed in to change notification settings - Fork 101
/
Copy pathFontManagerLinux.cc
246 lines (205 loc) · 6.52 KB
/
FontManagerLinux.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#include <fontconfig/fontconfig.h>
#include "FontDescriptor.h"
int convertWeight(FontWeight weight) {
switch (weight) {
case FontWeightThin:
return FC_WEIGHT_THIN;
case FontWeightUltraLight:
return FC_WEIGHT_ULTRALIGHT;
case FontWeightLight:
return FC_WEIGHT_LIGHT;
case FontWeightNormal:
return FC_WEIGHT_REGULAR;
case FontWeightMedium:
return FC_WEIGHT_MEDIUM;
case FontWeightSemiBold:
return FC_WEIGHT_SEMIBOLD;
case FontWeightBold:
return FC_WEIGHT_BOLD;
case FontWeightUltraBold:
return FC_WEIGHT_EXTRABOLD;
case FontWeightHeavy:
return FC_WEIGHT_ULTRABLACK;
default:
return FC_WEIGHT_REGULAR;
}
}
FontWeight convertWeight(int weight) {
switch (weight) {
case FC_WEIGHT_THIN:
return FontWeightThin;
case FC_WEIGHT_ULTRALIGHT:
return FontWeightUltraLight;
case FC_WEIGHT_LIGHT:
return FontWeightLight;
case FC_WEIGHT_REGULAR:
return FontWeightNormal;
case FC_WEIGHT_MEDIUM:
return FontWeightMedium;
case FC_WEIGHT_SEMIBOLD:
return FontWeightSemiBold;
case FC_WEIGHT_BOLD:
return FontWeightBold;
case FC_WEIGHT_EXTRABOLD:
return FontWeightUltraBold;
case FC_WEIGHT_ULTRABLACK:
return FontWeightHeavy;
default:
return FontWeightNormal;
}
}
int convertWidth(FontWidth width) {
switch (width) {
case FontWidthUltraCondensed:
return FC_WIDTH_ULTRACONDENSED;
case FontWidthExtraCondensed:
return FC_WIDTH_EXTRACONDENSED;
case FontWidthCondensed:
return FC_WIDTH_CONDENSED;
case FontWidthSemiCondensed:
return FC_WIDTH_SEMICONDENSED;
case FontWidthNormal:
return FC_WIDTH_NORMAL;
case FontWidthSemiExpanded:
return FC_WIDTH_SEMIEXPANDED;
case FontWidthExpanded:
return FC_WIDTH_EXPANDED;
case FontWidthExtraExpanded:
return FC_WIDTH_EXTRAEXPANDED;
case FontWidthUltraExpanded:
return FC_WIDTH_ULTRAEXPANDED;
default:
return FC_WIDTH_NORMAL;
}
}
FontWidth convertWidth(int width) {
switch (width) {
case FC_WIDTH_ULTRACONDENSED:
return FontWidthUltraCondensed;
case FC_WIDTH_EXTRACONDENSED:
return FontWidthExtraCondensed;
case FC_WIDTH_CONDENSED:
return FontWidthCondensed;
case FC_WIDTH_SEMICONDENSED:
return FontWidthSemiCondensed;
case FC_WIDTH_NORMAL:
return FontWidthNormal;
case FC_WIDTH_SEMIEXPANDED:
return FontWidthSemiExpanded;
case FC_WIDTH_EXPANDED:
return FontWidthExpanded;
case FC_WIDTH_EXTRAEXPANDED:
return FontWidthExtraExpanded;
case FC_WIDTH_ULTRAEXPANDED:
return FontWidthUltraExpanded;
default:
return FontWidthNormal;
}
}
FontDescriptor *createFontDescriptor(FcPattern *pattern) {
FcChar8 *path, *psName, *family, *style;
int weight, width, slant, spacing;
FcPatternGetString(pattern, FC_FILE, 0, &path);
FcPatternGetString(pattern, FC_POSTSCRIPT_NAME, 0, &psName);
FcPatternGetString(pattern, FC_FAMILY, 0, &family);
FcPatternGetString(pattern, FC_STYLE, 0, &style);
FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight);
FcPatternGetInteger(pattern, FC_WIDTH, 0, &width);
FcPatternGetInteger(pattern, FC_SLANT, 0, &slant);
FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing);
return new FontDescriptor(
(char *) path,
(char *) psName,
(char *) family,
(char *) style,
convertWeight(weight),
convertWidth(width),
slant == FC_SLANT_ITALIC,
spacing == FC_MONO
);
}
ResultSet *getResultSet(FcFontSet *fs) {
ResultSet *res = new ResultSet();
if (!fs)
return res;
for (int i = 0; i < fs->nfont; i++) {
res->push_back(createFontDescriptor(fs->fonts[i]));
}
return res;
}
ResultSet *getAvailableFonts() {
FcInit();
FcPattern *pattern = FcPatternCreate();
FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_POSTSCRIPT_NAME, FC_FAMILY, FC_STYLE, FC_WEIGHT, FC_WIDTH, FC_SLANT, FC_SPACING, NULL);
FcFontSet *fs = FcFontList(NULL, pattern, os);
ResultSet *res = getResultSet(fs);
FcPatternDestroy(pattern);
FcObjectSetDestroy(os);
FcFontSetDestroy(fs);
return res;
}
FcPattern *createPattern(FontDescriptor *desc) {
FcInit();
FcPattern *pattern = FcPatternCreate();
if (desc->postscriptName)
FcPatternAddString(pattern, FC_POSTSCRIPT_NAME, (FcChar8 *) desc->postscriptName);
if (desc->family)
FcPatternAddString(pattern, FC_FAMILY, (FcChar8 *) desc->family);
if (desc->style)
FcPatternAddString(pattern, FC_STYLE, (FcChar8 *) desc->style);
if (desc->italic)
FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
if (desc->weight)
FcPatternAddInteger(pattern, FC_WEIGHT, convertWeight(desc->weight));
if (desc->width)
FcPatternAddInteger(pattern, FC_WIDTH, convertWidth(desc->width));
if (desc->monospace)
FcPatternAddInteger(pattern, FC_SPACING, FC_MONO);
return pattern;
}
ResultSet *findFonts(FontDescriptor *desc) {
FcPattern *pattern = createPattern(desc);
FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_POSTSCRIPT_NAME, FC_FAMILY, FC_STYLE, FC_WEIGHT, FC_WIDTH, FC_SLANT, FC_SPACING, NULL);
FcFontSet *fs = FcFontList(NULL, pattern, os);
ResultSet *res = getResultSet(fs);
FcFontSetDestroy(fs);
FcPatternDestroy(pattern);
FcObjectSetDestroy(os);
return res;
}
FontDescriptor *findFont(FontDescriptor *desc) {
FcPattern *pattern = createPattern(desc);
FcConfigSubstitute(NULL, pattern, FcMatchPattern);
FcDefaultSubstitute(pattern);
FcResult result;
FcPattern *font = FcFontMatch(NULL, pattern, &result);
FontDescriptor *res = createFontDescriptor(font);
FcPatternDestroy(pattern);
FcPatternDestroy(font);
return res;
}
FontDescriptor *substituteFont(char *postscriptName, char *string) {
FcInit();
// create a pattern with the postscript name
FcPattern* pattern = FcPatternCreate();
FcPatternAddString(pattern, FC_POSTSCRIPT_NAME, (FcChar8 *) postscriptName);
// create a charset with each character in the string
FcCharSet* charset = FcCharSetCreate();
int len = strlen(string);
for (int i = 0; i < len;) {
FcChar32 c;
i += FcUtf8ToUcs4((FcChar8 *)string + i, &c, len - i);
FcCharSetAddChar(charset, c);
}
FcPatternAddCharSet(pattern, FC_CHARSET, charset);
FcCharSetDestroy(charset);
FcConfigSubstitute(0, pattern, FcMatchPattern);
FcDefaultSubstitute(pattern);
// find the best match font
FcResult result;
FcPattern *font = FcFontMatch(NULL, pattern, &result);
FontDescriptor *res = createFontDescriptor(font);
FcPatternDestroy(pattern);
FcPatternDestroy(font);
return res;
}