static const char* cff_get_ps_name( CFF_Face face ) { CFF_Font cff = (CFF_Font)face->extra.data; SFNT_Service sfnt = (SFNT_Service)face->sfnt; /* following the OpenType specification 1.7, we return the name stored */ /* in the `name' table for a CFF wrapped into an SFNT container */ if ( FT_IS_SFNT( FT_FACE( face ) ) && sfnt ) { FT_Library library = FT_FACE_LIBRARY( face ); FT_Module sfnt_module = FT_Get_Module( library, "sfnt" ); FT_Service_PsFontName service = (FT_Service_PsFontName)ft_module_get_service( sfnt_module, FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, 0 ); if ( service && service->get_ps_font_name ) return service->get_ps_font_name( FT_FACE( face ) ); } return (const char*)cff->font_name; }
static void fnt_face_done_fonts( FNT_Face face ) { FT_Memory memory = FT_FACE(face)->memory; FT_Stream stream = FT_FACE(face)->stream; FNT_Font* cur = face->fonts; FNT_Font* limit = cur + face->num_fonts; for ( ; cur < limit; cur++ ) fnt_font_done( cur, stream ); FREE( face->fonts ); face->num_fonts = 0; }
static void fnt_font_done( FNT_Face face ) { FT_Memory memory = FT_FACE( face )->memory; FT_Stream stream = FT_FACE( face )->stream; FNT_Font font = face->font; if ( !font ) return; if ( font->fnt_frame ) FT_FRAME_RELEASE( font->fnt_frame ); FT_FREE( font ); face->font = 0; }
static void cff_metrics_adjust( CFF_Face face ) { FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; var->metrics_adjust( FT_FACE( face ) ); }
static FT_Error cff_get_mm_var( CFF_Face face, FT_MM_Var* *master ) { FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; return mm->get_mm_var( FT_FACE( face ), master ); }
static FT_Error cff_set_instance( CFF_Face face, FT_UInt instance_index ) { FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; return mm->set_instance( FT_FACE( face ), instance_index ); }
static FT_Error cff_set_mm_blend( CFF_Face face, FT_UInt num_coords, FT_Fixed* coords ) { FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; return mm->set_mm_blend( FT_FACE( face ), num_coords, coords ); }
static FT_Error cff_get_mm_weightvector( CFF_Face face, FT_UInt* len, FT_Fixed* weightvector ) { FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; return mm->get_mm_weightvector( FT_FACE( face ), len, weightvector ); }
static FT_Error cff_get_var_design( CFF_Face face, FT_UInt num_coords, FT_Fixed* coords ) { FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; return mm->get_var_design( FT_FACE( face ), num_coords, coords ); }
static FT_Error cff_hadvance_adjust( CFF_Face face, FT_UInt gindex, FT_Int *avalue ) { FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; return var->hadvance_adjust( FT_FACE( face ), gindex, avalue ); }
tt_face_get_colr_layer( TT_Face face, FT_UInt base_glyph, FT_UInt *aglyph_index, FT_UInt *acolor_index, FT_LayerIterator* iterator ) { Colr* colr = (Colr*)face->colr; BaseGlyphRecord glyph_record; if ( !colr ) return 0; if ( !iterator->p ) { FT_ULong offset; /* first call to function */ iterator->layer = 0; if ( !find_base_glyph_record( colr->base_glyphs, colr->num_base_glyphs, base_glyph, &glyph_record ) ) return 0; if ( glyph_record.num_layers ) iterator->num_layers = glyph_record.num_layers; else return 0; offset = LAYER_SIZE * glyph_record.first_layer_index; if ( offset + LAYER_SIZE * glyph_record.num_layers > colr->table_size ) return 0; iterator->p = colr->layers + offset; } if ( iterator->layer >= iterator->num_layers ) return 0; *aglyph_index = FT_NEXT_USHORT( iterator->p ); *acolor_index = FT_NEXT_USHORT( iterator->p ); if ( *aglyph_index >= (FT_UInt)( FT_FACE( face )->num_glyphs ) || ( *acolor_index != 0xFFFF && *acolor_index >= face->palette_data.num_palette_entries ) ) return 0; iterator->layer++; return 1; }
tt_face_free_bdf_props( TT_Face face ) { TT_BDF bdf = &face->bdf; if ( bdf->loaded ) { FT_Stream stream = FT_FACE(face)->stream; if ( bdf->table != NULL ) FT_FRAME_RELEASE( bdf->table ); bdf->table_end = NULL; bdf->strings = NULL; bdf->strings_size = 0; } }
static FT_Error FNT_Size_Set_Pixels( FT_Size size ) { FNT_Face face = (FNT_Face)FT_SIZE_FACE( size ); FT_Face root = FT_FACE( face ); if ( size->metrics.y_ppem == root->available_sizes->height ) { FNT_Font font = face->font; size->metrics.ascender = font->header.ascent * 64; size->metrics.descender = ( font->header.pixel_height - font->header.ascent ) * 64; size->metrics.height = font->header.pixel_height * 64; size->metrics.max_advance = font->header.max_width * 64; return FNT_Err_Ok; } else return FNT_Err_Invalid_Pixel_Size; }
static FT_Error pcf_get_encodings( FT_Stream stream, PCF_Face face ) { FT_Error error = PCF_Err_Ok; FT_Memory memory = FT_FACE(face)->memory; FT_ULong format, size; int firstCol, lastCol; int firstRow, lastRow; int nencoding, encodingOffset; int i, j; PCF_Encoding tmpEncoding, encoding = 0; error = pcf_seek_to_table_type( stream, face->toc.tables, face->toc.count, PCF_BDF_ENCODINGS, &format, &size ); if ( error ) return error; error = FT_Stream_EnterFrame( stream, 14 ); if ( error ) return error; format = FT_GET_ULONG_LE(); if ( PCF_BYTE_ORDER( format ) == MSBFirst ) { firstCol = FT_GET_SHORT(); lastCol = FT_GET_SHORT(); firstRow = FT_GET_SHORT(); lastRow = FT_GET_SHORT(); face->defaultChar = FT_GET_SHORT(); } else { firstCol = FT_GET_SHORT_LE(); lastCol = FT_GET_SHORT_LE(); firstRow = FT_GET_SHORT_LE(); lastRow = FT_GET_SHORT_LE(); face->defaultChar = FT_GET_SHORT_LE(); } FT_Stream_ExitFrame( stream ); if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) return PCF_Err_Invalid_File_Format; FT_TRACE4(( "pdf_get_encodings:\n" )); FT_TRACE4(( " firstCol %d, lastCol %d, firstRow %d, lastRow %d\n", firstCol, lastCol, firstRow, lastRow )); nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 ); if ( FT_NEW_ARRAY( tmpEncoding, nencoding ) ) return PCF_Err_Out_Of_Memory; error = FT_Stream_EnterFrame( stream, 2 * nencoding ); if ( error ) goto Bail; for ( i = 0, j = 0 ; i < nencoding; i++ ) { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) encodingOffset = FT_GET_SHORT(); else encodingOffset = FT_GET_SHORT_LE(); if ( encodingOffset != -1 ) { tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) + firstRow ) * 256 ) + ( ( i % ( lastCol - firstCol + 1 ) ) + firstCol ); tmpEncoding[j].glyph = (FT_Short)encodingOffset; FT_TRACE5(( " code %d (0x%04X): idx %d\n", tmpEncoding[j].enc, tmpEncoding[j].enc, tmpEncoding[j].glyph )); j++; } } FT_Stream_ExitFrame( stream ); if ( FT_NEW_ARRAY( encoding, j ) ) goto Bail; for ( i = 0; i < j; i++ ) { encoding[i].enc = tmpEncoding[i].enc; encoding[i].glyph = tmpEncoding[i].glyph; } face->nencodings = j; face->encodings = encoding; FT_FREE( tmpEncoding ); return error; Bail: FT_FREE( encoding ); FT_FREE( tmpEncoding ); return error; }
static FT_Error pcf_get_metrics( FT_Stream stream, PCF_Face face ) { FT_Error error; FT_Memory memory = FT_FACE( face )->memory; FT_ULong format, size; PCF_Metric metrics = 0; FT_ULong nmetrics, i; error = pcf_seek_to_table_type( stream, face->toc.tables, face->toc.count, PCF_METRICS, &format, &size ); if ( error ) return error; if ( FT_READ_ULONG_LE( format ) ) goto Bail; if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) && !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) ) return FT_THROW( Invalid_File_Format ); if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) (void)FT_READ_ULONG( nmetrics ); else (void)FT_READ_ULONG_LE( nmetrics ); } else { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) (void)FT_READ_USHORT( nmetrics ); else (void)FT_READ_USHORT_LE( nmetrics ); } if ( error ) return FT_THROW( Invalid_File_Format ); face->nmetrics = nmetrics; if ( !nmetrics ) return FT_THROW( Invalid_Table ); FT_TRACE4(( "pcf_get_metrics:\n" )); FT_TRACE4(( " number of metrics: %d\n", nmetrics )); /* rough estimate */ if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) { if ( nmetrics > size / PCF_METRIC_SIZE ) return FT_THROW( Invalid_Table ); } else { if ( nmetrics > size / PCF_COMPRESSED_METRIC_SIZE ) return FT_THROW( Invalid_Table ); } if ( FT_NEW_ARRAY( face->metrics, nmetrics ) ) return FT_THROW( Out_Of_Memory ); metrics = face->metrics; for ( i = 0; i < nmetrics; i++, metrics++ ) { error = pcf_get_metric( stream, format, metrics ); metrics->bits = 0; FT_TRACE5(( " idx %d: width=%d, " "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n", i, metrics->characterWidth, metrics->leftSideBearing, metrics->rightSideBearing, metrics->ascent, metrics->descent, metrics->attributes )); if ( error ) break; /* sanity checks -- those values are used in `PCF_Glyph_Load' to */ /* compute a glyph's bitmap dimensions, thus setting them to zero in */ /* case of an error disables this particular glyph only */ if ( metrics->rightSideBearing < metrics->leftSideBearing || metrics->ascent + metrics->descent < 0 ) { metrics->characterWidth = 0; metrics->leftSideBearing = 0; metrics->rightSideBearing = 0; metrics->ascent = 0; metrics->descent = 0; FT_TRACE0(( "pcf_get_metrics:" " invalid metrics for glyph %d\n", i )); } } if ( error ) FT_FREE( face->metrics ); Bail: return error; }
static FT_Error pcf_get_encodings( FT_Stream stream, PCF_Face face ) { FT_Error error; FT_Memory memory = FT_FACE( face )->memory; FT_ULong format, size; int firstCol, lastCol; int firstRow, lastRow; int nencoding, encodingOffset; int i, j, k; PCF_Encoding encoding = NULL; error = pcf_seek_to_table_type( stream, face->toc.tables, face->toc.count, PCF_BDF_ENCODINGS, &format, &size ); if ( error ) return error; error = FT_Stream_EnterFrame( stream, 14 ); if ( error ) return error; format = FT_GET_ULONG_LE(); if ( PCF_BYTE_ORDER( format ) == MSBFirst ) { firstCol = FT_GET_SHORT(); lastCol = FT_GET_SHORT(); firstRow = FT_GET_SHORT(); lastRow = FT_GET_SHORT(); face->defaultChar = FT_GET_SHORT(); } else { firstCol = FT_GET_SHORT_LE(); lastCol = FT_GET_SHORT_LE(); firstRow = FT_GET_SHORT_LE(); lastRow = FT_GET_SHORT_LE(); face->defaultChar = FT_GET_SHORT_LE(); } FT_Stream_ExitFrame( stream ); if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) return FT_THROW( Invalid_File_Format ); /* sanity checks */ if ( firstCol < 0 || firstCol > lastCol || lastCol > 0xFF || firstRow < 0 || firstRow > lastRow || lastRow > 0xFF ) return FT_THROW( Invalid_Table ); FT_TRACE4(( "pdf_get_encodings:\n" )); FT_TRACE4(( " firstCol %d, lastCol %d, firstRow %d, lastRow %d\n", firstCol, lastCol, firstRow, lastRow )); nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 ); if ( FT_NEW_ARRAY( encoding, nencoding ) ) return FT_THROW( Out_Of_Memory ); error = FT_Stream_EnterFrame( stream, 2 * nencoding ); if ( error ) goto Bail; k = 0; for ( i = firstRow; i <= lastRow; i++ ) { for ( j = firstCol; j <= lastCol; j++ ) { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) encodingOffset = FT_GET_SHORT(); else encodingOffset = FT_GET_SHORT_LE(); if ( encodingOffset != -1 ) { encoding[k].enc = i * 256 + j; encoding[k].glyph = (FT_Short)encodingOffset; FT_TRACE5(( " code %d (0x%04X): idx %d\n", encoding[k].enc, encoding[k].enc, encoding[k].glyph )); k++; } } } FT_Stream_ExitFrame( stream ); if ( FT_RENEW_ARRAY( encoding, nencoding, k ) ) goto Bail; face->nencodings = k; face->encodings = encoding; return error; Bail: FT_FREE( encoding ); return error; }
static FT_Error pcf_read_TOC( FT_Stream stream, PCF_Face face ) { FT_Error error; PCF_Toc toc = &face->toc; PCF_Table tables; FT_Memory memory = FT_FACE( face )->memory; FT_UInt n; FT_ULong size; if ( FT_STREAM_SEEK( 0 ) || FT_STREAM_READ_FIELDS( pcf_toc_header, toc ) ) return FT_THROW( Cannot_Open_Resource ); if ( toc->version != PCF_FILE_VERSION || toc->count > FT_ARRAY_MAX( face->toc.tables ) || toc->count == 0 ) return FT_THROW( Invalid_File_Format ); if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) ) return FT_THROW( Out_Of_Memory ); tables = face->toc.tables; for ( n = 0; n < toc->count; n++ ) { if ( FT_STREAM_READ_FIELDS( pcf_table_header, tables ) ) goto Exit; tables++; } /* Sort tables and check for overlaps. Because they are almost */ /* always ordered already, an in-place bubble sort with simultaneous */ /* boundary checking seems appropriate. */ tables = face->toc.tables; for ( n = 0; n < toc->count - 1; n++ ) { FT_UInt i, have_change; have_change = 0; for ( i = 0; i < toc->count - 1 - n; i++ ) { PCF_TableRec tmp; if ( tables[i].offset > tables[i + 1].offset ) { tmp = tables[i]; tables[i] = tables[i + 1]; tables[i + 1] = tmp; have_change = 1; } if ( ( tables[i].size > tables[i + 1].offset ) || ( tables[i].offset > tables[i + 1].offset - tables[i].size ) ) { error = FT_THROW( Invalid_Offset ); goto Exit; } } if ( !have_change ) break; } /* * We now check whether the `size' and `offset' values are reasonable: * `offset' + `size' must not exceed the stream size. * * Note, however, that X11's `pcfWriteFont' routine (used by the * `bdftopcf' program to create PDF font files) has two special * features. * * - It always assigns the accelerator table a size of 100 bytes in the * TOC, regardless of its real size, which can vary between 34 and 72 * bytes. * * - Due to the way the routine is designed, it ships out the last font * table with its real size, ignoring the TOC's size value. Since * the TOC size values are always rounded up to a multiple of 4, the * difference can be up to three bytes for all tables except the * accelerator table, for which the difference can be as large as 66 * bytes. * */ tables = face->toc.tables; size = stream->size; for ( n = 0; n < toc->count - 1; n++ ) { /* we need two checks to avoid overflow */ if ( ( tables->size > size ) || ( tables->offset > size - tables->size ) ) { error = FT_THROW( Invalid_Table ); goto Exit; } tables++; } /* only check `tables->offset' for last table element ... */ if ( ( tables->offset > size ) ) { error = FT_THROW( Invalid_Table ); goto Exit; } /* ... and adjust `tables->size' to the real value if necessary */ if ( tables->size > size - tables->offset ) tables->size = size - tables->offset; #ifdef FT_DEBUG_LEVEL_TRACE { FT_UInt i, j; const char* name = "?"; FT_TRACE4(( "pcf_read_TOC:\n" )); FT_TRACE4(( " number of tables: %ld\n", face->toc.count )); tables = face->toc.tables; for ( i = 0; i < toc->count; i++ ) { for ( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] ); j++ ) if ( tables[i].type == (FT_UInt)( 1 << j ) ) name = tableNames[j]; FT_TRACE4(( " %d: type=%s, format=0x%X, " "size=%ld (0x%lX), offset=%ld (0x%lX)\n", i, name, tables[i].format, tables[i].size, tables[i].size, tables[i].offset, tables[i].offset )); } } #endif return FT_Err_Ok; Exit: FT_FREE( face->toc.tables ); return error; }
static FT_Error fnt_face_get_dll_fonts( FNT_Face face ) { FT_Error error; FT_Stream stream = FT_FACE(face)->stream; FT_Memory memory = FT_FACE(face)->memory; WinMZ_Header mz_header; face->fonts = 0; face->num_fonts = 0; /* does it begin with a MZ header? */ if ( FILE_Seek( 0 ) || READ_Fields( winmz_header_fields, &mz_header ) ) goto Exit; error = FNT_Err_Unknown_File_Format; if ( mz_header.magic == WINFNT_MZ_MAGIC ) { /* yes, now look for a NE header in the file */ WinNE_Header ne_header; if ( FILE_Seek( mz_header.lfanew ) || READ_Fields( winne_header_fields, &ne_header ) ) goto Exit; error = FNT_Err_Unknown_File_Format; if ( ne_header.magic == WINFNT_NE_MAGIC ) { /* good, now look in the resource table for each FNT resource */ FT_ULong res_offset = mz_header.lfanew + ne_header.resource_tab_offset; FT_UShort size_shift; FT_UShort font_count = 0; FT_ULong font_offset = 0; if ( FILE_Seek( res_offset ) || ACCESS_Frame( ne_header.rname_tab_offset - ne_header.resource_tab_offset ) ) goto Exit; size_shift = GET_UShortLE(); for (;;) { FT_UShort type_id, count; type_id = GET_UShortLE(); if ( !type_id ) break; count = GET_UShortLE(); if ( type_id == 0x8008 ) { font_count = count; font_offset = (FT_ULong)( FILE_Pos() + 4 + ( stream->cursor - stream->limit ) ); break; } stream->cursor += 4 + count * 12; } FORGET_Frame(); if ( !font_count || !font_offset ) { FT_TRACE2(( "this file doesn't contain any FNT resources!\n" )); error = FNT_Err_Unknown_File_Format; goto Exit; } if ( FILE_Seek( font_offset ) || ALLOC_ARRAY( face->fonts, font_count, FNT_Font ) ) goto Exit; face->num_fonts = font_count; if ( ACCESS_Frame( (FT_Long)font_count * 12 ) ) goto Exit; /* now read the offset and position of each FNT font */ { FNT_Font* cur = face->fonts; FNT_Font* limit = cur + font_count; for ( ; cur < limit; cur++ ) { cur->offset = (FT_ULong)GET_UShortLE() << size_shift; cur->fnt_size = (FT_ULong)GET_UShortLE() << size_shift; cur->size_shift = size_shift; stream->cursor += 8; } } FORGET_Frame(); /* finally, try to load each font there */ { FNT_Font* cur = face->fonts; FNT_Font* limit = cur + font_count; for ( ; cur < limit; cur++ ) { error = fnt_font_load( cur, stream ); if ( error ) goto Fail; } } } } Fail: if ( error ) fnt_face_done_fonts( face ); Exit: return error; }
static FT_Error FNT_Face_Init( FT_Stream stream, FNT_Face face, FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { FT_Error error; FT_Memory memory = FT_FACE_MEMORY( face ); FT_UNUSED( num_params ); FT_UNUSED( params ); FT_UNUSED( face_index ); /* try to load several fonts from a DLL */ error = fnt_face_get_dll_fonts( face ); if ( error ) { /* this didn't work, now try to load a single FNT font */ FNT_Font* font; if ( ALLOC( face->fonts, sizeof ( *face->fonts ) ) ) goto Exit; face->num_fonts = 1; font = face->fonts; font->offset = 0; font->fnt_size = stream->size; error = fnt_font_load( font, stream ); if ( error ) goto Fail; } /* all right, one or more fonts were loaded; we now need to */ /* fill the root FT_Face fields with relevant information */ { FT_Face root = FT_FACE( face ); FNT_Font* fonts = face->fonts; FNT_Font* limit = fonts + face->num_fonts; FNT_Font* cur; root->num_faces = 1; root->face_flags = FT_FACE_FLAG_FIXED_SIZES | FT_FACE_FLAG_HORIZONTAL; if ( fonts->header.avg_width == fonts->header.max_width ) root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; if ( fonts->header.italic ) root->style_flags |= FT_STYLE_FLAG_ITALIC; if ( fonts->header.weight >= 800 ) root->style_flags |= FT_STYLE_FLAG_BOLD; /* Setup the `fixed_sizes' array */ if ( ALLOC_ARRAY( root->available_sizes, face->num_fonts, FT_Bitmap_Size ) ) goto Fail; root->num_fixed_sizes = face->num_fonts; { FT_Bitmap_Size* size = root->available_sizes; for ( cur = fonts; cur < limit; cur++, size++ ) { size->width = cur->header.pixel_width; size->height = cur->header.pixel_height; } } /* Setup the `charmaps' array */ root->charmaps = &face->charmap_handle; root->num_charmaps = 1; face->charmap.encoding = ft_encoding_unicode; face->charmap.platform_id = 3; face->charmap.encoding_id = 1; face->charmap.face = root; face->charmap_handle = &face->charmap; root->charmap = face->charmap_handle; /* setup remaining flags */ root->num_glyphs = fonts->header.last_char - fonts->header.first_char + 1; root->family_name = (FT_String*)fonts->fnt_frame + fonts->header.face_name_offset; root->style_name = (char *)"Regular"; if ( root->style_flags & FT_STYLE_FLAG_BOLD ) { if ( root->style_flags & FT_STYLE_FLAG_ITALIC ) root->style_name = (char *)"Bold Italic"; else root->style_name = (char *)"Bold"; } else if ( root->style_flags & FT_STYLE_FLAG_ITALIC ) root->style_name = (char *)"Italic"; } Fail: if ( error ) FNT_Face_Done( face ); Exit: return error; }
pcf_load_font( FT_Stream stream, PCF_Face face ) { FT_Error error = PCF_Err_Ok; FT_Memory memory = FT_FACE(face)->memory; FT_Bool hasBDFAccelerators; error = pcf_read_TOC( stream, face ); if ( error ) goto Exit; error = pcf_get_properties( stream, face ); if ( error ) goto Exit; /* Use the old accelerators if no BDF accelerators are in the file. */ hasBDFAccelerators = pcf_has_table_type( face->toc.tables, face->toc.count, PCF_BDF_ACCELERATORS ); if ( !hasBDFAccelerators ) { error = pcf_get_accel( stream, face, PCF_ACCELERATORS ); if ( error ) goto Exit; } /* metrics */ error = pcf_get_metrics( stream, face ); if ( error ) goto Exit; /* bitmaps */ error = pcf_get_bitmaps( stream, face ); if ( error ) goto Exit; /* encodings */ error = pcf_get_encodings( stream, face ); if ( error ) goto Exit; /* BDF style accelerators (i.e. bounds based on encoded glyphs) */ if ( hasBDFAccelerators ) { error = pcf_get_accel( stream, face, PCF_BDF_ACCELERATORS ); if ( error ) goto Exit; } /* XXX: TO DO: inkmetrics and glyph_names are missing */ /* now construct the face object */ { FT_Face root = FT_FACE( face ); PCF_Property prop; root->num_faces = 1; root->face_index = 0; root->face_flags = FT_FACE_FLAG_FIXED_SIZES | FT_FACE_FLAG_HORIZONTAL | FT_FACE_FLAG_FAST_GLYPHS; if ( face->accel.constantWidth ) root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; if ( ( error = pcf_interpret_style( face ) ) != 0 ) goto Exit; prop = pcf_find_property( face, "FAMILY_NAME" ); if ( prop && prop->isString ) { if ( FT_STRDUP( root->family_name, prop->value.atom ) ) goto Exit; } else root->family_name = NULL; /* * Note: We shift all glyph indices by +1 since we must * respect the convention that glyph 0 always corresponds * to the `missing glyph'. * * This implies bumping the number of `available' glyphs by 1. */ root->num_glyphs = face->nmetrics + 1; root->num_fixed_sizes = 1; if ( FT_NEW_ARRAY( root->available_sizes, 1 ) ) goto Exit; { FT_Bitmap_Size* bsize = root->available_sizes; FT_Short resolution_x = 0, resolution_y = 0; FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) ); #if 0 bsize->height = face->accel.maxbounds.ascent << 6; #endif bsize->height = (FT_Short)( face->accel.fontAscent + face->accel.fontDescent ); prop = pcf_find_property( face, "AVERAGE_WIDTH" ); if ( prop ) bsize->width = (FT_Short)( ( prop->value.integer + 5 ) / 10 ); else bsize->width = (FT_Short)( bsize->height * 2/3 ); prop = pcf_find_property( face, "POINT_SIZE" ); if ( prop ) /* convert from 722.7 decipoints to 72 points per inch */ bsize->size = (FT_Pos)( ( prop->value.integer * 64 * 7200 + 36135L ) / 72270L ); prop = pcf_find_property( face, "PIXEL_SIZE" ); if ( prop ) bsize->y_ppem = (FT_Short)prop->value.integer << 6; prop = pcf_find_property( face, "RESOLUTION_X" ); if ( prop ) resolution_x = (FT_Short)prop->value.integer; prop = pcf_find_property( face, "RESOLUTION_Y" ); if ( prop ) resolution_y = (FT_Short)prop->value.integer; if ( bsize->y_ppem == 0 ) { bsize->y_ppem = bsize->size; if ( resolution_y ) bsize->y_ppem = bsize->y_ppem * resolution_y / 72; } if ( resolution_x && resolution_y ) bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y; else bsize->x_ppem = bsize->y_ppem; } /* set up charset */ { PCF_Property charset_registry = 0, charset_encoding = 0; charset_registry = pcf_find_property( face, "CHARSET_REGISTRY" ); charset_encoding = pcf_find_property( face, "CHARSET_ENCODING" ); if ( charset_registry && charset_registry->isString && charset_encoding && charset_encoding->isString ) { if ( FT_STRDUP( face->charset_encoding, charset_encoding->value.atom ) || FT_STRDUP( face->charset_registry, charset_registry->value.atom ) ) goto Exit; } } } Exit: if ( error ) { /* This is done to respect the behaviour of the original */ /* PCF font driver. */ error = PCF_Err_Invalid_File_Format; } return error; }
static FT_UInt cff_get_name_index( CFF_Face face, FT_String* glyph_name ) { CFF_Font cff; CFF_Charset charset; FT_Service_PsCMaps psnames; FT_String* name; FT_UShort sid; FT_UInt i; cff = (CFF_FontRec *)face->extra.data; charset = &cff->charset; /* CFF2 table does not have glyph names; */ /* we need to use `post' table method */ if ( cff->version_major == 2 ) { FT_Library library = FT_FACE_LIBRARY( face ); FT_Module sfnt_module = FT_Get_Module( library, "sfnt" ); FT_Service_GlyphDict service = (FT_Service_GlyphDict)ft_module_get_service( sfnt_module, FT_SERVICE_ID_GLYPH_DICT, 0 ); if ( service && service->name_index ) return service->name_index( FT_FACE( face ), glyph_name ); else { FT_ERROR(( "cff_get_name_index:" " cannot get glyph index from a CFF2 font\n" " " " without the `psnames' module\n" )); return 0; } } FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); if ( !psnames ) return 0; for ( i = 0; i < cff->num_glyphs; i++ ) { sid = charset->sids[i]; if ( sid > 390 ) name = cff_index_get_string( cff, sid - 391 ); else name = (FT_String *)psnames->adobe_std_strings( sid ); if ( !name ) continue; if ( !ft_strcmp( glyph_name, name ) ) return i; } return 0; }
static FT_Error cff_get_glyph_name( CFF_Face face, FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max ) { CFF_Font font = (CFF_Font)face->extra.data; FT_String* gname; FT_UShort sid; FT_Error error; /* CFF2 table does not have glyph names; */ /* we need to use `post' table method */ if ( font->version_major == 2 ) { FT_Library library = FT_FACE_LIBRARY( face ); FT_Module sfnt_module = FT_Get_Module( library, "sfnt" ); FT_Service_GlyphDict service = (FT_Service_GlyphDict)ft_module_get_service( sfnt_module, FT_SERVICE_ID_GLYPH_DICT, 0 ); if ( service && service->get_name ) return service->get_name( FT_FACE( face ), glyph_index, buffer, buffer_max ); else { FT_ERROR(( "cff_get_glyph_name:" " cannot get glyph name from a CFF2 font\n" " " " without the `psnames' module\n" )); error = FT_THROW( Missing_Module ); goto Exit; } } if ( !font->psnames ) { FT_ERROR(( "cff_get_glyph_name:" " cannot get glyph name from CFF & CEF fonts\n" " " " without the `psnames' module\n" )); error = FT_THROW( Missing_Module ); goto Exit; } /* first, locate the sid in the charset table */ sid = font->charset.sids[glyph_index]; /* now, lookup the name itself */ gname = cff_index_get_sid_string( font, sid ); if ( gname ) FT_STRCPYN( buffer, gname, buffer_max ); error = FT_Err_Ok; Exit: return error; }
static FT_Error pcf_get_properties( FT_Stream stream, PCF_Face face ) { PCF_ParseProperty props = 0; PCF_Property properties; FT_UInt nprops, i; FT_ULong format, size; FT_Error error; FT_Memory memory = FT_FACE(face)->memory; FT_ULong string_size; FT_String* strings = 0; error = pcf_seek_to_table_type( stream, face->toc.tables, face->toc.count, PCF_PROPERTIES, &format, &size ); if ( error ) goto Bail; if ( FT_READ_ULONG_LE( format ) ) goto Bail; FT_TRACE4(( "pcf_get_properties:\n" )); FT_TRACE4(( " format = %ld\n", format )); if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) goto Bail; if ( PCF_BYTE_ORDER( format ) == MSBFirst ) (void)FT_READ_ULONG( nprops ); else (void)FT_READ_ULONG_LE( nprops ); if ( error ) goto Bail; FT_TRACE4(( " nprop = %d\n", nprops )); /* rough estimate */ if ( nprops > size / PCF_PROPERTY_SIZE ) { error = PCF_Err_Invalid_Table; goto Bail; } face->nprops = nprops; if ( FT_NEW_ARRAY( props, nprops ) ) goto Bail; for ( i = 0; i < nprops; i++ ) { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) { if ( FT_STREAM_READ_FIELDS( pcf_property_msb_header, props + i ) ) goto Bail; } else { if ( FT_STREAM_READ_FIELDS( pcf_property_header, props + i ) ) goto Bail; } } /* pad the property array */ /* */ /* clever here - nprops is the same as the number of odd-units read, */ /* as only isStringProp are odd length (Keith Packard) */ /* */ if ( nprops & 3 ) { i = 4 - ( nprops & 3 ); if ( FT_STREAM_SKIP( i ) ) { error = PCF_Err_Invalid_Stream_Skip; goto Bail; } } if ( PCF_BYTE_ORDER( format ) == MSBFirst ) (void)FT_READ_ULONG( string_size ); else (void)FT_READ_ULONG_LE( string_size ); if ( error ) goto Bail; FT_TRACE4(( " string_size = %ld\n", string_size )); /* rough estimate */ if ( string_size > size - nprops * PCF_PROPERTY_SIZE ) { error = PCF_Err_Invalid_Table; goto Bail; } if ( FT_NEW_ARRAY( strings, string_size ) ) goto Bail; error = FT_Stream_Read( stream, (FT_Byte*)strings, string_size ); if ( error ) goto Bail; if ( FT_NEW_ARRAY( properties, nprops ) ) goto Bail; face->properties = properties; for ( i = 0; i < nprops; i++ ) { FT_Long name_offset = props[i].name; if ( ( name_offset < 0 ) || ( (FT_ULong)name_offset > string_size ) ) { error = PCF_Err_Invalid_Offset; goto Bail; } if ( FT_STRDUP( properties[i].name, strings + name_offset ) ) goto Bail; FT_TRACE4(( " %s:", properties[i].name )); properties[i].isString = props[i].isString; if ( props[i].isString ) { FT_Long value_offset = props[i].value; if ( ( value_offset < 0 ) || ( (FT_ULong)value_offset > string_size ) ) { error = PCF_Err_Invalid_Offset; goto Bail; } if ( FT_STRDUP( properties[i].value.atom, strings + value_offset ) ) goto Bail; FT_TRACE4(( " `%s'\n", properties[i].value.atom )); } else { properties[i].value.integer = props[i].value; FT_TRACE4(( " %d\n", properties[i].value.integer )); } } error = PCF_Err_Ok; Bail: FT_FREE( props ); FT_FREE( strings ); return error; }
pfr_face_init( FT_Stream stream, PFR_Face face, FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { FT_Error error; FT_UNUSED( num_params ); FT_UNUSED( params ); /* load the header and check it */ error = pfr_header_load( &face->header, stream ); if ( error ) goto Exit; if ( !pfr_header_check( &face->header ) ) { FT_TRACE4(( "pfr_face_init: not a valid PFR font\n" )); error = PFR_Err_Unknown_File_Format; goto Exit; } /* check face index */ { FT_UInt num_faces; error = pfr_log_font_count( stream, face->header.log_dir_offset, &num_faces ); if ( error ) goto Exit; face->root.num_faces = num_faces; } if ( face_index < 0 ) goto Exit; if ( face_index >= face->root.num_faces ) { FT_ERROR(( "pfr_face_init: invalid face index\n" )); error = PFR_Err_Invalid_Argument; goto Exit; } /* load the face */ error = pfr_log_font_load( &face->log_font, stream, face_index, face->header.log_dir_offset, FT_BOOL( face->header.phy_font_max_size_high != 0 ) ); if ( error ) goto Exit; /* now load the physical font descriptor */ error = pfr_phy_font_load( &face->phy_font, stream, face->log_font.phys_offset, face->log_font.phys_size ); if ( error ) goto Exit; /* now, set-up all root face fields */ { FT_Face root = FT_FACE( face ); PFR_PhyFont phy_font = &face->phy_font; root->face_index = face_index; root->num_glyphs = phy_font->num_chars; root->face_flags = FT_FACE_FLAG_SCALABLE; if ( (phy_font->flags & PFR_PHY_PROPORTIONAL) == 0 ) root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; if ( phy_font->flags & PFR_PHY_VERTICAL ) root->face_flags |= FT_FACE_FLAG_VERTICAL; else root->face_flags |= FT_FACE_FLAG_HORIZONTAL; if ( phy_font->num_strikes > 0 ) root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; if ( phy_font->num_kern_pairs > 0 ) root->face_flags |= FT_FACE_FLAG_KERNING; root->family_name = phy_font->font_id; root->style_name = NULL; /* no style name in font file */ root->num_fixed_sizes = 0; root->available_sizes = 0; root->bbox = phy_font->bbox; root->units_per_EM = (FT_UShort)phy_font->outline_resolution; root->ascender = (FT_Short) phy_font->bbox.yMax; root->descender = (FT_Short) phy_font->bbox.yMin; root->height = (FT_Short) ( ( ( root->ascender - root->descender ) * 12 ) / 10 ); /* now compute maximum advance width */ if ( ( phy_font->flags & PFR_PHY_PROPORTIONAL ) == 0 ) root->max_advance_width = (FT_Short)phy_font->standard_advance; else { FT_Int max = 0; FT_UInt count = phy_font->num_chars; PFR_Char gchar = phy_font->chars; for ( ; count > 0; count--, gchar++ ) { if ( max < gchar->advance ) max = gchar->advance; } root->max_advance_width = (FT_Short)max; } root->max_advance_height = root->height; root->underline_position = (FT_Short)( - root->units_per_EM / 10 ); root->underline_thickness = (FT_Short)( root->units_per_EM / 30 ); /* create charmap */ { FT_CharMapRec charmap; charmap.face = root; charmap.platform_id = 3; charmap.encoding_id = 1; charmap.encoding = FT_ENCODING_UNICODE; FT_CMap_New( &pfr_cmap_class_rec, NULL, &charmap, NULL ); #if 0 /* Select default charmap */ if (root->num_charmaps) root->charmap = root->charmaps[0]; #endif } /* check whether we've loaded any kerning pairs */ if ( phy_font->num_kern_pairs ) root->face_flags |= FT_FACE_FLAG_KERNING; } Exit: return error; }
static FT_Error pcf_get_bitmaps( FT_Stream stream, PCF_Face face ) { FT_Error error = PCF_Err_Ok; FT_Memory memory = FT_FACE(face)->memory; FT_Long* offsets; FT_Long bitmapSizes[GLYPHPADOPTIONS]; FT_ULong format, size; int nbitmaps, i, sizebitmaps = 0; error = pcf_seek_to_table_type( stream, face->toc.tables, face->toc.count, PCF_BITMAPS, &format, &size ); if ( error ) return error; error = FT_Stream_EnterFrame( stream, 8 ); if ( error ) return error; format = FT_GET_ULONG_LE(); if ( PCF_BYTE_ORDER( format ) == MSBFirst ) nbitmaps = FT_GET_ULONG(); else nbitmaps = FT_GET_ULONG_LE(); FT_Stream_ExitFrame( stream ); if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) return PCF_Err_Invalid_File_Format; FT_TRACE4(( "pcf_get_bitmaps:\n" )); FT_TRACE4(( " number of bitmaps: %d\n", nbitmaps )); if ( nbitmaps != face->nmetrics ) return PCF_Err_Invalid_File_Format; if ( FT_NEW_ARRAY( offsets, nbitmaps ) ) return error; for ( i = 0; i < nbitmaps; i++ ) { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) (void)FT_READ_LONG( offsets[i] ); else (void)FT_READ_LONG_LE( offsets[i] ); FT_TRACE5(( " bitmap %d: offset %ld (0x%lX)\n", i, offsets[i], offsets[i] )); } if ( error ) goto Bail; for ( i = 0; i < GLYPHPADOPTIONS; i++ ) { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) (void)FT_READ_LONG( bitmapSizes[i] ); else (void)FT_READ_LONG_LE( bitmapSizes[i] ); if ( error ) goto Bail; sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )]; FT_TRACE4(( " padding %d implies a size of %ld\n", i, bitmapSizes[i] )); } FT_TRACE4(( " %d bitmaps, padding index %ld\n", nbitmaps, PCF_GLYPH_PAD_INDEX( format ) )); FT_TRACE4(( " bitmap size = %d\n", sizebitmaps )); FT_UNUSED( sizebitmaps ); /* only used for debugging */ for ( i = 0; i < nbitmaps; i++ ) { /* rough estimate */ if ( ( offsets[i] < 0 ) || ( (FT_ULong)offsets[i] > size ) ) { FT_ERROR(( "pcf_get_bitmaps:")); FT_ERROR(( " invalid offset to bitmap data of glyph %d\n", i )); } else face->metrics[i].bits = stream->pos + offsets[i]; } face->bitmapsFormat = format; Bail: FT_FREE( offsets ); return error; }
static FT_Error pcf_get_metrics( FT_Stream stream, PCF_Face face ) { FT_Error error = PCF_Err_Ok; FT_Memory memory = FT_FACE(face)->memory; FT_ULong format, size; PCF_Metric metrics = 0; FT_ULong nmetrics, i; error = pcf_seek_to_table_type( stream, face->toc.tables, face->toc.count, PCF_METRICS, &format, &size ); if ( error ) return error; if ( FT_READ_ULONG_LE( format ) ) goto Bail; if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) && !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) ) return PCF_Err_Invalid_File_Format; if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) (void)FT_READ_ULONG( nmetrics ); else (void)FT_READ_ULONG_LE( nmetrics ); } else { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) (void)FT_READ_USHORT( nmetrics ); else (void)FT_READ_USHORT_LE( nmetrics ); } if ( error ) return PCF_Err_Invalid_File_Format; face->nmetrics = nmetrics; FT_TRACE4(( "pcf_get_metrics:\n" )); FT_TRACE4(( " number of metrics: %d\n", nmetrics )); /* rough estimate */ if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) { if ( nmetrics > size / PCF_METRIC_SIZE ) return PCF_Err_Invalid_Table; } else { if ( nmetrics > size / PCF_COMPRESSED_METRIC_SIZE ) return PCF_Err_Invalid_Table; } if ( FT_NEW_ARRAY( face->metrics, nmetrics ) ) return PCF_Err_Out_Of_Memory; metrics = face->metrics; for ( i = 0; i < nmetrics; i++ ) { error = pcf_get_metric( stream, format, metrics + i ); metrics[i].bits = 0; FT_TRACE5(( " idx %d: width=%d, " "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n", i, ( metrics + i )->characterWidth, ( metrics + i )->leftSideBearing, ( metrics + i )->rightSideBearing, ( metrics + i )->ascent, ( metrics + i )->descent, ( metrics + i )->attributes )); if ( error ) break; } if ( error ) FT_FREE( face->metrics ); Bail: return error; }
tt_face_find_bdf_prop( TT_Face face, const char* property_name, BDF_PropertyRec *aprop ) { TT_BDF bdf = &face->bdf; FT_Size size = FT_FACE(face)->size; FT_Error error = FT_Err_Ok; FT_Byte* p; FT_UInt count; FT_Byte* strike; FT_Offset property_len; aprop->type = BDF_PROPERTY_TYPE_NONE; if ( bdf->loaded == 0 ) { error = tt_face_load_bdf_props( face, FT_FACE( face )->stream ); if ( error ) goto Exit; } count = bdf->num_strikes; p = bdf->table + 8; strike = p + 4 * count; error = FT_ERR( Invalid_Argument ); if ( size == NULL || property_name == NULL ) goto Exit; property_len = ft_strlen( property_name ); if ( property_len == 0 ) goto Exit; for ( ; count > 0; count-- ) { FT_UInt _ppem = FT_NEXT_USHORT( p ); FT_UInt _count = FT_NEXT_USHORT( p ); if ( _ppem == size->metrics.y_ppem ) { count = _count; goto FoundStrike; } strike += 10 * _count; } goto Exit; FoundStrike: p = strike; for ( ; count > 0; count-- ) { FT_UInt type = FT_PEEK_USHORT( p + 4 ); if ( ( type & 0x10 ) != 0 ) { FT_UInt32 name_offset = FT_PEEK_ULONG( p ); FT_UInt32 value = FT_PEEK_ULONG( p + 6 ); /* be a bit paranoid for invalid entries here */ if ( name_offset < bdf->strings_size && property_len < bdf->strings_size - name_offset && ft_strncmp( property_name, (const char*)bdf->strings + name_offset, bdf->strings_size - name_offset ) == 0 ) { switch ( type & 0x0F ) { case 0x00: /* string */ case 0x01: /* atoms */ /* check that the content is really 0-terminated */ if ( value < bdf->strings_size && ft_memchr( bdf->strings + value, 0, bdf->strings_size ) ) { aprop->type = BDF_PROPERTY_TYPE_ATOM; aprop->u.atom = (const char*)bdf->strings + value; error = FT_Err_Ok; goto Exit; } break; case 0x02: aprop->type = BDF_PROPERTY_TYPE_INTEGER; aprop->u.integer = (FT_Int32)value; error = FT_Err_Ok; goto Exit; case 0x03: aprop->type = BDF_PROPERTY_TYPE_CARDINAL; aprop->u.cardinal = value; error = FT_Err_Ok; goto Exit; default: ; } } } p += 10; } Exit: return error; }
static FT_Error pcf_read_TOC( FT_Stream stream, PCF_Face face ) { FT_Error error; PCF_Toc toc = &face->toc; PCF_Table tables; FT_Memory memory = FT_FACE(face)->memory; FT_UInt n; if ( FT_STREAM_SEEK ( 0 ) || FT_STREAM_READ_FIELDS ( pcf_toc_header, toc ) ) return PCF_Err_Cannot_Open_Resource; if ( toc->version != PCF_FILE_VERSION || toc->count > FT_ARRAY_MAX( face->toc.tables ) || toc->count == 0 ) return PCF_Err_Invalid_File_Format; if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) ) return PCF_Err_Out_Of_Memory; tables = face->toc.tables; for ( n = 0; n < toc->count; n++ ) { if ( FT_STREAM_READ_FIELDS( pcf_table_header, tables ) ) goto Exit; tables++; } /* Sort tables and check for overlaps. Because they are almost */ /* always ordered already, an in-place bubble sort with simultaneous */ /* boundary checking seems appropriate. */ tables = face->toc.tables; for ( n = 0; n < toc->count - 1; n++ ) { FT_UInt i, have_change; have_change = 0; for ( i = 0; i < toc->count - 1 - n; i++ ) { PCF_TableRec tmp; if ( tables[i].offset > tables[i + 1].offset ) { tmp = tables[i]; tables[i] = tables[i + 1]; tables[i + 1] = tmp; have_change = 1; } if ( ( tables[i].size > tables[i + 1].offset ) || ( tables[i].offset > tables[i + 1].offset - tables[i].size ) ) return PCF_Err_Invalid_Offset; } if ( !have_change ) break; } #ifdef FT_DEBUG_LEVEL_TRACE { FT_UInt i, j; const char* name = "?"; FT_TRACE4(( "pcf_read_TOC:\n" )); FT_TRACE4(( " number of tables: %ld\n", face->toc.count )); tables = face->toc.tables; for ( i = 0; i < toc->count; i++ ) { for ( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] ); j++ ) if ( tables[i].type == (FT_UInt)( 1 << j ) ) name = tableNames[j]; FT_TRACE4(( " %d: type=%s, format=0x%X, " "size=%ld (0x%lX), offset=%ld (0x%lX)\n", i, name, tables[i].format, tables[i].size, tables[i].size, tables[i].offset, tables[i].offset )); } } #endif return PCF_Err_Ok; Exit: FT_FREE( face->toc.tables ); return error; }
static FT_Error T1_Parse_Glyph_And_Get_Char_String( T1_Decoder decoder, FT_UInt glyph_index, FT_Data* char_string, FT_Bool* force_scaling ) { T1_Face face = (T1_Face)decoder->builder.face; T1_Font type1 = &face->type1; FT_Error error = FT_Err_Ok; PSAux_Service psaux = (PSAux_Service)face->psaux; const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs; PS_Decoder psdecoder; #ifdef FT_CONFIG_OPTION_INCREMENTAL FT_Incremental_InterfaceRec *inc = face->root.internal->incremental_interface; #endif #ifdef T1_CONFIG_OPTION_OLD_ENGINE PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( face ); #endif decoder->font_matrix = type1->font_matrix; decoder->font_offset = type1->font_offset; #ifdef FT_CONFIG_OPTION_INCREMENTAL /* For incremental fonts get the character data using the */ /* callback function. */ if ( inc ) error = inc->funcs->get_glyph_data( inc->object, glyph_index, char_string ); else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ /* For ordinary fonts get the character data stored in the face record. */ { char_string->pointer = type1->charstrings[glyph_index]; char_string->length = (FT_Int)type1->charstrings_len[glyph_index]; } if ( !error ) { /* choose which renderer to use */ #ifdef T1_CONFIG_OPTION_OLD_ENGINE if ( driver->hinting_engine == FT_HINTING_FREETYPE || decoder->builder.metrics_only ) error = decoder_funcs->parse_charstrings_old( decoder, (FT_Byte*)char_string->pointer, (FT_UInt)char_string->length ); #else if ( decoder->builder.metrics_only ) error = decoder_funcs->parse_metrics( decoder, (FT_Byte*)char_string->pointer, (FT_UInt)char_string->length ); #endif else { CFF_SubFontRec subfont; psaux->ps_decoder_init( &psdecoder, decoder, TRUE ); psaux->t1_make_subfont( FT_FACE( face ), &face->type1.private_dict, &subfont ); psdecoder.current_subfont = &subfont; error = decoder_funcs->parse_charstrings( &psdecoder, (FT_Byte*)char_string->pointer, (FT_ULong)char_string->length ); /* Adobe's engine uses 16.16 numbers everywhere; */ /* as a consequence, glyphs larger than 2000ppem get rejected */ if ( FT_ERR_EQ( error, Glyph_Too_Big ) ) { /* this time, we retry unhinted and scale up the glyph later on */ /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */ /* 0x400 for both `x_scale' and `y_scale' in this case) */ ((T1_GlyphSlot)decoder->builder.glyph)->hint = FALSE; *force_scaling = TRUE; error = decoder_funcs->parse_charstrings( &psdecoder, (FT_Byte*)char_string->pointer, (FT_ULong)char_string->length ); } } } #ifdef FT_CONFIG_OPTION_INCREMENTAL /* Incremental fonts can optionally override the metrics. */ if ( !error && inc && inc->funcs->get_glyph_metrics ) { FT_Incremental_MetricsRec metrics; metrics.bearing_x = FIXED_TO_INT( decoder->builder.left_bearing.x ); metrics.bearing_y = 0; metrics.advance = FIXED_TO_INT( decoder->builder.advance.x ); metrics.advance_v = FIXED_TO_INT( decoder->builder.advance.y ); error = inc->funcs->get_glyph_metrics( inc->object, glyph_index, FALSE, &metrics ); decoder->builder.left_bearing.x = INT_TO_FIXED( metrics.bearing_x ); decoder->builder.advance.x = INT_TO_FIXED( metrics.advance ); decoder->builder.advance.y = INT_TO_FIXED( metrics.advance_v ); } #endif /* FT_CONFIG_OPTION_INCREMENTAL */ return error; }
static FT_Error pcf_interpret_style( PCF_Face pcf ) { FT_Error error = PCF_Err_Ok; FT_Face face = FT_FACE( pcf ); FT_Memory memory = face->memory; PCF_Property prop; int nn, len; char* strings[4] = { NULL, NULL, NULL, NULL }; int lengths[4]; face->style_flags = 0; prop = pcf_find_property( pcf, "SLANT" ); if ( prop && prop->isString && ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' || *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) ) { face->style_flags |= FT_STYLE_FLAG_ITALIC; strings[2] = ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ) ? (char *)"Oblique" : (char *)"Italic"; } prop = pcf_find_property( pcf, "WEIGHT_NAME" ); if ( prop && prop->isString && ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) ) { face->style_flags |= FT_STYLE_FLAG_BOLD; strings[1] = (char *)"Bold"; } prop = pcf_find_property( pcf, "SETWIDTH_NAME" ); if ( prop && prop->isString && *(prop->value.atom) && !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) ) strings[3] = (char *)(prop->value.atom); prop = pcf_find_property( pcf, "ADD_STYLE_NAME" ); if ( prop && prop->isString && *(prop->value.atom) && !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) ) strings[0] = (char *)(prop->value.atom); for ( len = 0, nn = 0; nn < 4; nn++ ) { lengths[nn] = 0; if ( strings[nn] ) { lengths[nn] = ft_strlen( strings[nn] ); len += lengths[nn] + 1; } } if ( len == 0 ) { strings[0] = (char *)"Regular"; lengths[0] = ft_strlen( strings[0] ); len = lengths[0] + 1; } { char* s; if ( FT_ALLOC( face->style_name, len ) ) return error; s = face->style_name; for ( nn = 0; nn < 4; nn++ ) { char* src = strings[nn]; len = lengths[nn]; if ( src == NULL ) continue; /* separate elements with a space */ if ( s != face->style_name ) *s++ = ' '; ft_memcpy( s, src, len ); /* need to convert spaces to dashes for */ /* add_style_name and setwidth_name */ if ( nn == 0 || nn == 3 ) { int mm; for ( mm = 0; mm < len; mm++ ) if (s[mm] == ' ') s[mm] = '-'; } s += len; } *s = 0; } return error; }