Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ftlzw.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 2004-2006, 2009, 2010, 2012, 2013 by                         */
  12. /*  Albert Chin-A-Young.                                                   */
  13. /*                                                                         */
  14. /*  Based on code in src/gzip/ftgzip.c, Copyright 2004 by                  */
  15. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  16. /*                                                                         */
  17. /*  This file is part of the FreeType project, and may only be used,       */
  18. /*  modified, and distributed under the terms of the FreeType project      */
  19. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  20. /*  this file you indicate that you have read the license and              */
  21. /*  understand and accept it fully.                                        */
  22. /*                                                                         */
  23. /***************************************************************************/
  24.  
  25. #include <ft2build.h>
  26. #include FT_INTERNAL_MEMORY_H
  27. #include FT_INTERNAL_STREAM_H
  28. #include FT_INTERNAL_DEBUG_H
  29. #include FT_LZW_H
  30. #include FT_CONFIG_STANDARD_LIBRARY_H
  31.  
  32.  
  33. #include FT_MODULE_ERRORS_H
  34.  
  35. #undef __FTERRORS_H__
  36.  
  37. #undef  FT_ERR_PREFIX
  38. #define FT_ERR_PREFIX  LZW_Err_
  39. #define FT_ERR_BASE    FT_Mod_Err_LZW
  40.  
  41. #include FT_ERRORS_H
  42.  
  43.  
  44. #ifdef FT_CONFIG_OPTION_USE_LZW
  45.  
  46. #ifdef FT_CONFIG_OPTION_PIC
  47. #error "lzw code does not support PIC yet"
  48. #endif
  49.  
  50. #include "ftzopen.h"
  51.  
  52.  
  53. /***************************************************************************/
  54. /***************************************************************************/
  55. /*****                                                                 *****/
  56. /*****                  M E M O R Y   M A N A G E M E N T              *****/
  57. /*****                                                                 *****/
  58. /***************************************************************************/
  59. /***************************************************************************/
  60.  
  61. /***************************************************************************/
  62. /***************************************************************************/
  63. /*****                                                                 *****/
  64. /*****                   F I L E   D E S C R I P T O R                 *****/
  65. /*****                                                                 *****/
  66. /***************************************************************************/
  67. /***************************************************************************/
  68.  
  69. #define FT_LZW_BUFFER_SIZE  4096
  70.  
  71.   typedef struct  FT_LZWFileRec_
  72.   {
  73.     FT_Stream       source;         /* parent/source stream        */
  74.     FT_Stream       stream;         /* embedding stream            */
  75.     FT_Memory       memory;         /* memory allocator            */
  76.     FT_LzwStateRec  lzw;            /* lzw decompressor state      */
  77.  
  78.     FT_Byte         buffer[FT_LZW_BUFFER_SIZE]; /* output buffer      */
  79.     FT_ULong        pos;                        /* position in output */
  80.     FT_Byte*        cursor;
  81.     FT_Byte*        limit;
  82.  
  83.   } FT_LZWFileRec, *FT_LZWFile;
  84.  
  85.  
  86.   /* check and skip .Z header */
  87.   static FT_Error
  88.   ft_lzw_check_header( FT_Stream  stream )
  89.   {
  90.     FT_Error  error;
  91.     FT_Byte   head[2];
  92.  
  93.  
  94.     if ( FT_STREAM_SEEK( 0 )       ||
  95.          FT_STREAM_READ( head, 2 ) )
  96.       goto Exit;
  97.  
  98.     /* head[0] && head[1] are the magic numbers */
  99.     if ( head[0] != 0x1f ||
  100.          head[1] != 0x9d )
  101.       error = FT_THROW( Invalid_File_Format );
  102.  
  103.   Exit:
  104.     return error;
  105.   }
  106.  
  107.  
  108.   static FT_Error
  109.   ft_lzw_file_init( FT_LZWFile  zip,
  110.                     FT_Stream   stream,
  111.                     FT_Stream   source )
  112.   {
  113.     FT_LzwState  lzw   = &zip->lzw;
  114.     FT_Error     error;
  115.  
  116.  
  117.     zip->stream = stream;
  118.     zip->source = source;
  119.     zip->memory = stream->memory;
  120.  
  121.     zip->limit  = zip->buffer + FT_LZW_BUFFER_SIZE;
  122.     zip->cursor = zip->limit;
  123.     zip->pos    = 0;
  124.  
  125.     /* check and skip .Z header */
  126.     error = ft_lzw_check_header( source );
  127.     if ( error )
  128.       goto Exit;
  129.  
  130.     /* initialize internal lzw variable */
  131.     ft_lzwstate_init( lzw, source );
  132.  
  133.   Exit:
  134.     return error;
  135.   }
  136.  
  137.  
  138.   static void
  139.   ft_lzw_file_done( FT_LZWFile  zip )
  140.   {
  141.     /* clear the rest */
  142.     ft_lzwstate_done( &zip->lzw );
  143.  
  144.     zip->memory = NULL;
  145.     zip->source = NULL;
  146.     zip->stream = NULL;
  147.   }
  148.  
  149.  
  150.   static FT_Error
  151.   ft_lzw_file_reset( FT_LZWFile  zip )
  152.   {
  153.     FT_Stream  stream = zip->source;
  154.     FT_Error   error;
  155.  
  156.  
  157.     if ( !FT_STREAM_SEEK( 0 ) )
  158.     {
  159.       ft_lzwstate_reset( &zip->lzw );
  160.  
  161.       zip->limit  = zip->buffer + FT_LZW_BUFFER_SIZE;
  162.       zip->cursor = zip->limit;
  163.       zip->pos    = 0;
  164.     }
  165.  
  166.     return error;
  167.   }
  168.  
  169.  
  170.   static FT_Error
  171.   ft_lzw_file_fill_output( FT_LZWFile  zip )
  172.   {
  173.     FT_LzwState  lzw = &zip->lzw;
  174.     FT_ULong     count;
  175.     FT_Error     error = FT_Err_Ok;
  176.  
  177.  
  178.     zip->cursor = zip->buffer;
  179.  
  180.     count = ft_lzwstate_io( lzw, zip->buffer, FT_LZW_BUFFER_SIZE );
  181.  
  182.     zip->limit = zip->cursor + count;
  183.  
  184.     if ( count == 0 )
  185.       error = FT_THROW( Invalid_Stream_Operation );
  186.  
  187.     return error;
  188.   }
  189.  
  190.  
  191.   /* fill output buffer; `count' must be <= FT_LZW_BUFFER_SIZE */
  192.   static FT_Error
  193.   ft_lzw_file_skip_output( FT_LZWFile  zip,
  194.                            FT_ULong    count )
  195.   {
  196.     FT_Error  error = FT_Err_Ok;
  197.  
  198.  
  199.     /* first, we skip what we can from the output buffer */
  200.     {
  201.       FT_ULong  delta = (FT_ULong)( zip->limit - zip->cursor );
  202.  
  203.  
  204.       if ( delta >= count )
  205.         delta = count;
  206.  
  207.       zip->cursor += delta;
  208.       zip->pos    += delta;
  209.  
  210.       count -= delta;
  211.     }
  212.  
  213.     /* next, we skip as many bytes remaining as possible */
  214.     while ( count > 0 )
  215.     {
  216.       FT_ULong  delta = FT_LZW_BUFFER_SIZE;
  217.       FT_ULong  numread;
  218.  
  219.  
  220.       if ( delta > count )
  221.         delta = count;
  222.  
  223.       numread = ft_lzwstate_io( &zip->lzw, NULL, delta );
  224.       if ( numread < delta )
  225.       {
  226.         /* not enough bytes */
  227.         error = FT_THROW( Invalid_Stream_Operation );
  228.         break;
  229.       }
  230.  
  231.       zip->pos += delta;
  232.       count    -= delta;
  233.     }
  234.  
  235.     return error;
  236.   }
  237.  
  238.  
  239.   static FT_ULong
  240.   ft_lzw_file_io( FT_LZWFile  zip,
  241.                   FT_ULong    pos,
  242.                   FT_Byte*    buffer,
  243.                   FT_ULong    count )
  244.   {
  245.     FT_ULong  result = 0;
  246.     FT_Error  error;
  247.  
  248.  
  249.     /* seeking backwards. */
  250.     if ( pos < zip->pos )
  251.     {
  252.       /* If the new position is within the output buffer, simply       */
  253.       /* decrement pointers, otherwise we reset the stream completely! */
  254.       if ( ( zip->pos - pos ) <= (FT_ULong)( zip->cursor - zip->buffer ) )
  255.       {
  256.         zip->cursor -= zip->pos - pos;
  257.         zip->pos     = pos;
  258.       }
  259.       else
  260.       {
  261.         error = ft_lzw_file_reset( zip );
  262.         if ( error )
  263.           goto Exit;
  264.       }
  265.     }
  266.  
  267.     /* skip unwanted bytes */
  268.     if ( pos > zip->pos )
  269.     {
  270.       error = ft_lzw_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
  271.       if ( error )
  272.         goto Exit;
  273.     }
  274.  
  275.     if ( count == 0 )
  276.       goto Exit;
  277.  
  278.     /* now read the data */
  279.     for (;;)
  280.     {
  281.       FT_ULong  delta;
  282.  
  283.  
  284.       delta = (FT_ULong)( zip->limit - zip->cursor );
  285.       if ( delta >= count )
  286.         delta = count;
  287.  
  288.       FT_MEM_COPY( buffer + result, zip->cursor, delta );
  289.       result      += delta;
  290.       zip->cursor += delta;
  291.       zip->pos    += delta;
  292.  
  293.       count -= delta;
  294.       if ( count == 0 )
  295.         break;
  296.  
  297.       error = ft_lzw_file_fill_output( zip );
  298.       if ( error )
  299.         break;
  300.     }
  301.  
  302.   Exit:
  303.     return result;
  304.   }
  305.  
  306.  
  307. /***************************************************************************/
  308. /***************************************************************************/
  309. /*****                                                                 *****/
  310. /*****            L Z W   E M B E D D I N G   S T R E A M              *****/
  311. /*****                                                                 *****/
  312. /***************************************************************************/
  313. /***************************************************************************/
  314.  
  315.   static void
  316.   ft_lzw_stream_close( FT_Stream  stream )
  317.   {
  318.     FT_LZWFile  zip    = (FT_LZWFile)stream->descriptor.pointer;
  319.     FT_Memory   memory = stream->memory;
  320.  
  321.  
  322.     if ( zip )
  323.     {
  324.       /* finalize lzw file descriptor */
  325.       ft_lzw_file_done( zip );
  326.  
  327.       FT_FREE( zip );
  328.  
  329.       stream->descriptor.pointer = NULL;
  330.     }
  331.   }
  332.  
  333.  
  334.   static FT_ULong
  335.   ft_lzw_stream_io( FT_Stream  stream,
  336.                     FT_ULong   pos,
  337.                     FT_Byte*   buffer,
  338.                     FT_ULong   count )
  339.   {
  340.     FT_LZWFile  zip = (FT_LZWFile)stream->descriptor.pointer;
  341.  
  342.  
  343.     return ft_lzw_file_io( zip, pos, buffer, count );
  344.   }
  345.  
  346.  
  347.   FT_EXPORT_DEF( FT_Error )
  348.   FT_Stream_OpenLZW( FT_Stream  stream,
  349.                      FT_Stream  source )
  350.   {
  351.     FT_Error    error;
  352.     FT_Memory   memory = source->memory;
  353.     FT_LZWFile  zip = NULL;
  354.  
  355.  
  356.     /*
  357.      *  Check the header right now; this prevents allocation of a huge
  358.      *  LZWFile object (400 KByte of heap memory) if not necessary.
  359.      *
  360.      *  Did I mention that you should never use .Z compressed font
  361.      *  files?
  362.      */
  363.     error = ft_lzw_check_header( source );
  364.     if ( error )
  365.       goto Exit;
  366.  
  367.     FT_ZERO( stream );
  368.     stream->memory = memory;
  369.  
  370.     if ( !FT_NEW( zip ) )
  371.     {
  372.       error = ft_lzw_file_init( zip, stream, source );
  373.       if ( error )
  374.       {
  375.         FT_FREE( zip );
  376.         goto Exit;
  377.       }
  378.  
  379.       stream->descriptor.pointer = zip;
  380.     }
  381.  
  382.     stream->size  = 0x7FFFFFFFL;  /* don't know the real size! */
  383.     stream->pos   = 0;
  384.     stream->base  = 0;
  385.     stream->read  = ft_lzw_stream_io;
  386.     stream->close = ft_lzw_stream_close;
  387.  
  388.   Exit:
  389.     return error;
  390.   }
  391.  
  392.  
  393. #include "ftzopen.c"
  394.  
  395.  
  396. #else  /* !FT_CONFIG_OPTION_USE_LZW */
  397.  
  398.  
  399.   FT_EXPORT_DEF( FT_Error )
  400.   FT_Stream_OpenLZW( FT_Stream  stream,
  401.                      FT_Stream  source )
  402.   {
  403.     FT_UNUSED( stream );
  404.     FT_UNUSED( source );
  405.  
  406.     return FT_THROW( Unimplemented_Feature );
  407.   }
  408.  
  409.  
  410. #endif /* !FT_CONFIG_OPTION_USE_LZW */
  411.  
  412.  
  413. /* END */
  414.