ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pcfread.c
Go to the documentation of this file.
00001 /*  pcfread.c
00002 
00003     FreeType font driver for pcf fonts
00004 
00005   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
00006             2010 by
00007   Francesco Zappa Nardelli
00008 
00009 Permission is hereby granted, free of charge, to any person obtaining a copy
00010 of this software and associated documentation files (the "Software"), to deal
00011 in the Software without restriction, including without limitation the rights
00012 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00013 copies of the Software, and to permit persons to whom the Software is
00014 furnished to do so, subject to the following conditions:
00015 
00016 The above copyright notice and this permission notice shall be included in
00017 all copies or substantial portions of the Software.
00018 
00019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00020 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00021 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00022 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00023 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00024 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00025 THE SOFTWARE.
00026 */
00027 
00028 
00029 #include <ft2build.h>
00030 
00031 #include FT_INTERNAL_DEBUG_H
00032 #include FT_INTERNAL_STREAM_H
00033 #include FT_INTERNAL_OBJECTS_H
00034 
00035 #include "pcf.h"
00036 #include "pcfread.h"
00037 
00038 #include "pcferror.h"
00039 
00040 
00041   /*************************************************************************/
00042   /*                                                                       */
00043   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00044   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00045   /* messages during execution.                                            */
00046   /*                                                                       */
00047 #undef  FT_COMPONENT
00048 #define FT_COMPONENT  trace_pcfread
00049 
00050 
00051 #ifdef FT_DEBUG_LEVEL_TRACE
00052   static const char* const  tableNames[] =
00053   {
00054     "prop", "accl", "mtrcs", "bmps", "imtrcs",
00055     "enc", "swidth", "names", "accel"
00056   };
00057 #endif
00058 
00059 
00060   static
00061   const FT_Frame_Field  pcf_toc_header[] =
00062   {
00063 #undef  FT_STRUCTURE
00064 #define FT_STRUCTURE  PCF_TocRec
00065 
00066     FT_FRAME_START( 8 ),
00067       FT_FRAME_ULONG_LE( version ),
00068       FT_FRAME_ULONG_LE( count ),
00069     FT_FRAME_END
00070   };
00071 
00072 
00073   static
00074   const FT_Frame_Field  pcf_table_header[] =
00075   {
00076 #undef  FT_STRUCTURE
00077 #define FT_STRUCTURE  PCF_TableRec
00078 
00079     FT_FRAME_START( 16  ),
00080       FT_FRAME_ULONG_LE( type ),
00081       FT_FRAME_ULONG_LE( format ),
00082       FT_FRAME_ULONG_LE( size ),
00083       FT_FRAME_ULONG_LE( offset ),
00084     FT_FRAME_END
00085   };
00086 
00087 
00088   static FT_Error
00089   pcf_read_TOC( FT_Stream  stream,
00090                 PCF_Face   face )
00091   {
00092     FT_Error   error;
00093     PCF_Toc    toc = &face->toc;
00094     PCF_Table  tables;
00095 
00096     FT_Memory  memory = FT_FACE(face)->memory;
00097     FT_UInt    n;
00098 
00099 
00100     if ( FT_STREAM_SEEK ( 0 )                          ||
00101          FT_STREAM_READ_FIELDS ( pcf_toc_header, toc ) )
00102       return PCF_Err_Cannot_Open_Resource;
00103 
00104     if ( toc->version != PCF_FILE_VERSION                 ||
00105          toc->count   >  FT_ARRAY_MAX( face->toc.tables ) ||
00106          toc->count   == 0                                )
00107       return PCF_Err_Invalid_File_Format;
00108 
00109     if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) )
00110       return PCF_Err_Out_Of_Memory;
00111 
00112     tables = face->toc.tables;
00113     for ( n = 0; n < toc->count; n++ )
00114     {
00115       if ( FT_STREAM_READ_FIELDS( pcf_table_header, tables ) )
00116         goto Exit;
00117       tables++;
00118     }
00119 
00120     /* Sort tables and check for overlaps.  Because they are almost      */
00121     /* always ordered already, an in-place bubble sort with simultaneous */
00122     /* boundary checking seems appropriate.                              */
00123     tables = face->toc.tables;
00124 
00125     for ( n = 0; n < toc->count - 1; n++ )
00126     {
00127       FT_UInt  i, have_change;
00128 
00129 
00130       have_change = 0;
00131 
00132       for ( i = 0; i < toc->count - 1 - n; i++ )
00133       {
00134         PCF_TableRec  tmp;
00135 
00136 
00137         if ( tables[i].offset > tables[i + 1].offset )
00138         {
00139           tmp           = tables[i];
00140           tables[i]     = tables[i + 1];
00141           tables[i + 1] = tmp;
00142 
00143           have_change = 1;
00144         }
00145 
00146         if ( ( tables[i].size   > tables[i + 1].offset )                  ||
00147              ( tables[i].offset > tables[i + 1].offset - tables[i].size ) )
00148           return PCF_Err_Invalid_Offset;
00149       }
00150 
00151       if ( !have_change )
00152         break;
00153     }
00154 
00155 #ifdef FT_DEBUG_LEVEL_TRACE
00156 
00157     {
00158       FT_UInt      i, j;
00159       const char*  name = "?";
00160 
00161 
00162       FT_TRACE4(( "pcf_read_TOC:\n" ));
00163 
00164       FT_TRACE4(( "  number of tables: %ld\n", face->toc.count ));
00165 
00166       tables = face->toc.tables;
00167       for ( i = 0; i < toc->count; i++ )
00168       {
00169         for ( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] );
00170               j++ )
00171           if ( tables[i].type == (FT_UInt)( 1 << j ) )
00172             name = tableNames[j];
00173 
00174         FT_TRACE4(( "  %d: type=%s, format=0x%X, "
00175                     "size=%ld (0x%lX), offset=%ld (0x%lX)\n",
00176                     i, name,
00177                     tables[i].format,
00178                     tables[i].size, tables[i].size,
00179                     tables[i].offset, tables[i].offset ));
00180       }
00181     }
00182 
00183 #endif
00184 
00185     return PCF_Err_Ok;
00186 
00187   Exit:
00188     FT_FREE( face->toc.tables );
00189     return error;
00190   }
00191 
00192 
00193 #define PCF_METRIC_SIZE  12
00194 
00195   static
00196   const FT_Frame_Field  pcf_metric_header[] =
00197   {
00198 #undef  FT_STRUCTURE
00199 #define FT_STRUCTURE  PCF_MetricRec
00200 
00201     FT_FRAME_START( PCF_METRIC_SIZE ),
00202       FT_FRAME_SHORT_LE( leftSideBearing ),
00203       FT_FRAME_SHORT_LE( rightSideBearing ),
00204       FT_FRAME_SHORT_LE( characterWidth ),
00205       FT_FRAME_SHORT_LE( ascent ),
00206       FT_FRAME_SHORT_LE( descent ),
00207       FT_FRAME_SHORT_LE( attributes ),
00208     FT_FRAME_END
00209   };
00210 
00211 
00212   static
00213   const FT_Frame_Field  pcf_metric_msb_header[] =
00214   {
00215 #undef  FT_STRUCTURE
00216 #define FT_STRUCTURE  PCF_MetricRec
00217 
00218     FT_FRAME_START( PCF_METRIC_SIZE ),
00219       FT_FRAME_SHORT( leftSideBearing ),
00220       FT_FRAME_SHORT( rightSideBearing ),
00221       FT_FRAME_SHORT( characterWidth ),
00222       FT_FRAME_SHORT( ascent ),
00223       FT_FRAME_SHORT( descent ),
00224       FT_FRAME_SHORT( attributes ),
00225     FT_FRAME_END
00226   };
00227 
00228 
00229 #define PCF_COMPRESSED_METRIC_SIZE  5
00230 
00231   static
00232   const FT_Frame_Field  pcf_compressed_metric_header[] =
00233   {
00234 #undef  FT_STRUCTURE
00235 #define FT_STRUCTURE  PCF_Compressed_MetricRec
00236 
00237     FT_FRAME_START( PCF_COMPRESSED_METRIC_SIZE ),
00238       FT_FRAME_BYTE( leftSideBearing ),
00239       FT_FRAME_BYTE( rightSideBearing ),
00240       FT_FRAME_BYTE( characterWidth ),
00241       FT_FRAME_BYTE( ascent ),
00242       FT_FRAME_BYTE( descent ),
00243     FT_FRAME_END
00244   };
00245 
00246 
00247   static FT_Error
00248   pcf_get_metric( FT_Stream   stream,
00249                   FT_ULong    format,
00250                   PCF_Metric  metric )
00251   {
00252     FT_Error  error = PCF_Err_Ok;
00253 
00254 
00255     if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
00256     {
00257       const FT_Frame_Field*  fields;
00258 
00259 
00260       /* parsing normal metrics */
00261       fields = PCF_BYTE_ORDER( format ) == MSBFirst
00262                ? pcf_metric_msb_header
00263                : pcf_metric_header;
00264 
00265       /* the following sets `error' but doesn't return in case of failure */
00266       (void)FT_STREAM_READ_FIELDS( fields, metric );
00267     }
00268     else
00269     {
00270       PCF_Compressed_MetricRec  compr;
00271 
00272 
00273       /* parsing compressed metrics */
00274       if ( FT_STREAM_READ_FIELDS( pcf_compressed_metric_header, &compr ) )
00275         goto Exit;
00276 
00277       metric->leftSideBearing  = (FT_Short)( compr.leftSideBearing  - 0x80 );
00278       metric->rightSideBearing = (FT_Short)( compr.rightSideBearing - 0x80 );
00279       metric->characterWidth   = (FT_Short)( compr.characterWidth   - 0x80 );
00280       metric->ascent           = (FT_Short)( compr.ascent           - 0x80 );
00281       metric->descent          = (FT_Short)( compr.descent          - 0x80 );
00282       metric->attributes       = 0;
00283     }
00284 
00285   Exit:
00286     return error;
00287   }
00288 
00289 
00290   static FT_Error
00291   pcf_seek_to_table_type( FT_Stream  stream,
00292                           PCF_Table  tables,
00293                           FT_ULong   ntables, /* same as PCF_Toc->count */
00294                           FT_ULong   type,
00295                           FT_ULong  *aformat,
00296                           FT_ULong  *asize )
00297   {
00298     FT_Error  error = PCF_Err_Invalid_File_Format;
00299     FT_ULong  i;
00300 
00301 
00302     for ( i = 0; i < ntables; i++ )
00303       if ( tables[i].type == type )
00304       {
00305         if ( stream->pos > tables[i].offset )
00306         {
00307           error = PCF_Err_Invalid_Stream_Skip;
00308           goto Fail;
00309         }
00310 
00311         if ( FT_STREAM_SKIP( tables[i].offset - stream->pos ) )
00312         {
00313           error = PCF_Err_Invalid_Stream_Skip;
00314           goto Fail;
00315         }
00316 
00317         *asize   = tables[i].size;
00318         *aformat = tables[i].format;
00319 
00320         return PCF_Err_Ok;
00321       }
00322 
00323   Fail:
00324     *asize = 0;
00325     return error;
00326   }
00327 
00328 
00329   static FT_Bool
00330   pcf_has_table_type( PCF_Table  tables,
00331                       FT_ULong   ntables, /* same as PCF_Toc->count */
00332                       FT_ULong   type )
00333   {
00334     FT_ULong  i;
00335 
00336 
00337     for ( i = 0; i < ntables; i++ )
00338       if ( tables[i].type == type )
00339         return TRUE;
00340 
00341     return FALSE;
00342   }
00343 
00344 
00345 #define PCF_PROPERTY_SIZE  9
00346 
00347   static
00348   const FT_Frame_Field  pcf_property_header[] =
00349   {
00350 #undef  FT_STRUCTURE
00351 #define FT_STRUCTURE  PCF_ParsePropertyRec
00352 
00353     FT_FRAME_START( PCF_PROPERTY_SIZE ),
00354       FT_FRAME_LONG_LE( name ),
00355       FT_FRAME_BYTE   ( isString ),
00356       FT_FRAME_LONG_LE( value ),
00357     FT_FRAME_END
00358   };
00359 
00360 
00361   static
00362   const FT_Frame_Field  pcf_property_msb_header[] =
00363   {
00364 #undef  FT_STRUCTURE
00365 #define FT_STRUCTURE  PCF_ParsePropertyRec
00366 
00367     FT_FRAME_START( PCF_PROPERTY_SIZE ),
00368       FT_FRAME_LONG( name ),
00369       FT_FRAME_BYTE( isString ),
00370       FT_FRAME_LONG( value ),
00371     FT_FRAME_END
00372   };
00373 
00374 
00375   FT_LOCAL_DEF( PCF_Property )
00376   pcf_find_property( PCF_Face          face,
00377                      const FT_String*  prop )
00378   {
00379     PCF_Property  properties = face->properties;
00380     FT_Bool       found      = 0;
00381     int           i;
00382 
00383 
00384     for ( i = 0 ; i < face->nprops && !found; i++ )
00385     {
00386       if ( !ft_strcmp( properties[i].name, prop ) )
00387         found = 1;
00388     }
00389 
00390     if ( found )
00391       return properties + i - 1;
00392     else
00393       return NULL;
00394   }
00395 
00396 
00397   static FT_Error
00398   pcf_get_properties( FT_Stream  stream,
00399                       PCF_Face   face )
00400   {
00401     PCF_ParseProperty  props      = 0;
00402     PCF_Property       properties;
00403     FT_ULong           nprops, i;
00404     FT_ULong           format, size;
00405     FT_Error           error;
00406     FT_Memory          memory     = FT_FACE(face)->memory;
00407     FT_ULong           string_size;
00408     FT_String*         strings    = 0;
00409 
00410 
00411     error = pcf_seek_to_table_type( stream,
00412                                     face->toc.tables,
00413                                     face->toc.count,
00414                                     PCF_PROPERTIES,
00415                                     &format,
00416                                     &size );
00417     if ( error )
00418       goto Bail;
00419 
00420     if ( FT_READ_ULONG_LE( format ) )
00421       goto Bail;
00422 
00423     FT_TRACE4(( "pcf_get_properties:\n" ));
00424 
00425     FT_TRACE4(( "  format = %ld\n", format ));
00426 
00427     if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
00428       goto Bail;
00429 
00430     if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00431       (void)FT_READ_ULONG( nprops );
00432     else
00433       (void)FT_READ_ULONG_LE( nprops );
00434     if ( error )
00435       goto Bail;
00436 
00437     FT_TRACE4(( "  nprop = %d (truncate %d props)\n",
00438                 (int)nprops, nprops - (int)nprops ));
00439 
00440     nprops = (int)nprops;
00441 
00442     /* rough estimate */
00443     if ( nprops > size / PCF_PROPERTY_SIZE )
00444     {
00445       error = PCF_Err_Invalid_Table;
00446       goto Bail;
00447     }
00448 
00449     face->nprops = (int)nprops;
00450 
00451     if ( FT_NEW_ARRAY( props, nprops ) )
00452       goto Bail;
00453 
00454     for ( i = 0; i < nprops; i++ )
00455     {
00456       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00457       {
00458         if ( FT_STREAM_READ_FIELDS( pcf_property_msb_header, props + i ) )
00459           goto Bail;
00460       }
00461       else
00462       {
00463         if ( FT_STREAM_READ_FIELDS( pcf_property_header, props + i ) )
00464           goto Bail;
00465       }
00466     }
00467 
00468     /* pad the property array                                            */
00469     /*                                                                   */
00470     /* clever here - nprops is the same as the number of odd-units read, */
00471     /* as only isStringProp are odd length   (Keith Packard)             */
00472     /*                                                                   */
00473     if ( nprops & 3 )
00474     {
00475       i = 4 - ( nprops & 3 );
00476       if ( FT_STREAM_SKIP( i ) )
00477       {
00478         error = PCF_Err_Invalid_Stream_Skip;
00479         goto Bail;
00480       }
00481     }
00482 
00483     if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00484       (void)FT_READ_ULONG( string_size );
00485     else
00486       (void)FT_READ_ULONG_LE( string_size );
00487     if ( error )
00488       goto Bail;
00489 
00490     FT_TRACE4(( "  string_size = %ld\n", string_size ));
00491 
00492     /* rough estimate */
00493     if ( string_size > size - nprops * PCF_PROPERTY_SIZE )
00494     {
00495       error = PCF_Err_Invalid_Table;
00496       goto Bail;
00497     }
00498 
00499     if ( FT_NEW_ARRAY( strings, string_size ) )
00500       goto Bail;
00501 
00502     error = FT_Stream_Read( stream, (FT_Byte*)strings, string_size );
00503     if ( error )
00504       goto Bail;
00505 
00506     if ( FT_NEW_ARRAY( properties, nprops ) )
00507       goto Bail;
00508 
00509     face->properties = properties;
00510 
00511     for ( i = 0; i < nprops; i++ )
00512     {
00513       FT_Long  name_offset = props[i].name;
00514 
00515 
00516       if ( ( name_offset < 0 )                     ||
00517            ( (FT_ULong)name_offset > string_size ) )
00518       {
00519         error = PCF_Err_Invalid_Offset;
00520         goto Bail;
00521       }
00522 
00523       if ( FT_STRDUP( properties[i].name, strings + name_offset ) )
00524         goto Bail;
00525 
00526       FT_TRACE4(( "  %s:", properties[i].name ));
00527 
00528       properties[i].isString = props[i].isString;
00529 
00530       if ( props[i].isString )
00531       {
00532         FT_Long  value_offset = props[i].value;
00533 
00534 
00535         if ( ( value_offset < 0 )                     ||
00536              ( (FT_ULong)value_offset > string_size ) )
00537         {
00538           error = PCF_Err_Invalid_Offset;
00539           goto Bail;
00540         }
00541 
00542         if ( FT_STRDUP( properties[i].value.atom, strings + value_offset ) )
00543           goto Bail;
00544 
00545         FT_TRACE4(( " `%s'\n", properties[i].value.atom ));
00546       }
00547       else
00548       {
00549         properties[i].value.l = props[i].value;
00550 
00551         FT_TRACE4(( " %d\n", properties[i].value.l ));
00552       }
00553     }
00554 
00555     error = PCF_Err_Ok;
00556 
00557   Bail:
00558     FT_FREE( props );
00559     FT_FREE( strings );
00560 
00561     return error;
00562   }
00563 
00564 
00565   static FT_Error
00566   pcf_get_metrics( FT_Stream  stream,
00567                    PCF_Face   face )
00568   {
00569     FT_Error    error    = PCF_Err_Ok;
00570     FT_Memory   memory   = FT_FACE(face)->memory;
00571     FT_ULong    format, size;
00572     PCF_Metric  metrics  = 0;
00573     FT_ULong    nmetrics, i;
00574 
00575 
00576     error = pcf_seek_to_table_type( stream,
00577                                     face->toc.tables,
00578                                     face->toc.count,
00579                                     PCF_METRICS,
00580                                     &format,
00581                                     &size );
00582     if ( error )
00583       return error;
00584 
00585     if ( FT_READ_ULONG_LE( format ) )
00586       goto Bail;
00587 
00588     if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT )     &&
00589          !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) )
00590       return PCF_Err_Invalid_File_Format;
00591 
00592     if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
00593     {
00594       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00595         (void)FT_READ_ULONG( nmetrics );
00596       else
00597         (void)FT_READ_ULONG_LE( nmetrics );
00598     }
00599     else
00600     {
00601       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00602         (void)FT_READ_USHORT( nmetrics );
00603       else
00604         (void)FT_READ_USHORT_LE( nmetrics );
00605     }
00606     if ( error )
00607       return PCF_Err_Invalid_File_Format;
00608 
00609     face->nmetrics = nmetrics;
00610 
00611     if ( !nmetrics )
00612       return PCF_Err_Invalid_Table;
00613 
00614     FT_TRACE4(( "pcf_get_metrics:\n" ));
00615 
00616     FT_TRACE4(( "  number of metrics: %d\n", nmetrics ));
00617 
00618     /* rough estimate */
00619     if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
00620     {
00621       if ( nmetrics > size / PCF_METRIC_SIZE )
00622         return PCF_Err_Invalid_Table;
00623     }
00624     else
00625     {
00626       if ( nmetrics > size / PCF_COMPRESSED_METRIC_SIZE )
00627         return PCF_Err_Invalid_Table;
00628     }
00629 
00630     if ( FT_NEW_ARRAY( face->metrics, nmetrics ) )
00631       return PCF_Err_Out_Of_Memory;
00632 
00633     metrics = face->metrics;
00634     for ( i = 0; i < nmetrics; i++ )
00635     {
00636       error = pcf_get_metric( stream, format, metrics + i );
00637 
00638       metrics[i].bits = 0;
00639 
00640       FT_TRACE5(( "  idx %d: width=%d, "
00641                   "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n",
00642                   i,
00643                   ( metrics + i )->characterWidth,
00644                   ( metrics + i )->leftSideBearing,
00645                   ( metrics + i )->rightSideBearing,
00646                   ( metrics + i )->ascent,
00647                   ( metrics + i )->descent,
00648                   ( metrics + i )->attributes ));
00649 
00650       if ( error )
00651         break;
00652     }
00653 
00654     if ( error )
00655       FT_FREE( face->metrics );
00656 
00657   Bail:
00658     return error;
00659   }
00660 
00661 
00662   static FT_Error
00663   pcf_get_bitmaps( FT_Stream  stream,
00664                    PCF_Face   face )
00665   {
00666     FT_Error   error  = PCF_Err_Ok;
00667     FT_Memory  memory = FT_FACE(face)->memory;
00668     FT_Long*   offsets;
00669     FT_Long    bitmapSizes[GLYPHPADOPTIONS];
00670     FT_ULong   format, size;
00671     FT_ULong   nbitmaps, i, sizebitmaps = 0;
00672 
00673 
00674     error = pcf_seek_to_table_type( stream,
00675                                     face->toc.tables,
00676                                     face->toc.count,
00677                                     PCF_BITMAPS,
00678                                     &format,
00679                                     &size );
00680     if ( error )
00681       return error;
00682 
00683     error = FT_Stream_EnterFrame( stream, 8 );
00684     if ( error )
00685       return error;
00686 
00687     format = FT_GET_ULONG_LE();
00688     if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00689       nbitmaps  = FT_GET_ULONG();
00690     else
00691       nbitmaps  = FT_GET_ULONG_LE();
00692 
00693     FT_Stream_ExitFrame( stream );
00694 
00695     if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
00696       return PCF_Err_Invalid_File_Format;
00697 
00698     FT_TRACE4(( "pcf_get_bitmaps:\n" ));
00699 
00700     FT_TRACE4(( "  number of bitmaps: %d\n", nbitmaps ));
00701 
00702     /* XXX: PCF_Face->nmetrics is singed FT_Long, see pcf.h */
00703     if ( face->nmetrics < 0 || nbitmaps != ( FT_ULong )face->nmetrics )
00704       return PCF_Err_Invalid_File_Format;
00705 
00706     if ( FT_NEW_ARRAY( offsets, nbitmaps ) )
00707       return error;
00708 
00709     for ( i = 0; i < nbitmaps; i++ )
00710     {
00711       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00712         (void)FT_READ_LONG( offsets[i] );
00713       else
00714         (void)FT_READ_LONG_LE( offsets[i] );
00715 
00716       FT_TRACE5(( "  bitmap %d: offset %ld (0x%lX)\n",
00717                   i, offsets[i], offsets[i] ));
00718     }
00719     if ( error )
00720       goto Bail;
00721 
00722     for ( i = 0; i < GLYPHPADOPTIONS; i++ )
00723     {
00724       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00725         (void)FT_READ_LONG( bitmapSizes[i] );
00726       else
00727         (void)FT_READ_LONG_LE( bitmapSizes[i] );
00728       if ( error )
00729         goto Bail;
00730 
00731       sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
00732 
00733       FT_TRACE4(( "  padding %d implies a size of %ld\n", i, bitmapSizes[i] ));
00734     }
00735 
00736     FT_TRACE4(( "  %d bitmaps, padding index %ld\n",
00737                 nbitmaps,
00738                 PCF_GLYPH_PAD_INDEX( format ) ));
00739     FT_TRACE4(( "  bitmap size = %d\n", sizebitmaps ));
00740 
00741     FT_UNUSED( sizebitmaps );       /* only used for debugging */
00742 
00743     for ( i = 0; i < nbitmaps; i++ )
00744     {
00745       /* rough estimate */
00746       if ( ( offsets[i] < 0 )              ||
00747            ( (FT_ULong)offsets[i] > size ) )
00748       {
00749         FT_TRACE0(( "pcf_get_bitmaps:"
00750                     " invalid offset to bitmap data of glyph %d\n", i ));
00751       }
00752       else
00753         face->metrics[i].bits = stream->pos + offsets[i];
00754     }
00755 
00756     face->bitmapsFormat = format;
00757 
00758   Bail:
00759     FT_FREE( offsets );
00760     return error;
00761   }
00762 
00763 
00764   static FT_Error
00765   pcf_get_encodings( FT_Stream  stream,
00766                      PCF_Face   face )
00767   {
00768     FT_Error      error  = PCF_Err_Ok;
00769     FT_Memory     memory = FT_FACE(face)->memory;
00770     FT_ULong      format, size;
00771     int           firstCol, lastCol;
00772     int           firstRow, lastRow;
00773     int           nencoding, encodingOffset;
00774     int           i, j;
00775     PCF_Encoding  tmpEncoding, encoding = 0;
00776 
00777 
00778     error = pcf_seek_to_table_type( stream,
00779                                     face->toc.tables,
00780                                     face->toc.count,
00781                                     PCF_BDF_ENCODINGS,
00782                                     &format,
00783                                     &size );
00784     if ( error )
00785       return error;
00786 
00787     error = FT_Stream_EnterFrame( stream, 14 );
00788     if ( error )
00789       return error;
00790 
00791     format = FT_GET_ULONG_LE();
00792 
00793     if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00794     {
00795       firstCol          = FT_GET_SHORT();
00796       lastCol           = FT_GET_SHORT();
00797       firstRow          = FT_GET_SHORT();
00798       lastRow           = FT_GET_SHORT();
00799       face->defaultChar = FT_GET_SHORT();
00800     }
00801     else
00802     {
00803       firstCol          = FT_GET_SHORT_LE();
00804       lastCol           = FT_GET_SHORT_LE();
00805       firstRow          = FT_GET_SHORT_LE();
00806       lastRow           = FT_GET_SHORT_LE();
00807       face->defaultChar = FT_GET_SHORT_LE();
00808     }
00809 
00810     FT_Stream_ExitFrame( stream );
00811 
00812     if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
00813       return PCF_Err_Invalid_File_Format;
00814 
00815     FT_TRACE4(( "pdf_get_encodings:\n" ));
00816 
00817     FT_TRACE4(( "  firstCol %d, lastCol %d, firstRow %d, lastRow %d\n",
00818                 firstCol, lastCol, firstRow, lastRow ));
00819 
00820     nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 );
00821 
00822     if ( FT_NEW_ARRAY( tmpEncoding, nencoding ) )
00823       return PCF_Err_Out_Of_Memory;
00824 
00825     error = FT_Stream_EnterFrame( stream, 2 * nencoding );
00826     if ( error )
00827       goto Bail;
00828 
00829     for ( i = 0, j = 0 ; i < nencoding; i++ )
00830     {
00831       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00832         encodingOffset = FT_GET_SHORT();
00833       else
00834         encodingOffset = FT_GET_SHORT_LE();
00835 
00836       if ( encodingOffset != -1 )
00837       {
00838         tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) +
00839                                  firstRow ) * 256 ) +
00840                                ( ( i % ( lastCol - firstCol + 1 ) ) +
00841                                  firstCol );
00842 
00843         tmpEncoding[j].glyph = (FT_Short)encodingOffset;
00844 
00845         FT_TRACE5(( "  code %d (0x%04X): idx %d\n",
00846                     tmpEncoding[j].enc, tmpEncoding[j].enc,
00847                     tmpEncoding[j].glyph ));
00848 
00849         j++;
00850       }
00851     }
00852     FT_Stream_ExitFrame( stream );
00853 
00854     if ( FT_NEW_ARRAY( encoding, j ) )
00855       goto Bail;
00856 
00857     for ( i = 0; i < j; i++ )
00858     {
00859       encoding[i].enc   = tmpEncoding[i].enc;
00860       encoding[i].glyph = tmpEncoding[i].glyph;
00861     }
00862 
00863     face->nencodings = j;
00864     face->encodings  = encoding;
00865     FT_FREE( tmpEncoding );
00866 
00867     return error;
00868 
00869   Bail:
00870     FT_FREE( encoding );
00871     FT_FREE( tmpEncoding );
00872     return error;
00873   }
00874 
00875 
00876   static
00877   const FT_Frame_Field  pcf_accel_header[] =
00878   {
00879 #undef  FT_STRUCTURE
00880 #define FT_STRUCTURE  PCF_AccelRec
00881 
00882     FT_FRAME_START( 20 ),
00883       FT_FRAME_BYTE      ( noOverlap ),
00884       FT_FRAME_BYTE      ( constantMetrics ),
00885       FT_FRAME_BYTE      ( terminalFont ),
00886       FT_FRAME_BYTE      ( constantWidth ),
00887       FT_FRAME_BYTE      ( inkInside ),
00888       FT_FRAME_BYTE      ( inkMetrics ),
00889       FT_FRAME_BYTE      ( drawDirection ),
00890       FT_FRAME_SKIP_BYTES( 1 ),
00891       FT_FRAME_LONG_LE   ( fontAscent ),
00892       FT_FRAME_LONG_LE   ( fontDescent ),
00893       FT_FRAME_LONG_LE   ( maxOverlap ),
00894     FT_FRAME_END
00895   };
00896 
00897 
00898   static
00899   const FT_Frame_Field  pcf_accel_msb_header[] =
00900   {
00901 #undef  FT_STRUCTURE
00902 #define FT_STRUCTURE  PCF_AccelRec
00903 
00904     FT_FRAME_START( 20 ),
00905       FT_FRAME_BYTE      ( noOverlap ),
00906       FT_FRAME_BYTE      ( constantMetrics ),
00907       FT_FRAME_BYTE      ( terminalFont ),
00908       FT_FRAME_BYTE      ( constantWidth ),
00909       FT_FRAME_BYTE      ( inkInside ),
00910       FT_FRAME_BYTE      ( inkMetrics ),
00911       FT_FRAME_BYTE      ( drawDirection ),
00912       FT_FRAME_SKIP_BYTES( 1 ),
00913       FT_FRAME_LONG      ( fontAscent ),
00914       FT_FRAME_LONG      ( fontDescent ),
00915       FT_FRAME_LONG      ( maxOverlap ),
00916     FT_FRAME_END
00917   };
00918 
00919 
00920   static FT_Error
00921   pcf_get_accel( FT_Stream  stream,
00922                  PCF_Face   face,
00923                  FT_ULong   type )
00924   {
00925     FT_ULong   format, size;
00926     FT_Error   error = PCF_Err_Ok;
00927     PCF_Accel  accel = &face->accel;
00928 
00929 
00930     error = pcf_seek_to_table_type( stream,
00931                                     face->toc.tables,
00932                                     face->toc.count,
00933                                     type,
00934                                     &format,
00935                                     &size );
00936     if ( error )
00937       goto Bail;
00938 
00939     if ( FT_READ_ULONG_LE( format ) )
00940       goto Bail;
00941 
00942     if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT )    &&
00943          !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
00944       goto Bail;
00945 
00946     if ( PCF_BYTE_ORDER( format ) == MSBFirst )
00947     {
00948       if ( FT_STREAM_READ_FIELDS( pcf_accel_msb_header, accel ) )
00949         goto Bail;
00950     }
00951     else
00952     {
00953       if ( FT_STREAM_READ_FIELDS( pcf_accel_header, accel ) )
00954         goto Bail;
00955     }
00956 
00957     error = pcf_get_metric( stream,
00958                             format & ( ~PCF_FORMAT_MASK ),
00959                             &(accel->minbounds) );
00960     if ( error )
00961       goto Bail;
00962 
00963     error = pcf_get_metric( stream,
00964                             format & ( ~PCF_FORMAT_MASK ),
00965                             &(accel->maxbounds) );
00966     if ( error )
00967       goto Bail;
00968 
00969     if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
00970     {
00971       error = pcf_get_metric( stream,
00972                               format & ( ~PCF_FORMAT_MASK ),
00973                               &(accel->ink_minbounds) );
00974       if ( error )
00975         goto Bail;
00976 
00977       error = pcf_get_metric( stream,
00978                               format & ( ~PCF_FORMAT_MASK ),
00979                               &(accel->ink_maxbounds) );
00980       if ( error )
00981         goto Bail;
00982     }
00983     else
00984     {
00985       accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */
00986       accel->ink_maxbounds = accel->maxbounds;
00987     }
00988 
00989   Bail:
00990     return error;
00991   }
00992 
00993 
00994   static FT_Error
00995   pcf_interpret_style( PCF_Face  pcf )
00996   {
00997     FT_Error   error  = PCF_Err_Ok;
00998     FT_Face    face   = FT_FACE( pcf );
00999     FT_Memory  memory = face->memory;
01000 
01001     PCF_Property  prop;
01002 
01003     size_t  nn, len;
01004     char*   strings[4] = { NULL, NULL, NULL, NULL };
01005     size_t  lengths[4];
01006 
01007 
01008     face->style_flags = 0;
01009 
01010     prop = pcf_find_property( pcf, "SLANT" );
01011     if ( prop && prop->isString                                       &&
01012          ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ||
01013            *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) )
01014     {
01015       face->style_flags |= FT_STYLE_FLAG_ITALIC;
01016       strings[2] = ( *(prop->value.atom) == 'O' ||
01017                      *(prop->value.atom) == 'o' ) ? (char *)"Oblique"
01018                                                   : (char *)"Italic";
01019     }
01020 
01021     prop = pcf_find_property( pcf, "WEIGHT_NAME" );
01022     if ( prop && prop->isString                                       &&
01023          ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) )
01024     {
01025       face->style_flags |= FT_STYLE_FLAG_BOLD;
01026       strings[1] = (char *)"Bold";
01027     }
01028 
01029     prop = pcf_find_property( pcf, "SETWIDTH_NAME" );
01030     if ( prop && prop->isString                                        &&
01031          *(prop->value.atom)                                           &&
01032          !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
01033       strings[3] = (char *)(prop->value.atom);
01034 
01035     prop = pcf_find_property( pcf, "ADD_STYLE_NAME" );
01036     if ( prop && prop->isString                                        &&
01037          *(prop->value.atom)                                           &&
01038          !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
01039       strings[0] = (char *)(prop->value.atom);
01040 
01041     for ( len = 0, nn = 0; nn < 4; nn++ )
01042     {
01043       lengths[nn] = 0;
01044       if ( strings[nn] )
01045       {
01046         lengths[nn] = ft_strlen( strings[nn] );
01047         len        += lengths[nn] + 1;
01048       }
01049     }
01050 
01051     if ( len == 0 )
01052     {
01053       strings[0] = (char *)"Regular";
01054       lengths[0] = ft_strlen( strings[0] );
01055       len        = lengths[0] + 1;
01056     }
01057 
01058     {
01059       char*  s;
01060 
01061 
01062       if ( FT_ALLOC( face->style_name, len ) )
01063         return error;
01064 
01065       s = face->style_name;
01066 
01067       for ( nn = 0; nn < 4; nn++ )
01068       {
01069         char*  src = strings[nn];
01070 
01071 
01072         len = lengths[nn];
01073 
01074         if ( src == NULL )
01075           continue;
01076 
01077         /* separate elements with a space */
01078         if ( s != face->style_name )
01079           *s++ = ' ';
01080 
01081         ft_memcpy( s, src, len );
01082 
01083         /* need to convert spaces to dashes for */
01084         /* add_style_name and setwidth_name     */
01085         if ( nn == 0 || nn == 3 )
01086         {
01087           size_t  mm;
01088 
01089 
01090           for ( mm = 0; mm < len; mm++ )
01091             if (s[mm] == ' ')
01092               s[mm] = '-';
01093         }
01094 
01095         s += len;
01096       }
01097       *s = 0;
01098     }
01099 
01100     return error;
01101   }
01102 
01103 
01104   FT_LOCAL_DEF( FT_Error )
01105   pcf_load_font( FT_Stream  stream,
01106                  PCF_Face   face )
01107   {
01108     FT_Error   error  = PCF_Err_Ok;
01109     FT_Memory  memory = FT_FACE(face)->memory;
01110     FT_Bool    hasBDFAccelerators;
01111 
01112 
01113     error = pcf_read_TOC( stream, face );
01114     if ( error )
01115       goto Exit;
01116 
01117     error = pcf_get_properties( stream, face );
01118     if ( error )
01119       goto Exit;
01120 
01121     /* Use the old accelerators if no BDF accelerators are in the file. */
01122     hasBDFAccelerators = pcf_has_table_type( face->toc.tables,
01123                                              face->toc.count,
01124                                              PCF_BDF_ACCELERATORS );
01125     if ( !hasBDFAccelerators )
01126     {
01127       error = pcf_get_accel( stream, face, PCF_ACCELERATORS );
01128       if ( error )
01129         goto Exit;
01130     }
01131 
01132     /* metrics */
01133     error = pcf_get_metrics( stream, face );
01134     if ( error )
01135       goto Exit;
01136 
01137     /* bitmaps */
01138     error = pcf_get_bitmaps( stream, face );
01139     if ( error )
01140       goto Exit;
01141 
01142     /* encodings */
01143     error = pcf_get_encodings( stream, face );
01144     if ( error )
01145       goto Exit;
01146 
01147     /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
01148     if ( hasBDFAccelerators )
01149     {
01150       error = pcf_get_accel( stream, face, PCF_BDF_ACCELERATORS );
01151       if ( error )
01152         goto Exit;
01153     }
01154 
01155     /* XXX: TO DO: inkmetrics and glyph_names are missing */
01156 
01157     /* now construct the face object */
01158     {
01159       FT_Face       root = FT_FACE( face );
01160       PCF_Property  prop;
01161 
01162 
01163       root->num_faces  = 1;
01164       root->face_index = 0;
01165       root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
01166                          FT_FACE_FLAG_HORIZONTAL  |
01167                          FT_FACE_FLAG_FAST_GLYPHS;
01168 
01169       if ( face->accel.constantWidth )
01170         root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
01171 
01172       if ( ( error = pcf_interpret_style( face ) ) != 0 )
01173          goto Exit;
01174 
01175       prop = pcf_find_property( face, "FAMILY_NAME" );
01176       if ( prop && prop->isString )
01177       {
01178         if ( FT_STRDUP( root->family_name, prop->value.atom ) )
01179           goto Exit;
01180       }
01181       else
01182         root->family_name = NULL;
01183 
01184       /*
01185        * Note: We shift all glyph indices by +1 since we must
01186        * respect the convention that glyph 0 always corresponds
01187        * to the `missing glyph'.
01188        *
01189        * This implies bumping the number of `available' glyphs by 1.
01190        */
01191       root->num_glyphs = face->nmetrics + 1;
01192 
01193       root->num_fixed_sizes = 1;
01194       if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
01195         goto Exit;
01196 
01197       {
01198         FT_Bitmap_Size*  bsize = root->available_sizes;
01199         FT_Short         resolution_x = 0, resolution_y = 0;
01200 
01201 
01202         FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );
01203 
01204 #if 0
01205         bsize->height = face->accel.maxbounds.ascent << 6;
01206 #endif
01207         bsize->height = (FT_Short)( face->accel.fontAscent +
01208                                     face->accel.fontDescent );
01209 
01210         prop = pcf_find_property( face, "AVERAGE_WIDTH" );
01211         if ( prop )
01212           bsize->width = (FT_Short)( ( prop->value.l + 5 ) / 10 );
01213         else
01214           bsize->width = (FT_Short)( bsize->height * 2/3 );
01215 
01216         prop = pcf_find_property( face, "POINT_SIZE" );
01217         if ( prop )
01218           /* convert from 722.7 decipoints to 72 points per inch */
01219           bsize->size =
01220             (FT_Pos)( ( prop->value.l * 64 * 7200 + 36135L ) / 72270L );
01221 
01222         prop = pcf_find_property( face, "PIXEL_SIZE" );
01223         if ( prop )
01224           bsize->y_ppem = (FT_Short)prop->value.l << 6;
01225 
01226         prop = pcf_find_property( face, "RESOLUTION_X" );
01227         if ( prop )
01228           resolution_x = (FT_Short)prop->value.l;
01229 
01230         prop = pcf_find_property( face, "RESOLUTION_Y" );
01231         if ( prop )
01232           resolution_y = (FT_Short)prop->value.l;
01233 
01234         if ( bsize->y_ppem == 0 )
01235         {
01236           bsize->y_ppem = bsize->size;
01237           if ( resolution_y )
01238             bsize->y_ppem = bsize->y_ppem * resolution_y / 72;
01239         }
01240         if ( resolution_x && resolution_y )
01241           bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y;
01242         else
01243           bsize->x_ppem = bsize->y_ppem;
01244       }
01245 
01246       /* set up charset */
01247       {
01248         PCF_Property  charset_registry = 0, charset_encoding = 0;
01249 
01250 
01251         charset_registry = pcf_find_property( face, "CHARSET_REGISTRY" );
01252         charset_encoding = pcf_find_property( face, "CHARSET_ENCODING" );
01253 
01254         if ( charset_registry && charset_registry->isString &&
01255              charset_encoding && charset_encoding->isString )
01256         {
01257           if ( FT_STRDUP( face->charset_encoding,
01258                           charset_encoding->value.atom ) ||
01259                FT_STRDUP( face->charset_registry,
01260                           charset_registry->value.atom ) )
01261             goto Exit;
01262         }
01263       }
01264     }
01265 
01266   Exit:
01267     if ( error )
01268     {
01269       /* This is done to respect the behaviour of the original */
01270       /* PCF font driver.                                      */
01271       error = PCF_Err_Invalid_File_Format;
01272     }
01273 
01274     return error;
01275   }
01276 
01277 
01278 /* END */

Generated on Sat May 26 2012 04:32:46 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.