You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
5.2 KiB
159 lines
5.2 KiB
// 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/fxge/cfx_renderdevice.h"
|
|
#include "core/fxge/dib/cfx_dibbase.h"
|
|
#include "core/fxge/dib/cfx_dibitmap.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(CFX_RenderDevice* pDevice,
|
|
const RetainPtr<CFX_DIBBase>& pDIBBase,
|
|
const CFX_Matrix* pImage2Device)
|
|
: m_pDevice(pDevice), m_ImageMatrix(*pImage2Device), m_pDIBBase(pDIBBase) {}
|
|
|
|
CXFA_ImageRenderer::~CXFA_ImageRenderer() = default;
|
|
|
|
bool CXFA_ImageRenderer::Start() {
|
|
FXDIB_ResampleOptions options;
|
|
options.bInterpolateBilinear = true;
|
|
if (m_pDevice->StartDIBits(m_pDIBBase, 255, 0, m_ImageMatrix, options,
|
|
&m_DeviceHandle)) {
|
|
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)) {
|
|
RetainPtr<CFX_DIBBase> pDib = m_pDIBBase;
|
|
if (m_pDIBBase->HasAlpha() &&
|
|
!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE) &&
|
|
!(m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
|
|
m_pCloneConvert = m_pDIBBase->CloneConvert(FXDIB_Rgb);
|
|
if (!m_pCloneConvert)
|
|
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, options, &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_pDIBBase->IsOpaqueImage()) {
|
|
if (m_pDevice->StretchDIBitsWithFlagsAndBlend(
|
|
m_pDIBBase, dest_left, dest_top, dest_width, dest_height, options,
|
|
BlendMode::kNormal)) {
|
|
return false;
|
|
}
|
|
}
|
|
if (m_pDIBBase->IsAlphaMask()) {
|
|
if (m_pDevice->StretchBitMaskWithFlags(m_pDIBBase, dest_left, dest_top,
|
|
dest_width, dest_height, 0,
|
|
options)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
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_pDIBBase->StretchTo(dest_width, dest_height, options, &dest_clip);
|
|
if (pStretched)
|
|
CompositeDIBitmap(pStretched, dest_rect.left, dest_rect.top);
|
|
|
|
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()) {
|
|
m_pDevice->SetBitMask(pBitmap, m_pTransformer->result().left,
|
|
m_pTransformer->result().top, 0);
|
|
} else {
|
|
m_pDevice->SetDIBitsWithBlend(pBitmap, m_pTransformer->result().left,
|
|
m_pTransformer->result().top,
|
|
BlendMode::kNormal);
|
|
}
|
|
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) {
|
|
if (!pDIBitmap)
|
|
return;
|
|
|
|
if (!pDIBitmap->IsAlphaMask()) {
|
|
if (m_pDevice->SetDIBits(pDIBitmap, left, top))
|
|
return;
|
|
} else if (m_pDevice->SetBitMask(pDIBitmap, left, top, 0)) {
|
|
return;
|
|
}
|
|
|
|
bool bGetBackGround = ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) ||
|
|
(!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) &&
|
|
(m_pDevice->GetRenderCaps() & FXRC_GET_BITS));
|
|
if (bGetBackGround) {
|
|
if (pDIBitmap->IsAlphaMask())
|
|
return;
|
|
|
|
m_pDevice->SetDIBitsWithBlend(pDIBitmap, left, top, BlendMode::kNormal);
|
|
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(m_pDevice.Get(), pCloneConvert,
|
|
&m_ImageMatrix);
|
|
if (!imageRender.Start())
|
|
return;
|
|
|
|
while (imageRender.Continue())
|
|
continue;
|
|
}
|