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" { 23 static void* gif_alloc_func(unsigned int size) { 24 return FX_Alloc(char, size); 25 } 26 static void gif_free_func(void* p) { 27 FX_Free(p); 28 } 29 }; 30 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 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 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 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 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 80 CCodec_GifModule::CCodec_GifModule() { 81 memset(m_szLastError, 0, sizeof(m_szLastError)); 82 } 83 84 CCodec_GifModule::~CCodec_GifModule() {} 85 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 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 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 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 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 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 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