Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenftobjs.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* ftobjs.c */ 00004 /* */ 00005 /* The FreeType private base classes (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_LIST_H 00022 #include FT_OUTLINE_H 00023 #include FT_INTERNAL_VALIDATE_H 00024 #include FT_INTERNAL_OBJECTS_H 00025 #include FT_INTERNAL_DEBUG_H 00026 #include FT_INTERNAL_RFORK_H 00027 #include FT_INTERNAL_STREAM_H 00028 #include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */ 00029 #include FT_TRUETYPE_TABLES_H 00030 #include FT_TRUETYPE_TAGS_H 00031 #include FT_TRUETYPE_IDS_H 00032 00033 #include FT_SERVICE_SFNT_H 00034 #include FT_SERVICE_POSTSCRIPT_NAME_H 00035 #include FT_SERVICE_GLYPH_DICT_H 00036 #include FT_SERVICE_TT_CMAP_H 00037 #include FT_SERVICE_KERNING_H 00038 #include FT_SERVICE_TRUETYPE_ENGINE_H 00039 00040 #ifdef FT_CONFIG_OPTION_MAC_FONTS 00041 #include "ftbase.h" 00042 #endif 00043 00044 #define GRID_FIT_METRICS 00045 00046 00047 FT_BASE_DEF( FT_Pointer ) 00048 ft_service_list_lookup( FT_ServiceDesc service_descriptors, 00049 const char* service_id ) 00050 { 00051 FT_Pointer result = NULL; 00052 FT_ServiceDesc desc = service_descriptors; 00053 00054 00055 if ( desc && service_id ) 00056 { 00057 for ( ; desc->serv_id != NULL; desc++ ) 00058 { 00059 if ( ft_strcmp( desc->serv_id, service_id ) == 0 ) 00060 { 00061 result = (FT_Pointer)desc->serv_data; 00062 break; 00063 } 00064 } 00065 } 00066 00067 return result; 00068 } 00069 00070 00071 FT_BASE_DEF( void ) 00072 ft_validator_init( FT_Validator valid, 00073 const FT_Byte* base, 00074 const FT_Byte* limit, 00075 FT_ValidationLevel level ) 00076 { 00077 valid->base = base; 00078 valid->limit = limit; 00079 valid->level = level; 00080 valid->error = FT_Err_Ok; 00081 } 00082 00083 00084 FT_BASE_DEF( FT_Int ) 00085 ft_validator_run( FT_Validator valid ) 00086 { 00087 /* This function doesn't work! None should call it. */ 00088 FT_UNUSED( valid ); 00089 00090 return -1; 00091 } 00092 00093 00094 FT_BASE_DEF( void ) 00095 ft_validator_error( FT_Validator valid, 00096 FT_Error error ) 00097 { 00098 /* since the cast below also disables the compiler's */ 00099 /* type check, we introduce a dummy variable, which */ 00100 /* will be optimized away */ 00101 volatile ft_jmp_buf* jump_buffer = &valid->jump_buffer; 00102 00103 00104 valid->error = error; 00105 00106 /* throw away volatileness; use `jump_buffer' or the */ 00107 /* compiler may warn about an unused local variable */ 00108 ft_longjmp( *(ft_jmp_buf*) jump_buffer, 1 ); 00109 } 00110 00111 00112 /*************************************************************************/ 00113 /*************************************************************************/ 00114 /*************************************************************************/ 00115 /**** ****/ 00116 /**** ****/ 00117 /**** S T R E A M ****/ 00118 /**** ****/ 00119 /**** ****/ 00120 /*************************************************************************/ 00121 /*************************************************************************/ 00122 /*************************************************************************/ 00123 00124 00125 /* create a new input stream from an FT_Open_Args structure */ 00126 /* */ 00127 FT_BASE_DEF( FT_Error ) 00128 FT_Stream_New( FT_Library library, 00129 const FT_Open_Args* args, 00130 FT_Stream *astream ) 00131 { 00132 FT_Error error; 00133 FT_Memory memory; 00134 FT_Stream stream; 00135 00136 00137 *astream = 0; 00138 00139 if ( !library ) 00140 return FT_Err_Invalid_Library_Handle; 00141 00142 if ( !args ) 00143 return FT_Err_Invalid_Argument; 00144 00145 memory = library->memory; 00146 00147 if ( FT_NEW( stream ) ) 00148 goto Exit; 00149 00150 stream->memory = memory; 00151 00152 if ( args->flags & FT_OPEN_MEMORY ) 00153 { 00154 /* create a memory-based stream */ 00155 FT_Stream_OpenMemory( stream, 00156 (const FT_Byte*)args->memory_base, 00157 args->memory_size ); 00158 } 00159 else if ( args->flags & FT_OPEN_PATHNAME ) 00160 { 00161 /* create a normal system stream */ 00162 error = FT_Stream_Open( stream, args->pathname ); 00163 stream->pathname.pointer = args->pathname; 00164 } 00165 else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream ) 00166 { 00167 /* use an existing, user-provided stream */ 00168 00169 /* in this case, we do not need to allocate a new stream object */ 00170 /* since the caller is responsible for closing it himself */ 00171 FT_FREE( stream ); 00172 stream = args->stream; 00173 } 00174 else 00175 error = FT_Err_Invalid_Argument; 00176 00177 if ( error ) 00178 FT_FREE( stream ); 00179 else 00180 stream->memory = memory; /* just to be certain */ 00181 00182 *astream = stream; 00183 00184 Exit: 00185 return error; 00186 } 00187 00188 00189 FT_BASE_DEF( void ) 00190 FT_Stream_Free( FT_Stream stream, 00191 FT_Int external ) 00192 { 00193 if ( stream ) 00194 { 00195 FT_Memory memory = stream->memory; 00196 00197 00198 FT_Stream_Close( stream ); 00199 00200 if ( !external ) 00201 FT_FREE( stream ); 00202 } 00203 } 00204 00205 00206 /*************************************************************************/ 00207 /* */ 00208 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 00209 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 00210 /* messages during execution. */ 00211 /* */ 00212 #undef FT_COMPONENT 00213 #define FT_COMPONENT trace_objs 00214 00215 00216 /*************************************************************************/ 00217 /*************************************************************************/ 00218 /*************************************************************************/ 00219 /**** ****/ 00220 /**** ****/ 00221 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/ 00222 /**** ****/ 00223 /**** ****/ 00224 /*************************************************************************/ 00225 /*************************************************************************/ 00226 /*************************************************************************/ 00227 00228 00229 static FT_Error 00230 ft_glyphslot_init( FT_GlyphSlot slot ) 00231 { 00232 FT_Driver driver = slot->face->driver; 00233 FT_Driver_Class clazz = driver->clazz; 00234 FT_Memory memory = driver->root.memory; 00235 FT_Error error = FT_Err_Ok; 00236 FT_Slot_Internal internal = NULL; 00237 00238 00239 slot->library = driver->root.library; 00240 00241 if ( FT_NEW( internal ) ) 00242 goto Exit; 00243 00244 slot->internal = internal; 00245 00246 if ( FT_DRIVER_USES_OUTLINES( driver ) ) 00247 error = FT_GlyphLoader_New( memory, &internal->loader ); 00248 00249 if ( !error && clazz->init_slot ) 00250 error = clazz->init_slot( slot ); 00251 00252 Exit: 00253 return error; 00254 } 00255 00256 00257 FT_BASE_DEF( void ) 00258 ft_glyphslot_free_bitmap( FT_GlyphSlot slot ) 00259 { 00260 if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) ) 00261 { 00262 FT_Memory memory = FT_FACE_MEMORY( slot->face ); 00263 00264 00265 FT_FREE( slot->bitmap.buffer ); 00266 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; 00267 } 00268 else 00269 { 00270 /* assume that the bitmap buffer was stolen or not */ 00271 /* allocated from the heap */ 00272 slot->bitmap.buffer = NULL; 00273 } 00274 } 00275 00276 00277 FT_BASE_DEF( void ) 00278 ft_glyphslot_set_bitmap( FT_GlyphSlot slot, 00279 FT_Byte* buffer ) 00280 { 00281 ft_glyphslot_free_bitmap( slot ); 00282 00283 slot->bitmap.buffer = buffer; 00284 00285 FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 ); 00286 } 00287 00288 00289 FT_BASE_DEF( FT_Error ) 00290 ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot, 00291 FT_ULong size ) 00292 { 00293 FT_Memory memory = FT_FACE_MEMORY( slot->face ); 00294 FT_Error error; 00295 00296 00297 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) 00298 FT_FREE( slot->bitmap.buffer ); 00299 else 00300 slot->internal->flags |= FT_GLYPH_OWN_BITMAP; 00301 00302 (void)FT_ALLOC( slot->bitmap.buffer, size ); 00303 return error; 00304 } 00305 00306 00307 static void 00308 ft_glyphslot_clear( FT_GlyphSlot slot ) 00309 { 00310 /* free bitmap if needed */ 00311 ft_glyphslot_free_bitmap( slot ); 00312 00313 /* clear all public fields in the glyph slot */ 00314 FT_ZERO( &slot->metrics ); 00315 FT_ZERO( &slot->outline ); 00316 00317 slot->bitmap.width = 0; 00318 slot->bitmap.rows = 0; 00319 slot->bitmap.pitch = 0; 00320 slot->bitmap.pixel_mode = 0; 00321 /* `slot->bitmap.buffer' has been handled by ft_glyphslot_free_bitmap */ 00322 00323 slot->bitmap_left = 0; 00324 slot->bitmap_top = 0; 00325 slot->num_subglyphs = 0; 00326 slot->subglyphs = 0; 00327 slot->control_data = 0; 00328 slot->control_len = 0; 00329 slot->other = 0; 00330 slot->format = FT_GLYPH_FORMAT_NONE; 00331 00332 slot->linearHoriAdvance = 0; 00333 slot->linearVertAdvance = 0; 00334 slot->lsb_delta = 0; 00335 slot->rsb_delta = 0; 00336 } 00337 00338 00339 static void 00340 ft_glyphslot_done( FT_GlyphSlot slot ) 00341 { 00342 FT_Driver driver = slot->face->driver; 00343 FT_Driver_Class clazz = driver->clazz; 00344 FT_Memory memory = driver->root.memory; 00345 00346 00347 if ( clazz->done_slot ) 00348 clazz->done_slot( slot ); 00349 00350 /* free bitmap buffer if needed */ 00351 ft_glyphslot_free_bitmap( slot ); 00352 00353 /* slot->internal might be NULL in out-of-memory situations */ 00354 if ( slot->internal ) 00355 { 00356 /* free glyph loader */ 00357 if ( FT_DRIVER_USES_OUTLINES( driver ) ) 00358 { 00359 FT_GlyphLoader_Done( slot->internal->loader ); 00360 slot->internal->loader = 0; 00361 } 00362 00363 FT_FREE( slot->internal ); 00364 } 00365 } 00366 00367 00368 /* documentation is in ftobjs.h */ 00369 00370 FT_BASE_DEF( FT_Error ) 00371 FT_New_GlyphSlot( FT_Face face, 00372 FT_GlyphSlot *aslot ) 00373 { 00374 FT_Error error; 00375 FT_Driver driver; 00376 FT_Driver_Class clazz; 00377 FT_Memory memory; 00378 FT_GlyphSlot slot; 00379 00380 00381 if ( !face || !face->driver ) 00382 return FT_Err_Invalid_Argument; 00383 00384 driver = face->driver; 00385 clazz = driver->clazz; 00386 memory = driver->root.memory; 00387 00388 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" )); 00389 if ( !FT_ALLOC( slot, clazz->slot_object_size ) ) 00390 { 00391 slot->face = face; 00392 00393 error = ft_glyphslot_init( slot ); 00394 if ( error ) 00395 { 00396 ft_glyphslot_done( slot ); 00397 FT_FREE( slot ); 00398 goto Exit; 00399 } 00400 00401 slot->next = face->glyph; 00402 face->glyph = slot; 00403 00404 if ( aslot ) 00405 *aslot = slot; 00406 } 00407 else if ( aslot ) 00408 *aslot = 0; 00409 00410 00411 Exit: 00412 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error )); 00413 return error; 00414 } 00415 00416 00417 /* documentation is in ftobjs.h */ 00418 00419 FT_BASE_DEF( void ) 00420 FT_Done_GlyphSlot( FT_GlyphSlot slot ) 00421 { 00422 if ( slot ) 00423 { 00424 FT_Driver driver = slot->face->driver; 00425 FT_Memory memory = driver->root.memory; 00426 FT_GlyphSlot prev; 00427 FT_GlyphSlot cur; 00428 00429 00430 /* Remove slot from its parent face's list */ 00431 prev = NULL; 00432 cur = slot->face->glyph; 00433 00434 while ( cur ) 00435 { 00436 if ( cur == slot ) 00437 { 00438 if ( !prev ) 00439 slot->face->glyph = cur->next; 00440 else 00441 prev->next = cur->next; 00442 00443 ft_glyphslot_done( slot ); 00444 FT_FREE( slot ); 00445 break; 00446 } 00447 prev = cur; 00448 cur = cur->next; 00449 } 00450 } 00451 } 00452 00453 00454 /* documentation is in freetype.h */ 00455 00456 FT_EXPORT_DEF( void ) 00457 FT_Set_Transform( FT_Face face, 00458 FT_Matrix* matrix, 00459 FT_Vector* delta ) 00460 { 00461 FT_Face_Internal internal; 00462 00463 00464 if ( !face ) 00465 return; 00466 00467 internal = face->internal; 00468 00469 internal->transform_flags = 0; 00470 00471 if ( !matrix ) 00472 { 00473 internal->transform_matrix.xx = 0x10000L; 00474 internal->transform_matrix.xy = 0; 00475 internal->transform_matrix.yx = 0; 00476 internal->transform_matrix.yy = 0x10000L; 00477 matrix = &internal->transform_matrix; 00478 } 00479 else 00480 internal->transform_matrix = *matrix; 00481 00482 /* set transform_flags bit flag 0 if `matrix' isn't the identity */ 00483 if ( ( matrix->xy | matrix->yx ) || 00484 matrix->xx != 0x10000L || 00485 matrix->yy != 0x10000L ) 00486 internal->transform_flags |= 1; 00487 00488 if ( !delta ) 00489 { 00490 internal->transform_delta.x = 0; 00491 internal->transform_delta.y = 0; 00492 delta = &internal->transform_delta; 00493 } 00494 else 00495 internal->transform_delta = *delta; 00496 00497 /* set transform_flags bit flag 1 if `delta' isn't the null vector */ 00498 if ( delta->x | delta->y ) 00499 internal->transform_flags |= 2; 00500 } 00501 00502 00503 static FT_Renderer 00504 ft_lookup_glyph_renderer( FT_GlyphSlot slot ); 00505 00506 00507 #ifdef GRID_FIT_METRICS 00508 static void 00509 ft_glyphslot_grid_fit_metrics( FT_GlyphSlot slot, 00510 FT_Bool vertical ) 00511 { 00512 FT_Glyph_Metrics* metrics = &slot->metrics; 00513 FT_Pos right, bottom; 00514 00515 00516 if ( vertical ) 00517 { 00518 metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX ); 00519 metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY ); 00520 00521 right = FT_PIX_CEIL( metrics->vertBearingX + metrics->width ); 00522 bottom = FT_PIX_CEIL( metrics->vertBearingY + metrics->height ); 00523 00524 metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX ); 00525 metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY ); 00526 00527 metrics->width = right - metrics->vertBearingX; 00528 metrics->height = bottom - metrics->vertBearingY; 00529 } 00530 else 00531 { 00532 metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX ); 00533 metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY ); 00534 00535 right = FT_PIX_CEIL ( metrics->horiBearingX + metrics->width ); 00536 bottom = FT_PIX_FLOOR( metrics->horiBearingY - metrics->height ); 00537 00538 metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX ); 00539 metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY ); 00540 00541 metrics->width = right - metrics->horiBearingX; 00542 metrics->height = metrics->horiBearingY - bottom; 00543 } 00544 00545 metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance ); 00546 metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance ); 00547 } 00548 #endif /* GRID_FIT_METRICS */ 00549 00550 00551 /* documentation is in freetype.h */ 00552 00553 FT_EXPORT_DEF( FT_Error ) 00554 FT_Load_Glyph( FT_Face face, 00555 FT_UInt glyph_index, 00556 FT_Int32 load_flags ) 00557 { 00558 FT_Error error; 00559 FT_Driver driver; 00560 FT_GlyphSlot slot; 00561 FT_Library library; 00562 FT_Bool autohint = FALSE; 00563 FT_Module hinter; 00564 00565 00566 if ( !face || !face->size || !face->glyph ) 00567 return FT_Err_Invalid_Face_Handle; 00568 00569 /* The validity test for `glyph_index' is performed by the */ 00570 /* font drivers. */ 00571 00572 slot = face->glyph; 00573 ft_glyphslot_clear( slot ); 00574 00575 driver = face->driver; 00576 library = driver->root.library; 00577 hinter = library->auto_hinter; 00578 00579 /* resolve load flags dependencies */ 00580 00581 if ( load_flags & FT_LOAD_NO_RECURSE ) 00582 load_flags |= FT_LOAD_NO_SCALE | 00583 FT_LOAD_IGNORE_TRANSFORM; 00584 00585 if ( load_flags & FT_LOAD_NO_SCALE ) 00586 { 00587 load_flags |= FT_LOAD_NO_HINTING | 00588 FT_LOAD_NO_BITMAP; 00589 00590 load_flags &= ~FT_LOAD_RENDER; 00591 } 00592 00593 /* 00594 * Determine whether we need to auto-hint or not. 00595 * The general rules are: 00596 * 00597 * - Do only auto-hinting if we have a hinter module, a scalable font 00598 * format dealing with outlines, and no transforms except simple 00599 * slants and/or rotations by integer multiples of 90 degrees. 00600 * 00601 * - Then, auto-hint if FT_LOAD_FORCE_AUTOHINT is set or if we don't 00602 * have a native font hinter. 00603 * 00604 * - Otherwise, auto-hint for LIGHT hinting mode. 00605 * 00606 * - Exception: The font is `tricky' and requires the native hinter to 00607 * load properly. 00608 */ 00609 00610 if ( hinter && 00611 !( load_flags & FT_LOAD_NO_HINTING ) && 00612 !( load_flags & FT_LOAD_NO_AUTOHINT ) && 00613 FT_DRIVER_IS_SCALABLE( driver ) && 00614 FT_DRIVER_USES_OUTLINES( driver ) && 00615 !FT_IS_TRICKY( face ) && 00616 ( ( face->internal->transform_matrix.yx == 0 && 00617 face->internal->transform_matrix.xx != 0 ) || 00618 ( face->internal->transform_matrix.xx == 0 && 00619 face->internal->transform_matrix.yx != 0 ) ) ) 00620 { 00621 if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) || 00622 !FT_DRIVER_HAS_HINTER( driver ) ) 00623 autohint = TRUE; 00624 else 00625 { 00626 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags ); 00627 00628 00629 if ( mode == FT_RENDER_MODE_LIGHT || 00630 face->internal->ignore_unpatented_hinter ) 00631 autohint = TRUE; 00632 } 00633 } 00634 00635 if ( autohint ) 00636 { 00637 FT_AutoHinter_Service hinting; 00638 00639 00640 /* try to load embedded bitmaps first if available */ 00641 /* */ 00642 /* XXX: This is really a temporary hack that should disappear */ 00643 /* promptly with FreeType 2.1! */ 00644 /* */ 00645 if ( FT_HAS_FIXED_SIZES( face ) && 00646 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) 00647 { 00648 error = driver->clazz->load_glyph( slot, face->size, 00649 glyph_index, 00650 load_flags | FT_LOAD_SBITS_ONLY ); 00651 00652 if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP ) 00653 goto Load_Ok; 00654 } 00655 00656 { 00657 FT_Face_Internal internal = face->internal; 00658 FT_Int transform_flags = internal->transform_flags; 00659 00660 00661 /* since the auto-hinter calls FT_Load_Glyph by itself, */ 00662 /* make sure that glyphs aren't transformed */ 00663 internal->transform_flags = 0; 00664 00665 /* load auto-hinted outline */ 00666 hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface; 00667 00668 error = hinting->load_glyph( (FT_AutoHinter)hinter, 00669 slot, face->size, 00670 glyph_index, load_flags ); 00671 00672 internal->transform_flags = transform_flags; 00673 } 00674 } 00675 else 00676 { 00677 error = driver->clazz->load_glyph( slot, 00678 face->size, 00679 glyph_index, 00680 load_flags ); 00681 if ( error ) 00682 goto Exit; 00683 00684 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) 00685 { 00686 /* check that the loaded outline is correct */ 00687 error = FT_Outline_Check( &slot->outline ); 00688 if ( error ) 00689 goto Exit; 00690 00691 #ifdef GRID_FIT_METRICS 00692 if ( !( load_flags & FT_LOAD_NO_HINTING ) ) 00693 ft_glyphslot_grid_fit_metrics( slot, 00694 FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) ); 00695 #endif 00696 } 00697 } 00698 00699 Load_Ok: 00700 /* compute the advance */ 00701 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 00702 { 00703 slot->advance.x = 0; 00704 slot->advance.y = slot->metrics.vertAdvance; 00705 } 00706 else 00707 { 00708 slot->advance.x = slot->metrics.horiAdvance; 00709 slot->advance.y = 0; 00710 } 00711 00712 /* compute the linear advance in 16.16 pixels */ 00713 if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 && 00714 ( FT_IS_SCALABLE( face ) ) ) 00715 { 00716 FT_Size_Metrics* metrics = &face->size->metrics; 00717 00718 00719 /* it's tricky! */ 00720 slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance, 00721 metrics->x_scale, 64 ); 00722 00723 slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance, 00724 metrics->y_scale, 64 ); 00725 } 00726 00727 if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 ) 00728 { 00729 FT_Face_Internal internal = face->internal; 00730 00731 00732 /* now, transform the glyph image if needed */ 00733 if ( internal->transform_flags ) 00734 { 00735 /* get renderer */ 00736 FT_Renderer renderer = ft_lookup_glyph_renderer( slot ); 00737 00738 00739 if ( renderer ) 00740 error = renderer->clazz->transform_glyph( 00741 renderer, slot, 00742 &internal->transform_matrix, 00743 &internal->transform_delta ); 00744 else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) 00745 { 00746 /* apply `standard' transformation if no renderer is available */ 00747 if ( &internal->transform_matrix ) 00748 FT_Outline_Transform( &slot->outline, 00749 &internal->transform_matrix ); 00750 00751 if ( &internal->transform_delta ) 00752 FT_Outline_Translate( &slot->outline, 00753 internal->transform_delta.x, 00754 internal->transform_delta.y ); 00755 } 00756 00757 /* transform advance */ 00758 FT_Vector_Transform( &slot->advance, &internal->transform_matrix ); 00759 } 00760 } 00761 00762 FT_TRACE5(( " x advance: %d\n" , slot->advance.x )); 00763 FT_TRACE5(( " y advance: %d\n" , slot->advance.y )); 00764 00765 FT_TRACE5(( " linear x advance: %d\n" , slot->linearHoriAdvance )); 00766 FT_TRACE5(( " linear y advance: %d\n" , slot->linearVertAdvance )); 00767 00768 /* do we need to render the image now? */ 00769 if ( !error && 00770 slot->format != FT_GLYPH_FORMAT_BITMAP && 00771 slot->format != FT_GLYPH_FORMAT_COMPOSITE && 00772 load_flags & FT_LOAD_RENDER ) 00773 { 00774 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags ); 00775 00776 00777 if ( mode == FT_RENDER_MODE_NORMAL && 00778 (load_flags & FT_LOAD_MONOCHROME ) ) 00779 mode = FT_RENDER_MODE_MONO; 00780 00781 error = FT_Render_Glyph( slot, mode ); 00782 } 00783 00784 Exit: 00785 return error; 00786 } 00787 00788 00789 /* documentation is in freetype.h */ 00790 00791 FT_EXPORT_DEF( FT_Error ) 00792 FT_Load_Char( FT_Face face, 00793 FT_ULong char_code, 00794 FT_Int32 load_flags ) 00795 { 00796 FT_UInt glyph_index; 00797 00798 00799 if ( !face ) 00800 return FT_Err_Invalid_Face_Handle; 00801 00802 glyph_index = (FT_UInt)char_code; 00803 if ( face->charmap ) 00804 glyph_index = FT_Get_Char_Index( face, char_code ); 00805 00806 return FT_Load_Glyph( face, glyph_index, load_flags ); 00807 } 00808 00809 00810 /* destructor for sizes list */ 00811 static void 00812 destroy_size( FT_Memory memory, 00813 FT_Size size, 00814 FT_Driver driver ) 00815 { 00816 /* finalize client-specific data */ 00817 if ( size->generic.finalizer ) 00818 size->generic.finalizer( size ); 00819 00820 /* finalize format-specific stuff */ 00821 if ( driver->clazz->done_size ) 00822 driver->clazz->done_size( size ); 00823 00824 FT_FREE( size->internal ); 00825 FT_FREE( size ); 00826 } 00827 00828 00829 static void 00830 ft_cmap_done_internal( FT_CMap cmap ); 00831 00832 00833 static void 00834 destroy_charmaps( FT_Face face, 00835 FT_Memory memory ) 00836 { 00837 FT_Int n; 00838 00839 00840 if ( !face ) 00841 return; 00842 00843 for ( n = 0; n < face->num_charmaps; n++ ) 00844 { 00845 FT_CMap cmap = FT_CMAP( face->charmaps[n] ); 00846 00847 00848 ft_cmap_done_internal( cmap ); 00849 00850 face->charmaps[n] = NULL; 00851 } 00852 00853 FT_FREE( face->charmaps ); 00854 face->num_charmaps = 0; 00855 } 00856 00857 00858 /* destructor for faces list */ 00859 static void 00860 destroy_face( FT_Memory memory, 00861 FT_Face face, 00862 FT_Driver driver ) 00863 { 00864 FT_Driver_Class clazz = driver->clazz; 00865 00866 00867 /* discard auto-hinting data */ 00868 if ( face->autohint.finalizer ) 00869 face->autohint.finalizer( face->autohint.data ); 00870 00871 /* Discard glyph slots for this face. */ 00872 /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */ 00873 while ( face->glyph ) 00874 FT_Done_GlyphSlot( face->glyph ); 00875 00876 /* discard all sizes for this face */ 00877 FT_List_Finalize( &face->sizes_list, 00878 (FT_List_Destructor)destroy_size, 00879 memory, 00880 driver ); 00881 face->size = 0; 00882 00883 /* now discard client data */ 00884 if ( face->generic.finalizer ) 00885 face->generic.finalizer( face ); 00886 00887 /* discard charmaps */ 00888 destroy_charmaps( face, memory ); 00889 00890 /* finalize format-specific stuff */ 00891 if ( clazz->done_face ) 00892 clazz->done_face( face ); 00893 00894 /* close the stream for this face if needed */ 00895 FT_Stream_Free( 00896 face->stream, 00897 ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 ); 00898 00899 face->stream = 0; 00900 00901 /* get rid of it */ 00902 if ( face->internal ) 00903 { 00904 FT_FREE( face->internal ); 00905 } 00906 FT_FREE( face ); 00907 } 00908 00909 00910 static void 00911 Destroy_Driver( FT_Driver driver ) 00912 { 00913 FT_List_Finalize( &driver->faces_list, 00914 (FT_List_Destructor)destroy_face, 00915 driver->root.memory, 00916 driver ); 00917 00918 /* check whether we need to drop the driver's glyph loader */ 00919 if ( FT_DRIVER_USES_OUTLINES( driver ) ) 00920 FT_GlyphLoader_Done( driver->glyph_loader ); 00921 } 00922 00923 00924 /*************************************************************************/ 00925 /* */ 00926 /* <Function> */ 00927 /* find_unicode_charmap */ 00928 /* */ 00929 /* <Description> */ 00930 /* This function finds a Unicode charmap, if there is one. */ 00931 /* And if there is more than one, it tries to favour the more */ 00932 /* extensive one, i.e., one that supports UCS-4 against those which */ 00933 /* are limited to the BMP (said UCS-2 encoding.) */ 00934 /* */ 00935 /* This function is called from open_face() (just below), and also */ 00936 /* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ). */ 00937 /* */ 00938 static FT_Error 00939 find_unicode_charmap( FT_Face face ) 00940 { 00941 FT_CharMap* first; 00942 FT_CharMap* cur; 00943 00944 00945 /* caller should have already checked that `face' is valid */ 00946 FT_ASSERT( face ); 00947 00948 first = face->charmaps; 00949 00950 if ( !first ) 00951 return FT_Err_Invalid_CharMap_Handle; 00952 00953 /* 00954 * The original TrueType specification(s) only specified charmap 00955 * formats that are capable of mapping 8 or 16 bit character codes to 00956 * glyph indices. 00957 * 00958 * However, recent updates to the Apple and OpenType specifications 00959 * introduced new formats that are capable of mapping 32-bit character 00960 * codes as well. And these are already used on some fonts, mainly to 00961 * map non-BMP Asian ideographs as defined in Unicode. 00962 * 00963 * For compatibility purposes, these fonts generally come with 00964 * *several* Unicode charmaps: 00965 * 00966 * - One of them in the "old" 16-bit format, that cannot access 00967 * all glyphs in the font. 00968 * 00969 * - Another one in the "new" 32-bit format, that can access all 00970 * the glyphs. 00971 * 00972 * This function has been written to always favor a 32-bit charmap 00973 * when found. Otherwise, a 16-bit one is returned when found. 00974 */ 00975 00976 /* Since the `interesting' table, with IDs (3,10), is normally the */ 00977 /* last one, we loop backwards. This loses with type1 fonts with */ 00978 /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP */ 00979 /* chars (.01% ?), and this is the same about 99.99% of the time! */ 00980 00981 cur = first + face->num_charmaps; /* points after the last one */ 00982 00983 for ( ; --cur >= first; ) 00984 { 00985 if ( cur[0]->encoding == FT_ENCODING_UNICODE ) 00986 { 00987 /* XXX If some new encodings to represent UCS-4 are added, */ 00988 /* they should be added here. */ 00989 if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT && 00990 cur[0]->encoding_id == TT_MS_ID_UCS_4 ) || 00991 ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE && 00992 cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) ) 00993 { 00994 #ifdef FT_MAX_CHARMAP_CACHEABLE 00995 if ( cur - first > FT_MAX_CHARMAP_CACHEABLE ) 00996 { 00997 FT_ERROR(( "find_unicode_charmap: UCS-4 cmap is found " 00998 "at too late position (%d)\n", cur - first )); 00999 continue; 01000 } 01001 #endif 01002 face->charmap = cur[0]; 01003 return FT_Err_Ok; 01004 } 01005 } 01006 } 01007 01008 /* We do not have any UCS-4 charmap. */ 01009 /* Do the loop again and search for UCS-2 charmaps. */ 01010 cur = first + face->num_charmaps; 01011 01012 for ( ; --cur >= first; ) 01013 { 01014 if ( cur[0]->encoding == FT_ENCODING_UNICODE ) 01015 { 01016 #ifdef FT_MAX_CHARMAP_CACHEABLE 01017 if ( cur - first > FT_MAX_CHARMAP_CACHEABLE ) 01018 { 01019 FT_ERROR(( "find_unicode_charmap: UCS-2 cmap is found " 01020 "at too late position (%d)\n", cur - first )); 01021 continue; 01022 } 01023 #endif 01024 face->charmap = cur[0]; 01025 return FT_Err_Ok; 01026 } 01027 } 01028 01029 return FT_Err_Invalid_CharMap_Handle; 01030 } 01031 01032 01033 /*************************************************************************/ 01034 /* */ 01035 /* <Function> */ 01036 /* find_variant_selector_charmap */ 01037 /* */ 01038 /* <Description> */ 01039 /* This function finds the variant selector charmap, if there is one. */ 01040 /* There can only be one (platform=0, specific=5, format=14). */ 01041 /* */ 01042 static FT_CharMap 01043 find_variant_selector_charmap( FT_Face face ) 01044 { 01045 FT_CharMap* first; 01046 FT_CharMap* end; 01047 FT_CharMap* cur; 01048 01049 01050 /* caller should have already checked that `face' is valid */ 01051 FT_ASSERT( face ); 01052 01053 first = face->charmaps; 01054 01055 if ( !first ) 01056 return NULL; 01057 01058 end = first + face->num_charmaps; /* points after the last one */ 01059 01060 for ( cur = first; cur < end; ++cur ) 01061 { 01062 if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE && 01063 cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR && 01064 FT_Get_CMap_Format( cur[0] ) == 14 ) 01065 { 01066 #ifdef FT_MAX_CHARMAP_CACHEABLE 01067 if ( cur - first > FT_MAX_CHARMAP_CACHEABLE ) 01068 { 01069 FT_ERROR(( "find_unicode_charmap: UVS cmap is found " 01070 "at too late position (%d)\n", cur - first )); 01071 continue; 01072 } 01073 #endif 01074 return cur[0]; 01075 } 01076 } 01077 01078 return NULL; 01079 } 01080 01081 01082 /*************************************************************************/ 01083 /* */ 01084 /* <Function> */ 01085 /* open_face */ 01086 /* */ 01087 /* <Description> */ 01088 /* This function does some work for FT_Open_Face(). */ 01089 /* */ 01090 static FT_Error 01091 open_face( FT_Driver driver, 01092 FT_Stream stream, 01093 FT_Long face_index, 01094 FT_Int num_params, 01095 FT_Parameter* params, 01096 FT_Face *aface ) 01097 { 01098 FT_Memory memory; 01099 FT_Driver_Class clazz; 01100 FT_Face face = 0; 01101 FT_Error error, error2; 01102 FT_Face_Internal internal = NULL; 01103 01104 01105 clazz = driver->clazz; 01106 memory = driver->root.memory; 01107 01108 /* allocate the face object and perform basic initialization */ 01109 if ( FT_ALLOC( face, clazz->face_object_size ) ) 01110 goto Fail; 01111 01112 if ( FT_NEW( internal ) ) 01113 goto Fail; 01114 01115 face->internal = internal; 01116 01117 face->driver = driver; 01118 face->memory = memory; 01119 face->stream = stream; 01120 01121 #ifdef FT_CONFIG_OPTION_INCREMENTAL 01122 { 01123 int i; 01124 01125 01126 face->internal->incremental_interface = 0; 01127 for ( i = 0; i < num_params && !face->internal->incremental_interface; 01128 i++ ) 01129 if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL ) 01130 face->internal->incremental_interface = 01131 (FT_Incremental_Interface)params[i].data; 01132 } 01133 #endif 01134 01135 if ( clazz->init_face ) 01136 error = clazz->init_face( stream, 01137 face, 01138 (FT_Int)face_index, 01139 num_params, 01140 params ); 01141 if ( error ) 01142 goto Fail; 01143 01144 /* select Unicode charmap by default */ 01145 error2 = find_unicode_charmap( face ); 01146 01147 /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */ 01148 /* is returned. */ 01149 01150 /* no error should happen, but we want to play safe */ 01151 if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle ) 01152 { 01153 error = error2; 01154 goto Fail; 01155 } 01156 01157 *aface = face; 01158 01159 Fail: 01160 if ( error ) 01161 { 01162 destroy_charmaps( face, memory ); 01163 if ( clazz->done_face ) 01164 clazz->done_face( face ); 01165 FT_FREE( internal ); 01166 FT_FREE( face ); 01167 *aface = 0; 01168 } 01169 01170 return error; 01171 } 01172 01173 01174 /* there's a Mac-specific extended implementation of FT_New_Face() */ 01175 /* in src/base/ftmac.c */ 01176 01177 #if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON ) 01178 01179 /* documentation is in freetype.h */ 01180 01181 FT_EXPORT_DEF( FT_Error ) 01182 FT_New_Face( FT_Library library, 01183 const char* pathname, 01184 FT_Long face_index, 01185 FT_Face *aface ) 01186 { 01187 FT_Open_Args args; 01188 01189 01190 /* test for valid `library' and `aface' delayed to FT_Open_Face() */ 01191 if ( !pathname ) 01192 return FT_Err_Invalid_Argument; 01193 01194 args.flags = FT_OPEN_PATHNAME; 01195 args.pathname = (char*)pathname; 01196 args.stream = NULL; 01197 01198 return FT_Open_Face( library, &args, face_index, aface ); 01199 } 01200 01201 #endif /* defined( FT_MACINTOSH ) && !defined( DARWIN_NO_CARBON ) */ 01202 01203 01204 /* documentation is in freetype.h */ 01205 01206 FT_EXPORT_DEF( FT_Error ) 01207 FT_New_Memory_Face( FT_Library library, 01208 const FT_Byte* file_base, 01209 FT_Long file_size, 01210 FT_Long face_index, 01211 FT_Face *aface ) 01212 { 01213 FT_Open_Args args; 01214 01215 01216 /* test for valid `library' and `face' delayed to FT_Open_Face() */ 01217 if ( !file_base ) 01218 return FT_Err_Invalid_Argument; 01219 01220 args.flags = FT_OPEN_MEMORY; 01221 args.memory_base = file_base; 01222 args.memory_size = file_size; 01223 args.stream = NULL; 01224 01225 return FT_Open_Face( library, &args, face_index, aface ); 01226 } 01227 01228 01229 #ifdef FT_CONFIG_OPTION_MAC_FONTS 01230 01231 /* The behavior here is very similar to that in base/ftmac.c, but it */ 01232 /* is designed to work on non-mac systems, so no mac specific calls. */ 01233 /* */ 01234 /* We look at the file and determine if it is a mac dfont file or a mac */ 01235 /* resource file, or a macbinary file containing a mac resource file. */ 01236 /* */ 01237 /* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */ 01238 /* the point, especially since there may be multiple `FOND' resources. */ 01239 /* Instead I'll just look for `sfnt' and `POST' resources, ordered as */ 01240 /* they occur in the file. */ 01241 /* */ 01242 /* Note that multiple `POST' resources do not mean multiple postscript */ 01243 /* fonts; they all get jammed together to make what is essentially a */ 01244 /* pfb file. */ 01245 /* */ 01246 /* We aren't interested in `NFNT' or `FONT' bitmap resources. */ 01247 /* */ 01248 /* As soon as we get an `sfnt' load it into memory and pass it off to */ 01249 /* FT_Open_Face. */ 01250 /* */ 01251 /* If we have a (set of) `POST' resources, massage them into a (memory) */ 01252 /* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */ 01253 /* going to try to save the kerning info. After all that lives in the */ 01254 /* `FOND' which isn't in the file containing the `POST' resources so */ 01255 /* we don't really have access to it. */ 01256 01257 01258 /* Finalizer for a memory stream; gets called by FT_Done_Face(). */ 01259 /* It frees the memory it uses. */ 01260 /* From ftmac.c. */ 01261 static void 01262 memory_stream_close( FT_Stream stream ) 01263 { 01264 FT_Memory memory = stream->memory; 01265 01266 01267 FT_FREE( stream->base ); 01268 01269 stream->size = 0; 01270 stream->base = 0; 01271 stream->close = 0; 01272 } 01273 01274 01275 /* Create a new memory stream from a buffer and a size. */ 01276 /* From ftmac.c. */ 01277 static FT_Error 01278 new_memory_stream( FT_Library library, 01279 FT_Byte* base, 01280 FT_ULong size, 01281 FT_Stream_CloseFunc close, 01282 FT_Stream *astream ) 01283 { 01284 FT_Error error; 01285 FT_Memory memory; 01286 FT_Stream stream; 01287 01288 01289 if ( !library ) 01290 return FT_Err_Invalid_Library_Handle; 01291 01292 if ( !base ) 01293 return FT_Err_Invalid_Argument; 01294 01295 *astream = 0; 01296 memory = library->memory; 01297 if ( FT_NEW( stream ) ) 01298 goto Exit; 01299 01300 FT_Stream_OpenMemory( stream, base, size ); 01301 01302 stream->close = close; 01303 01304 *astream = stream; 01305 01306 Exit: 01307 return error; 01308 } 01309 01310 01311 /* Create a new FT_Face given a buffer and a driver name. */ 01312 /* from ftmac.c */ 01313 FT_LOCAL_DEF( FT_Error ) 01314 open_face_from_buffer( FT_Library library, 01315 FT_Byte* base, 01316 FT_ULong size, 01317 FT_Long face_index, 01318 const char* driver_name, 01319 FT_Face *aface ) 01320 { 01321 FT_Open_Args args; 01322 FT_Error error; 01323 FT_Stream stream = NULL; 01324 FT_Memory memory = library->memory; 01325 01326 01327 error = new_memory_stream( library, 01328 base, 01329 size, 01330 memory_stream_close, 01331 &stream ); 01332 if ( error ) 01333 { 01334 FT_FREE( base ); 01335 return error; 01336 } 01337 01338 args.flags = FT_OPEN_STREAM; 01339 args.stream = stream; 01340 if ( driver_name ) 01341 { 01342 args.flags = args.flags | FT_OPEN_DRIVER; 01343 args.driver = FT_Get_Module( library, driver_name ); 01344 } 01345 01346 #ifdef FT_MACINTOSH 01347 /* At this point, face_index has served its purpose; */ 01348 /* whoever calls this function has already used it to */ 01349 /* locate the correct font data. We should not propagate */ 01350 /* this index to FT_Open_Face() (unless it is negative). */ 01351 01352 if ( face_index > 0 ) 01353 face_index = 0; 01354 #endif 01355 01356 error = FT_Open_Face( library, &args, face_index, aface ); 01357 01358 if ( error == FT_Err_Ok ) 01359 (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; 01360 else 01361 #ifdef FT_MACINTOSH 01362 FT_Stream_Free( stream, 0 ); 01363 #else 01364 { 01365 FT_Stream_Close( stream ); 01366 FT_FREE( stream ); 01367 } 01368 #endif 01369 01370 return error; 01371 } 01372 01373 01374 /* Look up `TYP1' or `CID ' table from sfnt table directory. */ 01375 /* `offset' and `length' must exclude the binary header in tables. */ 01376 01377 /* Type 1 and CID-keyed font drivers should recognize sfnt-wrapped */ 01378 /* format too. Here, since we can't expect that the TrueType font */ 01379 /* driver is loaded unconditially, we must parse the font by */ 01380 /* ourselves. We are only interested in the name of the table and */ 01381 /* the offset. */ 01382 01383 static FT_Error 01384 ft_lookup_PS_in_sfnt_stream( FT_Stream stream, 01385 FT_Long face_index, 01386 FT_ULong* offset, 01387 FT_ULong* length, 01388 FT_Bool* is_sfnt_cid ) 01389 { 01390 FT_Error error; 01391 FT_UShort numTables; 01392 FT_Long pstable_index; 01393 FT_ULong tag; 01394 int i; 01395 01396 01397 *offset = 0; 01398 *length = 0; 01399 *is_sfnt_cid = FALSE; 01400 01401 /* TODO: support for sfnt-wrapped PS/CID in TTC format */ 01402 01403 /* version check for 'typ1' (should be ignored?) */ 01404 if ( FT_READ_ULONG( tag ) ) 01405 return error; 01406 if ( tag != TTAG_typ1 ) 01407 return FT_Err_Unknown_File_Format; 01408 01409 if ( FT_READ_USHORT( numTables ) ) 01410 return error; 01411 if ( FT_STREAM_SKIP( 2 * 3 ) ) /* skip binary search header */ 01412 return error; 01413 01414 pstable_index = -1; 01415 *is_sfnt_cid = FALSE; 01416 01417 for ( i = 0; i < numTables; i++ ) 01418 { 01419 if ( FT_READ_ULONG( tag ) || FT_STREAM_SKIP( 4 ) || 01420 FT_READ_ULONG( *offset ) || FT_READ_ULONG( *length ) ) 01421 return error; 01422 01423 if ( tag == TTAG_CID ) 01424 { 01425 pstable_index++; 01426 *offset += 22; 01427 *length -= 22; 01428 *is_sfnt_cid = TRUE; 01429 if ( face_index < 0 ) 01430 return FT_Err_Ok; 01431 } 01432 else if ( tag == TTAG_TYP1 ) 01433 { 01434 pstable_index++; 01435 *offset += 24; 01436 *length -= 24; 01437 *is_sfnt_cid = FALSE; 01438 if ( face_index < 0 ) 01439 return FT_Err_Ok; 01440 } 01441 if ( face_index >= 0 && pstable_index == face_index ) 01442 return FT_Err_Ok; 01443 } 01444 return FT_Err_Table_Missing; 01445 } 01446 01447 01448 FT_LOCAL_DEF( FT_Error ) 01449 open_face_PS_from_sfnt_stream( FT_Library library, 01450 FT_Stream stream, 01451 FT_Long face_index, 01452 FT_Int num_params, 01453 FT_Parameter *params, 01454 FT_Face *aface ) 01455 { 01456 FT_Error error; 01457 FT_Memory memory = library->memory; 01458 FT_ULong offset, length; 01459 FT_Long pos; 01460 FT_Bool is_sfnt_cid; 01461 FT_Byte* sfnt_ps; 01462 01463 FT_UNUSED( num_params ); 01464 FT_UNUSED( params ); 01465 01466 01467 pos = FT_Stream_Pos( stream ); 01468 01469 error = ft_lookup_PS_in_sfnt_stream( stream, 01470 face_index, 01471 &offset, 01472 &length, 01473 &is_sfnt_cid ); 01474 if ( error ) 01475 goto Exit; 01476 01477 if ( FT_Stream_Seek( stream, pos + offset ) ) 01478 goto Exit; 01479 01480 if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) ) 01481 goto Exit; 01482 01483 error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length ); 01484 if ( error ) 01485 goto Exit; 01486 01487 error = open_face_from_buffer( library, 01488 sfnt_ps, 01489 length, 01490 face_index < 0 ? face_index : 0, 01491 is_sfnt_cid ? "cid" : "type1", 01492 aface ); 01493 Exit: 01494 { 01495 FT_Error error1; 01496 01497 01498 if ( error == FT_Err_Unknown_File_Format ) 01499 { 01500 error1 = FT_Stream_Seek( stream, pos ); 01501 if ( error1 ) 01502 return error1; 01503 } 01504 01505 return error; 01506 } 01507 } 01508 01509 01510 #if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON ) 01511 01512 /* The resource header says we've got resource_cnt `POST' (type1) */ 01513 /* resources in this file. They all need to be coalesced into */ 01514 /* one lump which gets passed on to the type1 driver. */ 01515 /* Here can be only one PostScript font in a file so face_index */ 01516 /* must be 0 (or -1). */ 01517 /* */ 01518 static FT_Error 01519 Mac_Read_POST_Resource( FT_Library library, 01520 FT_Stream stream, 01521 FT_Long *offsets, 01522 FT_Long resource_cnt, 01523 FT_Long face_index, 01524 FT_Face *aface ) 01525 { 01526 FT_Error error = FT_Err_Cannot_Open_Resource; 01527 FT_Memory memory = library->memory; 01528 FT_Byte* pfb_data; 01529 int i, type, flags; 01530 FT_Long len; 01531 FT_Long pfb_len, pfb_pos, pfb_lenpos; 01532 FT_Long rlen, temp; 01533 01534 01535 if ( face_index == -1 ) 01536 face_index = 0; 01537 if ( face_index != 0 ) 01538 return error; 01539 01540 /* Find the length of all the POST resources, concatenated. Assume */ 01541 /* worst case (each resource in its own section). */ 01542 pfb_len = 0; 01543 for ( i = 0; i < resource_cnt; ++i ) 01544 { 01545 error = FT_Stream_Seek( stream, offsets[i] ); 01546 if ( error ) 01547 goto Exit; 01548 if ( FT_READ_LONG( temp ) ) 01549 goto Exit; 01550 pfb_len += temp + 6; 01551 } 01552 01553 if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) ) 01554 goto Exit; 01555 01556 pfb_data[0] = 0x80; 01557 pfb_data[1] = 1; /* Ascii section */ 01558 pfb_data[2] = 0; /* 4-byte length, fill in later */ 01559 pfb_data[3] = 0; 01560 pfb_data[4] = 0; 01561 pfb_data[5] = 0; 01562 pfb_pos = 6; 01563 pfb_lenpos = 2; 01564 01565 len = 0; 01566 type = 1; 01567 for ( i = 0; i < resource_cnt; ++i ) 01568 { 01569 error = FT_Stream_Seek( stream, offsets[i] ); 01570 if ( error ) 01571 goto Exit2; 01572 if ( FT_READ_LONG( rlen ) ) 01573 goto Exit; 01574 if ( FT_READ_USHORT( flags ) ) 01575 goto Exit; 01576 FT_TRACE3(( "POST fragment[%d]: offsets=0x%08x, rlen=0x%08x, flags=0x%04x\n", 01577 i, offsets[i], rlen, flags )); 01578 01579 /* postpone the check of rlen longer than buffer until FT_Stream_Read() */ 01580 if ( ( flags >> 8 ) == 0 ) /* Comment, should not be loaded */ 01581 continue; 01582 01583 /* the flags are part of the resource, so rlen >= 2. */ 01584 /* but some fonts declare rlen = 0 for empty fragment */ 01585 if ( rlen > 2 ) 01586 rlen -= 2; 01587 else 01588 rlen = 0; 01589 01590 if ( ( flags >> 8 ) == type ) 01591 len += rlen; 01592 else 01593 { 01594 if ( pfb_lenpos + 3 > pfb_len + 2 ) 01595 goto Exit2; 01596 pfb_data[pfb_lenpos ] = (FT_Byte)( len ); 01597 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 ); 01598 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 ); 01599 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 ); 01600 01601 if ( ( flags >> 8 ) == 5 ) /* End of font mark */ 01602 break; 01603 01604 if ( pfb_pos + 6 > pfb_len + 2 ) 01605 goto Exit2; 01606 pfb_data[pfb_pos++] = 0x80; 01607 01608 type = flags >> 8; 01609 len = rlen; 01610 01611 pfb_data[pfb_pos++] = (FT_Byte)type; 01612 pfb_lenpos = pfb_pos; 01613 pfb_data[pfb_pos++] = 0; /* 4-byte length, fill in later */ 01614 pfb_data[pfb_pos++] = 0; 01615 pfb_data[pfb_pos++] = 0; 01616 pfb_data[pfb_pos++] = 0; 01617 } 01618 01619 error = FT_Err_Cannot_Open_Resource; 01620 if ( pfb_pos > pfb_len || pfb_pos + rlen > pfb_len ) 01621 goto Exit2; 01622 01623 error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen ); 01624 if ( error ) 01625 goto Exit2; 01626 pfb_pos += rlen; 01627 } 01628 01629 if ( pfb_pos + 2 > pfb_len + 2 ) 01630 goto Exit2; 01631 pfb_data[pfb_pos++] = 0x80; 01632 pfb_data[pfb_pos++] = 3; 01633 01634 if ( pfb_lenpos + 3 > pfb_len + 2 ) 01635 goto Exit2; 01636 pfb_data[pfb_lenpos ] = (FT_Byte)( len ); 01637 pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 ); 01638 pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 ); 01639 pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 ); 01640 01641 return open_face_from_buffer( library, 01642 pfb_data, 01643 pfb_pos, 01644 face_index, 01645 "type1", 01646 aface ); 01647 01648 Exit2: 01649 FT_FREE( pfb_data ); 01650 01651 Exit: 01652 return error; 01653 } 01654 01655 01656 /* The resource header says we've got resource_cnt `sfnt' */ 01657 /* (TrueType/OpenType) resources in this file. Look through */ 01658 /* them for the one indicated by face_index, load it into mem, */ 01659 /* pass it on the the truetype driver and return it. */ 01660 /* */ 01661 static FT_Error 01662 Mac_Read_sfnt_Resource( FT_Library library, 01663 FT_Stream stream, 01664 FT_Long *offsets, 01665 FT_Long resource_cnt, 01666 FT_Long face_index, 01667 FT_Face *aface ) 01668 { 01669 FT_Memory memory = library->memory; 01670 FT_Byte* sfnt_data; 01671 FT_Error error; 01672 FT_Long flag_offset; 01673 FT_Long rlen; 01674 int is_cff; 01675 FT_Long face_index_in_resource = 0; 01676 01677 01678 if ( face_index == -1 ) 01679 face_index = 0; 01680 if ( face_index >= resource_cnt ) 01681 return FT_Err_Cannot_Open_Resource; 01682 01683 flag_offset = offsets[face_index]; 01684 error = FT_Stream_Seek( stream, flag_offset ); 01685 if ( error ) 01686 goto Exit; 01687 01688 if ( FT_READ_LONG( rlen ) ) 01689 goto Exit; 01690 if ( rlen == -1 ) 01691 return FT_Err_Cannot_Open_Resource; 01692 01693 error = open_face_PS_from_sfnt_stream( library, 01694 stream, 01695 face_index, 01696 0, NULL, 01697 aface ); 01698 if ( !error ) 01699 goto Exit; 01700 01701 /* rewind sfnt stream before open_face_PS_from_sfnt_stream() */ 01702 if ( FT_Stream_Seek( stream, flag_offset + 4 ) ) 01703 goto Exit; 01704 01705 if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) ) 01706 return error; 01707 error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen ); 01708 if ( error ) 01709 goto Exit; 01710 01711 is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 ); 01712 error = open_face_from_buffer( library, 01713 sfnt_data, 01714 rlen, 01715 face_index_in_resource, 01716 is_cff ? "cff" : "truetype", 01717 aface ); 01718 01719 Exit: 01720 return error; 01721 } 01722 01723 01724 /* Check for a valid resource fork header, or a valid dfont */ 01725 /* header. In a resource fork the first 16 bytes are repeated */ 01726 /* at the location specified by bytes 4-7. In a dfont bytes */ 01727 /* 4-7 point to 16 bytes of zeroes instead. */ 01728 /* */ 01729 static FT_Error 01730 IsMacResource( FT_Library library, 01731 FT_Stream stream, 01732 FT_Long resource_offset, 01733 FT_Long face_index, 01734 FT_Face *aface ) 01735 { 01736 FT_Memory memory = library->memory; 01737 FT_Error error; 01738 FT_Long map_offset, rdara_pos; 01739 FT_Long *data_offsets; 01740 FT_Long count; 01741 01742 01743 error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset, 01744 &map_offset, &rdara_pos ); 01745 if ( error ) 01746 return error; 01747 01748 error = FT_Raccess_Get_DataOffsets( library, stream, 01749 map_offset, rdara_pos, 01750 TTAG_POST, 01751 &data_offsets, &count ); 01752 if ( !error ) 01753 { 01754 error = Mac_Read_POST_Resource( library, stream, data_offsets, count, 01755 face_index, aface ); 01756 FT_FREE( data_offsets ); 01757 /* POST exists in an LWFN providing a single face */ 01758 if ( !error ) 01759 (*aface)->num_faces = 1; 01760 return error; 01761 } 01762 01763 error = FT_Raccess_Get_DataOffsets( library, stream, 01764 map_offset, rdara_pos, 01765 TTAG_sfnt, 01766 &data_offsets, &count ); 01767 if ( !error ) 01768 { 01769 FT_Long face_index_internal = face_index % count; 01770 01771 01772 error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count, 01773 face_index_internal, aface ); 01774 FT_FREE( data_offsets ); 01775 if ( !error ) 01776 (*aface)->num_faces = count; 01777 } 01778 01779 return error; 01780 } 01781 01782 01783 /* Check for a valid macbinary header, and if we find one */ 01784 /* check that the (flattened) resource fork in it is valid. */ 01785 /* */ 01786 static FT_Error 01787 IsMacBinary( FT_Library library, 01788 FT_Stream stream, 01789 FT_Long face_index, 01790 FT_Face *aface ) 01791 { 01792 unsigned char header[128]; 01793 FT_Error error; 01794 FT_Long dlen, offset; 01795 01796 01797 if ( NULL == stream ) 01798 return FT_Err_Invalid_Stream_Operation; 01799 01800 error = FT_Stream_Seek( stream, 0 ); 01801 if ( error ) 01802 goto Exit; 01803 01804 error = FT_Stream_Read( stream, (FT_Byte*)header, 128 ); 01805 if ( error ) 01806 goto Exit; 01807 01808 if ( header[ 0] != 0 || 01809 header[74] != 0 || 01810 header[82] != 0 || 01811 header[ 1] == 0 || 01812 header[ 1] > 33 || 01813 header[63] != 0 || 01814 header[2 + header[1]] != 0 ) 01815 return FT_Err_Unknown_File_Format; 01816 01817 dlen = ( header[0x53] << 24 ) | 01818 ( header[0x54] << 16 ) | 01819 ( header[0x55] << 8 ) | 01820 header[0x56]; 01821 #if 0 01822 rlen = ( header[0x57] << 24 ) | 01823 ( header[0x58] << 16 ) | 01824 ( header[0x59] << 8 ) | 01825 header[0x5a]; 01826 #endif /* 0 */ 01827 offset = 128 + ( ( dlen + 127 ) & ~127 ); 01828 01829 return IsMacResource( library, stream, offset, face_index, aface ); 01830 01831 Exit: 01832 return error; 01833 } 01834 01835 01836 static FT_Error 01837 load_face_in_embedded_rfork( FT_Library library, 01838 FT_Stream stream, 01839 FT_Long face_index, 01840 FT_Face *aface, 01841 const FT_Open_Args *args ) 01842 { 01843 01844 #undef FT_COMPONENT 01845 #define FT_COMPONENT trace_raccess 01846 01847 FT_Memory memory = library->memory; 01848 FT_Error error = FT_Err_Unknown_File_Format; 01849 int i; 01850 01851 char * file_names[FT_RACCESS_N_RULES]; 01852 FT_Long offsets[FT_RACCESS_N_RULES]; 01853 FT_Error errors[FT_RACCESS_N_RULES]; 01854 FT_Bool is_darwin_vfs, vfs_rfork_has_no_font = FALSE; /* not tested */ 01855 01856 FT_Open_Args args2; 01857 FT_Stream stream2 = 0; 01858 01859 01860 FT_Raccess_Guess( library, stream, 01861 args->pathname, file_names, offsets, errors ); 01862 01863 for ( i = 0; i < FT_RACCESS_N_RULES; i++ ) 01864 { 01865 is_darwin_vfs = raccess_rule_by_darwin_vfs( i ); 01866 if ( is_darwin_vfs && vfs_rfork_has_no_font ) 01867 { 01868 FT_TRACE3(( "Skip rule %d: darwin vfs resource fork" 01869 " is already checked and" 01870 " no font is found\n", i )); 01871 continue; 01872 } 01873 01874 if ( errors[i] ) 01875 { 01876 FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i )); 01877 continue; 01878 } 01879 01880 args2.flags = FT_OPEN_PATHNAME; 01881 args2.pathname = file_names[i] ? file_names[i] : args->pathname; 01882 01883 FT_TRACE3(( "Try rule %d: %s (offset=%d) ...", 01884 i, args2.pathname, offsets[i] )); 01885 01886 error = FT_Stream_New( library, &args2, &stream2 ); 01887 if ( is_darwin_vfs && error == FT_Err_Cannot_Open_Stream ) 01888 vfs_rfork_has_no_font = TRUE; 01889 01890 if ( error ) 01891 { 01892 FT_TRACE3(( "failed\n" )); 01893 continue; 01894 } 01895 01896 error = IsMacResource( library, stream2, offsets[i], 01897 face_index, aface ); 01898 FT_Stream_Free( stream2, 0 ); 01899 01900 FT_TRACE3(( "%s\n", error ? "failed": "successful" )); 01901 01902 if ( !error ) 01903 break; 01904 else if ( is_darwin_vfs ) 01905 vfs_rfork_has_no_font = TRUE; 01906 } 01907 01908 for (i = 0; i < FT_RACCESS_N_RULES; i++) 01909 { 01910 if ( file_names[i] ) 01911 FT_FREE( file_names[i] ); 01912 } 01913 01914 /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */ 01915 if ( error ) 01916 error = FT_Err_Unknown_File_Format; 01917 01918 return error; 01919 01920 #undef FT_COMPONENT 01921 #define FT_COMPONENT trace_objs 01922 01923 } 01924 01925 01926 /* Check for some macintosh formats without Carbon framework. */ 01927 /* Is this a macbinary file? If so look at the resource fork. */ 01928 /* Is this a mac dfont file? */ 01929 /* Is this an old style resource fork? (in data) */ 01930 /* Else call load_face_in_embedded_rfork to try extra rules */ 01931 /* (defined in `ftrfork.c'). */ 01932 /* */ 01933 static FT_Error 01934 load_mac_face( FT_Library library, 01935 FT_Stream stream, 01936 FT_Long face_index, 01937 FT_Face *aface, 01938 const FT_Open_Args *args ) 01939 { 01940 FT_Error error; 01941 FT_UNUSED( args ); 01942 01943 01944 error = IsMacBinary( library, stream, face_index, aface ); 01945 if ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format ) 01946 { 01947 01948 #undef FT_COMPONENT 01949 #define FT_COMPONENT trace_raccess 01950 01951 FT_TRACE3(( "Try as dfont: %s ...", args->pathname )); 01952 01953 error = IsMacResource( library, stream, 0, face_index, aface ); 01954 01955 FT_TRACE3(( "%s\n", error ? "failed" : "successful" )); 01956 01957 #undef FT_COMPONENT 01958 #define FT_COMPONENT trace_objs 01959 01960 } 01961 01962 if ( ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format || 01963 FT_ERROR_BASE( error ) == FT_Err_Invalid_Stream_Operation ) && 01964 ( args->flags & FT_OPEN_PATHNAME ) ) 01965 error = load_face_in_embedded_rfork( library, stream, 01966 face_index, aface, args ); 01967 return error; 01968 } 01969 #endif 01970 01971 #endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */ 01972 01973 01974 /* documentation is in freetype.h */ 01975 01976 FT_EXPORT_DEF( FT_Error ) 01977 FT_Open_Face( FT_Library library, 01978 const FT_Open_Args* args, 01979 FT_Long face_index, 01980 FT_Face *aface ) 01981 { 01982 FT_Error error; 01983 FT_Driver driver; 01984 FT_Memory memory; 01985 FT_Stream stream = NULL; 01986 FT_Face face = NULL; 01987 FT_ListNode node = NULL; 01988 FT_Bool external_stream; 01989 FT_Module* cur; 01990 FT_Module* limit; 01991 01992 01993 /* test for valid `library' delayed to */ 01994 /* FT_Stream_New() */ 01995 01996 if ( ( !aface && face_index >= 0 ) || !args ) 01997 return FT_Err_Invalid_Argument; 01998 01999 external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) && 02000 args->stream ); 02001 02002 /* create input stream */ 02003 error = FT_Stream_New( library, args, &stream ); 02004 if ( error ) 02005 goto Fail3; 02006 02007 memory = library->memory; 02008 02009 /* If the font driver is specified in the `args' structure, use */ 02010 /* it. Otherwise, we scan the list of registered drivers. */ 02011 if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver ) 02012 { 02013 driver = FT_DRIVER( args->driver ); 02014 02015 /* not all modules are drivers, so check... */ 02016 if ( FT_MODULE_IS_DRIVER( driver ) ) 02017 { 02018 FT_Int num_params = 0; 02019 FT_Parameter* params = 0; 02020 02021 02022 if ( args->flags & FT_OPEN_PARAMS ) 02023 { 02024 num_params = args->num_params; 02025 params = args->params; 02026 } 02027 02028 error = open_face( driver, stream, face_index, 02029 num_params, params, &face ); 02030 if ( !error ) 02031 goto Success; 02032 } 02033 else 02034 error = FT_Err_Invalid_Handle; 02035 02036 FT_Stream_Free( stream, external_stream ); 02037 goto Fail; 02038 } 02039 else 02040 { 02041 /* check each font driver for an appropriate format */ 02042 cur = library->modules; 02043 limit = cur + library->num_modules; 02044 02045 02046 for ( ; cur < limit; cur++ ) 02047 { 02048 /* not all modules are font drivers, so check... */ 02049 if ( FT_MODULE_IS_DRIVER( cur[0] ) ) 02050 { 02051 FT_Int num_params = 0; 02052 FT_Parameter* params = 0; 02053 02054 02055 driver = FT_DRIVER( cur[0] ); 02056 02057 if ( args->flags & FT_OPEN_PARAMS ) 02058 { 02059 num_params = args->num_params; 02060 params = args->params; 02061 } 02062 02063 error = open_face( driver, stream, face_index, 02064 num_params, params, &face ); 02065 if ( !error ) 02066 goto Success; 02067 02068 #ifdef FT_CONFIG_OPTION_MAC_FONTS 02069 if ( ft_strcmp( cur[0]->clazz->module_name, "truetype" ) == 0 && 02070 FT_ERROR_BASE( error ) == FT_Err_Table_Missing ) 02071 { 02072 /* TrueType but essential tables are missing */ 02073 if ( FT_Stream_Seek( stream, 0 ) ) 02074 break; 02075 02076 error = open_face_PS_from_sfnt_stream( library, 02077 stream, 02078 face_index, 02079 num_params, 02080 params, 02081 aface ); 02082 if ( !error ) 02083 { 02084 FT_Stream_Free( stream, external_stream ); 02085 return error; 02086 } 02087 } 02088 #endif 02089 02090 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format ) 02091 goto Fail3; 02092 } 02093 } 02094 02095 Fail3: 02096 /* If we are on the mac, and we get an FT_Err_Invalid_Stream_Operation */ 02097 /* it may be because we have an empty data fork, so we need to check */ 02098 /* the resource fork. */ 02099 if ( FT_ERROR_BASE( error ) != FT_Err_Cannot_Open_Stream && 02100 FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format && 02101 FT_ERROR_BASE( error ) != FT_Err_Invalid_Stream_Operation ) 02102 goto Fail2; 02103 02104 #if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS ) 02105 error = load_mac_face( library, stream, face_index, aface, args ); 02106 if ( !error ) 02107 { 02108 /* We don't want to go to Success here. We've already done that. */ 02109 /* On the other hand, if we succeeded we still need to close this */ 02110 /* stream (we opened a different stream which extracted the */ 02111 /* interesting information out of this stream here. That stream */ 02112 /* will still be open and the face will point to it). */ 02113 FT_Stream_Free( stream, external_stream ); 02114 return error; 02115 } 02116 02117 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format ) 02118 goto Fail2; 02119 #endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */ 02120 02121 /* no driver is able to handle this format */ 02122 error = FT_Err_Unknown_File_Format; 02123 02124 Fail2: 02125 FT_Stream_Free( stream, external_stream ); 02126 goto Fail; 02127 } 02128 02129 Success: 02130 FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" )); 02131 02132 /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */ 02133 if ( external_stream ) 02134 face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM; 02135 02136 /* add the face object to its driver's list */ 02137 if ( FT_NEW( node ) ) 02138 goto Fail; 02139 02140 node->data = face; 02141 /* don't assume driver is the same as face->driver, so use */ 02142 /* face->driver instead. */ 02143 FT_List_Add( &face->driver->faces_list, node ); 02144 02145 /* now allocate a glyph slot object for the face */ 02146 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" )); 02147 02148 if ( face_index >= 0 ) 02149 { 02150 error = FT_New_GlyphSlot( face, NULL ); 02151 if ( error ) 02152 goto Fail; 02153 02154 /* finally, allocate a size object for the face */ 02155 { 02156 FT_Size size; 02157 02158 02159 FT_TRACE4(( "FT_Open_Face: Creating size object\n" )); 02160 02161 error = FT_New_Size( face, &size ); 02162 if ( error ) 02163 goto Fail; 02164 02165 face->size = size; 02166 } 02167 } 02168 02169 /* some checks */ 02170 02171 if ( FT_IS_SCALABLE( face ) ) 02172 { 02173 if ( face->height < 0 ) 02174 face->height = (FT_Short)-face->height; 02175 02176 if ( !FT_HAS_VERTICAL( face ) ) 02177 face->max_advance_height = (FT_Short)face->height; 02178 } 02179 02180 if ( FT_HAS_FIXED_SIZES( face ) ) 02181 { 02182 FT_Int i; 02183 02184 02185 for ( i = 0; i < face->num_fixed_sizes; i++ ) 02186 { 02187 FT_Bitmap_Size* bsize = face->available_sizes + i; 02188 02189 02190 if ( bsize->height < 0 ) 02191 bsize->height = (FT_Short)-bsize->height; 02192 if ( bsize->x_ppem < 0 ) 02193 bsize->x_ppem = (FT_Short)-bsize->x_ppem; 02194 if ( bsize->y_ppem < 0 ) 02195 bsize->y_ppem = -bsize->y_ppem; 02196 } 02197 } 02198 02199 /* initialize internal face data */ 02200 { 02201 FT_Face_Internal internal = face->internal; 02202 02203 02204 internal->transform_matrix.xx = 0x10000L; 02205 internal->transform_matrix.xy = 0; 02206 internal->transform_matrix.yx = 0; 02207 internal->transform_matrix.yy = 0x10000L; 02208 02209 internal->transform_delta.x = 0; 02210 internal->transform_delta.y = 0; 02211 02212 internal->refcount = 1; 02213 } 02214 02215 if ( aface ) 02216 *aface = face; 02217 else 02218 FT_Done_Face( face ); 02219 02220 goto Exit; 02221 02222 Fail: 02223 FT_Done_Face( face ); 02224 02225 Exit: 02226 FT_TRACE4(( "FT_Open_Face: Return %d\n", error )); 02227 02228 return error; 02229 } 02230 02231 02232 /* documentation is in freetype.h */ 02233 02234 FT_EXPORT_DEF( FT_Error ) 02235 FT_Attach_File( FT_Face face, 02236 const char* filepathname ) 02237 { 02238 FT_Open_Args open; 02239 02240 02241 /* test for valid `face' delayed to FT_Attach_Stream() */ 02242 02243 if ( !filepathname ) 02244 return FT_Err_Invalid_Argument; 02245 02246 open.stream = NULL; 02247 open.flags = FT_OPEN_PATHNAME; 02248 open.pathname = (char*)filepathname; 02249 02250 return FT_Attach_Stream( face, &open ); 02251 } 02252 02253 02254 /* documentation is in freetype.h */ 02255 02256 FT_EXPORT_DEF( FT_Error ) 02257 FT_Attach_Stream( FT_Face face, 02258 FT_Open_Args* parameters ) 02259 { 02260 FT_Stream stream; 02261 FT_Error error; 02262 FT_Driver driver; 02263 02264 FT_Driver_Class clazz; 02265 02266 02267 /* test for valid `parameters' delayed to FT_Stream_New() */ 02268 02269 if ( !face ) 02270 return FT_Err_Invalid_Face_Handle; 02271 02272 driver = face->driver; 02273 if ( !driver ) 02274 return FT_Err_Invalid_Driver_Handle; 02275 02276 error = FT_Stream_New( driver->root.library, parameters, &stream ); 02277 if ( error ) 02278 goto Exit; 02279 02280 /* we implement FT_Attach_Stream in each driver through the */ 02281 /* `attach_file' interface */ 02282 02283 error = FT_Err_Unimplemented_Feature; 02284 clazz = driver->clazz; 02285 if ( clazz->attach_file ) 02286 error = clazz->attach_file( face, stream ); 02287 02288 /* close the attached stream */ 02289 FT_Stream_Free( stream, 02290 (FT_Bool)( parameters->stream && 02291 ( parameters->flags & FT_OPEN_STREAM ) ) ); 02292 02293 Exit: 02294 return error; 02295 } 02296 02297 02298 /* documentation is in freetype.h */ 02299 02300 FT_EXPORT_DEF( FT_Error ) 02301 FT_Reference_Face( FT_Face face ) 02302 { 02303 face->internal->refcount++; 02304 02305 return FT_Err_Ok; 02306 } 02307 02308 02309 /* documentation is in freetype.h */ 02310 02311 FT_EXPORT_DEF( FT_Error ) 02312 FT_Done_Face( FT_Face face ) 02313 { 02314 FT_Error error; 02315 FT_Driver driver; 02316 FT_Memory memory; 02317 FT_ListNode node; 02318 02319 02320 error = FT_Err_Invalid_Face_Handle; 02321 if ( face && face->driver ) 02322 { 02323 face->internal->refcount--; 02324 if ( face->internal->refcount > 0 ) 02325 error = FT_Err_Ok; 02326 else 02327 { 02328 driver = face->driver; 02329 memory = driver->root.memory; 02330 02331 /* find face in driver's list */ 02332 node = FT_List_Find( &driver->faces_list, face ); 02333 if ( node ) 02334 { 02335 /* remove face object from the driver's list */ 02336 FT_List_Remove( &driver->faces_list, node ); 02337 FT_FREE( node ); 02338 02339 /* now destroy the object proper */ 02340 destroy_face( memory, face, driver ); 02341 error = FT_Err_Ok; 02342 } 02343 } 02344 } 02345 02346 return error; 02347 } 02348 02349 02350 /* documentation is in ftobjs.h */ 02351 02352 FT_EXPORT_DEF( FT_Error ) 02353 FT_New_Size( FT_Face face, 02354 FT_Size *asize ) 02355 { 02356 FT_Error error; 02357 FT_Memory memory; 02358 FT_Driver driver; 02359 FT_Driver_Class clazz; 02360 02361 FT_Size size = 0; 02362 FT_ListNode node = 0; 02363 02364 02365 if ( !face ) 02366 return FT_Err_Invalid_Face_Handle; 02367 02368 if ( !asize ) 02369 return FT_Err_Invalid_Size_Handle; 02370 02371 if ( !face->driver ) 02372 return FT_Err_Invalid_Driver_Handle; 02373 02374 *asize = 0; 02375 02376 driver = face->driver; 02377 clazz = driver->clazz; 02378 memory = face->memory; 02379 02380 /* Allocate new size object and perform basic initialisation */ 02381 if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) ) 02382 goto Exit; 02383 02384 size->face = face; 02385 02386 /* for now, do not use any internal fields in size objects */ 02387 size->internal = 0; 02388 02389 if ( clazz->init_size ) 02390 error = clazz->init_size( size ); 02391 02392 /* in case of success, add to the face's list */ 02393 if ( !error ) 02394 { 02395 *asize = size; 02396 node->data = size; 02397 FT_List_Add( &face->sizes_list, node ); 02398 } 02399 02400 Exit: 02401 if ( error ) 02402 { 02403 FT_FREE( node ); 02404 FT_FREE( size ); 02405 } 02406 02407 return error; 02408 } 02409 02410 02411 /* documentation is in ftobjs.h */ 02412 02413 FT_EXPORT_DEF( FT_Error ) 02414 FT_Done_Size( FT_Size size ) 02415 { 02416 FT_Error error; 02417 FT_Driver driver; 02418 FT_Memory memory; 02419 FT_Face face; 02420 FT_ListNode node; 02421 02422 02423 if ( !size ) 02424 return FT_Err_Invalid_Size_Handle; 02425 02426 face = size->face; 02427 if ( !face ) 02428 return FT_Err_Invalid_Face_Handle; 02429 02430 driver = face->driver; 02431 if ( !driver ) 02432 return FT_Err_Invalid_Driver_Handle; 02433 02434 memory = driver->root.memory; 02435 02436 error = FT_Err_Ok; 02437 node = FT_List_Find( &face->sizes_list, size ); 02438 if ( node ) 02439 { 02440 FT_List_Remove( &face->sizes_list, node ); 02441 FT_FREE( node ); 02442 02443 if ( face->size == size ) 02444 { 02445 face->size = 0; 02446 if ( face->sizes_list.head ) 02447 face->size = (FT_Size)(face->sizes_list.head->data); 02448 } 02449 02450 destroy_size( memory, size, driver ); 02451 } 02452 else 02453 error = FT_Err_Invalid_Size_Handle; 02454 02455 return error; 02456 } 02457 02458 02459 /* documentation is in ftobjs.h */ 02460 02461 FT_BASE_DEF( FT_Error ) 02462 FT_Match_Size( FT_Face face, 02463 FT_Size_Request req, 02464 FT_Bool ignore_width, 02465 FT_ULong* size_index ) 02466 { 02467 FT_Int i; 02468 FT_Long w, h; 02469 02470 02471 if ( !FT_HAS_FIXED_SIZES( face ) ) 02472 return FT_Err_Invalid_Face_Handle; 02473 02474 /* FT_Bitmap_Size doesn't provide enough info... */ 02475 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL ) 02476 return FT_Err_Unimplemented_Feature; 02477 02478 w = FT_REQUEST_WIDTH ( req ); 02479 h = FT_REQUEST_HEIGHT( req ); 02480 02481 if ( req->width && !req->height ) 02482 h = w; 02483 else if ( !req->width && req->height ) 02484 w = h; 02485 02486 w = FT_PIX_ROUND( w ); 02487 h = FT_PIX_ROUND( h ); 02488 02489 for ( i = 0; i < face->num_fixed_sizes; i++ ) 02490 { 02491 FT_Bitmap_Size* bsize = face->available_sizes + i; 02492 02493 02494 if ( h != FT_PIX_ROUND( bsize->y_ppem ) ) 02495 continue; 02496 02497 if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width ) 02498 { 02499 if ( size_index ) 02500 *size_index = (FT_ULong)i; 02501 02502 return FT_Err_Ok; 02503 } 02504 } 02505 02506 return FT_Err_Invalid_Pixel_Size; 02507 } 02508 02509 02510 /* documentation is in ftobjs.h */ 02511 02512 FT_BASE_DEF( void ) 02513 ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics, 02514 FT_Pos advance ) 02515 { 02516 FT_Pos height = metrics->height; 02517 02518 02519 /* compensate for glyph with bbox above/below the baseline */ 02520 if ( metrics->horiBearingY < 0 ) 02521 { 02522 if ( height < metrics->horiBearingY ) 02523 height = metrics->horiBearingY; 02524 } 02525 else if ( metrics->horiBearingY > 0 ) 02526 height -= metrics->horiBearingY; 02527 02528 /* the factor 1.2 is a heuristical value */ 02529 if ( !advance ) 02530 advance = height * 12 / 10; 02531 02532 metrics->vertBearingX = metrics->horiBearingX - metrics->horiAdvance / 2; 02533 metrics->vertBearingY = ( advance - height ) / 2; 02534 metrics->vertAdvance = advance; 02535 } 02536 02537 02538 static void 02539 ft_recompute_scaled_metrics( FT_Face face, 02540 FT_Size_Metrics* metrics ) 02541 { 02542 /* Compute root ascender, descender, test height, and max_advance */ 02543 02544 #ifdef GRID_FIT_METRICS 02545 metrics->ascender = FT_PIX_CEIL( FT_MulFix( face->ascender, 02546 metrics->y_scale ) ); 02547 02548 metrics->descender = FT_PIX_FLOOR( FT_MulFix( face->descender, 02549 metrics->y_scale ) ); 02550 02551 metrics->height = FT_PIX_ROUND( FT_MulFix( face->height, 02552 metrics->y_scale ) ); 02553 02554 metrics->max_advance = FT_PIX_ROUND( FT_MulFix( face->max_advance_width, 02555 metrics->x_scale ) ); 02556 #else /* !GRID_FIT_METRICS */ 02557 metrics->ascender = FT_MulFix( face->ascender, 02558 metrics->y_scale ); 02559 02560 metrics->descender = FT_MulFix( face->descender, 02561 metrics->y_scale ); 02562 02563 metrics->height = FT_MulFix( face->height, 02564 metrics->y_scale ); 02565 02566 metrics->max_advance = FT_MulFix( face->max_advance_width, 02567 metrics->x_scale ); 02568 #endif /* !GRID_FIT_METRICS */ 02569 } 02570 02571 02572 FT_BASE_DEF( void ) 02573 FT_Select_Metrics( FT_Face face, 02574 FT_ULong strike_index ) 02575 { 02576 FT_Size_Metrics* metrics; 02577 FT_Bitmap_Size* bsize; 02578 02579 02580 metrics = &face->size->metrics; 02581 bsize = face->available_sizes + strike_index; 02582 02583 metrics->x_ppem = (FT_UShort)( ( bsize->x_ppem + 32 ) >> 6 ); 02584 metrics->y_ppem = (FT_UShort)( ( bsize->y_ppem + 32 ) >> 6 ); 02585 02586 if ( FT_IS_SCALABLE( face ) ) 02587 { 02588 metrics->x_scale = FT_DivFix( bsize->x_ppem, 02589 face->units_per_EM ); 02590 metrics->y_scale = FT_DivFix( bsize->y_ppem, 02591 face->units_per_EM ); 02592 02593 ft_recompute_scaled_metrics( face, metrics ); 02594 } 02595 else 02596 { 02597 metrics->x_scale = 1L << 16; 02598 metrics->y_scale = 1L << 16; 02599 metrics->ascender = bsize->y_ppem; 02600 metrics->descender = 0; 02601 metrics->height = bsize->height << 6; 02602 metrics->max_advance = bsize->x_ppem; 02603 } 02604 } 02605 02606 02607 FT_BASE_DEF( void ) 02608 FT_Request_Metrics( FT_Face face, 02609 FT_Size_Request req ) 02610 { 02611 FT_Size_Metrics* metrics; 02612 02613 02614 metrics = &face->size->metrics; 02615 02616 if ( FT_IS_SCALABLE( face ) ) 02617 { 02618 FT_Long w = 0, h = 0, scaled_w = 0, scaled_h = 0; 02619 02620 02621 switch ( req->type ) 02622 { 02623 case FT_SIZE_REQUEST_TYPE_NOMINAL: 02624 w = h = face->units_per_EM; 02625 break; 02626 02627 case FT_SIZE_REQUEST_TYPE_REAL_DIM: 02628 w = h = face->ascender - face->descender; 02629 break; 02630 02631 case FT_SIZE_REQUEST_TYPE_BBOX: 02632 w = face->bbox.xMax - face->bbox.xMin; 02633 h = face->bbox.yMax - face->bbox.yMin; 02634 break; 02635 02636 case FT_SIZE_REQUEST_TYPE_CELL: 02637 w = face->max_advance_width; 02638 h = face->ascender - face->descender; 02639 break; 02640 02641 case FT_SIZE_REQUEST_TYPE_SCALES: 02642 metrics->x_scale = (FT_Fixed)req->width; 02643 metrics->y_scale = (FT_Fixed)req->height; 02644 if ( !metrics->x_scale ) 02645 metrics->x_scale = metrics->y_scale; 02646 else if ( !metrics->y_scale ) 02647 metrics->y_scale = metrics->x_scale; 02648 goto Calculate_Ppem; 02649 02650 case FT_SIZE_REQUEST_TYPE_MAX: 02651 break; 02652 } 02653 02654 /* to be on the safe side */ 02655 if ( w < 0 ) 02656 w = -w; 02657 02658 if ( h < 0 ) 02659 h = -h; 02660 02661 scaled_w = FT_REQUEST_WIDTH ( req ); 02662 scaled_h = FT_REQUEST_HEIGHT( req ); 02663 02664 /* determine scales */ 02665 if ( req->width ) 02666 { 02667 metrics->x_scale = FT_DivFix( scaled_w, w ); 02668 02669 if ( req->height ) 02670 { 02671 metrics->y_scale = FT_DivFix( scaled_h, h ); 02672 02673 if ( req->type == FT_SIZE_REQUEST_TYPE_CELL ) 02674 { 02675 if ( metrics->y_scale > metrics->x_scale ) 02676 metrics->y_scale = metrics->x_scale; 02677 else 02678 metrics->x_scale = metrics->y_scale; 02679 } 02680 } 02681 else 02682 { 02683 metrics->y_scale = metrics->x_scale; 02684 scaled_h = FT_MulDiv( scaled_w, h, w ); 02685 } 02686 } 02687 else 02688 { 02689 metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h ); 02690 scaled_w = FT_MulDiv( scaled_h, w, h ); 02691 } 02692 02693 Calculate_Ppem: 02694 /* calculate the ppems */ 02695 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL ) 02696 { 02697 scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale ); 02698 scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale ); 02699 } 02700 02701 metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 ); 02702 metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 ); 02703 02704 ft_recompute_scaled_metrics( face, metrics ); 02705 } 02706 else 02707 { 02708 FT_ZERO( metrics ); 02709 metrics->x_scale = 1L << 16; 02710 metrics->y_scale = 1L << 16; 02711 } 02712 } 02713 02714 02715 /* documentation is in freetype.h */ 02716 02717 FT_EXPORT_DEF( FT_Error ) 02718 FT_Select_Size( FT_Face face, 02719 FT_Int strike_index ) 02720 { 02721 FT_Driver_Class clazz; 02722 02723 02724 if ( !face || !FT_HAS_FIXED_SIZES( face ) ) 02725 return FT_Err_Invalid_Face_Handle; 02726 02727 if ( strike_index < 0 || strike_index >= face->num_fixed_sizes ) 02728 return FT_Err_Invalid_Argument; 02729 02730 clazz = face->driver->clazz; 02731 02732 if ( clazz->select_size ) 02733 return clazz->select_size( face->size, (FT_ULong)strike_index ); 02734 02735 FT_Select_Metrics( face, (FT_ULong)strike_index ); 02736 02737 return FT_Err_Ok; 02738 } 02739 02740 02741 /* documentation is in freetype.h */ 02742 02743 FT_EXPORT_DEF( FT_Error ) 02744 FT_Request_Size( FT_Face face, 02745 FT_Size_Request req ) 02746 { 02747 FT_Driver_Class clazz; 02748 FT_ULong strike_index; 02749 02750 02751 if ( !face ) 02752 return FT_Err_Invalid_Face_Handle; 02753 02754 if ( !req || req->width < 0 || req->height < 0 || 02755 req->type >= FT_SIZE_REQUEST_TYPE_MAX ) 02756 return FT_Err_Invalid_Argument; 02757 02758 clazz = face->driver->clazz; 02759 02760 if ( clazz->request_size ) 02761 return clazz->request_size( face->size, req ); 02762 02763 /* 02764 * The reason that a driver doesn't have `request_size' defined is 02765 * either that the scaling here suffices or that the supported formats 02766 * are bitmap-only and size matching is not implemented. 02767 * 02768 * In the latter case, a simple size matching is done. 02769 */ 02770 if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) ) 02771 { 02772 FT_Error error; 02773 02774 02775 error = FT_Match_Size( face, req, 0, &strike_index ); 02776 if ( error ) 02777 return error; 02778 02779 FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n", 02780 strike_index )); 02781 02782 return FT_Select_Size( face, (FT_Int)strike_index ); 02783 } 02784 02785 FT_Request_Metrics( face, req ); 02786 02787 return FT_Err_Ok; 02788 } 02789 02790 02791 /* documentation is in freetype.h */ 02792 02793 FT_EXPORT_DEF( FT_Error ) 02794 FT_Set_Char_Size( FT_Face face, 02795 FT_F26Dot6 char_width, 02796 FT_F26Dot6 char_height, 02797 FT_UInt horz_resolution, 02798 FT_UInt vert_resolution ) 02799 { 02800 FT_Size_RequestRec req; 02801 02802 02803 if ( !char_width ) 02804 char_width = char_height; 02805 else if ( !char_height ) 02806 char_height = char_width; 02807 02808 if ( !horz_resolution ) 02809 horz_resolution = vert_resolution; 02810 else if ( !vert_resolution ) 02811 vert_resolution = horz_resolution; 02812 02813 if ( char_width < 1 * 64 ) 02814 char_width = 1 * 64; 02815 if ( char_height < 1 * 64 ) 02816 char_height = 1 * 64; 02817 02818 if ( !horz_resolution ) 02819 horz_resolution = vert_resolution = 72; 02820 02821 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL; 02822 req.width = char_width; 02823 req.height = char_height; 02824 req.horiResolution = horz_resolution; 02825 req.vertResolution = vert_resolution; 02826 02827 return FT_Request_Size( face, &req ); 02828 } 02829 02830 02831 /* documentation is in freetype.h */ 02832 02833 FT_EXPORT_DEF( FT_Error ) 02834 FT_Set_Pixel_Sizes( FT_Face face, 02835 FT_UInt pixel_width, 02836 FT_UInt pixel_height ) 02837 { 02838 FT_Size_RequestRec req; 02839 02840 02841 if ( pixel_width == 0 ) 02842 pixel_width = pixel_height; 02843 else if ( pixel_height == 0 ) 02844 pixel_height = pixel_width; 02845 02846 if ( pixel_width < 1 ) 02847 pixel_width = 1; 02848 if ( pixel_height < 1 ) 02849 pixel_height = 1; 02850 02851 /* use `>=' to avoid potential compiler warning on 16bit platforms */ 02852 if ( pixel_width >= 0xFFFFU ) 02853 pixel_width = 0xFFFFU; 02854 if ( pixel_height >= 0xFFFFU ) 02855 pixel_height = 0xFFFFU; 02856 02857 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL; 02858 req.width = pixel_width << 6; 02859 req.height = pixel_height << 6; 02860 req.horiResolution = 0; 02861 req.vertResolution = 0; 02862 02863 return FT_Request_Size( face, &req ); 02864 } 02865 02866 02867 /* documentation is in freetype.h */ 02868 02869 FT_EXPORT_DEF( FT_Error ) 02870 FT_Get_Kerning( FT_Face face, 02871 FT_UInt left_glyph, 02872 FT_UInt right_glyph, 02873 FT_UInt kern_mode, 02874 FT_Vector *akerning ) 02875 { 02876 FT_Error error = FT_Err_Ok; 02877 FT_Driver driver; 02878 02879 02880 if ( !face ) 02881 return FT_Err_Invalid_Face_Handle; 02882 02883 if ( !akerning ) 02884 return FT_Err_Invalid_Argument; 02885 02886 driver = face->driver; 02887 02888 akerning->x = 0; 02889 akerning->y = 0; 02890 02891 if ( driver->clazz->get_kerning ) 02892 { 02893 error = driver->clazz->get_kerning( face, 02894 left_glyph, 02895 right_glyph, 02896 akerning ); 02897 if ( !error ) 02898 { 02899 if ( kern_mode != FT_KERNING_UNSCALED ) 02900 { 02901 akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale ); 02902 akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale ); 02903 02904 if ( kern_mode != FT_KERNING_UNFITTED ) 02905 { 02906 /* we scale down kerning values for small ppem values */ 02907 /* to avoid that rounding makes them too big. */ 02908 /* `25' has been determined heuristically. */ 02909 if ( face->size->metrics.x_ppem < 25 ) 02910 akerning->x = FT_MulDiv( akerning->x, 02911 face->size->metrics.x_ppem, 25 ); 02912 if ( face->size->metrics.y_ppem < 25 ) 02913 akerning->y = FT_MulDiv( akerning->y, 02914 face->size->metrics.y_ppem, 25 ); 02915 02916 akerning->x = FT_PIX_ROUND( akerning->x ); 02917 akerning->y = FT_PIX_ROUND( akerning->y ); 02918 } 02919 } 02920 } 02921 } 02922 02923 return error; 02924 } 02925 02926 02927 /* documentation is in freetype.h */ 02928 02929 FT_EXPORT_DEF( FT_Error ) 02930 FT_Get_Track_Kerning( FT_Face face, 02931 FT_Fixed point_size, 02932 FT_Int degree, 02933 FT_Fixed* akerning ) 02934 { 02935 FT_Service_Kerning service; 02936 FT_Error error = FT_Err_Ok; 02937 02938 02939 if ( !face ) 02940 return FT_Err_Invalid_Face_Handle; 02941 02942 if ( !akerning ) 02943 return FT_Err_Invalid_Argument; 02944 02945 FT_FACE_FIND_SERVICE( face, service, KERNING ); 02946 if ( !service ) 02947 return FT_Err_Unimplemented_Feature; 02948 02949 error = service->get_track( face, 02950 point_size, 02951 degree, 02952 akerning ); 02953 02954 return error; 02955 } 02956 02957 02958 /* documentation is in freetype.h */ 02959 02960 FT_EXPORT_DEF( FT_Error ) 02961 FT_Select_Charmap( FT_Face face, 02962 FT_Encoding encoding ) 02963 { 02964 FT_CharMap* cur; 02965 FT_CharMap* limit; 02966 02967 02968 if ( !face ) 02969 return FT_Err_Invalid_Face_Handle; 02970 02971 if ( encoding == FT_ENCODING_NONE ) 02972 return FT_Err_Invalid_Argument; 02973 02974 /* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */ 02975 /* charmap available, i.e., one with UCS-4 characters, if possible. */ 02976 /* */ 02977 /* This is done by find_unicode_charmap() above, to share code. */ 02978 if ( encoding == FT_ENCODING_UNICODE ) 02979 return find_unicode_charmap( face ); 02980 02981 cur = face->charmaps; 02982 if ( !cur ) 02983 return FT_Err_Invalid_CharMap_Handle; 02984 02985 limit = cur + face->num_charmaps; 02986 02987 for ( ; cur < limit; cur++ ) 02988 { 02989 if ( cur[0]->encoding == encoding ) 02990 { 02991 #ifdef FT_MAX_CHARMAP_CACHEABLE 02992 if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE ) 02993 { 02994 FT_ERROR(( "FT_Select_Charmap: requested charmap is found (%d), " 02995 "but in too late position to cache\n", 02996 cur - face->charmaps )); 02997 continue; 02998 } 02999 #endif 03000 face->charmap = cur[0]; 03001 return 0; 03002 } 03003 } 03004 03005 return FT_Err_Invalid_Argument; 03006 } 03007 03008 03009 /* documentation is in freetype.h */ 03010 03011 FT_EXPORT_DEF( FT_Error ) 03012 FT_Set_Charmap( FT_Face face, 03013 FT_CharMap charmap ) 03014 { 03015 FT_CharMap* cur; 03016 FT_CharMap* limit; 03017 03018 03019 if ( !face ) 03020 return FT_Err_Invalid_Face_Handle; 03021 03022 cur = face->charmaps; 03023 if ( !cur ) 03024 return FT_Err_Invalid_CharMap_Handle; 03025 if ( FT_Get_CMap_Format( charmap ) == 14 ) 03026 return FT_Err_Invalid_Argument; 03027 03028 limit = cur + face->num_charmaps; 03029 03030 for ( ; cur < limit; cur++ ) 03031 { 03032 if ( cur[0] == charmap ) 03033 { 03034 #ifdef FT_MAX_CHARMAP_CACHEABLE 03035 if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE ) 03036 { 03037 FT_ERROR(( "FT_Set_Charmap: requested charmap is found (%d), " 03038 "but in too late position to cache\n", 03039 cur - face->charmaps )); 03040 continue; 03041 } 03042 #endif 03043 face->charmap = cur[0]; 03044 return 0; 03045 } 03046 } 03047 return FT_Err_Invalid_Argument; 03048 } 03049 03050 03051 /* documentation is in freetype.h */ 03052 03053 FT_EXPORT_DEF( FT_Int ) 03054 FT_Get_Charmap_Index( FT_CharMap charmap ) 03055 { 03056 FT_Int i; 03057 03058 03059 if ( !charmap || !charmap->face ) 03060 return -1; 03061 03062 for ( i = 0; i < charmap->face->num_charmaps; i++ ) 03063 if ( charmap->face->charmaps[i] == charmap ) 03064 break; 03065 03066 FT_ASSERT( i < charmap->face->num_charmaps ); 03067 03068 #ifdef FT_MAX_CHARMAP_CACHEABLE 03069 if ( i > FT_MAX_CHARMAP_CACHEABLE ) 03070 { 03071 FT_ERROR(( "FT_Get_Charmap_Index: requested charmap is found (%d), " 03072 "but in too late position to cache\n", 03073 i )); 03074 return -i; 03075 } 03076 #endif 03077 return i; 03078 } 03079 03080 03081 static void 03082 ft_cmap_done_internal( FT_CMap cmap ) 03083 { 03084 FT_CMap_Class clazz = cmap->clazz; 03085 FT_Face face = cmap->charmap.face; 03086 FT_Memory memory = FT_FACE_MEMORY(face); 03087 03088 03089 if ( clazz->done ) 03090 clazz->done( cmap ); 03091 03092 FT_FREE( cmap ); 03093 } 03094 03095 03096 FT_BASE_DEF( void ) 03097 FT_CMap_Done( FT_CMap cmap ) 03098 { 03099 if ( cmap ) 03100 { 03101 FT_Face face = cmap->charmap.face; 03102 FT_Memory memory = FT_FACE_MEMORY( face ); 03103 FT_Error error; 03104 FT_Int i, j; 03105 03106 03107 for ( i = 0; i < face->num_charmaps; i++ ) 03108 { 03109 if ( (FT_CMap)face->charmaps[i] == cmap ) 03110 { 03111 FT_CharMap last_charmap = face->charmaps[face->num_charmaps - 1]; 03112 03113 03114 if ( FT_RENEW_ARRAY( face->charmaps, 03115 face->num_charmaps, 03116 face->num_charmaps - 1 ) ) 03117 return; 03118 03119 /* remove it from our list of charmaps */ 03120 for ( j = i + 1; j < face->num_charmaps; j++ ) 03121 { 03122 if ( j == face->num_charmaps - 1 ) 03123 face->charmaps[j - 1] = last_charmap; 03124 else 03125 face->charmaps[j - 1] = face->charmaps[j]; 03126 } 03127 03128 face->num_charmaps--; 03129 03130 if ( (FT_CMap)face->charmap == cmap ) 03131 face->charmap = NULL; 03132 03133 ft_cmap_done_internal( cmap ); 03134 03135 break; 03136 } 03137 } 03138 } 03139 } 03140 03141 03142 FT_BASE_DEF( FT_Error ) 03143 FT_CMap_New( FT_CMap_Class clazz, 03144 FT_Pointer init_data, 03145 FT_CharMap charmap, 03146 FT_CMap *acmap ) 03147 { 03148 FT_Error error = FT_Err_Ok; 03149 FT_Face face; 03150 FT_Memory memory; 03151 FT_CMap cmap; 03152 03153 03154 if ( clazz == NULL || charmap == NULL || charmap->face == NULL ) 03155 return FT_Err_Invalid_Argument; 03156 03157 face = charmap->face; 03158 memory = FT_FACE_MEMORY( face ); 03159 03160 if ( !FT_ALLOC( cmap, clazz->size ) ) 03161 { 03162 cmap->charmap = *charmap; 03163 cmap->clazz = clazz; 03164 03165 if ( clazz->init ) 03166 { 03167 error = clazz->init( cmap, init_data ); 03168 if ( error ) 03169 goto Fail; 03170 } 03171 03172 /* add it to our list of charmaps */ 03173 if ( FT_RENEW_ARRAY( face->charmaps, 03174 face->num_charmaps, 03175 face->num_charmaps + 1 ) ) 03176 goto Fail; 03177 03178 face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap; 03179 } 03180 03181 Exit: 03182 if ( acmap ) 03183 *acmap = cmap; 03184 03185 return error; 03186 03187 Fail: 03188 ft_cmap_done_internal( cmap ); 03189 cmap = NULL; 03190 goto Exit; 03191 } 03192 03193 03194 /* documentation is in freetype.h */ 03195 03196 FT_EXPORT_DEF( FT_UInt ) 03197 FT_Get_Char_Index( FT_Face face, 03198 FT_ULong charcode ) 03199 { 03200 FT_UInt result = 0; 03201 03202 03203 if ( face && face->charmap ) 03204 { 03205 FT_CMap cmap = FT_CMAP( face->charmap ); 03206 03207 03208 if ( charcode > 0xFFFFFFFFUL ) 03209 { 03210 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" )); 03211 FT_TRACE1(( " 0x%x is truncated\n", charcode )); 03212 } 03213 result = cmap->clazz->char_index( cmap, (FT_UInt32)charcode ); 03214 } 03215 return result; 03216 } 03217 03218 03219 /* documentation is in freetype.h */ 03220 03221 FT_EXPORT_DEF( FT_ULong ) 03222 FT_Get_First_Char( FT_Face face, 03223 FT_UInt *agindex ) 03224 { 03225 FT_ULong result = 0; 03226 FT_UInt gindex = 0; 03227 03228 03229 if ( face && face->charmap && face->num_glyphs ) 03230 { 03231 gindex = FT_Get_Char_Index( face, 0 ); 03232 if ( gindex == 0 || gindex >= (FT_UInt)face->num_glyphs ) 03233 result = FT_Get_Next_Char( face, 0, &gindex ); 03234 } 03235 03236 if ( agindex ) 03237 *agindex = gindex; 03238 03239 return result; 03240 } 03241 03242 03243 /* documentation is in freetype.h */ 03244 03245 FT_EXPORT_DEF( FT_ULong ) 03246 FT_Get_Next_Char( FT_Face face, 03247 FT_ULong charcode, 03248 FT_UInt *agindex ) 03249 { 03250 FT_ULong result = 0; 03251 FT_UInt gindex = 0; 03252 03253 03254 if ( face && face->charmap && face->num_glyphs ) 03255 { 03256 FT_UInt32 code = (FT_UInt32)charcode; 03257 FT_CMap cmap = FT_CMAP( face->charmap ); 03258 03259 03260 do { 03261 gindex = cmap->clazz->char_next( cmap, &code ); 03262 } while ( gindex >= (FT_UInt)face->num_glyphs ); 03263 03264 result = ( gindex == 0 ) ? 0 : code; 03265 } 03266 03267 if ( agindex ) 03268 *agindex = gindex; 03269 03270 return result; 03271 } 03272 03273 03274 /* documentation is in freetype.h */ 03275 03276 FT_EXPORT_DEF( FT_UInt ) 03277 FT_Face_GetCharVariantIndex( FT_Face face, 03278 FT_ULong charcode, 03279 FT_ULong variantSelector ) 03280 { 03281 FT_UInt result = 0; 03282 03283 03284 if ( face && face->charmap && 03285 face->charmap->encoding == FT_ENCODING_UNICODE ) 03286 { 03287 FT_CharMap charmap = find_variant_selector_charmap( face ); 03288 FT_CMap ucmap = FT_CMAP( face->charmap ); 03289 03290 03291 if ( charmap != NULL ) 03292 { 03293 FT_CMap vcmap = FT_CMAP( charmap ); 03294 03295 03296 if ( charcode > 0xFFFFFFFFUL ) 03297 { 03298 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" )); 03299 FT_TRACE1(( " 0x%x is truncated\n", charcode )); 03300 } 03301 if ( variantSelector > 0xFFFFFFFFUL ) 03302 { 03303 FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" )); 03304 FT_TRACE1(( " 0x%x is truncated\n", variantSelector )); 03305 } 03306 03307 result = vcmap->clazz->char_var_index( vcmap, ucmap, 03308 (FT_UInt32)charcode, 03309 (FT_UInt32)variantSelector ); 03310 } 03311 } 03312 03313 return result; 03314 } 03315 03316 03317 /* documentation is in freetype.h */ 03318 03319 FT_EXPORT_DEF( FT_Int ) 03320 FT_Face_GetCharVariantIsDefault( FT_Face face, 03321 FT_ULong charcode, 03322 FT_ULong variantSelector ) 03323 { 03324 FT_Int result = -1; 03325 03326 03327 if ( face ) 03328 { 03329 FT_CharMap charmap = find_variant_selector_charmap( face ); 03330 03331 03332 if ( charmap != NULL ) 03333 { 03334 FT_CMap vcmap = FT_CMAP( charmap ); 03335 03336 03337 if ( charcode > 0xFFFFFFFFUL ) 03338 { 03339 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" )); 03340 FT_TRACE1(( " 0x%x is truncated\n", charcode )); 03341 } 03342 if ( variantSelector > 0xFFFFFFFFUL ) 03343 { 03344 FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" )); 03345 FT_TRACE1(( " 0x%x is truncated\n", variantSelector )); 03346 } 03347 03348 result = vcmap->clazz->char_var_default( vcmap, 03349 (FT_UInt32)charcode, 03350 (FT_UInt32)variantSelector ); 03351 } 03352 } 03353 03354 return result; 03355 } 03356 03357 03358 /* documentation is in freetype.h */ 03359 03360 FT_EXPORT_DEF( FT_UInt32* ) 03361 FT_Face_GetVariantSelectors( FT_Face face ) 03362 { 03363 FT_UInt32 *result = NULL; 03364 03365 03366 if ( face ) 03367 { 03368 FT_CharMap charmap = find_variant_selector_charmap( face ); 03369 03370 03371 if ( charmap != NULL ) 03372 { 03373 FT_CMap vcmap = FT_CMAP( charmap ); 03374 FT_Memory memory = FT_FACE_MEMORY( face ); 03375 03376 03377 result = vcmap->clazz->variant_list( vcmap, memory ); 03378 } 03379 } 03380 03381 return result; 03382 } 03383 03384 03385 /* documentation is in freetype.h */ 03386 03387 FT_EXPORT_DEF( FT_UInt32* ) 03388 FT_Face_GetVariantsOfChar( FT_Face face, 03389 FT_ULong charcode ) 03390 { 03391 FT_UInt32 *result = NULL; 03392 03393 03394 if ( face ) 03395 { 03396 FT_CharMap charmap = find_variant_selector_charmap( face ); 03397 03398 03399 if ( charmap != NULL ) 03400 { 03401 FT_CMap vcmap = FT_CMAP( charmap ); 03402 FT_Memory memory = FT_FACE_MEMORY( face ); 03403 03404 03405 if ( charcode > 0xFFFFFFFFUL ) 03406 { 03407 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" )); 03408 FT_TRACE1(( " 0x%x is truncated\n", charcode )); 03409 } 03410 03411 result = vcmap->clazz->charvariant_list( vcmap, memory, 03412 (FT_UInt32)charcode ); 03413 } 03414 } 03415 return result; 03416 } 03417 03418 03419 /* documentation is in freetype.h */ 03420 03421 FT_EXPORT_DEF( FT_UInt32* ) 03422 FT_Face_GetCharsOfVariant( FT_Face face, 03423 FT_ULong variantSelector ) 03424 { 03425 FT_UInt32 *result = NULL; 03426 03427 03428 if ( face ) 03429 { 03430 FT_CharMap charmap = find_variant_selector_charmap( face ); 03431 03432 03433 if ( charmap != NULL ) 03434 { 03435 FT_CMap vcmap = FT_CMAP( charmap ); 03436 FT_Memory memory = FT_FACE_MEMORY( face ); 03437 03438 03439 if ( variantSelector > 0xFFFFFFFFUL ) 03440 { 03441 FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" )); 03442 FT_TRACE1(( " 0x%x is truncated\n", variantSelector )); 03443 } 03444 03445 result = vcmap->clazz->variantchar_list( vcmap, memory, 03446 (FT_UInt32)variantSelector ); 03447 } 03448 } 03449 03450 return result; 03451 } 03452 03453 03454 /* documentation is in freetype.h */ 03455 03456 FT_EXPORT_DEF( FT_UInt ) 03457 FT_Get_Name_Index( FT_Face face, 03458 FT_String* glyph_name ) 03459 { 03460 FT_UInt result = 0; 03461 03462 03463 if ( face && FT_HAS_GLYPH_NAMES( face ) ) 03464 { 03465 FT_Service_GlyphDict service; 03466 03467 03468 FT_FACE_LOOKUP_SERVICE( face, 03469 service, 03470 GLYPH_DICT ); 03471 03472 if ( service && service->name_index ) 03473 result = service->name_index( face, glyph_name ); 03474 } 03475 03476 return result; 03477 } 03478 03479 03480 /* documentation is in freetype.h */ 03481 03482 FT_EXPORT_DEF( FT_Error ) 03483 FT_Get_Glyph_Name( FT_Face face, 03484 FT_UInt glyph_index, 03485 FT_Pointer buffer, 03486 FT_UInt buffer_max ) 03487 { 03488 FT_Error error = FT_Err_Invalid_Argument; 03489 03490 03491 /* clean up buffer */ 03492 if ( buffer && buffer_max > 0 ) 03493 ((FT_Byte*)buffer)[0] = 0; 03494 03495 if ( face && 03496 (FT_Long)glyph_index <= face->num_glyphs && 03497 FT_HAS_GLYPH_NAMES( face ) ) 03498 { 03499 FT_Service_GlyphDict service; 03500 03501 03502 FT_FACE_LOOKUP_SERVICE( face, 03503 service, 03504 GLYPH_DICT ); 03505 03506 if ( service && service->get_name ) 03507 error = service->get_name( face, glyph_index, buffer, buffer_max ); 03508 } 03509 03510 return error; 03511 } 03512 03513 03514 /* documentation is in freetype.h */ 03515 03516 FT_EXPORT_DEF( const char* ) 03517 FT_Get_Postscript_Name( FT_Face face ) 03518 { 03519 const char* result = NULL; 03520 03521 03522 if ( !face ) 03523 goto Exit; 03524 03525 if ( !result ) 03526 { 03527 FT_Service_PsFontName service; 03528 03529 03530 FT_FACE_LOOKUP_SERVICE( face, 03531 service, 03532 POSTSCRIPT_FONT_NAME ); 03533 03534 if ( service && service->get_ps_font_name ) 03535 result = service->get_ps_font_name( face ); 03536 } 03537 03538 Exit: 03539 return result; 03540 } 03541 03542 03543 /* documentation is in tttables.h */ 03544 03545 FT_EXPORT_DEF( void* ) 03546 FT_Get_Sfnt_Table( FT_Face face, 03547 FT_Sfnt_Tag tag ) 03548 { 03549 void* table = 0; 03550 FT_Service_SFNT_Table service; 03551 03552 03553 if ( face && FT_IS_SFNT( face ) ) 03554 { 03555 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE ); 03556 if ( service != NULL ) 03557 table = service->get_table( face, tag ); 03558 } 03559 03560 return table; 03561 } 03562 03563 03564 /* documentation is in tttables.h */ 03565 03566 FT_EXPORT_DEF( FT_Error ) 03567 FT_Load_Sfnt_Table( FT_Face face, 03568 FT_ULong tag, 03569 FT_Long offset, 03570 FT_Byte* buffer, 03571 FT_ULong* length ) 03572 { 03573 FT_Service_SFNT_Table service; 03574 03575 03576 if ( !face || !FT_IS_SFNT( face ) ) 03577 return FT_Err_Invalid_Face_Handle; 03578 03579 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE ); 03580 if ( service == NULL ) 03581 return FT_Err_Unimplemented_Feature; 03582 03583 return service->load_table( face, tag, offset, buffer, length ); 03584 } 03585 03586 03587 /* documentation is in tttables.h */ 03588 03589 FT_EXPORT_DEF( FT_Error ) 03590 FT_Sfnt_Table_Info( FT_Face face, 03591 FT_UInt table_index, 03592 FT_ULong *tag, 03593 FT_ULong *length ) 03594 { 03595 FT_Service_SFNT_Table service; 03596 FT_ULong offset; 03597 03598 03599 if ( !face || !FT_IS_SFNT( face ) ) 03600 return FT_Err_Invalid_Face_Handle; 03601 03602 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE ); 03603 if ( service == NULL ) 03604 return FT_Err_Unimplemented_Feature; 03605 03606 return service->table_info( face, table_index, tag, &offset, length ); 03607 } 03608 03609 03610 /* documentation is in tttables.h */ 03611 03612 FT_EXPORT_DEF( FT_ULong ) 03613 FT_Get_CMap_Language_ID( FT_CharMap charmap ) 03614 { 03615 FT_Service_TTCMaps service; 03616 FT_Face face; 03617 TT_CMapInfo cmap_info; 03618 03619 03620 if ( !charmap || !charmap->face ) 03621 return 0; 03622 03623 face = charmap->face; 03624 FT_FACE_FIND_SERVICE( face, service, TT_CMAP ); 03625 if ( service == NULL ) 03626 return 0; 03627 if ( service->get_cmap_info( charmap, &cmap_info )) 03628 return 0; 03629 03630 return cmap_info.language; 03631 } 03632 03633 03634 /* documentation is in tttables.h */ 03635 03636 FT_EXPORT_DEF( FT_Long ) 03637 FT_Get_CMap_Format( FT_CharMap charmap ) 03638 { 03639 FT_Service_TTCMaps service; 03640 FT_Face face; 03641 TT_CMapInfo cmap_info; 03642 03643 03644 if ( !charmap || !charmap->face ) 03645 return -1; 03646 03647 face = charmap->face; 03648 FT_FACE_FIND_SERVICE( face, service, TT_CMAP ); 03649 if ( service == NULL ) 03650 return -1; 03651 if ( service->get_cmap_info( charmap, &cmap_info )) 03652 return -1; 03653 03654 return cmap_info.format; 03655 } 03656 03657 03658 /* documentation is in ftsizes.h */ 03659 03660 FT_EXPORT_DEF( FT_Error ) 03661 FT_Activate_Size( FT_Size size ) 03662 { 03663 FT_Face face; 03664 03665 03666 if ( size == NULL ) 03667 return FT_Err_Invalid_Argument; 03668 03669 face = size->face; 03670 if ( face == NULL || face->driver == NULL ) 03671 return FT_Err_Invalid_Argument; 03672 03673 /* we don't need anything more complex than that; all size objects */ 03674 /* are already listed by the face */ 03675 face->size = size; 03676 03677 return FT_Err_Ok; 03678 } 03679 03680 03681 /*************************************************************************/ 03682 /*************************************************************************/ 03683 /*************************************************************************/ 03684 /**** ****/ 03685 /**** ****/ 03686 /**** R E N D E R E R S ****/ 03687 /**** ****/ 03688 /**** ****/ 03689 /*************************************************************************/ 03690 /*************************************************************************/ 03691 /*************************************************************************/ 03692 03693 /* lookup a renderer by glyph format in the library's list */ 03694 FT_BASE_DEF( FT_Renderer ) 03695 FT_Lookup_Renderer( FT_Library library, 03696 FT_Glyph_Format format, 03697 FT_ListNode* node ) 03698 { 03699 FT_ListNode cur; 03700 FT_Renderer result = 0; 03701 03702 03703 if ( !library ) 03704 goto Exit; 03705 03706 cur = library->renderers.head; 03707 03708 if ( node ) 03709 { 03710 if ( *node ) 03711 cur = (*node)->next; 03712 *node = 0; 03713 } 03714 03715 while ( cur ) 03716 { 03717 FT_Renderer renderer = FT_RENDERER( cur->data ); 03718 03719 03720 if ( renderer->glyph_format == format ) 03721 { 03722 if ( node ) 03723 *node = cur; 03724 03725 result = renderer; 03726 break; 03727 } 03728 cur = cur->next; 03729 } 03730 03731 Exit: 03732 return result; 03733 } 03734 03735 03736 static FT_Renderer 03737 ft_lookup_glyph_renderer( FT_GlyphSlot slot ) 03738 { 03739 FT_Face face = slot->face; 03740 FT_Library library = FT_FACE_LIBRARY( face ); 03741 FT_Renderer result = library->cur_renderer; 03742 03743 03744 if ( !result || result->glyph_format != slot->format ) 03745 result = FT_Lookup_Renderer( library, slot->format, 0 ); 03746 03747 return result; 03748 } 03749 03750 03751 static void 03752 ft_set_current_renderer( FT_Library library ) 03753 { 03754 FT_Renderer renderer; 03755 03756 03757 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 ); 03758 library->cur_renderer = renderer; 03759 } 03760 03761 03762 static FT_Error 03763 ft_add_renderer( FT_Module module ) 03764 { 03765 FT_Library library = module->library; 03766 FT_Memory memory = library->memory; 03767 FT_Error error; 03768 FT_ListNode node = NULL; 03769 03770 03771 if ( FT_NEW( node ) ) 03772 goto Exit; 03773 03774 { 03775 FT_Renderer render = FT_RENDERER( module ); 03776 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz; 03777 03778 03779 render->clazz = clazz; 03780 render->glyph_format = clazz->glyph_format; 03781 03782 /* allocate raster object if needed */ 03783 if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && 03784 clazz->raster_class->raster_new ) 03785 { 03786 error = clazz->raster_class->raster_new( memory, &render->raster ); 03787 if ( error ) 03788 goto Fail; 03789 03790 render->raster_render = clazz->raster_class->raster_render; 03791 render->render = clazz->render_glyph; 03792 } 03793 03794 /* add to list */ 03795 node->data = module; 03796 FT_List_Add( &library->renderers, node ); 03797 03798 ft_set_current_renderer( library ); 03799 } 03800 03801 Fail: 03802 if ( error ) 03803 FT_FREE( node ); 03804 03805 Exit: 03806 return error; 03807 } 03808 03809 03810 static void 03811 ft_remove_renderer( FT_Module module ) 03812 { 03813 FT_Library library = module->library; 03814 FT_Memory memory = library->memory; 03815 FT_ListNode node; 03816 03817 03818 node = FT_List_Find( &library->renderers, module ); 03819 if ( node ) 03820 { 03821 FT_Renderer render = FT_RENDERER( module ); 03822 03823 03824 /* release raster object, if any */ 03825 if ( render->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && 03826 render->raster ) 03827 render->clazz->raster_class->raster_done( render->raster ); 03828 03829 /* remove from list */ 03830 FT_List_Remove( &library->renderers, node ); 03831 FT_FREE( node ); 03832 03833 ft_set_current_renderer( library ); 03834 } 03835 } 03836 03837 03838 /* documentation is in ftrender.h */ 03839 03840 FT_EXPORT_DEF( FT_Renderer ) 03841 FT_Get_Renderer( FT_Library library, 03842 FT_Glyph_Format format ) 03843 { 03844 /* test for valid `library' delayed to FT_Lookup_Renderer() */ 03845 03846 return FT_Lookup_Renderer( library, format, 0 ); 03847 } 03848 03849 03850 /* documentation is in ftrender.h */ 03851 03852 FT_EXPORT_DEF( FT_Error ) 03853 FT_Set_Renderer( FT_Library library, 03854 FT_Renderer renderer, 03855 FT_UInt num_params, 03856 FT_Parameter* parameters ) 03857 { 03858 FT_ListNode node; 03859 FT_Error error = FT_Err_Ok; 03860 03861 03862 if ( !library ) 03863 return FT_Err_Invalid_Library_Handle; 03864 03865 if ( !renderer ) 03866 return FT_Err_Invalid_Argument; 03867 03868 node = FT_List_Find( &library->renderers, renderer ); 03869 if ( !node ) 03870 { 03871 error = FT_Err_Invalid_Argument; 03872 goto Exit; 03873 } 03874 03875 FT_List_Up( &library->renderers, node ); 03876 03877 if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE ) 03878 library->cur_renderer = renderer; 03879 03880 if ( num_params > 0 ) 03881 { 03882 FT_Renderer_SetModeFunc set_mode = renderer->clazz->set_mode; 03883 03884 03885 for ( ; num_params > 0; num_params-- ) 03886 { 03887 error = set_mode( renderer, parameters->tag, parameters->data ); 03888 if ( error ) 03889 break; 03890 } 03891 } 03892 03893 Exit: 03894 return error; 03895 } 03896 03897 03898 FT_BASE_DEF( FT_Error ) 03899 FT_Render_Glyph_Internal( FT_Library library, 03900 FT_GlyphSlot slot, 03901 FT_Render_Mode render_mode ) 03902 { 03903 FT_Error error = FT_Err_Ok; 03904 FT_Renderer renderer; 03905 03906 03907 /* if it is already a bitmap, no need to do anything */ 03908 switch ( slot->format ) 03909 { 03910 case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */ 03911 break; 03912 03913 default: 03914 { 03915 FT_ListNode node = 0; 03916 FT_Bool update = 0; 03917 03918 03919 /* small shortcut for the very common case */ 03920 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) 03921 { 03922 renderer = library->cur_renderer; 03923 node = library->renderers.head; 03924 } 03925 else 03926 renderer = FT_Lookup_Renderer( library, slot->format, &node ); 03927 03928 error = FT_Err_Unimplemented_Feature; 03929 while ( renderer ) 03930 { 03931 error = renderer->render( renderer, slot, render_mode, NULL ); 03932 if ( !error || 03933 FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph ) 03934 break; 03935 03936 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ 03937 /* is unsupported by the current renderer for this glyph image */ 03938 /* format. */ 03939 03940 /* now, look for another renderer that supports the same */ 03941 /* format. */ 03942 renderer = FT_Lookup_Renderer( library, slot->format, &node ); 03943 update = 1; 03944 } 03945 03946 /* if we changed the current renderer for the glyph image format */ 03947 /* we need to select it as the next current one */ 03948 if ( !error && update && renderer ) 03949 FT_Set_Renderer( library, renderer, 0, 0 ); 03950 } 03951 } 03952 03953 return error; 03954 } 03955 03956 03957 /* documentation is in freetype.h */ 03958 03959 FT_EXPORT_DEF( FT_Error ) 03960 FT_Render_Glyph( FT_GlyphSlot slot, 03961 FT_Render_Mode render_mode ) 03962 { 03963 FT_Library library; 03964 03965 03966 if ( !slot || !slot->face ) 03967 return FT_Err_Invalid_Argument; 03968 03969 library = FT_FACE_LIBRARY( slot->face ); 03970 03971 return FT_Render_Glyph_Internal( library, slot, render_mode ); 03972 } 03973 03974 03975 /*************************************************************************/ 03976 /*************************************************************************/ 03977 /*************************************************************************/ 03978 /**** ****/ 03979 /**** ****/ 03980 /**** M O D U L E S ****/ 03981 /**** ****/ 03982 /**** ****/ 03983 /*************************************************************************/ 03984 /*************************************************************************/ 03985 /*************************************************************************/ 03986 03987 03988 /*************************************************************************/ 03989 /* */ 03990 /* <Function> */ 03991 /* Destroy_Module */ 03992 /* */ 03993 /* <Description> */ 03994 /* Destroys a given module object. For drivers, this also destroys */ 03995 /* all child faces. */ 03996 /* */ 03997 /* <InOut> */ 03998 /* module :: A handle to the target driver object. */ 03999 /* */ 04000 /* <Note> */ 04001 /* The driver _must_ be LOCKED! */ 04002 /* */ 04003 static void 04004 Destroy_Module( FT_Module module ) 04005 { 04006 FT_Memory memory = module->memory; 04007 FT_Module_Class* clazz = module->clazz; 04008 FT_Library library = module->library; 04009 04010 04011 /* finalize client-data - before anything else */ 04012 if ( module->generic.finalizer ) 04013 module->generic.finalizer( module ); 04014 04015 if ( library && library->auto_hinter == module ) 04016 library->auto_hinter = 0; 04017 04018 /* if the module is a renderer */ 04019 if ( FT_MODULE_IS_RENDERER( module ) ) 04020 ft_remove_renderer( module ); 04021 04022 /* if the module is a font driver, add some steps */ 04023 if ( FT_MODULE_IS_DRIVER( module ) ) 04024 Destroy_Driver( FT_DRIVER( module ) ); 04025 04026 /* finalize the module object */ 04027 if ( clazz->module_done ) 04028 clazz->module_done( module ); 04029 04030 /* discard it */ 04031 FT_FREE( module ); 04032 } 04033 04034 04035 /* documentation is in ftmodapi.h */ 04036 04037 FT_EXPORT_DEF( FT_Error ) 04038 FT_Add_Module( FT_Library library, 04039 const FT_Module_Class* clazz ) 04040 { 04041 FT_Error error; 04042 FT_Memory memory; 04043 FT_Module module; 04044 FT_UInt nn; 04045 04046 04047 #define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \ 04048 FREETYPE_MINOR ) 04049 04050 if ( !library ) 04051 return FT_Err_Invalid_Library_Handle; 04052 04053 if ( !clazz ) 04054 return FT_Err_Invalid_Argument; 04055 04056 /* check freetype version */ 04057 if ( clazz->module_requires > FREETYPE_VER_FIXED ) 04058 return FT_Err_Invalid_Version; 04059 04060 /* look for a module with the same name in the library's table */ 04061 for ( nn = 0; nn < library->num_modules; nn++ ) 04062 { 04063 module = library->modules[nn]; 04064 if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 ) 04065 { 04066 /* this installed module has the same name, compare their versions */ 04067 if ( clazz->module_version <= module->clazz->module_version ) 04068 return FT_Err_Lower_Module_Version; 04069 04070 /* remove the module from our list, then exit the loop to replace */ 04071 /* it by our new version.. */ 04072 FT_Remove_Module( library, module ); 04073 break; 04074 } 04075 } 04076 04077 memory = library->memory; 04078 error = FT_Err_Ok; 04079 04080 if ( library->num_modules >= FT_MAX_MODULES ) 04081 { 04082 error = FT_Err_Too_Many_Drivers; 04083 goto Exit; 04084 } 04085 04086 /* allocate module object */ 04087 if ( FT_ALLOC( module, clazz->module_size ) ) 04088 goto Exit; 04089 04090 /* base initialization */ 04091 module->library = library; 04092 module->memory = memory; 04093 module->clazz = (FT_Module_Class*)clazz; 04094 04095 /* check whether the module is a renderer - this must be performed */ 04096 /* before the normal module initialization */ 04097 if ( FT_MODULE_IS_RENDERER( module ) ) 04098 { 04099 /* add to the renderers list */ 04100 error = ft_add_renderer( module ); 04101 if ( error ) 04102 goto Fail; 04103 } 04104 04105 /* is the module a auto-hinter? */ 04106 if ( FT_MODULE_IS_HINTER( module ) ) 04107 library->auto_hinter = module; 04108 04109 /* if the module is a font driver */ 04110 if ( FT_MODULE_IS_DRIVER( module ) ) 04111 { 04112 /* allocate glyph loader if needed */ 04113 FT_Driver driver = FT_DRIVER( module ); 04114 04115 04116 driver->clazz = (FT_Driver_Class)module->clazz; 04117 if ( FT_DRIVER_USES_OUTLINES( driver ) ) 04118 { 04119 error = FT_GlyphLoader_New( memory, &driver->glyph_loader ); 04120 if ( error ) 04121 goto Fail; 04122 } 04123 } 04124 04125 if ( clazz->module_init ) 04126 { 04127 error = clazz->module_init( module ); 04128 if ( error ) 04129 goto Fail; 04130 } 04131 04132 /* add module to the library's table */ 04133 library->modules[library->num_modules++] = module; 04134 04135 Exit: 04136 return error; 04137 04138 Fail: 04139 if ( FT_MODULE_IS_DRIVER( module ) ) 04140 { 04141 FT_Driver driver = FT_DRIVER( module ); 04142 04143 04144 if ( FT_DRIVER_USES_OUTLINES( driver ) ) 04145 FT_GlyphLoader_Done( driver->glyph_loader ); 04146 } 04147 04148 if ( FT_MODULE_IS_RENDERER( module ) ) 04149 { 04150 FT_Renderer renderer = FT_RENDERER( module ); 04151 04152 04153 if ( renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && 04154 renderer->raster ) 04155 renderer->clazz->raster_class->raster_done( renderer->raster ); 04156 } 04157 04158 FT_FREE( module ); 04159 goto Exit; 04160 } 04161 04162 04163 /* documentation is in ftmodapi.h */ 04164 04165 FT_EXPORT_DEF( FT_Module ) 04166 FT_Get_Module( FT_Library library, 04167 const char* module_name ) 04168 { 04169 FT_Module result = 0; 04170 FT_Module* cur; 04171 FT_Module* limit; 04172 04173 04174 if ( !library || !module_name ) 04175 return result; 04176 04177 cur = library->modules; 04178 limit = cur + library->num_modules; 04179 04180 for ( ; cur < limit; cur++ ) 04181 if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 ) 04182 { 04183 result = cur[0]; 04184 break; 04185 } 04186 04187 return result; 04188 } 04189 04190 04191 /* documentation is in ftobjs.h */ 04192 04193 FT_BASE_DEF( const void* ) 04194 FT_Get_Module_Interface( FT_Library library, 04195 const char* mod_name ) 04196 { 04197 FT_Module module; 04198 04199 04200 /* test for valid `library' delayed to FT_Get_Module() */ 04201 04202 module = FT_Get_Module( library, mod_name ); 04203 04204 return module ? module->clazz->module_interface : 0; 04205 } 04206 04207 04208 FT_BASE_DEF( FT_Pointer ) 04209 ft_module_get_service( FT_Module module, 04210 const char* service_id ) 04211 { 04212 FT_Pointer result = NULL; 04213 04214 if ( module ) 04215 { 04216 FT_ASSERT( module->clazz && module->clazz->get_interface ); 04217 04218 /* first, look for the service in the module 04219 */ 04220 if ( module->clazz->get_interface ) 04221 result = module->clazz->get_interface( module, service_id ); 04222 04223 if ( result == NULL ) 04224 { 04225 /* we didn't find it, look in all other modules then 04226 */ 04227 FT_Library library = module->library; 04228 FT_Module* cur = library->modules; 04229 FT_Module* limit = cur + library->num_modules; 04230 04231 for ( ; cur < limit; cur++ ) 04232 { 04233 if ( cur[0] != module ) 04234 { 04235 FT_ASSERT( cur[0]->clazz ); 04236 04237 if ( cur[0]->clazz->get_interface ) 04238 { 04239 result = cur[0]->clazz->get_interface( cur[0], service_id ); 04240 if ( result != NULL ) 04241 break; 04242 } 04243 } 04244 } 04245 } 04246 } 04247 04248 return result; 04249 } 04250 04251 04252 /* documentation is in ftmodapi.h */ 04253 04254 FT_EXPORT_DEF( FT_Error ) 04255 FT_Remove_Module( FT_Library library, 04256 FT_Module module ) 04257 { 04258 /* try to find the module from the table, then remove it from there */ 04259 04260 if ( !library ) 04261 return FT_Err_Invalid_Library_Handle; 04262 04263 if ( module ) 04264 { 04265 FT_Module* cur = library->modules; 04266 FT_Module* limit = cur + library->num_modules; 04267 04268 04269 for ( ; cur < limit; cur++ ) 04270 { 04271 if ( cur[0] == module ) 04272 { 04273 /* remove it from the table */ 04274 library->num_modules--; 04275 limit--; 04276 while ( cur < limit ) 04277 { 04278 cur[0] = cur[1]; 04279 cur++; 04280 } 04281 limit[0] = 0; 04282 04283 /* destroy the module */ 04284 Destroy_Module( module ); 04285 04286 return FT_Err_Ok; 04287 } 04288 } 04289 } 04290 return FT_Err_Invalid_Driver_Handle; 04291 } 04292 04293 04294 /*************************************************************************/ 04295 /*************************************************************************/ 04296 /*************************************************************************/ 04297 /**** ****/ 04298 /**** ****/ 04299 /**** L I B R A R Y ****/ 04300 /**** ****/ 04301 /**** ****/ 04302 /*************************************************************************/ 04303 /*************************************************************************/ 04304 /*************************************************************************/ 04305 04306 04307 /* documentation is in ftmodapi.h */ 04308 04309 FT_EXPORT_DEF( FT_Error ) 04310 FT_Reference_Library( FT_Library library ) 04311 { 04312 library->refcount++; 04313 04314 return FT_Err_Ok; 04315 } 04316 04317 04318 /* documentation is in ftmodapi.h */ 04319 04320 FT_EXPORT_DEF( FT_Error ) 04321 FT_New_Library( FT_Memory memory, 04322 FT_Library *alibrary ) 04323 { 04324 FT_Library library = NULL; 04325 FT_Error error; 04326 04327 04328 if ( !memory ) 04329 return FT_Err_Invalid_Argument; 04330 04331 #ifdef FT_DEBUG_LEVEL_ERROR 04332 /* init debugging support */ 04333 ft_debug_init(); 04334 #endif 04335 04336 /* first of all, allocate the library object */ 04337 if ( FT_NEW( library ) ) 04338 return error; 04339 04340 library->memory = memory; 04341 04342 #ifdef FT_CONFIG_OPTION_PIC 04343 /* initialize position independent code containers */ 04344 error = ft_pic_container_init( library ); 04345 if ( error ) 04346 goto Fail; 04347 #endif 04348 04349 /* allocate the render pool */ 04350 library->raster_pool_size = FT_RENDER_POOL_SIZE; 04351 #if FT_RENDER_POOL_SIZE > 0 04352 if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) ) 04353 goto Fail; 04354 #endif 04355 04356 library->version_major = FREETYPE_MAJOR; 04357 library->version_minor = FREETYPE_MINOR; 04358 library->version_patch = FREETYPE_PATCH; 04359 04360 library->refcount = 1; 04361 04362 /* That's ok now */ 04363 *alibrary = library; 04364 04365 return FT_Err_Ok; 04366 04367 Fail: 04368 #ifdef FT_CONFIG_OPTION_PIC 04369 ft_pic_container_destroy( library ); 04370 #endif 04371 FT_FREE( library ); 04372 return error; 04373 } 04374 04375 04376 /* documentation is in freetype.h */ 04377 04378 FT_EXPORT_DEF( void ) 04379 FT_Library_Version( FT_Library library, 04380 FT_Int *amajor, 04381 FT_Int *aminor, 04382 FT_Int *apatch ) 04383 { 04384 FT_Int major = 0; 04385 FT_Int minor = 0; 04386 FT_Int patch = 0; 04387 04388 04389 if ( library ) 04390 { 04391 major = library->version_major; 04392 minor = library->version_minor; 04393 patch = library->version_patch; 04394 } 04395 04396 if ( amajor ) 04397 *amajor = major; 04398 04399 if ( aminor ) 04400 *aminor = minor; 04401 04402 if ( apatch ) 04403 *apatch = patch; 04404 } 04405 04406 04407 /* documentation is in ftmodapi.h */ 04408 04409 FT_EXPORT_DEF( FT_Error ) 04410 FT_Done_Library( FT_Library library ) 04411 { 04412 FT_Memory memory; 04413 04414 04415 if ( !library ) 04416 return FT_Err_Invalid_Library_Handle; 04417 04418 library->refcount--; 04419 if ( library->refcount > 0 ) 04420 goto Exit; 04421 04422 memory = library->memory; 04423 04424 /* Discard client-data */ 04425 if ( library->generic.finalizer ) 04426 library->generic.finalizer( library ); 04427 04428 /* 04429 * Close all faces in the library. If we don't do this, we can have 04430 * some subtle memory leaks. 04431 * 04432 * Example: 04433 * 04434 * - the cff font driver uses the pshinter module in cff_size_done 04435 * - if the pshinter module is destroyed before the cff font driver, 04436 * opened FT_Face objects managed by the driver are not properly 04437 * destroyed, resulting in a memory leak 04438 * 04439 * Some faces are dependent on other faces, like Type42 faces that 04440 * depend on TrueType faces synthesized internally. 04441 * 04442 * The order of drivers should be specified in driver_name[]. 04443 */ 04444 { 04445 FT_UInt m, n; 04446 const char* driver_name[] = { "type42", NULL }; 04447 04448 04449 for ( m = 0; 04450 m < sizeof ( driver_name ) / sizeof ( driver_name[0] ); 04451 m++ ) 04452 { 04453 for ( n = 0; n < library->num_modules; n++ ) 04454 { 04455 FT_Module module = library->modules[n]; 04456 const char* module_name = module->clazz->module_name; 04457 FT_List faces; 04458 04459 04460 if ( driver_name[m] && 04461 ft_strcmp( module_name, driver_name[m] ) != 0 ) 04462 continue; 04463 04464 if ( ( module->clazz->module_flags & FT_MODULE_FONT_DRIVER ) == 0 ) 04465 continue; 04466 04467 FT_TRACE7(( "FT_Done_Library: close faces for %s\n", module_name )); 04468 04469 faces = &FT_DRIVER( module )->faces_list; 04470 while ( faces->head ) 04471 { 04472 FT_Done_Face( FT_FACE( faces->head->data ) ); 04473 if ( faces->head ) 04474 FT_TRACE0(( "FT_Done_Library: failed to free some faces\n" )); 04475 } 04476 } 04477 } 04478 } 04479 04480 /* Close all other modules in the library */ 04481 #if 1 04482 /* XXX Modules are removed in the reversed order so that */ 04483 /* type42 module is removed before truetype module. This */ 04484 /* avoids double free in some occasions. It is a hack. */ 04485 while ( library->num_modules > 0 ) 04486 FT_Remove_Module( library, 04487 library->modules[library->num_modules - 1] ); 04488 #else 04489 { 04490 FT_UInt n; 04491 04492 04493 for ( n = 0; n < library->num_modules; n++ ) 04494 { 04495 FT_Module module = library->modules[n]; 04496 04497 04498 if ( module ) 04499 { 04500 Destroy_Module( module ); 04501 library->modules[n] = 0; 04502 } 04503 } 04504 } 04505 #endif 04506 04507 /* Destroy raster objects */ 04508 FT_FREE( library->raster_pool ); 04509 library->raster_pool_size = 0; 04510 04511 #ifdef FT_CONFIG_OPTION_PIC 04512 /* Destroy pic container contents */ 04513 ft_pic_container_destroy( library ); 04514 #endif 04515 04516 FT_FREE( library ); 04517 04518 Exit: 04519 return FT_Err_Ok; 04520 } 04521 04522 04523 /* documentation is in ftmodapi.h */ 04524 04525 FT_EXPORT_DEF( void ) 04526 FT_Set_Debug_Hook( FT_Library library, 04527 FT_UInt hook_index, 04528 FT_DebugHook_Func debug_hook ) 04529 { 04530 if ( library && debug_hook && 04531 hook_index < 04532 ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) ) 04533 library->debug_hooks[hook_index] = debug_hook; 04534 } 04535 04536 04537 /* documentation is in ftmodapi.h */ 04538 04539 FT_EXPORT_DEF( FT_TrueTypeEngineType ) 04540 FT_Get_TrueType_Engine_Type( FT_Library library ) 04541 { 04542 FT_TrueTypeEngineType result = FT_TRUETYPE_ENGINE_TYPE_NONE; 04543 04544 04545 if ( library ) 04546 { 04547 FT_Module module = FT_Get_Module( library, "truetype" ); 04548 04549 04550 if ( module ) 04551 { 04552 FT_Service_TrueTypeEngine service; 04553 04554 04555 service = (FT_Service_TrueTypeEngine) 04556 ft_module_get_service( module, 04557 FT_SERVICE_ID_TRUETYPE_ENGINE ); 04558 if ( service ) 04559 result = service->engine_type; 04560 } 04561 } 04562 04563 return result; 04564 } 04565 04566 04567 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS 04568 04569 FT_BASE_DEF( FT_Error ) 04570 ft_stub_set_char_sizes( FT_Size size, 04571 FT_F26Dot6 width, 04572 FT_F26Dot6 height, 04573 FT_UInt horz_res, 04574 FT_UInt vert_res ) 04575 { 04576 FT_Size_RequestRec req; 04577 FT_Driver driver = size->face->driver; 04578 04579 04580 if ( driver->clazz->request_size ) 04581 { 04582 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL; 04583 req.width = width; 04584 req.height = height; 04585 04586 if ( horz_res == 0 ) 04587 horz_res = vert_res; 04588 04589 if ( vert_res == 0 ) 04590 vert_res = horz_res; 04591 04592 if ( horz_res == 0 ) 04593 horz_res = vert_res = 72; 04594 04595 req.horiResolution = horz_res; 04596 req.vertResolution = vert_res; 04597 04598 return driver->clazz->request_size( size, &req ); 04599 } 04600 04601 return 0; 04602 } 04603 04604 04605 FT_BASE_DEF( FT_Error ) 04606 ft_stub_set_pixel_sizes( FT_Size size, 04607 FT_UInt width, 04608 FT_UInt height ) 04609 { 04610 FT_Size_RequestRec req; 04611 FT_Driver driver = size->face->driver; 04612 04613 04614 if ( driver->clazz->request_size ) 04615 { 04616 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL; 04617 req.width = width << 6; 04618 req.height = height << 6; 04619 req.horiResolution = 0; 04620 req.vertResolution = 0; 04621 04622 return driver->clazz->request_size( size, &req ); 04623 } 04624 04625 return 0; 04626 } 04627 04628 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ 04629 04630 04631 /* documentation is in freetype.h */ 04632 04633 FT_EXPORT_DEF( FT_Error ) 04634 FT_Get_SubGlyph_Info( FT_GlyphSlot glyph, 04635 FT_UInt sub_index, 04636 FT_Int *p_index, 04637 FT_UInt *p_flags, 04638 FT_Int *p_arg1, 04639 FT_Int *p_arg2, 04640 FT_Matrix *p_transform ) 04641 { 04642 FT_Error error = FT_Err_Invalid_Argument; 04643 04644 04645 if ( glyph && 04646 glyph->subglyphs && 04647 glyph->format == FT_GLYPH_FORMAT_COMPOSITE && 04648 sub_index < glyph->num_subglyphs ) 04649 { 04650 FT_SubGlyph subg = glyph->subglyphs + sub_index; 04651 04652 04653 *p_index = subg->index; 04654 *p_flags = subg->flags; 04655 *p_arg1 = subg->arg1; 04656 *p_arg2 = subg->arg2; 04657 *p_transform = subg->transform; 04658 } 04659 04660 return error; 04661 } 04662 04663 04664 /* END */ Generated on Sat May 26 2012 04:32:38 for ReactOS by
1.7.6.1
|