23#include FT_CONFIG_STANDARD_LIBRARY_H
26#if defined( TT_CONFIG_OPTION_EMBEDDED_BITMAPS ) && \
27 defined( FT_CONFIG_OPTION_USE_PNG )
30#define PNG_SKIP_SETJMP_CHECK 1
41 multiply_alpha(
unsigned int alpha,
44 unsigned int temp = alpha * color + 0x80;
47 return ( temp + ( temp >> 8 ) ) >> 8;
53 premultiply_data( png_structp png,
54 png_row_infop row_info,
57 unsigned int i = 0, limit;
67#if !defined( __INTEL_COMPILER ) && \
68 ( ( defined( __GNUC__ ) && \
69 ( ( __GNUC__ >= 5 ) || \
70 ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 7 ) ) ) ) || \
71 ( defined( __clang__ ) && \
72 ( ( __clang_major__ >= 4 ) || \
73 ( ( __clang_major__ == 3 ) && ( __clang_minor__ >= 2 ) ) ) ) ) && \
74 defined( __OPTIMIZE__ ) && \
75 defined( __SSE__ ) && \
76 __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
82#define vector_shuffle __builtin_shufflevector
84#define vector_shuffle __builtin_shuffle
87 typedef unsigned short v82
__attribute__(( vector_size( 16 ) ));
90 if ( row_info->rowbytes > 15 )
93 limit = row_info->rowbytes - 16 + 1;
94 for ( ; i < limit; i += 16 )
96 unsigned char* base = &data[i];
102 v82 n0x80 = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
103 v82 n0xFF = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
104 v82 n8 = { 8, 8, 8, 8, 8, 8, 8, 8 };
106 v82 ma = { 1, 1, 3, 3, 5, 5, 7, 7 };
107 v82 o1 = { 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF };
108 v82 m0 = { 1, 0, 3, 2, 5, 4, 7, 6 };
111 ft_memcpy( &s, base, 16 );
115 a = vector_shuffle( s1, ma );
117 s0 = vector_shuffle( s0, m0 );
123 s0 = ( s0 + ( s0 >> n8 ) ) >> n8;
124 s1 = ( s1 + ( s1 >> n8 ) ) >> n8;
126 s = s0 | ( s1 << n8 );
127 ft_memcpy( base, &s, 16 );
134 limit = row_info->rowbytes;
135 for ( ; i < limit; i += 4 )
137 unsigned char* base = &data[i];
138 unsigned int alpha = base[3];
142 base[0] = base[1] = base[2] = base[3] = 0;
146 unsigned int red = base[0];
147 unsigned int green = base[1];
148 unsigned int blue = base[2];
153 red = multiply_alpha( alpha, red );
154 green = multiply_alpha( alpha, green );
155 blue = multiply_alpha( alpha, blue );
158 base[0] = (
unsigned char)blue;
159 base[1] = (
unsigned char)green;
160 base[2] = (
unsigned char)red;
161 base[3] = (
unsigned char)alpha;
169 convert_bytes_to_data( png_structp png,
170 png_row_infop row_info,
178 for ( i = 0; i < row_info->rowbytes; i += 4 )
180 unsigned char* base = &data[i];
181 unsigned int red = base[0];
182 unsigned int green = base[1];
183 unsigned int blue = base[2];
186 base[0] = (
unsigned char)blue;
187 base[1] = (
unsigned char)green;
188 base[2] = (
unsigned char)red;
196 error_callback( png_structp png,
197 png_const_charp error_msg )
199 FT_Error* error = (FT_Error*)png_get_error_ptr( png );
201 FT_UNUSED( error_msg );
204 *error = FT_THROW( Out_Of_Memory );
205#ifdef PNG_SETJMP_SUPPORTED
206 ft_longjmp( png_jmpbuf( png ), 1 );
214 warning_callback( png_structp png,
215 png_const_charp error_msg )
218 FT_UNUSED( error_msg );
225 read_data_from_FT_Stream( png_structp png,
230 png_voidp p = png_get_io_ptr( png );
231 FT_Stream stream = (FT_Stream)p;
234 if ( FT_FRAME_ENTER( length ) )
236 FT_Error* e = (FT_Error*)png_get_error_ptr( png );
239 *e = FT_THROW( Invalid_Stream_Read );
240 png_error( png, NULL );
245 ft_memcpy( data, stream->cursor, length );
251 FT_LOCAL_DEF( FT_Error )
252 Load_SBit_Png( FT_GlyphSlot slot,
256 TT_SBit_Metrics metrics,
260 FT_Bool populate_map_and_metrics,
261 FT_Bool metrics_only )
263 FT_Bitmap *map = &slot->bitmap;
264 FT_Error error = FT_Err_Ok;
269 png_uint_32 imgWidth, imgHeight;
271 int bitdepth, color_type, interlace;
276 png_byte* *
volatile rows = NULL;
282 error = FT_THROW( Invalid_Argument );
286 if ( !populate_map_and_metrics &&
287 ( (FT_UInt)x_offset + metrics->width > map->width ||
288 (FT_UInt)y_offset + metrics->height > map->rows ||
290 map->pixel_mode != FT_PIXEL_MODE_BGRA ) )
292 error = FT_THROW( Invalid_Argument );
296 FT_Stream_OpenMemory( &stream, data, png_len );
298 png = png_create_read_struct( PNG_LIBPNG_VER_STRING,
304 error = FT_THROW( Out_Of_Memory );
308 info = png_create_info_struct( png );
311 error = FT_THROW( Out_Of_Memory );
312 png_destroy_read_struct( &png, NULL, NULL );
316 if ( ft_setjmp( png_jmpbuf( png ) ) )
318 error = FT_THROW( Invalid_File_Format );
322 png_set_read_fn( png, &stream, read_data_from_FT_Stream );
324 png_read_info( png, info );
325 png_get_IHDR( png, info,
326 &imgWidth, &imgHeight,
327 &bitdepth, &color_type, &interlace,
331 ( !populate_map_and_metrics &&
332 ( (FT_Int)imgWidth != metrics->width ||
333 (FT_Int)imgHeight != metrics->height ) ) )
336 if ( populate_map_and_metrics )
339 if ( imgHeight > 0x7FFF || imgWidth > 0x7FFF )
341 error = FT_THROW( Array_Too_Large );
345 metrics->width = (FT_UShort)imgWidth;
346 metrics->height = (FT_UShort)imgHeight;
348 map->width = metrics->width;
349 map->rows = metrics->height;
350 map->pixel_mode = FT_PIXEL_MODE_BGRA;
351 map->pitch = (int)( map->width * 4 );
352 map->num_grays = 256;
356 if ( color_type == PNG_COLOR_TYPE_PALETTE )
357 png_set_palette_to_rgb( png );
360 if ( color_type == PNG_COLOR_TYPE_GRAY )
362#if PNG_LIBPNG_VER >= 10209
363 png_set_expand_gray_1_2_4_to_8( png );
365 png_set_gray_1_2_4_to_8( png );
370 if ( png_get_valid( png, info, PNG_INFO_tRNS ) )
371 png_set_tRNS_to_alpha( png );
373 if ( bitdepth == 16 )
374 png_set_strip_16( png );
377 png_set_packing( png );
380 if ( color_type == PNG_COLOR_TYPE_GRAY ||
381 color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
382 png_set_gray_to_rgb( png );
384 if ( interlace != PNG_INTERLACE_NONE )
385 png_set_interlace_handling( png );
387 png_set_filler( png, 0xFF, PNG_FILLER_AFTER );
390 png_read_update_info( png, info );
391 png_get_IHDR( png, info,
392 &imgWidth, &imgHeight,
393 &bitdepth, &color_type, &interlace,
396 if ( bitdepth != 8 ||
397 !( color_type == PNG_COLOR_TYPE_RGB ||
398 color_type == PNG_COLOR_TYPE_RGB_ALPHA ) )
400 error = FT_THROW( Invalid_File_Format );
407 switch ( color_type )
410 case PNG_COLOR_TYPE_RGB_ALPHA:
411 png_set_read_user_transform_fn( png, premultiply_data );
414 case PNG_COLOR_TYPE_RGB:
416 png_set_read_user_transform_fn( png, convert_bytes_to_data );
420 if ( populate_map_and_metrics )
423 FT_ULong size = map->rows * (FT_ULong)map->pitch;
426 error = ft_glyphslot_alloc_bitmap( slot, size );
431 if ( FT_QNEW_ARRAY( rows, imgHeight ) )
433 error = FT_THROW( Out_Of_Memory );
437 for ( i = 0; i < (FT_Int)imgHeight; i++ )
438 rows[i] = map->buffer + ( y_offset + i ) * map->pitch + x_offset * 4;
440 png_read_image( png, rows );
442 png_read_end( png, info );
447 png_destroy_read_struct( &png, &info, NULL );
448 FT_Stream_Close( &stream );
457 typedef int pngshim_dummy_;