1a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/***************************************************************************/ 2a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* */ 3a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* pngshim.c */ 4a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* */ 5a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* PNG Bitmap glyph support. */ 6a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* */ 7a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* Copyright 2013 by Google, Inc. */ 8a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* Written by Stuart Gill and Behdad Esfahbod. */ 9a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* */ 10a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* This file is part of the FreeType project, and may only be used, */ 11a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* modified, and distributed under the terms of the FreeType project */ 12a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* this file you indicate that you have read the license and */ 14a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* understand and accept it fully. */ 15a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* */ 16a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/***************************************************************************/ 17a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 18a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 19a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include <ft2build.h> 20a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include FT_INTERNAL_DEBUG_H 21a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include FT_INTERNAL_STREAM_H 22a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include FT_TRUETYPE_TAGS_H 23a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include FT_CONFIG_STANDARD_LIBRARY_H 24a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 25a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 26a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#ifdef FT_CONFIG_OPTION_USE_PNG 27a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 28a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* We always include <stjmp.h>, so make libpng shut up! */ 29a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define PNG_SKIP_SETJMP_CHECK 1 30a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include <png.h> 31a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include "pngshim.h" 32a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 33a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include "sferrors.h" 34a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 35a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 36a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* This code is freely based on cairo-png.c. There's so many ways */ 37a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* to call libpng, and the way cairo does it is defacto standard. */ 38a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 39a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang static int 40a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang multiply_alpha( int alpha, 41a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang int color ) 42a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 43a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang int temp = ( alpha * color ) + 0x80; 44a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 45a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 46a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang return ( temp + ( temp >> 8 ) ) >> 8; 47a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 48a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 49a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 50a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* Premultiplies data and converts RGBA bytes => native endian. */ 51a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang static void 52a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang premultiply_data( png_structp png, 53a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_row_infop row_info, 54a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_bytep data ) 55a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 56a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang unsigned int i; 57a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 58a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_UNUSED( png ); 59a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 60a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 61a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang for ( i = 0; i < row_info->rowbytes; i += 4 ) 62a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 63a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang unsigned char* base = &data[i]; 64a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang unsigned int alpha = base[3]; 65a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 66a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 67a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( alpha == 0 ) 68a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang base[0] = base[1] = base[2] = base[3] = 0; 69a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 70a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang else 71a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 72a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang unsigned int red = base[0]; 73a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang unsigned int green = base[1]; 74a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang unsigned int blue = base[2]; 75a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 76a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 77a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( alpha != 0xFF ) 78a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 79a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang red = multiply_alpha( alpha, red ); 80a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang green = multiply_alpha( alpha, green ); 81a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang blue = multiply_alpha( alpha, blue ); 82a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 83a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 84a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang base[0] = blue; 85a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang base[1] = green; 86a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang base[2] = red; 87a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang base[3] = alpha; 88a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 89a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 90a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 91a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 92a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 93a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* Converts RGBx bytes to BGRA. */ 94a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang static void 95a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang convert_bytes_to_data( png_structp png, 96a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_row_infop row_info, 97a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_bytep data ) 98a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 99a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang unsigned int i; 100a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 101a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_UNUSED( png ); 102a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 103a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 104a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang for ( i = 0; i < row_info->rowbytes; i += 4 ) 105a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 106a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang unsigned char* base = &data[i]; 107a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang unsigned int red = base[0]; 108a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang unsigned int green = base[1]; 109a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang unsigned int blue = base[2]; 110a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 111a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 112a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang base[0] = blue; 113a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang base[1] = green; 114a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang base[2] = red; 115a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang base[3] = 0xFF; 116a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 117a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 118a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 119a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 120a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* Use error callback to avoid png writing to stderr. */ 121a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang static void 122a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang error_callback( png_structp png, 123a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_const_charp error_msg ) 124a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 125a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Error* error = png_get_error_ptr( png ); 126a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 127a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_UNUSED( error_msg ); 128a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 129a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 130a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang *error = FT_THROW( Out_Of_Memory ); 131a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#ifdef PNG_SETJMP_SUPPORTED 132a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang longjmp( png_jmpbuf( png ), 1 ); 133a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#endif 134a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* if we get here, then we have no choice but to abort ... */ 135a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 136a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 137a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 138a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* Use warning callback to avoid png writing to stderr. */ 139a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang static void 140a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang warning_callback( png_structp png, 141a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_const_charp error_msg ) 142a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 143a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_UNUSED( png ); 144a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_UNUSED( error_msg ); 145a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 146a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* Just ignore warnings. */ 147a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 148a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 149a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 150a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang static void 151a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang read_data_from_FT_Stream( png_structp png, 152a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_bytep data, 153a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_size_t length ) 154a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 155a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Error error; 156a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_voidp p = png_get_io_ptr( png ); 157a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Stream stream = (FT_Stream)p; 158a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 159a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 160a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( FT_FRAME_ENTER( length ) ) 161a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 162a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Error* e = png_get_error_ptr( png ); 163a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 164a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 165a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang *e = FT_THROW( Invalid_Stream_Read ); 166a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_error( png, NULL ); 167a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 168a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang return; 169a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 170a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 171a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang memcpy( data, stream->cursor, length ); 172a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 173a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_FRAME_EXIT(); 174a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 175a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 176a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 177a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang static FT_Error 178a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang Load_SBit_Png( FT_Bitmap* map, 179a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Int x_offset, 180a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Int y_offset, 181a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Int pix_bits, 182a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang TT_SBit_Metrics metrics, 183a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Memory memory, 184a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Byte* data, 185a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_UInt png_len ) 186a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 187a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Error error = FT_Err_Ok; 188a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_StreamRec stream; 189a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 190a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_structp png; 191a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_infop info; 192a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_uint_32 imgWidth, imgHeight; 193a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 194a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang int bitdepth, color_type, interlace; 195a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Int i; 196a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_byte* *rows; 197a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 198a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 199a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( x_offset < 0 || x_offset + metrics->width > map->width || 200a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang y_offset < 0 || y_offset + metrics->height > map->rows || 201a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang pix_bits != 32 || map->pixel_mode != FT_PIXEL_MODE_BGRA ) 202a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 203a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang error = FT_THROW( Invalid_Argument ); 204a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang goto Exit; 205a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 206a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 207a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Stream_OpenMemory( &stream, data, png_len ); 208a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 209a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png = png_create_read_struct( PNG_LIBPNG_VER_STRING, 210a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang &error, 211a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang error_callback, 212a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang warning_callback ); 213a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( !png ) 214a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 215a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang error = FT_THROW( Out_Of_Memory ); 216a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang goto Exit; 217a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 218a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 219a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang info = png_create_info_struct( png ); 220a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( !info ) 221a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 222a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang error = FT_THROW( Out_Of_Memory ); 223a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_destroy_read_struct( &png, NULL, NULL ); 224a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang goto Exit; 225a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 226a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 227a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( ft_setjmp( png_jmpbuf( png ) ) ) 228a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 229a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang error = FT_THROW( Invalid_File_Format ); 230a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang goto DestroyExit; 231a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 232a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 233a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_set_read_fn( png, &stream, read_data_from_FT_Stream ); 234a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 235a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_read_info( png, info ); 236a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_get_IHDR( png, info, 237a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang &imgWidth, &imgHeight, 238a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang &bitdepth, &color_type, &interlace, 239a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang NULL, NULL ); 240a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 241a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( error != FT_Err_Ok || 242a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang (FT_Int)imgWidth != metrics->width || 243a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang (FT_Int)imgHeight != metrics->height ) 244a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang goto DestroyExit; 245a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 246a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* convert palette/gray image to rgb */ 247a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( color_type == PNG_COLOR_TYPE_PALETTE ) 248a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_set_palette_to_rgb( png ); 249a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 250a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* expand gray bit depth if needed */ 251a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( color_type == PNG_COLOR_TYPE_GRAY ) 252a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 253a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#if PNG_LIBPNG_VER >= 10209 254a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_set_expand_gray_1_2_4_to_8( png ); 255a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#else 256a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_set_gray_1_2_4_to_8( png ); 257a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#endif 258a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 259a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 260a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* transform transparency to alpha */ 261a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( png_get_valid(png, info, PNG_INFO_tRNS ) ) 262a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_set_tRNS_to_alpha( png ); 263a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 264a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( bitdepth == 16 ) 265a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_set_strip_16( png ); 266a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 267a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( bitdepth < 8 ) 268a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_set_packing( png ); 269a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 270a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* convert grayscale to RGB */ 271a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( color_type == PNG_COLOR_TYPE_GRAY || 272a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) 273a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_set_gray_to_rgb( png ); 274a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 275a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( interlace != PNG_INTERLACE_NONE ) 276a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_set_interlace_handling( png ); 277a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 278a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_set_filler( png, 0xFF, PNG_FILLER_AFTER ); 279a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 280a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* recheck header after setting EXPAND options */ 281a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_read_update_info(png, info ); 282a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_get_IHDR( png, info, 283a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang &imgWidth, &imgHeight, 284a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang &bitdepth, &color_type, &interlace, 285a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang NULL, NULL ); 286a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 287a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( bitdepth != 8 || 288a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang !( color_type == PNG_COLOR_TYPE_RGB || 289a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang color_type == PNG_COLOR_TYPE_RGB_ALPHA ) ) 290a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 291a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang error = FT_THROW( Invalid_File_Format ); 292a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang goto DestroyExit; 293a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 294a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 295a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang switch ( color_type ) 296a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 297a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang default: 298a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* Shouldn't happen, but fall through. */ 299a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 300a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang case PNG_COLOR_TYPE_RGB_ALPHA: 301a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_set_read_user_transform_fn( png, premultiply_data ); 302a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang break; 303a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 304a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang case PNG_COLOR_TYPE_RGB: 305a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* Humm, this smells. Carry on though. */ 306a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_set_read_user_transform_fn( png, convert_bytes_to_data ); 307a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang break; 308a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 309a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 310a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( FT_NEW_ARRAY( rows, imgHeight ) ) 311a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang { 312a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang error = FT_THROW( Out_Of_Memory ); 313a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang goto DestroyExit; 314a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 315a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 316a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang for ( i = 0; i < (FT_Int)imgHeight; i++ ) 317a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang rows[i] = map->buffer + ( y_offset + i ) * map->pitch + x_offset * 4; 318a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 319a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_read_image( png, rows ); 320a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 321a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_FREE( rows ); 322a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 323a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_read_end( png, info ); 324a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 325a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang DestroyExit: 326a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang png_destroy_read_struct( &png, &info, NULL ); 327a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Stream_Close( &stream ); 328a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 329a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang Exit: 330a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang return error; 331a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang } 332a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 333a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#endif /* FT_CONFIG_OPTION_USE_PNG */ 334a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 335a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 336a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* END */ 337