summaryrefslogtreecommitdiff
path: root/xfa/fxfa/cxfa_imagerenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xfa/fxfa/cxfa_imagerenderer.cpp')
-rw-r--r--xfa/fxfa/cxfa_imagerenderer.cpp238
1 files changed, 238 insertions, 0 deletions
diff --git a/xfa/fxfa/cxfa_imagerenderer.cpp b/xfa/fxfa/cxfa_imagerenderer.cpp
new file mode 100644
index 0000000000..14f8b25af1
--- /dev/null
+++ b/xfa/fxfa/cxfa_imagerenderer.cpp
@@ -0,0 +1,238 @@
+// Copyright 2018 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/fxfa/cxfa_imagerenderer.h"
+
+#include "core/fpdfapi/page/cpdf_pageobjectholder.h"
+#include "core/fxge/cfx_renderdevice.h"
+#include "core/fxge/dib/cfx_dibsource.h"
+#include "core/fxge/dib/cfx_imagerenderer.h"
+#include "core/fxge/dib/cfx_imagetransformer.h"
+#include "third_party/base/ptr_util.h"
+
+CXFA_ImageRenderer::CXFA_ImageRenderer() : m_pDevice(nullptr) {}
+
+CXFA_ImageRenderer::~CXFA_ImageRenderer() {}
+
+bool CXFA_ImageRenderer::Start(CFX_RenderDevice* pDevice,
+ const RetainPtr<CFX_DIBSource>& pDIBSource,
+ FX_ARGB bitmap_argb,
+ int bitmap_alpha,
+ const CFX_Matrix* pImage2Device,
+ uint32_t flags,
+ int blendType) {
+ m_pDevice = pDevice;
+ m_pDIBSource = pDIBSource;
+ m_FillArgb = bitmap_argb;
+ m_BitmapAlpha = bitmap_alpha;
+ m_ImageMatrix = *pImage2Device;
+ m_Flags = flags;
+ m_BlendType = blendType;
+ return StartDIBSource();
+}
+
+bool CXFA_ImageRenderer::StartDIBSource() {
+ if (m_pDevice->StartDIBitsWithBlend(m_pDIBSource, m_BitmapAlpha, m_FillArgb,
+ &m_ImageMatrix, m_Flags, &m_DeviceHandle,
+ m_BlendType)) {
+ if (m_DeviceHandle) {
+ m_Status = 3;
+ return true;
+ }
+ return false;
+ }
+ CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect();
+ FX_RECT image_rect = image_rect_f.GetOuterRect();
+ int dest_width = image_rect.Width();
+ int dest_height = image_rect.Height();
+ if ((fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) ||
+ (fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) {
+ if (m_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) {
+ m_Result = false;
+ return false;
+ }
+ RetainPtr<CFX_DIBSource> pDib = m_pDIBSource;
+ if (m_pDIBSource->HasAlpha() &&
+ !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE) &&
+ !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
+ m_pCloneConvert = m_pDIBSource->CloneConvert(FXDIB_Rgb);
+ if (!m_pCloneConvert) {
+ m_Result = false;
+ return false;
+ }
+ pDib = m_pCloneConvert;
+ }
+ FX_RECT clip_box = m_pDevice->GetClipBox();
+ clip_box.Intersect(image_rect);
+ m_Status = 2;
+ m_pTransformer = pdfium::MakeUnique<CFX_ImageTransformer>(
+ pDib, &m_ImageMatrix, m_Flags, &clip_box);
+ return true;
+ }
+ if (m_ImageMatrix.a < 0)
+ dest_width = -dest_width;
+ if (m_ImageMatrix.d > 0)
+ dest_height = -dest_height;
+ int dest_left, dest_top;
+ dest_left = dest_width > 0 ? image_rect.left : image_rect.right;
+ dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom;
+ if (m_pDIBSource->IsOpaqueImage() && m_BitmapAlpha == 255) {
+ if (m_pDevice->StretchDIBitsWithFlagsAndBlend(
+ m_pDIBSource, dest_left, dest_top, dest_width, dest_height, m_Flags,
+ m_BlendType)) {
+ return false;
+ }
+ }
+ if (m_pDIBSource->IsAlphaMask()) {
+ if (m_BitmapAlpha != 255) {
+ m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha);
+ }
+ if (m_pDevice->StretchBitMaskWithFlags(m_pDIBSource, dest_left, dest_top,
+ dest_width, dest_height, m_FillArgb,
+ m_Flags)) {
+ return false;
+ }
+ }
+ if (m_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) {
+ m_Result = false;
+ return true;
+ }
+ FX_RECT clip_box = m_pDevice->GetClipBox();
+ FX_RECT dest_rect = clip_box;
+ dest_rect.Intersect(image_rect);
+ FX_RECT dest_clip(
+ dest_rect.left - image_rect.left, dest_rect.top - image_rect.top,
+ dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top);
+ RetainPtr<CFX_DIBitmap> pStretched =
+ m_pDIBSource->StretchTo(dest_width, dest_height, m_Flags, &dest_clip);
+ if (pStretched) {
+ CompositeDIBitmap(pStretched, dest_rect.left, dest_rect.top, m_FillArgb,
+ m_BitmapAlpha, m_BlendType, false);
+ }
+ return false;
+}
+
+bool CXFA_ImageRenderer::Continue() {
+ if (m_Status == 2) {
+ if (m_pTransformer->Continue(nullptr))
+ return true;
+
+ RetainPtr<CFX_DIBitmap> pBitmap = m_pTransformer->DetachBitmap();
+ if (!pBitmap)
+ return false;
+
+ if (pBitmap->IsAlphaMask()) {
+ if (m_BitmapAlpha != 255)
+ m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha);
+ m_Result =
+ m_pDevice->SetBitMask(pBitmap, m_pTransformer->result().left,
+ m_pTransformer->result().top, m_FillArgb);
+ } else {
+ if (m_BitmapAlpha != 255)
+ pBitmap->MultiplyAlpha(m_BitmapAlpha);
+ m_Result = m_pDevice->SetDIBitsWithBlend(
+ pBitmap, m_pTransformer->result().left, m_pTransformer->result().top,
+ m_BlendType);
+ }
+ return false;
+ }
+ if (m_Status == 3)
+ return m_pDevice->ContinueDIBits(m_DeviceHandle.get(), nullptr);
+
+ return false;
+}
+
+void CXFA_ImageRenderer::CompositeDIBitmap(
+ const RetainPtr<CFX_DIBitmap>& pDIBitmap,
+ int left,
+ int top,
+ FX_ARGB mask_argb,
+ int bitmap_alpha,
+ int blend_mode,
+ int iTransparency) {
+ if (!pDIBitmap) {
+ return;
+ }
+ bool bIsolated = !!(iTransparency & PDFTRANS_ISOLATED);
+ bool bGroup = !!(iTransparency & PDFTRANS_GROUP);
+ if (blend_mode == FXDIB_BLEND_NORMAL) {
+ if (!pDIBitmap->IsAlphaMask()) {
+ if (bitmap_alpha < 255) {
+ pDIBitmap->MultiplyAlpha(bitmap_alpha);
+ }
+ if (m_pDevice->SetDIBits(pDIBitmap, left, top)) {
+ return;
+ }
+ } else {
+ uint32_t fill_argb = (mask_argb);
+ if (bitmap_alpha < 255) {
+ ((uint8_t*)&fill_argb)[3] =
+ ((uint8_t*)&fill_argb)[3] * bitmap_alpha / 255;
+ }
+ if (m_pDevice->SetBitMask(pDIBitmap, left, top, fill_argb)) {
+ return;
+ }
+ }
+ }
+ bool bBackAlphaRequired = blend_mode && bIsolated;
+ bool bGetBackGround =
+ ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) ||
+ (!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) &&
+ (m_pDevice->GetRenderCaps() & FXRC_GET_BITS) && !bBackAlphaRequired);
+ if (bGetBackGround) {
+ if (bIsolated || !bGroup) {
+ if (pDIBitmap->IsAlphaMask()) {
+ return;
+ }
+ m_pDevice->SetDIBitsWithBlend(pDIBitmap, left, top, blend_mode);
+ } else {
+ FX_RECT rect(left, top, left + pDIBitmap->GetWidth(),
+ top + pDIBitmap->GetHeight());
+ rect.Intersect(m_pDevice->GetClipBox());
+ RetainPtr<CFX_DIBitmap> pClone;
+ if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) {
+ pClone = m_pDevice->GetBackDrop()->Clone(&rect);
+ RetainPtr<CFX_DIBitmap> pForeBitmap = m_pDevice->GetBitmap();
+ pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(),
+ pForeBitmap, rect.left, rect.top);
+ left = left >= 0 ? 0 : left;
+ top = top >= 0 ? 0 : top;
+ if (!pDIBitmap->IsAlphaMask())
+ pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(),
+ pDIBitmap, left, top, blend_mode);
+ else
+ pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(),
+ pDIBitmap, mask_argb, left, top, blend_mode);
+ } else {
+ pClone = pDIBitmap;
+ }
+ if (m_pDevice->GetBackDrop()) {
+ m_pDevice->SetDIBits(pClone, rect.left, rect.top);
+ } else {
+ if (pDIBitmap->IsAlphaMask())
+ return;
+ m_pDevice->SetDIBitsWithBlend(pDIBitmap, rect.left, rect.top,
+ blend_mode);
+ }
+ }
+ return;
+ }
+ if (!pDIBitmap->HasAlpha() ||
+ (m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE)) {
+ return;
+ }
+ RetainPtr<CFX_DIBitmap> pCloneConvert = pDIBitmap->CloneConvert(FXDIB_Rgb);
+ if (!pCloneConvert)
+ return;
+
+ CXFA_ImageRenderer imageRender;
+ if (!imageRender.Start(m_pDevice, pCloneConvert, m_FillArgb, m_BitmapAlpha,
+ &m_ImageMatrix, m_Flags)) {
+ return;
+ }
+ while (imageRender.Continue())
+ continue;
+}