PHP Classes

File: application/libraries/dompdf/lib/ttf2ufm/src/bdf.c

Recommend this page to a friend!
  Classes of harold rita   PHP Thesis Proposal Hub   application/libraries/dompdf/lib/ttf2ufm/src/bdf.c   Download  
File: application/libraries/dompdf/lib/ttf2ufm/src/bdf.c
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: PHP Thesis Proposal Hub
Store and publish research thesis documents
Author: By
Last change:
Date: 6 years ago
Size: 15,274 bytes
 

Contents

Class file image Download
/* * The font parser for the BDF files * * Copyright (c) 2001 by the TTF2PT1 project * Copyright (c) 2001 by Sergey Babkin * * see COPYRIGHT for the full copyright notice */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include "pt1.h" #include "global.h" /* prototypes of call entries */ static void openfont(char *fname, char *arg); static void closefont( void); static int getnglyphs ( void); static int glnames( GLYPH *glyph_list); static void readglyphs( GLYPH *glyph_list); static int glenc( GLYPH *glyph_list, int *encoding, int *unimap); static void fnmetrics( struct font_metrics *fm); static void glpath( int glyphno, GLYPH *glyph_list); static void kerning( GLYPH *glyph_list); /* globals */ /* front-end descriptor */ struct frontsw bdf_sw = { /*name*/ "bdf", /*descr*/ "BDF bitmapped fonts", /*suffix*/ { "bdf" }, /*open*/ openfont, /*close*/ closefont, /*nglyphs*/ getnglyphs, /*glnames*/ glnames, /*glmetrics*/ readglyphs, /*glenc*/ glenc, /*fnmetrics*/ fnmetrics, /*glpath*/ glpath, /*kerning*/ kerning, }; /* statics */ #define MAXLINE 10240 /* maximal line length in the input file */ static int lineno; /* line number */ #define GETLEN(s) s, (sizeof(s)-1) #define LENCMP(str, txt) strncmp(str, txt, sizeof(txt)-1) static FILE *bdf_file; static int nglyphs; static struct font_metrics fmet; /* many BDF fonts are of small pixel size, so we better try * to scale them by an integer to keep the dimensions in * whole pixels. However if the size is too big and a non- * integer scaling is needed, we use the standard ttf2pt1's * scaling abilities. */ static int pixel_size; static int scale; static int scale_external; static char *slant; static char xlfdname[201]; static char *spacing; static char *charset_reg; static char *charset_enc; static char *fnwidth; static int is_unicode = 0; /* tempoary storage for returning data to ttf2pt1 later on request */ static int maxenc = 0; static int *fontenc; static GENTRY **glpaths; static int got_glyphs = 0; static GLYPH *glyphs; static int curgl; static int readfile(FILE *f, int (*strfunc)(int len, char *str)); /* * Read the file and parse each string with strfunc(), * until strfunc() returns !=0 or the end of file happens. * Returns -1 on EOF or strfunc() returning <0, else 0 */ static int readfile( FILE *f, int (*strfunc)(int len, char *str) ) { static char str[MAXLINE]; /* input line, maybe should be dynamic ? */ char *s; int len, c, res; len=0; while(( c=getc(f) )!=EOF) { if(c=='\n') { str[len]=0; res = strfunc(len, str); lineno++; if(res<0) return -1; else if(res!=0) return 0; len=0; } else if(len<MAXLINE-1) { if(c!='\r') str[len++]=c; } else { fprintf(stderr, "**** bdf: line %d is too long (>%d)\n", lineno, MAXLINE-1); exit(1); } } return -1; /* EOF */ } /* * Parse the header of the font file. * Stop after the line CHARS is encountered. Ignore the unknown lines. */ struct line { char *name; /* property name with trailing space */ int namelen; /* length of the name string */ enum { ALLOW_REPEAT = 0x01, /* this property may be repeated in multiple lines */ IS_SEEN = 0x02, /* this property has been seen already */ MUST_SEE = 0x04, /* this property must be seen */ IS_LAST = 0x08 /* this is the last property to be read */ } flags; char *fmt; /* format string for the arguments, NULL means a string arg */ int nvals; /* number of values to be read by sscanf */ void *vp[4]; /* pointers to values to be read */ }; static struct line header[] = { { GETLEN("FONT "), 0, " %200s", 1, {&xlfdname} }, { GETLEN("SIZE "), MUST_SEE, " %d", 1, {&pixel_size} }, { GETLEN("FONTBOUNDINGBOX "), MUST_SEE, " %hd %hd %hd %hd", 4, {&fmet.bbox[2], &fmet.bbox[3], &fmet.bbox[0], &fmet.bbox[1]} }, { GETLEN("FAMILY_NAME "), MUST_SEE, NULL, 1, {&fmet.name_family} }, { GETLEN("WEIGHT_NAME "), MUST_SEE, NULL, 1, {&fmet.name_style} }, { GETLEN("COPYRIGHT "), 0, NULL, 1, {&fmet.name_copyright} }, { GETLEN("SLANT "), MUST_SEE, NULL, 1, {&slant} }, { GETLEN("SPACING "), 0, NULL, 1, {&spacing} }, { GETLEN("SETWIDTH_NAME "), 0, NULL, 1, {&fnwidth} }, { GETLEN("CHARSET_REGISTRY "), 0, NULL, 1, {&charset_reg} }, { GETLEN("CHARSET_ENCODING "), 0, NULL, 1, {&charset_enc} }, { GETLEN("FONT_ASCENT "), 0, " %hd", 1, {&fmet.ascender} }, { GETLEN("FONT_DESCENT "), 0, " %hd", 1, {&fmet.descender} }, /* these 2 must go in this order for post-processing */ { GETLEN("UNDERLINE_THICKNESS "), 0, " %hd", 1, {&fmet.underline_thickness} }, { GETLEN("UNDERLINE_POSITION "), 0, " %hd", 1, {&fmet.underline_position} }, { GETLEN("CHARS "), MUST_SEE|IS_LAST, " %d", 1, {&nglyphs} }, { NULL, 0, 0 } /* end mark: name==NULL */ }; static int handle_header( int len, char *str ) { struct line *cl; char *s, *p; char bf[2000]; int c; #if 0 fprintf(stderr, "line: %s\n", str); #endif for(cl = header; cl->name != 0; cl++) { if(strncmp(str, cl->name, cl->namelen)) continue; #if 0 fprintf(stderr, "match: %s\n", cl->name); #endif if(cl->flags & IS_SEEN) { if(cl->flags & ALLOW_REPEAT) continue; fprintf(stderr, "**** input line %d redefines the property %s\n", lineno, cl->name); exit(1); } cl->flags |= IS_SEEN; if(cl->fmt == 0) { if(len - cl->namelen + 1 > sizeof bf) len = sizeof bf; /* cut it down */ s = bf; /* a temporary buffer to extract the value */ /* skip until a quote */ for(p = str+cl->namelen; len!=0 && (c = *p)!=0; p++, len--) { if(c == '"') { p++; break; } } for(; len!=0 && (c = *p)!=0; p++, len--) { if(c == '"') { c = *++p; if(c == '"') *s++ = c; else break; } else *s++ = c; } *s = 0; /* end of line */ *((char **)(cl->vp[0])) = dupcnstring(bf, s-bf); } else { c = sscanf(str+cl->namelen, cl->fmt, cl->vp[0], cl->vp[1], cl->vp[2], cl->vp[3]); if(c != cl->nvals) { fprintf(stderr, "**** property %s at input line %d must have %d arguments\n", cl->name, lineno, cl->nvals); exit(1); } } if(cl->flags & IS_LAST) return 1; else return 0; } return 0; } /* * Parse the description of the glyphs */ static int handle_glyphs( int len, char *str ) { static int inbmap=0; static char *bmap; static int xsz, ysz, xoff, yoff; static int curln; int i, c; char *p, *plim, *psz; if(!LENCMP(str, "ENDFONT")) { if(curgl < nglyphs) { fprintf(stderr, "**** unexpected end of font file after %d glyphs\n", curgl); exit(1); } else return 1; } if(curgl >= nglyphs) { fprintf(stderr, "**** file contains more glyphs than advertised (%d)\n", nglyphs); exit(1); } if(!LENCMP(str, "STARTCHAR")) { /* sizeof will count \0 instead of ' ' */ for(i=sizeof("STARTCHAR"); str[i] == ' '; i++) {} glyphs[curgl].name = strdup(str + i); if(glyphs[curgl].name == 0) { fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); exit(255); } } else if(!LENCMP(str, "ENCODING")) { if(sscanf(str, "ENCODING %d", &fontenc[curgl])!=1) { fprintf(stderr,"**** weird ENCODING statement at line %d\n", lineno); exit(1); } if(fontenc[curgl] == -1) /* compatibility format */ sscanf(str, "ENCODING -1 %d", &fontenc[curgl]); if(fontenc[curgl] > maxenc) maxenc = fontenc[curgl]; } else if(!LENCMP(str, "DWIDTH")) { if(sscanf(str, "DWIDTH %d %d", &xsz, &ysz)!=2) { fprintf(stderr,"**** weird DWIDTH statement at line %d\n", lineno); exit(1); } glyphs[curgl].width = xsz*scale; } else if(!LENCMP(str, "BBX")) { if(sscanf(str, "BBX %d %d %d %d", &xsz, &ysz, &xoff, &yoff)!=4) { fprintf(stderr,"**** weird BBX statement at line %d\n", lineno); exit(1); } bmap=malloc(xsz*ysz); if(bmap==0) { fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); exit(255); } glyphs[curgl].lsb = -xoff*scale; glyphs[curgl].xMin = -xoff*scale; glyphs[curgl].xMax = (xsz-xoff)*scale; glyphs[curgl].yMin = -yoff*scale; glyphs[curgl].yMax = (ysz-xoff)*scale; } else if(!LENCMP(str, "BITMAP")) { inbmap=1; curln=ysz-1; /* the lowest line has index 0 */ } else if(!LENCMP(str, "ENDCHAR")) { inbmap=0; if(bmap) { glyphs[curgl].lastentry = 0; glyphs[curgl].path = 0; glyphs[curgl].entries = 0; bmp_outline(&glyphs[curgl], scale, bmap, xsz, ysz, xoff, yoff); free(bmap); /* remember in a static table or it will be erased */ glpaths[curgl] = glyphs[curgl].entries; glyphs[curgl].entries = 0; if(glpaths[curgl]) glyphs[curgl].ttf_pathlen = 1; else glyphs[curgl].ttf_pathlen = 0; } curgl++; } else if(inbmap) { if(curln<0) { fprintf(stderr,"**** bitmap is longer than %d lines at line %d\n", ysz, lineno); exit(1); } i=0; p=&bmap[curln*xsz]; psz=p+xsz; while(i<len) { c=str[i++]; if(!isxdigit(c)) { fprintf(stderr,"**** non-hex digit in bitmap at line %d\n", lineno); exit(1); } if(c<='9') c-='0'; else c= tolower(c)-'a'+10; for(plim=p+4; p<psz && p<plim; c<<=1) *p++ = (( c & 0x08 )!=0); } if(p<psz) { fprintf(stderr,"**** bitmap line is too short at line %d\n", lineno); exit(1); } curln--; } return 0; } /* * Read all the possible information about the glyphs */ static void readglyphs( GLYPH *glyph_list ) { int i; GLYPH *g; if(got_glyphs) return; /* pass them to handle_glyphs() through statics */ glyphs = glyph_list; curgl = 2; /* skip the empty glyph and .notdef */ /* initialize the empty glyph and .notdef */ for(i=0; i<2; i++) { g = &glyphs[i]; g->lsb = 0; g->width = fmet.bbox[2]; g->xMin = 0; g->yMin = 0; } g = &glyphs[0]; g->name = ".notdef"; g->xMax = fmet.bbox[2]*4/5; g->yMax = fmet.bbox[3]*4/5; g->entries = g->path = g->lastentry = 0; /* make it look as a black square */ fg_rmoveto(g, 0.0, 0.0); fg_rlineto(g, 0.0, (double)g->yMax); fg_rlineto(g, (double)g->xMax, (double)g->yMax); fg_rlineto(g, (double)g->xMax, 0.0); fg_rlineto(g, 0.0, 0.0); g_closepath(g); glpaths[0] = g->entries; g->entries = 0; g->ttf_pathlen = 4; g = &glyphs[1]; g->name = ".null"; g->xMax = g->yMax = 0; g->ttf_pathlen = 0; if(readfile(bdf_file, handle_glyphs) < 0) { fprintf(stderr, "**** file does not contain the ENDFONT line\n"); exit(1); } got_glyphs = 1; } /* * Open font and prepare to return information to the main driver. * May print error and warning messages. * Exit on error. */ static void openfont( char *fname, char *arg /* unused now */ ) { struct line *cl; int i, l; if ((bdf_file = fopen(fname, "r")) == NULL) { fprintf(stderr, "**** Cannot open file '%s'\n", fname); exit(1); } else { WARNING_2 fprintf(stderr, "Processing file %s\n", fname); } lineno = 1; for(cl = header; cl->name != 0; cl++) cl->flags &= ~IS_SEEN; if(readfile(bdf_file, handle_header) < 0) { fprintf(stderr, "**** file does not contain the CHARS definition\n"); exit(1); } for(cl = header; cl->name != 0; cl++) { if( (cl->flags & MUST_SEE) && !(cl->flags & IS_SEEN) ) { fprintf(stderr, "**** mandatory property %sis not found in the input line\n", cl->name); /* cl->name has a space at the end */ exit(1); } /* set a few defaults */ if( !(cl->flags & IS_SEEN) ) { if(cl->vp[0] == &fmet.underline_thickness) { fmet.underline_thickness = 1; } else if(cl->vp[0] == &fmet.underline_position) { fmet.underline_position = fmet.bbox[1] + fmet.underline_thickness - (pixel_size - fmet.bbox[3]); } else if(cl->vp[0] == &fmet.ascender) { fmet.ascender = fmet.bbox[2] + fmet.bbox[0]; } else if(cl->vp[0] == &fmet.descender) { fmet.descender = fmet.bbox[0]; } } } nglyphs += 2; /* add empty glyph and .notdef */ /* postprocessing to compensate for the differences in the metric formats */ fmet.bbox[2] += fmet.bbox[0]; fmet.bbox[3] += fmet.bbox[1]; scale = 1000/pixel_size; /* XXX ? */ if(scale*pixel_size < 950) { scale = 1; scale_external = 1; fmet.units_per_em = pixel_size; } else { scale_external = 0; fmet.units_per_em = scale*pixel_size; fmet.underline_position *= scale; fmet.underline_thickness *= scale; fmet.ascender *= scale; fmet.descender *= scale; for(i=0; i<4; i++) fmet.bbox[i] *= scale; } fmet.italic_angle = 0.0; if(spacing == 0 /* possibly an old font */ || toupper(spacing[0]) != 'P') /* or anything non-proportional */ fmet.is_fixed_pitch = 1; else fmet.is_fixed_pitch = 0; if(fmet.name_copyright==NULL) fmet.name_copyright = ""; /* create the full name */ l = strlen(fmet.name_family) + (fmet.name_style? strlen(fmet.name_style) : 0) + (fnwidth? strlen(fnwidth) : 0) + strlen("Oblique") + 1; if(( fmet.name_full = malloc(l) )==NULL) { fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); exit(255); } strcpy(fmet.name_full, fmet.name_family); if(fnwidth && strcmp(fnwidth, "Normal")) { strcat(fmet.name_full, fnwidth); } if(fmet.name_style && strcmp(fmet.name_style, "Medium")) { strcat(fmet.name_full, fmet.name_style); } switch(toupper(slant[0])) { case 'O': strcat(fmet.name_full, "Oblique"); break; case 'I': strcat(fmet.name_full, "Italic"); break; } fmet.name_ps = fmet.name_full; fmet.name_version = "1.0"; if(charset_reg && charset_enc && !strcmp(charset_reg, "iso10646") && !strcmp(charset_enc, "1")) is_unicode = 1; if(( fontenc = calloc(nglyphs, sizeof *fontenc) )==NULL) { fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); exit(255); } for(i=0; i<nglyphs; i++) fontenc[i] = -1; if(( glpaths = calloc(nglyphs, sizeof *glpaths) )==NULL) { fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); exit(255); } } /* * Close font. * Exit on error. */ static void closefont( void ) { if(fclose(bdf_file) < 0) { WARNING_1 fprintf(stderr, "Errors when closing the font file, ignored\n"); } } /* * Get the number of glyphs in font. */ static int getnglyphs ( void ) { return nglyphs; } /* * Get the names of the glyphs. * Returns 0 if the names were assigned, non-zero if the font * provides no glyph names. */ static int glnames( GLYPH *glyph_list ) { readglyphs(glyph_list); return 0; } /* * Get the original encoding of the font. * Returns 1 for if the original encoding is Unicode, 2 if the * original encoding is other 16-bit, 0 if 8-bit. */ static int glenc( GLYPH *glyph_list, int *encoding, int *unimap ) { int i, douni, e; if(is_unicode || forcemap) douni = 1; else douni = 0; for(i=0; i<nglyphs; i++) { e = fontenc[i]; if(douni) e = unicode_rev_lookup(e); if(e>=0 && e<ENCTABSZ && encoding[e] == -1) encoding[e] = i; } if(is_unicode) return 1; else if(maxenc > 255) return 2; else return 0; } /* * Get the font metrics */ static void fnmetrics( struct font_metrics *fm ) { *fm = fmet; } /* * Get the path of contrours for a glyph. */ static void glpath( int glyphno, GLYPH *glyf_list ) { readglyphs(glyf_list); glyf_list[glyphno].entries = glpaths[glyphno]; glpaths[glyphno] = 0; } /* * Get the kerning data. */ static void kerning( GLYPH *glyph_list ) { return; /* no kerning in BDF */ }