ReactOS 0.4.16-dev-2358-g0df3463
pngshim.c
Go to the documentation of this file.
1/****************************************************************************
2 *
3 * pngshim.c
4 *
5 * PNG Bitmap glyph support.
6 *
7 * Copyright (C) 2013-2020 by
8 * Google, Inc.
9 * Written by Stuart Gill and Behdad Esfahbod.
10 *
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.
16 *
17 */
18
19
22#include <freetype/tttags.h>
23#include FT_CONFIG_STANDARD_LIBRARY_H
24
25
26#if defined( TT_CONFIG_OPTION_EMBEDDED_BITMAPS ) && \
27 defined( FT_CONFIG_OPTION_USE_PNG )
28
29 /* We always include <setjmp.h>, so make libpng shut up! */
30#define PNG_SKIP_SETJMP_CHECK 1
31#include <png.h>
32#include "pngshim.h"
33
34#include "sferrors.h"
35
36
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. */
39
40 static unsigned int
41 multiply_alpha( unsigned int alpha,
42 unsigned int color )
43 {
44 unsigned int temp = alpha * color + 0x80;
45
46
47 return ( temp + ( temp >> 8 ) ) >> 8;
48 }
49
50
51 /* Premultiplies data and converts RGBA bytes => BGRA. */
52 static void
53 premultiply_data( png_structp png,
54 png_row_infop row_info,
56 {
57 unsigned int i = 0, limit;
58
59 /* The `vector_size' attribute was introduced in gcc 3.1, which */
60 /* predates clang; the `__BYTE_ORDER__' preprocessor symbol was */
61 /* introduced in gcc 4.6 and clang 3.2, respectively. */
62 /* `__builtin_shuffle' for gcc was introduced in gcc 4.7.0. */
63 /* */
64 /* Intel compilers do not currently support __builtin_shuffle; */
65
66 /* The Intel check must be first. */
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__
77
78#ifdef __clang__
79 /* the clang documentation doesn't cover the two-argument case of */
80 /* `__builtin_shufflevector'; however, it is is implemented since */
81 /* version 2.8 */
82#define vector_shuffle __builtin_shufflevector
83#else
84#define vector_shuffle __builtin_shuffle
85#endif
86
87 typedef unsigned short v82 __attribute__(( vector_size( 16 ) ));
88
89
90 if ( row_info->rowbytes > 15 )
91 {
92 /* process blocks of 16 bytes in one rush, which gives a nice speed-up */
93 limit = row_info->rowbytes - 16 + 1;
94 for ( ; i < limit; i += 16 )
95 {
96 unsigned char* base = &data[i];
97
98 v82 s, s0, s1, a;
99
100 /* clang <= 3.9 can't apply scalar values to vectors */
101 /* (or rather, it needs a different syntax) */
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 };
105
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 };
109
110
111 ft_memcpy( &s, base, 16 ); /* RGBA RGBA RGBA RGBA */
112 s0 = s & n0xFF; /* R B R B R B R B */
113 s1 = s >> n8; /* G A G A G A G A */
114
115 a = vector_shuffle( s1, ma ); /* A A A A A A A A */
116 s1 |= o1; /* G 1 G 1 G 1 G 1 */
117 s0 = vector_shuffle( s0, m0 ); /* B R B R B R B R */
118
119 s0 *= a;
120 s1 *= a;
121 s0 += n0x80;
122 s1 += n0x80;
123 s0 = ( s0 + ( s0 >> n8 ) ) >> n8;
124 s1 = ( s1 + ( s1 >> n8 ) ) >> n8;
125
126 s = s0 | ( s1 << n8 );
127 ft_memcpy( base, &s, 16 );
128 }
129 }
130#endif /* use `vector_size' */
131
132 FT_UNUSED( png );
133
134 limit = row_info->rowbytes;
135 for ( ; i < limit; i += 4 )
136 {
137 unsigned char* base = &data[i];
138 unsigned int alpha = base[3];
139
140
141 if ( alpha == 0 )
142 base[0] = base[1] = base[2] = base[3] = 0;
143
144 else
145 {
146 unsigned int red = base[0];
147 unsigned int green = base[1];
148 unsigned int blue = base[2];
149
150
151 if ( alpha != 0xFF )
152 {
153 red = multiply_alpha( alpha, red );
154 green = multiply_alpha( alpha, green );
155 blue = multiply_alpha( alpha, blue );
156 }
157
158 base[0] = (unsigned char)blue;
159 base[1] = (unsigned char)green;
160 base[2] = (unsigned char)red;
161 base[3] = (unsigned char)alpha;
162 }
163 }
164 }
165
166
167 /* Converts RGBx bytes to BGRA. */
168 static void
169 convert_bytes_to_data( png_structp png,
170 png_row_infop row_info,
172 {
173 unsigned int i;
174
175 FT_UNUSED( png );
176
177
178 for ( i = 0; i < row_info->rowbytes; i += 4 )
179 {
180 unsigned char* base = &data[i];
181 unsigned int red = base[0];
182 unsigned int green = base[1];
183 unsigned int blue = base[2];
184
185
186 base[0] = (unsigned char)blue;
187 base[1] = (unsigned char)green;
188 base[2] = (unsigned char)red;
189 base[3] = 0xFF;
190 }
191 }
192
193
194 /* Use error callback to avoid png writing to stderr. */
195 static void
196 error_callback( png_structp png,
198 {
199 FT_Error* error = (FT_Error*)png_get_error_ptr( png );
200
202
203
204 *error = FT_THROW( Out_Of_Memory );
205#ifdef PNG_SETJMP_SUPPORTED
206 ft_longjmp( png_jmpbuf( png ), 1 );
207#endif
208 /* if we get here, then we have no choice but to abort ... */
209 }
210
211
212 /* Use warning callback to avoid png writing to stderr. */
213 static void
214 warning_callback( png_structp png,
216 {
217 FT_UNUSED( png );
219
220 /* Just ignore warnings. */
221 }
222
223
224 static void
225 read_data_from_FT_Stream( png_structp png,
228 {
230 png_voidp p = png_get_io_ptr( png );
232
233
234 if ( FT_FRAME_ENTER( length ) )
235 {
236 FT_Error* e = (FT_Error*)png_get_error_ptr( png );
237
238
239 *e = FT_THROW( Invalid_Stream_Read );
240 png_error( png, NULL );
241
242 return;
243 }
244
245 ft_memcpy( data, stream->cursor, length );
246
248 }
249
250
252 Load_SBit_Png( FT_GlyphSlot slot,
253 FT_Int x_offset,
254 FT_Int y_offset,
255 FT_Int pix_bits,
258 FT_Byte* data,
259 FT_UInt png_len,
260 FT_Bool populate_map_and_metrics,
261 FT_Bool metrics_only )
262 {
263 FT_Bitmap *map = &slot->bitmap;
266
267 png_structp png;
269 png_uint_32 imgWidth, imgHeight;
270
271 int bitdepth, color_type, interlace;
272 FT_Int i;
273 png_byte* *rows = NULL; /* pacify compiler */
274
275
276 if ( x_offset < 0 ||
277 y_offset < 0 )
278 {
279 error = FT_THROW( Invalid_Argument );
280 goto Exit;
281 }
282
283 if ( !populate_map_and_metrics &&
284 ( (FT_UInt)x_offset + metrics->width > map->width ||
285 (FT_UInt)y_offset + metrics->height > map->rows ||
286 pix_bits != 32 ||
287 map->pixel_mode != FT_PIXEL_MODE_BGRA ) )
288 {
289 error = FT_THROW( Invalid_Argument );
290 goto Exit;
291 }
292
293 FT_Stream_OpenMemory( &stream, data, png_len );
294
295 png = png_create_read_struct( PNG_LIBPNG_VER_STRING,
296 &error,
297 error_callback,
298 warning_callback );
299 if ( !png )
300 {
301 error = FT_THROW( Out_Of_Memory );
302 goto Exit;
303 }
304
305 info = png_create_info_struct( png );
306 if ( !info )
307 {
308 error = FT_THROW( Out_Of_Memory );
309 png_destroy_read_struct( &png, NULL, NULL );
310 goto Exit;
311 }
312
313 if ( ft_setjmp( png_jmpbuf( png ) ) )
314 {
315 error = FT_THROW( Invalid_File_Format );
316 goto DestroyExit;
317 }
318
319 png_set_read_fn( png, &stream, read_data_from_FT_Stream );
320
321 png_read_info( png, info );
322 png_get_IHDR( png, info,
323 &imgWidth, &imgHeight,
324 &bitdepth, &color_type, &interlace,
325 NULL, NULL );
326
327 if ( error ||
328 ( !populate_map_and_metrics &&
329 ( (FT_Int)imgWidth != metrics->width ||
330 (FT_Int)imgHeight != metrics->height ) ) )
331 goto DestroyExit;
332
333 if ( populate_map_and_metrics )
334 {
335 /* reject too large bitmaps similarly to the rasterizer */
336 if ( imgHeight > 0x7FFF || imgWidth > 0x7FFF )
337 {
338 error = FT_THROW( Array_Too_Large );
339 goto DestroyExit;
340 }
341
342 metrics->width = (FT_UShort)imgWidth;
343 metrics->height = (FT_UShort)imgHeight;
344
345 map->width = metrics->width;
346 map->rows = metrics->height;
347 map->pixel_mode = FT_PIXEL_MODE_BGRA;
348 map->pitch = (int)( map->width * 4 );
349 map->num_grays = 256;
350 }
351
352 /* convert palette/gray image to rgb */
353 if ( color_type == PNG_COLOR_TYPE_PALETTE )
354 png_set_palette_to_rgb( png );
355
356 /* expand gray bit depth if needed */
357 if ( color_type == PNG_COLOR_TYPE_GRAY )
358 {
359#if PNG_LIBPNG_VER >= 10209
360 png_set_expand_gray_1_2_4_to_8( png );
361#else
362 png_set_gray_1_2_4_to_8( png );
363#endif
364 }
365
366 /* transform transparency to alpha */
367 if ( png_get_valid(png, info, PNG_INFO_tRNS ) )
368 png_set_tRNS_to_alpha( png );
369
370 if ( bitdepth == 16 )
371 png_set_strip_16( png );
372
373 if ( bitdepth < 8 )
374 png_set_packing( png );
375
376 /* convert grayscale to RGB */
377 if ( color_type == PNG_COLOR_TYPE_GRAY ||
378 color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
379 png_set_gray_to_rgb( png );
380
381 if ( interlace != PNG_INTERLACE_NONE )
382 png_set_interlace_handling( png );
383
384 png_set_filler( png, 0xFF, PNG_FILLER_AFTER );
385
386 /* recheck header after setting EXPAND options */
387 png_read_update_info(png, info );
388 png_get_IHDR( png, info,
389 &imgWidth, &imgHeight,
390 &bitdepth, &color_type, &interlace,
391 NULL, NULL );
392
393 if ( bitdepth != 8 ||
394 !( color_type == PNG_COLOR_TYPE_RGB ||
395 color_type == PNG_COLOR_TYPE_RGB_ALPHA ) )
396 {
397 error = FT_THROW( Invalid_File_Format );
398 goto DestroyExit;
399 }
400
401 if ( metrics_only )
402 goto DestroyExit;
403
404 switch ( color_type )
405 {
406 default:
407 /* Shouldn't happen, but fall through. */
408
410 png_set_read_user_transform_fn( png, premultiply_data );
411 break;
412
414 /* Humm, this smells. Carry on though. */
415 png_set_read_user_transform_fn( png, convert_bytes_to_data );
416 break;
417 }
418
419 if ( populate_map_and_metrics )
420 {
421 /* this doesn't overflow: 0x7FFF * 0x7FFF * 4 < 2^32 */
422 FT_ULong size = map->rows * (FT_ULong)map->pitch;
423
424
426 if ( error )
427 goto DestroyExit;
428 }
429
430 if ( FT_NEW_ARRAY( rows, imgHeight ) )
431 {
432 error = FT_THROW( Out_Of_Memory );
433 goto DestroyExit;
434 }
435
436 for ( i = 0; i < (FT_Int)imgHeight; i++ )
437 rows[i] = map->buffer + ( y_offset + i ) * map->pitch + x_offset * 4;
438
439 png_read_image( png, rows );
440
441 FT_FREE( rows );
442
443 png_read_end( png, info );
444
445 DestroyExit:
446 png_destroy_read_struct( &png, &info, NULL );
448
449 Exit:
450 return error;
451 }
452
453#else /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */
454
455 /* ANSI C doesn't like empty source files */
456 typedef int _pngshim_dummy;
457
458#endif /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */
459
460
461/* END */
Definition: _map.h:48
#define FT_LOCAL_DEF(x)
#define NULL
Definition: types.h:112
#define __attribute__(x)
Definition: wpp_private.h:207
unsigned char
Definition: typeof.h:29
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
return FT_Err_Ok
Definition: ftbbox.c:526
#define FT_THROW(e)
Definition: ftdebug.h:243
@ FT_PIXEL_MODE_BGRA
Definition: ftimage.h:189
#define FT_NEW_ARRAY(ptr, count)
Definition: ftmemory.h:341
#define FT_FREE(ptr)
Definition: ftmemory.h:337
ft_glyphslot_alloc_bitmap(FT_GlyphSlot slot, FT_ULong size)
Definition: ftobjs.c:514
#define ft_memcpy
Definition: ftstdlib.h:82
#define ft_longjmp
Definition: ftstdlib.h:162
#define ft_setjmp(b)
Definition: ftstdlib.h:163
#define FT_FRAME_ENTER(size)
Definition: ftstream.h:548
FT_Stream_Close(FT_Stream stream)
Definition: ftstream.c:48
#define FT_FRAME_EXIT()
Definition: ftstream.h:553
FT_Stream_OpenMemory(FT_Stream stream, const FT_Byte *base, FT_ULong size)
Definition: ftstream.c:34
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:64
struct FT_StreamRec_ * FT_Stream
Definition: ftsystem.h:198
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:108
unsigned long FT_ULong
Definition: fttypes.h:253
unsigned char FT_Byte
Definition: fttypes.h:154
int FT_Error
Definition: fttypes.h:299
unsigned short FT_UShort
Definition: fttypes.h:209
unsigned int FT_UInt
Definition: fttypes.h:231
signed int FT_Int
Definition: fttypes.h:220
GLclampf green
Definition: gl.h:1740
GLclampf GLclampf GLclampf alpha
Definition: gl.h:1740
GLdouble s
Definition: gl.h:2039
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLclampf GLclampf blue
Definition: gl.h:1740
GLsizeiptr size
Definition: glext.h:5919
GLuint color
Definition: glext.h:6243
GLsizei GLenum const GLvoid GLuint GLsizei GLfloat * metrics
Definition: glext.h:11745
GLint limit
Definition: glext.h:10326
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLfloat GLfloat p
Definition: glext.h:8902
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define e
Definition: ke_i.h:82
#define a
Definition: ke_i.h:78
#define red
Definition: linetest.c:67
struct S1 s1
#define error(str)
Definition: mkdosfs.c:1605
#define PNG_COLOR_TYPE_RGB
Definition: image.c:5165
#define PNG_COLOR_TYPE_RGB_ALPHA
Definition: image.c:5168
#define PNG_COLOR_TYPE_GRAY_ALPHA
Definition: image.c:5167
#define PNG_COLOR_TYPE_GRAY
Definition: image.c:5164
#define PNG_COLOR_TYPE_PALETTE
Definition: image.c:5166
static char memory[1024 *256]
Definition: process.c:122
png_voidp PNGAPI png_get_io_ptr(png_const_structrp png_ptr)
Definition: png.c:686
png_uint_32
Definition: png.h:1936
#define png_jmpbuf(png_ptr)
Definition: png.h:949
#define PNG_FILLER_AFTER
Definition: png.h:1246
#define PNG_INFO_tRNS
Definition: png.h:733
#define PNG_LIBPNG_VER_STRING
Definition: png.h:281
#define PNG_INTERLACE_NONE
Definition: png.h:684
png_byte * png_bytep
Definition: pngconf.h:579
size_t png_size_t
Definition: pngconf.h:523
const char * png_const_charp
Definition: pngconf.h:590
int _pngshim_dummy
Definition: pngshim.c:456
#define FT_UNUSED(arg)
static calc_node_t temp
Definition: rpn_ieee.c:38
static void Exit(void)
Definition: sock.c:1330
Definition: vfat.h:185
size_t rowbytes
Definition: png.h:754
Definition: parse.h:23
static const WCHAR * error_msg[8]
Definition: odbccp32.c:62