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 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 23 CXFA_ImageRenderer::~CXFA_ImageRenderer() {} 24 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 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 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