📄 ftifi.c
字号:
/* *//* Wake_FontFile : *//* *//* awakes a font file, and reloads important data from disk. *//* */static int Wake_FontFile( PFontFile cur_file ){ static TT_Face face; static TT_Glyph glyph; static TT_CharMap cmap; static TT_Face_Properties props; static PFontFace cur_face; ULONG encoding, i; if (cur_file->flags & FL_FLAG_LIVE_FACE) ERRRET(-1); /* already awoken !! */ /* OK, try to activate the FreeType objects */ error = TT_Open_Face(engine, cur_file->filename, &face); if (error) { COPY( "Error while opening " ); CAT( cur_file->filename ); CAT( ", error code = " ); CATI( error ); CAT( "\r\n" ); WRITE; return -1; /* error, can't open file */ /* XXX : should set error condition here! */ } /* Create a glyph container for it */ error = TT_New_Glyph( face, &glyph ); if (error) { COPY( "Error while creating container for " ); CAT( cur_file->filename ); CAT( ", error code = " ); CATI( error ); CAT( "\r\n" ); WRITE; goto Fail_Face; } /* now get suitable charmap for this font */ encoding = GetCharmap(face); error = TT_Get_CharMap(face, encoding & 0xFFFF, &cmap); if (error) { COPY( "Error: No char map in " ); CAT( cur_file->filename ); CAT( "\r\n" ); WRITE; goto Fail_Glyph; } /* Get face properties. Necessary to find out number of fonts for TTCs */ TT_Get_Face_Properties(face, &props); /* all right, now remove the face from the sleep list */ if (List_Remove( &idleFiles, cur_file->element )) ERET1( Fail_Glyph ); /* add it to the live list */ if (List_Insert( &liveFiles, cur_file->element )) ERET1( Fail_Glyph ); /* If the file is a TTC, the first face is now opened successfully. */ cur_file->numFaces = props.num_Faces; /* Now allocate memory for face data (one struct for each face in TTC). */ if (cur_file->faces == NULL) { if (ALLOC(cur_face, sizeof(TFontFace) * cur_file->numFaces)) ERET1( Fail_Glyph ); cur_file->faces = cur_face; } else cur_face = cur_file->faces; cur_face->face = face; /* possibly first face in a TTC */ cur_face->glyph = glyph; cur_face->charMap = cmap; cur_file->flags |= FL_FLAG_LIVE_FACE; if (!(cur_file->flags & FL_FLAG_ALREADY_USED)) { cur_face->charMode = encoding >> 16; /* Unicode, Symbol, ... */ cur_face->em_size = props.header->Units_Per_EM; /* if a face contains over 1024 glyphs, assume it's a DBCS font - */ /* VERY probable */ TT_Get_Face_Properties(cur_face->face, &props); if (props.num_Glyphs > 1024) { cur_file->flags |= FL_FLAG_DBCS_FILE; cur_face->flags |= FC_FLAG_DBCS_FACE; } cur_face->widths = NULL; cur_face->kernIndices = NULL; } /* load kerning directory, if any */ error = TT_Get_Kerning_Directory(face, &(cur_face->directory)); if (error) cur_face->directory.nTables = 0; /* indicates no kerning in font */ TT_Flush_Face(face); /* this is important ! */ /* open remaining faces if this font is a TTC */ for (i = 1; i < cur_file->numFaces; i++) { error = TT_Open_Collection(engine, cur_file->filename, i, &face); if (error) return -1; /* TODO: handle bad TTCs more tolerantly */ error = TT_New_Glyph( face, &glyph ); if (error) ERET1(Fail_Face); encoding = GetCharmap(face); error = TT_Get_CharMap(face, encoding & 0xFFFF, &cmap); if (error) ERET1(Fail_Glyph); cur_face = &(cur_file->faces[i]); cur_face->face = face; cur_face->glyph = glyph; cur_face->charMap = cmap; if (!(cur_file->flags & FL_FLAG_ALREADY_USED)) { cur_face->em_size = props.header->Units_Per_EM; cur_face->charMode = encoding >> 16; /* 0 - Unicode; 1 - Symbol */ if (cur_file->flags & FL_FLAG_DBCS_FILE) cur_face->flags |= FC_FLAG_DBCS_FACE; cur_face->widths = NULL; cur_face->kernIndices = NULL; } /* load kerning directory, if any */ error = TT_Get_Kerning_Directory(face, &(cur_face->directory)); if (error) cur_face->directory.nTables = 0; /* indicates no kerning in font */ } cur_file->flags |= FL_FLAG_ALREADY_USED; /* indicates some fields need no re-init */ error = TT_Flush_Face(face); /* this is important ! */ if (error) { COPY("Error flushing face\r\n"); WRITE; } return 0; /* everything is in order, return 0 == success */Fail_Glyph: /* This line isn't really necessary, because the glyph container */ /* would be destroyed by the following TT_Close_Face anyway. We */ /* however use it for the sake of orthodoxy */ TT_Done_Glyph( glyph );Fail_Face: TT_Close_Face(face); /* note that in case of error (e.g. out of memory), the face stays */ /* on the sleeping list */ return -1;}/****************************************************************************//* *//* Done_FontFile : *//* *//* destroys a given font file object. This will also destroy all of its *//* live child font sizes (which in turn will destroy the glyph caches). *//* This is done for all faces if the file is a collection. *//* *//* WARNING : The font face must be removed from its list by the caller *//* before this function is called. *//* */static void Done_FontFile( PFontFile *file ){ static PListElement element; static PListElement next; ULONG i;#if 0 /* this part isn't really used and maybe it never will */ /* destroy its font sizes */ element = (*face)->sizes.head; while (element) { next = element->next; /* XXX : right now, we simply free the font size object, */ /* because the instance is destroyed automatically */ /* by FreeType. */ FREE( element->data ); /* Done_FontSize( (PFontSize)element->data ); - later */ Done_Element( element ); element = next; }#endif /* now discard the font face itself */ if ((*file)->flags & FL_FLAG_LIVE_FACE) { for (i = 0; i < (*file)->numFaces; i++) { TT_Done_Glyph( (*file)->faces[i].glyph ); TT_Close_Face( (*file)->faces[i].face ); if ((*file)->faces[i].widths) FREE((*file)->faces[i].widths); if ((*file)->faces[i].kernIndices) FREE((*file)->faces[i].kernIndices); } } FREE( (*file)->faces ); FREE( *file );}/****************************************************************************//* *//* New_FontFile : *//* *//* return the address of the TFontFile corresponding to a given *//* HFF. Note that in our implementation, we could simply to a *//* typecast like '(PFontFile)hff'. However, for safety reasons, we *//* look up the handle in the list. *//* */static PFontFile New_FontFile( char* file_name ){ static PListElement element; static PFontFile cur_file; static TT_CharMap cmap; /* first, check if it's already open - in the live list */ for ( element = liveFiles.head; element; element = element->next ) { cur_file = (PFontFile)element->data; if (strcmp( cur_file->filename, file_name ) == 0) goto Exit_Same; } /* check in the idle list */ for ( element = idleFiles.head; element; element = element->next ) { cur_file = (PFontFile)element->data; if (strcmp( cur_file->filename, file_name ) == 0) goto Exit_Same; } /* OK, this file isn't opened yet. Create a new font face object */ /* then try to wake it up. This will fail if the file can't be found */ /* or if we lack memory.. */ element = New_Element(); if (!element) ERRRET(NULL); if ( ALLOC( cur_file, sizeof(TFontFile) ) ) ERET1( Fail_Element ); element->data = cur_file; element->key = (long)cur_file; /* use the HFF as cur key */ cur_file->element = element; cur_file->ref_count = 1; cur_file->hff = (HFF)cur_file; strcpy( cur_file->filename, file_name); cur_file->flags = 0; cur_file->faces = NULL;#if 0 /* not used */ cur_face->sizes.head = NULL; cur_face->sizes.tail = NULL; cur_face->sizes.count= 0;#endif /* add new font face to sleep list */ if (List_Insert( &idleFiles, element )) ERET1( Fail_File ); /* Make enough room in the live list */ if ( liveFiles.count >= max_open_files) { COPY( "rolling...\n" ); WRITE; if (Sleep_FontFile( (PFontFile)(liveFiles.tail->data) )) ERET1( Fail_File ); } /* wake new font file */ if ( Wake_FontFile( cur_file ) ) { COPY( "could not open/wake " ); CAT( file_name ); CAT( "\r\n" ); WRITE; if (List_Remove( &idleFiles, element )) ERET1( Fail_File ); ERET1( Fail_File ); } return cur_file; /* everything is in order */Fail_File: FREE( cur_file );Fail_Element: Done_Element( element ); return NULL;Exit_Same: cur_file->ref_count++; /* increment reference count */ COPY( " -> (duplicate) hff = " ); CATI( cur_file->hff ); CAT( "\r\n" ); WRITE; return cur_file; /* no sense going on */}/****************************************************************************//* *//* getFontFile : *//* *//* return the address of the TFontFile corresponding to a given *//* HFF. If asleep, the file and its face object(s) is awoken. *//* */PFontFile getFontFile( HFF hff ){ static PListElement element; /* look in the live list first */ element = List_Find( &liveFiles, (long)hff ); if (element) { /* move it to the front of the live list - if it isn't already */ if ( liveFiles.head != element ) { if ( List_Remove( &liveFiles, element ) ) ERRRET( NULL ); if ( List_Insert( &liveFiles, element ) ) ERRRET( NULL ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -