xref: /aosp_15_r20/external/pdfium/xfa/fxfa/cxfa_imagerenderer.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2018 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 "xfa/fxfa/cxfa_imagerenderer.h"
8 
9 #include <math.h>
10 
11 #include "core/fxge/cfx_renderdevice.h"
12 #include "core/fxge/dib/cfx_dibbase.h"
13 #include "core/fxge/dib/cfx_dibitmap.h"
14 #include "core/fxge/dib/cfx_imagerenderer.h"
15 #include "core/fxge/dib/cfx_imagetransformer.h"
16 
CXFA_ImageRenderer(CFX_RenderDevice * pDevice,const RetainPtr<CFX_DIBBase> & pDIBBase,const CFX_Matrix & pImage2Device)17 CXFA_ImageRenderer::CXFA_ImageRenderer(CFX_RenderDevice* pDevice,
18                                        const RetainPtr<CFX_DIBBase>& pDIBBase,
19                                        const CFX_Matrix& pImage2Device)
20     : m_ImageMatrix(pImage2Device), m_pDevice(pDevice), m_pDIBBase(pDIBBase) {}
21 
22 CXFA_ImageRenderer::~CXFA_ImageRenderer() = default;
23 
Start()24 bool CXFA_ImageRenderer::Start() {
25   FXDIB_ResampleOptions options;
26   options.bInterpolateBilinear = true;
27   if (m_pDevice->StartDIBits(m_pDIBBase, 255, 0, m_ImageMatrix, options,
28                              &m_DeviceHandle)) {
29     if (m_DeviceHandle) {
30       m_State = State::kStarted;
31       return true;
32     }
33     return false;
34   }
35   CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect();
36   FX_RECT image_rect = image_rect_f.GetOuterRect();
37   int dest_width = image_rect.Width();
38   int dest_height = image_rect.Height();
39   if ((fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) ||
40       (fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) {
41     RetainPtr<CFX_DIBBase> pDib = m_pDIBBase;
42     if (m_pDIBBase->IsAlphaFormat() &&
43         !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE) &&
44         !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
45       m_pCloneConvert = m_pDIBBase->ConvertTo(FXDIB_Format::kRgb);
46       if (!m_pCloneConvert)
47         return false;
48 
49       pDib = m_pCloneConvert;
50     }
51     FX_RECT clip_box = m_pDevice->GetClipBox();
52     clip_box.Intersect(image_rect);
53     m_State = State::kTransforming;
54     m_pTransformer = std::make_unique<CFX_ImageTransformer>(pDib, m_ImageMatrix,
55                                                             options, &clip_box);
56     return true;
57   }
58   if (m_ImageMatrix.a < 0)
59     dest_width = -dest_width;
60   if (m_ImageMatrix.d > 0)
61     dest_height = -dest_height;
62   int dest_left = dest_width > 0 ? image_rect.left : image_rect.right;
63   int dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom;
64   if (m_pDIBBase->IsOpaqueImage()) {
65     if (m_pDevice->StretchDIBitsWithFlagsAndBlend(
66             m_pDIBBase, dest_left, dest_top, dest_width, dest_height, options,
67             BlendMode::kNormal)) {
68       return false;
69     }
70   }
71   if (m_pDIBBase->IsMaskFormat()) {
72     if (m_pDevice->StretchBitMaskWithFlags(m_pDIBBase, dest_left, dest_top,
73                                            dest_width, dest_height, 0,
74                                            options)) {
75       return false;
76     }
77   }
78 
79   FX_RECT clip_box = m_pDevice->GetClipBox();
80   FX_RECT dest_rect = clip_box;
81   dest_rect.Intersect(image_rect);
82   FX_RECT dest_clip(
83       dest_rect.left - image_rect.left, dest_rect.top - image_rect.top,
84       dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top);
85   RetainPtr<CFX_DIBitmap> pStretched =
86       m_pDIBBase->StretchTo(dest_width, dest_height, options, &dest_clip);
87   if (pStretched)
88     CompositeDIBitmap(pStretched, dest_rect.left, dest_rect.top);
89 
90   return false;
91 }
92 
Continue()93 bool CXFA_ImageRenderer::Continue() {
94   if (m_State == State::kTransforming) {
95     if (m_pTransformer->Continue(nullptr))
96       return true;
97 
98     RetainPtr<CFX_DIBitmap> pBitmap = m_pTransformer->DetachBitmap();
99     if (!pBitmap)
100       return false;
101 
102     if (pBitmap->IsMaskFormat()) {
103       m_pDevice->SetBitMask(pBitmap, m_pTransformer->result().left,
104                             m_pTransformer->result().top, 0);
105     } else {
106       m_pDevice->SetDIBitsWithBlend(pBitmap, m_pTransformer->result().left,
107                                     m_pTransformer->result().top,
108                                     BlendMode::kNormal);
109     }
110     return false;
111   }
112   if (m_State == State::kStarted)
113     return m_pDevice->ContinueDIBits(m_DeviceHandle.get(), nullptr);
114 
115   return false;
116 }
117 
CompositeDIBitmap(const RetainPtr<CFX_DIBitmap> & pDIBitmap,int left,int top)118 void CXFA_ImageRenderer::CompositeDIBitmap(
119     const RetainPtr<CFX_DIBitmap>& pDIBitmap,
120     int left,
121     int top) {
122   if (!pDIBitmap)
123     return;
124 
125   if (!pDIBitmap->IsMaskFormat()) {
126     if (m_pDevice->SetDIBits(pDIBitmap, left, top))
127       return;
128   } else if (m_pDevice->SetBitMask(pDIBitmap, left, top, 0)) {
129     return;
130   }
131 
132   bool bGetBackGround = ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) ||
133                         (!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) &&
134                          (m_pDevice->GetRenderCaps() & FXRC_GET_BITS));
135   if (bGetBackGround) {
136     if (pDIBitmap->IsMaskFormat())
137       return;
138 
139     m_pDevice->SetDIBitsWithBlend(pDIBitmap, left, top, BlendMode::kNormal);
140     return;
141   }
142   if (!pDIBitmap->IsAlphaFormat() ||
143       (m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE)) {
144     return;
145   }
146 
147   RetainPtr<CFX_DIBitmap> pConverted = pDIBitmap->ConvertTo(FXDIB_Format::kRgb);
148   if (!pConverted)
149     return;
150 
151   CXFA_ImageRenderer imageRender(m_pDevice, pConverted, m_ImageMatrix);
152   if (!imageRender.Start())
153     return;
154 
155   while (imageRender.Continue())
156     continue;
157 }
158