• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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 "xfa/fxfa/cxfa_imagerenderer.h"
8 
9 #include "core/fxge/cfx_renderdevice.h"
10 #include "core/fxge/dib/cfx_dibsource.h"
11 #include "core/fxge/dib/cfx_imagerenderer.h"
12 #include "core/fxge/dib/cfx_imagetransformer.h"
13 #include "third_party/base/ptr_util.h"
14 
CXFA_ImageRenderer(CFX_RenderDevice * pDevice,const RetainPtr<CFX_DIBSource> & pDIBSource,const CFX_Matrix * pImage2Device)15 CXFA_ImageRenderer::CXFA_ImageRenderer(
16     CFX_RenderDevice* pDevice,
17     const RetainPtr<CFX_DIBSource>& pDIBSource,
18     const CFX_Matrix* pImage2Device)
19     : m_pDevice(pDevice),
20       m_ImageMatrix(*pImage2Device),
21       m_pDIBSource(pDIBSource) {}
22 
~CXFA_ImageRenderer()23 CXFA_ImageRenderer::~CXFA_ImageRenderer() {}
24 
Start()25 bool CXFA_ImageRenderer::Start() {
26   if (m_pDevice->StartDIBitsWithBlend(m_pDIBSource, 255, 0, &m_ImageMatrix,
27                                       FXDIB_INTERPOL, &m_DeviceHandle,
28                                       FXDIB_BLEND_NORMAL)) {
29     if (m_DeviceHandle) {
30       m_Status = 3;
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_DIBSource> pDib = m_pDIBSource;
42     if (m_pDIBSource->HasAlpha() &&
43         !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE) &&
44         !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
45       m_pCloneConvert = m_pDIBSource->CloneConvert(FXDIB_Rgb);
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_Status = 2;
54     m_pTransformer = pdfium::MakeUnique<CFX_ImageTransformer>(
55         pDib, &m_ImageMatrix, FXDIB_INTERPOL, &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_top;
63   dest_left = dest_width > 0 ? image_rect.left : image_rect.right;
64   dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom;
65   if (m_pDIBSource->IsOpaqueImage()) {
66     if (m_pDevice->StretchDIBitsWithFlagsAndBlend(
67             m_pDIBSource, dest_left, dest_top, dest_width, dest_height,
68             FXDIB_INTERPOL, FXDIB_BLEND_NORMAL)) {
69       return false;
70     }
71   }
72   if (m_pDIBSource->IsAlphaMask()) {
73     if (m_pDevice->StretchBitMaskWithFlags(m_pDIBSource, dest_left, dest_top,
74                                            dest_width, dest_height, 0,
75                                            FXDIB_INTERPOL)) {
76       return false;
77     }
78   }
79 
80   FX_RECT clip_box = m_pDevice->GetClipBox();
81   FX_RECT dest_rect = clip_box;
82   dest_rect.Intersect(image_rect);
83   FX_RECT dest_clip(
84       dest_rect.left - image_rect.left, dest_rect.top - image_rect.top,
85       dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top);
86   RetainPtr<CFX_DIBitmap> pStretched = m_pDIBSource->StretchTo(
87       dest_width, dest_height, FXDIB_INTERPOL, &dest_clip);
88   if (pStretched)
89     CompositeDIBitmap(pStretched, dest_rect.left, dest_rect.top);
90 
91   return false;
92 }
93 
Continue()94 bool CXFA_ImageRenderer::Continue() {
95   if (m_Status == 2) {
96     if (m_pTransformer->Continue(nullptr))
97       return true;
98 
99     RetainPtr<CFX_DIBitmap> pBitmap = m_pTransformer->DetachBitmap();
100     if (!pBitmap)
101       return false;
102 
103     if (pBitmap->IsAlphaMask()) {
104       m_pDevice->SetBitMask(pBitmap, m_pTransformer->result().left,
105                             m_pTransformer->result().top, 0);
106     } else {
107       m_pDevice->SetDIBitsWithBlend(pBitmap, m_pTransformer->result().left,
108                                     m_pTransformer->result().top,
109                                     FXDIB_BLEND_NORMAL);
110     }
111     return false;
112   }
113   if (m_Status == 3)
114     return m_pDevice->ContinueDIBits(m_DeviceHandle.get(), nullptr);
115 
116   return false;
117 }
118 
CompositeDIBitmap(const RetainPtr<CFX_DIBitmap> & pDIBitmap,int left,int top)119 void CXFA_ImageRenderer::CompositeDIBitmap(
120     const RetainPtr<CFX_DIBitmap>& pDIBitmap,
121     int left,
122     int top) {
123   if (!pDIBitmap)
124     return;
125 
126   if (!pDIBitmap->IsAlphaMask()) {
127     if (m_pDevice->SetDIBits(pDIBitmap, left, top))
128       return;
129   } else if (m_pDevice->SetBitMask(pDIBitmap, left, top, 0)) {
130     return;
131   }
132 
133   bool bGetBackGround = ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) ||
134                         (!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) &&
135                          (m_pDevice->GetRenderCaps() & FXRC_GET_BITS));
136   if (bGetBackGround) {
137     if (pDIBitmap->IsAlphaMask())
138       return;
139 
140     m_pDevice->SetDIBitsWithBlend(pDIBitmap, left, top, FXDIB_BLEND_NORMAL);
141     return;
142   }
143   if (!pDIBitmap->HasAlpha() ||
144       (m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE)) {
145     return;
146   }
147 
148   RetainPtr<CFX_DIBitmap> pCloneConvert = pDIBitmap->CloneConvert(FXDIB_Rgb);
149   if (!pCloneConvert)
150     return;
151 
152   CXFA_ImageRenderer imageRender(m_pDevice, pCloneConvert, &m_ImageMatrix);
153   if (!imageRender.Start())
154     return;
155 
156   while (imageRender.Continue())
157     continue;
158 }
159