1 // Copyright 2017 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 "core/fxge/dib/cfx_imagerenderer.h" 8 9 #include <memory> 10 11 #include "core/fxge/cfx_cliprgn.h" 12 #include "core/fxge/dib/cfx_imagestretcher.h" 13 #include "core/fxge/dib/cfx_imagetransformer.h" 14 #include "third_party/base/ptr_util.h" 15 16 CFX_ImageRenderer::CFX_ImageRenderer(const RetainPtr<CFX_DIBitmap>& pDevice, 17 const CFX_ClipRgn* pClipRgn, 18 const RetainPtr<CFX_DIBSource>& pSource, 19 int bitmap_alpha, 20 uint32_t mask_color, 21 const CFX_Matrix* pMatrix, 22 uint32_t dib_flags, 23 bool bRgbByteOrder) 24 : m_pDevice(pDevice), 25 m_pClipRgn(pClipRgn), 26 m_Matrix(*pMatrix), 27 m_BitmapAlpha(bitmap_alpha), 28 m_BlendType(FXDIB_BLEND_NORMAL), 29 m_bRgbByteOrder(bRgbByteOrder), 30 m_MaskColor(mask_color), 31 m_Status(0), 32 m_AlphaFlag(0) { 33 FX_RECT image_rect = m_Matrix.GetUnitRect().GetOuterRect(); 34 m_ClipBox = pClipRgn ? pClipRgn->GetBox() : FX_RECT(0, 0, pDevice->GetWidth(), 35 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 = FXDIB_SwapClipBox(bitmap_clip, 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 0, m_BlendType); 54 m_Stretcher = pdfium::MakeUnique<CFX_ImageStretcher>( 55 &m_Composer, pSource, dest_height, dest_width, bitmap_clip, 56 dib_flags); 57 if (m_Stretcher->Start()) 58 m_Status = 1; 59 return; 60 } 61 m_Status = 2; 62 m_pTransformer = pdfium::MakeUnique<CFX_ImageTransformer>( 63 pSource, &m_Matrix, dib_flags, &m_ClipBox); 64 return; 65 } 66 67 int dest_width = image_rect.Width(); 68 if (m_Matrix.a < 0) 69 dest_width = -dest_width; 70 71 int dest_height = image_rect.Height(); 72 if (m_Matrix.d > 0) 73 dest_height = -dest_height; 74 75 if (dest_width == 0 || dest_height == 0) 76 return; 77 78 FX_RECT bitmap_clip = m_ClipBox; 79 bitmap_clip.Offset(-image_rect.left, -image_rect.top); 80 m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color, m_ClipBox, 81 false, false, false, m_bRgbByteOrder, 0, m_BlendType); 82 m_Status = 1; 83 m_Stretcher = pdfium::MakeUnique<CFX_ImageStretcher>( 84 &m_Composer, pSource, dest_width, dest_height, bitmap_clip, dib_flags); 85 m_Stretcher->Start(); 86 } 87 88 CFX_ImageRenderer::~CFX_ImageRenderer() {} 89 90 bool CFX_ImageRenderer::Continue(IFX_PauseIndicator* pPause) { 91 if (m_Status == 1) 92 return m_Stretcher->Continue(pPause); 93 if (m_Status != 2) 94 return false; 95 if (m_pTransformer->Continue(pPause)) 96 return true; 97 98 RetainPtr<CFX_DIBitmap> pBitmap = m_pTransformer->DetachBitmap(); 99 if (!pBitmap || !pBitmap->GetBuffer()) 100 return false; 101 102 if (pBitmap->IsAlphaMask()) { 103 if (m_BitmapAlpha != 255) { 104 if (m_AlphaFlag >> 8) { 105 m_AlphaFlag = (((uint8_t)((m_AlphaFlag & 0xff) * m_BitmapAlpha / 255)) | 106 ((m_AlphaFlag >> 8) << 8)); 107 } else { 108 m_MaskColor = FXARGB_MUL_ALPHA(m_MaskColor, m_BitmapAlpha); 109 } 110 } 111 m_pDevice->CompositeMask( 112 m_pTransformer->result().left, m_pTransformer->result().top, 113 pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap, m_MaskColor, 0, 0, 114 m_BlendType, m_pClipRgn.Get(), m_bRgbByteOrder, m_AlphaFlag); 115 } else { 116 if (m_BitmapAlpha != 255) 117 pBitmap->MultiplyAlpha(m_BitmapAlpha); 118 m_pDevice->CompositeBitmap( 119 m_pTransformer->result().left, m_pTransformer->result().top, 120 pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap, 0, 0, m_BlendType, 121 m_pClipRgn.Get(), m_bRgbByteOrder); 122 } 123 return false; 124 } 125