ReactOS 0.4.15-dev-7907-g95bf896
pngshim.c
Go to the documentation of this file.
1/***************************************************************************/
2/* */
3/* pngshim.c */
4/* */
5/* PNG Bitmap glyph support. */
6/* */
7/* Copyright 2013-2018 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
20#include <ft2build.h>
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
25
26
27#if defined( TT_CONFIG_OPTION_EMBEDDED_BITMAPS ) && \
28 defined( FT_CONFIG_OPTION_USE_PNG )
29
30 /* We always include <setjmp.h>, so make libpng shut up! */
31#define PNG_SKIP_SETJMP_CHECK 1
32#include <png.h>
33#include "pngshim.h"
34
35#include "sferrors.h"
36
37
38 /* This code is freely based on cairo-png.c. There's so many ways */
39 /* to call libpng, and the way cairo does it is defacto standard. */
40
41 static unsigned int
42 multiply_alpha( unsigned int alpha,
43 unsigned int color )
44 {
45 unsigned int temp = alpha * color + 0x80;
46
47
48 return ( temp + ( temp >> 8 ) ) >> 8;
49 }
50
51
52 /* Premultiplies data and converts RGBA bytes => BGRA. */
53 static void
54 premultiply_data( png_structp png,
55 png_row_infop row_info,
57 {
58 unsigned int i = 0, limit;
59
60 /* The `vector_size' attribute was introduced in gcc 3.1, which */
61 /* predates clang; the `__BYTE_ORDER__' preprocessor symbol was */
62 /* introduced in gcc 4.6 and clang 3.2, respectively. */
63 /* `__builtin_shuffle' for gcc was introduced in gcc 4.7.0. */
64#if ( ( defined( __GNUC__ ) && \
65 ( ( __GNUC__ >= 5 ) || \
66 ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 7 ) ) ) ) || \
67 ( defined( __clang__ ) && \
68 ( ( __clang_major__ >= 4 ) || \
69 ( ( __clang_major__ == 3 ) && ( __clang_minor__ >= 2 ) ) ) ) ) && \
70 defined( __OPTIMIZE__ ) && \
71 __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
72
73#ifdef __clang__
74 /* the clang documentation doesn't cover the two-argument case of */
75 /* `__builtin_shufflevector'; however, it is is implemented since */
76 /* version 2.8 */
77#define vector_shuffle __builtin_shufflevector
78#else
79#define vector_shuffle __builtin_shuffle
80#endif
81
82 typedef unsigned short v82 __attribute__(( vector_size( 16 ) ));
83
84
85 if ( row_info->rowbytes > 15 )
86 {
87 /* process blocks of 16 bytes in one rush, which gives a nice speed-up */
88 limit = row_info->rowbytes - 16 + 1;
89 for ( ; i < limit; i += 16 )
90 {
91 unsigned char* base = &data[i];
92
93 v82 s, s0, s1, a;
94
95 /* clang <= 3.9 can't apply scalar values to vectors */
96 /* (or rather, it needs a different syntax) */
97 v82 n0x80 = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
98 v82 n0xFF = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
99 v82 n8 = { 8, 8, 8, 8, 8, 8, 8, 8 };
100
101 v82 ma = { 1, 1, 3, 3, 5, 5, 7, 7 };
102 v82 o1 = { 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF };
103 v82 m0 = { 1, 0, 3, 2, 5, 4, 7, 6 };
104
105
106 ft_memcpy( &s, base, 16 ); /* RGBA RGBA RGBA RGBA */
107 s0 = s & n0xFF; /* R B R B R B R B */
108 s1 = s >> n8; /* G A G A G A G A */
109
110 a = vector_shuffle( s1, ma ); /* A A A A A A A A */
111 s1 |= o1; /* G 1 G 1 G 1 G 1 */
112 s0 = vector_shuffle( s0, m0 ); /* B R B R B R B R */
113
114 s0 *= a;
115 s1 *= a;
116 s0 += n0x80;
117 s1 += n0x80;
118 s0 = ( s0 + ( s0 >> n8 ) ) >> n8;
119 s1 = ( s1 + ( s1 >> n8 ) ) >> n8;
120
121 s = s0 | ( s1 << n8 );
122 ft_memcpy( base, &s, 16 );
123 }
124 }
125#endif /* use `vector_size' */
126
127 FT_UNUSED( png );
128
129 limit = row_info->rowbytes;
130 for ( ; i < limit; i += 4 )
131 {
132 unsigned char* base = &data[i];
133 unsigned int alpha = base[3];
134
135
136 if ( alpha == 0 )
137 base[0] = base[1] = base[2] = base[3] = 0;
138
139 else
140 {
141 unsigned int red = base[0];
142 unsigned int green = base[1];
143 unsigned int blue = base[2];
144
145
146 if ( alpha != 0xFF )
147 {
148 red = multiply_alpha( alpha, red );
149 green = multiply_alpha( alpha, green );
150 blue = multiply_alpha( alpha, blue );
151 }
152
153 base[0] = (unsigned char)blue;
154 base[1] = (unsigned char)green;
155 base[2] = (unsigned char)red;
156 base[3] = (unsigned char)alpha;
157 }
158 }
159 }
160
161
162 /* Converts RGBx bytes to BGRA. */
163 static void
164 convert_bytes_to_data( png_structp png,
165 png_row_infop row_info,
167 {
168 unsigned int i;
169
170 FT_UNUSED( png );
171
172
173 for ( i = 0; i < row_info->rowbytes; i += 4 )
174 {
175 unsigned char* base = &data[i];
176 unsigned int red = base[0];
177 unsigned int green = base[1];
178 unsigned int blue = base[2];
179
180
181 base[0] = (unsigned char)blue;
182 base[1] = (unsigned char)green;
183 base[2] = (unsigned char)red;
184 base[3] = 0xFF;
185 }
186 }
187
188
189 /* Use error callback to avoid png writing to stderr. */
190 static void
191 error_callback( png_structp png,
193 {
194 FT_Error* error = (FT_Error*)png_get_error_ptr( png );
195
197
198
199 *error = FT_THROW( Out_Of_Memory );
200#ifdef PNG_SETJMP_SUPPORTED
201 ft_longjmp( png_jmpbuf( png ), 1 );
202#endif
203 /* if we get here, then we have no choice but to abort ... */
204 }
205
206
207 /* Use warning callback to avoid png writing to stderr. */
208 static void
209 warning_callback( png_structp png,
211 {
212 FT_UNUSED( png );
214
215 /* Just ignore warnings. */
216 }
217
218
219 static void
220 read_data_from_FT_Stream( png_structp png,
223 {
225 png_voidp p = png_get_io_ptr( png );
227
228
229 if ( FT_FRAME_ENTER( length ) )
230 {
231 FT_Error* e = (FT_Error*)png_get_error_ptr( png );
232
233
234 *e = FT_THROW( Invalid_Stream_Read );
235 png_error( png, NULL );
236
237 return;
238 }
239
240 ft_memcpy( data, stream->cursor, length );
241
243 }
244
245
247 Load_SBit_Png( FT_GlyphSlot slot,
248 FT_Int x_offset,
249 FT_Int y_offset,
250 FT_Int pix_bits,
253 FT_Byte* data,
254 FT_UInt png_len,
255 FT_Bool populate_map_and_metrics,
256 FT_Bool metrics_only )
257 {
258 FT_Bitmap *map = &slot->bitmap;
261
262 png_structp png;
264 png_uint_32 imgWidth, imgHeight;
265
266 int bitdepth, color_type, interlace;
267 FT_Int i;
268 png_byte* *rows = NULL; /* pacify compiler */
269
270
271 if ( x_offset < 0 ||
272 y_offset < 0 )
273 {
274 error = FT_THROW( Invalid_Argument );
275 goto Exit;
276 }
277
278 if ( !populate_map_and_metrics &&
279 ( (FT_UInt)x_offset + metrics->width > map->width ||
280 (FT_UInt)y_offset + metrics->height > map->rows ||
281 pix_bits != 32 ||
282 map->pixel_mode != FT_PIXEL_MODE_BGRA ) )
283 {
284 error = FT_THROW( Invalid_Argument );
285 goto Exit;
286 }
287
288 FT_Stream_OpenMemory( &stream, data, png_len );
289
290 png = png_create_read_struct( PNG_LIBPNG_VER_STRING,
291 &error,
292 error_callback,
293 warning_callback );
294 if ( !png )
295 {
296 error = FT_THROW( Out_Of_Memory );
297 goto Exit;
298 }
299
300 info = png_create_info_struct( png );
301 if ( !info )
302 {
303 error = FT_THROW( Out_Of_Memory );
304 png_destroy_read_struct( &png, NULL, NULL );
305 goto Exit;
306 }
307
308 if ( ft_setjmp( png_jmpbuf( png ) ) )
309 {
310 error = FT_THROW( Invalid_File_Format );
311 goto DestroyExit;
312 }
313
314 png_set_read_fn( png, &stream, read_data_from_FT_Stream );
315
316 png_read_info( png, info );
317 png_get_IHDR( png, info,
318 &imgWidth, &imgHeight,
319 &bitdepth, &color_type, &interlace,
320 NULL, NULL );
321
322 if ( error ||
323 ( !populate_map_and_metrics &&
324 ( (FT_Int)imgWidth != metrics->width ||
325 (FT_Int)imgHeight != metrics->height ) ) )
326 goto DestroyExit;
327
328 if ( populate_map_and_metrics )
329 {
330 metrics->width = (FT_UShort)imgWidth;
331 metrics->height = (FT_UShort)imgHeight;
332
333 map->width = metrics->width;
334 map->rows = metrics->height;
335 map->pixel_mode = FT_PIXEL_MODE_BGRA;
336 map->pitch = (int)( map->width * 4 );
337 map->num_grays = 256;
338
339 /* reject too large bitmaps similarly to the rasterizer */
340 if ( map->rows > 0x7FFF || map->width > 0x7FFF )
341 {
342 error = FT_THROW( Array_Too_Large );
343 goto DestroyExit;
344 }
345 }
346
347 /* convert palette/gray image to rgb */
348 if ( color_type == PNG_COLOR_TYPE_PALETTE )
349 png_set_palette_to_rgb( png );
350
351 /* expand gray bit depth if needed */
352 if ( color_type == PNG_COLOR_TYPE_GRAY )
353 {
354#if PNG_LIBPNG_VER >= 10209
355 png_set_expand_gray_1_2_4_to_8( png );
356#else
357 png_set_gray_1_2_4_to_8( png );
358#endif
359 }
360
361 /* transform transparency to alpha */
362 if ( png_get_valid(png, info, PNG_INFO_tRNS ) )
363 png_set_tRNS_to_alpha( png );
364
365 if ( bitdepth == 16 )
366 png_set_strip_16( png );
367
368 if ( bitdepth < 8 )
369 png_set_packing( png );
370
371 /* convert grayscale to RGB */
372 if ( color_type == PNG_COLOR_TYPE_GRAY ||
373 color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
374 png_set_gray_to_rgb( png );
375
376 if ( interlace != PNG_INTERLACE_NONE )
377 png_set_interlace_handling( png );
378
379 png_set_filler( png, 0xFF, PNG_FILLER_AFTER );
380
381 /* recheck header after setting EXPAND options */
382 png_read_update_info(png, info );
383 png_get_IHDR( png, info,
384 &imgWidth, &imgHeight,
385 &bitdepth, &color_type, &interlace,
386 NULL, NULL );
387
388 if ( bitdepth != 8 ||
389 !( color_type == PNG_COLOR_TYPE_RGB ||
390 color_type == PNG_COLOR_TYPE_RGB_ALPHA ) )
391 {
392 error = FT_THROW( Invalid_File_Format );
393 goto DestroyExit;
394 }
395
396 if ( metrics_only )
397 goto DestroyExit;
398
399 switch ( color_type )
400 {
401 default:
402 /* Shouldn't happen, but fall through. */
403
405 png_set_read_user_transform_fn( png, premultiply_data );
406 break;
407
409 /* Humm, this smells. Carry on though. */
410 png_set_read_user_transform_fn( png, convert_bytes_to_data );
411 break;
412 }
413
414 if ( populate_map_and_metrics )
415 {
416 /* this doesn't overflow: 0x7FFF * 0x7FFF * 4 < 2^32 */
417 FT_ULong size = map->rows * (FT_ULong)map->pitch;
418
419
421 if ( error )
422 goto DestroyExit;
423 }
424
425 if ( FT_NEW_ARRAY( rows, imgHeight ) )
426 {
427 error = FT_THROW( Out_Of_Memory );
428 goto DestroyExit;
429 }
430
431 for ( i = 0; i < (FT_Int)imgHeight; i++ )
432 rows[i] = map->buffer + ( y_offset + i ) * map->pitch + x_offset * 4;
433
434 png_read_image( png, rows );
435
436 FT_FREE( rows );
437
438 png_read_end( png, info );
439
440 DestroyExit:
441 png_destroy_read_struct( &png, &info, NULL );
443
444 Exit:
445 return error;
446 }
447
448#else /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */
449
450 /* ANSI C doesn't like empty source files */
451 typedef int _pngshim_dummy;
452
453#endif /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */
454
455
456/* END */
Definition: _map.h:48
#define NULL
Definition: types.h:112
#define __attribute__(x)
Definition: wpp_private.h:207
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
unsigned char
Definition: typeof.h:29
return FT_Err_Ok
Definition: ftbbox.c:511
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:388
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
#define FT_THROW(e)
Definition: ftdebug.h:213
@ FT_PIXEL_MODE_BGRA
Definition: ftimage.h:189
#define FT_NEW_ARRAY(ptr, count)
Definition: ftmemory.h:333
#define FT_FREE(ptr)
Definition: ftmemory.h:329
ft_glyphslot_alloc_bitmap(FT_GlyphSlot slot, FT_ULong size)
Definition: ftobjs.c:478
#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:512
FT_Stream_Close(FT_Stream stream)
Definition: ftstream.c:49
#define FT_FRAME_EXIT()
Definition: ftstream.h:517
FT_Stream_OpenMemory(FT_Stream stream, const FT_Byte *base, FT_ULong size)
Definition: ftstream.c:35
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
struct FT_StreamRec_ * FT_Stream
Definition: ftsystem.h:200
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:300
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:116
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:451
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