diff options
author | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
commit | f4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch) | |
tree | 2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/extras/ttf2pt1/ft.c | |
parent | a840692edc9c6d19cd7c057f68e39c7d95eb767d (diff) | |
download | nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2 nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip |
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz
Keywords:
Imported nx-X11-3.1.0-1.tar.gz
into Git repository
Diffstat (limited to 'nx-X11/extras/ttf2pt1/ft.c')
-rw-r--r-- | nx-X11/extras/ttf2pt1/ft.c | 808 |
1 files changed, 808 insertions, 0 deletions
diff --git a/nx-X11/extras/ttf2pt1/ft.c b/nx-X11/extras/ttf2pt1/ft.c new file mode 100644 index 000000000..60a429654 --- /dev/null +++ b/nx-X11/extras/ttf2pt1/ft.c @@ -0,0 +1,808 @@ +/* + * 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 <ft2build.h> +#include FT_FREETYPE_H +#include FT_TRUETYPE_TABLES_H +#include FT_BBOX_H +#include FT_GLYPH_H + +#include FT_CONFIG_CONFIG_H +#include FT_CONFIG_OPTIONS_H +#include FT_ERRORS_H +#include FT_SYSTEM_H +#include FT_IMAGE_H +#include FT_TYPES_H +#include FT_OUTLINE_H +#include FT_MODULE_H +#include FT_RENDER_H +#include FT_TYPE1_TABLES_H +#include FT_TRUETYPE_IDS_H +#include FT_TRUETYPE_TAGS_H +#include FT_MULTIPLE_MASTERS_H +#include FT_SFNT_NAMES_H + +#ifdef XP_PSTEXT +#include "os.h" +#include "Xproto.h" +#include "font.h" +#include "fontstruct.h" +#include "fntfilst.h" +#include "fontutil.h" +#include "fontenc.h" +#include "ft.h" +#define NOT_IN_FTFUNCS +#include "ftfuncs.h" +#endif /* XP_PSTEXT */ + +#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 FreeType2 library", + /*suffix*/ { "ttf", "ttc", "otf", "otc", "pfa", "pfb" }, + /*open*/ openfont, + /*close*/ closefont, + /*nglyphs*/ getnglyphs, + /*glnames*/ glnames, + /*glmetrics*/ glmetrics, + /*glenc*/ glenc, + /*fnmetrics*/ fnmetrics, + /*glpath*/ glpath, + /*kerning*/ kerning, +}; + +/* statics */ + +static char * dupcnstring( unsigned char *s, int len); + +#ifndef XP_PSTEXT +static FT_Library library; +#endif /* !XP_PSTEXT */ +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; + +#ifdef XP_PSTEXT + extern FT_Face xp_pstext_ft_face; + extern FT_Library ftypeLibrary; /* defined in xc/lib/font/FreeType/ftfuncs.c */ + + face = xp_pstext_ft_face; +#else + 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); + } +#endif /* XP_PSTEXT */ + + 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 +) +{ +#ifdef XP_PSTEXT + /* NOP */ +#else + 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"); + } +#endif /* XP_PSTEXT */ +} + +/* + * 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 + +#ifdef XP_PSTEXT + char buf[1024]; + long i; + FT_Error error; + +#ifdef XP_ONLY_BLOCKS + extern unsigned long xp_font_block_offset; + extern FTFontPtr xp_xtf; + int bc; /* block counter */ + + + /* FixMe: This code should use PsOut_Get_FreeType_Glyph_Name() instead of + * duplicating the code + */ + for( bc = xp_font_block_offset ; bc < (xp_font_block_offset+256) ; bc++ ) { + /* Remap X11 font index to FreeType font index */ + i = FTRemap(face, &xp_xtf->mapping, bc); + + if( i >= face->num_glyphs ) + continue; +#else + for(i=0; i < face->num_glyphs; i++) { +#endif /* XP_ONLY_BLOCKS */ + if( FT_Has_PS_Glyph_Names(face) ) { + error = FT_Get_Glyph_Name(face, i, buf, MAX_NAMELEN); + } + else + { + error = -1; + } + + if( error ) { + /* Check for unicode mapping + * See Adobe document "Unicode and Glyph Names" + * (http://partners.adobe.com/asn/tech/type/unicodegn.jsp) + */ + if( (xp_xtf->mapping.mapping->type == FONT_ENCODING_UNICODE) && + (i < 0xFFFE) ) + { + sprintf(buf, "uni%04lx", i); + } + else + { + sprintf(buf, "ch%02lx", i); + } + } + glyph_list[i].name = strdup(buf); + if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, buf); + if (glyph_list[i].name == NULL) { + fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); + exit(255); + } + } + + return 0; +#else + char bf[1024]; + long 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; +#endif /* XP_PSTEXT */ +} + +/* + * 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; + +#ifdef XP_ONLY_BLOCKS + extern unsigned long xp_font_block_offset; + extern FTFontPtr xp_xtf; + int bc; /* block counter */ + + for( bc = xp_font_block_offset ; bc < (xp_font_block_offset+256) ; bc++ ) { + /* Remap X11 font index to FreeType font index */ + i = FTRemap(face, &xp_xtf->mapping, bc); + + if( i >= face->num_glyphs ) + continue; + +#else + for(i=0; i < face->num_glyphs; i++) { +#endif /* XP_ONLY_BLOCKS */ + 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; + } +} + +/* + * 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 +) +{ +#ifdef XP_PSTEXT + int i, + e; + unsigned code; + extern FTFontPtr xp_xtf; + extern unsigned long xp_font_block_offset; + + enc_found = 1; + enc_type = 0; + + for(i=0; i<ENCTABSZ; i++) { + if(encoding[i] != -1) + continue; + + /* Remap X11 font index to FreeType font index */ + code = FTRemap(face, &xp_xtf->mapping, xp_font_block_offset+i); + + if(code == 0) + continue; /* .notdef */ + + encoding[i] = code; + } + + return enc_type; +#else + int i, e; + unsigned code; + + 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( 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; +#endif /* XP_PSTEXT */ +} + +/* duplicate a string with counter to a 0-terminated string */ +static char * +dupcnstring( + unsigned char *s, + int len +) +{ + char *res, *out; + int i, c; + static int warned=0; + + if(( res = malloc(len+1) )==NULL) { + fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); + exit(255); + } + + out = res; + for(i=0; i<len; i++) { + if(( c=s[i] )>=' ' && c!=127) + *out++ = c; + else if(!warned) { + warned=1; + WARNING_1 fprintf(stderr, "Some font name strings are in Unicode, may not show properly\n"); + } + } + *out = 0; + return res; +} + +/* + * 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; + + 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 XP_PSTEXT + { + extern const char *xp_psfontname; + + fm->name_ps = strdup(xp_psfontname); + + /* Handle the rare case if a family name was not provided by the TTF + * font (like Solaris TTF fonts in /usr/openwin/lib/locale/ko.UTF-8/X11/fonts/TrueType, + * /usr/openwin/lib/locale/ko/X11/fonts/TrueType) - in this case we + * have to generate a family name somehow... */ + if(fm->name_family == NULL) + fm->name_family = fm->name_ps; + } +#else + +#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 */ + +#endif /* XP_PSTEXT */ + + 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]; + for(i=0; str[i]!=0; i++) { + if( (str[i]=='B' + || str[i]=='b' + && ( i==0 || !isalpha(str[i-1]) ) + ) + && !strncmp("old",&str[i+1],3) + && !islower(str[i+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 |