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