Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpcfdrivr.c
Go to the documentation of this file.
00001 /* pcfdrivr.c 00002 00003 FreeType font driver for pcf files 00004 00005 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 by 00006 Francesco Zappa Nardelli 00007 00008 Permission is hereby granted, free of charge, to any person obtaining a copy 00009 of this software and associated documentation files (the "Software"), to deal 00010 in the Software without restriction, including without limitation the rights 00011 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00012 copies of the Software, and to permit persons to whom the Software is 00013 furnished to do so, subject to the following conditions: 00014 00015 The above copyright notice and this permission notice shall be included in 00016 all copies or substantial portions of the Software. 00017 00018 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00019 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00020 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00021 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00022 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00023 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00024 THE SOFTWARE. 00025 */ 00026 00027 00028 #include <ft2build.h> 00029 00030 #include FT_INTERNAL_DEBUG_H 00031 #include FT_INTERNAL_STREAM_H 00032 #include FT_INTERNAL_OBJECTS_H 00033 #include FT_GZIP_H 00034 #include FT_LZW_H 00035 #include FT_ERRORS_H 00036 #include FT_BDF_H 00037 #include FT_TRUETYPE_IDS_H 00038 00039 #include "pcf.h" 00040 #include "pcfdrivr.h" 00041 #include "pcfread.h" 00042 00043 #include "pcferror.h" 00044 #include "pcfutil.h" 00045 00046 #undef FT_COMPONENT 00047 #define FT_COMPONENT trace_pcfread 00048 00049 #include FT_SERVICE_BDF_H 00050 #include FT_SERVICE_XFREE86_NAME_H 00051 00052 00053 /*************************************************************************/ 00054 /* */ 00055 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 00056 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 00057 /* messages during execution. */ 00058 /* */ 00059 #undef FT_COMPONENT 00060 #define FT_COMPONENT trace_pcfdriver 00061 00062 00063 typedef struct PCF_CMapRec_ 00064 { 00065 FT_CMapRec root; 00066 FT_UInt num_encodings; 00067 PCF_Encoding encodings; 00068 00069 } PCF_CMapRec, *PCF_CMap; 00070 00071 00072 FT_CALLBACK_DEF( FT_Error ) 00073 pcf_cmap_init( FT_CMap pcfcmap, /* PCF_CMap */ 00074 FT_Pointer init_data ) 00075 { 00076 PCF_CMap cmap = (PCF_CMap)pcfcmap; 00077 PCF_Face face = (PCF_Face)FT_CMAP_FACE( pcfcmap ); 00078 00079 FT_UNUSED( init_data ); 00080 00081 00082 cmap->num_encodings = (FT_UInt)face->nencodings; 00083 cmap->encodings = face->encodings; 00084 00085 return PCF_Err_Ok; 00086 } 00087 00088 00089 FT_CALLBACK_DEF( void ) 00090 pcf_cmap_done( FT_CMap pcfcmap ) /* PCF_CMap */ 00091 { 00092 PCF_CMap cmap = (PCF_CMap)pcfcmap; 00093 00094 00095 cmap->encodings = NULL; 00096 cmap->num_encodings = 0; 00097 } 00098 00099 00100 FT_CALLBACK_DEF( FT_UInt ) 00101 pcf_cmap_char_index( FT_CMap pcfcmap, /* PCF_CMap */ 00102 FT_UInt32 charcode ) 00103 { 00104 PCF_CMap cmap = (PCF_CMap)pcfcmap; 00105 PCF_Encoding encodings = cmap->encodings; 00106 FT_UInt min, max, mid; 00107 FT_UInt result = 0; 00108 00109 00110 min = 0; 00111 max = cmap->num_encodings; 00112 00113 while ( min < max ) 00114 { 00115 FT_ULong code; 00116 00117 00118 mid = ( min + max ) >> 1; 00119 code = encodings[mid].enc; 00120 00121 if ( charcode == code ) 00122 { 00123 result = encodings[mid].glyph + 1; 00124 break; 00125 } 00126 00127 if ( charcode < code ) 00128 max = mid; 00129 else 00130 min = mid + 1; 00131 } 00132 00133 return result; 00134 } 00135 00136 00137 FT_CALLBACK_DEF( FT_UInt ) 00138 pcf_cmap_char_next( FT_CMap pcfcmap, /* PCF_CMap */ 00139 FT_UInt32 *acharcode ) 00140 { 00141 PCF_CMap cmap = (PCF_CMap)pcfcmap; 00142 PCF_Encoding encodings = cmap->encodings; 00143 FT_UInt min, max, mid; 00144 FT_ULong charcode = *acharcode + 1; 00145 FT_UInt result = 0; 00146 00147 00148 min = 0; 00149 max = cmap->num_encodings; 00150 00151 while ( min < max ) 00152 { 00153 FT_ULong code; 00154 00155 00156 mid = ( min + max ) >> 1; 00157 code = encodings[mid].enc; 00158 00159 if ( charcode == code ) 00160 { 00161 result = encodings[mid].glyph + 1; 00162 goto Exit; 00163 } 00164 00165 if ( charcode < code ) 00166 max = mid; 00167 else 00168 min = mid + 1; 00169 } 00170 00171 charcode = 0; 00172 if ( min < cmap->num_encodings ) 00173 { 00174 charcode = encodings[min].enc; 00175 result = encodings[min].glyph + 1; 00176 } 00177 00178 Exit: 00179 if ( charcode > 0xFFFFFFFFUL ) 00180 { 00181 FT_TRACE1(( "pcf_cmap_char_next: charcode 0x%x > 32bit API" )); 00182 *acharcode = 0; 00183 /* XXX: result should be changed to indicate an overflow error */ 00184 } 00185 else 00186 *acharcode = (FT_UInt32)charcode; 00187 return result; 00188 } 00189 00190 00191 FT_CALLBACK_TABLE_DEF 00192 const FT_CMap_ClassRec pcf_cmap_class = 00193 { 00194 sizeof ( PCF_CMapRec ), 00195 pcf_cmap_init, 00196 pcf_cmap_done, 00197 pcf_cmap_char_index, 00198 pcf_cmap_char_next, 00199 00200 NULL, NULL, NULL, NULL, NULL 00201 }; 00202 00203 00204 FT_CALLBACK_DEF( void ) 00205 PCF_Face_Done( FT_Face pcfface ) /* PCF_Face */ 00206 { 00207 PCF_Face face = (PCF_Face)pcfface; 00208 FT_Memory memory; 00209 00210 00211 if ( !face ) 00212 return; 00213 00214 memory = FT_FACE_MEMORY( face ); 00215 00216 FT_FREE( face->encodings ); 00217 FT_FREE( face->metrics ); 00218 00219 /* free properties */ 00220 { 00221 PCF_Property prop; 00222 FT_Int i; 00223 00224 00225 if ( face->properties ) 00226 { 00227 for ( i = 0; i < face->nprops; i++ ) 00228 { 00229 prop = &face->properties[i]; 00230 00231 if ( prop ) 00232 { 00233 FT_FREE( prop->name ); 00234 if ( prop->isString ) 00235 FT_FREE( prop->value.atom ); 00236 } 00237 } 00238 } 00239 FT_FREE( face->properties ); 00240 } 00241 00242 FT_FREE( face->toc.tables ); 00243 FT_FREE( pcfface->family_name ); 00244 FT_FREE( pcfface->style_name ); 00245 FT_FREE( pcfface->available_sizes ); 00246 FT_FREE( face->charset_encoding ); 00247 FT_FREE( face->charset_registry ); 00248 00249 FT_TRACE4(( "PCF_Face_Done: done face\n" )); 00250 00251 /* close gzip/LZW stream if any */ 00252 if ( pcfface->stream == &face->gzip_stream ) 00253 { 00254 FT_Stream_Close( &face->gzip_stream ); 00255 pcfface->stream = face->gzip_source; 00256 } 00257 } 00258 00259 00260 FT_CALLBACK_DEF( FT_Error ) 00261 PCF_Face_Init( FT_Stream stream, 00262 FT_Face pcfface, /* PCF_Face */ 00263 FT_Int face_index, 00264 FT_Int num_params, 00265 FT_Parameter* params ) 00266 { 00267 PCF_Face face = (PCF_Face)pcfface; 00268 FT_Error error = PCF_Err_Ok; 00269 00270 FT_UNUSED( num_params ); 00271 FT_UNUSED( params ); 00272 FT_UNUSED( face_index ); 00273 00274 00275 error = pcf_load_font( stream, face ); 00276 if ( error ) 00277 { 00278 PCF_Face_Done( pcfface ); 00279 00280 #if defined( FT_CONFIG_OPTION_USE_ZLIB ) || \ 00281 defined( FT_CONFIG_OPTION_USE_LZW ) 00282 00283 #ifdef FT_CONFIG_OPTION_USE_ZLIB 00284 { 00285 FT_Error error2; 00286 00287 00288 /* this didn't work, try gzip support! */ 00289 error2 = FT_Stream_OpenGzip( &face->gzip_stream, stream ); 00290 if ( FT_ERROR_BASE( error2 ) == FT_Err_Unimplemented_Feature ) 00291 goto Fail; 00292 00293 error = error2; 00294 } 00295 #endif /* FT_CONFIG_OPTION_USE_ZLIB */ 00296 00297 #ifdef FT_CONFIG_OPTION_USE_LZW 00298 if ( error ) 00299 { 00300 FT_Error error3; 00301 00302 00303 /* this didn't work, try LZW support! */ 00304 error3 = FT_Stream_OpenLZW( &face->gzip_stream, stream ); 00305 if ( FT_ERROR_BASE( error3 ) == FT_Err_Unimplemented_Feature ) 00306 goto Fail; 00307 00308 error = error3; 00309 } 00310 #endif /* FT_CONFIG_OPTION_USE_LZW */ 00311 00312 if ( error ) 00313 goto Fail; 00314 00315 face->gzip_source = stream; 00316 pcfface->stream = &face->gzip_stream; 00317 00318 stream = pcfface->stream; 00319 00320 error = pcf_load_font( stream, face ); 00321 if ( error ) 00322 goto Fail; 00323 00324 #else /* !(FT_CONFIG_OPTION_USE_ZLIB || FT_CONFIG_OPTION_USE_LZW) */ 00325 00326 goto Fail; 00327 00328 #endif 00329 } 00330 00331 /* set up charmap */ 00332 { 00333 FT_String *charset_registry = face->charset_registry; 00334 FT_String *charset_encoding = face->charset_encoding; 00335 FT_Bool unicode_charmap = 0; 00336 00337 00338 if ( charset_registry && charset_encoding ) 00339 { 00340 char* s = charset_registry; 00341 00342 00343 /* Uh, oh, compare first letters manually to avoid dependency 00344 on locales. */ 00345 if ( ( s[0] == 'i' || s[0] == 'I' ) && 00346 ( s[1] == 's' || s[1] == 'S' ) && 00347 ( s[2] == 'o' || s[2] == 'O' ) ) 00348 { 00349 s += 3; 00350 if ( !ft_strcmp( s, "10646" ) || 00351 ( !ft_strcmp( s, "8859" ) && 00352 !ft_strcmp( face->charset_encoding, "1" ) ) ) 00353 unicode_charmap = 1; 00354 } 00355 } 00356 00357 { 00358 FT_CharMapRec charmap; 00359 00360 00361 charmap.face = FT_FACE( face ); 00362 charmap.encoding = FT_ENCODING_NONE; 00363 /* initial platform/encoding should indicate unset status? */ 00364 charmap.platform_id = TT_PLATFORM_APPLE_UNICODE; 00365 charmap.encoding_id = TT_APPLE_ID_DEFAULT; 00366 00367 if ( unicode_charmap ) 00368 { 00369 charmap.encoding = FT_ENCODING_UNICODE; 00370 charmap.platform_id = TT_PLATFORM_MICROSOFT; 00371 charmap.encoding_id = TT_MS_ID_UNICODE_CS; 00372 } 00373 00374 error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL ); 00375 00376 #if 0 00377 /* Select default charmap */ 00378 if ( pcfface->num_charmaps ) 00379 pcfface->charmap = pcfface->charmaps[0]; 00380 #endif 00381 } 00382 } 00383 00384 Exit: 00385 return error; 00386 00387 Fail: 00388 FT_TRACE2(( "[not a valid PCF file]\n" )); 00389 PCF_Face_Done( pcfface ); 00390 error = PCF_Err_Unknown_File_Format; /* error */ 00391 goto Exit; 00392 } 00393 00394 00395 FT_CALLBACK_DEF( FT_Error ) 00396 PCF_Size_Select( FT_Size size, 00397 FT_ULong strike_index ) 00398 { 00399 PCF_Accel accel = &( (PCF_Face)size->face )->accel; 00400 00401 00402 FT_Select_Metrics( size->face, strike_index ); 00403 00404 size->metrics.ascender = accel->fontAscent << 6; 00405 size->metrics.descender = -accel->fontDescent << 6; 00406 size->metrics.max_advance = accel->maxbounds.characterWidth << 6; 00407 00408 return PCF_Err_Ok; 00409 } 00410 00411 00412 FT_CALLBACK_DEF( FT_Error ) 00413 PCF_Size_Request( FT_Size size, 00414 FT_Size_Request req ) 00415 { 00416 PCF_Face face = (PCF_Face)size->face; 00417 FT_Bitmap_Size* bsize = size->face->available_sizes; 00418 FT_Error error = PCF_Err_Invalid_Pixel_Size; 00419 FT_Long height; 00420 00421 00422 height = FT_REQUEST_HEIGHT( req ); 00423 height = ( height + 32 ) >> 6; 00424 00425 switch ( req->type ) 00426 { 00427 case FT_SIZE_REQUEST_TYPE_NOMINAL: 00428 if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) ) 00429 error = PCF_Err_Ok; 00430 break; 00431 00432 case FT_SIZE_REQUEST_TYPE_REAL_DIM: 00433 if ( height == ( face->accel.fontAscent + 00434 face->accel.fontDescent ) ) 00435 error = PCF_Err_Ok; 00436 break; 00437 00438 default: 00439 error = PCF_Err_Unimplemented_Feature; 00440 break; 00441 } 00442 00443 if ( error ) 00444 return error; 00445 else 00446 return PCF_Size_Select( size, 0 ); 00447 } 00448 00449 00450 FT_CALLBACK_DEF( FT_Error ) 00451 PCF_Glyph_Load( FT_GlyphSlot slot, 00452 FT_Size size, 00453 FT_UInt glyph_index, 00454 FT_Int32 load_flags ) 00455 { 00456 PCF_Face face = (PCF_Face)FT_SIZE_FACE( size ); 00457 FT_Stream stream; 00458 FT_Error error = PCF_Err_Ok; 00459 FT_Bitmap* bitmap = &slot->bitmap; 00460 PCF_Metric metric; 00461 FT_Offset bytes; 00462 00463 FT_UNUSED( load_flags ); 00464 00465 00466 FT_TRACE4(( "load_glyph %d ---", glyph_index )); 00467 00468 if ( !face || glyph_index >= (FT_UInt)face->root.num_glyphs ) 00469 { 00470 error = PCF_Err_Invalid_Argument; 00471 goto Exit; 00472 } 00473 00474 stream = face->root.stream; 00475 00476 if ( glyph_index > 0 ) 00477 glyph_index--; 00478 00479 metric = face->metrics + glyph_index; 00480 00481 bitmap->rows = metric->ascent + metric->descent; 00482 bitmap->width = metric->rightSideBearing - metric->leftSideBearing; 00483 bitmap->num_grays = 1; 00484 bitmap->pixel_mode = FT_PIXEL_MODE_MONO; 00485 00486 FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n", 00487 PCF_BIT_ORDER( face->bitmapsFormat ), 00488 PCF_BYTE_ORDER( face->bitmapsFormat ), 00489 PCF_GLYPH_PAD( face->bitmapsFormat ) )); 00490 00491 switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) ) 00492 { 00493 case 1: 00494 bitmap->pitch = ( bitmap->width + 7 ) >> 3; 00495 break; 00496 00497 case 2: 00498 bitmap->pitch = ( ( bitmap->width + 15 ) >> 4 ) << 1; 00499 break; 00500 00501 case 4: 00502 bitmap->pitch = ( ( bitmap->width + 31 ) >> 5 ) << 2; 00503 break; 00504 00505 case 8: 00506 bitmap->pitch = ( ( bitmap->width + 63 ) >> 6 ) << 3; 00507 break; 00508 00509 default: 00510 return PCF_Err_Invalid_File_Format; 00511 } 00512 00513 /* XXX: to do: are there cases that need repadding the bitmap? */ 00514 bytes = bitmap->pitch * bitmap->rows; 00515 00516 error = ft_glyphslot_alloc_bitmap( slot, bytes ); 00517 if ( error ) 00518 goto Exit; 00519 00520 if ( FT_STREAM_SEEK( metric->bits ) || 00521 FT_STREAM_READ( bitmap->buffer, bytes ) ) 00522 goto Exit; 00523 00524 if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst ) 00525 BitOrderInvert( bitmap->buffer, bytes ); 00526 00527 if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) != 00528 PCF_BIT_ORDER( face->bitmapsFormat ) ) ) 00529 { 00530 switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) ) 00531 { 00532 case 1: 00533 break; 00534 00535 case 2: 00536 TwoByteSwap( bitmap->buffer, bytes ); 00537 break; 00538 00539 case 4: 00540 FourByteSwap( bitmap->buffer, bytes ); 00541 break; 00542 } 00543 } 00544 00545 slot->format = FT_GLYPH_FORMAT_BITMAP; 00546 slot->bitmap_left = metric->leftSideBearing; 00547 slot->bitmap_top = metric->ascent; 00548 00549 slot->metrics.horiAdvance = metric->characterWidth << 6; 00550 slot->metrics.horiBearingX = metric->leftSideBearing << 6; 00551 slot->metrics.horiBearingY = metric->ascent << 6; 00552 slot->metrics.width = ( metric->rightSideBearing - 00553 metric->leftSideBearing ) << 6; 00554 slot->metrics.height = bitmap->rows << 6; 00555 00556 ft_synthesize_vertical_metrics( &slot->metrics, 00557 ( face->accel.fontAscent + 00558 face->accel.fontDescent ) << 6 ); 00559 00560 FT_TRACE4(( " --- ok\n" )); 00561 00562 Exit: 00563 return error; 00564 } 00565 00566 00567 /* 00568 * 00569 * BDF SERVICE 00570 * 00571 */ 00572 00573 static FT_Error 00574 pcf_get_bdf_property( PCF_Face face, 00575 const char* prop_name, 00576 BDF_PropertyRec *aproperty ) 00577 { 00578 PCF_Property prop; 00579 00580 00581 prop = pcf_find_property( face, prop_name ); 00582 if ( prop != NULL ) 00583 { 00584 if ( prop->isString ) 00585 { 00586 aproperty->type = BDF_PROPERTY_TYPE_ATOM; 00587 aproperty->u.atom = prop->value.atom; 00588 } 00589 else 00590 { 00591 if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) ) 00592 { 00593 FT_TRACE1(( "pcf_get_bdf_property: " )); 00594 FT_TRACE1(( "too large integer 0x%x is truncated\n" )); 00595 } 00596 /* Apparently, the PCF driver loads all properties as signed integers! 00597 * This really doesn't seem to be a problem, because this is 00598 * sufficient for any meaningful values. 00599 */ 00600 aproperty->type = BDF_PROPERTY_TYPE_INTEGER; 00601 aproperty->u.integer = (FT_Int32)prop->value.l; 00602 } 00603 return 0; 00604 } 00605 00606 return PCF_Err_Invalid_Argument; 00607 } 00608 00609 00610 static FT_Error 00611 pcf_get_charset_id( PCF_Face face, 00612 const char* *acharset_encoding, 00613 const char* *acharset_registry ) 00614 { 00615 *acharset_encoding = face->charset_encoding; 00616 *acharset_registry = face->charset_registry; 00617 00618 return 0; 00619 } 00620 00621 00622 static const FT_Service_BDFRec pcf_service_bdf = 00623 { 00624 (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id, 00625 (FT_BDF_GetPropertyFunc) pcf_get_bdf_property 00626 }; 00627 00628 00629 /* 00630 * 00631 * SERVICE LIST 00632 * 00633 */ 00634 00635 static const FT_ServiceDescRec pcf_services[] = 00636 { 00637 { FT_SERVICE_ID_BDF, &pcf_service_bdf }, 00638 { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_PCF }, 00639 { NULL, NULL } 00640 }; 00641 00642 00643 FT_CALLBACK_DEF( FT_Module_Interface ) 00644 pcf_driver_requester( FT_Module module, 00645 const char* name ) 00646 { 00647 FT_UNUSED( module ); 00648 00649 return ft_service_list_lookup( pcf_services, name ); 00650 } 00651 00652 00653 FT_CALLBACK_TABLE_DEF 00654 const FT_Driver_ClassRec pcf_driver_class = 00655 { 00656 { 00657 FT_MODULE_FONT_DRIVER | 00658 FT_MODULE_DRIVER_NO_OUTLINES, 00659 sizeof ( FT_DriverRec ), 00660 00661 "pcf", 00662 0x10000L, 00663 0x20000L, 00664 00665 0, 00666 00667 0, 00668 0, 00669 pcf_driver_requester 00670 }, 00671 00672 sizeof ( PCF_FaceRec ), 00673 sizeof ( FT_SizeRec ), 00674 sizeof ( FT_GlyphSlotRec ), 00675 00676 PCF_Face_Init, 00677 PCF_Face_Done, 00678 0, /* FT_Size_InitFunc */ 00679 0, /* FT_Size_DoneFunc */ 00680 0, /* FT_Slot_InitFunc */ 00681 0, /* FT_Slot_DoneFunc */ 00682 00683 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS 00684 ft_stub_set_char_sizes, 00685 ft_stub_set_pixel_sizes, 00686 #endif 00687 PCF_Glyph_Load, 00688 00689 0, /* FT_Face_GetKerningFunc */ 00690 0, /* FT_Face_AttachFunc */ 00691 0, /* FT_Face_GetAdvancesFunc */ 00692 00693 PCF_Size_Request, 00694 PCF_Size_Select 00695 }; 00696 00697 00698 /* END */ Generated on Thu May 24 2012 04:34:22 for ReactOS by
1.7.6.1
|