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 "core/fxcodec/codec/codec_int.h"
8 #include "core/fxcodec/include/fx_codec.h"
9 #include "core/fxcodec/lgif/fx_gif.h"
10 #include "core/fxge/include/fx_dib.h"
11 struct FXGIF_Context {
12   gif_decompress_struct_p gif_ptr;
13   void* parent_ptr;
14   void* child_ptr;
15 
16   void* (*m_AllocFunc)(unsigned int);
17   void (*m_FreeFunc)(void*);
18 };
19 extern "C" {
gif_alloc_func(unsigned int size)20 static void* gif_alloc_func(unsigned int size) {
21   return FX_Alloc(char, size);
22 }
gif_free_func(void * p)23 static void gif_free_func(void* p) {
24   FX_Free(p);
25 }
26 };
gif_error_data(gif_decompress_struct_p gif_ptr,const FX_CHAR * err_msg)27 static void gif_error_data(gif_decompress_struct_p gif_ptr,
28                            const FX_CHAR* err_msg) {
29   FXSYS_strncpy((char*)gif_ptr->err_ptr, err_msg, GIF_MAX_ERROR_SIZE - 1);
30   longjmp(gif_ptr->jmpbuf, 1);
31 }
gif_ask_buf_for_pal(gif_decompress_struct_p gif_ptr,int32_t pal_size)32 static uint8_t* gif_ask_buf_for_pal(gif_decompress_struct_p gif_ptr,
33                                     int32_t pal_size) {
34   FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr;
35   CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr;
36   return pModule->AskLocalPaletteBufCallback(
37       p->child_ptr, gif_get_frame_num(gif_ptr), pal_size);
38 }
gif_record_current_position(gif_decompress_struct_p gif_ptr,uint32_t * cur_pos_ptr)39 static void gif_record_current_position(gif_decompress_struct_p gif_ptr,
40                                         uint32_t* cur_pos_ptr) {
41   FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr;
42   CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr;
43   pModule->RecordCurrentPositionCallback(p->child_ptr, *cur_pos_ptr);
44 }
gif_read_scanline(gif_decompress_struct_p gif_ptr,int32_t row_num,uint8_t * row_buf)45 static void gif_read_scanline(gif_decompress_struct_p gif_ptr,
46                               int32_t row_num,
47                               uint8_t* row_buf) {
48   FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr;
49   CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr;
50   pModule->ReadScanlineCallback(p->child_ptr, row_num, row_buf);
51 }
gif_get_record_position(gif_decompress_struct_p gif_ptr,uint32_t cur_pos,int32_t left,int32_t top,int32_t width,int32_t height,int32_t pal_num,void * pal_ptr,int32_t delay_time,FX_BOOL user_input,int32_t trans_index,int32_t disposal_method,FX_BOOL interlace)52 static FX_BOOL gif_get_record_position(gif_decompress_struct_p gif_ptr,
53                                        uint32_t cur_pos,
54                                        int32_t left,
55                                        int32_t top,
56                                        int32_t width,
57                                        int32_t height,
58                                        int32_t pal_num,
59                                        void* pal_ptr,
60                                        int32_t delay_time,
61                                        FX_BOOL user_input,
62                                        int32_t trans_index,
63                                        int32_t disposal_method,
64                                        FX_BOOL interlace) {
65   FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr;
66   CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr;
67   return pModule->InputRecordPositionBufCallback(
68       p->child_ptr, cur_pos, FX_RECT(left, top, left + width, top + height),
69       pal_num, pal_ptr, delay_time, user_input, trans_index, disposal_method,
70       interlace);
71 }
72 
Start(void * pModule)73 FXGIF_Context* CCodec_GifModule::Start(void* pModule) {
74   FXGIF_Context* p = FX_Alloc(FXGIF_Context, 1);
75   if (!p)
76     return nullptr;
77 
78   FXSYS_memset(p, 0, sizeof(FXGIF_Context));
79   p->m_AllocFunc = gif_alloc_func;
80   p->m_FreeFunc = gif_free_func;
81   p->gif_ptr = nullptr;
82   p->parent_ptr = (void*)this;
83   p->child_ptr = pModule;
84   p->gif_ptr = gif_create_decompress();
85   if (!p->gif_ptr) {
86     FX_Free(p);
87     return nullptr;
88   }
89   p->gif_ptr->context_ptr = (void*)p;
90   p->gif_ptr->err_ptr = m_szLastError;
91   p->gif_ptr->gif_error_fn = gif_error_data;
92   p->gif_ptr->gif_ask_buf_for_pal_fn = gif_ask_buf_for_pal;
93   p->gif_ptr->gif_record_current_position_fn = gif_record_current_position;
94   p->gif_ptr->gif_get_row_fn = gif_read_scanline;
95   p->gif_ptr->gif_get_record_position_fn = gif_get_record_position;
96   return p;
97 }
98 
Finish(FXGIF_Context * ctx)99 void CCodec_GifModule::Finish(FXGIF_Context* ctx) {
100   if (ctx) {
101     gif_destroy_decompress(&ctx->gif_ptr);
102     ctx->m_FreeFunc(ctx);
103   }
104 }
105 
ReadHeader(FXGIF_Context * ctx,int * width,int * height,int * pal_num,void ** pal_pp,int * bg_index,CFX_DIBAttribute * pAttribute)106 int32_t CCodec_GifModule::ReadHeader(FXGIF_Context* ctx,
107                                      int* width,
108                                      int* height,
109                                      int* pal_num,
110                                      void** pal_pp,
111                                      int* bg_index,
112                                      CFX_DIBAttribute* pAttribute) {
113   if (setjmp(ctx->gif_ptr->jmpbuf))
114     return 0;
115 
116   int32_t ret = gif_read_header(ctx->gif_ptr);
117   if (ret != 1)
118     return ret;
119 
120   *width = ctx->gif_ptr->width;
121   *height = ctx->gif_ptr->height;
122   *pal_num = ctx->gif_ptr->global_pal_num;
123   *pal_pp = ctx->gif_ptr->global_pal_ptr;
124   *bg_index = ctx->gif_ptr->bc_index;
125   return 1;
126 }
127 
LoadFrameInfo(FXGIF_Context * ctx,int * frame_num)128 int32_t CCodec_GifModule::LoadFrameInfo(FXGIF_Context* ctx, int* frame_num) {
129   if (setjmp(ctx->gif_ptr->jmpbuf))
130     return 0;
131 
132   int32_t ret = gif_get_frame(ctx->gif_ptr);
133   if (ret != 1)
134     return ret;
135 
136   *frame_num = gif_get_frame_num(ctx->gif_ptr);
137   return 1;
138 }
139 
LoadFrame(FXGIF_Context * ctx,int frame_num,CFX_DIBAttribute * pAttribute)140 int32_t CCodec_GifModule::LoadFrame(FXGIF_Context* ctx,
141                                     int frame_num,
142                                     CFX_DIBAttribute* pAttribute) {
143   if (setjmp(ctx->gif_ptr->jmpbuf))
144     return 0;
145 
146   int32_t ret = gif_load_frame(ctx->gif_ptr, frame_num);
147   if (ret == 1) {
148     if (pAttribute) {
149       pAttribute->m_nGifLeft =
150           ctx->gif_ptr->img_ptr_arr_ptr->GetAt(frame_num)->image_info_ptr->left;
151       pAttribute->m_nGifTop =
152           ctx->gif_ptr->img_ptr_arr_ptr->GetAt(frame_num)->image_info_ptr->top;
153       pAttribute->m_fAspectRatio = ctx->gif_ptr->pixel_aspect;
154       if (ctx->gif_ptr->cmt_data_ptr) {
155         const uint8_t* buf =
156             (const uint8_t*)ctx->gif_ptr->cmt_data_ptr->GetBuffer(0);
157         uint32_t len = ctx->gif_ptr->cmt_data_ptr->GetLength();
158         if (len > 21) {
159           uint8_t size = *buf++;
160           if (size) {
161             pAttribute->m_strAuthor = CFX_ByteString(buf, size);
162           } else {
163             pAttribute->m_strAuthor.clear();
164           }
165           buf += size;
166           size = *buf++;
167           if (size == 20) {
168             FXSYS_memcpy(pAttribute->m_strTime, buf, size);
169           }
170         }
171       }
172     }
173   }
174   return ret;
175 }
176 
GetAvailInput(FXGIF_Context * ctx,uint8_t ** avail_buf_ptr)177 uint32_t CCodec_GifModule::GetAvailInput(FXGIF_Context* ctx,
178                                          uint8_t** avail_buf_ptr) {
179   return gif_get_avail_input(ctx->gif_ptr, avail_buf_ptr);
180 }
181 
Input(FXGIF_Context * ctx,const uint8_t * src_buf,uint32_t src_size)182 void CCodec_GifModule::Input(FXGIF_Context* ctx,
183                              const uint8_t* src_buf,
184                              uint32_t src_size) {
185   gif_input_buffer(ctx->gif_ptr, (uint8_t*)src_buf, src_size);
186 }
187