1727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/***************************************************************************/
2727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/*                                                                         */
3727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/*  pngshim.c                                                              */
4727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/*                                                                         */
5727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/*    PNG Bitmap glyph support.                                            */
6727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/*                                                                         */
79c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*  Copyright 2013, 2014 by Google, Inc.                                   */
8727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/*  Written by Stuart Gill and Behdad Esfahbod.                            */
9727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/*                                                                         */
10727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/*  This file is part of the FreeType project, and may only be used,       */
11727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/*  modified, and distributed under the terms of the FreeType project      */
12727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/*  this file you indicate that you have read the license and              */
14727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/*  understand and accept it fully.                                        */
15727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/*                                                                         */
16727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/***************************************************************************/
17727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
18727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
19727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include <ft2build.h>
20727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include FT_INTERNAL_DEBUG_H
21727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include FT_INTERNAL_STREAM_H
22727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include FT_TRUETYPE_TAGS_H
23727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include FT_CONFIG_STANDARD_LIBRARY_H
24727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
25727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
26727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#ifdef FT_CONFIG_OPTION_USE_PNG
27727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
28727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* We always include <stjmp.h>, so make libpng shut up! */
29727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#define PNG_SKIP_SETJMP_CHECK 1
30727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include <png.h>
31727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include "pngshim.h"
32727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
33727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include "sferrors.h"
34727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
35727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
36727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* This code is freely based on cairo-png.c.  There's so many ways */
37727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* to call libpng, and the way cairo does it is defacto standard.  */
38727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
39727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  static int
40727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  multiply_alpha( int  alpha,
41727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                  int  color )
42727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  {
43727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    int  temp = ( alpha * color ) + 0x80;
44727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
45727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
46727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return ( temp + ( temp >> 8 ) ) >> 8;
47727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  }
48727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
49727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
50727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* Premultiplies data and converts RGBA bytes => native endian. */
51727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  static void
52727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  premultiply_data( png_structp    png,
53727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                    png_row_infop  row_info,
54727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                    png_bytep      data )
55727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  {
56727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    unsigned int  i;
57727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
58727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_UNUSED( png );
59727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
60727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
61727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    for ( i = 0; i < row_info->rowbytes; i += 4 )
62727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    {
63727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      unsigned char*  base  = &data[i];
64727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      unsigned int    alpha = base[3];
65727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
66727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
67727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      if ( alpha == 0 )
68727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        base[0] = base[1] = base[2] = base[3] = 0;
69727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
70727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      else
71727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      {
72727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        unsigned int  red   = base[0];
73727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        unsigned int  green = base[1];
74727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        unsigned int  blue  = base[2];
75727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
76727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
77727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        if ( alpha != 0xFF )
78727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        {
79727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          red   = multiply_alpha( alpha, red   );
80727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          green = multiply_alpha( alpha, green );
81727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          blue  = multiply_alpha( alpha, blue  );
82727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        }
83727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
84727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        base[0] = blue;
85727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        base[1] = green;
86727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        base[2] = red;
87727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        base[3] = alpha;
88727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      }
89727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
90727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  }
91727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
92727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
93727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* Converts RGBx bytes to BGRA. */
94727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  static void
95727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  convert_bytes_to_data( png_structp    png,
96727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                         png_row_infop  row_info,
97727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                         png_bytep      data )
98727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  {
99727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    unsigned int  i;
100727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
101727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_UNUSED( png );
102727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
103727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
104727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    for ( i = 0; i < row_info->rowbytes; i += 4 )
105727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    {
106727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      unsigned char*  base  = &data[i];
107727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      unsigned int    red   = base[0];
108727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      unsigned int    green = base[1];
109727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      unsigned int    blue  = base[2];
110727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
111727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
112727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      base[0] = blue;
113727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      base[1] = green;
114727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      base[2] = red;
115727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      base[3] = 0xFF;
116727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
117727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  }
118727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
119727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
120727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* Use error callback to avoid png writing to stderr. */
121727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  static void
122727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  error_callback( png_structp      png,
123727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                  png_const_charp  error_msg )
124727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  {
125ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    FT_Error*  error = (FT_Error*)png_get_error_ptr( png );
126727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
127727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_UNUSED( error_msg );
128727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
129727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
130727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    *error = FT_THROW( Out_Of_Memory );
131727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#ifdef PNG_SETJMP_SUPPORTED
1329c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    ft_longjmp( png_jmpbuf( png ), 1 );
133727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#endif
134727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* if we get here, then we have no choice but to abort ... */
135727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  }
136727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
137727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
138727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* Use warning callback to avoid png writing to stderr. */
139727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  static void
140727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  warning_callback( png_structp      png,
141727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                    png_const_charp  error_msg )
142727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  {
143727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_UNUSED( png );
144727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_UNUSED( error_msg );
145727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
146727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* Just ignore warnings. */
147727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  }
148727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
149727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
150727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  static void
151727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  read_data_from_FT_Stream( png_structp  png,
152727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                            png_bytep    data,
153727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                            png_size_t   length )
154727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  {
155727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error   error;
156727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    png_voidp  p      = png_get_io_ptr( png );
157727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Stream  stream = (FT_Stream)p;
158727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
159727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
160727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( FT_FRAME_ENTER( length ) )
161727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    {
162ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      FT_Error*  e = (FT_Error*)png_get_error_ptr( png );
163727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
164727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
165727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      *e = FT_THROW( Invalid_Stream_Read );
166727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      png_error( png, NULL );
167727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
168727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return;
169727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
170727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
171727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    memcpy( data, stream->cursor, length );
172727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
173727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_FRAME_EXIT();
174727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  }
175727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
176727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
177ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  FT_LOCAL_DEF( FT_Error )
178ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  Load_SBit_Png( FT_GlyphSlot     slot,
179727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                 FT_Int           x_offset,
180727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                 FT_Int           y_offset,
181727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                 FT_Int           pix_bits,
182727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                 TT_SBit_Metrics  metrics,
183727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                 FT_Memory        memory,
184727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                 FT_Byte*         data,
185ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                 FT_UInt          png_len,
186ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease                 FT_Bool          populate_map_and_metrics )
187727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  {
188ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    FT_Bitmap    *map   = &slot->bitmap;
189727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error      error = FT_Err_Ok;
190727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_StreamRec  stream;
191727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
192727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    png_structp  png;
193727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    png_infop    info;
194727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    png_uint_32  imgWidth, imgHeight;
195727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
196727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    int         bitdepth, color_type, interlace;
197727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Int      i;
198ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    png_byte*  *rows = NULL; /* pacify compiler */
199727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
200727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
201ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    if ( x_offset < 0 ||
202ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease         y_offset < 0 )
203ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    {
204ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      error = FT_THROW( Invalid_Argument );
205ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      goto Exit;
206ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    }
207ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
208ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    if ( !populate_map_and_metrics                   &&
209ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease         ( x_offset + metrics->width  > map->width ||
210ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease           y_offset + metrics->height > map->rows  ||
211ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease           pix_bits != 32                          ||
212ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease           map->pixel_mode != FT_PIXEL_MODE_BGRA   ) )
213727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    {
214727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      error = FT_THROW( Invalid_Argument );
215727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      goto Exit;
216727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
217727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
218727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Stream_OpenMemory( &stream, data, png_len );
219727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
220727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    png = png_create_read_struct( PNG_LIBPNG_VER_STRING,
221727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                                  &error,
222727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                                  error_callback,
223727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                                  warning_callback );
224727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( !png )
225727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    {
226727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      error = FT_THROW( Out_Of_Memory );
227727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      goto Exit;
228727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
229727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
230727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    info = png_create_info_struct( png );
231727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( !info )
232727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    {
233727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      error = FT_THROW( Out_Of_Memory );
234727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      png_destroy_read_struct( &png, NULL, NULL );
235727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      goto Exit;
236727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
237727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
238727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( ft_setjmp( png_jmpbuf( png ) ) )
239727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    {
240727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      error = FT_THROW( Invalid_File_Format );
241727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      goto DestroyExit;
242727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
243727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
244727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    png_set_read_fn( png, &stream, read_data_from_FT_Stream );
245727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
246727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    png_read_info( png, info );
247727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    png_get_IHDR( png, info,
248727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                  &imgWidth, &imgHeight,
249727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                  &bitdepth, &color_type, &interlace,
250727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                  NULL, NULL );
251727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
252ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    if ( error                                        ||
253ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease         ( !populate_map_and_metrics                &&
254ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease           ( (FT_Int)imgWidth  != metrics->width  ||
255ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease             (FT_Int)imgHeight != metrics->height ) ) )
256727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      goto DestroyExit;
257727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
258ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    if ( populate_map_and_metrics )
259ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    {
260ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      FT_Long  size;
261ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
262ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
263ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      metrics->width  = (FT_Int)imgWidth;
264ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      metrics->height = (FT_Int)imgHeight;
265ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
266ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      map->width      = metrics->width;
267ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      map->rows       = metrics->height;
268ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      map->pixel_mode = FT_PIXEL_MODE_BGRA;
269ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      map->pitch      = map->width * 4;
270ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      map->num_grays  = 256;
271ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
272ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      size = map->rows * map->pitch;
273ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
274ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      error = ft_glyphslot_alloc_bitmap( slot, size );
275ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      if ( error )
276ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        goto DestroyExit;
277ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    }
278ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
279727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* convert palette/gray image to rgb */
280727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( color_type == PNG_COLOR_TYPE_PALETTE )
281727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      png_set_palette_to_rgb( png );
282727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
283727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* expand gray bit depth if needed */
284727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( color_type == PNG_COLOR_TYPE_GRAY )
285727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    {
286727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#if PNG_LIBPNG_VER >= 10209
287727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      png_set_expand_gray_1_2_4_to_8( png );
288727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#else
289727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      png_set_gray_1_2_4_to_8( png );
290727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#endif
291727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
292727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
293727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* transform transparency to alpha */
294727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( png_get_valid(png, info, PNG_INFO_tRNS ) )
295727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      png_set_tRNS_to_alpha( png );
296727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
297727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( bitdepth == 16 )
298727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      png_set_strip_16( png );
299727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
300727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( bitdepth < 8 )
301727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      png_set_packing( png );
302727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
303727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* convert grayscale to RGB */
304727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( color_type == PNG_COLOR_TYPE_GRAY       ||
305727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease         color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
306727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      png_set_gray_to_rgb( png );
307727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
308727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( interlace != PNG_INTERLACE_NONE )
309727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      png_set_interlace_handling( png );
310727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
311727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    png_set_filler( png, 0xFF, PNG_FILLER_AFTER );
312727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
313727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* recheck header after setting EXPAND options */
314727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    png_read_update_info(png, info );
315727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    png_get_IHDR( png, info,
316727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                  &imgWidth, &imgHeight,
317727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                  &bitdepth, &color_type, &interlace,
318727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                  NULL, NULL );
319727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
320727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( bitdepth != 8                              ||
321727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        !( color_type == PNG_COLOR_TYPE_RGB       ||
322727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease           color_type == PNG_COLOR_TYPE_RGB_ALPHA ) )
323727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    {
324727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      error = FT_THROW( Invalid_File_Format );
325727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      goto DestroyExit;
326727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
327727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
328727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    switch ( color_type )
329727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    {
330727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    default:
331727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      /* Shouldn't happen, but fall through. */
332727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
333727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    case PNG_COLOR_TYPE_RGB_ALPHA:
334727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      png_set_read_user_transform_fn( png, premultiply_data );
335727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      break;
336727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
337727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    case PNG_COLOR_TYPE_RGB:
338727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      /* Humm, this smells.  Carry on though. */
339727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      png_set_read_user_transform_fn( png, convert_bytes_to_data );
340727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      break;
341727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
342727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
343727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( FT_NEW_ARRAY( rows, imgHeight ) )
344727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    {
345727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      error = FT_THROW( Out_Of_Memory );
346727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      goto DestroyExit;
347727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
348727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
349727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    for ( i = 0; i < (FT_Int)imgHeight; i++ )
350727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      rows[i] = map->buffer + ( y_offset + i ) * map->pitch + x_offset * 4;
351727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
352727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    png_read_image( png, rows );
353727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
354727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_FREE( rows );
355727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
356727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    png_read_end( png, info );
357727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
358727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  DestroyExit:
359727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    png_destroy_read_struct( &png, &info, NULL );
360727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Stream_Close( &stream );
361727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
362727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  Exit:
363727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return error;
364727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  }
365727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
366727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#endif /* FT_CONFIG_OPTION_USE_PNG */
367727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
368727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
369727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/* END */
370