Cleanup of CGifDecompressor part 1

This CL changes the tag_gif_decompress_struct into CGifDecompressor. It cleans
up a bunch of unnecessary function pointers and starts cleaning up the members
of the new class.

Change-Id: Id49cd8f5377dc8daaa15118551dadad4ddde7931
Reviewed-on: https://pdfium-review.googlesource.com/5170
Reviewed-by: dsinclair <dsinclair@chromium.org>
Commit-Queue: Nicolás Peña <npm@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index 680416c..1abcc8d 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -729,6 +729,8 @@
       "core/fxcodec/codec/fx_codec_progress.cpp",
       "core/fxcodec/lbmp/fx_bmp.cpp",
       "core/fxcodec/lbmp/fx_bmp.h",
+      "core/fxcodec/lgif/cgifdecompressor.cpp",
+      "core/fxcodec/lgif/cgifdecompressor.h",
       "core/fxcodec/lgif/fx_gif.cpp",
       "core/fxcodec/lgif/fx_gif.h",
     ]
diff --git a/core/fxcodec/codec/ccodec_gifmodule.cpp b/core/fxcodec/codec/ccodec_gifmodule.cpp
index b538805..33d74a9 100644
--- a/core/fxcodec/codec/ccodec_gifmodule.cpp
+++ b/core/fxcodec/codec/ccodec_gifmodule.cpp
@@ -8,74 +8,10 @@
 
 #include "core/fxcodec/codec/codec_int.h"
 #include "core/fxcodec/fx_codec.h"
+#include "core/fxcodec/lgif/cgifdecompressor.h"
 #include "core/fxcodec/lgif/fx_gif.h"
 #include "core/fxge/fx_dib.h"
-
-struct FXGIF_Context {
-  gif_decompress_struct_p gif_ptr;
-  void* parent_ptr;
-
-  void* (*m_AllocFunc)(unsigned int);
-  void (*m_FreeFunc)(void*);
-};
-
-extern "C" {
-static void* gif_alloc_func(unsigned int size) {
-  return FX_Alloc(char, size);
-}
-static void gif_free_func(void* p) {
-  FX_Free(p);
-}
-};
-
-static void gif_error_data(gif_decompress_struct_p gif_ptr,
-                           const char* err_msg) {
-  strncpy((char*)gif_ptr->err_ptr, err_msg, GIF_MAX_ERROR_SIZE - 1);
-  longjmp(gif_ptr->jmpbuf, 1);
-}
-
-static uint8_t* gif_ask_buf_for_pal(gif_decompress_struct_p gif_ptr,
-                                    int32_t pal_size) {
-  FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr;
-  CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr;
-  return pModule->GetDelegate()->GifAskLocalPaletteBuf(
-      gif_get_frame_num(gif_ptr), pal_size);
-}
-
-static void gif_record_current_position(gif_decompress_struct_p gif_ptr,
-                                        uint32_t* cur_pos_ptr) {
-  FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr;
-  CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr;
-  pModule->GetDelegate()->GifRecordCurrentPosition(*cur_pos_ptr);
-}
-
-static void gif_read_scanline(gif_decompress_struct_p gif_ptr,
-                              int32_t row_num,
-                              uint8_t* row_buf) {
-  FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr;
-  CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr;
-  pModule->GetDelegate()->GifReadScanline(row_num, row_buf);
-}
-
-static bool 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) {
-  FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr;
-  CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr;
-  return pModule->GetDelegate()->GifInputRecordPositionBuf(
-      cur_pos, FX_RECT(left, top, left + width, top + height), pal_num, pal_ptr,
-      delay_time, user_input, trans_index, disposal_method, interlace);
-}
+#include "third_party/base/ptr_util.h"
 
 CCodec_GifModule::CCodec_GifModule() {
   memset(m_szLastError, 0, sizeof(m_szLastError));
@@ -89,29 +25,15 @@
     return nullptr;
 
   memset(p, 0, sizeof(FXGIF_Context));
-  p->m_AllocFunc = gif_alloc_func;
-  p->m_FreeFunc = gif_free_func;
-  p->gif_ptr = nullptr;
   p->parent_ptr = this;
-  p->gif_ptr = gif_create_decompress();
-  if (!p->gif_ptr) {
-    FX_Free(p);
-    return nullptr;
-  }
-  p->gif_ptr->context_ptr = p;
-  p->gif_ptr->err_ptr = m_szLastError;
-  p->gif_ptr->gif_error_fn = gif_error_data;
-  p->gif_ptr->gif_ask_buf_for_pal_fn = gif_ask_buf_for_pal;
-  p->gif_ptr->gif_record_current_position_fn = gif_record_current_position;
-  p->gif_ptr->gif_get_row_fn = gif_read_scanline;
-  p->gif_ptr->gif_get_record_position_fn = gif_get_record_position;
+  p->m_Gif = pdfium::MakeUnique<CGifDecompressor>(p, m_szLastError);
   return p;
 }
 
 void CCodec_GifModule::Finish(FXGIF_Context* ctx) {
   if (ctx) {
-    gif_destroy_decompress(&ctx->gif_ptr);
-    ctx->m_FreeFunc(ctx);
+    ctx->m_Gif = nullptr;
+    FX_Free(ctx);
   }
 }
 
@@ -122,52 +44,52 @@
                                              void** pal_pp,
                                              int* bg_index,
                                              CFX_DIBAttribute* pAttribute) {
-  if (setjmp(ctx->gif_ptr->jmpbuf))
+  if (setjmp(ctx->m_Gif->jmpbuf))
     return GifDecodeStatus::Error;
 
-  GifDecodeStatus ret = gif_read_header(ctx->gif_ptr);
+  GifDecodeStatus ret = gif_read_header(ctx->m_Gif.get());
   if (ret != GifDecodeStatus::Success)
     return ret;
 
-  *width = ctx->gif_ptr->width;
-  *height = ctx->gif_ptr->height;
-  *pal_num = ctx->gif_ptr->global_pal_num;
-  *pal_pp = ctx->gif_ptr->global_pal_ptr;
-  *bg_index = ctx->gif_ptr->bc_index;
+  *width = ctx->m_Gif->width;
+  *height = ctx->m_Gif->height;
+  *pal_num = ctx->m_Gif->global_pal_num;
+  *pal_pp = ctx->m_Gif->m_GlobalPalette.data();
+  *bg_index = ctx->m_Gif->bc_index;
   return GifDecodeStatus::Success;
 }
 
 GifDecodeStatus CCodec_GifModule::LoadFrameInfo(FXGIF_Context* ctx,
                                                 int* frame_num) {
-  if (setjmp(ctx->gif_ptr->jmpbuf))
+  if (setjmp(ctx->m_Gif->jmpbuf))
     return GifDecodeStatus::Error;
 
-  GifDecodeStatus ret = gif_get_frame(ctx->gif_ptr);
+  GifDecodeStatus ret = gif_get_frame(ctx->m_Gif.get());
   if (ret != GifDecodeStatus::Success)
     return ret;
 
-  *frame_num = gif_get_frame_num(ctx->gif_ptr);
+  *frame_num = gif_get_frame_num(ctx->m_Gif.get());
   return GifDecodeStatus::Success;
 }
 
 GifDecodeStatus CCodec_GifModule::LoadFrame(FXGIF_Context* ctx,
                                             int frame_num,
                                             CFX_DIBAttribute* pAttribute) {
-  if (setjmp(ctx->gif_ptr->jmpbuf))
+  if (setjmp(ctx->m_Gif->jmpbuf))
     return GifDecodeStatus::Error;
 
-  GifDecodeStatus ret = gif_load_frame(ctx->gif_ptr, frame_num);
+  GifDecodeStatus ret = gif_load_frame(ctx->m_Gif.get(), frame_num);
   if (ret == GifDecodeStatus::Success) {
     if (pAttribute) {
       pAttribute->m_nGifLeft =
-          (*ctx->gif_ptr->img_ptr_arr_ptr)[frame_num]->image_info_ptr->left;
+          (*ctx->m_Gif->img_ptr_arr_ptr)[frame_num]->image_info_ptr->left;
       pAttribute->m_nGifTop =
-          (*ctx->gif_ptr->img_ptr_arr_ptr)[frame_num]->image_info_ptr->top;
-      pAttribute->m_fAspectRatio = ctx->gif_ptr->pixel_aspect;
-      if (ctx->gif_ptr->cmt_data_ptr) {
+          (*ctx->m_Gif->img_ptr_arr_ptr)[frame_num]->image_info_ptr->top;
+      pAttribute->m_fAspectRatio = ctx->m_Gif->pixel_aspect;
+      if (ctx->m_Gif->cmt_data_ptr) {
         const uint8_t* buf =
-            (const uint8_t*)ctx->gif_ptr->cmt_data_ptr->GetBuffer(0);
-        uint32_t len = ctx->gif_ptr->cmt_data_ptr->GetLength();
+            (const uint8_t*)ctx->m_Gif->cmt_data_ptr->GetBuffer(0);
+        uint32_t len = ctx->m_Gif->cmt_data_ptr->GetLength();
         if (len > 21) {
           uint8_t size = *buf++;
           if (size) {
@@ -189,11 +111,11 @@
 
 uint32_t CCodec_GifModule::GetAvailInput(FXGIF_Context* ctx,
                                          uint8_t** avail_buf_ptr) {
-  return gif_get_avail_input(ctx->gif_ptr, avail_buf_ptr);
+  return gif_get_avail_input(ctx->m_Gif.get(), avail_buf_ptr);
 }
 
 void CCodec_GifModule::Input(FXGIF_Context* ctx,
                              const uint8_t* src_buf,
                              uint32_t src_size) {
-  gif_input_buffer(ctx->gif_ptr, (uint8_t*)src_buf, src_size);
+  gif_input_buffer(ctx->m_Gif.get(), (uint8_t*)src_buf, src_size);
 }
diff --git a/core/fxcodec/codec/ccodec_gifmodule.h b/core/fxcodec/codec/ccodec_gifmodule.h
index b42a866..c429822 100644
--- a/core/fxcodec/codec/ccodec_gifmodule.h
+++ b/core/fxcodec/codec/ccodec_gifmodule.h
@@ -12,7 +12,7 @@
 #include "core/fxcrt/fx_system.h"
 
 class CFX_DIBAttribute;
-struct FXGIF_Context;
+class FXGIF_Context;
 
 class CCodec_GifModule {
  public:
diff --git a/core/fxcodec/lgif/cgifdecompressor.cpp b/core/fxcodec/lgif/cgifdecompressor.cpp
new file mode 100644
index 0000000..fb461f7
--- /dev/null
+++ b/core/fxcodec/lgif/cgifdecompressor.cpp
@@ -0,0 +1,96 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/lgif/cgifdecompressor.h"
+
+#include <utility>
+
+#include "core/fxcodec/codec/ccodec_gifmodule.h"
+#include "core/fxcodec/lgif/fx_gif.h"
+#include "third_party/base/ptr_util.h"
+#include "third_party/base/stl_util.h"
+
+FXGIF_Context::FXGIF_Context() {}
+
+FXGIF_Context::~FXGIF_Context() {}
+
+CGifDecompressor::CGifDecompressor(FXGIF_Context* p, char* error_string)
+    : decode_status(GIF_D_STATUS_SIG),
+      err_ptr(error_string),
+      context_ptr(p),
+      cmt_data_ptr(new CFX_ByteString),
+      pt_ptr_arr_ptr(new std::vector<GifPlainText*>),
+      img_ptr_arr_ptr(new std::vector<GifImage*>) {}
+
+CGifDecompressor::~CGifDecompressor() {
+  // TODO(npm): fix ownership in CGifDecompressor to avoid all of the frees and
+  // deletes in here.
+  GifPalette* pGlobalPal = m_GlobalPalette.data();
+  if (img_ptr_arr_ptr) {
+    size_t size_img_arr = img_ptr_arr_ptr->size();
+    for (size_t i = 0; i < size_img_arr; i++) {
+      GifImage* p = (*img_ptr_arr_ptr)[i];
+      FX_Free(p->image_info_ptr);
+      FX_Free(p->image_gce_ptr);
+      FX_Free(p->image_row_buf);
+      if (p->local_pal_ptr && p->local_pal_ptr != pGlobalPal)
+        FX_Free(p->local_pal_ptr);
+      FX_Free(p);
+    }
+    img_ptr_arr_ptr->clear();
+    delete img_ptr_arr_ptr;
+  }
+  delete cmt_data_ptr;
+  FX_Free(gce_ptr);
+  if (pt_ptr_arr_ptr) {
+    size_t size_pt_arr = pt_ptr_arr_ptr->size();
+    for (size_t i = 0; i < size_pt_arr; i++) {
+      GifPlainText* p = (*pt_ptr_arr_ptr)[i];
+      FX_Free(p->gce_ptr);
+      FX_Free(p->pte_ptr);
+      delete p->string_ptr;
+      FX_Free(p);
+    }
+    pt_ptr_arr_ptr->clear();
+    delete pt_ptr_arr_ptr;
+  }
+}
+
+void CGifDecompressor::ErrorData(const char* err_msg) {
+  strncpy(err_ptr, err_msg, GIF_MAX_ERROR_SIZE - 1);
+  longjmp(jmpbuf, 1);
+}
+
+uint8_t* CGifDecompressor::AskBufForPal(int32_t pal_size) {
+  return context_ptr->parent_ptr->GetDelegate()->GifAskLocalPaletteBuf(
+      gif_get_frame_num(this), pal_size);
+}
+
+void CGifDecompressor::RecordCurrentPosition(uint32_t* cur_pos_ptr) {
+  context_ptr->parent_ptr->GetDelegate()->GifRecordCurrentPosition(
+      *cur_pos_ptr);
+}
+
+void CGifDecompressor::ReadScanline(int32_t row_num, uint8_t* row_buf) {
+  context_ptr->parent_ptr->GetDelegate()->GifReadScanline(row_num, row_buf);
+}
+
+bool CGifDecompressor::GetRecordPosition(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) {
+  return context_ptr->parent_ptr->GetDelegate()->GifInputRecordPositionBuf(
+      cur_pos, FX_RECT(left, top, left + width, top + height), pal_num, pal_ptr,
+      delay_time, user_input, trans_index, disposal_method, interlace);
+}
diff --git a/core/fxcodec/lgif/cgifdecompressor.h b/core/fxcodec/lgif/cgifdecompressor.h
new file mode 100644
index 0000000..32d9dc4
--- /dev/null
+++ b/core/fxcodec/lgif/cgifdecompressor.h
@@ -0,0 +1,79 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_LGIF_CGIFDECOMPRESSOR_H_
+#define CORE_FXCODEC_LGIF_CGIFDECOMPRESSOR_H_
+
+#include <setjmp.h>
+#include <memory>
+#include <vector>
+
+#include "core/fxcodec/lgif/fx_gif.h"
+#include "core/fxcrt/fx_basic.h"
+
+class CCodec_GifModule;
+
+// TODO(npm): Get rid of this, maybe rename CGifDecompressor->GifContext
+class FXGIF_Context {
+ public:
+  FXGIF_Context();
+  ~FXGIF_Context();
+
+  std::unique_ptr<CGifDecompressor> m_Gif;
+  CCodec_GifModule* parent_ptr;
+};
+
+class CGifDecompressor {
+ public:
+  CGifDecompressor(FXGIF_Context* p, char* error_string);
+  ~CGifDecompressor();
+
+  void ErrorData(const char* err_msg);
+  uint8_t* AskBufForPal(int32_t pal_size);
+  void RecordCurrentPosition(uint32_t* cur_pos_ptr);
+  void ReadScanline(int32_t row_num, uint8_t* row_buf);
+  bool GetRecordPosition(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);
+
+  jmp_buf jmpbuf;
+  std::vector<GifPalette> m_GlobalPalette;
+  int32_t global_pal_num;
+  uint32_t img_row_offset;
+  uint32_t img_row_avail_size;
+  uint32_t avail_in;
+  int32_t decode_status;
+  uint32_t skip_size;
+
+  char* err_ptr;
+  FXGIF_Context* context_ptr;
+  CFX_ByteString* cmt_data_ptr;
+  GifGCE* gce_ptr;
+  std::vector<GifPlainText*>* pt_ptr_arr_ptr;
+  uint8_t* next_in;
+  std::vector<GifImage*>* img_ptr_arr_ptr;
+  std::unique_ptr<CGifLZWDecoder> m_ImgDecoder;
+
+  int width;
+  int height;
+
+  uint8_t bc_index;
+  uint8_t pixel_aspect;
+  uint8_t global_sort_flag;
+  uint8_t global_color_resolution;
+  uint8_t img_pass_num;
+};
+
+#endif  // CORE_FXCODEC_LGIF_CGIFDECOMPRESSOR_H_
diff --git a/core/fxcodec/lgif/fx_gif.cpp b/core/fxcodec/lgif/fx_gif.cpp
index 307834d..059da92 100644
--- a/core/fxcodec/lgif/fx_gif.cpp
+++ b/core/fxcodec/lgif/fx_gif.cpp
@@ -9,6 +9,8 @@
 #include <utility>
 
 #include "core/fxcodec/lbmp/fx_bmp.h"
+#include "core/fxcodec/lgif/cgifdecompressor.h"
+#include "third_party/base/ptr_util.h"
 #include "third_party/base/stl_util.h"
 
 static_assert(sizeof(GifImageInfo) == 9,
@@ -21,21 +23,13 @@
 
 namespace {
 
-void gif_error(gif_decompress_struct_p gif_ptr, const char* err_msg) {
-  if (gif_ptr && gif_ptr->gif_error_fn)
-    gif_ptr->gif_error_fn(gif_ptr, err_msg);
-}
-
-void gif_warn(gif_decompress_struct_p gif_ptr, const char* err_msg) {}
-
-void gif_takeover_gce_ptr(gif_decompress_struct_p gif_ptr,
-                          GifGCE** gce_ptr_ptr) {
+void gif_takeover_gce_ptr(CGifDecompressor* gif_ptr, GifGCE** gce_ptr_ptr) {
   *gce_ptr_ptr = nullptr;
   if (gif_ptr->gce_ptr)
     std::swap(*gce_ptr_ptr, gif_ptr->gce_ptr);
 }
 
-uint8_t* gif_read_data(gif_decompress_struct_p gif_ptr,
+uint8_t* gif_read_data(CGifDecompressor* gif_ptr,
                        uint8_t** des_buf_pp,
                        uint32_t data_size) {
   if (!gif_ptr || gif_ptr->avail_in < gif_ptr->skip_size + data_size)
@@ -46,14 +40,14 @@
   return *des_buf_pp;
 }
 
-void gif_save_decoding_status(gif_decompress_struct_p gif_ptr, int32_t status) {
+void gif_save_decoding_status(CGifDecompressor* gif_ptr, int32_t status) {
   gif_ptr->decode_status = status;
   gif_ptr->next_in += gif_ptr->skip_size;
   gif_ptr->avail_in -= gif_ptr->skip_size;
   gif_ptr->skip_size = 0;
 }
 
-GifDecodeStatus gif_decode_extension(gif_decompress_struct_p gif_ptr) {
+GifDecodeStatus gif_decode_extension(CGifDecompressor* gif_ptr) {
   uint8_t* data_size_ptr = nullptr;
   uint8_t* data_ptr = nullptr;
   uint32_t skip_size_org = gif_ptr->skip_size;
@@ -160,9 +154,9 @@
   return GifDecodeStatus::Success;
 }
 
-GifDecodeStatus gif_decode_image_info(gif_decompress_struct_p gif_ptr) {
+GifDecodeStatus gif_decode_image_info(CGifDecompressor* gif_ptr) {
   if (gif_ptr->width == 0 || gif_ptr->height == 0) {
-    gif_error(gif_ptr, "No Image Header Info");
+    gif_ptr->ErrorData("No Image Header Info");
     return GifDecodeStatus::Error;
   }
   uint32_t skip_size_org = gif_ptr->skip_size;
@@ -191,7 +185,7 @@
     FX_Free(gif_image_ptr->image_info_ptr);
     FX_Free(gif_image_ptr->image_row_buf);
     FX_Free(gif_image_ptr);
-    gif_error(gif_ptr, "Image Data Out Of LSD, The File May Be Corrupt");
+    gif_ptr->ErrorData("Image Data Out Of LSD, The File May Be Corrupt");
     return GifDecodeStatus::Error;
   }
   GifLF* gif_img_info_lf_ptr = (GifLF*)&gif_img_info_ptr->local_flag;
@@ -206,7 +200,7 @@
       return GifDecodeStatus::Unfinished;
     }
     gif_image_ptr->local_pal_ptr =
-        (GifPalette*)gif_ptr->gif_ask_buf_for_pal_fn(gif_ptr, loc_pal_size);
+        (GifPalette*)gif_ptr->AskBufForPal(loc_pal_size);
     if (gif_image_ptr->local_pal_ptr) {
       memcpy((uint8_t*)gif_image_ptr->local_pal_ptr, loc_pal_ptr, loc_pal_size);
     }
@@ -221,8 +215,7 @@
     return GifDecodeStatus::Unfinished;
   }
   gif_image_ptr->image_code_size = *code_size_ptr;
-  gif_ptr->gif_record_current_position_fn(gif_ptr,
-                                          &gif_image_ptr->image_data_pos);
+  gif_ptr->RecordCurrentPosition(&gif_image_ptr->image_data_pos);
   gif_image_ptr->image_data_pos += gif_ptr->skip_size;
   gif_takeover_gce_ptr(gif_ptr, &gif_image_ptr->image_gce_ptr);
   gif_ptr->img_ptr_arr_ptr->push_back(gif_image_ptr);
@@ -230,12 +223,12 @@
   return GifDecodeStatus::Success;
 }
 
-void gif_decoding_failure_at_tail_cleanup(gif_decompress_struct_p gif_ptr,
+void gif_decoding_failure_at_tail_cleanup(CGifDecompressor* gif_ptr,
                                           GifImage* gif_image_ptr) {
   FX_Free(gif_image_ptr->image_row_buf);
   gif_image_ptr->image_row_buf = nullptr;
   gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);
-  gif_error(gif_ptr, "Decode Image Data Error");
+  gif_ptr->ErrorData("Decode Image Data Error");
 }
 
 }  // namespace
@@ -403,56 +396,7 @@
   return GifDecodeStatus::Error;
 }
 
-gif_decompress_struct_p gif_create_decompress() {
-  gif_decompress_struct_p gif_ptr = FX_Alloc(gif_decompress_struct, 1);
-  memset(gif_ptr, 0, sizeof(gif_decompress_struct));
-  gif_ptr->decode_status = GIF_D_STATUS_SIG;
-  gif_ptr->img_ptr_arr_ptr = new std::vector<GifImage*>;
-  gif_ptr->cmt_data_ptr = new CFX_ByteString;
-  gif_ptr->pt_ptr_arr_ptr = new std::vector<GifPlainText*>;
-  return gif_ptr;
-}
-
-void gif_destroy_decompress(gif_decompress_struct_pp gif_ptr_ptr) {
-  if (!gif_ptr_ptr || !*gif_ptr_ptr)
-    return;
-
-  gif_decompress_struct_p gif_ptr = *gif_ptr_ptr;
-  *gif_ptr_ptr = nullptr;
-  FX_Free(gif_ptr->global_pal_ptr);
-  delete gif_ptr->img_decoder_ptr;
-  if (gif_ptr->img_ptr_arr_ptr) {
-    size_t size_img_arr = gif_ptr->img_ptr_arr_ptr->size();
-    for (size_t i = 0; i < size_img_arr; i++) {
-      GifImage* p = (*gif_ptr->img_ptr_arr_ptr)[i];
-      FX_Free(p->image_info_ptr);
-      FX_Free(p->image_gce_ptr);
-      FX_Free(p->image_row_buf);
-      if (p->local_pal_ptr && p->local_pal_ptr != gif_ptr->global_pal_ptr)
-        FX_Free(p->local_pal_ptr);
-      FX_Free(p);
-    }
-    gif_ptr->img_ptr_arr_ptr->clear();
-    delete gif_ptr->img_ptr_arr_ptr;
-  }
-  delete gif_ptr->cmt_data_ptr;
-  FX_Free(gif_ptr->gce_ptr);
-  if (gif_ptr->pt_ptr_arr_ptr) {
-    size_t size_pt_arr = gif_ptr->pt_ptr_arr_ptr->size();
-    for (size_t i = 0; i < size_pt_arr; i++) {
-      GifPlainText* p = (*gif_ptr->pt_ptr_arr_ptr)[i];
-      FX_Free(p->gce_ptr);
-      FX_Free(p->pte_ptr);
-      delete p->string_ptr;
-      FX_Free(p);
-    }
-    gif_ptr->pt_ptr_arr_ptr->clear();
-    delete gif_ptr->pt_ptr_arr_ptr;
-  }
-  FX_Free(gif_ptr);
-}
-
-GifDecodeStatus gif_read_header(gif_decompress_struct_p gif_ptr) {
+GifDecodeStatus gif_read_header(CGifDecompressor* gif_ptr) {
   if (!gif_ptr)
     return GifDecodeStatus::Error;
 
@@ -463,7 +407,7 @@
 
   if (strncmp(gif_header_ptr->signature, GIF_SIGNATURE, 3) != 0 ||
       gif_header_ptr->version[0] != '8' || gif_header_ptr->version[2] != 'a') {
-    gif_error(gif_ptr, "Not A Gif Image");
+    gif_ptr->ErrorData("Not A Gif Image");
     return GifDecodeStatus::Error;
   }
   GifLSD* gif_lsd_ptr = nullptr;
@@ -483,9 +427,8 @@
     gif_ptr->global_sort_flag = ((GifGF*)&gif_lsd_ptr->global_flag)->sort_flag;
     gif_ptr->global_color_resolution =
         ((GifGF*)&gif_lsd_ptr->global_flag)->color_resolution;
-    FX_Free(gif_ptr->global_pal_ptr);
-    gif_ptr->global_pal_ptr = (GifPalette*)FX_Alloc(uint8_t, global_pal_size);
-    memcpy(gif_ptr->global_pal_ptr, global_pal_ptr, global_pal_size);
+    gif_ptr->m_GlobalPalette.resize(global_pal_size / 3);
+    memcpy(gif_ptr->m_GlobalPalette.data(), global_pal_ptr, global_pal_size);
   }
   gif_ptr->width = (int)GetWord_LSBFirst((uint8_t*)&gif_lsd_ptr->width);
   gif_ptr->height = (int)GetWord_LSBFirst((uint8_t*)&gif_lsd_ptr->height);
@@ -494,7 +437,7 @@
   return GifDecodeStatus::Success;
 }
 
-GifDecodeStatus gif_get_frame(gif_decompress_struct_p gif_ptr) {
+GifDecodeStatus gif_get_frame(CGifDecompressor* gif_ptr) {
   if (!gif_ptr)
     return GifDecodeStatus::Error;
 
@@ -520,11 +463,11 @@
             return GifDecodeStatus::Success;
           default:
             if (gif_ptr->avail_in) {
-              gif_warn(gif_ptr, "The Gif File has non_standard Tag!");
+              // The Gif File has non_standard Tag!
               gif_save_decoding_status(gif_ptr, GIF_D_STATUS_SIG);
               continue;
             }
-            gif_warn(gif_ptr, "The Gif File Doesn't have Trailer Tag!");
+            // The Gif File Doesn't have Trailer Tag!
             return GifDecodeStatus::Success;
         }
       }
@@ -590,8 +533,7 @@
   return GifDecodeStatus::Success;
 }
 
-GifDecodeStatus gif_load_frame(gif_decompress_struct_p gif_ptr,
-                               int32_t frame_num) {
+GifDecodeStatus gif_load_frame(CGifDecompressor* gif_ptr, int32_t frame_num) {
   if (!gif_ptr || !pdfium::IndexInBounds(*gif_ptr->img_ptr_arr_ptr, frame_num))
     return GifDecodeStatus::Error;
 
@@ -601,7 +543,7 @@
   GifImage* gif_image_ptr = (*gif_ptr->img_ptr_arr_ptr)[frame_num];
   uint32_t gif_img_row_bytes = gif_image_ptr->image_info_ptr->width;
   if (gif_img_row_bytes == 0) {
-    gif_error(gif_ptr, "Error Invalid Number of Row Bytes");
+    gif_ptr->ErrorData("Error Invalid Number of Row Bytes");
     return GifDecodeStatus::Error;
   }
   if (gif_ptr->decode_status == GIF_D_STATUS_TAIL) {
@@ -618,9 +560,8 @@
             : 0;
     gif_ptr->avail_in = 0;
     if (!gif_img_gce_ptr) {
-      bool bRes = gif_ptr->gif_get_record_position_fn(
-          gif_ptr, gif_image_ptr->image_data_pos,
-          gif_image_ptr->image_info_ptr->left,
+      bool bRes = gif_ptr->GetRecordPosition(
+          gif_image_ptr->image_data_pos, gif_image_ptr->image_info_ptr->left,
           gif_image_ptr->image_info_ptr->top,
           gif_image_ptr->image_info_ptr->width,
           gif_image_ptr->image_info_ptr->height, loc_pal_num,
@@ -630,13 +571,12 @@
       if (!bRes) {
         FX_Free(gif_image_ptr->image_row_buf);
         gif_image_ptr->image_row_buf = nullptr;
-        gif_error(gif_ptr, "Error Read Record Position Data");
+        gif_ptr->ErrorData("Error Read Record Position Data");
         return GifDecodeStatus::Error;
       }
     } else {
-      bool bRes = gif_ptr->gif_get_record_position_fn(
-          gif_ptr, gif_image_ptr->image_data_pos,
-          gif_image_ptr->image_info_ptr->left,
+      bool bRes = gif_ptr->GetRecordPosition(
+          gif_image_ptr->image_data_pos, gif_image_ptr->image_info_ptr->left,
           gif_image_ptr->image_info_ptr->top,
           gif_image_ptr->image_info_ptr->width,
           gif_image_ptr->image_info_ptr->height, loc_pal_num,
@@ -653,26 +593,27 @@
       if (!bRes) {
         FX_Free(gif_image_ptr->image_row_buf);
         gif_image_ptr->image_row_buf = nullptr;
-        gif_error(gif_ptr, "Error Read Record Position Data");
+        gif_ptr->ErrorData("Error Read Record Position Data");
         return GifDecodeStatus::Error;
       }
     }
     if (gif_image_ptr->image_code_size >= 32) {
       FX_Free(gif_image_ptr->image_row_buf);
       gif_image_ptr->image_row_buf = nullptr;
-      gif_error(gif_ptr, "Error Invalid Code Size");
+      gif_ptr->ErrorData("Error Invalid Code Size");
       return GifDecodeStatus::Error;
     }
-    if (!gif_ptr->img_decoder_ptr)
-      gif_ptr->img_decoder_ptr = new CGifLZWDecoder(gif_ptr->err_ptr);
-    gif_ptr->img_decoder_ptr->InitTable(gif_image_ptr->image_code_size);
+    if (!gif_ptr->m_ImgDecoder.get())
+      gif_ptr->m_ImgDecoder =
+          pdfium::MakeUnique<CGifLZWDecoder>(gif_ptr->err_ptr);
+    gif_ptr->m_ImgDecoder->InitTable(gif_image_ptr->image_code_size);
     gif_ptr->img_row_offset = 0;
     gif_ptr->img_row_avail_size = 0;
     gif_ptr->img_pass_num = 0;
     gif_image_ptr->image_row_num = 0;
     gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);
   }
-  CGifLZWDecoder* img_decoder_ptr = gif_ptr->img_decoder_ptr;
+  CGifLZWDecoder* img_decoder_ptr = gif_ptr->m_ImgDecoder.get();
   if (gif_ptr->decode_status == GIF_D_STATUS_IMG_DATA) {
     if (!gif_read_data(gif_ptr, &data_size_ptr, 1))
       return GifDecodeStatus::Unfinished;
@@ -695,8 +636,8 @@
       }
       while (ret != GifDecodeStatus::Error) {
         if (ret == GifDecodeStatus::Success) {
-          gif_ptr->gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num,
-                                  gif_image_ptr->image_row_buf);
+          gif_ptr->ReadScanline(gif_image_ptr->image_row_num,
+                                gif_image_ptr->image_row_buf);
           FX_Free(gif_image_ptr->image_row_buf);
           gif_image_ptr->image_row_buf = nullptr;
           gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);
@@ -725,8 +666,8 @@
         }
         if (ret == GifDecodeStatus::InsufficientDestSize) {
           if (((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->interlace) {
-            gif_ptr->gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num,
-                                    gif_image_ptr->image_row_buf);
+            gif_ptr->ReadScanline(gif_image_ptr->image_row_num,
+                                  gif_image_ptr->image_row_buf);
             gif_image_ptr->image_row_num +=
                 s_gif_interlace_step[gif_ptr->img_pass_num];
             if (gif_image_ptr->image_row_num >=
@@ -740,8 +681,8 @@
                   s_gif_interlace_step[gif_ptr->img_pass_num] / 2;
             }
           } else {
-            gif_ptr->gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num++,
-                                    gif_image_ptr->image_row_buf);
+            gif_ptr->ReadScanline(gif_image_ptr->image_row_num++,
+                                  gif_image_ptr->image_row_buf);
           }
           gif_ptr->img_row_offset = 0;
           gif_ptr->img_row_avail_size = gif_img_row_bytes;
@@ -757,11 +698,11 @@
     }
     gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);
   }
-  gif_error(gif_ptr, "Decode Image Data Error");
+  gif_ptr->ErrorData("Decode Image Data Error");
   return GifDecodeStatus::Error;
 }
 
-void gif_input_buffer(gif_decompress_struct_p gif_ptr,
+void gif_input_buffer(CGifDecompressor* gif_ptr,
                       uint8_t* src_buf,
                       uint32_t src_size) {
   gif_ptr->next_in = src_buf;
@@ -769,7 +710,7 @@
   gif_ptr->skip_size = 0;
 }
 
-uint32_t gif_get_avail_input(gif_decompress_struct_p gif_ptr,
+uint32_t gif_get_avail_input(CGifDecompressor* gif_ptr,
                              uint8_t** avail_buf_ptr) {
   if (avail_buf_ptr) {
     *avail_buf_ptr = nullptr;
@@ -779,6 +720,6 @@
   return gif_ptr->avail_in;
 }
 
-int32_t gif_get_frame_num(gif_decompress_struct_p gif_ptr) {
+int32_t gif_get_frame_num(CGifDecompressor* gif_ptr) {
   return pdfium::CollectionSize<int32_t>(*gif_ptr->img_ptr_arr_ptr);
 }
diff --git a/core/fxcodec/lgif/fx_gif.h b/core/fxcodec/lgif/fx_gif.h
index c833684..58dad20 100644
--- a/core/fxcodec/lgif/fx_gif.h
+++ b/core/fxcodec/lgif/fx_gif.h
@@ -12,6 +12,8 @@
 
 #include "core/fxcrt/fx_basic.h"
 
+class CGifDecompressor;
+
 #define GIF_SIGNATURE "GIF"
 #define GIF_SIG_EXTENSION 0x21
 #define GIF_SIG_IMAGE 0x2C
@@ -162,69 +164,16 @@
   char* err_msg_ptr;
 };
 
-typedef struct tag_gif_decompress_struct gif_decompress_struct;
-typedef gif_decompress_struct* gif_decompress_struct_p;
-typedef gif_decompress_struct_p* gif_decompress_struct_pp;
 static const int32_t s_gif_interlace_step[4] = {8, 8, 4, 2};
-struct tag_gif_decompress_struct {
-  jmp_buf jmpbuf;
-  char* err_ptr;
-  void (*gif_error_fn)(gif_decompress_struct_p gif_ptr, const char* err_msg);
-  void* context_ptr;
-  int width;
-  int height;
-  GifPalette* global_pal_ptr;
-  int32_t global_pal_num;
-  uint8_t global_sort_flag;
-  uint8_t global_color_resolution;
 
-  uint8_t bc_index;
-  uint8_t pixel_aspect;
-  CGifLZWDecoder* img_decoder_ptr;
-  uint32_t img_row_offset;
-  uint32_t img_row_avail_size;
-  uint8_t img_pass_num;
-  std::vector<GifImage*>* img_ptr_arr_ptr;
-  uint8_t* (*gif_ask_buf_for_pal_fn)(gif_decompress_struct_p gif_ptr,
-                                     int32_t pal_size);
-  uint8_t* next_in;
-  uint32_t avail_in;
-  int32_t decode_status;
-  uint32_t skip_size;
-  void (*gif_record_current_position_fn)(gif_decompress_struct_p gif_ptr,
-                                         uint32_t* cur_pos_ptr);
-  void (*gif_get_row_fn)(gif_decompress_struct_p gif_ptr,
-                         int32_t row_num,
-                         uint8_t* row_buf);
-  bool (*gif_get_record_position_fn)(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);
-  CFX_ByteString* cmt_data_ptr;
-  GifGCE* gce_ptr;
-  std::vector<GifPlainText*>* pt_ptr_arr_ptr;
-};
-
-gif_decompress_struct_p gif_create_decompress();
-void gif_destroy_decompress(gif_decompress_struct_pp gif_ptr_ptr);
-GifDecodeStatus gif_read_header(gif_decompress_struct_p gif_ptr);
-GifDecodeStatus gif_get_frame(gif_decompress_struct_p gif_ptr);
-int32_t gif_get_frame_num(gif_decompress_struct_p gif_ptr);
-GifDecodeStatus gif_load_frame(gif_decompress_struct_p gif_ptr,
-                               int32_t frame_num);
-void gif_input_buffer(gif_decompress_struct_p gif_ptr,
+GifDecodeStatus gif_read_header(CGifDecompressor* gif_ptr);
+GifDecodeStatus gif_get_frame(CGifDecompressor* gif_ptr);
+int32_t gif_get_frame_num(CGifDecompressor* gif_ptr);
+GifDecodeStatus gif_load_frame(CGifDecompressor* gif_ptr, int32_t frame_num);
+void gif_input_buffer(CGifDecompressor* gif_ptr,
                       uint8_t* src_buf,
                       uint32_t src_size);
-uint32_t gif_get_avail_input(gif_decompress_struct_p gif_ptr,
+uint32_t gif_get_avail_input(CGifDecompressor* gif_ptr,
                              uint8_t** avail_buf_ptr);
 
 #endif  // CORE_FXCODEC_LGIF_FX_GIF_H_