diff options
-rw-r--r-- | BUILD.gn | 14 | ||||
-rw-r--r-- | core/fxcodec/codec/ccodec_gifmodule.cpp | 80 | ||||
-rw-r--r-- | core/fxcodec/codec/ccodec_gifmodule.h | 24 | ||||
-rw-r--r-- | core/fxcodec/codec/fx_codec_progress.cpp | 18 | ||||
-rw-r--r-- | core/fxcodec/gif/cfx_gif.cpp | 20 | ||||
-rw-r--r-- | core/fxcodec/gif/cfx_gif.h (renamed from core/fxcodec/lgif/fx_gif.h) | 50 | ||||
-rw-r--r-- | core/fxcodec/gif/cfx_gifcontext.cpp | 537 | ||||
-rw-r--r-- | core/fxcodec/gif/cfx_gifcontext.h | 76 | ||||
-rw-r--r-- | core/fxcodec/gif/cfx_lzwdecompressor.cpp (renamed from core/fxcodec/lgif/cfx_lzwdecoder.cpp) | 57 | ||||
-rw-r--r-- | core/fxcodec/gif/cfx_lzwdecompressor.h (renamed from core/fxcodec/lgif/cfx_lzwdecoder.h) | 26 | ||||
-rw-r--r-- | core/fxcodec/gif/cfx_lzwdecompressor_unittest.cpp (renamed from core/fxcodec/lgif/cfx_lzwdecoder_unittest.cpp) | 46 | ||||
-rw-r--r-- | core/fxcodec/lgif/cgifcontext.cpp | 549 | ||||
-rw-r--r-- | core/fxcodec/lgif/cgifcontext.h | 76 | ||||
-rw-r--r-- | core/fxcodec/lgif/fx_gif.cpp | 18 |
14 files changed, 791 insertions, 800 deletions
@@ -775,14 +775,14 @@ static_library("fxcodec") { "core/fxcodec/codec/ccodec_tiffmodule.cpp", "core/fxcodec/codec/ccodec_tiffmodule.h", "core/fxcodec/codec/fx_codec_progress.cpp", + "core/fxcodec/gif/cfx_gif.cpp", + "core/fxcodec/gif/cfx_gif.h", + "core/fxcodec/gif/cfx_gifcontext.cpp", + "core/fxcodec/gif/cfx_gifcontext.h", + "core/fxcodec/gif/cfx_lzwdecompressor.cpp", + "core/fxcodec/gif/cfx_lzwdecompressor.h", "core/fxcodec/lbmp/fx_bmp.cpp", "core/fxcodec/lbmp/fx_bmp.h", - "core/fxcodec/lgif/cfx_lzwdecoder.cpp", - "core/fxcodec/lgif/cfx_lzwdecoder.h", - "core/fxcodec/lgif/cgifcontext.cpp", - "core/fxcodec/lgif/cgifcontext.h", - "core/fxcodec/lgif/fx_gif.cpp", - "core/fxcodec/lgif/fx_gif.h", ] deps += [ "third_party:fx_lpng", @@ -1950,7 +1950,7 @@ test("pdfium_unittests") { include_dirs = [] if (pdf_enable_xfa) { sources += [ - "core/fxcodec/lgif/cfx_lzwdecoder_unittest.cpp", + "core/fxcodec/gif/cfx_lzwdecompressor_unittest.cpp", "core/fxcrt/css/cfx_cssdeclaration_unittest.cpp", "core/fxcrt/css/cfx_cssstylesheet_unittest.cpp", "core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp", diff --git a/core/fxcodec/codec/ccodec_gifmodule.cpp b/core/fxcodec/codec/ccodec_gifmodule.cpp index b7e55d5208..0567af06ea 100644 --- a/core/fxcodec/codec/ccodec_gifmodule.cpp +++ b/core/fxcodec/codec/ccodec_gifmodule.cpp @@ -8,8 +8,8 @@ #include "core/fxcodec/codec/codec_int.h" #include "core/fxcodec/fx_codec.h" -#include "core/fxcodec/lgif/cgifcontext.h" -#include "core/fxcodec/lgif/fx_gif.h" +#include "core/fxcodec/gif/cfx_gif.h" +#include "core/fxcodec/gif/cfx_gifcontext.h" #include "core/fxge/fx_dib.h" #include "third_party/base/ptr_util.h" @@ -19,55 +19,55 @@ CCodec_GifModule::~CCodec_GifModule() {} std::unique_ptr<CCodec_GifModule::Context> CCodec_GifModule::Start( Delegate* pDelegate) { - return pdfium::MakeUnique<CGifContext>(this, pDelegate); + return pdfium::MakeUnique<CFX_GifContext>(this, pDelegate); } -GifDecodeStatus CCodec_GifModule::ReadHeader(Context* pContext, - int* width, - int* height, - int* pal_num, - void** pal_pp, - int* bg_index, - CFX_DIBAttribute* pAttribute) { - auto* context = static_cast<CGifContext*>(pContext); - GifDecodeStatus ret = context->ReadHeader(); - if (ret != GifDecodeStatus::Success) +CFX_GifDecodeStatus CCodec_GifModule::ReadHeader(Context* pContext, + int* width, + int* height, + int* pal_num, + void** pal_pp, + int* bg_index, + CFX_DIBAttribute* pAttribute) { + auto* context = static_cast<CFX_GifContext*>(pContext); + CFX_GifDecodeStatus ret = context->ReadHeader(); + if (ret != CFX_GifDecodeStatus::Success) return ret; - *width = context->width; - *height = context->height; - *pal_num = (2 << context->global_pal_exp); - *pal_pp = context->m_GlobalPalette.empty() ? nullptr - : context->m_GlobalPalette.data(); - *bg_index = context->bc_index; - return GifDecodeStatus::Success; + *width = context->width_; + *height = context->height_; + *pal_num = (2 << context->global_pal_exp_); + *pal_pp = context->global_palette_.empty() ? nullptr + : context->global_palette_.data(); + *bg_index = context->bc_index_; + return CFX_GifDecodeStatus::Success; } -GifDecodeStatus CCodec_GifModule::LoadFrameInfo(Context* pContext, - int* frame_num) { - auto* context = static_cast<CGifContext*>(pContext); - GifDecodeStatus ret = context->GetFrame(); - if (ret != GifDecodeStatus::Success) +CFX_GifDecodeStatus CCodec_GifModule::LoadFrameInfo(Context* pContext, + int* frame_num) { + auto* context = static_cast<CFX_GifContext*>(pContext); + CFX_GifDecodeStatus ret = context->GetFrame(); + if (ret != CFX_GifDecodeStatus::Success) return ret; *frame_num = context->GetFrameNum(); - return GifDecodeStatus::Success; + return CFX_GifDecodeStatus::Success; } -GifDecodeStatus CCodec_GifModule::LoadFrame(Context* pContext, - int frame_num, - CFX_DIBAttribute* pAttribute) { - auto* context = static_cast<CGifContext*>(pContext); - GifDecodeStatus ret = context->LoadFrame(frame_num); - if (ret != GifDecodeStatus::Success || !pAttribute) +CFX_GifDecodeStatus CCodec_GifModule::LoadFrame(Context* pContext, + int frame_num, + CFX_DIBAttribute* pAttribute) { + auto* context = static_cast<CFX_GifContext*>(pContext); + CFX_GifDecodeStatus ret = context->LoadFrame(frame_num); + if (ret != CFX_GifDecodeStatus::Success || !pAttribute) return ret; - pAttribute->m_nGifLeft = context->m_Images[frame_num]->m_ImageInfo.left; - pAttribute->m_nGifTop = context->m_Images[frame_num]->m_ImageInfo.top; - pAttribute->m_fAspectRatio = context->pixel_aspect; + pAttribute->m_nGifLeft = context->images_[frame_num]->image_info.left; + pAttribute->m_nGifTop = context->images_[frame_num]->image_info.top; + pAttribute->m_fAspectRatio = context->pixel_aspect_; const uint8_t* buf = - reinterpret_cast<const uint8_t*>(context->cmt_data.GetBuffer(0)); - uint32_t len = context->cmt_data.GetLength(); + reinterpret_cast<const uint8_t*>(context->cmt_data_.GetBuffer(0)); + uint32_t len = context->cmt_data_.GetLength(); if (len > 21) { uint8_t size = *buf++; if (size != 0) @@ -75,18 +75,18 @@ GifDecodeStatus CCodec_GifModule::LoadFrame(Context* pContext, else pAttribute->m_strAuthor.clear(); } - return GifDecodeStatus::Success; + return CFX_GifDecodeStatus::Success; } uint32_t CCodec_GifModule::GetAvailInput(Context* pContext, uint8_t** avail_buf_ptr) { - auto* context = static_cast<CGifContext*>(pContext); + auto* context = static_cast<CFX_GifContext*>(pContext); return context->GetAvailInput(avail_buf_ptr); } void CCodec_GifModule::Input(Context* pContext, const uint8_t* src_buf, uint32_t src_size) { - auto* context = static_cast<CGifContext*>(pContext); + auto* context = static_cast<CFX_GifContext*>(pContext); context->SetInputBuffer((uint8_t*)src_buf, src_size); } diff --git a/core/fxcodec/codec/ccodec_gifmodule.h b/core/fxcodec/codec/ccodec_gifmodule.h index fe1c46478d..886c902bba 100644 --- a/core/fxcodec/codec/ccodec_gifmodule.h +++ b/core/fxcodec/codec/ccodec_gifmodule.h @@ -9,7 +9,7 @@ #include <memory> -#include "core/fxcodec/lgif/fx_gif.h" +#include "core/fxcodec/gif/cfx_gif.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_system.h" @@ -43,17 +43,17 @@ class CCodec_GifModule { std::unique_ptr<Context> Start(Delegate* pDelegate); uint32_t GetAvailInput(Context* context, uint8_t** avail_buf_ptr = nullptr); void Input(Context* context, const uint8_t* src_buf, uint32_t src_size); - GifDecodeStatus ReadHeader(Context* context, - int* width, - int* height, - int* pal_num, - void** pal_pp, - int* bg_index, - CFX_DIBAttribute* pAttribute); - GifDecodeStatus LoadFrameInfo(Context* context, int* frame_num); - GifDecodeStatus LoadFrame(Context* context, - int frame_num, - CFX_DIBAttribute* pAttribute); + CFX_GifDecodeStatus ReadHeader(Context* context, + int* width, + int* height, + int* pal_num, + void** pal_pp, + int* bg_index, + CFX_DIBAttribute* pAttribute); + CFX_GifDecodeStatus LoadFrameInfo(Context* context, int* frame_num); + CFX_GifDecodeStatus LoadFrame(Context* context, + int frame_num, + CFX_DIBAttribute* pAttribute); }; #endif // CORE_FXCODEC_CODEC_CCODEC_GIFMODULE_H_ diff --git a/core/fxcodec/codec/fx_codec_progress.cpp b/core/fxcodec/codec/fx_codec_progress.cpp index d28277173e..746a574bbc 100644 --- a/core/fxcodec/codec/fx_codec_progress.cpp +++ b/core/fxcodec/codec/fx_codec_progress.cpp @@ -1203,10 +1203,10 @@ bool CCodec_ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType, m_offSet += size; pGifModule->Input(m_pGifContext.get(), m_pSrcBuf, size); m_SrcComponents = 1; - GifDecodeStatus readResult = pGifModule->ReadHeader( + CFX_GifDecodeStatus readResult = pGifModule->ReadHeader( m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber, (void**)&m_pGifPalette, &m_GifBgIndex, nullptr); - while (readResult == GifDecodeStatus::Unfinished) { + while (readResult == CFX_GifDecodeStatus::Unfinished) { FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; if (!GifReadMoreData(pGifModule, error_status)) { m_pGifContext = nullptr; @@ -1217,7 +1217,7 @@ bool CCodec_ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType, m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber, (void**)&m_pGifPalette, &m_GifBgIndex, nullptr); } - if (readResult == GifDecodeStatus::Success) { + if (readResult == CFX_GifDecodeStatus::Success) { m_SrcBPC = 8; m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); return true; @@ -1815,9 +1815,9 @@ FXCODEC_STATUS CCodec_ProgressiveDecoder::GetFrames(int32_t* frames) { return m_status; } while (true) { - GifDecodeStatus readResult = + CFX_GifDecodeStatus readResult = pGifModule->LoadFrameInfo(m_pGifContext.get(), &m_FrameNumber); - while (readResult == GifDecodeStatus::Unfinished) { + while (readResult == CFX_GifDecodeStatus::Unfinished) { FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_READ; if (!GifReadMoreData(pGifModule, error_status)) return error_status; @@ -1825,7 +1825,7 @@ FXCODEC_STATUS CCodec_ProgressiveDecoder::GetFrames(int32_t* frames) { readResult = pGifModule->LoadFrameInfo(m_pGifContext.get(), &m_FrameNumber); } - if (readResult == GifDecodeStatus::Success) { + if (readResult == CFX_GifDecodeStatus::Success) { *frames = m_FrameNumber; m_status = FXCODEC_STATUS_DECODE_READY; return m_status; @@ -2118,9 +2118,9 @@ FXCODEC_STATUS CCodec_ProgressiveDecoder::ContinueDecode() { return m_status; } - GifDecodeStatus readRes = + CFX_GifDecodeStatus readRes = pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr); - while (readRes == GifDecodeStatus::Unfinished) { + while (readRes == CFX_GifDecodeStatus::Unfinished) { FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; if (!GifReadMoreData(pGifModule, error_status)) { m_pDeviceBitmap = nullptr; @@ -2132,7 +2132,7 @@ FXCODEC_STATUS CCodec_ProgressiveDecoder::ContinueDecode() { pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr); } - if (readRes == GifDecodeStatus::Success) { + if (readRes == CFX_GifDecodeStatus::Success) { m_pDeviceBitmap = nullptr; m_pFile = nullptr; m_status = FXCODEC_STATUS_DECODE_FINISH; diff --git a/core/fxcodec/gif/cfx_gif.cpp b/core/fxcodec/gif/cfx_gif.cpp new file mode 100644 index 0000000000..c3c5c85323 --- /dev/null +++ b/core/fxcodec/gif/cfx_gif.cpp @@ -0,0 +1,20 @@ +// Copyright 2014 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/gif/cfx_gif.h" + +static_assert(sizeof(CFX_CFX_GifImageInfo) == 9, + "CFX_CFX_GifImageInfo should have a size of 9"); +static_assert(sizeof(CFX_GifPalette) == 3, + "CFX_GifPalette should have a size of 3"); +static_assert(sizeof(CFX_GifPlainTextExtension) == 13, + "CFX_GifPlainTextExtension should have a size of 13"); +static_assert(sizeof(CFX_GifGraphicControlExtension) == 5, + "CFX_GifGraphicControlExtension should have a size of 5"); +static_assert(sizeof(CFX_GifHeader) == 6, + "CFX_GifHeader should have a size of 6"); +static_assert(sizeof(CFX_GifLocalScreenDescriptor) == 7, + "CFX_GifLocalScreenDescriptor should have a size of 7"); diff --git a/core/fxcodec/lgif/fx_gif.h b/core/fxcodec/gif/cfx_gif.h index 08a64c8326..02a4862017 100644 --- a/core/fxcodec/lgif/fx_gif.h +++ b/core/fxcodec/gif/cfx_gif.h @@ -4,13 +4,13 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#ifndef CORE_FXCODEC_LGIF_FX_GIF_H_ -#define CORE_FXCODEC_LGIF_FX_GIF_H_ +#ifndef CORE_FXCODEC_GIF_CFX_GIF_H_ +#define CORE_FXCODEC_GIF_CFX_GIF_H_ #include <memory> #include <vector> -class CGifContext; +class CFX_GifContext; #define GIF_SIGNATURE "GIF" #define GIF_SIG_EXTENSION 0x21 @@ -42,7 +42,7 @@ typedef struct { uint8_t sort_flag : 1; uint8_t color_resolution : 3; uint8_t global_pal : 1; -} GifGlobalFlags; +} CFX_GifGlobalFlags; typedef struct { uint8_t pal_bits : 3; @@ -50,42 +50,42 @@ typedef struct { uint8_t sort_flag : 1; uint8_t interlace : 1; uint8_t local_pal : 1; -} GifLocalFlags; +} CFX_GifLocalFlags; typedef struct { char signature[3]; char version[3]; -} GifHeader; +} CFX_GifHeader; typedef struct { uint16_t width; uint16_t height; - GifGlobalFlags global_flags; + CFX_GifGlobalFlags global_flags; uint8_t bc_index; uint8_t pixel_aspect; -} GifLocalScreenDescriptor; +} CFX_GifLocalScreenDescriptor; typedef struct { uint16_t left; uint16_t top; uint16_t width; uint16_t height; - GifLocalFlags local_flags; -} GifImageInfo; + CFX_GifLocalFlags local_flags; +} CFX_CFX_GifImageInfo; typedef struct { uint8_t transparency : 1; uint8_t user_input : 1; uint8_t disposal_method : 3; uint8_t reserved : 3; -} GifControlExtensionFlags; +} CFX_GifControlExtensionFlags; typedef struct { uint8_t block_size; - GifControlExtensionFlags gce_flags; + CFX_GifControlExtensionFlags gce_flags; uint16_t delay_time; uint8_t trans_index; -} GifGraphicControlExtension; +} CFX_GifGraphicControlExtension; typedef struct { uint8_t block_size; @@ -99,7 +99,7 @@ typedef struct { uint8_t fc_index; uint8_t bc_index; -} GifPlainTextExtension; +} CFX_GifPlainTextExtension; typedef struct { uint8_t block_size; @@ -107,10 +107,10 @@ typedef struct { uint8_t app_authentication[3]; } GifApplicationExtension; -typedef struct { uint8_t r, g, b; } GifPalette; +typedef struct { uint8_t r, g, b; } CFX_GifPalette; #pragma pack() -enum class GifDecodeStatus { +enum class CFX_GifDecodeStatus { Error, Success, Unfinished, @@ -118,14 +118,14 @@ enum class GifDecodeStatus { }; typedef struct { - std::unique_ptr<GifGraphicControlExtension> m_ImageGCE; - std::vector<GifPalette> m_LocalPalettes; - std::vector<uint8_t> m_ImageRowBuf; - GifImageInfo m_ImageInfo; + std::unique_ptr<CFX_GifGraphicControlExtension> image_GCE; + std::vector<CFX_GifPalette> local_palettes; + std::vector<uint8_t> row_buffer; + CFX_CFX_GifImageInfo image_info; uint8_t local_pallette_exp; - uint8_t image_code_exp; - uint32_t image_data_pos; - int32_t image_row_num; -} GifImage; + uint8_t code_exp; + uint32_t data_pos; + int32_t row_num; +} CFX_GifImage; -#endif // CORE_FXCODEC_LGIF_FX_GIF_H_ +#endif // CORE_FXCODEC_GIF_CFX_GIF_H_ diff --git a/core/fxcodec/gif/cfx_gifcontext.cpp b/core/fxcodec/gif/cfx_gifcontext.cpp new file mode 100644 index 0000000000..a882a58bd2 --- /dev/null +++ b/core/fxcodec/gif/cfx_gifcontext.cpp @@ -0,0 +1,537 @@ +// 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/gif/cfx_gifcontext.h" + +#include <algorithm> +#include <utility> + +#include "core/fxcodec/codec/ccodec_gifmodule.h" +#include "core/fxcodec/gif/cfx_gif.h" +#include "core/fxcodec/lbmp/fx_bmp.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +namespace { + +const int32_t s_gif_interlace_step[4] = {8, 8, 4, 2}; + +} // namespace + +CFX_GifContext::CFX_GifContext(CCodec_GifModule* gif_module, + CCodec_GifModule::Delegate* delegate) + : gif_module_(gif_module), + delegate_(delegate), + global_pal_exp_(0), + img_row_offset_(0), + img_row_avail_size_(0), + avail_in_(0), + decode_status_(GIF_D_STATUS_SIG), + skip_size_(0), + next_in_(nullptr), + width_(0), + height_(0), + bc_index_(0), + pixel_aspect_(0), + global_sort_flag_(0), + global_color_resolution_(0), + img_pass_num_(0) {} + +CFX_GifContext::~CFX_GifContext() {} + +void CFX_GifContext::RecordCurrentPosition(uint32_t* cur_pos) { + delegate_->GifRecordCurrentPosition(*cur_pos); +} + +void CFX_GifContext::ReadScanline(int32_t row_num, uint8_t* row_buf) { + delegate_->GifReadScanline(row_num, row_buf); +} + +bool CFX_GifContext::GetRecordPosition(uint32_t cur_pos, + int32_t left, + int32_t top, + int32_t width, + int32_t height, + int32_t pal_num, + CFX_GifPalette* pal, + int32_t delay_time, + bool user_input, + int32_t trans_index, + int32_t disposal_method, + bool interlace) { + return delegate_->GifInputRecordPositionBuf( + cur_pos, FX_RECT(left, top, left + width, top + height), pal_num, pal, + delay_time, user_input, trans_index, disposal_method, interlace); +} + +CFX_GifDecodeStatus CFX_GifContext::ReadHeader() { + uint32_t skip_size_org = skip_size_; + CFX_GifHeader* gif_header = nullptr; + if (!ReadData(reinterpret_cast<uint8_t**>(&gif_header), 6)) + return CFX_GifDecodeStatus::Unfinished; + + if (strncmp(gif_header->signature, GIF_SIGNATURE, 3) != 0 || + gif_header->version[0] != '8' || gif_header->version[2] != 'a') + return CFX_GifDecodeStatus::Error; + + CFX_GifLocalScreenDescriptor* gif_lsd = nullptr; + if (!ReadData(reinterpret_cast<uint8_t**>(&gif_lsd), 7)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + if (gif_lsd->global_flags.global_pal) { + global_pal_exp_ = gif_lsd->global_flags.pal_bits; + uint32_t global_pal_size = unsigned(2 << global_pal_exp_) * 3u; + uint8_t* global_pal = nullptr; + if (!ReadData(&global_pal, global_pal_size)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + global_sort_flag_ = gif_lsd->global_flags.sort_flag; + global_color_resolution_ = gif_lsd->global_flags.color_resolution; + global_palette_.resize(global_pal_size / 3); + memcpy(global_palette_.data(), global_pal, global_pal_size); + } + + width_ = static_cast<int>( + GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_lsd->width))); + height_ = static_cast<int>( + GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_lsd->height))); + bc_index_ = gif_lsd->bc_index; + pixel_aspect_ = gif_lsd->pixel_aspect; + return CFX_GifDecodeStatus::Success; +} + +CFX_GifDecodeStatus CFX_GifContext::GetFrame() { + CFX_GifDecodeStatus ret = CFX_GifDecodeStatus::Success; + while (true) { + switch (decode_status_) { + case GIF_D_STATUS_TAIL: + return CFX_GifDecodeStatus::Success; + case GIF_D_STATUS_SIG: { + uint8_t* signature = nullptr; + if (!ReadData(&signature, 1)) + return CFX_GifDecodeStatus::Unfinished; + + switch (*signature) { + case GIF_SIG_EXTENSION: + SaveDecodingStatus(GIF_D_STATUS_EXT); + continue; + case GIF_SIG_IMAGE: + SaveDecodingStatus(GIF_D_STATUS_IMG_INFO); + continue; + case GIF_SIG_TRAILER: + SaveDecodingStatus(GIF_D_STATUS_TAIL); + return CFX_GifDecodeStatus::Success; + default: + if (avail_in_) { + // The Gif File has non_standard Tag! + SaveDecodingStatus(GIF_D_STATUS_SIG); + continue; + } + // The Gif File Doesn't have Trailer Tag! + return CFX_GifDecodeStatus::Success; + } + } + case GIF_D_STATUS_EXT: { + uint8_t* extension = nullptr; + if (!ReadData(&extension, 1)) + return CFX_GifDecodeStatus::Unfinished; + + switch (*extension) { + case GIF_BLOCK_CE: + SaveDecodingStatus(GIF_D_STATUS_EXT_CE); + continue; + case GIF_BLOCK_GCE: + SaveDecodingStatus(GIF_D_STATUS_EXT_GCE); + continue; + case GIF_BLOCK_PTE: + SaveDecodingStatus(GIF_D_STATUS_EXT_PTE); + continue; + default: { + int32_t status = GIF_D_STATUS_EXT_UNE; + if (*extension == GIF_BLOCK_PTE) { + status = GIF_D_STATUS_EXT_PTE; + } + SaveDecodingStatus(status); + continue; + } + } + } + case GIF_D_STATUS_IMG_INFO: { + ret = DecodeImageInfo(); + if (ret != CFX_GifDecodeStatus::Success) + return ret; + + continue; + } + case GIF_D_STATUS_IMG_DATA: { + uint8_t* img_data_size = nullptr; + uint8_t* img_data = nullptr; + uint32_t skip_size_org = skip_size_; + if (!ReadData(&img_data_size, 1)) + return CFX_GifDecodeStatus::Unfinished; + + while (*img_data_size != GIF_BLOCK_TERMINAL) { + if (!ReadData(&img_data, *img_data_size)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + SaveDecodingStatus(GIF_D_STATUS_IMG_DATA); + skip_size_org = skip_size_; + if (!ReadData(&img_data_size, 1)) + return CFX_GifDecodeStatus::Unfinished; + } + SaveDecodingStatus(GIF_D_STATUS_SIG); + continue; + } + default: { + ret = DecodeExtension(); + if (ret != CFX_GifDecodeStatus::Success) + return ret; + break; + } + } + } + return CFX_GifDecodeStatus::Success; +} + +CFX_GifDecodeStatus CFX_GifContext::LoadFrame(int32_t frame_num) { + if (!pdfium::IndexInBounds(images_, frame_num)) + return CFX_GifDecodeStatus::Error; + + uint8_t* img_data_size = nullptr; + uint8_t* img_data = nullptr; + uint32_t skip_size_org = skip_size_; + CFX_GifImage* gif_image = images_[frame_num].get(); + uint32_t gif_img_row_bytes = gif_image->image_info.width; + if (gif_img_row_bytes == 0) + return CFX_GifDecodeStatus::Error; + + if (decode_status_ == GIF_D_STATUS_TAIL) { + gif_image->row_buffer.resize(gif_img_row_bytes); + CFX_GifGraphicControlExtension* gif_img_gce = gif_image->image_GCE.get(); + int32_t loc_pal_num = + gif_image->image_info.local_flags.local_pal + ? (2 << gif_image->image_info.local_flags.pal_bits) + : 0; + avail_in_ = 0; + CFX_GifPalette* pLocalPalette = gif_image->local_palettes.empty() + ? nullptr + : gif_image->local_palettes.data(); + if (!gif_img_gce) { + bool bRes = GetRecordPosition( + gif_image->data_pos, gif_image->image_info.left, + gif_image->image_info.top, gif_image->image_info.width, + gif_image->image_info.height, loc_pal_num, pLocalPalette, 0, 0, -1, 0, + gif_image->image_info.local_flags.interlace); + if (!bRes) { + gif_image->row_buffer.clear(); + return CFX_GifDecodeStatus::Error; + } + } else { + bool bRes = GetRecordPosition( + gif_image->data_pos, gif_image->image_info.left, + gif_image->image_info.top, gif_image->image_info.width, + gif_image->image_info.height, loc_pal_num, pLocalPalette, + static_cast<int32_t>(gif_image->image_GCE->delay_time), + gif_image->image_GCE->gce_flags.user_input, + gif_image->image_GCE->gce_flags.transparency + ? static_cast<int32_t>(gif_image->image_GCE->trans_index) + : -1, + static_cast<int32_t>(gif_image->image_GCE->gce_flags.disposal_method), + gif_image->image_info.local_flags.interlace); + if (!bRes) { + gif_image->row_buffer.clear(); + return CFX_GifDecodeStatus::Error; + } + } + + if (gif_image->code_exp > GIF_MAX_LZW_EXP) { + gif_image->row_buffer.clear(); + return CFX_GifDecodeStatus::Error; + } + + img_row_offset_ = 0; + img_row_avail_size_ = 0; + img_pass_num_ = 0; + gif_image->row_num = 0; + SaveDecodingStatus(GIF_D_STATUS_IMG_DATA); + } + + if (decode_status_ == GIF_D_STATUS_IMG_DATA) { + if (!ReadData(&img_data_size, 1)) + return CFX_GifDecodeStatus::Unfinished; + + if (*img_data_size != GIF_BLOCK_TERMINAL) { + if (!ReadData(&img_data, *img_data_size)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + if (!lzw_decompressor_.get()) + lzw_decompressor_ = CFX_LZWDecompressor::Create( + !gif_image->local_palettes.empty() ? gif_image->local_pallette_exp + : global_pal_exp_, + gif_image->code_exp); + SaveDecodingStatus(GIF_D_STATUS_IMG_DATA); + img_row_offset_ += img_row_avail_size_; + img_row_avail_size_ = gif_img_row_bytes - img_row_offset_; + CFX_GifDecodeStatus ret = + lzw_decompressor_.get() + ? lzw_decompressor_->Decode( + img_data, *img_data_size, + gif_image->row_buffer.data() + img_row_offset_, + &img_row_avail_size_) + : CFX_GifDecodeStatus::Error; + if (ret == CFX_GifDecodeStatus::Error) { + DecodingFailureAtTailCleanup(gif_image); + return CFX_GifDecodeStatus::Error; + } + while (ret != CFX_GifDecodeStatus::Error) { + if (ret == CFX_GifDecodeStatus::Success) { + ReadScanline(gif_image->row_num, gif_image->row_buffer.data()); + gif_image->row_buffer.clear(); + SaveDecodingStatus(GIF_D_STATUS_TAIL); + return CFX_GifDecodeStatus::Success; + } + if (ret == CFX_GifDecodeStatus::Unfinished) { + skip_size_org = skip_size_; + if (!ReadData(&img_data_size, 1)) + return CFX_GifDecodeStatus::Unfinished; + + if (*img_data_size != GIF_BLOCK_TERMINAL) { + if (!ReadData(&img_data, *img_data_size)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + if (!lzw_decompressor_.get()) + lzw_decompressor_ = CFX_LZWDecompressor::Create( + !gif_image->local_palettes.empty() + ? gif_image->local_pallette_exp + : global_pal_exp_, + gif_image->code_exp); + SaveDecodingStatus(GIF_D_STATUS_IMG_DATA); + img_row_offset_ += img_row_avail_size_; + img_row_avail_size_ = gif_img_row_bytes - img_row_offset_; + ret = lzw_decompressor_.get() + ? lzw_decompressor_->Decode( + img_data, *img_data_size, + gif_image->row_buffer.data() + img_row_offset_, + &img_row_avail_size_) + : CFX_GifDecodeStatus::Error; + } + } + if (ret == CFX_GifDecodeStatus::InsufficientDestSize) { + if (gif_image->image_info.local_flags.interlace) { + ReadScanline(gif_image->row_num, gif_image->row_buffer.data()); + gif_image->row_num += s_gif_interlace_step[img_pass_num_]; + if (gif_image->row_num >= + static_cast<int32_t>(gif_image->image_info.height)) { + img_pass_num_++; + if (img_pass_num_ == FX_ArraySize(s_gif_interlace_step)) { + DecodingFailureAtTailCleanup(gif_image); + return CFX_GifDecodeStatus::Error; + } + gif_image->row_num = s_gif_interlace_step[img_pass_num_] / 2; + } + } else { + ReadScanline(gif_image->row_num++, gif_image->row_buffer.data()); + } + img_row_offset_ = 0; + img_row_avail_size_ = gif_img_row_bytes; + ret = lzw_decompressor_.get() + ? lzw_decompressor_->Decode( + img_data, *img_data_size, + gif_image->row_buffer.data() + img_row_offset_, + &img_row_avail_size_) + : CFX_GifDecodeStatus::Error; + } + if (ret == CFX_GifDecodeStatus::Error) { + DecodingFailureAtTailCleanup(gif_image); + return CFX_GifDecodeStatus::Error; + } + } + } + SaveDecodingStatus(GIF_D_STATUS_TAIL); + } + return CFX_GifDecodeStatus::Error; +} + +void CFX_GifContext::SetInputBuffer(uint8_t* src_buf, uint32_t src_size) { + next_in_ = src_buf; + avail_in_ = src_size; + skip_size_ = 0; +} + +uint32_t CFX_GifContext::GetAvailInput(uint8_t** avail_buf) const { + if (avail_buf) { + *avail_buf = nullptr; + if (avail_in_ > 0) + *avail_buf = next_in_; + } + return avail_in_; +} + +int32_t CFX_GifContext::GetFrameNum() const { + return pdfium::CollectionSize<int32_t>(images_); +} + +uint8_t* CFX_GifContext::ReadData(uint8_t** des_buf_pp, uint32_t data_size) { + if (avail_in_ < skip_size_ + data_size) + return nullptr; + + *des_buf_pp = next_in_ + skip_size_; + skip_size_ += data_size; + return *des_buf_pp; +} + +void CFX_GifContext::SaveDecodingStatus(int32_t status) { + decode_status_ = status; + next_in_ += skip_size_; + avail_in_ -= skip_size_; + skip_size_ = 0; +} + +CFX_GifDecodeStatus CFX_GifContext::DecodeExtension() { + uint8_t* data_size = nullptr; + uint8_t* data_buf = nullptr; + uint32_t skip_size_org = skip_size_; + switch (decode_status_) { + case GIF_D_STATUS_EXT_CE: { + if (!ReadData(&data_size, 1)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + cmt_data_.clear(); + while (*data_size != GIF_BLOCK_TERMINAL) { + uint8_t block_size = *data_size; + if (!ReadData(&data_buf, *data_size) || !ReadData(&data_size, 1)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + cmt_data_ += ByteString(data_buf, block_size); + } + break; + } + case GIF_D_STATUS_EXT_PTE: { + CFX_GifPlainTextExtension* gif_pte = nullptr; + if (!ReadData(reinterpret_cast<uint8_t**>(&gif_pte), 13)) + return CFX_GifDecodeStatus::Unfinished; + + graphic_control_extension_ = nullptr; + if (!ReadData(&data_size, 1)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + while (*data_size != GIF_BLOCK_TERMINAL) { + if (!ReadData(&data_buf, *data_size) || !ReadData(&data_size, 1)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + } + break; + } + case GIF_D_STATUS_EXT_GCE: { + CFX_GifGraphicControlExtension* gif_gce = nullptr; + if (!ReadData(reinterpret_cast<uint8_t**>(&gif_gce), 6)) + return CFX_GifDecodeStatus::Unfinished; + + if (!graphic_control_extension_.get()) + graphic_control_extension_ = + pdfium::MakeUnique<CFX_GifGraphicControlExtension>(); + graphic_control_extension_->block_size = gif_gce->block_size; + graphic_control_extension_->gce_flags = gif_gce->gce_flags; + graphic_control_extension_->delay_time = + GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_gce->delay_time)); + graphic_control_extension_->trans_index = gif_gce->trans_index; + break; + } + default: { + if (decode_status_ == GIF_D_STATUS_EXT_PTE) + graphic_control_extension_ = nullptr; + if (!ReadData(&data_size, 1)) + return CFX_GifDecodeStatus::Unfinished; + + while (*data_size != GIF_BLOCK_TERMINAL) { + if (!ReadData(&data_buf, *data_size) || !ReadData(&data_size, 1)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + } + } + } + SaveDecodingStatus(GIF_D_STATUS_SIG); + return CFX_GifDecodeStatus::Success; +} + +CFX_GifDecodeStatus CFX_GifContext::DecodeImageInfo() { + if (width_ <= 0 || height_ <= 0) + return CFX_GifDecodeStatus::Error; + + uint32_t skip_size_org = skip_size_; + CFX_CFX_GifImageInfo* img_info = nullptr; + if (!ReadData(reinterpret_cast<uint8_t**>(&img_info), 9)) + return CFX_GifDecodeStatus::Unfinished; + + auto gif_image = pdfium::MakeUnique<CFX_GifImage>(); + gif_image->image_info.left = + GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&img_info->left)); + gif_image->image_info.top = + GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&img_info->top)); + gif_image->image_info.width = + GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&img_info->width)); + gif_image->image_info.height = + GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&img_info->height)); + gif_image->image_info.local_flags = img_info->local_flags; + if (gif_image->image_info.left + gif_image->image_info.width > width_ || + gif_image->image_info.top + gif_image->image_info.height > height_) + return CFX_GifDecodeStatus::Error; + + CFX_GifLocalFlags* gif_img_info_lf = &img_info->local_flags; + if (gif_img_info_lf->local_pal) { + gif_image->local_pallette_exp = gif_img_info_lf->pal_bits; + uint32_t loc_pal_size = unsigned(2 << gif_img_info_lf->pal_bits) * 3u; + uint8_t* loc_pal = nullptr; + if (!ReadData(&loc_pal, loc_pal_size)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + gif_image->local_palettes = std::vector<CFX_GifPalette>(loc_pal_size / 3); + std::copy(loc_pal, loc_pal + loc_pal_size, + reinterpret_cast<uint8_t*>(gif_image->local_palettes.data())); + } + + uint8_t* code_size = nullptr; + if (!ReadData(&code_size, 1)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + gif_image->code_exp = *code_size; + RecordCurrentPosition(&gif_image->data_pos); + gif_image->data_pos += skip_size_; + gif_image->image_GCE = nullptr; + if (graphic_control_extension_.get()) { + gif_image->image_GCE = std::move(graphic_control_extension_); + graphic_control_extension_ = nullptr; + } + images_.push_back(std::move(gif_image)); + SaveDecodingStatus(GIF_D_STATUS_IMG_DATA); + return CFX_GifDecodeStatus::Success; +} + +void CFX_GifContext::DecodingFailureAtTailCleanup(CFX_GifImage* gif_image) { + gif_image->row_buffer.clear(); + SaveDecodingStatus(GIF_D_STATUS_TAIL); +} diff --git a/core/fxcodec/gif/cfx_gifcontext.h b/core/fxcodec/gif/cfx_gifcontext.h new file mode 100644 index 0000000000..a1cffb2746 --- /dev/null +++ b/core/fxcodec/gif/cfx_gifcontext.h @@ -0,0 +1,76 @@ +// 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_GIF_CFX_GIFCONTEXT_H_ +#define CORE_FXCODEC_GIF_CFX_GIFCONTEXT_H_ + +#include <memory> +#include <vector> + +#include "core/fxcodec/codec/ccodec_gifmodule.h" +#include "core/fxcodec/gif/cfx_gif.h" +#include "core/fxcodec/gif/cfx_lzwdecompressor.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/unowned_ptr.h" + +class CFX_GifContext : public CCodec_GifModule::Context { + public: + CFX_GifContext(CCodec_GifModule* gif_module, + CCodec_GifModule::Delegate* delegate); + ~CFX_GifContext() override; + + void RecordCurrentPosition(uint32_t* cur_pos); + 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, + CFX_GifPalette* pal, + int32_t delay_time, + bool user_input, + int32_t trans_index, + int32_t disposal_method, + bool interlace); + CFX_GifDecodeStatus ReadHeader(); + CFX_GifDecodeStatus GetFrame(); + CFX_GifDecodeStatus LoadFrame(int32_t frame_num); + void SetInputBuffer(uint8_t* src_buf, uint32_t src_size); + uint32_t GetAvailInput(uint8_t** avail_buf) const; + int32_t GetFrameNum() const; + + UnownedPtr<CCodec_GifModule> gif_module_; + UnownedPtr<CCodec_GifModule::Delegate> delegate_; + std::vector<CFX_GifPalette> global_palette_; + uint8_t global_pal_exp_; + uint32_t img_row_offset_; + uint32_t img_row_avail_size_; + uint32_t avail_in_; + int32_t decode_status_; + uint32_t skip_size_; + ByteString cmt_data_; + std::unique_ptr<CFX_GifGraphicControlExtension> graphic_control_extension_; + uint8_t* next_in_; + std::vector<std::unique_ptr<CFX_GifImage>> images_; + std::unique_ptr<CFX_LZWDecompressor> lzw_decompressor_; + 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_; + + private: + uint8_t* ReadData(uint8_t** des_buf_pp, uint32_t data_size); + void SaveDecodingStatus(int32_t status); + CFX_GifDecodeStatus DecodeExtension(); + CFX_GifDecodeStatus DecodeImageInfo(); + void DecodingFailureAtTailCleanup(CFX_GifImage* gif_image); +}; + +#endif // CORE_FXCODEC_GIF_CFX_GIFCONTEXT_H_ diff --git a/core/fxcodec/lgif/cfx_lzwdecoder.cpp b/core/fxcodec/gif/cfx_lzwdecompressor.cpp index 9479eeafaa..27e36b12e9 100644 --- a/core/fxcodec/lgif/cfx_lzwdecoder.cpp +++ b/core/fxcodec/gif/cfx_lzwdecompressor.cpp @@ -4,7 +4,7 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "core/fxcodec/lgif/cfx_lzwdecoder.h" +#include "core/fxcodec/gif/cfx_lzwdecompressor.h" #include <algorithm> #include <memory> @@ -15,15 +15,16 @@ #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" -std::unique_ptr<CFX_LZWDecoder> CFX_LZWDecoder::Create(uint8_t color_exp, - uint8_t code_exp) { +std::unique_ptr<CFX_LZWDecompressor> CFX_LZWDecompressor::Create( + uint8_t color_exp, + uint8_t code_exp) { if (code_exp > GIF_MAX_LZW_EXP || code_exp + 1 < color_exp) return nullptr; - return std::unique_ptr<CFX_LZWDecoder>( - new CFX_LZWDecoder(color_exp, code_exp)); + return std::unique_ptr<CFX_LZWDecompressor>( + new CFX_LZWDecompressor(color_exp, code_exp)); } -CFX_LZWDecoder::CFX_LZWDecoder(uint8_t color_exp, uint8_t code_exp) +CFX_LZWDecompressor::CFX_LZWDecompressor(uint8_t color_exp, uint8_t code_exp) : code_size_(code_exp), code_size_cur_(0), code_color_end_(static_cast<uint16_t>(2 << color_exp)), @@ -38,17 +39,17 @@ CFX_LZWDecoder::CFX_LZWDecoder(uint8_t color_exp, uint8_t code_exp) bits_left_(0), code_store_(0) {} -CFX_LZWDecoder::~CFX_LZWDecoder() {} +CFX_LZWDecompressor::~CFX_LZWDecompressor() {} -GifDecodeStatus CFX_LZWDecoder::Decode(uint8_t* src_buf, - uint32_t src_size, - uint8_t* des_buf, - uint32_t* des_size) { +CFX_GifDecodeStatus CFX_LZWDecompressor::Decode(uint8_t* src_buf, + uint32_t src_size, + uint8_t* des_buf, + uint32_t* des_size) { if (!src_buf || src_size == 0 || !des_buf || !des_size) - return GifDecodeStatus::Error; + return CFX_GifDecodeStatus::Error; if (*des_size == 0) - return GifDecodeStatus::InsufficientDestSize; + return CFX_GifDecodeStatus::InsufficientDestSize; next_in_ = src_buf; avail_in_ = src_size; @@ -60,7 +61,7 @@ GifDecodeStatus CFX_LZWDecoder::Decode(uint8_t* src_buf, if (*des_size < stack_size_) { memcpy(des_buf, &stack_[GIF_MAX_LZW_CODE - stack_size_], *des_size); stack_size_ -= static_cast<uint16_t>(*des_size); - return GifDecodeStatus::InsufficientDestSize; + return CFX_GifDecodeStatus::InsufficientDestSize; } memcpy(des_buf, &stack_[GIF_MAX_LZW_CODE - stack_size_], stack_size_); @@ -71,17 +72,17 @@ GifDecodeStatus CFX_LZWDecoder::Decode(uint8_t* src_buf, while (i <= *des_size && (avail_in_ > 0 || bits_left_ >= code_size_cur_)) { if (code_size_cur_ > GIF_MAX_LZW_EXP) - return GifDecodeStatus::Error; + return CFX_GifDecodeStatus::Error; if (avail_in_ > 0) { if (bits_left_ > 31) - return GifDecodeStatus::Error; + return CFX_GifDecodeStatus::Error; pdfium::base::CheckedNumeric<uint32_t> safe_code = *next_in_++; safe_code <<= bits_left_; safe_code |= code_store_; if (!safe_code.IsValid()) - return GifDecodeStatus::Error; + return CFX_GifDecodeStatus::Error; code_store_ = safe_code.ValueOrDie(); --avail_in_; @@ -99,7 +100,7 @@ GifDecodeStatus CFX_LZWDecoder::Decode(uint8_t* src_buf, } if (code == code_end_) { *des_size = i; - return GifDecodeStatus::Success; + return CFX_GifDecodeStatus::Success; } if (code_old_ != static_cast<uint16_t>(-1)) { @@ -107,12 +108,12 @@ GifDecodeStatus CFX_LZWDecoder::Decode(uint8_t* src_buf, if (code == code_next_) { AddCode(code_old_, code_first_); if (!DecodeString(code)) - return GifDecodeStatus::Error; + return CFX_GifDecodeStatus::Error; } else if (code > code_next_) { - return GifDecodeStatus::Error; + return CFX_GifDecodeStatus::Error; } else { if (!DecodeString(code)) - return GifDecodeStatus::Error; + return CFX_GifDecodeStatus::Error; uint8_t append_char = stack_[GIF_MAX_LZW_CODE - stack_size_]; AddCode(code_old_, append_char); @@ -120,14 +121,14 @@ GifDecodeStatus CFX_LZWDecoder::Decode(uint8_t* src_buf, } } else { if (!DecodeString(code)) - return GifDecodeStatus::Error; + return CFX_GifDecodeStatus::Error; } code_old_ = code; if (i + stack_size_ > *des_size) { memcpy(des_buf, &stack_[GIF_MAX_LZW_CODE - stack_size_], *des_size - i); stack_size_ -= static_cast<uint16_t>(*des_size - i); - return GifDecodeStatus::InsufficientDestSize; + return CFX_GifDecodeStatus::InsufficientDestSize; } memcpy(des_buf, &stack_[GIF_MAX_LZW_CODE - stack_size_], stack_size_); @@ -138,13 +139,13 @@ GifDecodeStatus CFX_LZWDecoder::Decode(uint8_t* src_buf, } if (avail_in_ != 0) - return GifDecodeStatus::Error; + return CFX_GifDecodeStatus::Error; *des_size = i; - return GifDecodeStatus::Unfinished; + return CFX_GifDecodeStatus::Unfinished; } -void CFX_LZWDecoder::ClearTable() { +void CFX_LZWDecompressor::ClearTable() { code_size_cur_ = code_size_ + 1; code_next_ = code_end_ + 1; code_old_ = static_cast<uint16_t>(-1); @@ -154,7 +155,7 @@ void CFX_LZWDecoder::ClearTable() { code_table_[i].suffix = static_cast<uint8_t>(i); } -void CFX_LZWDecoder::AddCode(uint16_t prefix_code, uint8_t append_char) { +void CFX_LZWDecompressor::AddCode(uint16_t prefix_code, uint8_t append_char) { if (code_next_ == GIF_MAX_LZW_CODE) return; @@ -166,7 +167,7 @@ void CFX_LZWDecoder::AddCode(uint16_t prefix_code, uint8_t append_char) { } } -bool CFX_LZWDecoder::DecodeString(uint16_t code) { +bool CFX_LZWDecompressor::DecodeString(uint16_t code) { stack_size_ = 0; while (code >= code_clear_ && code <= code_next_) { if (code == code_table_[code].prefix || stack_size_ == GIF_MAX_LZW_CODE - 1) diff --git a/core/fxcodec/lgif/cfx_lzwdecoder.h b/core/fxcodec/gif/cfx_lzwdecompressor.h index 9dbf15d9b7..10c0a566d7 100644 --- a/core/fxcodec/lgif/cfx_lzwdecoder.h +++ b/core/fxcodec/gif/cfx_lzwdecompressor.h @@ -4,15 +4,15 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#ifndef CORE_FXCODEC_LGIF_CFX_LZWDECODER_H_ -#define CORE_FXCODEC_LGIF_CFX_LZWDECODER_H_ +#ifndef CORE_FXCODEC_GIF_CFX_LZWDECOMPRESSOR_H_ +#define CORE_FXCODEC_GIF_CFX_LZWDECOMPRESSOR_H_ #include <memory> #include <vector> -#include "core/fxcodec/lgif/fx_gif.h" +#include "core/fxcodec/gif/cfx_gif.h" -class CFX_LZWDecoder { +class CFX_LZWDecompressor { public: typedef struct { uint16_t prefix; @@ -20,17 +20,17 @@ class CFX_LZWDecoder { } CodeEntry; // Returns nullptr on error - static std::unique_ptr<CFX_LZWDecoder> Create(uint8_t color_exp, - uint8_t code_exp); - ~CFX_LZWDecoder(); + static std::unique_ptr<CFX_LZWDecompressor> Create(uint8_t color_exp, + uint8_t code_exp); + ~CFX_LZWDecompressor(); - GifDecodeStatus Decode(uint8_t* src_buf, - uint32_t src_size, - uint8_t* des_buf, - uint32_t* des_size); + CFX_GifDecodeStatus Decode(uint8_t* src_buf, + uint32_t src_size, + uint8_t* des_buf, + uint32_t* des_size); private: - CFX_LZWDecoder(uint8_t color_exp, uint8_t code_exp); + CFX_LZWDecompressor(uint8_t color_exp, uint8_t code_exp); void ClearTable(); void AddCode(uint16_t prefix_code, uint8_t append_char); bool DecodeString(uint16_t code); @@ -52,4 +52,4 @@ class CFX_LZWDecoder { uint32_t code_store_; }; -#endif // CORE_FXCODEC_LGIF_CFX_LZWDECODER_H_ +#endif // CORE_FXCODEC_GIF_CFX_LZWDECOMPRESSOR_H_ diff --git a/core/fxcodec/lgif/cfx_lzwdecoder_unittest.cpp b/core/fxcodec/gif/cfx_lzwdecompressor_unittest.cpp index 9e4b7b788e..cc3ce6367d 100644 --- a/core/fxcodec/lgif/cfx_lzwdecoder_unittest.cpp +++ b/core/fxcodec/gif/cfx_lzwdecompressor_unittest.cpp @@ -2,21 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "core/fxcodec/lgif/cfx_lzwdecoder.h" +#include "core/fxcodec/gif/cfx_lzwdecompressor.h" #include "core/fxcrt/fx_memory.h" #include "testing/gtest/include/gtest/gtest.h" -TEST(CFX_LZWDecoder, CreateBadParams) { - EXPECT_EQ(nullptr, CFX_LZWDecoder::Create(0x10, 0x2)); - EXPECT_EQ(nullptr, CFX_LZWDecoder::Create(0x4, 0x0F)); +TEST(CFX_LZWDecompressor, CreateBadParams) { + EXPECT_EQ(nullptr, CFX_LZWDecompressor::Create(0x10, 0x2)); + EXPECT_EQ(nullptr, CFX_LZWDecompressor::Create(0x4, 0x0F)); } -TEST(CFX_LZWDecoder, DecodeBadParams) { +TEST(CFX_LZWDecompressor, DecodeBadParams) { uint8_t palette_exp = 0x0; uint8_t code_exp = 0x2; - auto decoder = CFX_LZWDecoder::Create(palette_exp, code_exp); + auto decoder = CFX_LZWDecompressor::Create(palette_exp, code_exp); ASSERT_NE(nullptr, decoder); uint8_t image_data[10]; @@ -25,25 +25,25 @@ TEST(CFX_LZWDecoder, DecodeBadParams) { uint8_t output_data[10]; uint32_t output_size = FX_ArraySize(output_data); - EXPECT_EQ(GifDecodeStatus::Error, + EXPECT_EQ(CFX_GifDecodeStatus::Error, decoder->Decode(nullptr, image_size, output_data, &output_size)); - EXPECT_EQ(GifDecodeStatus::Error, + EXPECT_EQ(CFX_GifDecodeStatus::Error, decoder->Decode(image_data, 0, output_data, &output_size)); - EXPECT_EQ(GifDecodeStatus::Error, + EXPECT_EQ(CFX_GifDecodeStatus::Error, decoder->Decode(image_data, image_size, nullptr, &output_size)); - EXPECT_EQ(GifDecodeStatus::Error, + EXPECT_EQ(CFX_GifDecodeStatus::Error, decoder->Decode(image_data, image_size, output_data, nullptr)); output_size = 0; - EXPECT_EQ(GifDecodeStatus::InsufficientDestSize, + EXPECT_EQ(CFX_GifDecodeStatus::InsufficientDestSize, decoder->Decode(image_data, image_size, output_data, &output_size)); } -TEST(CFX_LZWDecoder, Decode1x1SingleColour) { +TEST(CFX_LZWDecompressor, Decode1x1SingleColour) { uint8_t palette_exp = 0x0; uint8_t code_exp = 0x2; - auto decoder = CFX_LZWDecoder::Create(palette_exp, code_exp); + auto decoder = CFX_LZWDecompressor::Create(palette_exp, code_exp); ASSERT_NE(nullptr, decoder); uint8_t image_data[] = {0x44, 0x01}; @@ -52,7 +52,7 @@ TEST(CFX_LZWDecoder, Decode1x1SingleColour) { uint8_t output_data[1]; uint32_t output_size = FX_ArraySize(output_data); - EXPECT_EQ(GifDecodeStatus::Success, + EXPECT_EQ(CFX_GifDecodeStatus::Success, decoder->Decode(image_data, image_size, output_data, &output_size)); uint8_t expected_data[] = {0x00}; @@ -60,11 +60,11 @@ TEST(CFX_LZWDecoder, Decode1x1SingleColour) { EXPECT_TRUE(0 == memcmp(expected_data, output_data, sizeof(expected_data))); } -TEST(CFX_LZWDecoder, Decode10x10SingleColour) { +TEST(CFX_LZWDecompressor, Decode10x10SingleColour) { uint8_t palette_exp = 0x0; uint8_t code_exp = 0x2; - auto decoder = CFX_LZWDecoder::Create(palette_exp, code_exp); + auto decoder = CFX_LZWDecompressor::Create(palette_exp, code_exp); ASSERT_NE(nullptr, decoder); uint8_t image_data[] = {0x84, 0x8F, 0xA9, 0xCB, 0xED, 0x0F, 0x63, 0x2B}; @@ -74,7 +74,7 @@ TEST(CFX_LZWDecoder, Decode10x10SingleColour) { memset(output_data, 0, sizeof(output_data)); uint32_t output_size = FX_ArraySize(output_data); - EXPECT_EQ(GifDecodeStatus::Success, + EXPECT_EQ(CFX_GifDecodeStatus::Success, decoder->Decode(image_data, image_size, output_data, &output_size)); uint8_t expected_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -91,11 +91,11 @@ TEST(CFX_LZWDecoder, Decode10x10SingleColour) { EXPECT_TRUE(0 == memcmp(expected_data, output_data, sizeof(expected_data))); } -TEST(CFX_LZWDecoder, Decode10x10MultipleColour) { +TEST(CFX_LZWDecompressor, Decode10x10MultipleColour) { uint8_t palette_exp = 0x1; uint8_t code_exp = 0x2; - auto decoder = CFX_LZWDecoder::Create(palette_exp, code_exp); + auto decoder = CFX_LZWDecompressor::Create(palette_exp, code_exp); ASSERT_NE(nullptr, decoder); uint8_t image_data[] = {0x8C, 0x2D, 0x99, 0x87, 0x2A, 0x1C, 0xDC, 0x33, @@ -107,7 +107,7 @@ TEST(CFX_LZWDecoder, Decode10x10MultipleColour) { memset(output_data, 0, sizeof(output_data)); uint32_t output_size = FX_ArraySize(output_data); - EXPECT_EQ(GifDecodeStatus::Success, + EXPECT_EQ(CFX_GifDecodeStatus::Success, decoder->Decode(image_data, image_size, output_data, &output_size)); uint8_t expected_data[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, @@ -124,12 +124,12 @@ TEST(CFX_LZWDecoder, Decode10x10MultipleColour) { EXPECT_TRUE(0 == memcmp(expected_data, output_data, sizeof(expected_data))); } -TEST(CFX_LZWDecoder, HandleColourCodeOutOfPalette) { +TEST(CFX_LZWDecompressor, HandleColourCodeOutOfPalette) { uint8_t palette_exp = 0x2; // Image uses 10 colours, so the palette exp // should be 3, 2^(3+1) = 16 colours. uint8_t code_exp = 0x4; - auto decoder = CFX_LZWDecoder::Create(palette_exp, code_exp); + auto decoder = CFX_LZWDecompressor::Create(palette_exp, code_exp); ASSERT_NE(nullptr, decoder); uint8_t image_data[] = {0x30, 0xC9, 0x49, 0x81, 0xBD, 0x78, 0xE8, 0xCD, @@ -142,6 +142,6 @@ TEST(CFX_LZWDecoder, HandleColourCodeOutOfPalette) { memset(output_data, 0, sizeof(output_data)); uint32_t output_size = FX_ArraySize(output_data); - EXPECT_EQ(GifDecodeStatus::Error, + EXPECT_EQ(CFX_GifDecodeStatus::Error, decoder->Decode(image_data, image_size, output_data, &output_size)); } diff --git a/core/fxcodec/lgif/cgifcontext.cpp b/core/fxcodec/lgif/cgifcontext.cpp deleted file mode 100644 index af1895316f..0000000000 --- a/core/fxcodec/lgif/cgifcontext.cpp +++ /dev/null @@ -1,549 +0,0 @@ -// 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/cgifcontext.h" - -#include <algorithm> -#include <utility> - -#include "core/fxcodec/codec/ccodec_gifmodule.h" -#include "core/fxcodec/lbmp/fx_bmp.h" -#include "core/fxcodec/lgif/fx_gif.h" -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" - -namespace { - -const int32_t s_gif_interlace_step[4] = {8, 8, 4, 2}; - -} // namespace - -CGifContext::CGifContext(CCodec_GifModule* gif_module, - CCodec_GifModule::Delegate* pDelegate) - : m_pModule(gif_module), - m_pDelegate(pDelegate), - global_pal_exp(0), - img_row_offset(0), - img_row_avail_size(0), - avail_in(0), - decode_status(GIF_D_STATUS_SIG), - skip_size(0), - next_in(nullptr), - width(0), - height(0), - bc_index(0), - pixel_aspect(0), - global_sort_flag(0), - global_color_resolution(0), - img_pass_num(0) { -} - -CGifContext::~CGifContext() {} - -void CGifContext::RecordCurrentPosition(uint32_t* cur_pos_ptr) { - m_pDelegate->GifRecordCurrentPosition(*cur_pos_ptr); -} - -void CGifContext::ReadScanline(int32_t row_num, uint8_t* row_buf) { - m_pDelegate->GifReadScanline(row_num, row_buf); -} - -bool CGifContext::GetRecordPosition(uint32_t cur_pos, - int32_t left, - int32_t top, - int32_t width, - int32_t height, - int32_t pal_num, - GifPalette* pal_ptr, - int32_t delay_time, - bool user_input, - int32_t trans_index, - int32_t disposal_method, - bool interlace) { - return m_pDelegate->GifInputRecordPositionBuf( - cur_pos, FX_RECT(left, top, left + width, top + height), pal_num, pal_ptr, - delay_time, user_input, trans_index, disposal_method, interlace); -} - -GifDecodeStatus CGifContext::ReadHeader() { - uint32_t skip_size_org = skip_size; - GifHeader* gif_header_ptr = nullptr; - if (!ReadData(reinterpret_cast<uint8_t**>(&gif_header_ptr), 6)) - return GifDecodeStatus::Unfinished; - - if (strncmp(gif_header_ptr->signature, GIF_SIGNATURE, 3) != 0 || - gif_header_ptr->version[0] != '8' || gif_header_ptr->version[2] != 'a') - return GifDecodeStatus::Error; - - GifLocalScreenDescriptor* gif_lsd_ptr = nullptr; - if (!ReadData(reinterpret_cast<uint8_t**>(&gif_lsd_ptr), 7)) { - skip_size = skip_size_org; - return GifDecodeStatus::Unfinished; - } - - if (gif_lsd_ptr->global_flags.global_pal) { - global_pal_exp = gif_lsd_ptr->global_flags.pal_bits; - uint32_t global_pal_size = unsigned(2 << global_pal_exp) * 3u; - uint8_t* global_pal_ptr = nullptr; - if (!ReadData(&global_pal_ptr, global_pal_size)) { - skip_size = skip_size_org; - return GifDecodeStatus::Unfinished; - } - - global_sort_flag = gif_lsd_ptr->global_flags.sort_flag; - global_color_resolution = gif_lsd_ptr->global_flags.color_resolution; - m_GlobalPalette.resize(global_pal_size / 3); - memcpy(m_GlobalPalette.data(), global_pal_ptr, global_pal_size); - } - - width = static_cast<int>( - GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_lsd_ptr->width))); - height = static_cast<int>( - GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_lsd_ptr->height))); - bc_index = gif_lsd_ptr->bc_index; - pixel_aspect = gif_lsd_ptr->pixel_aspect; - return GifDecodeStatus::Success; -} - -GifDecodeStatus CGifContext::GetFrame() { - GifDecodeStatus ret = GifDecodeStatus::Success; - while (true) { - switch (decode_status) { - case GIF_D_STATUS_TAIL: - return GifDecodeStatus::Success; - case GIF_D_STATUS_SIG: { - uint8_t* sig_ptr = nullptr; - if (!ReadData(&sig_ptr, 1)) - return GifDecodeStatus::Unfinished; - - switch (*sig_ptr) { - case GIF_SIG_EXTENSION: - SaveDecodingStatus(GIF_D_STATUS_EXT); - continue; - case GIF_SIG_IMAGE: - SaveDecodingStatus(GIF_D_STATUS_IMG_INFO); - continue; - case GIF_SIG_TRAILER: - SaveDecodingStatus(GIF_D_STATUS_TAIL); - return GifDecodeStatus::Success; - default: - if (avail_in) { - // The Gif File has non_standard Tag! - SaveDecodingStatus(GIF_D_STATUS_SIG); - continue; - } - // The Gif File Doesn't have Trailer Tag! - return GifDecodeStatus::Success; - } - } - case GIF_D_STATUS_EXT: { - uint8_t* ext_ptr = nullptr; - if (!ReadData(&ext_ptr, 1)) - return GifDecodeStatus::Unfinished; - - switch (*ext_ptr) { - case GIF_BLOCK_CE: - SaveDecodingStatus(GIF_D_STATUS_EXT_CE); - continue; - case GIF_BLOCK_GCE: - SaveDecodingStatus(GIF_D_STATUS_EXT_GCE); - continue; - case GIF_BLOCK_PTE: - SaveDecodingStatus(GIF_D_STATUS_EXT_PTE); - continue; - default: { - int32_t status = GIF_D_STATUS_EXT_UNE; - if (*ext_ptr == GIF_BLOCK_PTE) { - status = GIF_D_STATUS_EXT_PTE; - } - SaveDecodingStatus(status); - continue; - } - } - } - case GIF_D_STATUS_IMG_INFO: { - ret = DecodeImageInfo(); - if (ret != GifDecodeStatus::Success) - return ret; - - continue; - } - case GIF_D_STATUS_IMG_DATA: { - uint8_t* data_size_ptr = nullptr; - uint8_t* data_ptr = nullptr; - uint32_t skip_size_org = skip_size; - if (!ReadData(&data_size_ptr, 1)) - return GifDecodeStatus::Unfinished; - - while (*data_size_ptr != GIF_BLOCK_TERMINAL) { - if (!ReadData(&data_ptr, *data_size_ptr)) { - skip_size = skip_size_org; - return GifDecodeStatus::Unfinished; - } - - SaveDecodingStatus(GIF_D_STATUS_IMG_DATA); - skip_size_org = skip_size; - if (!ReadData(&data_size_ptr, 1)) - return GifDecodeStatus::Unfinished; - } - SaveDecodingStatus(GIF_D_STATUS_SIG); - continue; - } - default: { - ret = DecodeExtension(); - if (ret != GifDecodeStatus::Success) - return ret; - break; - } - } - } - return GifDecodeStatus::Success; -} - -GifDecodeStatus CGifContext::LoadFrame(int32_t frame_num) { - if (!pdfium::IndexInBounds(m_Images, frame_num)) - return GifDecodeStatus::Error; - - uint8_t* data_size_ptr = nullptr; - uint8_t* data_ptr = nullptr; - uint32_t skip_size_org = skip_size; - GifImage* gif_image_ptr = m_Images[frame_num].get(); - uint32_t gif_img_row_bytes = gif_image_ptr->m_ImageInfo.width; - if (gif_img_row_bytes == 0) - return GifDecodeStatus::Error; - - if (decode_status == GIF_D_STATUS_TAIL) { - gif_image_ptr->m_ImageRowBuf.resize(gif_img_row_bytes); - GifGraphicControlExtension* gif_img_gce_ptr = - gif_image_ptr->m_ImageGCE.get(); - int32_t loc_pal_num = - gif_image_ptr->m_ImageInfo.local_flags.local_pal - ? (2 << gif_image_ptr->m_ImageInfo.local_flags.pal_bits) - : 0; - avail_in = 0; - GifPalette* pLocalPalette = gif_image_ptr->m_LocalPalettes.empty() - ? nullptr - : gif_image_ptr->m_LocalPalettes.data(); - if (!gif_img_gce_ptr) { - bool bRes = GetRecordPosition( - 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, pLocalPalette, 0, 0, - -1, 0, gif_image_ptr->m_ImageInfo.local_flags.interlace); - if (!bRes) { - gif_image_ptr->m_ImageRowBuf.clear(); - return GifDecodeStatus::Error; - } - } else { - bool bRes = GetRecordPosition( - 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, pLocalPalette, - static_cast<int32_t>(gif_image_ptr->m_ImageGCE->delay_time), - gif_image_ptr->m_ImageGCE->gce_flags.user_input, - gif_image_ptr->m_ImageGCE->gce_flags.transparency - ? static_cast<int32_t>(gif_image_ptr->m_ImageGCE->trans_index) - : -1, - static_cast<int32_t>( - gif_image_ptr->m_ImageGCE->gce_flags.disposal_method), - gif_image_ptr->m_ImageInfo.local_flags.interlace); - if (!bRes) { - gif_image_ptr->m_ImageRowBuf.clear(); - return GifDecodeStatus::Error; - } - } - - if (gif_image_ptr->image_code_exp > GIF_MAX_LZW_EXP) { - gif_image_ptr->m_ImageRowBuf.clear(); - return GifDecodeStatus::Error; - } - - img_row_offset = 0; - img_row_avail_size = 0; - img_pass_num = 0; - gif_image_ptr->image_row_num = 0; - SaveDecodingStatus(GIF_D_STATUS_IMG_DATA); - } - - if (decode_status == GIF_D_STATUS_IMG_DATA) { - if (!ReadData(&data_size_ptr, 1)) - return GifDecodeStatus::Unfinished; - - if (*data_size_ptr != GIF_BLOCK_TERMINAL) { - if (!ReadData(&data_ptr, *data_size_ptr)) { - skip_size = skip_size_org; - return GifDecodeStatus::Unfinished; - } - - if (!m_ImgDecoder.get()) - m_ImgDecoder = - CFX_LZWDecoder::Create(!gif_image_ptr->m_LocalPalettes.empty() - ? gif_image_ptr->local_pallette_exp - : global_pal_exp, - gif_image_ptr->image_code_exp); - SaveDecodingStatus(GIF_D_STATUS_IMG_DATA); - img_row_offset += img_row_avail_size; - img_row_avail_size = gif_img_row_bytes - img_row_offset; - GifDecodeStatus ret = - m_ImgDecoder.get() - ? m_ImgDecoder->Decode( - data_ptr, *data_size_ptr, - gif_image_ptr->m_ImageRowBuf.data() + img_row_offset, - &img_row_avail_size) - : GifDecodeStatus::Error; - if (ret == GifDecodeStatus::Error) { - DecodingFailureAtTailCleanup(gif_image_ptr); - return GifDecodeStatus::Error; - } - while (ret != GifDecodeStatus::Error) { - if (ret == GifDecodeStatus::Success) { - ReadScanline(gif_image_ptr->image_row_num, - gif_image_ptr->m_ImageRowBuf.data()); - gif_image_ptr->m_ImageRowBuf.clear(); - SaveDecodingStatus(GIF_D_STATUS_TAIL); - return GifDecodeStatus::Success; - } - if (ret == GifDecodeStatus::Unfinished) { - skip_size_org = skip_size; - if (!ReadData(&data_size_ptr, 1)) - return GifDecodeStatus::Unfinished; - - if (*data_size_ptr != GIF_BLOCK_TERMINAL) { - if (!ReadData(&data_ptr, *data_size_ptr)) { - skip_size = skip_size_org; - return GifDecodeStatus::Unfinished; - } - if (!m_ImgDecoder.get()) - m_ImgDecoder = - CFX_LZWDecoder::Create(!gif_image_ptr->m_LocalPalettes.empty() - ? gif_image_ptr->local_pallette_exp - : global_pal_exp, - gif_image_ptr->image_code_exp); - SaveDecodingStatus(GIF_D_STATUS_IMG_DATA); - img_row_offset += img_row_avail_size; - img_row_avail_size = gif_img_row_bytes - img_row_offset; - ret = - m_ImgDecoder.get() - ? m_ImgDecoder->Decode( - data_ptr, *data_size_ptr, - gif_image_ptr->m_ImageRowBuf.data() + img_row_offset, - &img_row_avail_size) - : GifDecodeStatus::Error; - } - } - if (ret == GifDecodeStatus::InsufficientDestSize) { - if (gif_image_ptr->m_ImageInfo.local_flags.interlace) { - ReadScanline(gif_image_ptr->image_row_num, - gif_image_ptr->m_ImageRowBuf.data()); - gif_image_ptr->image_row_num += s_gif_interlace_step[img_pass_num]; - if (gif_image_ptr->image_row_num >= - static_cast<int32_t>(gif_image_ptr->m_ImageInfo.height)) { - img_pass_num++; - if (img_pass_num == FX_ArraySize(s_gif_interlace_step)) { - DecodingFailureAtTailCleanup(gif_image_ptr); - return GifDecodeStatus::Error; - } - gif_image_ptr->image_row_num = - s_gif_interlace_step[img_pass_num] / 2; - } - } else { - ReadScanline(gif_image_ptr->image_row_num++, - gif_image_ptr->m_ImageRowBuf.data()); - } - img_row_offset = 0; - img_row_avail_size = gif_img_row_bytes; - ret = m_ImgDecoder.get() - ? m_ImgDecoder->Decode( - data_ptr, *data_size_ptr, - gif_image_ptr->m_ImageRowBuf.data() + img_row_offset, - &img_row_avail_size) - : GifDecodeStatus::Error; - } - if (ret == GifDecodeStatus::Error) { - DecodingFailureAtTailCleanup(gif_image_ptr); - return GifDecodeStatus::Error; - } - } - } - SaveDecodingStatus(GIF_D_STATUS_TAIL); - } - return GifDecodeStatus::Error; -} - -void CGifContext::SetInputBuffer(uint8_t* src_buf, uint32_t src_size) { - next_in = src_buf; - avail_in = src_size; - skip_size = 0; -} - -uint32_t CGifContext::GetAvailInput(uint8_t** avail_buf_ptr) const { - if (avail_buf_ptr) { - *avail_buf_ptr = nullptr; - if (avail_in > 0) - *avail_buf_ptr = next_in; - } - return avail_in; -} - -int32_t CGifContext::GetFrameNum() const { - return pdfium::CollectionSize<int32_t>(m_Images); -} - -uint8_t* CGifContext::ReadData(uint8_t** des_buf_pp, uint32_t data_size) { - if (avail_in < skip_size + data_size) - return nullptr; - - *des_buf_pp = next_in + skip_size; - skip_size += data_size; - return *des_buf_pp; -} - -void CGifContext::SaveDecodingStatus(int32_t status) { - decode_status = status; - next_in += skip_size; - avail_in -= skip_size; - skip_size = 0; -} - -GifDecodeStatus CGifContext::DecodeExtension() { - uint8_t* data_size_ptr = nullptr; - uint8_t* data_ptr = nullptr; - uint32_t skip_size_org = skip_size; - switch (decode_status) { - case GIF_D_STATUS_EXT_CE: { - if (!ReadData(&data_size_ptr, 1)) { - skip_size = skip_size_org; - return GifDecodeStatus::Unfinished; - } - - cmt_data.clear(); - while (*data_size_ptr != GIF_BLOCK_TERMINAL) { - uint8_t data_size = *data_size_ptr; - if (!ReadData(&data_ptr, *data_size_ptr) || - !ReadData(&data_size_ptr, 1)) { - skip_size = skip_size_org; - return GifDecodeStatus::Unfinished; - } - - cmt_data += ByteString(data_ptr, data_size); - } - break; - } - case GIF_D_STATUS_EXT_PTE: { - GifPlainTextExtension* gif_pte = nullptr; - if (!ReadData(reinterpret_cast<uint8_t**>(&gif_pte), 13)) - return GifDecodeStatus::Unfinished; - - m_GraphicControlExtension = nullptr; - if (!ReadData(&data_size_ptr, 1)) { - skip_size = skip_size_org; - return GifDecodeStatus::Unfinished; - } - - while (*data_size_ptr != GIF_BLOCK_TERMINAL) { - if (!ReadData(&data_ptr, *data_size_ptr) || - !ReadData(&data_size_ptr, 1)) { - skip_size = skip_size_org; - return GifDecodeStatus::Unfinished; - } - } - break; - } - case GIF_D_STATUS_EXT_GCE: { - GifGraphicControlExtension* gif_gce_ptr = nullptr; - if (!ReadData(reinterpret_cast<uint8_t**>(&gif_gce_ptr), 6)) - return GifDecodeStatus::Unfinished; - - if (!m_GraphicControlExtension.get()) - m_GraphicControlExtension = - pdfium::MakeUnique<GifGraphicControlExtension>(); - m_GraphicControlExtension->block_size = gif_gce_ptr->block_size; - m_GraphicControlExtension->gce_flags = gif_gce_ptr->gce_flags; - m_GraphicControlExtension->delay_time = GetWord_LSBFirst( - reinterpret_cast<uint8_t*>(&gif_gce_ptr->delay_time)); - m_GraphicControlExtension->trans_index = gif_gce_ptr->trans_index; - break; - } - default: { - if (decode_status == GIF_D_STATUS_EXT_PTE) - m_GraphicControlExtension = nullptr; - if (!ReadData(&data_size_ptr, 1)) - return GifDecodeStatus::Unfinished; - - while (*data_size_ptr != GIF_BLOCK_TERMINAL) { - if (!ReadData(&data_ptr, *data_size_ptr) || - !ReadData(&data_size_ptr, 1)) { - skip_size = skip_size_org; - return GifDecodeStatus::Unfinished; - } - } - } - } - SaveDecodingStatus(GIF_D_STATUS_SIG); - return GifDecodeStatus::Success; -} - -GifDecodeStatus CGifContext::DecodeImageInfo() { - if (width == 0 || height == 0) - return GifDecodeStatus::Error; - - uint32_t skip_size_org = skip_size; - GifImageInfo* gif_img_info_ptr = nullptr; - if (!ReadData(reinterpret_cast<uint8_t**>(&gif_img_info_ptr), 9)) - return GifDecodeStatus::Unfinished; - - 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_flags = gif_img_info_ptr->local_flags; - if (gif_image->m_ImageInfo.left + gif_image->m_ImageInfo.width > width || - gif_image->m_ImageInfo.top + gif_image->m_ImageInfo.height > height) - return GifDecodeStatus::Error; - - GifLocalFlags* gif_img_info_lf_ptr = &gif_img_info_ptr->local_flags; - if (gif_img_info_lf_ptr->local_pal) { - gif_image->local_pallette_exp = gif_img_info_lf_ptr->pal_bits; - uint32_t loc_pal_size = unsigned(2 << gif_img_info_lf_ptr->pal_bits) * 3u; - uint8_t* loc_pal_ptr = nullptr; - if (!ReadData(&loc_pal_ptr, loc_pal_size)) { - skip_size = skip_size_org; - return GifDecodeStatus::Unfinished; - } - - 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 (!ReadData(&code_size_ptr, 1)) { - skip_size = skip_size_org; - return GifDecodeStatus::Unfinished; - } - - gif_image->image_code_exp = *code_size_ptr; - RecordCurrentPosition(&gif_image->image_data_pos); - gif_image->image_data_pos += skip_size; - gif_image->m_ImageGCE = nullptr; - if (m_GraphicControlExtension.get()) { - gif_image->m_ImageGCE = std::move(m_GraphicControlExtension); - m_GraphicControlExtension = nullptr; - } - m_Images.push_back(std::move(gif_image)); - SaveDecodingStatus(GIF_D_STATUS_IMG_DATA); - return GifDecodeStatus::Success; -} - -void CGifContext::DecodingFailureAtTailCleanup(GifImage* gif_image_ptr) { - gif_image_ptr->m_ImageRowBuf.clear(); - SaveDecodingStatus(GIF_D_STATUS_TAIL); -} diff --git a/core/fxcodec/lgif/cgifcontext.h b/core/fxcodec/lgif/cgifcontext.h deleted file mode 100644 index 2573a2e470..0000000000 --- a/core/fxcodec/lgif/cgifcontext.h +++ /dev/null @@ -1,76 +0,0 @@ -// 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_CGIFCONTEXT_H_ -#define CORE_FXCODEC_LGIF_CGIFCONTEXT_H_ - -#include <memory> -#include <vector> - -#include "core/fxcodec/codec/ccodec_gifmodule.h" -#include "core/fxcodec/lgif/cfx_lzwdecoder.h" -#include "core/fxcodec/lgif/fx_gif.h" -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/unowned_ptr.h" - -class CGifContext : public CCodec_GifModule::Context { - public: - CGifContext(CCodec_GifModule* gif_module, - CCodec_GifModule::Delegate* pDelegate); - ~CGifContext() override; - - 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, - GifPalette* pal_ptr, - int32_t delay_time, - bool user_input, - int32_t trans_index, - int32_t disposal_method, - bool interlace); - GifDecodeStatus ReadHeader(); - GifDecodeStatus GetFrame(); - GifDecodeStatus LoadFrame(int32_t frame_num); - void SetInputBuffer(uint8_t* src_buf, uint32_t src_size); - uint32_t GetAvailInput(uint8_t** avail_buf_ptr) const; - int32_t GetFrameNum() const; - - UnownedPtr<CCodec_GifModule> m_pModule; - UnownedPtr<CCodec_GifModule::Delegate> m_pDelegate; - std::vector<GifPalette> m_GlobalPalette; - uint8_t global_pal_exp; - uint32_t img_row_offset; - uint32_t img_row_avail_size; - uint32_t avail_in; - int32_t decode_status; - uint32_t skip_size; - ByteString cmt_data; - std::unique_ptr<GifGraphicControlExtension> m_GraphicControlExtension; - uint8_t* next_in; - std::vector<std::unique_ptr<GifImage>> m_Images; - std::unique_ptr<CFX_LZWDecoder> 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; - - private: - uint8_t* ReadData(uint8_t** des_buf_pp, uint32_t data_size); - void SaveDecodingStatus(int32_t status); - GifDecodeStatus DecodeExtension(); - GifDecodeStatus DecodeImageInfo(); - void DecodingFailureAtTailCleanup(GifImage* gif_image_ptr); -}; - -#endif // CORE_FXCODEC_LGIF_CGIFCONTEXT_H_ diff --git a/core/fxcodec/lgif/fx_gif.cpp b/core/fxcodec/lgif/fx_gif.cpp deleted file mode 100644 index b8e5cb8994..0000000000 --- a/core/fxcodec/lgif/fx_gif.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2014 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/fx_gif.h" - -static_assert(sizeof(GifImageInfo) == 9, - "GifImageInfo should have a size of 9"); -static_assert(sizeof(GifPalette) == 3, "GifPalette should have a size of 3"); -static_assert(sizeof(GifPlainTextExtension) == 13, - "GifPlainTextExtension should have a size of 13"); -static_assert(sizeof(GifGraphicControlExtension) == 5, - "GifGraphicControlExtension should have a size of 5"); -static_assert(sizeof(GifHeader) == 6, "GifHeader should have a size of 6"); -static_assert(sizeof(GifLocalScreenDescriptor) == 7, - "GifLocalScreenDescriptor should have a size of 7"); |