Cleanup CGifDecompressor part 2

Change-Id: I9754da8d1bf54b328761ac9d83fcc4a3518b4a73
Reviewed-on: https://pdfium-review.googlesource.com/5230
Reviewed-by: dsinclair <dsinclair@chromium.org>
Commit-Queue: Nicolás Peña <npm@chromium.org>
diff --git a/core/fxcodec/codec/ccodec_gifmodule.cpp b/core/fxcodec/codec/ccodec_gifmodule.cpp
index 33d74a9..70f55ce 100644
--- a/core/fxcodec/codec/ccodec_gifmodule.cpp
+++ b/core/fxcodec/codec/ccodec_gifmodule.cpp
@@ -82,27 +82,18 @@
   if (ret == GifDecodeStatus::Success) {
     if (pAttribute) {
       pAttribute->m_nGifLeft =
-          (*ctx->m_Gif->img_ptr_arr_ptr)[frame_num]->image_info_ptr->left;
-      pAttribute->m_nGifTop =
-          (*ctx->m_Gif->img_ptr_arr_ptr)[frame_num]->image_info_ptr->top;
+          ctx->m_Gif->m_Images[frame_num]->m_ImageInfo.left;
+      pAttribute->m_nGifTop = ctx->m_Gif->m_Images[frame_num]->m_ImageInfo.top;
       pAttribute->m_fAspectRatio = ctx->m_Gif->pixel_aspect;
-      if (ctx->m_Gif->cmt_data_ptr) {
-        const uint8_t* buf =
-            (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) {
-            pAttribute->m_strAuthor = CFX_ByteString(buf, size);
-          } else {
-            pAttribute->m_strAuthor.clear();
-          }
-          buf += size;
-          size = *buf++;
-          if (size == 20) {
-            memcpy(pAttribute->m_strTime, buf, size);
-          }
-        }
+      const uint8_t* buf =
+          reinterpret_cast<const uint8_t*>(ctx->m_Gif->cmt_data.GetBuffer(0));
+      uint32_t len = ctx->m_Gif->cmt_data.GetLength();
+      if (len > 21) {
+        uint8_t size = *buf++;
+        if (size != 0)
+          pAttribute->m_strAuthor = CFX_ByteString(buf, size);
+        else
+          pAttribute->m_strAuthor.clear();
       }
     }
   }
diff --git a/core/fxcodec/codec/ccodec_gifmodule.h b/core/fxcodec/codec/ccodec_gifmodule.h
index c429822..862bee5 100644
--- a/core/fxcodec/codec/ccodec_gifmodule.h
+++ b/core/fxcodec/codec/ccodec_gifmodule.h
@@ -19,8 +19,6 @@
   class Delegate {
    public:
     virtual void GifRecordCurrentPosition(uint32_t& cur_pos) = 0;
-    virtual uint8_t* GifAskLocalPaletteBuf(int32_t frame_num,
-                                           int32_t pal_size) = 0;
     virtual bool GifInputRecordPositionBuf(uint32_t rcd_pos,
                                            const FX_RECT& img_rc,
                                            int32_t pal_num,
diff --git a/core/fxcodec/codec/ccodec_pngmodule.cpp b/core/fxcodec/codec/ccodec_pngmodule.cpp
index 09bc1ac..5529eae 100644
--- a/core/fxcodec/codec/ccodec_pngmodule.cpp
+++ b/core/fxcodec/codec/ccodec_pngmodule.cpp
@@ -50,19 +50,6 @@
     png_get_iCCP(png_ptr, info_ptr, &icc_name, &compress_type, &icc_profile,
                  &icc_proflen);
 #endif
-    int bTime = 0;
-#if defined(PNG_tIME_SUPPORTED)
-    png_timep t = nullptr;
-    png_get_tIME(png_ptr, info_ptr, &t);
-    if (t) {
-      memset(pAttribute->m_strTime, 0, sizeof(pAttribute->m_strTime));
-      FXSYS_snprintf((char*)pAttribute->m_strTime,
-                     sizeof(pAttribute->m_strTime), "%4u:%2u:%2u %2u:%2u:%2u",
-                     t->year, t->month, t->day, t->hour, t->minute, t->second);
-      pAttribute->m_strTime[sizeof(pAttribute->m_strTime) - 1] = 0;
-      bTime = 1;
-    }
-#endif
 #if defined(PNG_TEXT_SUPPORTED)
     int i;
     FX_STRSIZE len;
@@ -73,14 +60,7 @@
     for (i = 0; i < num_text; i++) {
       len = FXSYS_strlen(text[i].key);
       buf = "Time";
-      if (!memcmp(buf, text[i].key, std::min(len, FXSYS_strlen(buf)))) {
-        if (!bTime) {
-          memset(pAttribute->m_strTime, 0, sizeof(pAttribute->m_strTime));
-          memcpy(
-              pAttribute->m_strTime, text[i].text,
-              std::min(sizeof(pAttribute->m_strTime) - 1, text[i].text_length));
-        }
-      } else {
+      if (memcmp(buf, text[i].key, std::min(len, FXSYS_strlen(buf)))) {
         buf = "Author";
         if (!memcmp(buf, text[i].key, std::min(len, FXSYS_strlen(buf)))) {
           pAttribute->m_strAuthor =
diff --git a/core/fxcodec/codec/ccodec_progressivedecoder.h b/core/fxcodec/codec/ccodec_progressivedecoder.h
index f63c1de..6fa0daf 100644
--- a/core/fxcodec/codec/ccodec_progressivedecoder.h
+++ b/core/fxcodec/codec/ccodec_progressivedecoder.h
@@ -179,7 +179,6 @@
 
   // CCodec_GifModule::Delegate
   void GifRecordCurrentPosition(uint32_t& cur_pos) override;
-  uint8_t* GifAskLocalPaletteBuf(int32_t frame_num, int32_t pal_size) override;
   bool GifInputRecordPositionBuf(uint32_t rcd_pos,
                                  const FX_RECT& img_rc,
                                  int32_t pal_num,
diff --git a/core/fxcodec/codec/fx_codec.cpp b/core/fxcodec/codec/fx_codec.cpp
index 38f5a76..e695bc9 100644
--- a/core/fxcodec/codec/fx_codec.cpp
+++ b/core/fxcodec/codec/fx_codec.cpp
@@ -252,9 +252,8 @@
       m_nGifTop(0),
       m_pGifLocalPalette(nullptr),
       m_nGifLocalPalNum(0),
-      m_nBmpCompressType(0) {
-  memset(m_strTime, 0, sizeof(m_strTime));
-}
+      m_nBmpCompressType(0) {}
+
 CFX_DIBAttribute::~CFX_DIBAttribute() {
   for (const auto& pair : m_Exif)
     FX_Free(pair.second);
diff --git a/core/fxcodec/codec/fx_codec_progress.cpp b/core/fxcodec/codec/fx_codec_progress.cpp
index 56c9ed9..c61cb0b 100644
--- a/core/fxcodec/codec/fx_codec_progress.cpp
+++ b/core/fxcodec/codec/fx_codec_progress.cpp
@@ -615,11 +615,6 @@
   cur_pos = m_offSet - remain_size;
 }
 
-uint8_t* CCodec_ProgressiveDecoder::GifAskLocalPaletteBuf(int32_t frame_num,
-                                                          int32_t pal_size) {
-  return FX_Alloc(uint8_t, pal_size);
-}
-
 bool CCodec_ProgressiveDecoder::GifInputRecordPositionBuf(
     uint32_t rcd_pos,
     const FX_RECT& img_rc,
diff --git a/core/fxcodec/fx_codec.h b/core/fxcodec/fx_codec.h
index f034ac2..fd7b174 100644
--- a/core/fxcodec/fx_codec.h
+++ b/core/fxcodec/fx_codec.h
@@ -49,7 +49,6 @@
   float m_fAspectRatio;
   uint16_t m_wDPIUnit;
   CFX_ByteString m_strAuthor;
-  uint8_t m_strTime[20];
   int32_t m_nGifLeft;
   int32_t m_nGifTop;
   uint32_t* m_pGifLocalPalette;
diff --git a/core/fxcodec/lgif/cgifdecompressor.cpp b/core/fxcodec/lgif/cgifdecompressor.cpp
index fb461f7..073659f 100644
--- a/core/fxcodec/lgif/cgifdecompressor.cpp
+++ b/core/fxcodec/lgif/cgifdecompressor.cpp
@@ -18,64 +18,22 @@
 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*>) {}
+    : decode_status(GIF_D_STATUS_SIG), err_ptr(error_string), gif_context(p) {}
 
-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;
-  }
-}
+CGifDecompressor::~CGifDecompressor() {}
 
 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(
+  gif_context->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);
+  gif_context->parent_ptr->GetDelegate()->GifReadScanline(row_num, row_buf);
 }
 
 bool CGifDecompressor::GetRecordPosition(uint32_t cur_pos,
@@ -84,13 +42,13 @@
                                          int32_t width,
                                          int32_t height,
                                          int32_t pal_num,
-                                         void* pal_ptr,
+                                         GifPalette* 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(
+  return gif_context->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
index 32d9dc4..8d24154 100644
--- a/core/fxcodec/lgif/cgifdecompressor.h
+++ b/core/fxcodec/lgif/cgifdecompressor.h
@@ -32,7 +32,6 @@
   ~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,
@@ -41,7 +40,7 @@
                          int32_t width,
                          int32_t height,
                          int32_t pal_num,
-                         void* pal_ptr,
+                         GifPalette* pal_ptr,
                          int32_t delay_time,
                          bool user_input,
                          int32_t trans_index,
@@ -58,12 +57,11 @@
   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;
+  FXGIF_Context* gif_context;
+  CFX_ByteString cmt_data;
+  std::unique_ptr<GifGCE> m_GifGCE;
   uint8_t* next_in;
-  std::vector<GifImage*>* img_ptr_arr_ptr;
+  std::vector<std::unique_ptr<GifImage>> m_Images;
   std::unique_ptr<CGifLZWDecoder> m_ImgDecoder;
 
   int width;
diff --git a/core/fxcodec/lgif/fx_gif.cpp b/core/fxcodec/lgif/fx_gif.cpp
index 059da92..e50e64a 100644
--- a/core/fxcodec/lgif/fx_gif.cpp
+++ b/core/fxcodec/lgif/fx_gif.cpp
@@ -6,6 +6,7 @@
 
 #include "core/fxcodec/lgif/fx_gif.h"
 
+#include <algorithm>
 #include <utility>
 
 #include "core/fxcodec/lbmp/fx_bmp.h"
@@ -23,12 +24,6 @@
 
 namespace {
 
-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(CGifDecompressor* gif_ptr,
                        uint8_t** des_buf_pp,
                        uint32_t data_size) {
@@ -57,7 +52,7 @@
         gif_ptr->skip_size = skip_size_org;
         return GifDecodeStatus::Unfinished;
       }
-      gif_ptr->cmt_data_ptr->clear();
+      gif_ptr->cmt_data.clear();
       while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
         uint8_t data_size = *data_size_ptr;
         if (!gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) ||
@@ -65,79 +60,46 @@
           gif_ptr->skip_size = skip_size_org;
           return GifDecodeStatus::Unfinished;
         }
-        *(gif_ptr->cmt_data_ptr) +=
-            CFX_ByteString((const char*)data_ptr, data_size);
+        gif_ptr->cmt_data += CFX_ByteString(data_ptr, data_size);
       }
-    } break;
+      break;
+    }
     case GIF_D_STATUS_EXT_PTE: {
-      GifPTE* gif_pte_ptr = nullptr;
-      if (!gif_read_data(gif_ptr, (uint8_t**)&gif_pte_ptr, 13))
+      GifPTE* gif_pte = nullptr;
+      if (!gif_read_data(gif_ptr, reinterpret_cast<uint8_t**>(&gif_pte), 13))
         return GifDecodeStatus::Unfinished;
 
-      GifPlainText* gif_pt_ptr = FX_Alloc(GifPlainText, 1);
-      memset(gif_pt_ptr, 0, sizeof(GifPlainText));
-      gif_takeover_gce_ptr(gif_ptr, &gif_pt_ptr->gce_ptr);
-      gif_pt_ptr->pte_ptr = FX_Alloc(GifPTE, 1);
-      gif_pt_ptr->string_ptr = new CFX_ByteString;
-      gif_pt_ptr->pte_ptr->block_size = gif_pte_ptr->block_size;
-      gif_pt_ptr->pte_ptr->grid_left =
-          GetWord_LSBFirst((uint8_t*)&gif_pte_ptr->grid_left);
-      gif_pt_ptr->pte_ptr->grid_top =
-          GetWord_LSBFirst((uint8_t*)&gif_pte_ptr->grid_top);
-      gif_pt_ptr->pte_ptr->grid_width =
-          GetWord_LSBFirst((uint8_t*)&gif_pte_ptr->grid_width);
-      gif_pt_ptr->pte_ptr->grid_height =
-          GetWord_LSBFirst((uint8_t*)&gif_pte_ptr->grid_height);
-      gif_pt_ptr->pte_ptr->char_width = gif_pte_ptr->char_width;
-      gif_pt_ptr->pte_ptr->char_height = gif_pte_ptr->char_height;
-      gif_pt_ptr->pte_ptr->fc_index = gif_pte_ptr->fc_index;
-      gif_pt_ptr->pte_ptr->bc_index = gif_pte_ptr->bc_index;
+      gif_ptr->m_GifGCE = nullptr;
       if (!gif_read_data(gif_ptr, &data_size_ptr, 1)) {
         gif_ptr->skip_size = skip_size_org;
-        if (gif_pt_ptr) {
-          FX_Free(gif_pt_ptr->gce_ptr);
-          FX_Free(gif_pt_ptr->pte_ptr);
-          delete gif_pt_ptr->string_ptr;
-          FX_Free(gif_pt_ptr);
-        }
         return GifDecodeStatus::Unfinished;
       }
       while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
-        uint8_t data_size = *data_size_ptr;
         if (!gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) ||
             !gif_read_data(gif_ptr, &data_size_ptr, 1)) {
           gif_ptr->skip_size = skip_size_org;
-          if (gif_pt_ptr) {
-            FX_Free(gif_pt_ptr->gce_ptr);
-            FX_Free(gif_pt_ptr->pte_ptr);
-            delete gif_pt_ptr->string_ptr;
-            FX_Free(gif_pt_ptr);
-          }
           return GifDecodeStatus::Unfinished;
         }
-        *(gif_pt_ptr->string_ptr) +=
-            CFX_ByteString((const char*)data_ptr, data_size);
       }
-      gif_ptr->pt_ptr_arr_ptr->push_back(gif_pt_ptr);
-    } break;
+      break;
+    }
     case GIF_D_STATUS_EXT_GCE: {
       GifGCE* gif_gce_ptr = nullptr;
-      if (!gif_read_data(gif_ptr, (uint8_t**)&gif_gce_ptr, 6))
+      if (!gif_read_data(gif_ptr, reinterpret_cast<uint8_t**>(&gif_gce_ptr), 6))
         return GifDecodeStatus::Unfinished;
 
-      if (!gif_ptr->gce_ptr)
-        gif_ptr->gce_ptr = FX_Alloc(GifGCE, 1);
-      gif_ptr->gce_ptr->block_size = gif_gce_ptr->block_size;
-      gif_ptr->gce_ptr->gce_flag = gif_gce_ptr->gce_flag;
-      gif_ptr->gce_ptr->delay_time =
-          GetWord_LSBFirst((uint8_t*)&gif_gce_ptr->delay_time);
-      gif_ptr->gce_ptr->trans_index = gif_gce_ptr->trans_index;
-    } break;
+      if (!gif_ptr->m_GifGCE.get())
+        gif_ptr->m_GifGCE = pdfium::MakeUnique<GifGCE>();
+      gif_ptr->m_GifGCE->block_size = gif_gce_ptr->block_size;
+      gif_ptr->m_GifGCE->gce_flag = gif_gce_ptr->gce_flag;
+      gif_ptr->m_GifGCE->delay_time = GetWord_LSBFirst(
+          reinterpret_cast<uint8_t*>(&gif_gce_ptr->delay_time));
+      gif_ptr->m_GifGCE->trans_index = gif_gce_ptr->trans_index;
+      break;
+    }
     default: {
-      if (gif_ptr->decode_status == GIF_D_STATUS_EXT_PTE) {
-        FX_Free(gif_ptr->gce_ptr);
-        gif_ptr->gce_ptr = nullptr;
-      }
+      if (gif_ptr->decode_status == GIF_D_STATUS_EXT_PTE)
+        gif_ptr->m_GifGCE = nullptr;
       if (!gif_read_data(gif_ptr, &data_size_ptr, 1))
         return GifDecodeStatus::Unfinished;
 
@@ -161,30 +123,24 @@
   }
   uint32_t skip_size_org = gif_ptr->skip_size;
   GifImageInfo* gif_img_info_ptr = nullptr;
-  if (!gif_read_data(gif_ptr, (uint8_t**)&gif_img_info_ptr, 9))
+  if (!gif_read_data(gif_ptr, reinterpret_cast<uint8_t**>(&gif_img_info_ptr),
+                     9))
     return GifDecodeStatus::Unfinished;
 
-  GifImage* gif_image_ptr = FX_Alloc(GifImage, 1);
-  memset(gif_image_ptr, 0, sizeof(GifImage));
-  gif_image_ptr->image_info_ptr = FX_Alloc(GifImageInfo, 1);
-  gif_image_ptr->image_info_ptr->left =
-      GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->left);
-  gif_image_ptr->image_info_ptr->top =
-      GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->top);
-  gif_image_ptr->image_info_ptr->width =
-      GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->width);
-  gif_image_ptr->image_info_ptr->height =
-      GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->height);
-  gif_image_ptr->image_info_ptr->local_flag = gif_img_info_ptr->local_flag;
-  if (gif_image_ptr->image_info_ptr->left +
-              gif_image_ptr->image_info_ptr->width >
+  auto gif_image = pdfium::MakeUnique<GifImage>();
+  gif_image->m_ImageInfo.left =
+      GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_img_info_ptr->left));
+  gif_image->m_ImageInfo.top =
+      GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_img_info_ptr->top));
+  gif_image->m_ImageInfo.width =
+      GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_img_info_ptr->width));
+  gif_image->m_ImageInfo.height =
+      GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_img_info_ptr->height));
+  gif_image->m_ImageInfo.local_flag = gif_img_info_ptr->local_flag;
+  if (gif_image->m_ImageInfo.left + gif_image->m_ImageInfo.width >
           gif_ptr->width ||
-      gif_image_ptr->image_info_ptr->top +
-              gif_image_ptr->image_info_ptr->height >
+      gif_image->m_ImageInfo.top + gif_image->m_ImageInfo.height >
           gif_ptr->height) {
-    FX_Free(gif_image_ptr->image_info_ptr);
-    FX_Free(gif_image_ptr->image_row_buf);
-    FX_Free(gif_image_ptr);
     gif_ptr->ErrorData("Image Data Out Of LSD, The File May Be Corrupt");
     return GifDecodeStatus::Error;
   }
@@ -194,45 +150,43 @@
     uint8_t* loc_pal_ptr = nullptr;
     if (!gif_read_data(gif_ptr, &loc_pal_ptr, loc_pal_size)) {
       gif_ptr->skip_size = skip_size_org;
-      FX_Free(gif_image_ptr->image_info_ptr);
-      FX_Free(gif_image_ptr->image_row_buf);
-      FX_Free(gif_image_ptr);
       return GifDecodeStatus::Unfinished;
     }
-    gif_image_ptr->local_pal_ptr =
-        (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);
-    }
+    gif_image->m_LocalPalettes = std::vector<GifPalette>(loc_pal_size / 3);
+    std::copy(loc_pal_ptr, loc_pal_ptr + loc_pal_size,
+              reinterpret_cast<uint8_t*>(gif_image->m_LocalPalettes.data()));
   }
   uint8_t* code_size_ptr = nullptr;
   if (!gif_read_data(gif_ptr, &code_size_ptr, 1)) {
     gif_ptr->skip_size = skip_size_org;
-    FX_Free(gif_image_ptr->image_info_ptr);
-    FX_Free(gif_image_ptr->local_pal_ptr);
-    FX_Free(gif_image_ptr->image_row_buf);
-    FX_Free(gif_image_ptr);
     return GifDecodeStatus::Unfinished;
   }
-  gif_image_ptr->image_code_size = *code_size_ptr;
-  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);
+  gif_image->image_code_size = *code_size_ptr;
+  gif_ptr->RecordCurrentPosition(&gif_image->image_data_pos);
+  gif_image->image_data_pos += gif_ptr->skip_size;
+  gif_image->m_ImageGCE = nullptr;
+  if (gif_ptr->m_GifGCE.get()) {
+    gif_image->m_ImageGCE = std::move(gif_ptr->m_GifGCE);
+    gif_ptr->m_GifGCE = nullptr;
+  }
+  gif_ptr->m_Images.push_back(std::move(gif_image));
   gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);
   return GifDecodeStatus::Success;
 }
 
 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_image_ptr->m_ImageRowBuf.clear();
   gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);
   gif_ptr->ErrorData("Decode Image Data Error");
 }
 
 }  // namespace
 
+GifImage::GifImage() {}
+
+GifImage::~GifImage() {}
+
 void CGifLZWDecoder::Input(uint8_t* src_buf, uint32_t src_size) {
   next_in = src_buf;
   avail_in = src_size;
@@ -430,8 +384,10 @@
     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);
+  gif_ptr->width =
+      (int)GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_lsd_ptr->width));
+  gif_ptr->height =
+      (int)GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_lsd_ptr->height));
   gif_ptr->bc_index = gif_lsd_ptr->bc_index;
   gif_ptr->pixel_aspect = gif_lsd_ptr->pixel_aspect;
   return GifDecodeStatus::Success;
@@ -534,72 +490,60 @@
 }
 
 GifDecodeStatus gif_load_frame(CGifDecompressor* gif_ptr, int32_t frame_num) {
-  if (!gif_ptr || !pdfium::IndexInBounds(*gif_ptr->img_ptr_arr_ptr, frame_num))
+  if (!gif_ptr || !pdfium::IndexInBounds(gif_ptr->m_Images, frame_num))
     return GifDecodeStatus::Error;
 
   uint8_t* data_size_ptr = nullptr;
   uint8_t* data_ptr = nullptr;
   uint32_t skip_size_org = gif_ptr->skip_size;
-  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;
+  GifImage* gif_image_ptr = gif_ptr->m_Images[frame_num].get();
+  uint32_t gif_img_row_bytes = gif_image_ptr->m_ImageInfo.width;
   if (gif_img_row_bytes == 0) {
     gif_ptr->ErrorData("Error Invalid Number of Row Bytes");
     return GifDecodeStatus::Error;
   }
   if (gif_ptr->decode_status == GIF_D_STATUS_TAIL) {
-    if (gif_image_ptr->image_row_buf) {
-      FX_Free(gif_image_ptr->image_row_buf);
-      gif_image_ptr->image_row_buf = nullptr;
-    }
-    gif_image_ptr->image_row_buf = FX_Alloc(uint8_t, gif_img_row_bytes);
-    GifGCE* gif_img_gce_ptr = gif_image_ptr->image_gce_ptr;
+    gif_image_ptr->m_ImageRowBuf.resize(gif_img_row_bytes);
+    GifGCE* gif_img_gce_ptr = gif_image_ptr->m_ImageGCE.get();
     int32_t loc_pal_num =
-        ((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->local_pal
-            ? (2 << ((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)
-                        ->pal_bits)
+        ((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->local_pal
+            ? (2 << ((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->pal_bits)
             : 0;
     gif_ptr->avail_in = 0;
     if (!gif_img_gce_ptr) {
       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,
-          gif_image_ptr->local_pal_ptr, 0, 0, -1, 0,
-          (bool)((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)
-              ->interlace);
+          gif_image_ptr->image_data_pos, gif_image_ptr->m_ImageInfo.left,
+          gif_image_ptr->m_ImageInfo.top, gif_image_ptr->m_ImageInfo.width,
+          gif_image_ptr->m_ImageInfo.height, loc_pal_num,
+          gif_image_ptr->m_LocalPalettes.data(), 0, 0, -1, 0,
+          (bool)((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->interlace);
       if (!bRes) {
-        FX_Free(gif_image_ptr->image_row_buf);
-        gif_image_ptr->image_row_buf = nullptr;
+        gif_image_ptr->m_ImageRowBuf.clear();
         gif_ptr->ErrorData("Error Read Record Position Data");
         return GifDecodeStatus::Error;
       }
     } else {
       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,
-          gif_image_ptr->local_pal_ptr,
-          (int32_t)gif_image_ptr->image_gce_ptr->delay_time,
-          (bool)((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)->user_input,
-          ((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)->transparency
-              ? (int32_t)gif_image_ptr->image_gce_ptr->trans_index
+          gif_image_ptr->image_data_pos, gif_image_ptr->m_ImageInfo.left,
+          gif_image_ptr->m_ImageInfo.top, gif_image_ptr->m_ImageInfo.width,
+          gif_image_ptr->m_ImageInfo.height, loc_pal_num,
+          gif_image_ptr->m_LocalPalettes.data(),
+          (int32_t)gif_image_ptr->m_ImageGCE->delay_time,
+          (bool)((GifCEF*)&gif_image_ptr->m_ImageGCE->gce_flag)->user_input,
+          ((GifCEF*)&gif_image_ptr->m_ImageGCE->gce_flag)->transparency
+              ? (int32_t)gif_image_ptr->m_ImageGCE->trans_index
               : -1,
-          (int32_t)((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)
+          (int32_t)((GifCEF*)&gif_image_ptr->m_ImageGCE->gce_flag)
               ->disposal_method,
-          (bool)((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)
-              ->interlace);
+          (bool)((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->interlace);
       if (!bRes) {
-        FX_Free(gif_image_ptr->image_row_buf);
-        gif_image_ptr->image_row_buf = nullptr;
+        gif_image_ptr->m_ImageRowBuf.clear();
         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_image_ptr->m_ImageRowBuf.clear();
       gif_ptr->ErrorData("Error Invalid Code Size");
       return GifDecodeStatus::Error;
     }
@@ -628,7 +572,7 @@
       gif_ptr->img_row_offset += gif_ptr->img_row_avail_size;
       gif_ptr->img_row_avail_size = gif_img_row_bytes - gif_ptr->img_row_offset;
       GifDecodeStatus ret = img_decoder_ptr->Decode(
-          gif_image_ptr->image_row_buf + gif_ptr->img_row_offset,
+          gif_image_ptr->m_ImageRowBuf.data() + gif_ptr->img_row_offset,
           &gif_ptr->img_row_avail_size);
       if (ret == GifDecodeStatus::Error) {
         gif_decoding_failure_at_tail_cleanup(gif_ptr, gif_image_ptr);
@@ -637,9 +581,8 @@
       while (ret != GifDecodeStatus::Error) {
         if (ret == GifDecodeStatus::Success) {
           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_image_ptr->m_ImageRowBuf.data());
+          gif_image_ptr->m_ImageRowBuf.clear();
           gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL);
           return GifDecodeStatus::Success;
         }
@@ -660,18 +603,18 @@
             gif_ptr->img_row_avail_size =
                 gif_img_row_bytes - gif_ptr->img_row_offset;
             ret = img_decoder_ptr->Decode(
-                gif_image_ptr->image_row_buf + gif_ptr->img_row_offset,
+                gif_image_ptr->m_ImageRowBuf.data() + gif_ptr->img_row_offset,
                 &gif_ptr->img_row_avail_size);
           }
         }
         if (ret == GifDecodeStatus::InsufficientDestSize) {
-          if (((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->interlace) {
+          if (((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->interlace) {
             gif_ptr->ReadScanline(gif_image_ptr->image_row_num,
-                                  gif_image_ptr->image_row_buf);
+                                  gif_image_ptr->m_ImageRowBuf.data());
             gif_image_ptr->image_row_num +=
                 s_gif_interlace_step[gif_ptr->img_pass_num];
             if (gif_image_ptr->image_row_num >=
-                (int32_t)gif_image_ptr->image_info_ptr->height) {
+                (int32_t)gif_image_ptr->m_ImageInfo.height) {
               gif_ptr->img_pass_num++;
               if (gif_ptr->img_pass_num == FX_ArraySize(s_gif_interlace_step)) {
                 gif_decoding_failure_at_tail_cleanup(gif_ptr, gif_image_ptr);
@@ -682,12 +625,12 @@
             }
           } else {
             gif_ptr->ReadScanline(gif_image_ptr->image_row_num++,
-                                  gif_image_ptr->image_row_buf);
+                                  gif_image_ptr->m_ImageRowBuf.data());
           }
           gif_ptr->img_row_offset = 0;
           gif_ptr->img_row_avail_size = gif_img_row_bytes;
           ret = img_decoder_ptr->Decode(
-              gif_image_ptr->image_row_buf + gif_ptr->img_row_offset,
+              gif_image_ptr->m_ImageRowBuf.data() + gif_ptr->img_row_offset,
               &gif_ptr->img_row_avail_size);
         }
         if (ret == GifDecodeStatus::Error) {
@@ -721,5 +664,5 @@
 }
 
 int32_t gif_get_frame_num(CGifDecompressor* gif_ptr) {
-  return pdfium::CollectionSize<int32_t>(*gif_ptr->img_ptr_arr_ptr);
+  return pdfium::CollectionSize<int32_t>(gif_ptr->m_Images);
 }
diff --git a/core/fxcodec/lgif/fx_gif.h b/core/fxcodec/lgif/fx_gif.h
index 58dad20..7bae79f 100644
--- a/core/fxcodec/lgif/fx_gif.h
+++ b/core/fxcodec/lgif/fx_gif.h
@@ -8,6 +8,7 @@
 #define CORE_FXCODEC_LGIF_FX_GIF_H_
 
 #include <setjmp.h>
+#include <memory>
 #include <vector>
 
 #include "core/fxcrt/fx_basic.h"
@@ -101,21 +102,6 @@
 } GifAE;
 typedef struct tagGifPalette { uint8_t r, g, b; } GifPalette;
 #pragma pack()
-typedef struct tagGifImage {
-  GifGCE* image_gce_ptr;
-  GifPalette* local_pal_ptr;
-  GifImageInfo* image_info_ptr;
-  uint8_t image_code_size;
-  uint32_t image_data_pos;
-  uint8_t* image_row_buf;
-  int32_t image_row_num;
-} GifImage;
-
-typedef struct tagGifPlainText {
-  GifGCE* gce_ptr;
-  GifPTE* pte_ptr;
-  CFX_ByteString* string_ptr;
-} GifPlainText;
 
 enum class GifDecodeStatus {
   Error,
@@ -124,6 +110,20 @@
   InsufficientDestSize,  // Only used internally by CGifLZWDecoder::Decode()
 };
 
+class GifImage {
+ public:
+  GifImage();
+  ~GifImage();
+
+  std::unique_ptr<GifGCE> m_ImageGCE;
+  std::vector<GifPalette> m_LocalPalettes;
+  std::vector<uint8_t> m_ImageRowBuf;
+  GifImageInfo m_ImageInfo;
+  uint8_t image_code_size;
+  uint32_t image_data_pos;
+  int32_t image_row_num;
+};
+
 class CGifLZWDecoder {
  public:
   struct tag_Table {