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

Generated on Tue Jul 5 14:13:48 2011 for ROOT_528-00b_version by  doxygen 1.5.1