pfrsbit.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  pfrsbit.c                                                              */
00004 /*                                                                         */
00005 /*    FreeType PFR bitmap loader (body).                                   */
00006 /*                                                                         */
00007 /*  Copyright 2002, 2003, 2006, 2009 by                                    */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019 #include "pfrsbit.h"
00020 #include "pfrload.h"
00021 #include FT_INTERNAL_DEBUG_H
00022 #include FT_INTERNAL_STREAM_H
00023 
00024 #include "pfrerror.h"
00025 
00026 #undef  FT_COMPONENT
00027 #define FT_COMPONENT  trace_pfr
00028 
00029 
00030   /*************************************************************************/
00031   /*************************************************************************/
00032   /*****                                                               *****/
00033   /*****                      PFR BIT WRITER                           *****/
00034   /*****                                                               *****/
00035   /*************************************************************************/
00036   /*************************************************************************/
00037 
00038   typedef struct  PFR_BitWriter_
00039   {
00040     FT_Byte*  line;      /* current line start                    */
00041     FT_Int    pitch;     /* line size in bytes                    */
00042     FT_Int    width;     /* width in pixels/bits                  */
00043     FT_Int    rows;      /* number of remaining rows to scan      */
00044     FT_Int    total;     /* total number of bits to draw          */
00045 
00046   } PFR_BitWriterRec, *PFR_BitWriter;
00047 
00048 
00049   static void
00050   pfr_bitwriter_init( PFR_BitWriter  writer,
00051                       FT_Bitmap*     target,
00052                       FT_Bool        decreasing )
00053   {
00054     writer->line   = target->buffer;
00055     writer->pitch  = target->pitch;
00056     writer->width  = target->width;
00057     writer->rows   = target->rows;
00058     writer->total  = writer->width * writer->rows;
00059 
00060     if ( !decreasing )
00061     {
00062       writer->line += writer->pitch * ( target->rows-1 );
00063       writer->pitch = -writer->pitch;
00064     }
00065   }
00066 
00067 
00068   static void
00069   pfr_bitwriter_decode_bytes( PFR_BitWriter  writer,
00070                               FT_Byte*       p,
00071                               FT_Byte*       limit )
00072   {
00073     FT_Int    n, reload;
00074     FT_Int    left = writer->width;
00075     FT_Byte*  cur  = writer->line;
00076     FT_UInt   mask = 0x80;
00077     FT_UInt   val  = 0;
00078     FT_UInt   c    = 0;
00079 
00080 
00081     n = (FT_Int)( limit - p ) * 8;
00082     if ( n > writer->total )
00083       n = writer->total;
00084 
00085     reload = n & 7;
00086 
00087     for ( ; n > 0; n-- )
00088     {
00089       if ( ( n & 7 ) == reload )
00090         val = *p++;
00091 
00092       if ( val & 0x80 )
00093         c |= mask;
00094 
00095       val  <<= 1;
00096       mask >>= 1;
00097 
00098       if ( --left <= 0 )
00099       {
00100         cur[0] = (FT_Byte)c;
00101         left   = writer->width;
00102         mask   = 0x80;
00103 
00104         writer->line += writer->pitch;
00105         cur           = writer->line;
00106         c             = 0;
00107       }
00108       else if ( mask == 0 )
00109       {
00110         cur[0] = (FT_Byte)c;
00111         mask   = 0x80;
00112         c      = 0;
00113         cur ++;
00114       }
00115     }
00116 
00117     if ( mask != 0x80 )
00118       cur[0] = (FT_Byte)c;
00119   }
00120 
00121 
00122   static void
00123   pfr_bitwriter_decode_rle1( PFR_BitWriter  writer,
00124                              FT_Byte*       p,
00125                              FT_Byte*       limit )
00126   {
00127     FT_Int    n, phase, count, counts[2], reload;
00128     FT_Int    left = writer->width;
00129     FT_Byte*  cur  = writer->line;
00130     FT_UInt   mask = 0x80;
00131     FT_UInt   c    = 0;
00132 
00133 
00134     n = writer->total;
00135 
00136     phase     = 1;
00137     counts[0] = 0;
00138     counts[1] = 0;
00139     count     = 0;
00140     reload    = 1;
00141 
00142     for ( ; n > 0; n-- )
00143     {
00144       if ( reload )
00145       {
00146         do
00147         {
00148           if ( phase )
00149           {
00150             FT_Int  v;
00151 
00152 
00153             if ( p >= limit )
00154               break;
00155 
00156             v         = *p++;
00157             counts[0] = v >> 4;
00158             counts[1] = v & 15;
00159             phase     = 0;
00160             count     = counts[0];
00161           }
00162           else
00163           {
00164             phase = 1;
00165             count = counts[1];
00166           }
00167 
00168         } while ( count == 0 );
00169       }
00170 
00171       if ( phase )
00172         c |= mask;
00173 
00174       mask >>= 1;
00175 
00176       if ( --left <= 0 )
00177       {
00178         cur[0] = (FT_Byte) c;
00179         left   = writer->width;
00180         mask   = 0x80;
00181 
00182         writer->line += writer->pitch;
00183         cur           = writer->line;
00184         c             = 0;
00185       }
00186       else if ( mask == 0 )
00187       {
00188         cur[0] = (FT_Byte)c;
00189         mask   = 0x80;
00190         c      = 0;
00191         cur ++;
00192       }
00193 
00194       reload = ( --count <= 0 );
00195     }
00196 
00197     if ( mask != 0x80 )
00198       cur[0] = (FT_Byte) c;
00199   }
00200 
00201 
00202   static void
00203   pfr_bitwriter_decode_rle2( PFR_BitWriter  writer,
00204                              FT_Byte*       p,
00205                              FT_Byte*       limit )
00206   {
00207     FT_Int    n, phase, count, reload;
00208     FT_Int    left = writer->width;
00209     FT_Byte*  cur  = writer->line;
00210     FT_UInt   mask = 0x80;
00211     FT_UInt   c    = 0;
00212 
00213 
00214     n = writer->total;
00215 
00216     phase  = 1;
00217     count  = 0;
00218     reload = 1;
00219 
00220     for ( ; n > 0; n-- )
00221     {
00222       if ( reload )
00223       {
00224         do
00225         {
00226           if ( p >= limit )
00227             break;
00228 
00229           count = *p++;
00230           phase = phase ^ 1;
00231 
00232         } while ( count == 0 );
00233       }
00234 
00235       if ( phase )
00236         c |= mask;
00237 
00238       mask >>= 1;
00239 
00240       if ( --left <= 0 )
00241       {
00242         cur[0] = (FT_Byte) c;
00243         c      = 0;
00244         mask   = 0x80;
00245         left   = writer->width;
00246 
00247         writer->line += writer->pitch;
00248         cur           = writer->line;
00249       }
00250       else if ( mask == 0 )
00251       {
00252         cur[0] = (FT_Byte)c;
00253         c      = 0;
00254         mask   = 0x80;
00255         cur ++;
00256       }
00257 
00258       reload = ( --count <= 0 );
00259     }
00260 
00261     if ( mask != 0x80 )
00262       cur[0] = (FT_Byte) c;
00263   }
00264 
00265 
00266   /*************************************************************************/
00267   /*************************************************************************/
00268   /*****                                                               *****/
00269   /*****                  BITMAP DATA DECODING                         *****/
00270   /*****                                                               *****/
00271   /*************************************************************************/
00272   /*************************************************************************/
00273 
00274   static void
00275   pfr_lookup_bitmap_data( FT_Byte*   base,
00276                           FT_Byte*   limit,
00277                           FT_UInt    count,
00278                           FT_UInt    flags,
00279                           FT_UInt    char_code,
00280                           FT_ULong*  found_offset,
00281                           FT_ULong*  found_size )
00282   {
00283     FT_UInt   left, right, char_len;
00284     FT_Bool   two = FT_BOOL( flags & 1 );
00285     FT_Byte*  buff;
00286 
00287 
00288     char_len = 4;
00289     if ( two )       char_len += 1;
00290     if ( flags & 2 ) char_len += 1;
00291     if ( flags & 4 ) char_len += 1;
00292 
00293     left  = 0;
00294     right = count;
00295 
00296     while ( left < right )
00297     {
00298       FT_UInt  middle, code;
00299 
00300 
00301       middle = ( left + right ) >> 1;
00302       buff   = base + middle * char_len;
00303 
00304       /* check that we are not outside of the table -- */
00305       /* this is possible with broken fonts...         */
00306       if ( buff + char_len > limit )
00307         goto Fail;
00308 
00309       if ( two )
00310         code = PFR_NEXT_USHORT( buff );
00311       else
00312         code = PFR_NEXT_BYTE( buff );
00313 
00314       if ( code == char_code )
00315         goto Found_It;
00316 
00317       if ( code < char_code )
00318         left = middle;
00319       else
00320         right = middle;
00321     }
00322 
00323   Fail:
00324     /* Not found */
00325     *found_size   = 0;
00326     *found_offset = 0;
00327     return;
00328 
00329   Found_It:
00330     if ( flags & 2 )
00331       *found_size = PFR_NEXT_USHORT( buff );
00332     else
00333       *found_size = PFR_NEXT_BYTE( buff );
00334 
00335     if ( flags & 4 )
00336       *found_offset = PFR_NEXT_ULONG( buff );
00337     else
00338       *found_offset = PFR_NEXT_USHORT( buff );
00339   }
00340 
00341 
00342   /* load bitmap metrics.  "*padvance" must be set to the default value */
00343   /* before calling this function...                                    */
00344   /*                                                                    */
00345   static FT_Error
00346   pfr_load_bitmap_metrics( FT_Byte**  pdata,
00347                            FT_Byte*   limit,
00348                            FT_Long    scaled_advance,
00349                            FT_Long   *axpos,
00350                            FT_Long   *aypos,
00351                            FT_UInt   *axsize,
00352                            FT_UInt   *aysize,
00353                            FT_Long   *aadvance,
00354                            FT_UInt   *aformat )
00355   {
00356     FT_Error  error = 0;
00357     FT_Byte   flags;
00358     FT_Char   b;
00359     FT_Byte*  p = *pdata;
00360     FT_Long   xpos, ypos, advance;
00361     FT_UInt   xsize, ysize;
00362 
00363 
00364     PFR_CHECK( 1 );
00365     flags = PFR_NEXT_BYTE( p );
00366 
00367     xpos    = 0;
00368     ypos    = 0;
00369     xsize   = 0;
00370     ysize   = 0;
00371     advance = 0;
00372 
00373     switch ( flags & 3 )
00374     {
00375     case 0:
00376       PFR_CHECK( 1 );
00377       b    = PFR_NEXT_INT8( p );
00378       xpos = b >> 4;
00379       ypos = ( (FT_Char)( b << 4 ) ) >> 4;
00380       break;
00381 
00382     case 1:
00383       PFR_CHECK( 2 );
00384       xpos = PFR_NEXT_INT8( p );
00385       ypos = PFR_NEXT_INT8( p );
00386       break;
00387 
00388     case 2:
00389       PFR_CHECK( 4 );
00390       xpos = PFR_NEXT_SHORT( p );
00391       ypos = PFR_NEXT_SHORT( p );
00392       break;
00393 
00394     case 3:
00395       PFR_CHECK( 6 );
00396       xpos = PFR_NEXT_LONG( p );
00397       ypos = PFR_NEXT_LONG( p );
00398       break;
00399 
00400     default:
00401       ;
00402     }
00403 
00404     flags >>= 2;
00405     switch ( flags & 3 )
00406     {
00407     case 0:
00408       /* blank image */
00409       xsize = 0;
00410       ysize = 0;
00411       break;
00412 
00413     case 1:
00414       PFR_CHECK( 1 );
00415       b     = PFR_NEXT_BYTE( p );
00416       xsize = ( b >> 4 ) & 0xF;
00417       ysize = b & 0xF;
00418       break;
00419 
00420     case 2:
00421       PFR_CHECK( 2 );
00422       xsize = PFR_NEXT_BYTE( p );
00423       ysize = PFR_NEXT_BYTE( p );
00424       break;
00425 
00426     case 3:
00427       PFR_CHECK( 4 );
00428       xsize = PFR_NEXT_USHORT( p );
00429       ysize = PFR_NEXT_USHORT( p );
00430       break;
00431 
00432     default:
00433       ;
00434     }
00435 
00436     flags >>= 2;
00437     switch ( flags & 3 )
00438     {
00439     case 0:
00440       advance = scaled_advance;
00441       break;
00442 
00443     case 1:
00444       PFR_CHECK( 1 );
00445       advance = PFR_NEXT_INT8( p ) << 8;
00446       break;
00447 
00448     case 2:
00449       PFR_CHECK( 2 );
00450       advance = PFR_NEXT_SHORT( p );
00451       break;
00452 
00453     case 3:
00454       PFR_CHECK( 3 );
00455       advance = PFR_NEXT_LONG( p );
00456       break;
00457 
00458     default:
00459       ;
00460     }
00461 
00462     *axpos    = xpos;
00463     *aypos    = ypos;
00464     *axsize   = xsize;
00465     *aysize   = ysize;
00466     *aadvance = advance;
00467     *aformat  = flags >> 2;
00468     *pdata    = p;
00469 
00470   Exit:
00471     return error;
00472 
00473   Too_Short:
00474     error = PFR_Err_Invalid_Table;
00475     FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" ));
00476     goto Exit;
00477   }
00478 
00479 
00480   static FT_Error
00481   pfr_load_bitmap_bits( FT_Byte*    p,
00482                         FT_Byte*    limit,
00483                         FT_UInt     format,
00484                         FT_Bool     decreasing,
00485                         FT_Bitmap*  target )
00486   {
00487     FT_Error          error = 0;
00488     PFR_BitWriterRec  writer;
00489 
00490 
00491     if ( target->rows > 0 && target->width > 0 )
00492     {
00493       pfr_bitwriter_init( &writer, target, decreasing );
00494 
00495       switch ( format )
00496       {
00497       case 0: /* packed bits */
00498         pfr_bitwriter_decode_bytes( &writer, p, limit );
00499         break;
00500 
00501       case 1: /* RLE1 */
00502         pfr_bitwriter_decode_rle1( &writer, p, limit );
00503         break;
00504 
00505       case 2: /* RLE2 */
00506         pfr_bitwriter_decode_rle2( &writer, p, limit );
00507         break;
00508 
00509       default:
00510         FT_ERROR(( "pfr_read_bitmap_data: invalid image type\n" ));
00511         error = PFR_Err_Invalid_File_Format;
00512       }
00513     }
00514 
00515     return error;
00516   }
00517 
00518 
00519   /*************************************************************************/
00520   /*************************************************************************/
00521   /*****                                                               *****/
00522   /*****                     BITMAP LOADING                            *****/
00523   /*****                                                               *****/
00524   /*************************************************************************/
00525   /*************************************************************************/
00526 
00527   FT_LOCAL( FT_Error )
00528   pfr_slot_load_bitmap( PFR_Slot  glyph,
00529                         PFR_Size  size,
00530                         FT_UInt   glyph_index )
00531   {
00532     FT_Error     error;
00533     PFR_Face     face   = (PFR_Face) glyph->root.face;
00534     FT_Stream    stream = face->root.stream;
00535     PFR_PhyFont  phys   = &face->phy_font;
00536     FT_ULong     gps_offset;
00537     FT_ULong     gps_size;
00538     PFR_Char     character;
00539     PFR_Strike   strike;
00540 
00541 
00542     character = &phys->chars[glyph_index];
00543 
00544     /* Look-up a bitmap strike corresponding to the current */
00545     /* character dimensions                                 */
00546     {
00547       FT_UInt  n;
00548 
00549 
00550       strike = phys->strikes;
00551       for ( n = 0; n < phys->num_strikes; n++ )
00552       {
00553         if ( strike->x_ppm == (FT_UInt)size->root.metrics.x_ppem &&
00554              strike->y_ppm == (FT_UInt)size->root.metrics.y_ppem )
00555         {
00556           goto Found_Strike;
00557         }
00558 
00559         strike++;
00560       }
00561 
00562       /* couldn't find it */
00563       return PFR_Err_Invalid_Argument;
00564     }
00565 
00566   Found_Strike:
00567 
00568     /* Now lookup the glyph's position within the file */
00569     {
00570       FT_UInt  char_len;
00571 
00572 
00573       char_len = 4;
00574       if ( strike->flags & 1 ) char_len += 1;
00575       if ( strike->flags & 2 ) char_len += 1;
00576       if ( strike->flags & 4 ) char_len += 1;
00577 
00578       /* Access data directly in the frame to speed lookups */
00579       if ( FT_STREAM_SEEK( phys->bct_offset + strike->bct_offset ) ||
00580            FT_FRAME_ENTER( char_len * strike->num_bitmaps )        )
00581         goto Exit;
00582 
00583       pfr_lookup_bitmap_data( stream->cursor,
00584                               stream->limit,
00585                               strike->num_bitmaps,
00586                               strike->flags,
00587                               character->char_code,
00588                               &gps_offset,
00589                               &gps_size );
00590 
00591       FT_FRAME_EXIT();
00592 
00593       if ( gps_size == 0 )
00594       {
00595         /* Could not find a bitmap program string for this glyph */
00596         error = PFR_Err_Invalid_Argument;
00597         goto Exit;
00598       }
00599     }
00600 
00601     /* get the bitmap metrics */
00602     {
00603       FT_Long   xpos = 0, ypos = 0, advance = 0;
00604       FT_UInt   xsize = 0, ysize = 0, format = 0;
00605       FT_Byte*  p;
00606 
00607 
00608       /* compute linear advance */
00609       advance = character->advance;
00610       if ( phys->metrics_resolution != phys->outline_resolution )
00611         advance = FT_MulDiv( advance,
00612                              phys->outline_resolution,
00613                              phys->metrics_resolution );
00614 
00615       glyph->root.linearHoriAdvance = advance;
00616 
00617       /* compute default advance, i.e., scaled advance.  This can be */
00618       /* overridden in the bitmap header of certain glyphs.          */
00619       advance = FT_MulDiv( (FT_Fixed)size->root.metrics.x_ppem << 8,
00620                            character->advance,
00621                            phys->metrics_resolution );
00622 
00623       if ( FT_STREAM_SEEK( face->header.gps_section_offset + gps_offset ) ||
00624            FT_FRAME_ENTER( gps_size )                                     )
00625         goto Exit;
00626 
00627       p     = stream->cursor;
00628       error = pfr_load_bitmap_metrics( &p, stream->limit,
00629                                        advance,
00630                                        &xpos, &ypos,
00631                                        &xsize, &ysize,
00632                                        &advance, &format );
00633 
00634       /*
00635        * XXX: on 16bit system, we return an error for huge bitmap
00636        *      which causes a size truncation, because truncated
00637        *      size properties makes bitmap glyph broken.
00638        */
00639       if ( xpos > FT_INT_MAX || ( ypos + ysize ) > FT_INT_MAX )
00640       {
00641         FT_TRACE1(( "pfr_slot_load_bitmap:" ));
00642         FT_TRACE1(( "huge bitmap glyph %dx%d over FT_GlyphSlot\n",
00643                      xpos, ypos ));
00644         error = PFR_Err_Invalid_Pixel_Size;
00645       }
00646 
00647       if ( !error )
00648       {
00649         glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
00650 
00651         /* Set up glyph bitmap and metrics */
00652 
00653         /* XXX: needs casts to fit FT_Bitmap.{width|rows|pitch} */
00654         glyph->root.bitmap.width      = (FT_Int)xsize;
00655         glyph->root.bitmap.rows       = (FT_Int)ysize;
00656         glyph->root.bitmap.pitch      = (FT_Int)( xsize + 7 ) >> 3;
00657         glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
00658 
00659         /* XXX: needs casts to fit FT_Glyph_Metrics.{width|height} */
00660         glyph->root.metrics.width        = (FT_Pos)xsize << 6;
00661         glyph->root.metrics.height       = (FT_Pos)ysize << 6;
00662         glyph->root.metrics.horiBearingX = xpos << 6;
00663         glyph->root.metrics.horiBearingY = ypos << 6;
00664         glyph->root.metrics.horiAdvance  = FT_PIX_ROUND( ( advance >> 2 ) );
00665         glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1;
00666         glyph->root.metrics.vertBearingY = 0;
00667         glyph->root.metrics.vertAdvance  = size->root.metrics.height;
00668 
00669         /* XXX: needs casts fit FT_GlyphSlotRec.bitmap_{left|top} */
00670         glyph->root.bitmap_left = (FT_Int)xpos;
00671         glyph->root.bitmap_top  = (FT_Int)(ypos + ysize);
00672 
00673         /* Allocate and read bitmap data */
00674         {
00675           FT_ULong  len = glyph->root.bitmap.pitch * ysize;
00676 
00677 
00678           error = ft_glyphslot_alloc_bitmap( &glyph->root, len );
00679           if ( !error )
00680           {
00681             error = pfr_load_bitmap_bits(
00682                       p,
00683                       stream->limit,
00684                       format,
00685                       FT_BOOL(face->header.color_flags & 2),
00686                       &glyph->root.bitmap );
00687           }
00688         }
00689       }
00690 
00691       FT_FRAME_EXIT();
00692     }
00693 
00694   Exit:
00695     return error;
00696   }
00697 
00698 /* END */

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