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_imagerenderer.h"
8 
9 #include <memory>
10 
11 #include "core/fxge/cfx_cliprgn.h"
12 #include "core/fxge/dib/cfx_dibitmap.h"
13 #include "core/fxge/dib/cfx_imagestretcher.h"
14 #include "core/fxge/dib/cfx_imagetransformer.h"
15 #include "third_party/base/ptr_util.h"
16 
CFX_ImageRenderer(const RetainPtr<CFX_DIBitmap> & pDevice,const CFX_ClipRgn * pClipRgn,const RetainPtr<CFX_DIBBase> & pSource,int bitmap_alpha,uint32_t mask_color,const CFX_Matrix & matrix,const FXDIB_ResampleOptions & options,bool bRgbByteOrder)17 CFX_ImageRenderer::CFX_ImageRenderer(const RetainPtr<CFX_DIBitmap>& pDevice,
18                                      const CFX_ClipRgn* pClipRgn,
19                                      const RetainPtr<CFX_DIBBase>& pSource,
20                                      int bitmap_alpha,
21                                      uint32_t mask_color,
22                                      const CFX_Matrix& matrix,
23                                      const FXDIB_ResampleOptions& options,
24                                      bool bRgbByteOrder)
25     : m_pDevice(pDevice),
26       m_pClipRgn(pClipRgn),
27       m_Matrix(matrix),
28       m_BitmapAlpha(bitmap_alpha),
29       m_MaskColor(mask_color),
30       m_bRgbByteOrder(bRgbByteOrder) {
31   FX_RECT image_rect = m_Matrix.GetUnitRect().GetOuterRect();
32   m_ClipBox = pClipRgn
33                   ? pClipRgn->GetBox()
34                   : FX_RECT(0, 0, pDevice->GetWidth(), pDevice->GetHeight());
35   m_ClipBox.Intersect(image_rect);
36   if (m_ClipBox.IsEmpty())
37     return;
38 
39   if ((fabs(m_Matrix.b) >= 0.5f || m_Matrix.a == 0) ||
40       (fabs(m_Matrix.c) >= 0.5f || m_Matrix.d == 0)) {
41     if (fabs(m_Matrix.a) < fabs(m_Matrix.b) / 20 &&
42         fabs(m_Matrix.d) < fabs(m_Matrix.c) / 20 && fabs(m_Matrix.a) < 0.5f &&
43         fabs(m_Matrix.d) < 0.5f) {
44       int dest_width = image_rect.Width();
45       int dest_height = image_rect.Height();
46       FX_RECT bitmap_clip = m_ClipBox;
47       bitmap_clip.Offset(-image_rect.left, -image_rect.top);
48       bitmap_clip = FXDIB_SwapClipBox(bitmap_clip, dest_width, dest_height,
49                                       m_Matrix.c > 0, m_Matrix.b < 0);
50       m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color, m_ClipBox,
51                          true, m_Matrix.c > 0, m_Matrix.b < 0, m_bRgbByteOrder,
52                          BlendMode::kNormal);
53       m_Stretcher = pdfium::MakeUnique<CFX_ImageStretcher>(
54           &m_Composer, pSource, dest_height, dest_width, bitmap_clip, options);
55       if (m_Stretcher->Start())
56         m_Status = 1;
57       return;
58     }
59     m_Status = 2;
60     m_pTransformer = pdfium::MakeUnique<CFX_ImageTransformer>(
61         pSource, m_Matrix, options, &m_ClipBox);
62     return;
63   }
64 
65   int dest_width = image_rect.Width();
66   if (m_Matrix.a < 0)
67     dest_width = -dest_width;
68 
69   int dest_height = image_rect.Height();
70   if (m_Matrix.d > 0)
71     dest_height = -dest_height;
72 
73   if (dest_width == 0 || dest_height == 0)
74     return;
75 
76   FX_RECT bitmap_clip = m_ClipBox;
77   bitmap_clip.Offset(-image_rect.left, -image_rect.top);
78   m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color, m_ClipBox,
79                      false, false, false, m_bRgbByteOrder, BlendMode::kNormal);
80   m_Status = 1;
81   m_Stretcher = pdfium::MakeUnique<CFX_ImageStretcher>(
82       &m_Composer, pSource, dest_width, dest_height, bitmap_clip, options);
83   m_Stretcher->Start();
84 }
85 
~CFX_ImageRenderer()86 CFX_ImageRenderer::~CFX_ImageRenderer() {}
87 
Continue(PauseIndicatorIface * pPause)88 bool CFX_ImageRenderer::Continue(PauseIndicatorIface* pPause) {
89   if (m_Status == 1)
90     return m_Stretcher->Continue(pPause);
91   if (m_Status != 2)
92     return false;
93   if (m_pTransformer->Continue(pPause))
94     return true;
95 
96   RetainPtr<CFX_DIBitmap> pBitmap = m_pTransformer->DetachBitmap();
97   if (!pBitmap || !pBitmap->GetBuffer())
98     return false;
99 
100   if (pBitmap->IsAlphaMask()) {
101     if (m_BitmapAlpha != 255)
102       m_MaskColor = FXARGB_MUL_ALPHA(m_MaskColor, m_BitmapAlpha);
103     m_pDevice->CompositeMask(
104         m_pTransformer->result().left, m_pTransformer->result().top,
105         pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap, m_MaskColor, 0, 0,
106         BlendMode::kNormal, m_pClipRgn.Get(), m_bRgbByteOrder);
107   } else {
108     if (m_BitmapAlpha != 255)
109       pBitmap->MultiplyAlpha(m_BitmapAlpha);
110     m_pDevice->CompositeBitmap(
111         m_pTransformer->result().left, m_pTransformer->result().top,
112         pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap, 0, 0,
113         BlendMode::kNormal, m_pClipRgn.Get(), m_bRgbByteOrder);
114   }
115   return false;
116 }
117