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

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, 2010 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 = PFR_Err_Ok;
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 = PFR_Err_Ok;
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 Sun May 27 2012 04:33:58 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.