Charles.Forsyth20060303a828770d19 years agoHistory
670 lines · 16.9 KB · C
RawDownload
/***************************************************************************//*                                                                         *//*  pfrsbit.c                                                              *//*                                                                         *//*    FreeType PFR bitmap loader (body).                                   *//*                                                                         *//*  Copyright 2002 by                                                      *//*  David Turner, Robert Wilhelm, and Werner Lemberg.                      *//*                                                                         *//*  This file is part of the FreeType project, and may only be used,       *//*  modified, and distributed under the terms of the FreeType project      *//*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     *//*  this file you indicate that you have read the license and              *//*  understand and accept it fully.                                        *//*                                                                         *//***************************************************************************/  #include "pfrsbit.h"#include "pfrload.h"#include FT_INTERNAL_DEBUG_H#include FT_INTERNAL_STREAM_H #include "pfrerror.h" #undef  FT_COMPONENT#define FT_COMPONENT  trace_pfr    /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                      PFR BIT WRITER                           *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/   typedef struct  PFR_BitWriter_  {    FT_Byte*  line;      /* current line start                    */    FT_Int    pitch;     /* line size in bytes                    */    FT_Int    width;     /* width in pixels/bits                  */    FT_Int    rows;      /* number of remaining rows to scan      */    FT_Int    total;     /* total number of bits to draw          */   } PFR_BitWriterRec, *PFR_BitWriter;    static void  pfr_bitwriter_init( PFR_BitWriter  writer,                      FT_Bitmap*     target,                      FT_Bool        decreasing )  {    writer->line   = target->buffer;    writer->pitch  = target->pitch;    writer->width  = target->width;    writer->rows   = target->rows;    writer->total  = writer->width * writer->rows;     if ( !decreasing )    {      writer->line += writer->pitch * ( target->rows-1 );      writer->pitch = -writer->pitch;    }  }    static void  pfr_bitwriter_decode_bytes( PFR_BitWriter  writer,                              FT_Byte*       p,                              FT_Byte*       limit )  {    FT_Int    n, reload;    FT_Int    left = writer->width;    FT_Byte*  cur  = writer->line;    FT_UInt   mask = 0x80;    FT_UInt   val  = 0;    FT_UInt   c    = 0;      n = (FT_Int)( limit - p ) * 8;    if ( n > writer->total )      n = writer->total;     reload = n & 7;     for ( ; n > 0; n-- )    {      if ( ( n & 7 ) == reload )        val = *p++;       if ( val & 0x80 )        c |= mask;       val  <<= 1;      mask >>= 1;       if ( --left <= 0 )      {        cur[0] = (FT_Byte)c;        left   = writer->width;        mask   = 0x80;         writer->line += writer->pitch;        cur           = writer->line;        c             = 0;      }      else if ( mask == 0 )      {        cur[0] = c;        mask   = 0x80;        c      = 0;        cur ++;      }    }     if ( mask != 0x80 )      cur[0] = c;  }    static void  pfr_bitwriter_decode_rle1( PFR_BitWriter  writer,                             FT_Byte*       p,                             FT_Byte*       limit )  {    FT_Int    n, phase, count, counts[2], reload;    FT_Int    left = writer->width;    FT_Byte*  cur  = writer->line;    FT_UInt   mask = 0x80;    FT_UInt   c    = 0;      n = writer->total;     phase     = 1;    counts[0] = 0;    counts[1] = 0;    count     = 0;    reload    = 1;     for ( ; n > 0; n-- )    {      if ( reload )      {        do        {          if ( phase )          {            FT_Int  v;              if ( p >= limit )              break;             v         = *p++;            counts[0] = v >> 4;            counts[1] = v & 15;            phase     = 0;            count     = counts[0];          }          else          {            phase = 1;            count = counts[1];          }         } while ( count == 0 );      }       if ( phase )        c |= mask;       mask >>= 1;       if ( --left <= 0 )      {        cur[0] = (FT_Byte) c;        left   = writer->width;        mask   = 0x80;         writer->line += writer->pitch;        cur           = writer->line;        c             = 0;      }      else if ( mask == 0 )      {        cur[0] = c;        mask   = 0x80;        c      = 0;        cur ++;      }       reload = ( --count <= 0 );    }     if ( mask != 0x80 )      cur[0] = (FT_Byte) c;  }    static void  pfr_bitwriter_decode_rle2( PFR_BitWriter  writer,                             FT_Byte*       p,                             FT_Byte*       limit )  {    FT_Int    n, phase, count, reload;    FT_Int    left = writer->width;    FT_Byte*  cur  = writer->line;    FT_UInt   mask = 0x80;    FT_UInt   c    = 0;      n = writer->total;     phase  = 1;    count  = 0;    reload = 1;     for ( ; n > 0; n-- )    {      if ( reload )      {        do        {          if ( p >= limit )            break;           count = *p++;          phase = phase ^ 1;         } while ( count == 0 );      }       if ( phase )        c |= mask;       mask >>= 1;       if ( --left <= 0 )      {        cur[0] = (FT_Byte) c;        c      = 0;        mask   = 0x80;        left   = writer->width;         writer->line += writer->pitch;        cur           = writer->line;      }      else if ( mask == 0 )      {        cur[0] = c;        c      = 0;        mask   = 0x80;        cur ++;      }       reload = ( --count <= 0 );    }     if ( mask != 0x80 )      cur[0] = (FT_Byte) c;  }    /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                  BITMAP DATA DECODING                         *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/   static void  pfr_lookup_bitmap_data( FT_Byte*   base,                          FT_Byte*   limit,                          FT_Int     count,                          FT_Byte    flags,                          FT_UInt    char_code,                          FT_ULong*  found_offset,                          FT_ULong*  found_size )  {    FT_UInt   left, right, char_len;    FT_Bool   two = flags & 1;    FT_Byte*  buff;      char_len = 4;    if ( two )       char_len += 1;    if ( flags & 2 ) char_len += 1;    if ( flags & 4 ) char_len += 1;     left  = 0;    right = count;     while ( left < right )    {      FT_UInt  middle, code;        middle = ( left + right ) >> 1;      buff   = base + middle * char_len;       /* check that we are not outside of the table -- */      /* this is possible with broken fonts...         */      if ( buff + char_len > limit )        goto Fail;       if ( two )        code = PFR_NEXT_USHORT( buff );      else        code = PFR_NEXT_BYTE( buff );       if ( code == char_code )        goto Found_It;       if ( code < char_code )        left = middle;      else        right = middle;    }   Fail:    /* Not found */    *found_size   = 0;    *found_offset = 0;    return;   Found_It:    if ( flags & 2 )      *found_size = PFR_NEXT_USHORT( buff );    else      *found_size = PFR_NEXT_BYTE( buff );     if ( flags & 4 )      *found_offset = PFR_NEXT_ULONG( buff );    else      *found_offset = PFR_NEXT_USHORT( buff );  }    /* load bitmap metrics.  "*padvance" must be set to the default value */  /* before calling this function...                                    */  /*                                                                    */  static FT_Error  pfr_load_bitmap_metrics( FT_Byte**  pdata,                           FT_Byte*   limit,                           FT_Long    scaled_advance,                           FT_Long   *axpos,                           FT_Long   *aypos,                           FT_UInt   *axsize,                           FT_UInt   *aysize,                           FT_Long   *aadvance,                           FT_UInt   *aformat )  {    FT_Error  error = 0;    FT_Byte   flags;    FT_Char   b;    FT_Byte*  p = *pdata;    FT_Long   xpos, ypos, advance;    FT_UInt   xsize, ysize;      PFR_CHECK( 1 );    flags = PFR_NEXT_BYTE( p );     xpos    = 0;    ypos    = 0;    xsize   = 0;    ysize   = 0;    advance = 0;     switch ( flags & 3 )    {    case 0:      PFR_CHECK( 1 );      b    = PFR_NEXT_INT8( p );      xpos = b >> 4;      ypos = ( (FT_Char)( b << 4 ) ) >> 4;      break;     case 1:      PFR_CHECK( 2 );      xpos = PFR_NEXT_INT8( p );      ypos = PFR_NEXT_INT8( p );      break;     case 2:      PFR_CHECK( 4 );      xpos = PFR_NEXT_SHORT( p );      ypos = PFR_NEXT_SHORT( p );      break;     case 3:      PFR_CHECK( 6 );      xpos = PFR_NEXT_LONG( p );      ypos = PFR_NEXT_LONG( p );      break;     default:      ;    }     flags >>= 2;    switch ( flags & 3 )    {    case 0:      /* blank image */      xsize = 0;      ysize = 0;      break;     case 1:      PFR_CHECK( 1 );      b     = PFR_NEXT_BYTE( p );      xsize = ( b >> 4 ) & 0xF;      ysize = b & 0xF;      break;     case 2:      PFR_CHECK( 2 );      xsize = PFR_NEXT_BYTE( p );      ysize = PFR_NEXT_BYTE( p );      break;     case 3:      PFR_CHECK( 4 );      xsize = PFR_NEXT_USHORT( p );      ysize = PFR_NEXT_USHORT( p );      break;     default:      ;    }     flags >>= 2;    switch ( flags & 3 )    {    case 0:      advance = scaled_advance;      break;     case 1:      PFR_CHECK( 1 );      advance = PFR_NEXT_INT8( p ) << 8;      break;     case 2:      PFR_CHECK( 2 );      advance = PFR_NEXT_SHORT( p );      break;     case 3:      PFR_CHECK( 3 );      advance = PFR_NEXT_LONG( p );      break;     default:      ;    }     *axpos    = xpos;    *aypos    = ypos;    *axsize   = xsize;    *aysize   = ysize;    *aadvance = advance;    *aformat  = flags >> 2;    *pdata    = p;   Exit:    return error;   Too_Short:    error = PFR_Err_Invalid_Table;    FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" ));    goto Exit;  }    static FT_Error  pfr_load_bitmap_bits( FT_Byte*    p,                        FT_Byte*    limit,                        FT_UInt     format,                        FT_UInt     decreasing,                        FT_Bitmap*  target )  {    FT_Error          error = 0;    PFR_BitWriterRec  writer;      if ( target->rows > 0 && target->width > 0 )    {      pfr_bitwriter_init( &writer, target, decreasing );       switch ( format )      {      case 0: /* packed bits */        pfr_bitwriter_decode_bytes( &writer, p, limit );        break; 

Lines 1–500 of 670.