(root)/
freetype-2.13.2/
src/
lzw/
ftzopen.c
       1  /****************************************************************************
       2   *
       3   * ftzopen.c
       4   *
       5   *   FreeType support for .Z compressed files.
       6   *
       7   * This optional component relies on NetBSD's zopen().  It should mainly
       8   * be used to parse compressed PCF fonts, as found with many X11 server
       9   * distributions.
      10   *
      11   * Copyright (C) 2005-2023 by
      12   * David Turner.
      13   *
      14   * This file is part of the FreeType project, and may only be used,
      15   * modified, and distributed under the terms of the FreeType project
      16   * license, LICENSE.TXT.  By continuing to use, modify, or distribute
      17   * this file you indicate that you have read the license and
      18   * understand and accept it fully.
      19   *
      20   */
      21  
      22  #include "ftzopen.h"
      23  #include <freetype/internal/ftmemory.h>
      24  #include <freetype/internal/ftstream.h>
      25  #include <freetype/internal/ftdebug.h>
      26  
      27  
      28    static int
      29    ft_lzwstate_refill( FT_LzwState  state )
      30    {
      31      FT_ULong  count;
      32  
      33  
      34      if ( state->in_eof )
      35        return -1;
      36  
      37      count = FT_Stream_TryRead( state->source,
      38                                 state->buf_tab,
      39                                 state->num_bits );  /* WHY? */
      40  
      41      state->buf_size   = (FT_UInt)count;
      42      state->buf_total += count;
      43      state->in_eof     = FT_BOOL( count < state->num_bits );
      44      state->buf_offset = 0;
      45  
      46      state->buf_size <<= 3;
      47      if ( state->buf_size > state->num_bits )
      48        state->buf_size -= state->num_bits - 1;
      49      else
      50        return -1; /* not enough data */
      51  
      52      if ( count == 0 )  /* end of file */
      53        return -1;
      54  
      55      return 0;
      56    }
      57  
      58  
      59    static FT_Int32
      60    ft_lzwstate_get_code( FT_LzwState  state )
      61    {
      62      FT_UInt   num_bits = state->num_bits;
      63      FT_UInt   offset   = state->buf_offset;
      64      FT_Byte*  p;
      65      FT_Int    result;
      66  
      67  
      68      if ( state->buf_clear                    ||
      69           offset >= state->buf_size           ||
      70           state->free_ent >= state->free_bits )
      71      {
      72        if ( state->free_ent >= state->free_bits )
      73        {
      74          state->num_bits = ++num_bits;
      75          if ( num_bits > LZW_MAX_BITS )
      76            return -1;
      77  
      78          state->free_bits = state->num_bits < state->max_bits
      79                             ? (FT_UInt)( ( 1UL << num_bits ) - 256 )
      80                             : state->max_free + 1;
      81        }
      82  
      83        if ( state->buf_clear )
      84        {
      85          state->num_bits  = num_bits = LZW_INIT_BITS;
      86          state->free_bits = (FT_UInt)( ( 1UL << num_bits ) - 256 );
      87          state->buf_clear = 0;
      88        }
      89  
      90        if ( ft_lzwstate_refill( state ) < 0 )
      91          return -1;
      92  
      93        offset = 0;
      94      }
      95  
      96      state->buf_offset = offset + num_bits;
      97  
      98      p         = &state->buf_tab[offset >> 3];
      99      offset   &= 7;
     100      result    = *p++ >> offset;
     101      offset    = 8 - offset;
     102      num_bits -= offset;
     103  
     104      if ( num_bits >= 8 )
     105      {
     106        result   |= *p++ << offset;
     107        offset   += 8;
     108        num_bits -= 8;
     109      }
     110      if ( num_bits > 0 )
     111        result |= ( *p & LZW_MASK( num_bits ) ) << offset;
     112  
     113      return result;
     114    }
     115  
     116  
     117    /* grow the character stack */
     118    static int
     119    ft_lzwstate_stack_grow( FT_LzwState  state )
     120    {
     121      if ( state->stack_top >= state->stack_size )
     122      {
     123        FT_Memory  memory = state->memory;
     124        FT_Error   error;
     125        FT_Offset  old_size = state->stack_size;
     126        FT_Offset  new_size = old_size;
     127  
     128        new_size = new_size + ( new_size >> 1 ) + 4;
     129  
     130        /* if relocating to heap */
     131        if ( state->stack == state->stack_0 )
     132        {
     133          state->stack = NULL;
     134          old_size     = 0;
     135        }
     136  
     137        /* requirement of the character stack larger than 1<<LZW_MAX_BITS */
     138        /* implies bug in the decompression code                          */
     139        if ( new_size > ( 1 << LZW_MAX_BITS ) )
     140        {
     141          new_size = 1 << LZW_MAX_BITS;
     142          if ( new_size == old_size )
     143            return -1;
     144        }
     145  
     146        if ( FT_QREALLOC( state->stack, old_size, new_size ) )
     147          return -1;
     148  
     149        /* if relocating to heap */
     150        if ( old_size == 0 )
     151          FT_MEM_COPY( state->stack, state->stack_0, FT_LZW_DEFAULT_STACK_SIZE );
     152  
     153        state->stack_size = new_size;
     154      }
     155      return 0;
     156    }
     157  
     158  
     159    /* grow the prefix/suffix arrays */
     160    static int
     161    ft_lzwstate_prefix_grow( FT_LzwState  state )
     162    {
     163      FT_UInt    old_size = state->prefix_size;
     164      FT_UInt    new_size = old_size;
     165      FT_Memory  memory   = state->memory;
     166      FT_Error   error;
     167  
     168  
     169      if ( new_size == 0 )  /* first allocation -> 9 bits */
     170        new_size = 512;
     171      else
     172        new_size += new_size >> 2;  /* don't grow too fast */
     173  
     174      /*
     175       * Note that the `suffix' array is located in the same memory block
     176       * pointed to by `prefix'.
     177       *
     178       * I know that sizeof(FT_Byte) == 1 by definition, but it is clearer
     179       * to write it literally.
     180       *
     181       */
     182      if ( FT_REALLOC_MULT( state->prefix, old_size, new_size,
     183                            sizeof ( FT_UShort ) + sizeof ( FT_Byte ) ) )
     184        return -1;
     185  
     186      /* now adjust `suffix' and move the data accordingly */
     187      state->suffix = (FT_Byte*)( state->prefix + new_size );
     188  
     189      FT_MEM_MOVE( state->suffix,
     190                   state->prefix + old_size,
     191                   old_size * sizeof ( FT_Byte ) );
     192  
     193      state->prefix_size = new_size;
     194      return 0;
     195    }
     196  
     197  
     198    FT_LOCAL_DEF( void )
     199    ft_lzwstate_reset( FT_LzwState  state )
     200    {
     201      state->in_eof     = 0;
     202      state->buf_offset = 0;
     203      state->buf_size   = 0;
     204      state->buf_clear  = 0;
     205      state->buf_total  = 0;
     206      state->stack_top  = 0;
     207      state->num_bits   = LZW_INIT_BITS;
     208      state->phase      = FT_LZW_PHASE_START;
     209    }
     210  
     211  
     212    FT_LOCAL_DEF( void )
     213    ft_lzwstate_init( FT_LzwState  state,
     214                      FT_Stream    source )
     215    {
     216      FT_ZERO( state );
     217  
     218      state->source = source;
     219      state->memory = source->memory;
     220  
     221      state->prefix      = NULL;
     222      state->suffix      = NULL;
     223      state->prefix_size = 0;
     224  
     225      state->stack      = state->stack_0;
     226      state->stack_size = sizeof ( state->stack_0 );
     227  
     228      ft_lzwstate_reset( state );
     229    }
     230  
     231  
     232    FT_LOCAL_DEF( void )
     233    ft_lzwstate_done( FT_LzwState  state )
     234    {
     235      FT_Memory  memory = state->memory;
     236  
     237  
     238      ft_lzwstate_reset( state );
     239  
     240      if ( state->stack != state->stack_0 )
     241        FT_FREE( state->stack );
     242  
     243      FT_FREE( state->prefix );
     244      state->suffix = NULL;
     245  
     246      FT_ZERO( state );
     247    }
     248  
     249  
     250  #define FTLZW_STACK_PUSH( c )                        \
     251    FT_BEGIN_STMNT                                     \
     252      if ( state->stack_top >= state->stack_size &&    \
     253           ft_lzwstate_stack_grow( state ) < 0   )     \
     254        goto Eof;                                      \
     255                                                       \
     256      state->stack[state->stack_top++] = (FT_Byte)(c); \
     257    FT_END_STMNT
     258  
     259  
     260    FT_LOCAL_DEF( FT_ULong )
     261    ft_lzwstate_io( FT_LzwState  state,
     262                    FT_Byte*     buffer,
     263                    FT_ULong     out_size )
     264    {
     265      FT_ULong  result = 0;
     266  
     267      FT_UInt  old_char = state->old_char;
     268      FT_UInt  old_code = state->old_code;
     269      FT_UInt  in_code  = state->in_code;
     270  
     271  
     272      if ( out_size == 0 )
     273        goto Exit;
     274  
     275      switch ( state->phase )
     276      {
     277      case FT_LZW_PHASE_START:
     278        {
     279          FT_Byte   max_bits;
     280          FT_Int32  c;
     281  
     282  
     283          /* skip magic bytes, and read max_bits + block_flag */
     284          if ( FT_Stream_Seek( state->source, 2 ) != 0               ||
     285               FT_Stream_TryRead( state->source, &max_bits, 1 ) != 1 )
     286            goto Eof;
     287  
     288          state->max_bits   = max_bits & LZW_BIT_MASK;
     289          state->block_mode = max_bits & LZW_BLOCK_MASK;
     290          state->max_free   = (FT_UInt)( ( 1UL << state->max_bits ) - 256 );
     291  
     292          if ( state->max_bits > LZW_MAX_BITS )
     293            goto Eof;
     294  
     295          state->num_bits = LZW_INIT_BITS;
     296          state->free_ent = ( state->block_mode ? LZW_FIRST
     297                                                : LZW_CLEAR ) - 256;
     298          in_code  = 0;
     299  
     300          state->free_bits = state->num_bits < state->max_bits
     301                             ? (FT_UInt)( ( 1UL << state->num_bits ) - 256 )
     302                             : state->max_free + 1;
     303  
     304          c = ft_lzwstate_get_code( state );
     305          if ( c < 0 || c > 255 )
     306            goto Eof;
     307  
     308          old_code = old_char = (FT_UInt)c;
     309  
     310          if ( buffer )
     311            buffer[result] = (FT_Byte)old_char;
     312  
     313          if ( ++result >= out_size )
     314            goto Exit;
     315  
     316          state->phase = FT_LZW_PHASE_CODE;
     317        }
     318        FALL_THROUGH;
     319  
     320      case FT_LZW_PHASE_CODE:
     321        {
     322          FT_Int32  c;
     323          FT_UInt   code;
     324  
     325  
     326        NextCode:
     327          c = ft_lzwstate_get_code( state );
     328          if ( c < 0 )
     329            goto Eof;
     330  
     331          code = (FT_UInt)c;
     332  
     333          if ( code == LZW_CLEAR && state->block_mode )
     334          {
     335            /* why not LZW_FIRST-256 ? */
     336            state->free_ent  = ( LZW_FIRST - 1 ) - 256;
     337            state->buf_clear = 1;
     338  
     339            /* not quite right, but at least more predictable */
     340            old_code = 0;
     341            old_char = 0;
     342  
     343            goto NextCode;
     344          }
     345  
     346          in_code = code; /* save code for later */
     347  
     348          if ( code >= 256U )
     349          {
     350            /* special case for KwKwKwK */
     351            if ( code - 256U >= state->free_ent )
     352            {
     353              /* corrupted LZW stream */
     354              if ( code - 256U > state->free_ent )
     355                goto Eof;
     356  
     357              FTLZW_STACK_PUSH( old_char );
     358              code = old_code;
     359            }
     360  
     361            while ( code >= 256U )
     362            {
     363              if ( !state->prefix )
     364                goto Eof;
     365  
     366              FTLZW_STACK_PUSH( state->suffix[code - 256] );
     367              code = state->prefix[code - 256];
     368            }
     369          }
     370  
     371          old_char = code;
     372          FTLZW_STACK_PUSH( old_char );
     373  
     374          state->phase = FT_LZW_PHASE_STACK;
     375        }
     376        FALL_THROUGH;
     377  
     378      case FT_LZW_PHASE_STACK:
     379        {
     380          while ( state->stack_top > 0 )
     381          {
     382            state->stack_top--;
     383  
     384            if ( buffer )
     385              buffer[result] = state->stack[state->stack_top];
     386  
     387            if ( ++result == out_size )
     388              goto Exit;
     389          }
     390  
     391          /* now create new entry */
     392          if ( state->free_ent < state->max_free )
     393          {
     394            if ( state->free_ent >= state->prefix_size &&
     395                 ft_lzwstate_prefix_grow( state ) < 0  )
     396              goto Eof;
     397  
     398            FT_ASSERT( state->free_ent < state->prefix_size );
     399  
     400            state->prefix[state->free_ent] = (FT_UShort)old_code;
     401            state->suffix[state->free_ent] = (FT_Byte)  old_char;
     402  
     403            state->free_ent += 1;
     404          }
     405  
     406          old_code = in_code;
     407  
     408          state->phase = FT_LZW_PHASE_CODE;
     409          goto NextCode;
     410        }
     411  
     412      default:  /* state == EOF */
     413        ;
     414      }
     415  
     416    Exit:
     417      state->old_code = old_code;
     418      state->old_char = old_char;
     419      state->in_code  = in_code;
     420  
     421      return result;
     422  
     423    Eof:
     424      state->phase = FT_LZW_PHASE_EOF;
     425      goto Exit;
     426    }
     427  
     428  
     429  /* END */