source: branches/2.2/filemanager/tp/dompdf/lib/ttf2ufm/ttf2ufm-src/ft.c @ 3019

Revision 3019, 13.9 KB checked in by amuller, 14 years ago (diff)

Ticket #1135 - Corrigindo CSS e adicionando filemanager

Line 
1/*
2 * The font parser using the FreeType library version 2.
3 *
4 * see COPYRIGHT
5 *
6 */
7
8#ifdef USE_FREETYPE
9
10#include <stdio.h>
11#include <string.h>
12#include <stdlib.h>
13#include <ctype.h>
14#include <sys/types.h>
15#include <freetype/config/ftheader.h>
16#include <freetype/freetype.h>
17#include <freetype/ftglyph.h>
18#include <freetype/ftsnames.h>
19#include <freetype/ttnameid.h>
20#include <freetype/ftoutln.h>
21#include "pt1.h"
22#include "global.h"
23
24/* prototypes of call entries */
25static void openfont(char *fname, char *arg);
26static void closefont( void);
27static int getnglyphs ( void);
28static int glnames( GLYPH *glyph_list);
29static void glmetrics( GLYPH *glyph_list);
30static int glenc( GLYPH *glyph_list, int *encoding, int *unimap);
31static void fnmetrics( struct font_metrics *fm);
32static void glpath( int glyphno, GLYPH *glyph_list);
33static void kerning( GLYPH *glyph_list);
34
35/* globals */
36
37/* front-end descriptor */
38struct frontsw freetype_sw = {
39        /*name*/       "ft",
40        /*descr*/      "based on the FreeType library",
41        /*suffix*/     { "ttf", "otf", "pfa", "pfb" },
42        /*open*/       openfont,
43        /*close*/      closefont,
44        /*nglyphs*/    getnglyphs,
45        /*glnames*/    glnames,
46        /*glmetrics*/  glmetrics,
47        /*glenc*/      glenc,
48        /*fnmetrics*/  fnmetrics,
49        /*glpath*/     glpath,
50        /*kerning*/    kerning,
51};
52
53/* statics */
54
55static FT_Library library;
56static FT_Face face;
57
58static int enc_type, enc_found;
59
60/* SFNT functions do not seem to be included by default in FT2beta8 */
61#define ENABLE_SFNT
62
63/*
64 * Open font and prepare to return information to the main driver.
65 * May print error and warning messages.
66 * Exit on error.
67 */
68
69static void
70openfont(
71        char *fname,
72        char *arg /* unused now */
73)
74{
75        FT_Error error;
76
77        if( FT_Init_FreeType( &library ) ) {
78                fprintf(stderr, "** FreeType initialization failed\n");
79                exit(1);
80        }
81
82        if( error = FT_New_Face( library, fname, 0, &face ) ) {
83                if ( error == FT_Err_Unknown_File_Format )
84                        fprintf(stderr, "**** %s has format unknown to FreeType\n", fname);
85                else
86                        fprintf(stderr, "**** Cannot access %s ****\n", fname);
87                exit(1);
88        }
89
90        if(FT_HAS_FIXED_SIZES(face)) {
91                WARNING_1 fprintf(stderr, "Font contains bitmaps\n");
92        }
93        if(FT_HAS_MULTIPLE_MASTERS(face)) {
94                WARNING_1 fprintf(stderr, "Font contains multiple masters, using default\n");
95        }
96
97        if(ISDBG(FT)) fprintf(stderr," %d units per EM\n", face->units_per_EM);
98
99        enc_found = 0;
100}
101
102/*
103 * Close font.
104 * Exit on error.
105 */
106
107static void
108closefont(
109        void
110)
111{
112        if( FT_Done_Face(face) ) {
113                WARNING_1 fprintf(stderr, "Errors when closing the font file, ignored\n");
114        }
115        if( FT_Done_FreeType(library) ) {
116                WARNING_1 fprintf(stderr, "Errors when stopping FreeType, ignored\n");
117        }
118}
119
120/*
121 * Get the number of glyphs in font.
122 */
123
124static int
125getnglyphs (
126        void
127)
128{
129        if(ISDBG(FT)) fprintf(stderr, "%d glyphs in font\n", face->num_glyphs);
130        return (int)face->num_glyphs;
131}
132
133/*
134 * Get the names of the glyphs.
135 * Returns 0 if the names were assigned, non-zero if the font
136 * provides no glyph names.
137 */
138
139static int
140glnames(
141        GLYPH *glyph_list
142)
143{
144#define MAX_NAMELEN     1024
145        unsigned char bf[1024];
146        int i;
147
148        if( ! FT_HAS_GLYPH_NAMES(face) ) {
149                WARNING_1 fprintf(stderr, "Font has no glyph names\n");
150                return 1;
151        }
152
153        for(i=0; i < face->num_glyphs; i++) {
154                if( FT_Get_Glyph_Name(face, i, bf, MAX_NAMELEN) || bf[0]==0 ) {
155                        sprintf(bf, "_g_%d", i);
156                        WARNING_2 fprintf(stderr,
157                                "Glyph No. %d has no postscript name, becomes %s\n", i, bf);
158                }
159                glyph_list[i].name = strdup(bf);
160                if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, bf);
161                if (glyph_list[i].name == NULL) {
162                        fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
163                        exit(255);
164                }
165        }
166        return 0;
167}
168
169/*
170 * Get the metrics of the glyphs.
171 */
172
173static void
174glmetrics(
175        GLYPH *glyph_list
176)
177{
178        GLYPH          *g;
179        int i;
180        FT_Glyph_Metrics *met;
181        FT_BBox bbox;
182        FT_Glyph gly;
183    FT_ULong charcode;
184    FT_UInt  index;
185
186        for(i=0; i < face->num_glyphs; i++) {
187                g = &(glyph_list[i]);
188
189                if( FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE) ) {
190                        fprintf(stderr, "Can't load glyph %s, skipped\n", g->name);
191                        continue;
192                }
193
194                met = &face->glyph->metrics;
195
196                if(FT_HAS_HORIZONTAL(face)) {
197                        g->width = met->horiAdvance;
198                        g->lsb = met->horiBearingX;
199                } else {
200                        WARNING_2 fprintf(stderr, "Glyph %s has no horizontal metrics, guessed them\n", g->name);
201                        g->width = met->width;
202                        g->lsb = 0;
203                }
204
205                if( FT_Get_Glyph(face->glyph, &gly) ) {
206                        fprintf(stderr, "Can't access glyph %s bbox, skipped\n", g->name);
207                        continue;
208                }
209
210                FT_Glyph_Get_CBox(gly, ft_glyph_bbox_unscaled, &bbox);
211                g->xMin = bbox.xMin;
212                g->yMin = bbox.yMin;
213                g->xMax = bbox.xMax;
214                g->yMax = bbox.yMax;
215
216                g->ttf_pathlen = face->glyph->outline.n_points;
217
218        }
219
220    charcode = FT_Get_First_Char(face, &index);
221    while ( index != 0 ) {
222      if ( index >= face->num_glyphs ) {
223        break;
224      }
225      for ( i = 0; i < GLYPH_MAX_ENCODINGS; i++ ) {
226        if ( glyph_list[index].orig_code[i] == -1 )
227          break;
228      }
229
230      if ( i == GLYPH_MAX_ENCODINGS ) {
231        if (strcmp(glyph_list[index].name, ".notdef") != 0) {
232          WARNING_2 fprintf(stderr,
233                            "Glyph %s has >= %d encodings (A), %4.4x & %4.4x\n",
234                            GLYPH_MAX_ENCODINGS,
235                            glyph_list[index].name,
236                            glyph_list[index].orig_code[i],
237                            charcode);
238        }
239      } else {
240        glyph_list[index].orig_code[i] = charcode;
241      }
242
243      charcode = FT_Get_Next_Char(face, charcode, &index);
244    }
245}
246
247/*
248 * Get the original encoding of the font.
249 * Returns 1 for if the original encoding is Unicode, 2 if the
250 * original encoding is other 16-bit, 0 if 8-bit.
251 */
252
253static int
254glenc(
255        GLYPH *glyph_list,
256        int *encoding,
257        int *unimap
258)
259{
260        int i, e;
261        unsigned code, index;
262
263        if(ISDBG(FT))
264                for(e=0; e < face->num_charmaps; e++) {
265                        fprintf(stderr, "found encoding pid=%d eid=%d\n",
266                                face->charmaps[e]->platform_id,
267                                face->charmaps[e]->encoding_id);
268                }
269
270        if(enc_found)
271                goto populate_map;
272
273        enc_type = 0;
274
275        /* first check for an explicit PID/EID */
276
277        if(force_pid != -1) {
278                for(e=0; e < face->num_charmaps; e++) {
279                        if(face->charmaps[e]->platform_id == force_pid
280                        && face->charmaps[e]->encoding_id == force_eid) {
281                                WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n",
282                                        force_pid, force_eid);
283                                if( !face->charmaps || FT_Set_Charmap(face, face->charmaps[e]) ) {
284                                        fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
285                                        exit(1);
286                                }
287                                enc_type = 1;
288                                goto populate_map;
289                        }
290                }
291                fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n",
292                        force_pid, force_eid);
293                exit(1);
294        }
295
296        /* next check for a direct Adobe mapping */
297
298        if(!forcemap) {
299                for(e=0; e < face->num_charmaps; e++) {
300                        if(face->charmaps[e]->encoding == ft_encoding_adobe_custom) {
301                                WARNING_1 fputs("Found Adobe Custom Encoding\n", stderr);
302                                if( FT_Set_Charmap(face, face->charmaps[e]) ) {
303                                        fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
304                                        exit(1);
305                                }
306                                goto populate_map;
307                        }
308                }
309        }
310
311        for(e=0; e < face->num_charmaps; e++) {
312                if(face->charmaps[e]->platform_id == 3) {
313                        switch(face->charmaps[e]->encoding_id) {
314                        case 0:
315                                WARNING_1 fputs("Found Symbol Encoding\n", stderr);
316                                break;
317                        case 1:
318                                WARNING_1 fputs("Found Unicode Encoding\n", stderr);
319                                enc_type = 1;
320                                break;
321                        default:
322                                WARNING_1 {
323                                        fprintf(stderr,
324                                        "****MS Encoding ID %d not supported****\n",
325                                                face->charmaps[e]->encoding_id);
326                                        fputs("Treating it like Symbol encoding\n", stderr);
327                                }
328                                break;
329                        }
330                        break;
331                }
332        }
333        if(e >= face->num_charmaps) {
334                WARNING_1 fputs("No Microsoft encoding, using first encoding available\n", stderr);
335                e = 0;
336        }
337       
338        if( FT_Set_Charmap(face, face->charmaps[e]) ) {
339                fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
340                exit(1);
341        }
342
343populate_map:
344        enc_found = 1;
345
346        for(i=0; i<ENCTABSZ; i++) {
347                if(encoding[i] != -1)
348                        continue;
349                if(enc_type == 1 || forcemap) {
350                        code = unimap[i];
351                        if(code == (unsigned) -1)
352                                continue;
353                } else
354                        code = i;
355
356                code = FT_Get_Char_Index(face, code);
357                if(0 && ISDBG(FT)) fprintf(stderr, "code of %3d is %3d\n", i, code);
358                if(code == 0)
359                        continue; /* .notdef */
360                encoding[i] = code;
361        }
362
363        return enc_type;
364}
365
366/*
367 * Get the font metrics
368 */
369static void
370fnmetrics(
371        struct font_metrics *fm
372)
373{
374        char *str;
375        static char *fieldstocheck[3];
376#ifdef ENABLE_SFNT
377        FT_SfntName sn;
378#endif /* ENABLE_SFNT */
379        int i, j, len;
380
381        fm->italic_angle = 0.0; /* FreeType hides the angle */
382        fm->underline_position = face->underline_position;
383        fm->underline_thickness = face->underline_thickness;
384        fm->is_fixed_pitch = FT_IS_FIXED_WIDTH(face);
385
386        fm->ascender = face->ascender;
387        fm->descender = face->descender;
388
389        fm->units_per_em =  face->units_per_EM;
390
391        fm->bbox[0] = face->bbox.xMin;
392        fm->bbox[1] = face->bbox.yMin;
393        fm->bbox[2] = face->bbox.xMax;
394        fm->bbox[3] = face->bbox.yMax;
395
396#ifdef ENABLE_SFNT
397        if( FT_Get_Sfnt_Name(face, TT_NAME_ID_COPYRIGHT, &sn) )
398#endif /* ENABLE_SFNT */
399                fm->name_copyright = "";
400#ifdef ENABLE_SFNT
401        else
402                fm->name_copyright = dupcnstring(sn.string, sn.string_len);
403#endif /* ENABLE_SFNT */
404
405        fm->name_family = face->family_name;
406
407        fm->name_style = face->style_name;
408        if(fm->name_style == NULL)
409                fm->name_style = "";
410
411#ifdef ENABLE_SFNT
412        if( FT_Get_Sfnt_Name(face, TT_NAME_ID_FULL_NAME, &sn) )
413#endif /* ENABLE_SFNT */
414        {
415                int len;
416
417                len = strlen(fm->name_family) + strlen(fm->name_style) + 2;
418                if(( fm->name_full = malloc(len) )==NULL) {
419                        fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
420                        exit(255);
421                }
422                strcpy(fm->name_full, fm->name_family);
423                if(strlen(fm->name_style) != 0) {
424                        strcat(fm->name_full, " ");
425                        strcat(fm->name_full, fm->name_style);
426                }
427        }
428#ifdef ENABLE_SFNT
429        else
430                fm->name_full = dupcnstring(sn.string, sn.string_len);
431#endif /* ENABLE_SFNT */
432
433#ifdef ENABLE_SFNT
434        if( FT_Get_Sfnt_Name(face, TT_NAME_ID_VERSION_STRING, &sn) )
435#endif /* ENABLE_SFNT */
436                fm->name_version = "1.0";
437#ifdef ENABLE_SFNT
438        else
439                fm->name_version = dupcnstring(sn.string, sn.string_len);
440#endif /* ENABLE_SFNT */
441
442#ifdef ENABLE_SFNT
443        if( FT_Get_Sfnt_Name(face, TT_NAME_ID_PS_NAME , &sn) ) {
444#endif /* ENABLE_SFNT */
445                if(( fm->name_ps = strdup(fm->name_full) )==NULL) {
446                        fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
447                        exit(255);
448                }
449#ifdef ENABLE_SFNT
450        } else
451                fm->name_ps = dupcnstring(sn.string, sn.string_len);
452#endif /* ENABLE_SFNT */
453        for(i=0; fm->name_ps[i]!=0; i++)
454                if(fm->name_ps[i] == ' ')
455                        fm->name_ps[i] = '_'; /* no spaces in the Postscript name *m
456
457        /* guess the boldness from the font names */
458        fm->force_bold=0;
459
460        fieldstocheck[0] = fm->name_style;
461        fieldstocheck[1] = fm->name_full;
462        fieldstocheck[2] = fm->name_ps;
463
464        for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(fieldstocheck[0]); i++) {
465                str=fieldstocheck[i];
466                len = strlen(str);
467                for(j=0; j<len; j++) {
468                        if( (str[j]=='B'
469                                || str[j]=='b'
470                                        && ( j==0 || !isalpha(str[j-1]) )
471                                )
472                        && !strncmp("old",&str[j+1],3)
473                        && (j+4 >= len || !islower(str[j+4]))
474                        ) {
475                                fm->force_bold=1;
476                                break;
477                        }
478                }
479        }
480}
481
482/*
483 * Functions to decompose the outlines
484 */
485
486static GLYPH *curg;
487static double lastx, lasty;
488
489static int
490outl_moveto(
491        FT_Vector *to,
492        void *unused
493)
494{
495        double tox, toy;
496
497        tox = fscale((double)to->x); toy = fscale((double)to->y);
498
499        /* FreeType does not do explicit closepath() */
500        if(curg->lastentry) {
501                g_closepath(curg);
502        }
503        fg_rmoveto(curg, tox, toy);
504        lastx = tox; lasty = toy;
505
506        return 0;
507}
508
509static int
510outl_lineto(
511        FT_Vector *to,
512        void *unused
513)
514{
515        double tox, toy;
516
517        tox = fscale((double)to->x); toy = fscale((double)to->y);
518
519        fg_rlineto(curg, tox, toy);
520        lastx = tox; lasty = toy;
521
522        return 0;
523}
524
525static int
526outl_conicto(
527        FT_Vector *control1,
528        FT_Vector *to,
529        void *unused
530)
531{
532        double c1x, c1y, tox, toy;
533
534        c1x = fscale((double)control1->x); c1y = fscale((double)control1->y);
535        tox = fscale((double)to->x); toy = fscale((double)to->y);
536
537        fg_rrcurveto(curg,
538                (lastx + 2.0 * c1x) / 3.0, (lasty + 2.0 * c1y) / 3.0,
539                (2.0 * c1x + tox) / 3.0, (2.0 * c1y + toy) / 3.0,
540                tox, toy );
541        lastx = tox; lasty = toy;
542
543        return 0;
544}
545
546static int
547outl_cubicto(
548        FT_Vector *control1,
549        FT_Vector *control2,
550        FT_Vector *to,
551        void *unused
552)
553{
554        double c1x, c1y, c2x, c2y, tox, toy;
555
556        c1x = fscale((double)control1->x); c1y = fscale((double)control1->y);
557        c2x = fscale((double)control2->x); c2y = fscale((double)control2->y);
558        tox = fscale((double)to->x); toy = fscale((double)to->y);
559
560        fg_rrcurveto(curg, c1x, c1y, c2x, c2y, tox, toy);
561        lastx = tox; lasty = toy;
562
563        return 0;
564}
565
566static FT_Outline_Funcs ft_outl_funcs = {
567        outl_moveto,
568        outl_lineto,
569        outl_conicto,
570        outl_cubicto,
571        0,
572        0
573};
574
575/*
576 * Get the path of contrours for a glyph.
577 */
578
579static void
580glpath(
581        int glyphno,
582        GLYPH *glyf_list
583)
584{
585        FT_Outline *ol;
586
587        curg = &glyf_list[glyphno];
588
589        if( FT_Load_Glyph(face, glyphno, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE|FT_LOAD_NO_HINTING)
590        || face->glyph->format != ft_glyph_format_outline ) {
591                fprintf(stderr, "Can't load glyph %s, skipped\n", curg->name);
592                return;
593        }
594
595        ol = &face->glyph->outline;
596        lastx = 0.0; lasty = 0.0;
597
598        if( FT_Outline_Decompose(ol, &ft_outl_funcs, NULL) ) {
599                fprintf(stderr, "Can't decompose outline of glyph %s, skipped\n", curg->name);
600                return;
601        }
602
603        /* FreeType does not do explicit closepath() */
604        if(curg->lastentry) {
605                g_closepath(curg);
606        }
607
608        if(ol->flags & ft_outline_reverse_fill) {
609                assertpath(curg->entries, __FILE__, __LINE__, curg->name);
610                reversepaths(curg);
611        }
612}
613
614/*
615 * Get the kerning data.
616 */
617
618static void
619kerning(
620        GLYPH *glyph_list
621)
622{
623        int     i, j, n;
624        int     nglyphs = face->num_glyphs;
625        FT_Vector k;
626        GLYPH *gl;
627
628        if( nglyphs == 0 || !FT_HAS_KERNING(face) ) {
629        WARNING_1 fputs("No Kerning data\n", stderr);
630                return;
631        }
632
633        for(i=0; i<nglyphs; i++)  {
634                if( (glyph_list[i].flags & GF_USED) ==0)
635                        continue;
636                for(j=0; j<nglyphs; j++) {
637                        if( (glyph_list[j].flags & GF_USED) ==0)
638                                continue;
639                        if( FT_Get_Kerning(face, i, j, ft_kerning_unscaled, &k) )
640                                continue;
641                        if( k.x == 0 )
642                                continue;
643
644                        addkernpair(i, j, k.x);
645                }
646        }
647}
648
649#endif
Note: See TracBrowser for help on using the repository browser.