• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "core/fxge/dib/cfx_imagestretcher.h"
8 
9 #include "core/fxcrt/fx_safe_types.h"
10 #include "core/fxge/dib/cfx_dibbase.h"
11 #include "core/fxge/dib/cfx_dibitmap.h"
12 #include "core/fxge/dib/cstretchengine.h"
13 #include "core/fxge/dib/fx_dib.h"
14 #include "third_party/base/check.h"
15 #include "third_party/base/check_op.h"
16 #include "third_party/base/span.h"
17 
18 namespace {
19 
20 const int kMaxProgressiveStretchPixels = 1000000;
21 
SourceSizeWithinLimit(int width,int height)22 bool SourceSizeWithinLimit(int width, int height) {
23   return !height || width < kMaxProgressiveStretchPixels / height;
24 }
25 
GetStretchedFormat(const CFX_DIBBase & src)26 FXDIB_Format GetStretchedFormat(const CFX_DIBBase& src) {
27   FXDIB_Format format = src.GetFormat();
28   if (format == FXDIB_Format::k1bppMask)
29     return FXDIB_Format::k8bppMask;
30   if (format == FXDIB_Format::k1bppRgb)
31     return FXDIB_Format::k8bppRgb;
32   if (format == FXDIB_Format::k8bppRgb && src.HasPalette())
33     return FXDIB_Format::kRgb;
34   return format;
35 }
36 
37 // Builds a new palette with a size of `CFX_DIBBase::kPaletteSize` from the
38 // existing palette in `source`. Note: The caller must make sure that the
39 // parameters meet the following conditions:
40 //   source       - The format must be `FXDIB_Format::k1bppRgb` and it must
41 //                  have a palette.
42 //   palette_span - The size must be `CFX_DIBBase::kPaletteSize` to be able
43 //                  to hold the new palette.
44 
BuildPaletteFrom1BppSource(const RetainPtr<const CFX_DIBBase> & source,pdfium::span<FX_ARGB> palette_span)45 void BuildPaletteFrom1BppSource(const RetainPtr<const CFX_DIBBase>& source,
46                                 pdfium::span<FX_ARGB> palette_span) {
47   DCHECK_EQ(FXDIB_Format::k1bppRgb, source->GetFormat());
48   DCHECK(source->HasPalette());
49   DCHECK_EQ(CFX_DIBBase::kPaletteSize, palette_span.size());
50 
51   int a0;
52   int r0;
53   int g0;
54   int b0;
55   std::tie(a0, r0, g0, b0) = ArgbDecode(source->GetPaletteArgb(0));
56   int a1;
57   int r1;
58   int g1;
59   int b1;
60   std::tie(a1, r1, g1, b1) = ArgbDecode(source->GetPaletteArgb(1));
61   DCHECK_EQ(255, a0);
62   DCHECK_EQ(255, a1);
63 
64   for (int i = 0; i < static_cast<int>(CFX_DIBBase::kPaletteSize); ++i) {
65     int r = r0 + (r1 - r0) * i / 255;
66     int g = g0 + (g1 - g0) * i / 255;
67     int b = b0 + (b1 - b0) * i / 255;
68     palette_span[i] = ArgbEncode(255, r, g, b);
69   }
70 }
71 
72 }  // namespace
73 
CFX_ImageStretcher(ScanlineComposerIface * pDest,const RetainPtr<const CFX_DIBBase> & pSource,int dest_width,int dest_height,const FX_RECT & bitmap_rect,const FXDIB_ResampleOptions & options)74 CFX_ImageStretcher::CFX_ImageStretcher(
75     ScanlineComposerIface* pDest,
76     const RetainPtr<const CFX_DIBBase>& pSource,
77     int dest_width,
78     int dest_height,
79     const FX_RECT& bitmap_rect,
80     const FXDIB_ResampleOptions& options)
81     : m_pDest(pDest),
82       m_pSource(pSource),
83       m_ResampleOptions(options),
84       m_DestWidth(dest_width),
85       m_DestHeight(dest_height),
86       m_ClipRect(bitmap_rect),
87       m_DestFormat(GetStretchedFormat(*pSource)) {
88   DCHECK(m_ClipRect.Valid());
89 }
90 
91 CFX_ImageStretcher::~CFX_ImageStretcher() = default;
92 
Start()93 bool CFX_ImageStretcher::Start() {
94   if (m_DestWidth == 0 || m_DestHeight == 0)
95     return false;
96 
97   if (m_pSource->GetFormat() == FXDIB_Format::k1bppRgb &&
98       m_pSource->HasPalette()) {
99     FX_ARGB pal[CFX_DIBBase::kPaletteSize];
100     BuildPaletteFrom1BppSource(m_pSource, pal);
101     if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), m_DestFormat,
102                           pal)) {
103       return false;
104     }
105   } else if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(),
106                                m_DestFormat, {})) {
107     return false;
108   }
109   return StartStretch();
110 }
111 
Continue(PauseIndicatorIface * pPause)112 bool CFX_ImageStretcher::Continue(PauseIndicatorIface* pPause) {
113   return ContinueStretch(pPause);
114 }
115 
source()116 RetainPtr<const CFX_DIBBase> CFX_ImageStretcher::source() {
117   return m_pSource;
118 }
119 
StartStretch()120 bool CFX_ImageStretcher::StartStretch() {
121   m_pStretchEngine = std::make_unique<CStretchEngine>(
122       m_pDest, m_DestFormat, m_DestWidth, m_DestHeight, m_ClipRect, m_pSource,
123       m_ResampleOptions);
124   m_pStretchEngine->StartStretchHorz();
125   if (SourceSizeWithinLimit(m_pSource->GetWidth(), m_pSource->GetHeight())) {
126     m_pStretchEngine->Continue(nullptr);
127     return false;
128   }
129   return true;
130 }
131 
ContinueStretch(PauseIndicatorIface * pPause)132 bool CFX_ImageStretcher::ContinueStretch(PauseIndicatorIface* pPause) {
133   return m_pStretchEngine && m_pStretchEngine->Continue(pPause);
134 }
135