• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include <algorithm>
8 
9 #include "core/include/fxcodec/fx_codec.h"
10 #include "core/include/fxge/fx_dib.h"
11 #include "codec_int.h"
12 
13 extern "C" {
14 #undef FAR
15 #include "third_party/lpng_v163/png.h"
16 }
17 
_png_error_data(png_structp png_ptr,png_const_charp error_msg)18 static void _png_error_data(png_structp png_ptr, png_const_charp error_msg) {
19   if (png_get_error_ptr(png_ptr)) {
20     FXSYS_strncpy((char*)png_get_error_ptr(png_ptr), error_msg,
21                   PNG_ERROR_SIZE - 1);
22   }
23   longjmp(png_jmpbuf(png_ptr), 1);
24 }
_png_warning_data(png_structp png_ptr,png_const_charp error_msg)25 static void _png_warning_data(png_structp png_ptr, png_const_charp error_msg) {}
_png_load_bmp_attribute(png_structp png_ptr,png_infop info_ptr,CFX_DIBAttribute * pAttribute)26 static void _png_load_bmp_attribute(png_structp png_ptr,
27                                     png_infop info_ptr,
28                                     CFX_DIBAttribute* pAttribute) {
29   if (pAttribute) {
30 #if defined(PNG_pHYs_SUPPORTED)
31     pAttribute->m_nXDPI = png_get_x_pixels_per_meter(png_ptr, info_ptr);
32     pAttribute->m_nYDPI = png_get_y_pixels_per_meter(png_ptr, info_ptr);
33     png_uint_32 res_x, res_y;
34     int unit_type;
35     png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type);
36     switch (unit_type) {
37       case PNG_RESOLUTION_METER:
38         pAttribute->m_wDPIUnit = FXCODEC_RESUNIT_METER;
39         break;
40       default:
41         pAttribute->m_wDPIUnit = FXCODEC_RESUNIT_NONE;
42     }
43 #endif
44 #if defined(PNG_iCCP_SUPPORTED)
45     png_charp icc_name;
46     png_bytep icc_profile;
47     png_uint_32 icc_proflen;
48     int compress_type;
49     png_get_iCCP(png_ptr, info_ptr, &icc_name, &compress_type, &icc_profile,
50                  &icc_proflen);
51 #endif
52     int bTime = 0;
53 #if defined(PNG_tIME_SUPPORTED)
54     png_timep t = NULL;
55     png_get_tIME(png_ptr, info_ptr, &t);
56     if (t) {
57       FXSYS_memset(pAttribute->m_strTime, 0, sizeof(pAttribute->m_strTime));
58       FXSYS_snprintf((FX_CHAR*)pAttribute->m_strTime,
59                      sizeof(pAttribute->m_strTime), "%4d:%2d:%2d %2d:%2d:%2d",
60                      t->year, t->month, t->day, t->hour, t->minute, t->second);
61       pAttribute->m_strTime[sizeof(pAttribute->m_strTime) - 1] = 0;
62       bTime = 1;
63     }
64 #endif
65 #if defined(PNG_TEXT_SUPPORTED)
66     int i;
67     FX_STRSIZE len;
68     const FX_CHAR* buf;
69     int num_text;
70     png_textp text = NULL;
71     png_get_text(png_ptr, info_ptr, &text, &num_text);
72     for (i = 0; i < num_text; i++) {
73       len = FXSYS_strlen(text[i].key);
74       buf = "Time";
75       if (!FXSYS_memcmp(buf, text[i].key, std::min(len, FXSYS_strlen(buf)))) {
76         if (!bTime) {
77           FXSYS_memset(pAttribute->m_strTime, 0, sizeof(pAttribute->m_strTime));
78           FXSYS_memcpy(
79               pAttribute->m_strTime, text[i].text,
80               std::min(sizeof(pAttribute->m_strTime) - 1, text[i].text_length));
81         }
82       } else {
83         buf = "Author";
84         if (!FXSYS_memcmp(buf, text[i].key, std::min(len, FXSYS_strlen(buf)))) {
85           pAttribute->m_strAuthor.Empty();
86           pAttribute->m_strAuthor.Load((uint8_t*)text[i].text,
87                                        (FX_STRSIZE)text[i].text_length);
88         }
89       }
90     }
91 #endif
92   }
93 }
94 struct FXPNG_Context {
95   png_structp png_ptr;
96   png_infop info_ptr;
97   void* parent_ptr;
98   void* child_ptr;
99 
100   void* (*m_AllocFunc)(unsigned int);
101   void (*m_FreeFunc)(void*);
102 };
103 extern "C" {
_png_alloc_func(unsigned int size)104 static void* _png_alloc_func(unsigned int size) {
105   return FX_Alloc(char, size);
106 }
_png_free_func(void * p)107 static void _png_free_func(void* p) {
108   if (p != NULL) {
109     FX_Free(p);
110   }
111 }
112 };
_png_get_header_func(png_structp png_ptr,png_infop info_ptr)113 static void _png_get_header_func(png_structp png_ptr, png_infop info_ptr) {
114   FXPNG_Context* p = (FXPNG_Context*)png_get_progressive_ptr(png_ptr);
115   if (p == NULL) {
116     return;
117   }
118   CCodec_PngModule* pModule = (CCodec_PngModule*)p->parent_ptr;
119   if (pModule == NULL) {
120     return;
121   }
122   png_uint_32 width = 0, height = 0;
123   int bpc = 0, color_type = 0, color_type1 = 0, pass = 0;
124   double gamma = 1.0;
125   png_get_IHDR(png_ptr, info_ptr, &width, &height, &bpc, &color_type, NULL,
126                NULL, NULL);
127   color_type1 = color_type;
128   if (bpc > 8) {
129     png_set_strip_16(png_ptr);
130   } else if (bpc < 8) {
131     png_set_expand_gray_1_2_4_to_8(png_ptr);
132   }
133   bpc = 8;
134   if (color_type == PNG_COLOR_TYPE_PALETTE) {
135     png_set_palette_to_rgb(png_ptr);
136   }
137   pass = png_set_interlace_handling(png_ptr);
138   if (!pModule->ReadHeaderCallback(p->child_ptr, width, height, bpc, pass,
139                                    &color_type, &gamma)) {
140     png_error(p->png_ptr, "Read Header Callback Error");
141   }
142   int intent;
143   if (png_get_sRGB(png_ptr, info_ptr, &intent)) {
144     png_set_gamma(png_ptr, gamma, 0.45455);
145   } else {
146     double image_gamma;
147     if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) {
148       png_set_gamma(png_ptr, gamma, image_gamma);
149     } else {
150       png_set_gamma(png_ptr, gamma, 0.45455);
151     }
152   }
153   switch (color_type) {
154     case PNG_COLOR_TYPE_GRAY:
155     case PNG_COLOR_TYPE_GRAY_ALPHA: {
156       if (color_type1 & PNG_COLOR_MASK_COLOR) {
157         png_set_rgb_to_gray(png_ptr, 1, 0.299, 0.587);
158       }
159     } break;
160     case PNG_COLOR_TYPE_PALETTE:
161       if (color_type1 != PNG_COLOR_TYPE_PALETTE) {
162         png_error(p->png_ptr, "Not Support Output Palette Now");
163       }
164     case PNG_COLOR_TYPE_RGB:
165     case PNG_COLOR_TYPE_RGB_ALPHA:
166       if (!(color_type1 & PNG_COLOR_MASK_COLOR)) {
167         png_set_gray_to_rgb(png_ptr);
168       }
169       png_set_bgr(png_ptr);
170       break;
171   }
172   if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
173     png_set_strip_alpha(png_ptr);
174   }
175   if (color_type & PNG_COLOR_MASK_ALPHA &&
176       !(color_type1 & PNG_COLOR_MASK_ALPHA)) {
177     png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
178   }
179   png_read_update_info(png_ptr, info_ptr);
180 }
_png_get_end_func(png_structp png_ptr,png_infop info_ptr)181 static void _png_get_end_func(png_structp png_ptr, png_infop info_ptr) {}
_png_get_row_func(png_structp png_ptr,png_bytep new_row,png_uint_32 row_num,int pass)182 static void _png_get_row_func(png_structp png_ptr,
183                               png_bytep new_row,
184                               png_uint_32 row_num,
185                               int pass) {
186   FXPNG_Context* p = (FXPNG_Context*)png_get_progressive_ptr(png_ptr);
187   if (p == NULL) {
188     return;
189   }
190   CCodec_PngModule* pModule = (CCodec_PngModule*)p->parent_ptr;
191   uint8_t* src_buf = NULL;
192   if (!pModule->AskScanlineBufCallback(p->child_ptr, row_num, src_buf)) {
193     png_error(png_ptr, "Ask Scanline buffer Callback Error");
194   }
195   if (src_buf != NULL) {
196     png_progressive_combine_row(png_ptr, src_buf, new_row);
197   }
198   pModule->FillScanlineBufCompletedCallback(p->child_ptr, pass, row_num);
199 }
Start(void * pModule)200 void* CCodec_PngModule::Start(void* pModule) {
201   FXPNG_Context* p = (FXPNG_Context*)FX_Alloc(uint8_t, sizeof(FXPNG_Context));
202   if (p == NULL) {
203     return NULL;
204   }
205   p->m_AllocFunc = _png_alloc_func;
206   p->m_FreeFunc = _png_free_func;
207   p->png_ptr = NULL;
208   p->info_ptr = NULL;
209   p->parent_ptr = (void*)this;
210   p->child_ptr = pModule;
211   p->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
212   if (p->png_ptr == NULL) {
213     FX_Free(p);
214     return NULL;
215   }
216   p->info_ptr = png_create_info_struct(p->png_ptr);
217   if (p->info_ptr == NULL) {
218     png_destroy_read_struct(&(p->png_ptr), (png_infopp)NULL, (png_infopp)NULL);
219     FX_Free(p);
220     return NULL;
221   }
222   if (setjmp(png_jmpbuf(p->png_ptr))) {
223     if (p != NULL) {
224       png_destroy_read_struct(&(p->png_ptr), &(p->info_ptr), (png_infopp)NULL);
225       FX_Free(p);
226     }
227     return NULL;
228   }
229   png_set_progressive_read_fn(p->png_ptr, p, _png_get_header_func,
230                               _png_get_row_func, _png_get_end_func);
231   png_set_error_fn(p->png_ptr, m_szLastError, (png_error_ptr)_png_error_data,
232                    (png_error_ptr)_png_warning_data);
233   return p;
234 }
Finish(void * pContext)235 void CCodec_PngModule::Finish(void* pContext) {
236   FXPNG_Context* p = (FXPNG_Context*)pContext;
237   if (p != NULL) {
238     png_destroy_read_struct(&(p->png_ptr), &(p->info_ptr), (png_infopp)NULL);
239     p->m_FreeFunc(p);
240   }
241 }
Input(void * pContext,const uint8_t * src_buf,FX_DWORD src_size,CFX_DIBAttribute * pAttribute)242 FX_BOOL CCodec_PngModule::Input(void* pContext,
243                                 const uint8_t* src_buf,
244                                 FX_DWORD src_size,
245                                 CFX_DIBAttribute* pAttribute) {
246   FXPNG_Context* p = (FXPNG_Context*)pContext;
247   if (setjmp(png_jmpbuf(p->png_ptr))) {
248     if (pAttribute &&
249         0 == FXSYS_strcmp(m_szLastError, "Read Header Callback Error")) {
250       _png_load_bmp_attribute(p->png_ptr, p->info_ptr, pAttribute);
251     }
252     return FALSE;
253   }
254   png_process_data(p->png_ptr, p->info_ptr, (uint8_t*)src_buf, src_size);
255   return TRUE;
256 }
257