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