Home | History | Annotate | Download | only in codec
      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