Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencffobjs.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* cffobjs.c */ 00004 /* */ 00005 /* OpenType objects manager (body). */ 00006 /* */ 00007 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ 00008 /* 2010 by */ 00009 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00010 /* */ 00011 /* This file is part of the FreeType project, and may only be used, */ 00012 /* modified, and distributed under the terms of the FreeType project */ 00013 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00014 /* this file you indicate that you have read the license and */ 00015 /* understand and accept it fully. */ 00016 /* */ 00017 /***************************************************************************/ 00018 00019 00020 #include <ft2build.h> 00021 #include FT_INTERNAL_DEBUG_H 00022 #include FT_INTERNAL_CALC_H 00023 #include FT_INTERNAL_STREAM_H 00024 #include FT_ERRORS_H 00025 #include FT_TRUETYPE_IDS_H 00026 #include FT_TRUETYPE_TAGS_H 00027 #include FT_INTERNAL_SFNT_H 00028 #include "cffobjs.h" 00029 #include "cffload.h" 00030 #include "cffcmap.h" 00031 #include "cfferrs.h" 00032 #include "cffpic.h" 00033 00034 00035 /*************************************************************************/ 00036 /* */ 00037 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 00038 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 00039 /* messages during execution. */ 00040 /* */ 00041 #undef FT_COMPONENT 00042 #define FT_COMPONENT trace_cffobjs 00043 00044 00045 /*************************************************************************/ 00046 /* */ 00047 /* SIZE FUNCTIONS */ 00048 /* */ 00049 /* Note that we store the global hints in the size's `internal' root */ 00050 /* field. */ 00051 /* */ 00052 /*************************************************************************/ 00053 00054 00055 static PSH_Globals_Funcs 00056 cff_size_get_globals_funcs( CFF_Size size ) 00057 { 00058 CFF_Face face = (CFF_Face)size->root.face; 00059 CFF_Font font = (CFF_Font)face->extra.data; 00060 PSHinter_Service pshinter = font->pshinter; 00061 FT_Module module; 00062 00063 00064 module = FT_Get_Module( size->root.face->driver->root.library, 00065 "pshinter" ); 00066 return ( module && pshinter && pshinter->get_globals_funcs ) 00067 ? pshinter->get_globals_funcs( module ) 00068 : 0; 00069 } 00070 00071 00072 FT_LOCAL_DEF( void ) 00073 cff_size_done( FT_Size cffsize ) /* CFF_Size */ 00074 { 00075 CFF_Size size = (CFF_Size)cffsize; 00076 CFF_Face face = (CFF_Face)size->root.face; 00077 CFF_Font font = (CFF_Font)face->extra.data; 00078 CFF_Internal internal = (CFF_Internal)cffsize->internal; 00079 00080 00081 if ( internal ) 00082 { 00083 PSH_Globals_Funcs funcs; 00084 00085 00086 funcs = cff_size_get_globals_funcs( size ); 00087 if ( funcs ) 00088 { 00089 FT_UInt i; 00090 00091 00092 funcs->destroy( internal->topfont ); 00093 00094 for ( i = font->num_subfonts; i > 0; i-- ) 00095 funcs->destroy( internal->subfonts[i - 1] ); 00096 } 00097 00098 /* `internal' is freed by destroy_size (in ftobjs.c) */ 00099 } 00100 } 00101 00102 00103 /* CFF and Type 1 private dictionaries have slightly different */ 00104 /* structures; we need to synthesize a Type 1 dictionary on the fly */ 00105 00106 static void 00107 cff_make_private_dict( CFF_SubFont subfont, 00108 PS_Private priv ) 00109 { 00110 CFF_Private cpriv = &subfont->private_dict; 00111 FT_UInt n, count; 00112 00113 00114 FT_MEM_ZERO( priv, sizeof ( *priv ) ); 00115 00116 count = priv->num_blue_values = cpriv->num_blue_values; 00117 for ( n = 0; n < count; n++ ) 00118 priv->blue_values[n] = (FT_Short)cpriv->blue_values[n]; 00119 00120 count = priv->num_other_blues = cpriv->num_other_blues; 00121 for ( n = 0; n < count; n++ ) 00122 priv->other_blues[n] = (FT_Short)cpriv->other_blues[n]; 00123 00124 count = priv->num_family_blues = cpriv->num_family_blues; 00125 for ( n = 0; n < count; n++ ) 00126 priv->family_blues[n] = (FT_Short)cpriv->family_blues[n]; 00127 00128 count = priv->num_family_other_blues = cpriv->num_family_other_blues; 00129 for ( n = 0; n < count; n++ ) 00130 priv->family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n]; 00131 00132 priv->blue_scale = cpriv->blue_scale; 00133 priv->blue_shift = (FT_Int)cpriv->blue_shift; 00134 priv->blue_fuzz = (FT_Int)cpriv->blue_fuzz; 00135 00136 priv->standard_width[0] = (FT_UShort)cpriv->standard_width; 00137 priv->standard_height[0] = (FT_UShort)cpriv->standard_height; 00138 00139 count = priv->num_snap_widths = cpriv->num_snap_widths; 00140 for ( n = 0; n < count; n++ ) 00141 priv->snap_widths[n] = (FT_Short)cpriv->snap_widths[n]; 00142 00143 count = priv->num_snap_heights = cpriv->num_snap_heights; 00144 for ( n = 0; n < count; n++ ) 00145 priv->snap_heights[n] = (FT_Short)cpriv->snap_heights[n]; 00146 00147 priv->force_bold = cpriv->force_bold; 00148 priv->language_group = cpriv->language_group; 00149 priv->lenIV = cpriv->lenIV; 00150 } 00151 00152 00153 FT_LOCAL_DEF( FT_Error ) 00154 cff_size_init( FT_Size cffsize ) /* CFF_Size */ 00155 { 00156 CFF_Size size = (CFF_Size)cffsize; 00157 FT_Error error = CFF_Err_Ok; 00158 PSH_Globals_Funcs funcs = cff_size_get_globals_funcs( size ); 00159 00160 00161 if ( funcs ) 00162 { 00163 CFF_Face face = (CFF_Face)cffsize->face; 00164 CFF_Font font = (CFF_Font)face->extra.data; 00165 CFF_Internal internal; 00166 00167 PS_PrivateRec priv; 00168 FT_Memory memory = cffsize->face->memory; 00169 00170 FT_UInt i; 00171 00172 00173 if ( FT_NEW( internal ) ) 00174 goto Exit; 00175 00176 cff_make_private_dict( &font->top_font, &priv ); 00177 error = funcs->create( cffsize->face->memory, &priv, 00178 &internal->topfont ); 00179 if ( error ) 00180 goto Exit; 00181 00182 for ( i = font->num_subfonts; i > 0; i-- ) 00183 { 00184 CFF_SubFont sub = font->subfonts[i - 1]; 00185 00186 00187 cff_make_private_dict( sub, &priv ); 00188 error = funcs->create( cffsize->face->memory, &priv, 00189 &internal->subfonts[i - 1] ); 00190 if ( error ) 00191 goto Exit; 00192 } 00193 00194 cffsize->internal = (FT_Size_Internal)(void*)internal; 00195 } 00196 00197 size->strike_index = 0xFFFFFFFFUL; 00198 00199 Exit: 00200 return error; 00201 } 00202 00203 00204 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 00205 00206 FT_LOCAL_DEF( FT_Error ) 00207 cff_size_select( FT_Size size, 00208 FT_ULong strike_index ) 00209 { 00210 CFF_Size cffsize = (CFF_Size)size; 00211 PSH_Globals_Funcs funcs; 00212 00213 00214 cffsize->strike_index = strike_index; 00215 00216 FT_Select_Metrics( size->face, strike_index ); 00217 00218 funcs = cff_size_get_globals_funcs( cffsize ); 00219 00220 if ( funcs ) 00221 { 00222 CFF_Face face = (CFF_Face)size->face; 00223 CFF_Font font = (CFF_Font)face->extra.data; 00224 CFF_Internal internal = (CFF_Internal)size->internal; 00225 00226 FT_ULong top_upm = font->top_font.font_dict.units_per_em; 00227 FT_UInt i; 00228 00229 00230 funcs->set_scale( internal->topfont, 00231 size->metrics.x_scale, size->metrics.y_scale, 00232 0, 0 ); 00233 00234 for ( i = font->num_subfonts; i > 0; i-- ) 00235 { 00236 CFF_SubFont sub = font->subfonts[i - 1]; 00237 FT_ULong sub_upm = sub->font_dict.units_per_em; 00238 FT_Pos x_scale, y_scale; 00239 00240 00241 if ( top_upm != sub_upm ) 00242 { 00243 x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm ); 00244 y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm ); 00245 } 00246 else 00247 { 00248 x_scale = size->metrics.x_scale; 00249 y_scale = size->metrics.y_scale; 00250 } 00251 00252 funcs->set_scale( internal->subfonts[i - 1], 00253 x_scale, y_scale, 0, 0 ); 00254 } 00255 } 00256 00257 return CFF_Err_Ok; 00258 } 00259 00260 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 00261 00262 00263 FT_LOCAL_DEF( FT_Error ) 00264 cff_size_request( FT_Size size, 00265 FT_Size_Request req ) 00266 { 00267 CFF_Size cffsize = (CFF_Size)size; 00268 PSH_Globals_Funcs funcs; 00269 00270 00271 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 00272 00273 if ( FT_HAS_FIXED_SIZES( size->face ) ) 00274 { 00275 CFF_Face cffface = (CFF_Face)size->face; 00276 SFNT_Service sfnt = (SFNT_Service)cffface->sfnt; 00277 FT_ULong strike_index; 00278 00279 00280 if ( sfnt->set_sbit_strike( cffface, req, &strike_index ) ) 00281 cffsize->strike_index = 0xFFFFFFFFUL; 00282 else 00283 return cff_size_select( size, strike_index ); 00284 } 00285 00286 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 00287 00288 FT_Request_Metrics( size->face, req ); 00289 00290 funcs = cff_size_get_globals_funcs( cffsize ); 00291 00292 if ( funcs ) 00293 { 00294 CFF_Face cffface = (CFF_Face)size->face; 00295 CFF_Font font = (CFF_Font)cffface->extra.data; 00296 CFF_Internal internal = (CFF_Internal)size->internal; 00297 00298 FT_ULong top_upm = font->top_font.font_dict.units_per_em; 00299 FT_UInt i; 00300 00301 00302 funcs->set_scale( internal->topfont, 00303 size->metrics.x_scale, size->metrics.y_scale, 00304 0, 0 ); 00305 00306 for ( i = font->num_subfonts; i > 0; i-- ) 00307 { 00308 CFF_SubFont sub = font->subfonts[i - 1]; 00309 FT_ULong sub_upm = sub->font_dict.units_per_em; 00310 FT_Pos x_scale, y_scale; 00311 00312 00313 if ( top_upm != sub_upm ) 00314 { 00315 x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm ); 00316 y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm ); 00317 } 00318 else 00319 { 00320 x_scale = size->metrics.x_scale; 00321 y_scale = size->metrics.y_scale; 00322 } 00323 00324 funcs->set_scale( internal->subfonts[i - 1], 00325 x_scale, y_scale, 0, 0 ); 00326 } 00327 } 00328 00329 return CFF_Err_Ok; 00330 } 00331 00332 00333 /*************************************************************************/ 00334 /* */ 00335 /* SLOT FUNCTIONS */ 00336 /* */ 00337 /*************************************************************************/ 00338 00339 FT_LOCAL_DEF( void ) 00340 cff_slot_done( FT_GlyphSlot slot ) 00341 { 00342 slot->internal->glyph_hints = 0; 00343 } 00344 00345 00346 FT_LOCAL_DEF( FT_Error ) 00347 cff_slot_init( FT_GlyphSlot slot ) 00348 { 00349 CFF_Face face = (CFF_Face)slot->face; 00350 CFF_Font font = (CFF_Font)face->extra.data; 00351 PSHinter_Service pshinter = font->pshinter; 00352 00353 00354 if ( pshinter ) 00355 { 00356 FT_Module module; 00357 00358 00359 module = FT_Get_Module( slot->face->driver->root.library, 00360 "pshinter" ); 00361 if ( module ) 00362 { 00363 T2_Hints_Funcs funcs; 00364 00365 00366 funcs = pshinter->get_t2_funcs( module ); 00367 slot->internal->glyph_hints = (void*)funcs; 00368 } 00369 } 00370 00371 return CFF_Err_Ok; 00372 } 00373 00374 00375 /*************************************************************************/ 00376 /* */ 00377 /* FACE FUNCTIONS */ 00378 /* */ 00379 /*************************************************************************/ 00380 00381 static FT_String* 00382 cff_strcpy( FT_Memory memory, 00383 const FT_String* source ) 00384 { 00385 FT_Error error; 00386 FT_String* result; 00387 00388 00389 (void)FT_STRDUP( result, source ); 00390 00391 FT_UNUSED( error ); 00392 00393 return result; 00394 } 00395 00396 00397 /* Strip all subset prefixes of the form `ABCDEF+'. Usually, there */ 00398 /* is only one, but font names like `APCOOG+JFABTD+FuturaBQ-Bold' */ 00399 /* have been seen in the wild. */ 00400 00401 static void 00402 remove_subset_prefix( FT_String* name ) 00403 { 00404 FT_Int32 idx = 0; 00405 FT_Int32 length = strlen( name ) + 1; 00406 FT_Bool continue_search = 1; 00407 00408 00409 while ( continue_search ) 00410 { 00411 if ( length >= 7 && name[6] == '+' ) 00412 { 00413 for ( idx = 0; idx < 6; idx++ ) 00414 { 00415 /* ASCII uppercase letters */ 00416 if ( !( 'A' <= name[idx] && name[idx] <= 'Z' ) ) 00417 continue_search = 0; 00418 } 00419 00420 if ( continue_search ) 00421 { 00422 for ( idx = 7; idx < length; idx++ ) 00423 name[idx - 7] = name[idx]; 00424 } 00425 } 00426 else 00427 continue_search = 0; 00428 } 00429 } 00430 00431 00432 FT_LOCAL_DEF( FT_Error ) 00433 cff_face_init( FT_Stream stream, 00434 FT_Face cffface, /* CFF_Face */ 00435 FT_Int face_index, 00436 FT_Int num_params, 00437 FT_Parameter* params ) 00438 { 00439 CFF_Face face = (CFF_Face)cffface; 00440 FT_Error error; 00441 SFNT_Service sfnt; 00442 FT_Service_PsCMaps psnames; 00443 PSHinter_Service pshinter; 00444 FT_Bool pure_cff = 1; 00445 FT_Bool sfnt_format = 0; 00446 FT_Library library = cffface->driver->root.library; 00447 00448 00449 sfnt = (SFNT_Service)FT_Get_Module_Interface( 00450 library, "sfnt" ); 00451 if ( !sfnt ) 00452 goto Bad_Format; 00453 00454 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); 00455 00456 pshinter = (PSHinter_Service)FT_Get_Module_Interface( 00457 library, "pshinter" ); 00458 00459 /* create input stream from resource */ 00460 if ( FT_STREAM_SEEK( 0 ) ) 00461 goto Exit; 00462 00463 /* check whether we have a valid OpenType file */ 00464 error = sfnt->init_face( stream, face, face_index, num_params, params ); 00465 if ( !error ) 00466 { 00467 if ( face->format_tag != TTAG_OTTO ) /* `OTTO'; OpenType/CFF font */ 00468 { 00469 FT_TRACE2(( "[not a valid OpenType/CFF font]\n" )); 00470 goto Bad_Format; 00471 } 00472 00473 /* if we are performing a simple font format check, exit immediately */ 00474 if ( face_index < 0 ) 00475 return CFF_Err_Ok; 00476 00477 /* UNDOCUMENTED! A CFF in an SFNT can have only a single font. */ 00478 if ( face_index > 0 ) 00479 { 00480 FT_ERROR(( "cff_face_init: invalid face index\n" )); 00481 error = CFF_Err_Invalid_Argument; 00482 goto Exit; 00483 } 00484 00485 sfnt_format = 1; 00486 00487 /* now, the font can be either an OpenType/CFF font, or an SVG CEF */ 00488 /* font; in the latter case it doesn't have a `head' table */ 00489 error = face->goto_table( face, TTAG_head, stream, 0 ); 00490 if ( !error ) 00491 { 00492 pure_cff = 0; 00493 00494 /* load font directory */ 00495 error = sfnt->load_face( stream, face, 0, num_params, params ); 00496 if ( error ) 00497 goto Exit; 00498 } 00499 else 00500 { 00501 /* load the `cmap' table explicitly */ 00502 error = sfnt->load_cmap( face, stream ); 00503 if ( error ) 00504 goto Exit; 00505 00506 /* XXX: we don't load the GPOS table, as OpenType Layout */ 00507 /* support will be added later to a layout library on top of */ 00508 /* FreeType 2 */ 00509 } 00510 00511 /* now load the CFF part of the file */ 00512 error = face->goto_table( face, TTAG_CFF, stream, 0 ); 00513 if ( error ) 00514 goto Exit; 00515 } 00516 else 00517 { 00518 /* rewind to start of file; we are going to load a pure-CFF font */ 00519 if ( FT_STREAM_SEEK( 0 ) ) 00520 goto Exit; 00521 error = CFF_Err_Ok; 00522 } 00523 00524 /* now load and parse the CFF table in the file */ 00525 { 00526 CFF_Font cff; 00527 CFF_FontRecDict dict; 00528 FT_Memory memory = cffface->memory; 00529 FT_Int32 flags; 00530 FT_UInt i; 00531 00532 00533 if ( FT_NEW( cff ) ) 00534 goto Exit; 00535 00536 face->extra.data = cff; 00537 error = cff_font_load( library, stream, face_index, cff, pure_cff ); 00538 if ( error ) 00539 goto Exit; 00540 00541 cff->pshinter = pshinter; 00542 cff->psnames = psnames; 00543 00544 cffface->face_index = face_index; 00545 00546 /* Complement the root flags with some interesting information. */ 00547 /* Note that this is only necessary for pure CFF and CEF fonts; */ 00548 /* SFNT based fonts use the `name' table instead. */ 00549 00550 cffface->num_glyphs = cff->num_glyphs; 00551 00552 dict = &cff->top_font.font_dict; 00553 00554 /* we need the `PSNames' module for CFF and CEF formats */ 00555 /* which aren't CID-keyed */ 00556 if ( dict->cid_registry == 0xFFFFU && !psnames ) 00557 { 00558 FT_ERROR(( "cff_face_init:" 00559 " cannot open CFF & CEF fonts\n" 00560 " " 00561 " without the `PSNames' module\n" )); 00562 goto Bad_Format; 00563 } 00564 00565 if ( !dict->units_per_em ) 00566 dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM; 00567 00568 /* Normalize the font matrix so that `matrix->xx' is 1; the */ 00569 /* scaling is done with `units_per_em' then (at this point, */ 00570 /* it already contains the scaling factor, but without */ 00571 /* normalization of the matrix). */ 00572 /* */ 00573 /* Note that the offsets must be expressed in integer font */ 00574 /* units. */ 00575 00576 { 00577 FT_Matrix* matrix = &dict->font_matrix; 00578 FT_Vector* offset = &dict->font_offset; 00579 FT_ULong* upm = &dict->units_per_em; 00580 FT_Fixed temp = FT_ABS( matrix->yy ); 00581 00582 00583 if ( temp != 0x10000L ) 00584 { 00585 *upm = FT_DivFix( *upm, temp ); 00586 00587 matrix->xx = FT_DivFix( matrix->xx, temp ); 00588 matrix->yx = FT_DivFix( matrix->yx, temp ); 00589 matrix->xy = FT_DivFix( matrix->xy, temp ); 00590 matrix->yy = FT_DivFix( matrix->yy, temp ); 00591 offset->x = FT_DivFix( offset->x, temp ); 00592 offset->y = FT_DivFix( offset->y, temp ); 00593 } 00594 00595 offset->x >>= 16; 00596 offset->y >>= 16; 00597 } 00598 00599 for ( i = cff->num_subfonts; i > 0; i-- ) 00600 { 00601 CFF_FontRecDict sub = &cff->subfonts[i - 1]->font_dict; 00602 CFF_FontRecDict top = &cff->top_font.font_dict; 00603 00604 FT_Matrix* matrix; 00605 FT_Vector* offset; 00606 FT_ULong* upm; 00607 FT_Fixed temp; 00608 00609 00610 if ( sub->units_per_em ) 00611 { 00612 FT_Long scaling; 00613 00614 00615 if ( top->units_per_em > 1 && sub->units_per_em > 1 ) 00616 scaling = FT_MIN( top->units_per_em, sub->units_per_em ); 00617 else 00618 scaling = 1; 00619 00620 FT_Matrix_Multiply_Scaled( &top->font_matrix, 00621 &sub->font_matrix, 00622 scaling ); 00623 FT_Vector_Transform_Scaled( &sub->font_offset, 00624 &top->font_matrix, 00625 scaling ); 00626 00627 sub->units_per_em = FT_MulDiv( sub->units_per_em, 00628 top->units_per_em, 00629 scaling ); 00630 } 00631 else 00632 { 00633 sub->font_matrix = top->font_matrix; 00634 sub->font_offset = top->font_offset; 00635 00636 sub->units_per_em = top->units_per_em; 00637 } 00638 00639 matrix = &sub->font_matrix; 00640 offset = &sub->font_offset; 00641 upm = &sub->units_per_em; 00642 temp = FT_ABS( matrix->yy ); 00643 00644 if ( temp != 0x10000L ) 00645 { 00646 *upm = FT_DivFix( *upm, temp ); 00647 00648 /* if *upm is larger than 100*1000 we divide by 1000 -- */ 00649 /* this can happen if e.g. there is no top-font FontMatrix */ 00650 /* and the subfont FontMatrix already contains the complete */ 00651 /* scaling for the subfont (see section 5.11 of the PLRM) */ 00652 00653 /* 100 is a heuristic value */ 00654 00655 if ( *upm > 100L * 1000L ) 00656 *upm = ( *upm + 500 ) / 1000; 00657 00658 matrix->xx = FT_DivFix( matrix->xx, temp ); 00659 matrix->yx = FT_DivFix( matrix->yx, temp ); 00660 matrix->xy = FT_DivFix( matrix->xy, temp ); 00661 matrix->yy = FT_DivFix( matrix->yy, temp ); 00662 offset->x = FT_DivFix( offset->x, temp ); 00663 offset->y = FT_DivFix( offset->y, temp ); 00664 } 00665 00666 offset->x >>= 16; 00667 offset->y >>= 16; 00668 } 00669 00670 if ( pure_cff ) 00671 { 00672 char* style_name = NULL; 00673 00674 00675 /* set up num_faces */ 00676 cffface->num_faces = cff->num_faces; 00677 00678 /* compute number of glyphs */ 00679 if ( dict->cid_registry != 0xFFFFU ) 00680 cffface->num_glyphs = cff->charset.max_cid + 1; 00681 else 00682 cffface->num_glyphs = cff->charstrings_index.count; 00683 00684 /* set global bbox, as well as EM size */ 00685 cffface->bbox.xMin = dict->font_bbox.xMin >> 16; 00686 cffface->bbox.yMin = dict->font_bbox.yMin >> 16; 00687 /* no `U' suffix here to 0xFFFF! */ 00688 cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFF ) >> 16; 00689 cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFF ) >> 16; 00690 00691 cffface->units_per_EM = (FT_UShort)( dict->units_per_em ); 00692 00693 cffface->ascender = (FT_Short)( cffface->bbox.yMax ); 00694 cffface->descender = (FT_Short)( cffface->bbox.yMin ); 00695 00696 cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 ); 00697 if ( cffface->height < cffface->ascender - cffface->descender ) 00698 cffface->height = (FT_Short)( cffface->ascender - cffface->descender ); 00699 00700 cffface->underline_position = 00701 (FT_Short)( dict->underline_position >> 16 ); 00702 cffface->underline_thickness = 00703 (FT_Short)( dict->underline_thickness >> 16 ); 00704 00705 /* retrieve font family & style name */ 00706 cffface->family_name = cff_index_get_name( cff, face_index ); 00707 if ( cffface->family_name ) 00708 { 00709 char* full = cff_index_get_sid_string( cff, 00710 dict->full_name ); 00711 char* fullp = full; 00712 char* family = cffface->family_name; 00713 char* family_name = NULL; 00714 00715 00716 remove_subset_prefix( cffface->family_name ); 00717 00718 if ( dict->family_name ) 00719 { 00720 family_name = cff_index_get_sid_string( cff, 00721 dict->family_name ); 00722 if ( family_name ) 00723 family = family_name; 00724 } 00725 00726 /* We try to extract the style name from the full name. */ 00727 /* We need to ignore spaces and dashes during the search. */ 00728 if ( full && family ) 00729 { 00730 while ( *fullp ) 00731 { 00732 /* skip common characters at the start of both strings */ 00733 if ( *fullp == *family ) 00734 { 00735 family++; 00736 fullp++; 00737 continue; 00738 } 00739 00740 /* ignore spaces and dashes in full name during comparison */ 00741 if ( *fullp == ' ' || *fullp == '-' ) 00742 { 00743 fullp++; 00744 continue; 00745 } 00746 00747 /* ignore spaces and dashes in family name during comparison */ 00748 if ( *family == ' ' || *family == '-' ) 00749 { 00750 family++; 00751 continue; 00752 } 00753 00754 if ( !*family && *fullp ) 00755 { 00756 /* The full name begins with the same characters as the */ 00757 /* family name, with spaces and dashes removed. In this */ 00758 /* case, the remaining string in `fullp' will be used as */ 00759 /* the style name. */ 00760 style_name = cff_strcpy( memory, fullp ); 00761 } 00762 break; 00763 } 00764 } 00765 } 00766 else 00767 { 00768 char *cid_font_name = 00769 cff_index_get_sid_string( cff, 00770 dict->cid_font_name ); 00771 00772 00773 /* do we have a `/FontName' for a CID-keyed font? */ 00774 if ( cid_font_name ) 00775 cffface->family_name = cff_strcpy( memory, cid_font_name ); 00776 } 00777 00778 if ( style_name ) 00779 cffface->style_name = style_name; 00780 else 00781 /* assume "Regular" style if we don't know better */ 00782 cffface->style_name = cff_strcpy( memory, (char *)"Regular" ); 00783 00784 /*******************************************************************/ 00785 /* */ 00786 /* Compute face flags. */ 00787 /* */ 00788 flags = (FT_UInt32)( FT_FACE_FLAG_SCALABLE | /* scalable outlines */ 00789 FT_FACE_FLAG_HORIZONTAL | /* horizontal data */ 00790 FT_FACE_FLAG_HINTER ); /* has native hinter */ 00791 00792 if ( sfnt_format ) 00793 flags |= (FT_UInt32)FT_FACE_FLAG_SFNT; 00794 00795 /* fixed width font? */ 00796 if ( dict->is_fixed_pitch ) 00797 flags |= (FT_UInt32)FT_FACE_FLAG_FIXED_WIDTH; 00798 00799 /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */ 00800 #if 0 00801 /* kerning available? */ 00802 if ( face->kern_pairs ) 00803 flags |= (FT_UInt32)FT_FACE_FLAG_KERNING; 00804 #endif 00805 00806 cffface->face_flags = flags; 00807 00808 /*******************************************************************/ 00809 /* */ 00810 /* Compute style flags. */ 00811 /* */ 00812 flags = 0; 00813 00814 if ( dict->italic_angle ) 00815 flags |= FT_STYLE_FLAG_ITALIC; 00816 00817 { 00818 char *weight = cff_index_get_sid_string( cff, 00819 dict->weight ); 00820 00821 00822 if ( weight ) 00823 if ( !ft_strcmp( weight, "Bold" ) || 00824 !ft_strcmp( weight, "Black" ) ) 00825 flags |= FT_STYLE_FLAG_BOLD; 00826 } 00827 00828 /* double check */ 00829 if ( !(flags & FT_STYLE_FLAG_BOLD) && cffface->style_name ) 00830 if ( !ft_strncmp( cffface->style_name, "Bold", 4 ) || 00831 !ft_strncmp( cffface->style_name, "Black", 5 ) ) 00832 flags |= FT_STYLE_FLAG_BOLD; 00833 00834 cffface->style_flags = flags; 00835 } 00836 00837 00838 #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES 00839 /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */ 00840 /* has unset this flag because of the 3.0 `post' table. */ 00841 if ( dict->cid_registry == 0xFFFFU ) 00842 cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; 00843 #endif 00844 00845 if ( dict->cid_registry != 0xFFFFU && pure_cff ) 00846 cffface->face_flags |= FT_FACE_FLAG_CID_KEYED; 00847 00848 00849 /*******************************************************************/ 00850 /* */ 00851 /* Compute char maps. */ 00852 /* */ 00853 00854 /* Try to synthesize a Unicode charmap if there is none available */ 00855 /* already. If an OpenType font contains a Unicode "cmap", we */ 00856 /* will use it, whatever be in the CFF part of the file. */ 00857 { 00858 FT_CharMapRec cmaprec; 00859 FT_CharMap cmap; 00860 FT_UInt nn; 00861 CFF_Encoding encoding = &cff->encoding; 00862 00863 00864 for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ ) 00865 { 00866 cmap = cffface->charmaps[nn]; 00867 00868 /* Windows Unicode? */ 00869 if ( cmap->platform_id == TT_PLATFORM_MICROSOFT && 00870 cmap->encoding_id == TT_MS_ID_UNICODE_CS ) 00871 goto Skip_Unicode; 00872 00873 /* Apple Unicode platform id? */ 00874 if ( cmap->platform_id == TT_PLATFORM_APPLE_UNICODE ) 00875 goto Skip_Unicode; /* Apple Unicode */ 00876 } 00877 00878 /* since CID-keyed fonts don't contain glyph names, we can't */ 00879 /* construct a cmap */ 00880 if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU ) 00881 goto Exit; 00882 00883 #ifdef FT_MAX_CHARMAP_CACHEABLE 00884 if ( nn + 1 > FT_MAX_CHARMAP_CACHEABLE ) 00885 { 00886 FT_ERROR(( "cff_face_init: no Unicode cmap is found, " 00887 "and too many subtables (%d) to add synthesized cmap\n", 00888 nn )); 00889 goto Exit; 00890 } 00891 #endif 00892 00893 /* we didn't find a Unicode charmap -- synthesize one */ 00894 cmaprec.face = cffface; 00895 cmaprec.platform_id = TT_PLATFORM_MICROSOFT; 00896 cmaprec.encoding_id = TT_MS_ID_UNICODE_CS; 00897 cmaprec.encoding = FT_ENCODING_UNICODE; 00898 00899 nn = (FT_UInt)cffface->num_charmaps; 00900 00901 error = FT_CMap_New( &FT_CFF_CMAP_UNICODE_CLASS_REC_GET, NULL, 00902 &cmaprec, NULL ); 00903 if ( error && FT_Err_No_Unicode_Glyph_Name != error ) 00904 goto Exit; 00905 error = FT_Err_Ok; 00906 00907 /* if no Unicode charmap was previously selected, select this one */ 00908 if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps ) 00909 cffface->charmap = cffface->charmaps[nn]; 00910 00911 Skip_Unicode: 00912 #ifdef FT_MAX_CHARMAP_CACHEABLE 00913 if ( nn > FT_MAX_CHARMAP_CACHEABLE ) 00914 { 00915 FT_ERROR(( "cff_face_init: Unicode cmap is found, " 00916 "but too many preceding subtables (%d) to access\n", 00917 nn - 1 )); 00918 goto Exit; 00919 } 00920 #endif 00921 if ( encoding->count > 0 ) 00922 { 00923 FT_CMap_Class clazz; 00924 00925 00926 cmaprec.face = cffface; 00927 cmaprec.platform_id = TT_PLATFORM_ADOBE; /* Adobe platform id */ 00928 00929 if ( encoding->offset == 0 ) 00930 { 00931 cmaprec.encoding_id = TT_ADOBE_ID_STANDARD; 00932 cmaprec.encoding = FT_ENCODING_ADOBE_STANDARD; 00933 clazz = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET; 00934 } 00935 else if ( encoding->offset == 1 ) 00936 { 00937 cmaprec.encoding_id = TT_ADOBE_ID_EXPERT; 00938 cmaprec.encoding = FT_ENCODING_ADOBE_EXPERT; 00939 clazz = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET; 00940 } 00941 else 00942 { 00943 cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM; 00944 cmaprec.encoding = FT_ENCODING_ADOBE_CUSTOM; 00945 clazz = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET; 00946 } 00947 00948 error = FT_CMap_New( clazz, NULL, &cmaprec, NULL ); 00949 } 00950 } 00951 } 00952 00953 Exit: 00954 return error; 00955 00956 Bad_Format: 00957 error = CFF_Err_Unknown_File_Format; 00958 goto Exit; 00959 } 00960 00961 00962 FT_LOCAL_DEF( void ) 00963 cff_face_done( FT_Face cffface ) /* CFF_Face */ 00964 { 00965 CFF_Face face = (CFF_Face)cffface; 00966 FT_Memory memory; 00967 SFNT_Service sfnt; 00968 00969 00970 if ( !face ) 00971 return; 00972 00973 memory = cffface->memory; 00974 sfnt = (SFNT_Service)face->sfnt; 00975 00976 if ( sfnt ) 00977 sfnt->done_face( face ); 00978 00979 { 00980 CFF_Font cff = (CFF_Font)face->extra.data; 00981 00982 00983 if ( cff ) 00984 { 00985 cff_font_done( cff ); 00986 FT_FREE( face->extra.data ); 00987 } 00988 } 00989 } 00990 00991 00992 FT_LOCAL_DEF( FT_Error ) 00993 cff_driver_init( FT_Module module ) 00994 { 00995 FT_UNUSED( module ); 00996 00997 return CFF_Err_Ok; 00998 } 00999 01000 01001 FT_LOCAL_DEF( void ) 01002 cff_driver_done( FT_Module module ) 01003 { 01004 FT_UNUSED( module ); 01005 } 01006 01007 01008 /* END */ Generated on Sun May 27 2012 04:33:49 for ReactOS by
1.7.6.1
|