1 /* libwmf (font.c): library for wmf conversion
2 Copyright (C) 2000,2001 Francis James Franklin
3
4 The libwmf Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 The libwmf Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with the libwmf Library; see the file COPYING. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
18
19
20 #ifdef HAVE_CONFIG_H
21 #include "wmfconfig.h"
22 #endif /* HAVE_CONFIG_H */
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <math.h>
27 #include <ctype.h>
28 #include <sys/stat.h>
29
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
33
34 #include "wmfdefs.h"
35
36 #include "font.h"
37
38 #ifdef _WIN32
39
40 extern char* _libwmf_get_fontdir();
41
_libwmf_get_xtra_fontmap(void)42 static char* _libwmf_get_xtra_fontmap (void)
43 {
44 static char retval[1000] = "";
45
46 if (retval[0] == '\0')
47 { strcpy (retval, _libwmf_get_fontdir ());
48 strcat (retval, "\\share\\libwmf\\fonts\\fontmap");
49 }
50
51 return retval;
52 }
53
54 #undef WMF_XTRA_FONTMAP
55 #define WMF_XTRA_FONTMAP _libwmf_get_xtra_fontmap ()
56
remap_font_file_name(wmfAPI * API,char * filename)57 static char* remap_font_file_name(wmfAPI* API,char* filename)
58 {
59 /* If filename is prefixed with the compile-time WMF_FONTDIR,
60 * substitute the run-time font directory.
61 */
62 char* retval;
63 if (strncmp (filename, WMF_FONTDIR "/", strlen (WMF_FONTDIR "/")) == 0)
64 { retval = wmf_malloc (API,strlen (filename) - strlen (WMF_FONTDIR) + strlen (_libwmf_get_fontdir ()) + 1);
65 strcpy (retval,_libwmf_get_fontdir ());
66 strcat (retval,filename + strlen (WMF_FONTDIR));
67 }
68 else
69 { retval = wmf_strdup (API,filename);
70 }
71
72 return retval;
73 }
74
75 #endif
76
ipa_font_add_wmf(wmfAPI * API,wmfFontMap * mapping)77 static void ipa_font_add_wmf (wmfAPI* API,wmfFontMap* mapping)
78 { wmfFontmapData* font_data = (wmfFontmapData*) ((wmfFontData*) API->font_data)->user_data;
79
80 wmfFontMap* more;
81
82 unsigned int i = 0;
83
84 while (font_data->wmf[i].name)
85 { if (strcmp (font_data->wmf[i].name,mapping->name) == 0) break;
86 i++;
87 }
88
89 if (font_data->wmf[i].name) return; /* Entry exists already */
90
91 if ((i & 0x0f) == (unsigned int) 0x0f)
92 { more = (wmfFontMap*) wmf_realloc (API,font_data->wmf,(i + 0x11) * sizeof (wmfFontMap));
93
94 if (ERR (API))
95 { WMF_DEBUG (API,"bailing...");
96 return;
97 }
98
99 font_data->wmf = more;
100 }
101
102 font_data->wmf[i].name = wmf_strdup (API,mapping->name );
103 font_data->wmf[i].normal = wmf_strdup (API,mapping->normal );
104 font_data->wmf[i].italic = wmf_strdup (API,mapping->italic );
105 font_data->wmf[i].bold = wmf_strdup (API,mapping->bold );
106 font_data->wmf[i].bolditalic = wmf_strdup (API,mapping->bolditalic);
107
108 if (ERR (API))
109 { WMF_DEBUG (API,"bailing...");
110 return;
111 }
112
113 i++;
114 font_data->wmf[i].name = 0;
115 }
116
ipa_font_add_sub(wmfAPI * API,wmfMapping * mapping)117 static void ipa_font_add_sub (wmfAPI* API,wmfMapping* mapping)
118 { wmfFontmapData* font_data = (wmfFontmapData*) ((wmfFontData*) API->font_data)->user_data;
119
120 wmfMapping* more;
121
122 unsigned int i = 0;
123
124 while (font_data->sub[i].name)
125 { if (strcmp (font_data->sub[i].name,mapping->name) == 0) break;
126 i++;
127 }
128
129 if (font_data->sub[i].name) return; /* Entry exists already */
130
131 if ((i & 0x0f) == (unsigned int) 0x0f)
132 { more = (wmfMapping*) wmf_realloc (API,font_data->sub,(i + 0x11) * sizeof (wmfMapping));
133
134 if (ERR (API))
135 { WMF_DEBUG (API,"bailing...");
136 return;
137 }
138
139 font_data->sub = more;
140 }
141
142 font_data->sub[i].name = wmf_strdup (API,mapping->name );
143 font_data->sub[i].mapping = wmf_strdup (API,mapping->mapping);
144
145 if (ERR (API))
146 { WMF_DEBUG (API,"bailing...");
147 return;
148 }
149
150 i++;
151 font_data->sub[i].name = 0;
152 }
153
ipa_font_add_ps(wmfAPI * API,wmfMapping * mapping)154 static void ipa_font_add_ps (wmfAPI* API,wmfMapping* mapping)
155 { wmfFontmapData* font_data = (wmfFontmapData*) ((wmfFontData*) API->font_data)->user_data;
156
157 wmfFT_Mapping* more;
158
159 unsigned int i = 0;
160
161 while (font_data->ps[i].name)
162 { if (strcmp (font_data->ps[i].name,mapping->name) == 0) break;
163 i++;
164 }
165
166 if (font_data->ps[i].name) return; /* Entry exists already */
167
168 if ((i & 0x0f) == (unsigned int) 0x0f)
169 { more = (wmfFT_Mapping*) wmf_realloc (API,font_data->ps,(i + 0x11) * sizeof (wmfFT_Mapping));
170
171 if (ERR (API))
172 { WMF_DEBUG (API,"bailing...");
173 return;
174 }
175
176 font_data->ps = more;
177 }
178
179 font_data->ps[i].name = wmf_strdup (API,mapping->name );
180 font_data->ps[i].mapping = wmf_strdup (API,mapping->mapping);
181 font_data->ps[i].encoding = mapping->encoding;
182
183 if (ERR (API))
184 { WMF_DEBUG (API,"bailing...");
185 return;
186 }
187
188 font_data->ps[i].face = 0;
189
190 i++;
191 font_data->ps[i].name = 0;
192 }
193
ipa_font_add_cache(wmfAPI * API,wmfFT_CacheEntry * entry)194 static void ipa_font_add_cache (wmfAPI* API,wmfFT_CacheEntry* entry)
195 { wmfFontmapData* font_data = (wmfFontmapData*) ((wmfFontData*) API->font_data)->user_data;
196
197 wmfFT_CacheEntry* more;
198
199 unsigned int i = 0;
200
201 while (font_data->cache[i].name)
202 { if (strcmp (font_data->cache[i].path,entry->path) == 0) break;
203 i++;
204 }
205
206 if (font_data->cache[i].name) return; /* Entry exists already */
207
208 if ((i & 0x0f) == (unsigned int) 0x0f)
209 { more = (wmfFT_CacheEntry*) wmf_realloc (API,font_data->cache,(i + 0x11) * sizeof (wmfFT_CacheEntry));
210
211 if (ERR (API))
212 { WMF_DEBUG (API,"bailing...");
213 return;
214 }
215
216 font_data->cache = more;
217 }
218
219 font_data->cache[i].name = wmf_strdup (API,entry->name);
220 font_data->cache[i].path = wmf_strdup (API,entry->path);
221 font_data->cache[i].face = entry->face;
222
223 if (ERR (API))
224 { WMF_DEBUG (API,"bailing...");
225 return;
226 }
227
228 i++;
229 font_data->cache[i].name = 0;
230 }
231
wmf_ipa_font_lookup(wmfAPI * API,char * ps_name)232 char* wmf_ipa_font_lookup (wmfAPI* API,char* ps_name)
233 { wmfFontmapData* font_data = (wmfFontmapData*) ((wmfFontData*) API->font_data)->user_data;
234
235 unsigned int i = 0;
236
237 while (font_data->cache[i].name)
238 { if (strcmp (font_data->cache[i].name,ps_name) == 0) break;
239 i++;
240 }
241
242 if (font_data->cache[i].name == 0) return (0);
243
244 return (font_data->cache[i].path);
245 }
246
wmf_ipa_font_init(wmfAPI * API,wmfAPI_Options * options)247 void wmf_ipa_font_init (wmfAPI* API,wmfAPI_Options* options)
248 { wmfFontData* font_data = 0;
249
250 wmfFontmapData* fontmap_data = 0;
251
252 unsigned int i;
253 unsigned int count;
254
255 API->font_data = wmf_malloc (API,sizeof (wmfFontData));
256
257 if (ERR (API))
258 { WMF_DEBUG (API,"bailing...");
259 return;
260 }
261
262 font_data = (wmfFontData*) API->font_data;
263
264 font_data->map = wmf_ipa_font_map;
265
266 font_data->stringwidth = wmf_ipa_font_stringwidth;
267
268 font_data->user_data = wmf_malloc (API,sizeof (wmfFontmapData));
269
270 if (ERR (API))
271 { WMF_DEBUG (API,"bailing...");
272 return;
273 }
274
275 fontmap_data = (wmfFontmapData*) font_data->user_data;
276
277 API->fonts = (char**) wmf_malloc (API,16 * sizeof (char*));
278
279 if (ERR (API))
280 { WMF_DEBUG (API,"bailing...");
281 return;
282 }
283
284 API->fonts[0] = 0;
285
286 fontmap_data->fontdirs = (char**) wmf_malloc (API,16 * sizeof (char*));
287
288 if (ERR (API))
289 { WMF_DEBUG (API,"bailing...");
290 return;
291 }
292
293 fontmap_data->fontdirs[0] = 0;
294
295 fontmap_data->wmf = (wmfFontMap*) wmf_malloc (API,16 * sizeof (wmfFontMap));
296
297 if (ERR (API))
298 { WMF_DEBUG (API,"bailing...");
299 return;
300 }
301
302 fontmap_data->wmf[0].name = 0;
303
304 if ((API->flags & WMF_OPT_FONTMAP) && options->font.wmf)
305 { i = 0;
306 while (options->font.wmf[i].name)
307 { ipa_font_add_wmf (API,&(options->font.wmf[i]));
308
309 if (ERR (API)) break;
310
311 i++;
312 }
313 if (ERR (API))
314 { WMF_DEBUG (API,"bailing...");
315 return;
316 }
317 }
318
319 count = sizeof WMFFontMap / sizeof (wmfFontMap);
320
321 for (i = 0; i < count; i++)
322 { ipa_font_add_wmf (API,&(WMFFontMap[i]));
323
324 if (ERR (API)) break;
325 }
326 if (ERR (API))
327 { WMF_DEBUG (API,"bailing...");
328 return;
329 }
330
331 fontmap_data->sub = (wmfMapping*) wmf_malloc (API,16 * sizeof (wmfMapping));
332
333 if (ERR (API))
334 { WMF_DEBUG (API,"bailing...");
335 return;
336 }
337
338 fontmap_data->sub[0].name = 0;
339
340 if ((API->flags & WMF_OPT_FONTMAP) && options->font.sub)
341 { i = 0;
342 while (options->font.sub[i].name)
343 { ipa_font_add_sub (API,&(options->font.sub[i]));
344
345 if (ERR (API)) break;
346
347 i++;
348 }
349 if (ERR (API))
350 { WMF_DEBUG (API,"bailing...");
351 return;
352 }
353 }
354
355 count = sizeof SubFontMap / sizeof (wmfMapping);
356
357 for (i = 0; i < count; i++)
358 { ipa_font_add_sub (API,&(SubFontMap[i]));
359
360 if (ERR (API)) break;
361 }
362 if (ERR (API))
363 { WMF_DEBUG (API,"bailing...");
364 return;
365 }
366
367 fontmap_data->ps = (wmfFT_Mapping*) wmf_malloc (API,16 * sizeof (wmfFT_Mapping));
368
369 if (ERR (API))
370 { WMF_DEBUG (API,"bailing...");
371 return;
372 }
373
374 fontmap_data->ps[0].name = 0;
375
376 fontmap_data->cache = (wmfFT_CacheEntry*) wmf_malloc (API,16 * sizeof (wmfFT_CacheEntry));
377
378 if (ERR (API))
379 { WMF_DEBUG (API,"bailing...");
380 return;
381 }
382
383 fontmap_data->cache[0].name = 0;
384
385 if ((API->flags & WMF_OPT_FONTMAP) && options->font.ps)
386 { i = 0;
387 while (options->font.ps[i].name)
388 { ipa_font_add_ps (API,&(options->font.ps[i]));
389
390 if (ERR (API)) break;
391
392 i++;
393 }
394 if (ERR (API))
395 { WMF_DEBUG (API,"bailing...");
396 return;
397 }
398 }
399
400 count = 13;
401
402 for (i = 0; i < count; i++)
403 { ipa_font_add_ps (API,&(PSFontMap[i]));
404
405 if (ERR (API)) break;
406 }
407 if (ERR (API))
408 { WMF_DEBUG (API,"bailing...");
409 return;
410 }
411
412 if (FT_Init_FreeType (&(fontmap_data->Library)) != 0)
413 { WMF_ERROR (API,"Failed to initialize freetype...");
414 API->err = wmf_E_DeviceError;
415 fontmap_data->Library = 0;
416 }
417
418 API->flags |= API_FTLIBRARY_OPEN;
419
420 fontmap_data->FD.max = 0;
421 fontmap_data->FD.len = 0;
422
423 fontmap_data->FD.FI = 0;
424
425 if (API->flags & WMF_OPT_SYS_FONTS)
426 { if (API->flags & WMF_OPT_SYS_FONTMAP)
427 { wmf_ipa_font_map_xml (API,&(fontmap_data->FD),options->sys_fontmap_file);
428 }
429 else
430 { wmf_ipa_font_map_xml (API,&(fontmap_data->FD),WMF_SYS_FONTMAP);
431 }
432 }
433
434 if (API->flags & WMF_OPT_XTRA_FONTS)
435 { if (API->flags & WMF_OPT_XTRA_FONTMAP)
436 { wmf_ipa_font_map_xml (API,&(fontmap_data->FD),options->xtra_fontmap_file);
437 }
438 else
439 { wmf_ipa_font_map_xml (API,&(fontmap_data->FD),WMF_XTRA_FONTMAP);
440 }
441 }
442
443 fontmap_data->GS.max = 0;
444 fontmap_data->GS.len = 0;
445
446 fontmap_data->GS.FI = 0;
447
448 if (API->flags & WMF_OPT_GS_FONTMAP)
449 { wmf_ipa_font_map_gs (API,&(fontmap_data->GS),options->gs_fontmap_file);
450 }
451 else
452 { wmf_ipa_font_map_gs (API,&(fontmap_data->GS),WMF_GS_FONTMAP);
453 }
454 }
455
wmf_ipa_font_map_set(wmfAPI * API,wmfMap map)456 void wmf_ipa_font_map_set (wmfAPI* API,wmfMap map)
457 { wmfFontData* font_data = (wmfFontData*) API->font_data;
458
459 font_data->map = map;
460 }
461
wmf_ipa_font_dir(wmfAPI * API,char * fontdir)462 void wmf_ipa_font_dir (wmfAPI* API,char* fontdir)
463 { wmfFontmapData* font_data = (wmfFontmapData*) ((wmfFontData*) API->font_data)->user_data;
464
465 char** more;
466
467 unsigned int i = 0;
468
469 while (font_data->fontdirs[i])
470 { if (strcmp (font_data->fontdirs[i],fontdir) == 0) break;
471 i++;
472 }
473
474 if (font_data->fontdirs[i]) return; /* Entry exists already */
475
476 if ((i & 0x0f) == (unsigned int) 0x0f)
477 { more = (char**) wmf_realloc (API,font_data->fontdirs,(i + 0x11) * sizeof (char*));
478
479 if (ERR (API))
480 { WMF_DEBUG (API,"bailing...");
481 return;
482 }
483
484 font_data->fontdirs = more;
485 }
486
487 font_data->fontdirs[i] = wmf_strdup (API,fontdir);
488
489 if (ERR (API))
490 { WMF_DEBUG (API,"bailing...");
491 return;
492 }
493
494 i++;
495 font_data->fontdirs[i] = 0;
496 }
497
ipa_font_add_api(wmfAPI * API,char * name)498 static void ipa_font_add_api (wmfAPI* API,char* name)
499 { char** more;
500
501 unsigned int i = 0;
502
503 while (API->fonts[i])
504 { if (strcmp (API->fonts[i],name) == 0) break;
505 i++;
506 }
507
508 if (API->fonts[i]) return; /* Entry exists already */
509
510 if ((i & 0x0f) == (unsigned int) 0x0f)
511 { more = (char**) wmf_realloc (API,API->fonts,(i + 0x11) * sizeof (char*));
512
513 if (ERR (API))
514 { WMF_DEBUG (API,"bailing...");
515 return;
516 }
517
518 API->fonts = more;
519 }
520
521 API->fonts[i] = wmf_strdup (API,name);
522
523 if (ERR (API))
524 { WMF_DEBUG (API,"bailing...");
525 return;
526 }
527
528 i++;
529 API->fonts[i] = 0;
530 }
531
532 /* Returns width of string in points, assuming (unstretched) font size of 1pt
533 * WARNING: This is not very accurate. If anyone has a better idea, then...
534 */
wmf_ipa_font_stringwidth(wmfAPI * API,wmfFont * font,char * str)535 float wmf_ipa_font_stringwidth (wmfAPI* API,wmfFont* font,char* str)
536 { FT_Face face = WMF_FONT_FTFACE (font);
537
538 if (!face) return 0.0;
539
540 FT_Vector delta;
541
542 FT_Bool use_kerning;
543
544 FT_UInt glyph_index;
545 FT_UInt previous;
546
547 float width;
548
549 int i;
550 int length;
551
552 if ((face == 0) || (str == 0))
553 { WMF_DEBUG (API,"wmf_ipa_font_stringwidth: NULL face or str - ??");
554 return 0;
555 }
556
557 FT_Set_Char_Size (face,0,12 * 64,300,100);
558
559 FT_Set_Transform (face,0,0);
560
561 use_kerning = FT_HAS_KERNING (face);
562
563 previous = 0;
564
565 width = 0;
566
567 length = strlen (str);
568
569 for (i = 0; i < length; i++)
570 { /* convert character code to glyph index */
571 /* ==== Should this be unsigned ?? ==== */
572
573 glyph_index = FT_Get_Char_Index (face,str[i]);
574
575 if (use_kerning && previous && glyph_index)
576 { FT_Get_Kerning (face,previous,glyph_index,0,&delta);
577
578 width += (float) (delta.x >> 6);
579 }
580
581 if (glyph_index)
582 { /* load glyph image into the slot. DO NOT RENDER IT! */
583 FT_Load_Glyph (face,glyph_index,FT_LOAD_DEFAULT);
584
585 if (face->glyph) width += (float) (face->glyph->advance.x >> 6);
586 }
587
588 previous = glyph_index;
589 }
590
591 return (width*72/(300*12));
592 }
593
ipa_char_position(wmfFont * font,char * str,char * last)594 static float ipa_char_position (wmfFont* font,char* str,char* last)
595 { FT_Face face = WMF_FONT_FTFACE (font);
596
597 if (!face) return 0.0;
598
599 FT_Vector delta;
600
601 FT_Bool use_kerning;
602
603 FT_UInt glyph_index;
604 FT_UInt previous;
605
606 float width;
607
608 char* ptr;
609
610 FT_Set_Char_Size (face,0,12 * 64,300,100);
611
612 FT_Set_Transform (face,0,0);
613
614 use_kerning = FT_HAS_KERNING (face);
615
616 previous = 0;
617
618 width = 0;
619
620 for (ptr = str; ptr <= last; ptr++)
621 { /* convert character code to glyph index */ /* === Should this be unsigned ?? ==== */
622 glyph_index = FT_Get_Char_Index (face,(*ptr));
623
624 if (use_kerning && previous && glyph_index)
625 { FT_Get_Kerning (face,previous,glyph_index,0,&delta);
626
627 width += (float) (delta.x >> 6);
628 }
629
630 if (ptr == last) break;
631
632 /* load glyph image into the slot. DO NOT RENDER IT! */
633 FT_Load_Glyph (face,glyph_index,FT_LOAD_DEFAULT);
634
635 width += (float) (face->glyph->advance.x >> 6);
636
637 previous = glyph_index;
638 }
639
640 return (width*72/(300*12));
641 }
642
wmf_ipa_draw_text(wmfAPI * API,wmfDrawText_t * draw_text,wmfCharDrawer ipa_draw_text)643 void wmf_ipa_draw_text (wmfAPI* API,wmfDrawText_t* draw_text,wmfCharDrawer ipa_draw_text)
644 { wmfDrawText_t draw_char;
645
646 size_t i;
647 size_t length;
648
649 char buffer[2];
650
651 float text_width;
652
653 float cos_theta;
654 float sin_theta;
655
656 double theta;
657
658 length = strlen (draw_text->str);
659
660 theta = - WMF_TEXT_ANGLE (draw_text->dc->font);
661
662 cos_theta = (float) cos (theta);
663 sin_theta = (float) sin (theta);
664
665 for (i = 0; i < length; i++)
666 { draw_char.dc = draw_text->dc;
667
668 buffer[0] = draw_text->str[i];
669 buffer[1] = 0;
670
671 text_width = ipa_char_position (draw_text->dc->font,draw_text->str,draw_text->str+i);
672
673 text_width = (float) ((double) text_width * draw_text->font_height * draw_text->font_ratio);
674
675 draw_char.pt.x = draw_text->pt.x + text_width * cos_theta;
676 draw_char.pt.y = draw_text->pt.y + text_width * sin_theta;
677
678 draw_char.TL.x = 0;
679 draw_char.TL.y = 0;
680 draw_char.BR.x = 0;
681 draw_char.BR.y = 0;
682
683 draw_char.bbox.TL.x = 0;
684 draw_char.bbox.TL.y = 0;
685 draw_char.bbox.TR.x = 0;
686 draw_char.bbox.TR.y = 0;
687 draw_char.bbox.BR.x = 0;
688 draw_char.bbox.BR.y = 0;
689 draw_char.bbox.BL.x = 0;
690 draw_char.bbox.BL.y = 0;
691
692 draw_char.str = buffer;
693
694 draw_char.flags = draw_text->flags;
695
696 draw_char.font_height = draw_text->font_height;
697 draw_char.font_ratio = draw_text->font_ratio;
698
699 ipa_draw_text (API,&draw_char);
700 }
701 }
702
wmf_ipa_font_map_xml(wmfAPI * API,wmfXML_FontData * FD,char * xmlfontmap)703 void wmf_ipa_font_map_xml (wmfAPI* API,wmfXML_FontData* FD,char* xmlfontmap)
704 { FD->max = 0;
705 FD->len = 0;
706
707 FD->FI = 0;
708
709 #ifdef HAVE_EXPAT
710 exmlfontmap_read (API,FD,xmlfontmap);
711 return;
712 #endif /* HAVE_EXPAT */
713 #ifdef HAVE_LIBXML2
714 xml2fontmap_read (API,FD,xmlfontmap);
715 return;
716 #endif /* HAVE_LIBXML2 */
717 WMF_DEBUG (API,"warning: no XML support!");
718 }
719
720 #ifdef HAVE_EXPAT
721
722 #include <expat.h>
723
724 #define EXML_BUFSIZE 1024
725
exml_start(void * user_data,const char * tag,const char ** attributes)726 static void exml_start (void* user_data,const char* tag,const char** attributes)
727 { const char** attr;
728
729 EXML_FontData* exml_data = (EXML_FontData*) user_data;
730
731 wmfAPI* API = exml_data->API;
732
733 wmfXML_FontData* FD = exml_data->FD;
734
735 wmfXML_FontInfo* more = 0;
736
737 wmfXML_FontInfo FI;
738
739 if ((tag == 0) || (attributes == 0)) return;
740
741 if (strcmp (tag,"font")) return;
742
743 FI.format = 0;
744 FI.metrics = 0;
745 FI.glyphs = 0;
746 FI.name = 0;
747 FI.fullname = 0;
748 FI.familyname = 0;
749 FI.weight = 0;
750 FI.version = 0;
751 FI.alias = 0;
752
753 attr = attributes;
754 while (*attr)
755 { if (strcmp ((*attr),"format") == 0)
756 { attr++;
757 FI.format = wmf_strdup (API,(char*) (*attr));
758 }
759 else if (strcmp ((*attr),"metrics") == 0)
760 { attr++;
761 FI.metrics = wmf_strdup (API,(char*) (*attr));
762 }
763 else if (strcmp ((*attr),"glyphs") == 0)
764 { attr++;
765 FI.glyphs = wmf_strdup (API,(char*) (*attr));
766 }
767 else if (strcmp ((*attr),"name") == 0)
768 { attr++;
769 FI.name = wmf_strdup (API,(char*) (*attr));
770 }
771 else if (strcmp ((*attr),"fullname") == 0)
772 { attr++;
773 FI.fullname = wmf_strdup (API,(char*) (*attr));
774 }
775 else if (strcmp ((*attr),"familyname") == 0)
776 { attr++;
777 FI.familyname = wmf_strdup (API,(char*) (*attr));
778 }
779 else if (strcmp ((*attr),"weight") == 0)
780 { attr++;
781 FI.weight = wmf_strdup (API,(char*) (*attr));
782 }
783 else if (strcmp ((*attr),"version") == 0)
784 { attr++;
785 FI.version = wmf_strdup (API,(char*) (*attr));
786 }
787 else if (strcmp ((*attr),"alias") == 0)
788 { attr++;
789 FI.alias = wmf_strdup (API,(char*) (*attr));
790 }
791 else attr++;
792 attr++;
793 }
794
795 if (FD->len == FD->max)
796 { more = wmf_realloc (API,FD->FI,(FD->max + 32) * sizeof (wmfXML_FontInfo));
797 if (more)
798 { FD->FI = more;
799 FD->max += 32;
800 }
801 }
802 if (FD->len < FD->max)
803 { FD->FI[FD->len] = FI;
804 FD->len++;
805 }
806 }
807
exmlfontmap_read(wmfAPI * API,wmfXML_FontData * FD,char * xmlfontmap)808 static void exmlfontmap_read (wmfAPI* API,wmfXML_FontData* FD,char* xmlfontmap)
809 { int status = 0;
810 int length;
811
812 char buffer[EXML_BUFSIZE];
813
814 void* user_data;
815
816 FILE* in;
817
818 EXML_FontData exml_data;
819
820 XML_Parser exml;
821
822 FD->max = 32;
823 FD->len = 0;
824
825 FD->FI = wmf_malloc (API,FD->max * sizeof (wmfXML_FontInfo));
826
827 if (ERR (API))
828 { WMF_DEBUG (API,"bailing...");
829 FD->max = 0;
830 return;
831 }
832
833 in = fopen (xmlfontmap,"r");
834
835 if (in == 0)
836 { WMF_DEBUG (API,"unable to open xml-fontmap");
837 FD->max = 0;
838 wmf_free (API,FD->FI);
839 FD->FI = 0;
840 return;
841 }
842
843 exml = XML_ParserCreate (0);
844
845 if (exml == 0)
846 { WMF_DEBUG (API,"error creating expat-xml parser");
847 FD->max = 0;
848 wmf_free (API,FD->FI);
849 FD->FI = 0;
850 fclose (in);
851 return;
852 }
853
854 exml_data.API = API;
855 exml_data.FD = FD;
856
857 user_data = (void*) (&exml_data);
858
859 XML_SetUserData (exml,user_data);
860
861 XML_SetStartElementHandler (exml,exml_start);
862
863 while (fgets (buffer,EXML_BUFSIZE,in))
864 { length = (int) strlen (buffer);
865
866 if (XML_Parse (exml,buffer,length,0) == 0)
867 { WMF_DEBUG (API,"expat-xml: error parsing xml fontmap");
868 status = 1;
869 break;
870 }
871 }
872 if (status == 0) XML_Parse (exml,buffer,0,1);
873
874 XML_ParserFree (exml);
875
876 fclose (in);
877
878 if (FD->len == 0)
879 { FD->max = 0;
880 wmf_free (API,FD->FI);
881 FD->FI = 0;
882 }
883 }
884 #endif /* HAVE_EXPAT */
885
886 #ifdef HAVE_LIBXML2
887
888 #include <libxml/parser.h>
889 #include <libxml/parserInternals.h>
890
xml2_start(void * user_data,const char * tag,const char ** attributes)891 static void xml2_start (void* user_data,const char* tag,const char** attributes)
892 { const char** attr;
893
894 XML2_FontData* xml2_data = (XML2_FontData*) user_data;
895
896 wmfAPI* API = xml2_data->API;
897
898 wmfXML_FontData* FD = xml2_data->FD;
899
900 wmfXML_FontInfo* more = 0;
901
902 wmfXML_FontInfo FI;
903
904 if ((tag == 0) || (attributes == 0)) return;
905
906 if (strcmp (tag,"font")) return;
907
908 FI.format = 0;
909 FI.metrics = 0;
910 FI.glyphs = 0;
911 FI.name = 0;
912 FI.fullname = 0;
913 FI.familyname = 0;
914 FI.weight = 0;
915 FI.version = 0;
916 FI.alias = 0;
917
918 attr = attributes;
919 while (*attr)
920 { if (strcmp ((*attr),"format") == 0)
921 { attr++;
922 FI.format = wmf_strdup (API,(char*) (*attr));
923 }
924 else if (strcmp ((*attr),"metrics") == 0)
925 { attr++;
926 FI.metrics = wmf_strdup (API,(char*) (*attr));
927 }
928 else if (strcmp ((*attr),"glyphs") == 0)
929 { attr++;
930 FI.glyphs = wmf_strdup (API,(char*) (*attr));
931 }
932 else if (strcmp ((*attr),"name") == 0)
933 { attr++;
934 FI.name = wmf_strdup (API,(char*) (*attr));
935 }
936 else if (strcmp ((*attr),"fullname") == 0)
937 { attr++;
938 FI.fullname = wmf_strdup (API,(char*) (*attr));
939 }
940 else if (strcmp ((*attr),"familyname") == 0)
941 { attr++;
942 FI.familyname = wmf_strdup (API,(char*) (*attr));
943 }
944 else if (strcmp ((*attr),"weight") == 0)
945 { attr++;
946 FI.weight = wmf_strdup (API,(char*) (*attr));
947 }
948 else if (strcmp ((*attr),"version") == 0)
949 { attr++;
950 FI.version = wmf_strdup (API,(char*) (*attr));
951 }
952 else if (strcmp ((*attr),"alias") == 0)
953 { attr++;
954 FI.alias = wmf_strdup (API,(char*) (*attr));
955 }
956 else attr++;
957 attr++;
958 }
959
960 if (FD->len == FD->max)
961 { more = wmf_realloc (API,FD->FI,(FD->max + 32) * sizeof (wmfXML_FontInfo));
962 if (more)
963 { FD->FI = more;
964 FD->max += 32;
965 }
966 }
967 if (FD->len < FD->max)
968 { FD->FI[FD->len] = FI;
969 FD->len++;
970 }
971 }
972
xml2fontmap_read(wmfAPI * API,wmfXML_FontData * FD,char * xmlfontmap)973 static void xml2fontmap_read (wmfAPI* API,wmfXML_FontData* FD,char* xmlfontmap)
974 { XML2_FontData xml2_data;
975
976 xmlParserCtxtPtr ctxt;
977
978 xmlSAXHandler sax;
979
980 memset ((void*) (&sax), 0, sizeof (xmlSAXHandler));
981
982 sax.startElement = (startElementSAXFunc) xml2_start;
983
984 xml2_data.API = API;
985 xml2_data.FD = FD;
986
987 ctxt = xmlCreateFileParserCtxt (xmlfontmap);
988
989 if (ctxt == 0) return;
990
991 ctxt->sax = &sax;
992 ctxt->userData = (void*) (&xml2_data);
993
994 xmlParseDocument (ctxt);
995
996 ctxt->sax = 0;
997
998 xmlFreeParserCtxt (ctxt);
999 }
1000
1001 #endif /* HAVE_LIBXML2 */
1002
wmf_ipa_font_map_gs(wmfAPI * API,wmfGS_FontData * FD,char * gsfontmap)1003 void wmf_ipa_font_map_gs (wmfAPI* API,wmfGS_FontData* FD,char* gsfontmap)
1004 { ipa_font_gs_file (API,FD,gsfontmap);
1005
1006 if (ERR (API))
1007 { WMF_DEBUG (API,"bailing...");
1008 return;
1009 }
1010
1011 /* TODO ?? */
1012 }
1013
ipa_font_gs_file(wmfAPI * API,wmfGS_FontData * FD,char * file)1014 static void ipa_font_gs_file (wmfAPI* API,wmfGS_FontData* FD,char* file)
1015 { char* line = 0;
1016
1017 char* name = 0;
1018 char* alias = 0;
1019
1020 FILE* in = 0;
1021
1022 in = fopen (file,"r");
1023
1024 if (in == 0)
1025 { WMF_DEBUG (API,"ipa_font_gs_file: unable to read ghostscript fontmap!\n");
1026 return;
1027 }
1028
1029 while (wmf_true)
1030 { line = ipa_font_gs_readline (API,in);
1031
1032 if (line == 0) break;
1033
1034 if (*line)
1035 { name = line;
1036 alias = line;
1037
1038 while (!isspace ((int) (*alias)))
1039 { if ((*alias) == 0) break;
1040 alias++;
1041 }
1042 if (*alias)
1043 { (*alias) = 0;
1044 alias++;
1045 }
1046
1047 ipa_font_gs_add (API,FD,name,alias);
1048 }
1049
1050 wmf_free (API,line);
1051 }
1052
1053 fclose (in);
1054 }
1055
ipa_font_gs_add(wmfAPI * API,wmfGS_FontData * FD,char * name,char * alias)1056 static void ipa_font_gs_add (wmfAPI* API,wmfGS_FontData* FD,char* name,char* alias)
1057 { wmfGS_FontInfo* more = 0;
1058
1059 wmf_bool_t fMatched;
1060
1061 unsigned int i;
1062
1063 if ((name == 0) || (alias == 0)) return;
1064
1065 if (name[0] != '/') return;
1066
1067 if ((alias[0] != '/') && (alias[0] != '(')) return;
1068
1069 if ((alias[0] == '(') && (alias[strlen (alias) - 1] != ')')) return;
1070
1071 if (FD->FI == 0)
1072 { FD->FI = (wmfGS_FontInfo*) wmf_calloc (API,0x20,sizeof (wmfGS_FontInfo));
1073
1074 if (ERR (API))
1075 { WMF_DEBUG (API,"bailing...");
1076 return;
1077 }
1078
1079 FD->max = 0x20;
1080 FD->len = 0;
1081 }
1082
1083 fMatched = wmf_false;
1084 for (i = 0; i < FD->len; i++)
1085 { if (strcmp (FD->FI[i].name,name+1) == 0)
1086 { wmf_free (API,FD->FI[i].alias);
1087 FD->FI[i].alias = wmf_strdup (API,alias);
1088 fMatched = wmf_true;
1089 break;
1090 }
1091 }
1092 if (fMatched) return;
1093
1094 if (FD->len == FD->max)
1095 { more = (wmfGS_FontInfo*) wmf_realloc (API,FD->FI,(FD->max+0x20) * sizeof (wmfGS_FontInfo));
1096
1097 if (ERR (API))
1098 { WMF_DEBUG (API,"bailing...");
1099 return;
1100 }
1101
1102 FD->FI = more;
1103
1104 FD->max += 0x20;
1105 }
1106
1107 FD->FI[FD->len].name = wmf_strdup (API,name+1);
1108 FD->FI[FD->len].alias = wmf_strdup (API,alias);
1109
1110 FD->len++;
1111 }
1112
ipa_font_gs_alias(wmfGS_FontData * FD,char * name)1113 static char* ipa_font_gs_alias (wmfGS_FontData* FD,char* name)
1114 { char* alias = 0;
1115
1116 unsigned int i;
1117
1118 for (i = 0; i < FD->len; i++)
1119 { if (strcmp (FD->FI[i].name,name) == 0)
1120 { alias = FD->FI[i].alias;
1121 break;
1122 }
1123 }
1124
1125 return (alias);
1126 }
1127
ipa_font_gs_readline(wmfAPI * API,FILE * in)1128 static char* ipa_font_gs_readline (wmfAPI* API,FILE* in)
1129 { char buf[128];
1130
1131 char* line = 0;
1132 char* more = 0;
1133 char* ptr = 0;
1134 char* ptr1 = 0;
1135 char* ptr2 = 0;
1136
1137 wmf_bool_t fBackSlash;
1138 wmf_bool_t fContinue;
1139 wmf_bool_t fReadExtra = wmf_false;
1140
1141 if (fgets (buf,128,in) == 0) return (0);
1142
1143 fBackSlash = wmf_false;
1144 fContinue = wmf_true;
1145 ptr = buf;
1146 while (*ptr)
1147 { if (((*ptr) == '%') && (!fBackSlash))
1148 { fContinue = wmf_false;
1149 if (buf[strlen(buf)-1] != '\n')
1150 { fReadExtra = wmf_true;
1151 }
1152 else
1153 { fReadExtra = wmf_false;
1154 }
1155 (*ptr) = 0;
1156 break;
1157 }
1158 if ((*ptr) == '\n')
1159 { if (fBackSlash)
1160 { fContinue = wmf_true;
1161 ptr--;
1162 }
1163 else
1164 { fContinue = wmf_false;
1165 }
1166 (*ptr) = 0;
1167 break;
1168 }
1169 if ((*ptr) == '\\')
1170 { fBackSlash = wmf_true;
1171 }
1172 else
1173 { fBackSlash = wmf_false;
1174 }
1175 ptr++;
1176 }
1177
1178 line = wmf_strdup (API,buf);
1179
1180 if (line == 0) return (line);
1181
1182 while (fContinue)
1183 { if (fgets (buf,10,in) == 0)
1184 { wmf_free (API,line);
1185 return (0);
1186 }
1187
1188 fBackSlash = wmf_false;
1189 fContinue = wmf_true;
1190 ptr = buf;
1191 while (*ptr)
1192 { if (((*ptr) == '%') && (!fBackSlash))
1193 { fContinue = wmf_false;
1194 fReadExtra = wmf_true;
1195 (*ptr) = 0;
1196 break;
1197 }
1198 if ((*ptr) == '\n')
1199 { if (fBackSlash)
1200 { fContinue = wmf_true;
1201 ptr--;
1202 }
1203 else
1204 { fContinue = wmf_false;
1205 }
1206 (*ptr) = 0;
1207 break;
1208 }
1209 if ((*ptr) == '\\')
1210 { fBackSlash = wmf_true;
1211 }
1212 else
1213 { fBackSlash = wmf_false;
1214 }
1215 ptr++;
1216 }
1217
1218 more = wmf_str_append (API,line,buf);
1219
1220 wmf_free (API,line);
1221
1222 line = more;
1223
1224 if (line == 0)
1225 {
1226 break;
1227 }
1228 }
1229
1230 if (line == 0) return (0);
1231
1232 if (fReadExtra)
1233 {
1234 while (buf[strlen(buf)-1] != '\n')
1235 if (fgets (buf,128,in) == 0)
1236 break;
1237 }
1238
1239 /* Strip the string */
1240
1241 ptr1 = line;
1242 ptr2 = line;
1243 while (*ptr2)
1244 { if (!isspace ((int) (*ptr2))) break;
1245 ptr2++;
1246 }
1247 while (*ptr2)
1248 { if (isspace ((int) (*ptr2))) break;
1249 (*ptr1) = (*ptr2);
1250 ptr1++;
1251 ptr2++;
1252 }
1253 if (*ptr2)
1254 { (*ptr1) = (*ptr2);
1255 ptr1++;
1256 ptr2++;
1257 }
1258 while (*ptr2)
1259 { if (!isspace ((int) (*ptr2))) break;
1260 ptr2++;
1261 }
1262 while (*ptr2)
1263 { if (isspace ((int) (*ptr2))) break;
1264 (*ptr1) = (*ptr2);
1265 ptr1++;
1266 ptr2++;
1267 }
1268 (*ptr1) = 0;
1269
1270 while ((--ptr1) >= line)
1271 { if (!isspace ((int) (*ptr1))) break;
1272 (*ptr1) = 0;
1273 }
1274
1275 ptr1 = line;
1276 ptr2 = line;
1277 while (*ptr2)
1278 { if ((*ptr2) == '%') ptr1--;
1279 (*ptr1) = (*ptr2);
1280 ptr1++;
1281 ptr2++;
1282 }
1283 (*ptr1) = 0;
1284
1285 return (line);
1286 }
1287
1288 /**
1289 * This is the fun bit.
1290 *
1291 * @param API the API handle
1292 * @param font WMF font object: font's \b family \b name, \b italics flag, and the \b weight
1293 *
1294 * Other inputs include: a ghostscript-style Fontmap, and up to two XML RedHat-style fontmaps. (These are
1295 * all parsed earlier.) There are also the fallback 13 standard postscript fonts. And then there is a list
1296 * of font directories to search for fonts.
1297 *
1298 * \b libwmf requires fonts to have a postscript name, and maintains an internal cache of glyphs path and
1299 * \b freetype font face, keyed to postscript font name. Unfortunately, although the XML fontmaps do have
1300 * font \b family \b name, the GS fontmap does not. In the latter, therefore, matching WMF font info to
1301 * postscript font name is hit-and-miss.
1302 */
wmf_ipa_font_map(wmfAPI * API,wmfFont * font)1303 void wmf_ipa_font_map (wmfAPI* API,wmfFont* font)
1304 { wmfIPAFont* ipa_font = 0;
1305
1306 char* mapping = 0;
1307
1308 if (font == 0) return;
1309 if (font->user_data == 0)
1310 { font->user_data = wmf_malloc (API,sizeof (wmfIPAFont));
1311
1312 if (ERR (API))
1313 { WMF_DEBUG (API,"bailing...");
1314 return;
1315 }
1316 }
1317
1318 ipa_font = (wmfIPAFont*) font->user_data;
1319
1320 ipa_font->ps_name = 0;
1321 ipa_font->ft_face = 0;
1322
1323 /* Check system fonts for match and load font face if found...
1324 */
1325 if (ipa_font_sys_face (API,font,ipa_font_sys_map (API,font))) return;
1326
1327 /* Check GS fontmap for match and load font face if found...
1328 */
1329 if (ipa_font_gs_face (API,font,ipa_font_gs_map (API,font))) return;
1330
1331 /* otherwise, load one of standard 13...
1332 */
1333 mapping = ipa_font_std (API,font);
1334
1335 if (mapping)
1336 { if (ipa_font_face (API,font,mapping)) return;
1337 }
1338
1339 WMF_ERROR (API,"wmf_ipa_font_map: failed to load *any* font!");
1340 API->err = wmf_E_BadFile;
1341 }
1342
1343 /**
1344 * Searches XML Fontmap for font-name matching WMF's font name.
1345 *
1346 * Basically, this is matching a font's family name + italic + weight parameters to a postscript name.
1347 * Font weight is problematic.
1348 */
ipa_font_sys_map(wmfAPI * API,wmfFont * font)1349 static wmfXML_FontInfo* ipa_font_sys_map (wmfAPI* API,wmfFont* font)
1350 { wmfFontmapData* font_data = (wmfFontmapData*) ((wmfFontData*) API->font_data)->user_data;
1351
1352 wmfXML_FontInfo* FI = 0;
1353
1354 unsigned int i;
1355
1356 for (i = 0; i < font_data->FD.len; i++)
1357 { if (strcmp (font->lfFaceName,font_data->FD.FI[i].familyname) == 0)
1358 { if ( wmf_strstr (font_data->FD.FI[i].fullname,"Italic")
1359 || wmf_strstr (font_data->FD.FI[i].fullname,"Oblique"))
1360 { if (font->lfItalic != 1) continue;
1361 }
1362 else
1363 { if (font->lfItalic == 1) continue;
1364 }
1365 if ( wmf_strstr (font_data->FD.FI[i].weight,"Bold")
1366 || wmf_strstr (font_data->FD.FI[i].weight,"Demi")) /* or "Medium" ?? */
1367 { if (font->lfWeight <= 550) continue;
1368 }
1369 else
1370 { if (font->lfWeight > 550) continue;
1371 }
1372 FI = &(font_data->FD.FI[i]);
1373 break;
1374 }
1375 }
1376
1377 return (FI);
1378 }
1379
1380 /**
1381 * Checks XML Fontmap entry is valid before loading face.
1382 */
ipa_font_sys_face(wmfAPI * API,wmfFont * font,wmfXML_FontInfo * FI)1383 static FT_Face ipa_font_sys_face (wmfAPI* API,wmfFont* font,wmfXML_FontInfo* FI)
1384 {
1385 #if 0
1386 wmfFontmapData* font_data = (wmfFontmapData*) ((wmfFontData*) API->font_data)->user_data;
1387 struct stat stat_buf;
1388 #endif
1389
1390 FT_Face face = 0;
1391
1392 if (FI == 0) return (0);
1393
1394 if (FI->name == 0)
1395 { WMF_DEBUG (API,"no postscript name in system-font record?");
1396 return (0);
1397 }
1398
1399 if (FI->glyphs == 0)
1400 { WMF_DEBUG (API,"no glyphs in system-font record?");
1401 return (0);
1402 }
1403
1404 face = ipa_font_face (API,font,FI->name);
1405
1406 return (face);
1407 }
1408
1409 /**
1410 * Searches GS Fontmap for font-name matching WMF's font name.
1411 *
1412 * Basically, this is matching a font's family name + italic + weight parameters to a postscript name.
1413 * I have decided to test only the first word of the family name, so incorrect matches are probably.
1414 * Font weight is problematic as well.
1415 */
ipa_font_gs_map(wmfAPI * API,wmfFont * font)1416 static wmfGS_FontInfo* ipa_font_gs_map (wmfAPI* API,wmfFont* font)
1417 { wmfFontmapData* font_data = (wmfFontmapData*) ((wmfFontData*) API->font_data)->user_data;
1418
1419 wmfGS_FontData* GS = &(font_data->GS);
1420 wmfGS_FontInfo* FI = 0;
1421
1422 wmf_bool_t require_italic;
1423 wmf_bool_t require_bold;
1424 wmf_bool_t found_italic;
1425 wmf_bool_t found_bold;
1426
1427 unsigned int name_length = 0;
1428 unsigned int i;
1429
1430 char* name = 0;
1431 char* ptr = 0;
1432
1433 if (GS->len == 0) return (0);
1434
1435 name = font->lfFaceName;
1436
1437 if (name == 0 || name[0] == 0)
1438 name = "Times";
1439
1440 /* Find first white-space character or eol
1441 */
1442 ptr = name;
1443 while (!isspace (*ptr))
1444 { if ((*ptr) == 0) break;
1445 ptr++;
1446 name_length++;
1447 }
1448
1449 if (name_length == 0)
1450 { WMF_DEBUG (API,"Unexpectedly short font name?");
1451 API->err = wmf_E_Glitch;
1452 return (0);
1453 }
1454
1455 require_italic = ((font->lfItalic == 1) ? wmf_true : wmf_false);
1456
1457 require_bold = ((font->lfWeight > 550) ? wmf_true : wmf_false);
1458
1459 /* Search for match in GS Fontmap list
1460 */
1461 for (i = 0; i < GS->len; i++)
1462 { if (strncmp (name,GS->FI[i].name,name_length) == 0)
1463 { found_italic = wmf_false;
1464 found_bold = wmf_false;
1465 if ( wmf_strstr (GS->FI[i].name,"Ital")
1466 || wmf_strstr (GS->FI[i].name,"Obli"))
1467 { found_italic = wmf_true;
1468 }
1469 if ( wmf_strstr (GS->FI[i].name,"Bold")
1470 || wmf_strstr (GS->FI[i].name,"Demi")) /* or "Medi" ?? */
1471 { found_bold = wmf_true;
1472 }
1473 if ((require_italic == found_italic) && (require_bold == found_bold))
1474 { FI = &(GS->FI[i]);
1475 break;
1476 }
1477 }
1478 }
1479
1480 if (FI == 0) return (0);
1481
1482 return (FI);
1483 }
1484
1485 /**
1486 * Takes a [name]/[alias] pair from the GS Fontmap and tries to load [name] as a font,
1487 * and then, provided [alias] is aliased to a font-file & not a 3rd font-name, [alias].
1488 */
ipa_font_gs_face(wmfAPI * API,wmfFont * font,wmfGS_FontInfo * FI)1489 static FT_Face ipa_font_gs_face (wmfAPI* API,wmfFont* font,wmfGS_FontInfo* FI)
1490 { wmfFontmapData* font_data = (wmfFontmapData*) ((wmfFontData*) API->font_data)->user_data;
1491
1492 FT_Face face = 0;
1493
1494 char* aalias = 0;
1495
1496 if (FI == 0) return (0);
1497
1498 face = ipa_font_face (API,font,FI->name);
1499
1500 if (face) return (face);
1501
1502 if (FI->alias[0] != '/') return (0);
1503
1504 aalias = ipa_font_gs_alias (&(font_data->GS),FI->alias+1);
1505
1506 if (aalias[0] != '(')
1507 { WMF_DEBUG (API,"font lookup is too complicated! Giving up...");
1508 return (0);
1509 }
1510
1511 face = ipa_font_face (API,font,FI->alias+1);
1512
1513 return (face);
1514 }
1515
1516 /**
1517 * Takes a postscript font name and:
1518 *
1519 * (1) Check to see whether font has been cached; if so: return (ipa_font_face_cached ())
1520 * (2) Check for font in XML table; if found:
1521 * (a) ipa_font_face_open ()
1522 * (b) return (ipa_font_face_cached ())
1523 * (3) Check for font with file in GS table; if so:
1524 * (a) search for font file in font search path; if found:
1525 * ( i) ipa_font_face_open ()
1526 * (ii) return (ipa_font_face_cached ())
1527 * (4) Check for font in internal table; if found:
1528 * (a) ipa_font_face_open ()
1529 * (b) return (ipa_font_face_cached ())
1530 * (5) return (0)
1531 */
ipa_font_face(wmfAPI * API,wmfFont * font,char * ps_name)1532 static FT_Face ipa_font_face (wmfAPI* API,wmfFont* font,char* ps_name)
1533 { wmfFontmapData* font_data = (wmfFontmapData*) ((wmfFontData*) API->font_data)->user_data;
1534
1535 FT_Face face = 0;
1536
1537 unsigned int i;
1538
1539 char* name = 0;
1540 char* suffix = 0;
1541 char* glyphs = 0;
1542 char* metrics = 0;
1543
1544 /* (1) Check to see whether font has been cached; if so: return (ipa_font_face_cached ())
1545 */
1546 face = ipa_font_face_cached (API,font,ps_name);
1547
1548 if (face) return (face);
1549
1550 /* (2) Check for font in XML table
1551 */
1552 glyphs = 0;
1553 metrics = 0;
1554 for (i = 0; i < font_data->FD.len; i++)
1555 { if (font_data->FD.FI[i].name == 0) continue;
1556 if (strcmp (ps_name,font_data->FD.FI[i].name) == 0)
1557 { glyphs = font_data->FD.FI[i].glyphs;
1558 metrics = font_data->FD.FI[i].metrics;
1559 break;
1560 }
1561 }
1562
1563 if (glyphs)
1564 { face = ipa_font_face_open (API,ps_name,glyphs,metrics);
1565
1566 if (face) return (ipa_font_face_cached (API,font,ps_name));
1567 }
1568
1569 /* (3) Check for font with file in GS table
1570 */
1571 name = 0;
1572 for (i = 0; i < font_data->GS.len; i++)
1573 { if (strcmp (ps_name,font_data->GS.FI[i].name) == 0)
1574 { if (font_data->GS.FI[i].alias[0] == '(')
1575 { name = wmf_strdup (API,font_data->GS.FI[i].alias + 1);
1576 }
1577 break;
1578 }
1579 }
1580
1581 glyphs = 0;
1582 if (name)
1583 { name[strlen (name) - 1] = 0;
1584
1585 glyphs = ipa_font_path_find (API,name);
1586 }
1587
1588 metrics = 0;
1589 if (glyphs)
1590 { if (strlen (name) > 3)
1591 { suffix = name + strlen (name) - 4;
1592 if ((strcmp (suffix,".pfa") == 0) || (strcmp (suffix,".pfb") == 0))
1593 { strcpy (suffix,".afm");
1594 metrics = ipa_font_path_find (API,name);
1595 }
1596 }
1597
1598 face = ipa_font_face_open (API,ps_name,glyphs,metrics);
1599 }
1600
1601 if (name) wmf_free (API,name);
1602
1603 if (glyphs) wmf_free (API,glyphs);
1604 if (metrics) wmf_free (API,metrics);
1605
1606 if (face) return (ipa_font_face_cached (API,font,ps_name));
1607
1608 /* (4) Check for font in internal table
1609 */
1610 name = 0;
1611 i = 0;
1612 while (font_data->ps[i].name)
1613 { if (strcmp (ps_name,font_data->ps[i].name) == 0)
1614 { name = wmf_strdup (API,font_data->ps[i].mapping);
1615 break;
1616 }
1617 i++;
1618 }
1619
1620 glyphs = 0;
1621 if (name)
1622 { glyphs = ipa_font_path_find (API,name);
1623 }
1624
1625 metrics = 0;
1626 if (glyphs)
1627 { if (strlen (name) > 3)
1628 { suffix = name + strlen (name) - 4;
1629 if ((strcmp (suffix,".pfa") == 0) || (strcmp (suffix,".pfb") == 0))
1630 { strcpy (suffix,".afm");
1631 metrics = ipa_font_path_find (API,name);
1632 }
1633 }
1634
1635 face = ipa_font_face_open (API,ps_name,glyphs,metrics);
1636 }
1637
1638 if (name) wmf_free (API,name);
1639
1640 if (glyphs) wmf_free (API,glyphs);
1641 if (metrics) wmf_free (API,metrics);
1642
1643 if (face) return (ipa_font_face_cached (API,font,ps_name));
1644
1645 /* (5) return (0)
1646 */
1647 return (0);
1648 }
1649
1650 /**
1651 * Opens the font with freetype and caches postscript name, glyphs path & FT font face
1652 */
ipa_font_face_open(wmfAPI * API,char * ps_name,char * glyphs,char * metrics)1653 static FT_Face ipa_font_face_open (wmfAPI* API,char* ps_name,char* glyphs,char* metrics)
1654 { wmfFontmapData* font_data = (wmfFontmapData*) ((wmfFontData*) API->font_data)->user_data;
1655
1656 wmfFT_CacheEntry entry;
1657
1658 FT_Face face = 0;
1659
1660 struct stat stat_buf;
1661
1662 #ifdef _WIN32
1663 glyphs = remap_font_file_name (API,glyphs);
1664 #endif
1665 if (stat (glyphs,&stat_buf))
1666 { WMF_ERROR (API,"unable to stat font file:");
1667 WMF_ERROR (API,glyphs);
1668 API->err = wmf_E_BadFile;
1669 #ifdef _WIN32
1670 wmf_free (API,glyphs);
1671 #endif
1672 return (0);
1673 }
1674
1675 if (FT_New_Face (font_data->Library,glyphs,0,&face) != 0)
1676 { WMF_ERROR (API,"Failed to open font:");
1677 WMF_ERROR (API,glyphs);
1678 API->err = wmf_E_DeviceError;
1679 #ifdef _WIN32
1680 wmf_free (API,glyphs);
1681 #endif
1682 return (0);
1683 }
1684
1685 #ifdef _WIN32
1686 metrics = remap_font_file_name (API,metrics);
1687 #endif
1688 if (metrics)
1689 { if (stat (metrics,&stat_buf))
1690 { WMF_DEBUG (API,"unable to stat font metrics file:");
1691 WMF_DEBUG (API,metrics);
1692 }
1693 else
1694 { if (FT_Attach_File (face,metrics) != 0)
1695 { WMF_DEBUG (API,"unable to load font metrics file:");
1696 WMF_DEBUG (API,metrics);
1697 }
1698 }
1699 }
1700
1701 /* Select encoding (I'm very uncertain about this!): - [TODO] ??
1702 */
1703 if (FT_Select_Charmap (face,ft_encoding_adobe_standard) == 0)
1704 { WMF_DEBUG (API,glyphs);
1705 WMF_DEBUG (API,"Adobe Standard Encoding");
1706 }
1707 else if (FT_Select_Charmap (face,ft_encoding_adobe_custom) == 0)
1708 { WMF_DEBUG (API,glyphs);
1709 WMF_DEBUG (API,"Adobe Custom Encoding");
1710 }
1711 else if (FT_Select_Charmap (face,ft_encoding_symbol) == 0)
1712 { WMF_DEBUG (API,glyphs);
1713 WMF_DEBUG (API,"Symbol Encoding");
1714 }
1715 else if (FT_Select_Charmap (face,ft_encoding_unicode) == 0)
1716 { WMF_DEBUG (API,glyphs);
1717 WMF_DEBUG (API,"Unicode Encoding");
1718 }
1719 else
1720 { WMF_ERROR (API,"Bad encoding! (Please help me!)");
1721 API->err = wmf_E_DeviceError;
1722 }
1723
1724 entry.name = ps_name;
1725 entry.path = glyphs;
1726
1727 entry.face = face;
1728
1729 ipa_font_add_cache (API,&entry); /* cache font name, path & face */
1730
1731 ipa_font_add_api (API,ps_name); /* add font name to list of fonts used */
1732
1733 return (face);
1734 }
1735
1736 /**
1737 * Finds font info in cache and sets WMF's font entry appropriately.
1738 */
ipa_font_face_cached(wmfAPI * API,wmfFont * font,char * ps_name)1739 static FT_Face ipa_font_face_cached (wmfAPI* API,wmfFont* font,char* ps_name)
1740 { wmfFontmapData* font_data = (wmfFontmapData*) ((wmfFontData*) API->font_data)->user_data;
1741
1742 wmfIPAFont* ipa_font = (wmfIPAFont*) font->user_data;
1743
1744 FT_Face face = 0;
1745
1746 unsigned int i;
1747
1748 /* Check cache for font
1749 */
1750 i = 0;
1751 while (font_data->cache[i].name)
1752 { if (strcmp (font_data->cache[i].name,ps_name) == 0)
1753 { face = font_data->cache[i].face;
1754 break;
1755 }
1756 i++;
1757 }
1758
1759 if (face)
1760 { ipa_font->ps_name = ps_name;
1761 ipa_font->ft_face = face;
1762 }
1763
1764 return (face);
1765 }
1766
1767 /**
1768 * Search for file_name in font path and return full path to file as wmf_malloc() string
1769 */
ipa_font_path_find(wmfAPI * API,char * file_name)1770 static char* ipa_font_path_find (wmfAPI* API,char* file_name)
1771 { wmfFontmapData* font_data = (wmfFontmapData*) ((wmfFontData*) API->font_data)->user_data;
1772
1773 struct stat stat_buf;
1774
1775 unsigned int length;
1776 unsigned int count;
1777 unsigned int i;
1778
1779 char* path = 0;
1780
1781 /* Determine length of string required to hold path name of font
1782 */
1783 count = 0;
1784 i = 0;
1785 while (font_data->fontdirs[i])
1786 { length = strlen (font_data->fontdirs[i]);
1787 if (count < length) count = length;
1788 i++;
1789 }
1790 count += 1 + strlen (file_name) + 1;
1791
1792 path = (char*) wmf_malloc (API,count);
1793
1794 if (ERR (API))
1795 { WMF_DEBUG (API,"bailing...");
1796 return (0);
1797 }
1798
1799 /* Compose full font file path:
1800 */
1801 i = 0;
1802 while (font_data->fontdirs[i])
1803 { strcpy (path,font_data->fontdirs[i]);
1804 strcat (path,"/");
1805 strcat (path,file_name);
1806 WMF_DEBUG (API,path);
1807 if (stat (path,&stat_buf) == 0) break; /* file exists */
1808 i++;
1809 }
1810
1811 if (font_data->fontdirs[i] == 0)
1812 { WMF_DEBUG (API,"file not found in font path.");
1813 wmf_free (API,path);
1814 path = 0;
1815 }
1816
1817 return (path);
1818 }
1819
1820 /**
1821 * If after XML & GS fontmap searches the font still hasn't been matched, then use one of the 13 standard
1822 * postscript fonts (or any others that have been added via library options).
1823 */
ipa_font_std(wmfAPI * API,wmfFont * font)1824 static char* ipa_font_std (wmfAPI* API,wmfFont* font)
1825 { wmfFontmapData* font_data = (wmfFontmapData*) ((wmfFontData*) API->font_data)->user_data;
1826
1827 char* mapping = 0;
1828
1829 unsigned int i;
1830 unsigned int index = 0;
1831
1832 /* First: check for an exact match:
1833 */
1834 i = 0;
1835 while (font_data->wmf[i].name)
1836 { if (strcmp (font->lfFaceName,font_data->wmf[i].name) == 0)
1837 { mapping = font_data->wmf[i].name;
1838 break;
1839 }
1840 i++;
1841 }
1842
1843 /* If no exact match, check for a close (i.e., sub-string) match:
1844 */
1845 if (mapping == 0)
1846 { i = 0;
1847 while (font_data->sub[i].name)
1848 { if (wmf_strstr (font->lfFaceName,font_data->sub[i].name))
1849 { mapping = font_data->sub[i].mapping;
1850 break;
1851 }
1852 i++;
1853 }
1854 }
1855
1856 /* If still no match, use the default:
1857 */
1858 if (mapping == 0) mapping = DefaultFontMapping;
1859
1860 /* Check chosen mapping in list of exact names:
1861 */
1862 i = 0;
1863 while (font_data->wmf[i].name)
1864 { if (strcmp (mapping,font_data->wmf[i].name) == 0)
1865 { index = i;
1866 break;
1867 }
1868 i++;
1869 }
1870
1871 /* If not found then something odd has happened - probably a typo somewhere...
1872 */
1873 if (font_data->wmf[i].name == 0)
1874 { WMF_ERROR (API,"Glitch! Unmapped font...");
1875 API->err = wmf_E_Glitch;
1876 return (0);
1877 }
1878
1879 /* Select a new mapping (the PS font name) on basis of weight & italic parameters
1880 */
1881 if (font->lfWeight > 550) /* => Bold (?? Don't ask me...) */
1882 { if (font->lfItalic == 1) /* Italic */
1883 { mapping = font_data->wmf[index].bolditalic;
1884 }
1885 else
1886 { mapping = font_data->wmf[index].bold;
1887 }
1888 }
1889 else
1890 { if (font->lfItalic == 1) /* Italic */
1891 { mapping = font_data->wmf[index].italic;
1892 }
1893 else
1894 { mapping = font_data->wmf[index].normal;
1895 }
1896 }
1897
1898 return (mapping);
1899 }
1900