1 // Copyright 2017 The PDFium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #ifndef CORE_FXGE_DIB_CSTRETCHENGINE_H_ 8 #define CORE_FXGE_DIB_CSTRETCHENGINE_H_ 9 10 #include <stdint.h> 11 12 #include "core/fxcrt/check_op.h" 13 #include "core/fxcrt/data_vector.h" 14 #include "core/fxcrt/fixed_size_data_vector.h" 15 #include "core/fxcrt/fx_coordinates.h" 16 #include "core/fxcrt/fx_system.h" 17 #include "core/fxcrt/raw_span.h" 18 #include "core/fxcrt/retain_ptr.h" 19 #include "core/fxcrt/unowned_ptr.h" 20 #include "core/fxge/dib/fx_dib.h" 21 22 class CFX_DIBBase; 23 class PauseIndicatorIface; 24 class ScanlineComposerIface; 25 26 class CStretchEngine { 27 public: 28 static constexpr uint32_t kFixedPointBits = 16; 29 static constexpr uint32_t kFixedPointOne = 1 << kFixedPointBits; 30 FixedFromDouble(double d)31 static inline uint32_t FixedFromDouble(double d) { 32 return static_cast<uint32_t>(FXSYS_round(d * kFixedPointOne)); 33 } 34 PixelFromFixed(uint32_t fixed)35 static inline uint8_t PixelFromFixed(uint32_t fixed) { 36 return static_cast<uint8_t>(fixed >> kFixedPointBits); 37 } 38 39 // Indicates whether to manually set interpolate bilinear option to true to 40 // achieve a smoother rendering results. 41 static bool UseInterpolateBilinear(const FXDIB_ResampleOptions& options, 42 int dest_width, 43 int dest_height, 44 int src_width, 45 int src_height); 46 47 struct PixelWeight { SetStartEndPixelWeight48 void SetStartEnd(int src_start, int src_end, size_t weight_count) { 49 CHECK_LT(src_end - src_start, static_cast<int>(weight_count)); 50 m_SrcStart = src_start; 51 m_SrcEnd = src_end; 52 } 53 GetWeightForPositionPixelWeight54 uint32_t GetWeightForPosition(int position) const { 55 CHECK_GE(position, m_SrcStart); 56 CHECK_LE(position, m_SrcEnd); 57 // SAFETY: enforced by checks above. 58 return UNSAFE_BUFFERS(m_Weights[position - m_SrcStart]); 59 } 60 SetWeightForPositionPixelWeight61 void SetWeightForPosition(int position, uint32_t weight) { 62 CHECK_GE(position, m_SrcStart); 63 CHECK_LE(position, m_SrcEnd); 64 // SAFETY: enforced by checks above. 65 UNSAFE_BUFFERS(m_Weights[position - m_SrcStart] = weight); 66 } 67 68 // NOTE: relies on defined behaviour for unsigned overflow to 69 // decrement the previous position, as needed. RemoveLastWeightAndAdjustPixelWeight70 void RemoveLastWeightAndAdjust(uint32_t weight_change) { 71 CHECK_GT(m_SrcEnd, m_SrcStart); 72 --m_SrcEnd; 73 // SAFETY: enforced by checks above. 74 UNSAFE_BUFFERS(m_Weights[m_SrcEnd - m_SrcStart] += weight_change); 75 } 76 77 int m_SrcStart; 78 int m_SrcEnd; // Note: inclusive, [0, -1] for empty range at 0. 79 uint32_t m_Weights[1]; // Not really 1, variable size. 80 }; 81 82 class WeightTable { 83 public: 84 WeightTable(); 85 ~WeightTable(); 86 87 // Accepts a negative `dest_len` argument, producing a "mirror 88 // image" of the result if `dest_len` is negative. 89 bool CalculateWeights(int dest_len, 90 int dest_min, 91 int dest_max, 92 int src_len, 93 int src_min, 94 int src_max, 95 const FXDIB_ResampleOptions& options); 96 97 const PixelWeight* GetPixelWeight(int pixel) const; 98 PixelWeight* GetPixelWeight(int pixel); 99 100 private: 101 int m_DestMin = 0; 102 size_t m_ItemSizeBytes = 0; 103 size_t m_WeightTablesSizeBytes = 0; 104 DataVector<uint8_t> m_WeightTables; 105 }; 106 107 CStretchEngine(ScanlineComposerIface* pDestBitmap, 108 FXDIB_Format dest_format, 109 int dest_width, 110 int dest_height, 111 const FX_RECT& clip_rect, 112 const RetainPtr<const CFX_DIBBase>& pSrcBitmap, 113 const FXDIB_ResampleOptions& options); 114 ~CStretchEngine(); 115 116 bool Continue(PauseIndicatorIface* pPause); 117 bool StartStretchHorz(); 118 bool ContinueStretchHorz(PauseIndicatorIface* pPause); 119 void StretchVert(); 120 GetResampleOptionsForTest()121 const FXDIB_ResampleOptions& GetResampleOptionsForTest() const { 122 return m_ResampleOptions; 123 } 124 125 private: 126 enum class State : uint8_t { kInitial, kHorizontal, kVertical }; 127 128 enum class TransformMethod : uint8_t { 129 k1BppTo8Bpp, 130 k1BppToManyBpp, 131 k8BppTo8Bpp, 132 k8BppToManyBpp, 133 kManyBpptoManyBpp, 134 kManyBpptoManyBppWithAlpha 135 }; 136 137 const FXDIB_Format m_DestFormat; 138 const int m_DestBpp; 139 const int m_SrcBpp; 140 const bool m_bHasAlpha; 141 RetainPtr<const CFX_DIBBase> const m_pSource; 142 pdfium::raw_span<const uint32_t> m_pSrcPalette; 143 const int m_SrcWidth; 144 const int m_SrcHeight; 145 UnownedPtr<ScanlineComposerIface> const m_pDestBitmap; 146 const int m_DestWidth; 147 const int m_DestHeight; 148 const FX_RECT m_DestClip; 149 DataVector<uint8_t> m_DestScanline; 150 FixedSizeDataVector<uint8_t> m_InterBuf; 151 FX_RECT m_SrcClip; 152 int m_InterPitch; 153 int m_ExtraMaskPitch; 154 FXDIB_ResampleOptions m_ResampleOptions; 155 TransformMethod m_TransMethod; 156 State m_State = State::kInitial; 157 int m_CurRow = 0; 158 WeightTable m_WeightTable; 159 }; 160 161 #endif // CORE_FXGE_DIB_CSTRETCHENGINE_H_ 162