Lines 24-29
Link Here
|
24 |
#include "gsexit.h" |
24 |
#include "gsexit.h" |
25 |
#include "gp.h" |
25 |
#include "gp.h" |
26 |
|
26 |
|
|
|
27 |
#define HAVE_FONTCONFIG |
28 |
|
29 |
#ifdef HAVE_FONTCONFIG |
30 |
#include <fontconfig/fontconfig.h> |
31 |
#endif |
32 |
|
27 |
/* |
33 |
/* |
28 |
* This is the only place in Ghostscript that calls 'exit'. Including |
34 |
* This is the only place in Ghostscript that calls 'exit'. Including |
29 |
* <stdlib.h> is overkill, but that's where it's declared on ANSI systems. |
35 |
* <stdlib.h> is overkill, but that's where it's declared on ANSI systems. |
Lines 175-190
Link Here
|
175 |
* building a custom fontmap file. |
181 |
* building a custom fontmap file. |
176 |
*/ |
182 |
*/ |
177 |
|
183 |
|
|
|
184 |
|
185 |
/* Mangle the FontConfig family and style information into a |
186 |
* PostScript font name */ |
187 |
#ifdef HAVE_FONTCONFIG |
188 |
static void makePSFontName(char* family, int weight, int slant, char *buf, int bufsize) |
189 |
{ |
190 |
int bytesCopied, length, i; |
191 |
const char *slantname, *weightname; |
192 |
|
193 |
switch (slant) { |
194 |
case FC_SLANT_ROMAN: slantname=""; break;; |
195 |
case FC_SLANT_OBLIQUE: slantname="Oblique"; break;; |
196 |
case FC_SLANT_ITALIC: slantname="Italic"; break;; |
197 |
default: slantname="Unknown"; break;; |
198 |
} |
199 |
|
200 |
switch (weight) { |
201 |
case FC_WEIGHT_MEDIUM: weightname=""; break;; |
202 |
case FC_WEIGHT_LIGHT: weightname="Light"; break;; |
203 |
case FC_WEIGHT_DEMIBOLD: weightname="Demi"; break;; |
204 |
case FC_WEIGHT_BOLD: weightname="Bold"; break;; |
205 |
case FC_WEIGHT_BLACK: weightname="Black"; break;; |
206 |
default: weightname="Unknown"; break;; |
207 |
} |
208 |
|
209 |
length = strlen(family); |
210 |
if (length >= bufsize) |
211 |
length = bufsize; |
212 |
/* Copy the family name, stripping spaces */ |
213 |
bytesCopied=0; |
214 |
for (i = 0; i < length; i++) |
215 |
if (family[i] != ' ') |
216 |
buf[bytesCopied++] = family[i]; |
217 |
|
218 |
if ( ((slant != FC_SLANT_ROMAN) || (weight != FC_WEIGHT_MEDIUM)) \ |
219 |
&& bytesCopied < bufsize ) |
220 |
{ |
221 |
buf[bytesCopied] = '-'; |
222 |
bytesCopied++; |
223 |
if (weight != FC_WEIGHT_MEDIUM) |
224 |
{ |
225 |
length = strlen(family); |
226 |
if ((length + bytesCopied) >= bufsize) |
227 |
length = bufsize - bytesCopied - 1; |
228 |
strncpy(buf+bytesCopied, weightname, length); |
229 |
bytesCopied += length; |
230 |
} |
231 |
if (slant != FC_SLANT_ROMAN) |
232 |
{ |
233 |
length = strlen(family); |
234 |
if ((length + bytesCopied) >= bufsize) |
235 |
length = bufsize - bytesCopied - 1; |
236 |
strncpy(buf+bytesCopied, slantname, length); |
237 |
bytesCopied += length; |
238 |
} |
239 |
} |
240 |
buf[bytesCopied] = '\0'; |
241 |
} |
242 |
#endif |
243 |
|
244 |
/* State struct for font iteration - passed as an opaque 'void*' through the rest of gs */ |
245 |
#ifdef HAVE_FONTCONFIG |
246 |
typedef struct { |
247 |
int index; /* current index of iteration over font_list */ |
248 |
FcConfig* fc; /* FontConfig library handle */ |
249 |
FcFontSet* font_list; /* FontConfig font list */ |
250 |
char name[255]; /* name of last font */ |
251 |
} unix_fontenum_t; |
252 |
#endif |
253 |
|
178 |
void *gp_enumerate_fonts_init(gs_memory_t *mem) |
254 |
void *gp_enumerate_fonts_init(gs_memory_t *mem) |
179 |
{ |
255 |
{ |
|
|
256 |
#ifdef HAVE_FONTCONFIG |
257 |
unix_fontenum_t *state = (unix_fontenum_t *)malloc(sizeof(unix_fontenum_t)); |
258 |
if (state == NULL) |
259 |
return NULL; /* Failed to allocate state */ |
260 |
|
261 |
state->index = 0; |
262 |
state->fc = NULL; |
263 |
state->font_list = NULL; |
264 |
|
265 |
/* Load the fontconfig library */ |
266 |
state->fc = FcInitLoadConfigAndFonts(); |
267 |
if (state->fc == NULL) { |
268 |
free(state); |
269 |
state = NULL; |
270 |
dlprintf("destroyed state - fontconfig init failed"); |
271 |
return NULL; /* Failed to open fontconfig library */ |
272 |
} |
273 |
|
274 |
/* load the font set that we'll iterate over */ |
275 |
FcPattern *pat = FcPatternBuild(NULL, |
276 |
FC_OUTLINE, FcTypeBool, 1, |
277 |
FC_SCALABLE, FcTypeBool, 1, |
278 |
NULL); |
279 |
FcObjectSet* os = FcObjectSetBuild(FC_FILE, FC_OUTLINE, FC_FAMILY, FC_WEIGHT, FC_SLANT, 0); |
280 |
state->font_list = FcFontList(0, pat, os); |
281 |
FcPatternDestroy(pat); |
282 |
FcObjectSetDestroy(os); |
283 |
if (state->font_list == NULL) { |
284 |
free(state); |
285 |
state = NULL; |
286 |
return NULL; /* Failed to generate font list */ |
287 |
} |
288 |
return (void *)state; |
289 |
#else |
180 |
return NULL; |
290 |
return NULL; |
|
|
291 |
#endif |
181 |
} |
292 |
} |
182 |
|
293 |
|
183 |
int gp_enumerate_fonts_next(void *enum_state, char **fontname, char **path) |
294 |
int gp_enumerate_fonts_next(void *enum_state, char **fontname, char **path) |
184 |
{ |
295 |
{ |
|
|
296 |
#ifdef HAVE_FONTCONFIG |
297 |
char* psname = NULL; |
298 |
|
299 |
unix_fontenum_t* state = (unix_fontenum_t *)enum_state; |
300 |
if (state == NULL) { |
301 |
return 0; /* gp_enumerate_fonts_init failed for some reason */ |
302 |
} |
303 |
|
304 |
/* Bits of the following were borrowed from Red Hat's GS 7 FontConfig patch */ |
305 |
FcChar8* file_fc = NULL; |
306 |
FcChar8* family_fc = NULL; |
307 |
int outline_fc, slant_fc, weight_fc; |
308 |
FcResult result; |
309 |
|
310 |
if (state->index == state->font_list->nfont) { |
311 |
return 0; /* we've run out of fonts */ |
312 |
} |
313 |
|
314 |
FcPattern* font = state->font_list->fonts[state->index]; |
315 |
|
316 |
result = FcPatternGetString (font, FC_FAMILY, 0, &family_fc); |
317 |
if (result != FcResultMatch || family_fc == NULL) { |
318 |
dlprintf ("DEBUG: FC_FAMILY mismatch\n"); |
319 |
return 0; |
320 |
} |
321 |
|
322 |
result = FcPatternGetString (font, FC_FILE, 0, &file_fc); |
323 |
if (result != FcResultMatch || file_fc == NULL) { |
324 |
dlprintf ("DEBUG: FC_FILE mismatch\n"); |
325 |
return 0; |
326 |
} |
327 |
|
328 |
result = FcPatternGetBool (font, FC_OUTLINE, 0, &outline_fc); |
329 |
if (result != FcResultMatch) { |
330 |
dlprintf1 ("DEBUG: FC_OUTLINE failed to match on %s\n", (char*)family_fc); |
331 |
return 0; |
332 |
} |
333 |
|
334 |
result = FcPatternGetInteger (font, FC_SLANT, 0, &slant_fc); |
335 |
if (result != FcResultMatch) { |
336 |
dlprintf ("DEBUG: FC_SLANT didn't match\n"); |
337 |
return 0; |
338 |
} |
339 |
|
340 |
result = FcPatternGetInteger (font, FC_WEIGHT, 0, &weight_fc); |
341 |
if (result != FcResultMatch) { |
342 |
dlprintf ("DEBUG: FC_WEIGHT didn't match\n"); |
343 |
return 0; |
344 |
} |
345 |
|
346 |
/* Gross hack to work around Fontconfig's inability to tell |
347 |
* us the font's PostScript name - generate it ourselves. |
348 |
* We must free the memory allocated here next time around. */ |
349 |
makePSFontName((char *)family_fc, weight_fc, slant_fc, &state->name, sizeof(state->name)); |
350 |
*fontname = &state->name; |
351 |
|
352 |
/* return the font path straight out of fontconfig */ |
353 |
*path = (char*)file_fc; |
354 |
|
355 |
state->index ++; |
356 |
return 1; |
357 |
#else |
185 |
return 0; |
358 |
return 0; |
|
|
359 |
#endif |
186 |
} |
360 |
} |
187 |
|
361 |
|
188 |
void gp_enumerate_fonts_free(void *enum_state) |
362 |
void gp_enumerate_fonts_free(void *enum_state) |
189 |
{ |
363 |
{ |
190 |
} |
364 |
#ifdef HAVE_FONTCONFIG |
|
|
365 |
unix_fontenum_t* state = (unix_fontenum_t *)enum_state; |
366 |
if (state != NULL) { |
367 |
if (state->font_list != NULL) |
368 |
FcFontSetDestroy(state->font_list); |
369 |
free(state); |
370 |
} |
371 |
#endif |
372 |
} |
373 |
|