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
CFX_ImageRenderer(const RetainPtr<CFX_DIBitmap> & pDevice,const CFX_ClipRgn * pClipRgn,const RetainPtr<CFX_DIBSource> & pSource,int bitmap_alpha,uint32_t mask_color,const CFX_Matrix * pMatrix,uint32_t dib_flags,bool bRgbByteOrder)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
~CFX_ImageRenderer()88 CFX_ImageRenderer::~CFX_ImageRenderer() {}
89
Continue(IFX_PauseIndicator * pPause)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