1 /***************************************************************************/
5 /* PNG Bitmap glyph support. */
7 /* Copyright 2013-2016 by */
9 /* Written by Stuart Gill and Behdad Esfahbod. */
11 /* This file is part of the FreeType project, and may only be used, */
12 /* modified, and distributed under the terms of the FreeType project */
13 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
14 /* this file you indicate that you have read the license and */
15 /* understand and accept it fully. */
17 /***************************************************************************/
21 #include FT_INTERNAL_DEBUG_H
22 #include FT_INTERNAL_STREAM_H
23 #include FT_TRUETYPE_TAGS_H
24 #include FT_CONFIG_STANDARD_LIBRARY_H
27 #ifdef FT_CONFIG_OPTION_USE_PNG
29 /* We always include <stjmp.h>, so make libpng shut up! */
30 #define PNG_SKIP_SETJMP_CHECK 1
37 /* This code is freely based on cairo-png.c. There's so many ways */
38 /* to call libpng, and the way cairo does it is defacto standard. */
41 multiply_alpha( unsigned int alpha,
44 unsigned int temp = alpha * color + 0x80;
47 return ( temp + ( temp >> 8 ) ) >> 8;
51 /* Premultiplies data and converts RGBA bytes => native endian. */
53 premultiply_data( png_structp png,
54 png_row_infop row_info,
62 for ( i = 0; i < row_info->rowbytes; i += 4 )
64 unsigned char* base = &data[i];
65 unsigned int alpha = base[3];
69 base[0] = base[1] = base[2] = base[3] = 0;
73 unsigned int red = base[0];
74 unsigned int green = base[1];
75 unsigned int blue = base[2];
80 red = multiply_alpha( alpha, red );
81 green = multiply_alpha( alpha, green );
82 blue = multiply_alpha( alpha, blue );
85 base[0] = (unsigned char)blue;
86 base[1] = (unsigned char)green;
87 base[2] = (unsigned char)red;
88 base[3] = (unsigned char)alpha;
94 /* Converts RGBx bytes to BGRA. */
96 convert_bytes_to_data( png_structp png,
97 png_row_infop row_info,
105 for ( i = 0; i < row_info->rowbytes; i += 4 )
107 unsigned char* base = &data[i];
108 unsigned int red = base[0];
109 unsigned int green = base[1];
110 unsigned int blue = base[2];
113 base[0] = (unsigned char)blue;
114 base[1] = (unsigned char)green;
115 base[2] = (unsigned char)red;
121 /* Use error callback to avoid png writing to stderr. */
123 error_callback( png_structp png,
124 png_const_charp error_msg )
126 FT_Error* error = (FT_Error*)png_get_error_ptr( png );
128 FT_UNUSED( error_msg );
131 *error = FT_THROW( Out_Of_Memory );
132 #ifdef PNG_SETJMP_SUPPORTED
133 ft_longjmp( png_jmpbuf( png ), 1 );
135 /* if we get here, then we have no choice but to abort ... */
139 /* Use warning callback to avoid png writing to stderr. */
141 warning_callback( png_structp png,
142 png_const_charp error_msg )
145 FT_UNUSED( error_msg );
147 /* Just ignore warnings. */
152 read_data_from_FT_Stream( png_structp png,
157 png_voidp p = png_get_io_ptr( png );
158 FT_Stream stream = (FT_Stream)p;
161 if ( FT_FRAME_ENTER( length ) )
163 FT_Error* e = (FT_Error*)png_get_error_ptr( png );
166 *e = FT_THROW( Invalid_Stream_Read );
167 png_error( png, NULL );
172 memcpy( data, stream->cursor, length );
178 FT_LOCAL_DEF( FT_Error )
179 Load_SBit_Png( FT_GlyphSlot slot,
183 TT_SBit_Metrics metrics,
187 FT_Bool populate_map_and_metrics )
189 FT_Bitmap *map = &slot->bitmap;
190 FT_Error error = FT_Err_Ok;
195 png_uint_32 imgWidth, imgHeight;
197 int bitdepth, color_type, interlace;
199 png_byte* *rows = NULL; /* pacify compiler */
205 error = FT_THROW( Invalid_Argument );
209 if ( !populate_map_and_metrics &&
210 ( (FT_UInt)x_offset + metrics->width > map->width ||
211 (FT_UInt)y_offset + metrics->height > map->rows ||
213 map->pixel_mode != FT_PIXEL_MODE_BGRA ) )
215 error = FT_THROW( Invalid_Argument );
219 FT_Stream_OpenMemory( &stream, data, png_len );
221 png = png_create_read_struct( PNG_LIBPNG_VER_STRING,
227 error = FT_THROW( Out_Of_Memory );
231 info = png_create_info_struct( png );
234 error = FT_THROW( Out_Of_Memory );
235 png_destroy_read_struct( &png, NULL, NULL );
239 if ( ft_setjmp( png_jmpbuf( png ) ) )
241 error = FT_THROW( Invalid_File_Format );
245 png_set_read_fn( png, &stream, read_data_from_FT_Stream );
247 png_read_info( png, info );
248 png_get_IHDR( png, info,
249 &imgWidth, &imgHeight,
250 &bitdepth, &color_type, &interlace,
254 ( !populate_map_and_metrics &&
255 ( (FT_Int)imgWidth != metrics->width ||
256 (FT_Int)imgHeight != metrics->height ) ) )
259 if ( populate_map_and_metrics )
264 metrics->width = (FT_UShort)imgWidth;
265 metrics->height = (FT_UShort)imgHeight;
267 map->width = metrics->width;
268 map->rows = metrics->height;
269 map->pixel_mode = FT_PIXEL_MODE_BGRA;
270 map->pitch = (int)( map->width * 4 );
271 map->num_grays = 256;
273 /* reject too large bitmaps similarly to the rasterizer */
274 if ( map->rows > 0x7FFF || map->width > 0x7FFF )
276 error = FT_THROW( Array_Too_Large );
280 /* this doesn't overflow: 0x7FFF * 0x7FFF * 4 < 2^32 */
281 size = map->rows * (FT_ULong)map->pitch;
283 error = ft_glyphslot_alloc_bitmap( slot, size );
288 /* convert palette/gray image to rgb */
289 if ( color_type == PNG_COLOR_TYPE_PALETTE )
290 png_set_palette_to_rgb( png );
292 /* expand gray bit depth if needed */
293 if ( color_type == PNG_COLOR_TYPE_GRAY )
295 #if PNG_LIBPNG_VER >= 10209
296 png_set_expand_gray_1_2_4_to_8( png );
298 png_set_gray_1_2_4_to_8( png );
302 /* transform transparency to alpha */
303 if ( png_get_valid(png, info, PNG_INFO_tRNS ) )
304 png_set_tRNS_to_alpha( png );
306 if ( bitdepth == 16 )
307 png_set_strip_16( png );
310 png_set_packing( png );
312 /* convert grayscale to RGB */
313 if ( color_type == PNG_COLOR_TYPE_GRAY ||
314 color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
315 png_set_gray_to_rgb( png );
317 if ( interlace != PNG_INTERLACE_NONE )
318 png_set_interlace_handling( png );
320 png_set_filler( png, 0xFF, PNG_FILLER_AFTER );
322 /* recheck header after setting EXPAND options */
323 png_read_update_info(png, info );
324 png_get_IHDR( png, info,
325 &imgWidth, &imgHeight,
326 &bitdepth, &color_type, &interlace,
329 if ( bitdepth != 8 ||
330 !( color_type == PNG_COLOR_TYPE_RGB ||
331 color_type == PNG_COLOR_TYPE_RGB_ALPHA ) )
333 error = FT_THROW( Invalid_File_Format );
337 switch ( color_type )
340 /* Shouldn't happen, but fall through. */
342 case PNG_COLOR_TYPE_RGB_ALPHA:
343 png_set_read_user_transform_fn( png, premultiply_data );
346 case PNG_COLOR_TYPE_RGB:
347 /* Humm, this smells. Carry on though. */
348 png_set_read_user_transform_fn( png, convert_bytes_to_data );
352 if ( FT_NEW_ARRAY( rows, imgHeight ) )
354 error = FT_THROW( Out_Of_Memory );
358 for ( i = 0; i < (FT_Int)imgHeight; i++ )
359 rows[i] = map->buffer + ( y_offset + i ) * map->pitch + x_offset * 4;
361 png_read_image( png, rows );
365 png_read_end( png, info );
368 png_destroy_read_struct( &png, &info, NULL );
369 FT_Stream_Close( &stream );
375 #endif /* FT_CONFIG_OPTION_USE_PNG */