• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 PDFium Authors. All rights reserved.
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 <climits>
10 #include <tuple>
11 
12 #include "core/fxcrt/fx_safe_types.h"
13 #include "core/fxge/dib/cfx_dibbase.h"
14 #include "core/fxge/dib/cfx_dibitmap.h"
15 #include "core/fxge/dib/cstretchengine.h"
16 #include "core/fxge/fx_dib.h"
17 #include "third_party/base/ptr_util.h"
18 #include "third_party/base/stl_util.h"
19 
20 namespace {
21 
22 const int kMaxProgressiveStretchPixels = 1000000;
23 
SourceSizeWithinLimit(int width,int height)24 bool SourceSizeWithinLimit(int width, int height) {
25   return !height || width < kMaxProgressiveStretchPixels / height;
26 }
27 
GetStretchedFormat(const CFX_DIBBase & src)28 FXDIB_Format GetStretchedFormat(const CFX_DIBBase& src) {
29   FXDIB_Format format = src.GetFormat();
30   if (format == FXDIB_1bppMask)
31     return FXDIB_8bppMask;
32   if (format == FXDIB_1bppRgb)
33     return FXDIB_8bppRgb;
34   if (format == FXDIB_8bppRgb && src.GetPalette())
35     return FXDIB_Rgb;
36   return format;
37 }
38 
39 // Returns tuple c, m, y, k
CmykDecode(const uint32_t cmyk)40 std::tuple<int, int, int, int> CmykDecode(const uint32_t cmyk) {
41   return std::make_tuple(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk),
42                          FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk));
43 }
44 
45 }  // namespace
46 
CFX_ImageStretcher(ScanlineComposerIface * pDest,const RetainPtr<CFX_DIBBase> & pSource,int dest_width,int dest_height,const FX_RECT & bitmap_rect,const FXDIB_ResampleOptions & options)47 CFX_ImageStretcher::CFX_ImageStretcher(ScanlineComposerIface* pDest,
48                                        const RetainPtr<CFX_DIBBase>& pSource,
49                                        int dest_width,
50                                        int dest_height,
51                                        const FX_RECT& bitmap_rect,
52                                        const FXDIB_ResampleOptions& options)
53     : m_pDest(pDest),
54       m_pSource(pSource),
55       m_ResampleOptions(options),
56       m_DestWidth(dest_width),
57       m_DestHeight(dest_height),
58       m_ClipRect(bitmap_rect),
59       m_DestFormat(GetStretchedFormat(*pSource)),
60       m_DestBPP(GetBppFromFormat(m_DestFormat)) {
61   ASSERT(m_ClipRect.Valid());
62 }
63 
~CFX_ImageStretcher()64 CFX_ImageStretcher::~CFX_ImageStretcher() {}
65 
Start()66 bool CFX_ImageStretcher::Start() {
67   if (m_DestWidth == 0 || m_DestHeight == 0)
68     return false;
69 
70   if (m_pSource->GetFormat() == FXDIB_1bppRgb && m_pSource->GetPalette()) {
71     FX_ARGB pal[256];
72     int a0;
73     int r0;
74     int g0;
75     int b0;
76     std::tie(a0, r0, g0, b0) = ArgbDecode(m_pSource->GetPaletteArgb(0));
77     int a1;
78     int r1;
79     int g1;
80     int b1;
81     std::tie(a1, r1, g1, b1) = ArgbDecode(m_pSource->GetPaletteArgb(1));
82     for (int i = 0; i < 256; ++i) {
83       int a = a0 + (a1 - a0) * i / 255;
84       int r = r0 + (r1 - r0) * i / 255;
85       int g = g0 + (g1 - g0) * i / 255;
86       int b = b0 + (b1 - b0) * i / 255;
87       pal[i] = ArgbEncode(a, r, g, b);
88     }
89     if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), m_DestFormat,
90                           pal)) {
91       return false;
92     }
93   } else if (m_pSource->GetFormat() == FXDIB_1bppCmyk &&
94              m_pSource->GetPalette()) {
95     FX_CMYK pal[256];
96     int c0;
97     int m0;
98     int y0;
99     int k0;
100     std::tie(c0, m0, y0, k0) = CmykDecode(m_pSource->GetPaletteArgb(0));
101     int c1;
102     int m1;
103     int y1;
104     int k1;
105     std::tie(c1, m1, y1, k1) = CmykDecode(m_pSource->GetPaletteArgb(1));
106     for (int i = 0; i < 256; ++i) {
107       int c = c0 + (c1 - c0) * i / 255;
108       int m = m0 + (m1 - m0) * i / 255;
109       int y = y0 + (y1 - y0) * i / 255;
110       int k = k0 + (k1 - k0) * i / 255;
111       pal[i] = CmykEncode(c, m, y, k);
112     }
113     if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), m_DestFormat,
114                           pal)) {
115       return false;
116     }
117   } else if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(),
118                                m_DestFormat, nullptr)) {
119     return false;
120   }
121   return StartStretch();
122 }
123 
Continue(PauseIndicatorIface * pPause)124 bool CFX_ImageStretcher::Continue(PauseIndicatorIface* pPause) {
125   return ContinueStretch(pPause);
126 }
127 
source()128 RetainPtr<CFX_DIBBase> CFX_ImageStretcher::source() {
129   return m_pSource;
130 }
131 
StartStretch()132 bool CFX_ImageStretcher::StartStretch() {
133   m_pStretchEngine = pdfium::MakeUnique<CStretchEngine>(
134       m_pDest.Get(), m_DestFormat, m_DestWidth, m_DestHeight, m_ClipRect,
135       m_pSource, m_ResampleOptions);
136   m_pStretchEngine->StartStretchHorz();
137   if (SourceSizeWithinLimit(m_pSource->GetWidth(), m_pSource->GetHeight())) {
138     m_pStretchEngine->Continue(nullptr);
139     return false;
140   }
141   return true;
142 }
143 
ContinueStretch(PauseIndicatorIface * pPause)144 bool CFX_ImageStretcher::ContinueStretch(PauseIndicatorIface* pPause) {
145   return m_pStretchEngine && m_pStretchEngine->Continue(pPause);
146 }
147