PHP Classes

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

Recommend this page to a friend!
  Classes of harold rita   PHP Thesis Proposal Hub   application/libraries/dompdf/lib/ttf2ufm/src/ft.c   Download  
File: application/libraries/dompdf/lib/ttf2ufm/src/ft.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: 14,184 bytes
 

Contents

Class file image Download
/* * The font parser using the FreeType library version 2. * * see COPYRIGHT * */ #ifdef USE_FREETYPE #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <sys/types.h> #include <freetype/config/ftheader.h> #include <freetype/freetype.h> #include <freetype/ftglyph.h> #include <freetype/ftsnames.h> #include <freetype/ttnameid.h> #include <freetype/ftoutln.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 glmetrics( 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 freetype_sw = { /*name*/ "ft", /*descr*/ "based on the FreeType library", /*suffix*/ { "ttf", "otf", "pfa", "pfb" }, /*open*/ openfont, /*close*/ closefont, /*nglyphs*/ getnglyphs, /*glnames*/ glnames, /*glmetrics*/ glmetrics, /*glenc*/ glenc, /*fnmetrics*/ fnmetrics, /*glpath*/ glpath, /*kerning*/ kerning, }; /* statics */ static FT_Library library; static FT_Face face; static int enc_type, enc_found; /* SFNT functions do not seem to be included by default in FT2beta8 */ #define ENABLE_SFNT /* * 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 */ ) { FT_Error error; if( FT_Init_FreeType( &library ) ) { fprintf(stderr, "** FreeType initialization failed\n"); exit(1); } if( error = FT_New_Face( library, fname, 0, &face ) ) { if ( error == FT_Err_Unknown_File_Format ) fprintf(stderr, "**** %s has format unknown to FreeType\n", fname); else fprintf(stderr, "**** Cannot access %s ****\n", fname); exit(1); } if(FT_HAS_FIXED_SIZES(face)) { WARNING_1 fprintf(stderr, "Font contains bitmaps\n"); } if(FT_HAS_MULTIPLE_MASTERS(face)) { WARNING_1 fprintf(stderr, "Font contains multiple masters, using default\n"); } if(ISDBG(FT)) fprintf(stderr," %d units per EM\n", face->units_per_EM); enc_found = 0; } /* * Close font. * Exit on error. */ static void closefont( void ) { if( FT_Done_Face(face) ) { WARNING_1 fprintf(stderr, "Errors when closing the font file, ignored\n"); } if( FT_Done_FreeType(library) ) { WARNING_1 fprintf(stderr, "Errors when stopping FreeType, ignored\n"); } } /* * Get the number of glyphs in font. */ static int getnglyphs ( void ) { if(ISDBG(FT)) fprintf(stderr, "%d glyphs in font\n", face->num_glyphs); return (int)face->num_glyphs; } /* * 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 ) { #define MAX_NAMELEN 1024 unsigned char bf[1024]; int i; if( ! FT_HAS_GLYPH_NAMES(face) ) { WARNING_1 fprintf(stderr, "Font has no glyph names\n"); return 1; } for(i=0; i < face->num_glyphs; i++) { if( FT_Get_Glyph_Name(face, i, bf, MAX_NAMELEN) || bf[0]==0 ) { sprintf(bf, "_g_%d", i); WARNING_2 fprintf(stderr, "Glyph No. %d has no postscript name, becomes %s\n", i, bf); } glyph_list[i].name = strdup(bf); if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, bf); if (glyph_list[i].name == NULL) { fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); exit(255); } } return 0; } /* * Get the metrics of the glyphs. */ static void glmetrics( GLYPH *glyph_list ) { GLYPH *g; int i; FT_Glyph_Metrics *met; FT_BBox bbox; FT_Glyph gly; FT_ULong charcode; FT_UInt index; for(i=0; i < face->num_glyphs; i++) { g = &(glyph_list[i]); if( FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE) ) { fprintf(stderr, "Can't load glyph %s, skipped\n", g->name); continue; } met = &face->glyph->metrics; if(FT_HAS_HORIZONTAL(face)) { g->width = met->horiAdvance; g->lsb = met->horiBearingX; } else { WARNING_2 fprintf(stderr, "Glyph %s has no horizontal metrics, guessed them\n", g->name); g->width = met->width; g->lsb = 0; } if( FT_Get_Glyph(face->glyph, &gly) ) { fprintf(stderr, "Can't access glyph %s bbox, skipped\n", g->name); continue; } FT_Glyph_Get_CBox(gly, ft_glyph_bbox_unscaled, &bbox); g->xMin = bbox.xMin; g->yMin = bbox.yMin; g->xMax = bbox.xMax; g->yMax = bbox.yMax; g->ttf_pathlen = face->glyph->outline.n_points; } charcode = FT_Get_First_Char(face, &index); while ( index != 0 ) { if ( index >= face->num_glyphs ) { break; } for ( i = 0; i < GLYPH_MAX_ENCODINGS; i++ ) { if ( glyph_list[index].orig_code[i] == -1 ) break; } if ( i == GLYPH_MAX_ENCODINGS ) { if (strcmp(glyph_list[index].name, ".notdef") != 0) { WARNING_2 fprintf(stderr, "Glyph %s has >= %d encodings (A), %4.4x & %4.4x\n", GLYPH_MAX_ENCODINGS, glyph_list[index].name, glyph_list[index].orig_code[i], charcode); } } else { glyph_list[index].orig_code[i] = charcode; } charcode = FT_Get_Next_Char(face, charcode, &index); } } /* * 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, e; unsigned code, index; if(ISDBG(FT)) for(e=0; e < face->num_charmaps; e++) { fprintf(stderr, "found encoding pid=%d eid=%d\n", face->charmaps[e]->platform_id, face->charmaps[e]->encoding_id); } if(enc_found) goto populate_map; enc_type = 0; /* first check for an explicit PID/EID */ if(force_pid != -1) { for(e=0; e < face->num_charmaps; e++) { if(face->charmaps[e]->platform_id == force_pid && face->charmaps[e]->encoding_id == force_eid) { WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n", force_pid, force_eid); if( !face->charmaps || FT_Set_Charmap(face, face->charmaps[e]) ) { fprintf(stderr, "**** Cannot set charmap in FreeType ****\n"); exit(1); } enc_type = 1; goto populate_map; } } fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n", force_pid, force_eid); exit(1); } /* next check for a direct Adobe mapping */ if(!forcemap) { for(e=0; e < face->num_charmaps; e++) { if(face->charmaps[e]->encoding == ft_encoding_adobe_custom) { WARNING_1 fputs("Found Adobe Custom Encoding\n", stderr); if( FT_Set_Charmap(face, face->charmaps[e]) ) { fprintf(stderr, "**** Cannot set charmap in FreeType ****\n"); exit(1); } goto populate_map; } } } for(e=0; e < face->num_charmaps; e++) { if(face->charmaps[e]->platform_id == 3) { switch(face->charmaps[e]->encoding_id) { case 0: WARNING_1 fputs("Found Symbol Encoding\n", stderr); break; case 1: WARNING_1 fputs("Found Unicode Encoding\n", stderr); enc_type = 1; break; default: WARNING_1 { fprintf(stderr, "****MS Encoding ID %d not supported****\n", face->charmaps[e]->encoding_id); fputs("Treating it like Symbol encoding\n", stderr); } break; } break; } } if(e >= face->num_charmaps) { WARNING_1 fputs("No Microsoft encoding, using first encoding available\n", stderr); e = 0; } if( FT_Set_Charmap(face, face->charmaps[e]) ) { fprintf(stderr, "**** Cannot set charmap in FreeType ****\n"); exit(1); } populate_map: enc_found = 1; for(i=0; i<ENCTABSZ; i++) { if(encoding[i] != -1) continue; if(enc_type == 1 || forcemap) { code = unimap[i]; if(code == (unsigned) -1) continue; } else code = i; code = FT_Get_Char_Index(face, code); if(0 && ISDBG(FT)) fprintf(stderr, "code of %3d is %3d\n", i, code); if(code == 0) continue; /* .notdef */ encoding[i] = code; } return enc_type; } /* * Get the font metrics */ static void fnmetrics( struct font_metrics *fm ) { char *str; static char *fieldstocheck[3]; #ifdef ENABLE_SFNT FT_SfntName sn; #endif /* ENABLE_SFNT */ int i, j, len; fm->italic_angle = 0.0; /* FreeType hides the angle */ fm->underline_position = face->underline_position; fm->underline_thickness = face->underline_thickness; fm->is_fixed_pitch = FT_IS_FIXED_WIDTH(face); fm->ascender = face->ascender; fm->descender = face->descender; fm->units_per_em = face->units_per_EM; fm->bbox[0] = face->bbox.xMin; fm->bbox[1] = face->bbox.yMin; fm->bbox[2] = face->bbox.xMax; fm->bbox[3] = face->bbox.yMax; #ifdef ENABLE_SFNT if( FT_Get_Sfnt_Name(face, TT_NAME_ID_COPYRIGHT, &sn) ) #endif /* ENABLE_SFNT */ fm->name_copyright = ""; #ifdef ENABLE_SFNT else fm->name_copyright = dupcnstring(sn.string, sn.string_len); #endif /* ENABLE_SFNT */ fm->name_family = face->family_name; fm->name_style = face->style_name; if(fm->name_style == NULL) fm->name_style = ""; #ifdef ENABLE_SFNT if( FT_Get_Sfnt_Name(face, TT_NAME_ID_FULL_NAME, &sn) ) #endif /* ENABLE_SFNT */ { int len; len = strlen(fm->name_family) + strlen(fm->name_style) + 2; if(( fm->name_full = malloc(len) )==NULL) { fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); exit(255); } strcpy(fm->name_full, fm->name_family); if(strlen(fm->name_style) != 0) { strcat(fm->name_full, " "); strcat(fm->name_full, fm->name_style); } } #ifdef ENABLE_SFNT else fm->name_full = dupcnstring(sn.string, sn.string_len); #endif /* ENABLE_SFNT */ #ifdef ENABLE_SFNT if( FT_Get_Sfnt_Name(face, TT_NAME_ID_VERSION_STRING, &sn) ) #endif /* ENABLE_SFNT */ fm->name_version = "1.0"; #ifdef ENABLE_SFNT else fm->name_version = dupcnstring(sn.string, sn.string_len); #endif /* ENABLE_SFNT */ #ifdef ENABLE_SFNT if( FT_Get_Sfnt_Name(face, TT_NAME_ID_PS_NAME , &sn) ) { #endif /* ENABLE_SFNT */ if(( fm->name_ps = strdup(fm->name_full) )==NULL) { fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); exit(255); } #ifdef ENABLE_SFNT } else fm->name_ps = dupcnstring(sn.string, sn.string_len); #endif /* ENABLE_SFNT */ for(i=0; fm->name_ps[i]!=0; i++) if(fm->name_ps[i] == ' ') fm->name_ps[i] = '_'; /* no spaces in the Postscript name *m /* guess the boldness from the font names */ fm->force_bold=0; fieldstocheck[0] = fm->name_style; fieldstocheck[1] = fm->name_full; fieldstocheck[2] = fm->name_ps; for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(fieldstocheck[0]); i++) { str=fieldstocheck[i]; len = strlen(str); for(j=0; j<len; j++) { if( (str[j]=='B' || str[j]=='b' && ( j==0 || !isalpha(str[j-1]) ) ) && !strncmp("old",&str[j+1],3) && (j+4 >= len || !islower(str[j+4])) ) { fm->force_bold=1; break; } } } } /* * Functions to decompose the outlines */ static GLYPH *curg; static double lastx, lasty; static int outl_moveto( FT_Vector *to, void *unused ) { double tox, toy; tox = fscale((double)to->x); toy = fscale((double)to->y); /* FreeType does not do explicit closepath() */ if(curg->lastentry) { g_closepath(curg); } fg_rmoveto(curg, tox, toy); lastx = tox; lasty = toy; return 0; } static int outl_lineto( FT_Vector *to, void *unused ) { double tox, toy; tox = fscale((double)to->x); toy = fscale((double)to->y); fg_rlineto(curg, tox, toy); lastx = tox; lasty = toy; return 0; } static int outl_conicto( FT_Vector *control1, FT_Vector *to, void *unused ) { double c1x, c1y, tox, toy; c1x = fscale((double)control1->x); c1y = fscale((double)control1->y); tox = fscale((double)to->x); toy = fscale((double)to->y); fg_rrcurveto(curg, (lastx + 2.0 * c1x) / 3.0, (lasty + 2.0 * c1y) / 3.0, (2.0 * c1x + tox) / 3.0, (2.0 * c1y + toy) / 3.0, tox, toy ); lastx = tox; lasty = toy; return 0; } static int outl_cubicto( FT_Vector *control1, FT_Vector *control2, FT_Vector *to, void *unused ) { double c1x, c1y, c2x, c2y, tox, toy; c1x = fscale((double)control1->x); c1y = fscale((double)control1->y); c2x = fscale((double)control2->x); c2y = fscale((double)control2->y); tox = fscale((double)to->x); toy = fscale((double)to->y); fg_rrcurveto(curg, c1x, c1y, c2x, c2y, tox, toy); lastx = tox; lasty = toy; return 0; } static FT_Outline_Funcs ft_outl_funcs = { outl_moveto, outl_lineto, outl_conicto, outl_cubicto, 0, 0 }; /* * Get the path of contrours for a glyph. */ static void glpath( int glyphno, GLYPH *glyf_list ) { FT_Outline *ol; curg = &glyf_list[glyphno]; if( FT_Load_Glyph(face, glyphno, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE|FT_LOAD_NO_HINTING) || face->glyph->format != ft_glyph_format_outline ) { fprintf(stderr, "Can't load glyph %s, skipped\n", curg->name); return; } ol = &face->glyph->outline; lastx = 0.0; lasty = 0.0; if( FT_Outline_Decompose(ol, &ft_outl_funcs, NULL) ) { fprintf(stderr, "Can't decompose outline of glyph %s, skipped\n", curg->name); return; } /* FreeType does not do explicit closepath() */ if(curg->lastentry) { g_closepath(curg); } if(ol->flags & ft_outline_reverse_fill) { assertpath(curg->entries, __FILE__, __LINE__, curg->name); reversepaths(curg); } } /* * Get the kerning data. */ static void kerning( GLYPH *glyph_list ) { int i, j, n; int nglyphs = face->num_glyphs; FT_Vector k; GLYPH *gl; if( nglyphs == 0 || !FT_HAS_KERNING(face) ) { WARNING_1 fputs("No Kerning data\n", stderr); return; } for(i=0; i<nglyphs; i++) { if( (glyph_list[i].flags & GF_USED) ==0) continue; for(j=0; j<nglyphs; j++) { if( (glyph_list[j].flags & GF_USED) ==0) continue; if( FT_Get_Kerning(face, i, j, ft_kerning_unscaled, &k) ) continue; if( k.x == 0 ) continue; addkernpair(i, j, k.x); } } } #endif