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

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

Ticket #1135 - Corrigindo CSS e adicionando filemanager

RevLine 
[3019]1/*
2 * The font parser for the BDF files
3 *
4 * Copyright (c) 2001 by the TTF2PT1 project
5 * Copyright (c) 2001 by Sergey Babkin
6 *
7 * see COPYRIGHT for the full copyright notice
8 */
9
10#include <stdio.h>
11#include <string.h>
12#include <stdlib.h>
13#include <ctype.h>
14#include "pt1.h"
15#include "global.h"
16
17/* prototypes of call entries */
18static void openfont(char *fname, char *arg);
19static void closefont( void);
20static int getnglyphs ( void);
21static int glnames( GLYPH *glyph_list);
22static void readglyphs( GLYPH *glyph_list);
23static int glenc( GLYPH *glyph_list, int *encoding, int *unimap);
24static void fnmetrics( struct font_metrics *fm);
25static void glpath( int glyphno, GLYPH *glyph_list);
26static void kerning( GLYPH *glyph_list);
27
28/* globals */
29
30/* front-end descriptor */
31struct frontsw bdf_sw = {
32        /*name*/       "bdf",
33        /*descr*/      "BDF bitmapped fonts",
34        /*suffix*/     { "bdf" },
35        /*open*/       openfont,
36        /*close*/      closefont,
37        /*nglyphs*/    getnglyphs,
38        /*glnames*/    glnames,
39        /*glmetrics*/  readglyphs,
40        /*glenc*/      glenc,
41        /*fnmetrics*/  fnmetrics,
42        /*glpath*/     glpath,
43        /*kerning*/    kerning,
44};
45
46/* statics */
47
48#define MAXLINE 10240 /* maximal line length in the input file */
49
50static int lineno; /* line number */
51
52#define GETLEN(s)       s, (sizeof(s)-1)
53#define LENCMP(str, txt)        strncmp(str, txt, sizeof(txt)-1)
54
55static FILE *bdf_file;
56static int nglyphs;
57static struct font_metrics fmet;
58
59/* many BDF fonts are of small pixel size, so we better try
60 * to scale them by an integer to keep the dimensions in
61 * whole pixels. However if the size is too big and a non-
62 * integer scaling is needed, we use the standard ttf2pt1's
63 * scaling abilities.
64 */
65static int pixel_size;
66static int scale;
67static int scale_external;
68
69static char *slant;
70static char xlfdname[201];
71static char *spacing;
72static char *charset_reg;
73static char *charset_enc;
74static char *fnwidth;
75static int is_unicode = 0;
76
77/* tempoary storage for returning data to ttf2pt1 later on request */
78static int maxenc = 0;
79static int *fontenc;
80static GENTRY **glpaths;
81
82static int got_glyphs = 0;
83static GLYPH *glyphs;
84static int curgl;
85
86static int readfile(FILE *f, int (*strfunc)(int len, char *str));
87
88/*
89 * Read the file and parse each string with strfunc(),
90 * until strfunc() returns !=0 or the end of file happens.
91 * Returns -1 on EOF or strfunc() returning <0, else 0
92 */
93
94static int
95readfile(
96        FILE *f,
97        int (*strfunc)(int len, char *str)
98)
99{
100        static char str[MAXLINE]; /* input line, maybe should be dynamic ? */
101        char *s;
102        int len, c, res;
103
104        len=0;
105        while(( c=getc(f) )!=EOF) {
106                if(c=='\n') {
107                        str[len]=0;
108
109                        res = strfunc(len, str);
110                        lineno++;
111                        if(res<0)
112                                return -1;
113                        else if(res!=0)
114                                return 0;
115
116                        len=0;
117                } else if(len<MAXLINE-1) {
118                        if(c!='\r')
119                                str[len++]=c;
120                } else {
121                        fprintf(stderr, "**** bdf: line %d is too long (>%d)\n", lineno, MAXLINE-1);
122                        exit(1);
123                }
124        }
125        return -1; /* EOF */
126}
127
128/*
129 * Parse the header of the font file.
130 * Stop after the line CHARS is encountered. Ignore the unknown lines.
131 */
132
133struct line {
134        char *name; /* property name with trailing space */
135        int namelen; /* length of the name string */
136        enum {
137                ALLOW_REPEAT = 0x01, /* this property may be repeated in multiple lines */
138                IS_SEEN = 0x02, /* this property has been seen already */
139                MUST_SEE = 0x04, /* this property must be seen */
140                IS_LAST = 0x08 /* this is the last property to be read */
141        } flags;
142        char *fmt; /* format string for the arguments, NULL means a string arg */
143        int nvals; /* number of values to be read by sscanf */
144        void *vp[4]; /* pointers to values to be read */
145};
146               
147static struct line header[] = {
148        { GETLEN("FONT "), 0, " %200s", 1, {&xlfdname} },
149        { GETLEN("SIZE "), MUST_SEE, " %d", 1, {&pixel_size} },
150        { GETLEN("FONTBOUNDINGBOX "), MUST_SEE, " %hd %hd %hd %hd", 4,
151                {&fmet.bbox[2], &fmet.bbox[3], &fmet.bbox[0], &fmet.bbox[1]} },
152        { GETLEN("FAMILY_NAME "), MUST_SEE, NULL, 1, {&fmet.name_family} },
153        { GETLEN("WEIGHT_NAME "), MUST_SEE, NULL, 1, {&fmet.name_style} },
154        { GETLEN("COPYRIGHT "), 0, NULL, 1, {&fmet.name_copyright} },
155        { GETLEN("SLANT "), MUST_SEE, NULL, 1, {&slant} },
156        { GETLEN("SPACING "), 0, NULL, 1, {&spacing} },
157        { GETLEN("SETWIDTH_NAME "), 0, NULL, 1, {&fnwidth} },
158        { GETLEN("CHARSET_REGISTRY "), 0, NULL, 1, {&charset_reg} },
159        { GETLEN("CHARSET_ENCODING "), 0, NULL, 1, {&charset_enc} },
160        { GETLEN("FONT_ASCENT "), 0, " %hd", 1, {&fmet.ascender} },
161        { GETLEN("FONT_DESCENT "), 0, " %hd", 1, {&fmet.descender} },
162
163        /* these 2 must go in this order for post-processing */
164        { GETLEN("UNDERLINE_THICKNESS "), 0, " %hd", 1, {&fmet.underline_thickness} },
165        { GETLEN("UNDERLINE_POSITION "), 0, " %hd", 1, {&fmet.underline_position} },
166
167        { GETLEN("CHARS "), MUST_SEE|IS_LAST, " %d", 1, {&nglyphs} },
168        { NULL, 0, 0 } /* end mark: name==NULL */
169};
170
171static int
172handle_header(
173        int len,
174        char *str
175)
176{
177        struct line *cl;
178        char *s, *p;
179        char bf[2000];
180        int c;
181
182#if 0
183        fprintf(stderr, "line: %s\n", str);
184#endif
185        for(cl = header; cl->name != 0; cl++) {
186                if(strncmp(str, cl->name, cl->namelen))
187                        continue;
188#if 0
189                fprintf(stderr, "match: %s\n", cl->name);
190#endif
191                if(cl->flags & IS_SEEN) {
192                        if(cl->flags & ALLOW_REPEAT)
193                                continue;
194                       
195                        fprintf(stderr, "**** input line %d redefines the property %s\n", lineno, cl->name);
196                        exit(1);
197                }
198                cl->flags |= IS_SEEN;
199                if(cl->fmt == 0) {
200                        if(len - cl->namelen + 1 > sizeof bf)
201                                len = sizeof bf; /* cut it down */
202
203                        s = bf; /* a temporary buffer to extract the value */
204
205                        /* skip until a quote */
206                        for(p = str+cl->namelen; len!=0 && (c = *p)!=0; p++, len--) {
207                                if(c == '"') {
208                                        p++;
209                                        break;
210                                }
211                        }
212                        for(; len!=0 && (c = *p)!=0; p++, len--) {
213                                if(c == '"') {
214                                        c = *++p;
215                                        if(c == '"')
216                                                *s++ = c;
217                                        else
218                                                break;
219                                } else
220                                        *s++ = c;
221                        }
222                        *s = 0; /* end of line */
223
224                        *((char **)(cl->vp[0])) = dupcnstring(bf, s-bf);
225                } else {
226                        c = sscanf(str+cl->namelen, cl->fmt, cl->vp[0], cl->vp[1], cl->vp[2], cl->vp[3]);
227                        if(c != cl->nvals) {
228                                fprintf(stderr, "**** property %s at input line %d must have %d arguments\n",
229                                        cl->name, lineno, cl->nvals);
230                                exit(1);
231                        }
232                }
233                if(cl->flags & IS_LAST)
234                        return 1;
235                else
236                        return 0;
237        }
238        return 0;
239}
240
241/*
242 * Parse the description of the glyphs
243 */
244
245static int
246handle_glyphs(
247        int len,
248        char *str
249)
250{
251        static int inbmap=0;
252        static char *bmap;
253        static int xsz, ysz, xoff, yoff;
254        static int curln;
255        int i, c;
256        char *p, *plim, *psz;
257
258        if(!LENCMP(str, "ENDFONT")) {
259                if(curgl < nglyphs) {
260                        fprintf(stderr, "**** unexpected end of font file after %d glyphs\n", curgl);
261                        exit(1);
262                } else
263                        return 1;
264        }
265        if(curgl >= nglyphs) {
266                fprintf(stderr, "**** file contains more glyphs than advertised (%d)\n", nglyphs);
267                exit(1);
268        }
269        if(!LENCMP(str, "STARTCHAR")) {
270                /* sizeof will count \0 instead of ' ' */
271                for(i=sizeof("STARTCHAR"); str[i] == ' '; i++)
272                        {}
273
274                glyphs[curgl].name = strdup(str + i);
275                if(glyphs[curgl].name == 0) {
276                        fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
277                        exit(255);
278                }
279        } else if(!LENCMP(str, "ENCODING")) {
280                if(sscanf(str, "ENCODING %d", &fontenc[curgl])!=1) {
281                        fprintf(stderr,"**** weird ENCODING statement at line %d\n", lineno);
282                        exit(1);
283                }
284                if(fontenc[curgl] == -1)  /* compatibility format */
285                        sscanf(str, "ENCODING -1 %d", &fontenc[curgl]);
286                if(fontenc[curgl] > maxenc)
287                        maxenc = fontenc[curgl];
288        } else if(!LENCMP(str, "DWIDTH")) {
289                if(sscanf(str, "DWIDTH %d %d", &xsz, &ysz)!=2) {
290                        fprintf(stderr,"**** weird DWIDTH statement at line %d\n", lineno);
291                        exit(1);
292                }
293                glyphs[curgl].width = xsz*scale;
294        } else if(!LENCMP(str, "BBX")) {
295                if(sscanf(str, "BBX %d %d %d %d", &xsz, &ysz, &xoff, &yoff)!=4) {
296                        fprintf(stderr,"**** weird BBX statement at line %d\n", lineno);
297                        exit(1);
298                }
299                bmap=malloc(xsz*ysz);
300                if(bmap==0) {
301                        fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
302                        exit(255);
303                }
304                glyphs[curgl].lsb = -xoff*scale;
305                glyphs[curgl].xMin = -xoff*scale;
306                glyphs[curgl].xMax = (xsz-xoff)*scale;
307                glyphs[curgl].yMin = -yoff*scale;
308                glyphs[curgl].yMax = (ysz-xoff)*scale;
309        } else if(!LENCMP(str, "BITMAP")) {
310                inbmap=1;
311                curln=ysz-1; /* the lowest line has index 0 */
312        } else if(!LENCMP(str, "ENDCHAR")) {
313                inbmap=0;
314                if(bmap) {
315                        glyphs[curgl].lastentry = 0;
316                        glyphs[curgl].path = 0;
317                        glyphs[curgl].entries = 0;
318                        bmp_outline(&glyphs[curgl], scale, bmap, xsz, ysz, xoff, yoff);
319                        free(bmap);
320                        /* remember in a static table or it will be erased */
321                        glpaths[curgl] = glyphs[curgl].entries;
322                        glyphs[curgl].entries = 0;
323
324                        if(glpaths[curgl])
325                                glyphs[curgl].ttf_pathlen = 1;
326                        else
327                                glyphs[curgl].ttf_pathlen = 0;
328                }
329                curgl++;
330        } else if(inbmap) {
331                if(curln<0) {
332                        fprintf(stderr,"**** bitmap is longer than %d lines at line %d\n", ysz, lineno);
333                        exit(1);
334                }
335
336                i=0;
337                p=&bmap[curln*xsz]; psz=p+xsz;
338                while(i<len) {
339                        c=str[i++];
340                        if(!isxdigit(c)) {
341                                fprintf(stderr,"**** non-hex digit in bitmap at line %d\n", lineno);
342                                exit(1);
343                        }
344                        if(c<='9')
345                                c-='0';
346                        else
347                                c= tolower(c)-'a'+10;
348
349                        for(plim=p+4; p<psz && p<plim; c<<=1)
350                                *p++ = (( c & 0x08 )!=0);
351                }
352                if(p<psz) {
353                        fprintf(stderr,"**** bitmap line is too short at line %d\n", lineno);
354                        exit(1);
355                }
356                curln--;
357        }
358        return 0;
359}
360
361/*
362 * Read all the possible information about the glyphs
363 */
364
365static void
366readglyphs(
367        GLYPH *glyph_list
368)
369{
370        int i;
371        GLYPH *g;
372
373        if(got_glyphs)
374                return;
375
376        /* pass them to handle_glyphs() through statics */
377        glyphs = glyph_list;
378        curgl = 2; /* skip the empty glyph and .notdef */
379
380        /* initialize the empty glyph and .notdef */
381
382        for(i=0; i<2; i++) {
383                g = &glyphs[i];
384                g->lsb = 0;
385                g->width = fmet.bbox[2];
386                g->xMin = 0;
387                g->yMin = 0;
388        }
389        g = &glyphs[0];
390        g->name = ".notdef";
391        g->xMax = fmet.bbox[2]*4/5;
392        g->yMax = fmet.bbox[3]*4/5;
393        g->entries = g->path = g->lastentry = 0;
394        /* make it look as a black square */
395        fg_rmoveto(g, 0.0, 0.0);
396        fg_rlineto(g, 0.0, (double)g->yMax);
397        fg_rlineto(g, (double)g->xMax, (double)g->yMax);
398        fg_rlineto(g, (double)g->xMax, 0.0);
399        fg_rlineto(g, 0.0, 0.0);
400        g_closepath(g);
401        glpaths[0] = g->entries;
402        g->entries = 0;
403        g->ttf_pathlen = 4;
404
405        g = &glyphs[1];
406        g->name = ".null";
407        g->xMax = g->yMax = 0;
408        g->ttf_pathlen = 0;
409
410        if(readfile(bdf_file, handle_glyphs) < 0) {
411                fprintf(stderr, "**** file does not contain the ENDFONT line\n");
412                exit(1);
413        }
414        got_glyphs = 1;
415}
416
417/*
418 * Open font and prepare to return information to the main driver.
419 * May print error and warning messages.
420 * Exit on error.
421 */
422
423static void
424openfont(
425        char *fname,
426        char *arg /* unused now */
427)
428{
429        struct line *cl;
430        int i, l;
431
432        if ((bdf_file = fopen(fname, "r")) == NULL) {
433                fprintf(stderr, "**** Cannot open file '%s'\n", fname);
434                exit(1);
435        } else {
436                WARNING_2 fprintf(stderr, "Processing file %s\n", fname);
437        }
438
439        lineno = 1;
440
441        for(cl = header; cl->name != 0; cl++)
442                cl->flags &= ~IS_SEEN;
443        if(readfile(bdf_file, handle_header) < 0) {
444                fprintf(stderr, "**** file does not contain the CHARS definition\n");
445                exit(1);
446        }
447        for(cl = header; cl->name != 0; cl++) {
448                if( (cl->flags & MUST_SEE) && !(cl->flags & IS_SEEN) ) {
449                        fprintf(stderr, "**** mandatory property %sis not found in the input line\n",
450                                cl->name); /* cl->name has a space at the end */
451                        exit(1);
452                }
453
454                /* set a few defaults */
455                if( !(cl->flags & IS_SEEN) ) {
456                        if(cl->vp[0] == &fmet.underline_thickness) {
457                                fmet.underline_thickness = 1;
458                        } else if(cl->vp[0] == &fmet.underline_position) {
459                                fmet.underline_position = fmet.bbox[1] + fmet.underline_thickness
460                                        - (pixel_size - fmet.bbox[3]);
461                        } else if(cl->vp[0] == &fmet.ascender) {
462                                fmet.ascender = fmet.bbox[2] + fmet.bbox[0];
463                        } else if(cl->vp[0] == &fmet.descender) {
464                                fmet.descender = fmet.bbox[0];
465                        }
466                }
467        }
468
469        nglyphs += 2; /* add empty glyph and .notdef */
470
471        /* postprocessing to compensate for the differences in the metric formats */
472        fmet.bbox[2] += fmet.bbox[0];
473        fmet.bbox[3] += fmet.bbox[1];
474
475        scale = 1000/pixel_size; /* XXX ? */
476        if(scale*pixel_size < 950) {
477                scale = 1;
478                scale_external = 1;
479                fmet.units_per_em = pixel_size;
480        } else {
481                scale_external = 0;
482                fmet.units_per_em = scale*pixel_size;
483
484                fmet.underline_position *= scale;
485                fmet.underline_thickness *= scale;
486                fmet.ascender *= scale;
487                fmet.descender *= scale;
488                for(i=0; i<4; i++)
489                        fmet.bbox[i] *= scale;
490        }
491
492        fmet.italic_angle = 0.0;
493        if(spacing == 0 /* possibly an old font */
494        || toupper(spacing[0]) != 'P') /* or anything non-proportional */
495                fmet.is_fixed_pitch = 1;
496        else
497                fmet.is_fixed_pitch = 0;
498
499        if(fmet.name_copyright==NULL)
500                fmet.name_copyright = "";
501       
502        /* create the full name */
503        l = strlen(fmet.name_family)
504                + (fmet.name_style? strlen(fmet.name_style) : 0)
505                + (fnwidth? strlen(fnwidth) : 0)
506                + strlen("Oblique") + 1;
507
508        if(( fmet.name_full = malloc(l) )==NULL) {
509                fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
510                exit(255);
511        }
512        strcpy(fmet.name_full, fmet.name_family);
513        if(fnwidth && strcmp(fnwidth, "Normal")) {
514                strcat(fmet.name_full, fnwidth);
515        }
516        if(fmet.name_style && strcmp(fmet.name_style, "Medium")) {
517                strcat(fmet.name_full, fmet.name_style);
518        }
519        switch(toupper(slant[0])) {
520        case 'O':
521                strcat(fmet.name_full, "Oblique");
522                break;
523        case 'I':
524                strcat(fmet.name_full, "Italic");
525                break;
526        }
527
528        fmet.name_ps = fmet.name_full;
529        fmet.name_version = "1.0";
530
531        if(charset_reg && charset_enc
532        && !strcmp(charset_reg, "iso10646") && !strcmp(charset_enc, "1"))
533                is_unicode = 1;
534
535        if(( fontenc = calloc(nglyphs, sizeof *fontenc) )==NULL) {
536                fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
537                exit(255);
538        }
539        for(i=0; i<nglyphs; i++)
540                fontenc[i] = -1;
541        if(( glpaths = calloc(nglyphs, sizeof *glpaths) )==NULL) {
542                fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
543                exit(255);
544        }
545}
546
547/*
548 * Close font.
549 * Exit on error.
550 */
551
552static void
553closefont(
554        void
555)
556{
557        if(fclose(bdf_file) < 0) {
558                WARNING_1 fprintf(stderr, "Errors when closing the font file, ignored\n");
559        }
560}
561
562/*
563 * Get the number of glyphs in font.
564 */
565
566static int
567getnglyphs (
568        void
569)
570{
571        return nglyphs;
572}
573
574/*
575 * Get the names of the glyphs.
576 * Returns 0 if the names were assigned, non-zero if the font
577 * provides no glyph names.
578 */
579
580static int
581glnames(
582        GLYPH *glyph_list
583)
584{
585        readglyphs(glyph_list);
586        return 0;
587}
588
589/*
590 * Get the original encoding of the font.
591 * Returns 1 for if the original encoding is Unicode, 2 if the
592 * original encoding is other 16-bit, 0 if 8-bit.
593 */
594
595static int
596glenc(
597        GLYPH *glyph_list,
598        int *encoding,
599        int *unimap
600)
601{
602        int i, douni, e;
603
604        if(is_unicode || forcemap)
605                douni = 1;
606        else
607                douni = 0;
608
609        for(i=0; i<nglyphs; i++) {
610                e = fontenc[i];
611                if(douni)
612                        e = unicode_rev_lookup(e);
613                if(e>=0 && e<ENCTABSZ && encoding[e] == -1)
614                        encoding[e] = i;
615        }
616
617        if(is_unicode)
618                return 1;
619        else if(maxenc > 255)
620                return 2;
621        else
622                return 0;
623}
624       
625/*
626 * Get the font metrics
627 */
628static void
629fnmetrics(
630        struct font_metrics *fm
631)
632{
633        *fm = fmet;
634}
635
636/*
637 * Get the path of contrours for a glyph.
638 */
639
640static void
641glpath(
642        int glyphno,
643        GLYPH *glyf_list
644)
645{
646        readglyphs(glyf_list);
647        glyf_list[glyphno].entries = glpaths[glyphno];
648        glpaths[glyphno] = 0;
649}
650
651/*
652 * Get the kerning data.
653 */
654
655static void
656kerning(
657        GLYPH *glyph_list
658)
659{
660        return; /* no kerning in BDF */
661}
Note: See TracBrowser for help on using the repository browser.