// Copyright 2017 The PDFium Authors // 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_FXGE_DIB_CSTRETCHENGINE_H_ #define CORE_FXGE_DIB_CSTRETCHENGINE_H_ #include #include "core/fxcrt/data_vector.h" #include "core/fxcrt/fixed_try_alloc_zeroed_data_vector.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_system.h" #include "core/fxcrt/retain_ptr.h" #include "core/fxcrt/unowned_ptr.h" #include "core/fxge/dib/fx_dib.h" #include "third_party/base/check_op.h" #include "third_party/base/span.h" class CFX_DIBBase; class PauseIndicatorIface; class ScanlineComposerIface; class CStretchEngine { public: static constexpr uint32_t kFixedPointBits = 16; static constexpr uint32_t kFixedPointOne = 1 << kFixedPointBits; static inline uint32_t FixedFromDouble(double d) { return static_cast(FXSYS_round(d * kFixedPointOne)); } static inline uint32_t FixedFromFloat(float f) { return static_cast(FXSYS_roundf(f * kFixedPointOne)); } static inline uint8_t PixelFromFixed(uint32_t fixed) { return static_cast(fixed >> kFixedPointBits); } // Indicates whether to manually set interpolate bilinear option to true to // achieve a smoother rendering results. static bool UseInterpolateBilinear(const FXDIB_ResampleOptions& options, int dest_width, int dest_height, int src_width, int src_height); struct PixelWeight { static size_t TotalBytesForWeightCount(size_t weight_count); void SetStartEnd(int src_start, int src_end, size_t weight_count) { CHECK_LT(src_end - src_start, static_cast(weight_count)); m_SrcStart = src_start; m_SrcEnd = src_end; } uint32_t GetWeightForPosition(int position) const { CHECK_GE(position, m_SrcStart); CHECK_LE(position, m_SrcEnd); return m_Weights[position - m_SrcStart]; } void SetWeightForPosition(int position, uint32_t weight) { CHECK_GE(position, m_SrcStart); CHECK_LE(position, m_SrcEnd); m_Weights[position - m_SrcStart] = weight; } // NOTE: relies on defined behaviour for unsigned overflow to // decrement the previous position, as needed. void RemoveLastWeightAndAdjust(uint32_t weight_change) { CHECK_GT(m_SrcEnd, m_SrcStart); --m_SrcEnd; m_Weights[m_SrcEnd - m_SrcStart] += weight_change; } int m_SrcStart; int m_SrcEnd; // Note: inclusive, [0, -1] for empty range at 0. uint32_t m_Weights[1]; // Not really 1, variable size. }; class WeightTable { public: WeightTable(); ~WeightTable(); // Accepts a negative `dest_len` argument, producing a "mirror // image" of the result if `dest_len` is negative. bool CalculateWeights(int dest_len, int dest_min, int dest_max, int src_len, int src_min, int src_max, const FXDIB_ResampleOptions& options); const PixelWeight* GetPixelWeight(int pixel) const; PixelWeight* GetPixelWeight(int pixel); private: int m_DestMin = 0; size_t m_ItemSizeBytes = 0; size_t m_WeightTablesSizeBytes = 0; DataVector m_WeightTables; }; CStretchEngine(ScanlineComposerIface* pDestBitmap, FXDIB_Format dest_format, int dest_width, int dest_height, const FX_RECT& clip_rect, const RetainPtr& pSrcBitmap, const FXDIB_ResampleOptions& options); ~CStretchEngine(); bool Continue(PauseIndicatorIface* pPause); bool StartStretchHorz(); bool ContinueStretchHorz(PauseIndicatorIface* pPause); void StretchVert(); const FXDIB_ResampleOptions& GetResampleOptionsForTest() const { return m_ResampleOptions; } private: enum class State : uint8_t { kInitial, kHorizontal, kVertical }; enum class TransformMethod : uint8_t { k1BppTo8Bpp, k1BppToManyBpp, k8BppTo8Bpp, k8BppToManyBpp, kManyBpptoManyBpp, kManyBpptoManyBppWithAlpha }; const FXDIB_Format m_DestFormat; const int m_DestBpp; const int m_SrcBpp; const bool m_bHasAlpha; RetainPtr const m_pSource; pdfium::span m_pSrcPalette; const int m_SrcWidth; const int m_SrcHeight; UnownedPtr const m_pDestBitmap; const int m_DestWidth; const int m_DestHeight; const FX_RECT m_DestClip; DataVector m_DestScanline; FixedTryAllocZeroedDataVector m_InterBuf; FX_RECT m_SrcClip; int m_InterPitch; int m_ExtraMaskPitch; FXDIB_ResampleOptions m_ResampleOptions; TransformMethod m_TransMethod; State m_State = State::kInitial; int m_CurRow = 0; WeightTable m_WeightTable; }; #endif // CORE_FXGE_DIB_CSTRETCHENGINE_H_