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