From 43f382c23c24a7b8214f4ea461623f13e25ca02a Mon Sep 17 00:00:00 2001 From: npm Date: Wed, 23 Nov 2016 07:35:23 -0800 Subject: Move CPDF_ImageRenderer from render_int Review-Url: https://codereview.chromium.org/2525833002 --- BUILD.gn | 2 + core/fpdfapi/render/cpdf_imagerenderer.cpp | 608 +++++++++++++++++++++++++++++ core/fpdfapi/render/cpdf_imagerenderer.h | 71 ++++ core/fpdfapi/render/cpdf_renderstatus.cpp | 6 +- core/fpdfapi/render/fpdf_render_image.cpp | 597 ---------------------------- core/fpdfapi/render/render_int.h | 51 --- 6 files changed, 685 insertions(+), 650 deletions(-) create mode 100644 core/fpdfapi/render/cpdf_imagerenderer.cpp create mode 100644 core/fpdfapi/render/cpdf_imagerenderer.h diff --git a/BUILD.gn b/BUILD.gn index 6ce0545677..84a415cd4d 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -543,6 +543,8 @@ static_library("fpdfapi") { "core/fpdfapi/render/cpdf_docrenderdata.h", "core/fpdfapi/render/cpdf_imageloader.cpp", "core/fpdfapi/render/cpdf_imageloader.h", + "core/fpdfapi/render/cpdf_imagerenderer.cpp", + "core/fpdfapi/render/cpdf_imagerenderer.h", "core/fpdfapi/render/cpdf_pagerendercache.h", "core/fpdfapi/render/cpdf_progressiverenderer.h", "core/fpdfapi/render/cpdf_rendercontext.h", diff --git a/core/fpdfapi/render/cpdf_imagerenderer.cpp b/core/fpdfapi/render/cpdf_imagerenderer.cpp new file mode 100644 index 0000000000..6d951a8d39 --- /dev/null +++ b/core/fpdfapi/render/cpdf_imagerenderer.cpp @@ -0,0 +1,608 @@ +// Copyright 2016 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 "core/fpdfapi/render/cpdf_imagerenderer.h" + +#include + +#include "core/fpdfapi/page/cpdf_docpagedata.h" +#include "core/fpdfapi/page/cpdf_image.h" +#include "core/fpdfapi/page/cpdf_imageobject.h" +#include "core/fpdfapi/page/cpdf_page.h" +#include "core/fpdfapi/page/cpdf_pageobject.h" +#include "core/fpdfapi/page/cpdf_shadingpattern.h" +#include "core/fpdfapi/page/cpdf_tilingpattern.h" +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/render/cpdf_pagerendercache.h" +#include "core/fpdfapi/render/cpdf_rendercontext.h" +#include "core/fpdfapi/render/cpdf_renderstatus.h" +#include "core/fpdfapi/render/cpdf_transferfunc.h" +#include "core/fpdfapi/render/render_int.h" +#include "core/fpdfdoc/cpdf_occontext.h" +#include "core/fxcrt/fx_safe_types.h" +#include "core/fxge/cfx_fxgedevice.h" +#include "core/fxge/cfx_pathdata.h" + +#ifdef _SKIA_SUPPORT_ +#include "core/fxge/skia/fx_skia_device.h" +#endif + +CPDF_ImageRenderer::CPDF_ImageRenderer() { + m_pRenderStatus = nullptr; + m_pImageObject = nullptr; + m_Result = true; + m_Status = 0; + m_DeviceHandle = nullptr; + m_bStdCS = false; + m_bPatternColor = false; + m_BlendType = FXDIB_BLEND_NORMAL; + m_pPattern = nullptr; + m_pObj2Device = nullptr; +} + +CPDF_ImageRenderer::~CPDF_ImageRenderer() { + if (m_DeviceHandle) + m_pRenderStatus->m_pDevice->CancelDIBits(m_DeviceHandle); +} + +bool CPDF_ImageRenderer::StartLoadDIBSource() { + CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); + FX_RECT image_rect = image_rect_f.GetOuterRect(); + if (!image_rect.Valid()) + return false; + + int dest_width = image_rect.Width(); + int dest_height = image_rect.Height(); + if (m_ImageMatrix.a < 0) + dest_width = -dest_width; + if (m_ImageMatrix.d > 0) + dest_height = -dest_height; + if (m_Loader.Start( + m_pImageObject, m_pRenderStatus->m_pContext->GetPageCache(), m_bStdCS, + m_pRenderStatus->m_GroupFamily, m_pRenderStatus->m_bLoadMask, + m_pRenderStatus, dest_width, dest_height)) { + m_Status = 4; + return true; + } + return false; +} + +bool CPDF_ImageRenderer::StartRenderDIBSource() { + if (!m_Loader.m_pBitmap) + return false; + + m_BitmapAlpha = + FXSYS_round(255 * m_pImageObject->m_GeneralState.GetFillAlpha()); + m_pDIBSource = m_Loader.m_pBitmap; + if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_ALPHA && + !m_Loader.m_pMask) { + return StartBitmapAlpha(); + } + if (m_pImageObject->m_GeneralState.GetTR()) { + if (!m_pImageObject->m_GeneralState.GetTransferFunc()) { + m_pImageObject->m_GeneralState.SetTransferFunc( + m_pRenderStatus->GetTransferFunc( + m_pImageObject->m_GeneralState.GetTR())); + } + if (m_pImageObject->m_GeneralState.GetTransferFunc() && + !m_pImageObject->m_GeneralState.GetTransferFunc()->m_bIdentity) { + m_pDIBSource = m_Loader.m_pBitmap = + m_pImageObject->m_GeneralState.GetTransferFunc()->TranslateImage( + m_Loader.m_pBitmap, !m_Loader.m_bCached); + if (m_Loader.m_bCached && m_Loader.m_pMask) + m_Loader.m_pMask = m_Loader.m_pMask->Clone(); + m_Loader.m_bCached = false; + } + } + m_FillArgb = 0; + m_bPatternColor = false; + m_pPattern = nullptr; + if (m_pDIBSource->IsAlphaMask()) { + const CPDF_Color* pColor = m_pImageObject->m_ColorState.GetFillColor(); + if (pColor && pColor->IsPattern()) { + m_pPattern = pColor->GetPattern(); + if (m_pPattern) + m_bPatternColor = true; + } + m_FillArgb = m_pRenderStatus->GetFillArgb(m_pImageObject); + } else if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_GRAY) { + m_pClone.reset(m_pDIBSource->Clone()); + m_pClone->ConvertColorScale(m_pRenderStatus->m_Options.m_BackColor, + m_pRenderStatus->m_Options.m_ForeColor); + m_pDIBSource = m_pClone.get(); + } + m_Flags = 0; + if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_DOWNSAMPLE) + m_Flags |= RENDER_FORCE_DOWNSAMPLE; + else if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_HALFTONE) + m_Flags |= RENDER_FORCE_HALFTONE; + if (m_pRenderStatus->m_pDevice->GetDeviceClass() != FXDC_DISPLAY) { + CPDF_Object* pFilters = + m_pImageObject->GetImage()->GetStream()->GetDict()->GetDirectObjectFor( + "Filter"); + if (pFilters) { + if (pFilters->IsName()) { + CFX_ByteString bsDecodeType = pFilters->GetString(); + if (bsDecodeType == "DCTDecode" || bsDecodeType == "JPXDecode") + m_Flags |= FXRENDER_IMAGE_LOSSY; + } else if (CPDF_Array* pArray = pFilters->AsArray()) { + for (size_t i = 0; i < pArray->GetCount(); i++) { + CFX_ByteString bsDecodeType = pArray->GetStringAt(i); + if (bsDecodeType == "DCTDecode" || bsDecodeType == "JPXDecode") { + m_Flags |= FXRENDER_IMAGE_LOSSY; + break; + } + } + } + } + } + if (m_pRenderStatus->m_Options.m_Flags & RENDER_NOIMAGESMOOTH) + m_Flags |= FXDIB_NOSMOOTH; + else if (m_pImageObject->GetImage()->IsInterpol()) + m_Flags |= FXDIB_INTERPOL; + if (m_Loader.m_pMask) + return DrawMaskedImage(); + + if (m_bPatternColor) + return DrawPatternImage(m_pObj2Device); + + if (m_BitmapAlpha != 255 || !m_pImageObject->m_GeneralState || + !m_pImageObject->m_GeneralState.GetFillOP() || + m_pImageObject->m_GeneralState.GetOPMode() != 0 || + m_pImageObject->m_GeneralState.GetBlendType() != FXDIB_BLEND_NORMAL || + m_pImageObject->m_GeneralState.GetStrokeAlpha() != 1.0f || + m_pImageObject->m_GeneralState.GetFillAlpha() != 1.0f) { + return StartDIBSource(); + } + CPDF_Document* pDocument = nullptr; + CPDF_Page* pPage = nullptr; + if (m_pRenderStatus->m_pContext->GetPageCache()) { + pPage = m_pRenderStatus->m_pContext->GetPageCache()->GetPage(); + pDocument = pPage->m_pDocument; + } else { + pDocument = m_pImageObject->GetImage()->GetDocument(); + } + CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : nullptr; + CPDF_Object* pCSObj = + m_pImageObject->GetImage()->GetStream()->GetDict()->GetDirectObjectFor( + "ColorSpace"); + CPDF_ColorSpace* pColorSpace = + pDocument->LoadColorSpace(pCSObj, pPageResources); + if (!pColorSpace) + return StartDIBSource(); + int format = pColorSpace->GetFamily(); + if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION || + format == PDFCS_DEVICEN) { + m_BlendType = FXDIB_BLEND_DARKEN; + } + pDocument->GetPageData()->ReleaseColorSpace(pCSObj); + return StartDIBSource(); +} + +bool CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, + CPDF_PageObject* pObj, + const CFX_Matrix* pObj2Device, + bool bStdCS, + int blendType) { + m_pRenderStatus = pStatus; + m_bStdCS = bStdCS; + m_pImageObject = pObj->AsImage(); + m_BlendType = blendType; + m_pObj2Device = pObj2Device; + CPDF_Dictionary* pOC = m_pImageObject->GetImage()->GetOC(); + if (pOC && m_pRenderStatus->m_Options.m_pOCContext && + !m_pRenderStatus->m_Options.m_pOCContext->CheckOCGVisible(pOC)) { + return false; + } + m_ImageMatrix = m_pImageObject->matrix(); + m_ImageMatrix.Concat(*pObj2Device); + if (StartLoadDIBSource()) + return true; + return StartRenderDIBSource(); +} + +bool CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, + const CFX_DIBSource* pDIBSource, + FX_ARGB bitmap_argb, + int bitmap_alpha, + const CFX_Matrix* pImage2Device, + uint32_t flags, + bool bStdCS, + int blendType) { + m_pRenderStatus = pStatus; + m_pDIBSource = pDIBSource; + m_FillArgb = bitmap_argb; + m_BitmapAlpha = bitmap_alpha; + m_ImageMatrix = *pImage2Device; + m_Flags = flags; + m_bStdCS = bStdCS; + m_BlendType = blendType; + return StartDIBSource(); +} + +bool CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device) { + if (m_pRenderStatus->m_bPrint && + !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { + m_Result = false; + return false; + } + FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOuterRect(); + rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox()); + if (rect.IsEmpty()) + return false; + + CFX_Matrix new_matrix = m_ImageMatrix; + new_matrix.TranslateI(-rect.left, -rect.top); + int width = rect.Width(); + int height = rect.Height(); + CFX_FxgeDevice bitmap_device1; + if (!bitmap_device1.Create(rect.Width(), rect.Height(), FXDIB_Rgb32, nullptr)) + return true; + + bitmap_device1.GetBitmap()->Clear(0xffffff); + CPDF_RenderStatus bitmap_render; + bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device1, + nullptr, nullptr, nullptr, nullptr, + &m_pRenderStatus->m_Options, 0, + m_pRenderStatus->m_bDropObjects, nullptr, true); + CFX_Matrix patternDevice = *pObj2Device; + patternDevice.Translate((FX_FLOAT)-rect.left, (FX_FLOAT)-rect.top); + if (CPDF_TilingPattern* pTilingPattern = m_pPattern->AsTilingPattern()) { + bitmap_render.DrawTilingPattern(pTilingPattern, m_pImageObject, + &patternDevice, false); + } else if (CPDF_ShadingPattern* pShadingPattern = + m_pPattern->AsShadingPattern()) { + bitmap_render.DrawShadingPattern(pShadingPattern, m_pImageObject, + &patternDevice, false); + } + + CFX_FxgeDevice bitmap_device2; + if (!bitmap_device2.Create(rect.Width(), rect.Height(), FXDIB_8bppRgb, + nullptr)) { + return true; + } + bitmap_device2.GetBitmap()->Clear(0); + CPDF_RenderStatus bitmap_render2; + bitmap_render2.Initialize(m_pRenderStatus->m_pContext, &bitmap_device2, + nullptr, nullptr, nullptr, nullptr, nullptr, 0, + m_pRenderStatus->m_bDropObjects, nullptr, true); + CPDF_ImageRenderer image_render; + if (image_render.Start(&bitmap_render2, m_pDIBSource, 0xffffffff, 255, + &new_matrix, m_Flags, true, FXDIB_BLEND_NORMAL)) { + image_render.Continue(nullptr); + } + if (m_Loader.m_MatteColor != 0xffffffff) { + int matte_r = FXARGB_R(m_Loader.m_MatteColor); + int matte_g = FXARGB_G(m_Loader.m_MatteColor); + int matte_b = FXARGB_B(m_Loader.m_MatteColor); + for (int row = 0; row < height; row++) { + uint8_t* dest_scan = + (uint8_t*)bitmap_device1.GetBitmap()->GetScanline(row); + const uint8_t* mask_scan = bitmap_device2.GetBitmap()->GetScanline(row); + for (int col = 0; col < width; col++) { + int alpha = *mask_scan++; + if (!alpha) { + dest_scan += 4; + continue; + } + int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; + if (orig < 0) + orig = 0; + else if (orig > 255) + orig = 255; + *dest_scan++ = orig; + orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; + if (orig < 0) + orig = 0; + else if (orig > 255) + orig = 255; + *dest_scan++ = orig; + orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; + if (orig < 0) + orig = 0; + else if (orig > 255) + orig = 255; + *dest_scan++ = orig; + dest_scan++; + } + } + } + bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); + bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); + bitmap_device1.GetBitmap()->MultiplyAlpha(255); + m_pRenderStatus->m_pDevice->SetDIBitsWithBlend( + bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); + return false; +} + +bool CPDF_ImageRenderer::DrawMaskedImage() { + if (m_pRenderStatus->m_bPrint && + !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { + m_Result = false; + return false; + } + FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOuterRect(); + rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox()); + if (rect.IsEmpty()) + return false; + + CFX_Matrix new_matrix = m_ImageMatrix; + new_matrix.TranslateI(-rect.left, -rect.top); + int width = rect.Width(); + int height = rect.Height(); + CFX_FxgeDevice bitmap_device1; + if (!bitmap_device1.Create(width, height, FXDIB_Rgb32, nullptr)) + return true; + +#if defined _SKIA_SUPPORT_ + bitmap_device1.Clear(0xffffff); +#else + bitmap_device1.GetBitmap()->Clear(0xffffff); +#endif + CPDF_RenderStatus bitmap_render; + bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device1, + nullptr, nullptr, nullptr, nullptr, nullptr, 0, + m_pRenderStatus->m_bDropObjects, nullptr, true); + CPDF_ImageRenderer image_render; + if (image_render.Start(&bitmap_render, m_pDIBSource, 0, 255, &new_matrix, + m_Flags, true, FXDIB_BLEND_NORMAL)) { + image_render.Continue(nullptr); + } + CFX_FxgeDevice bitmap_device2; + if (!bitmap_device2.Create(width, height, FXDIB_8bppRgb, nullptr)) + return true; + +#if defined _SKIA_SUPPORT_ + bitmap_device2.Clear(0); +#else + bitmap_device2.GetBitmap()->Clear(0); +#endif + CPDF_RenderStatus bitmap_render2; + bitmap_render2.Initialize(m_pRenderStatus->m_pContext, &bitmap_device2, + nullptr, nullptr, nullptr, nullptr, nullptr, 0, + m_pRenderStatus->m_bDropObjects, nullptr, true); + CPDF_ImageRenderer image_render2; + if (image_render2.Start(&bitmap_render2, m_Loader.m_pMask, 0xffffffff, 255, + &new_matrix, m_Flags, true, FXDIB_BLEND_NORMAL)) { + image_render2.Continue(nullptr); + } + if (m_Loader.m_MatteColor != 0xffffffff) { + int matte_r = FXARGB_R(m_Loader.m_MatteColor); + int matte_g = FXARGB_G(m_Loader.m_MatteColor); + int matte_b = FXARGB_B(m_Loader.m_MatteColor); + for (int row = 0; row < height; row++) { + uint8_t* dest_scan = + (uint8_t*)bitmap_device1.GetBitmap()->GetScanline(row); + const uint8_t* mask_scan = bitmap_device2.GetBitmap()->GetScanline(row); + for (int col = 0; col < width; col++) { + int alpha = *mask_scan++; + if (alpha) { + int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; + if (orig < 0) { + orig = 0; + } else if (orig > 255) { + orig = 255; + } + *dest_scan++ = orig; + orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; + if (orig < 0) { + orig = 0; + } else if (orig > 255) { + orig = 255; + } + *dest_scan++ = orig; + orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; + if (orig < 0) { + orig = 0; + } else if (orig > 255) { + orig = 255; + } + *dest_scan++ = orig; + dest_scan++; + } else { + dest_scan += 4; + } + } + } + } +#ifdef _SKIA_SUPPORT_ + m_pRenderStatus->m_pDevice->SetBitsWithMask( + bitmap_device1.GetBitmap(), bitmap_device2.GetBitmap(), rect.left, + rect.top, m_BitmapAlpha, m_BlendType); +#else + bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); + bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); + if (m_BitmapAlpha < 255) + bitmap_device1.GetBitmap()->MultiplyAlpha(m_BitmapAlpha); + m_pRenderStatus->m_pDevice->SetDIBitsWithBlend( + bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); +#endif // _SKIA_SUPPORT_ + return false; +} + +bool CPDF_ImageRenderer::StartDIBSource() { + if (!(m_Flags & RENDER_FORCE_DOWNSAMPLE) && m_pDIBSource->GetBPP() > 1) { + FX_SAFE_SIZE_T image_size = m_pDIBSource->GetBPP(); + image_size /= 8; + image_size *= m_pDIBSource->GetWidth(); + image_size *= m_pDIBSource->GetHeight(); + if (!image_size.IsValid()) + return false; + + if (image_size.ValueOrDie() > FPDF_HUGE_IMAGE_SIZE && + !(m_Flags & RENDER_FORCE_HALFTONE)) { + m_Flags |= RENDER_FORCE_DOWNSAMPLE; + } + } +#ifdef _SKIA_SUPPORT_ + CFX_DIBitmap* premultiplied = m_pDIBSource->Clone(); + if (m_pDIBSource->HasAlpha()) + CFX_SkiaDeviceDriver::PreMultiply(premultiplied); + if (m_pRenderStatus->m_pDevice->StartDIBitsWithBlend( + premultiplied, m_BitmapAlpha, m_FillArgb, &m_ImageMatrix, m_Flags, + m_DeviceHandle, m_BlendType)) { + if (m_DeviceHandle) { + m_Status = 3; + return true; + } + return false; + } +#else + if (m_pRenderStatus->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; + } +#endif + 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 ((FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) || + (FXSYS_fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) { + if (m_pRenderStatus->m_bPrint && + !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { + m_Result = false; + return false; + } + FX_RECT clip_box = m_pRenderStatus->m_pDevice->GetClipBox(); + clip_box.Intersect(image_rect); + m_Status = 2; + m_pTransformer.reset(new CFX_ImageTransformer(m_pDIBSource, &m_ImageMatrix, + m_Flags, &clip_box)); + m_pTransformer->Start(); + return true; + } + if (m_ImageMatrix.a < 0) + dest_width = -dest_width; + + if (m_ImageMatrix.d > 0) + dest_height = -dest_height; + + int dest_left = dest_width > 0 ? image_rect.left : image_rect.right; + int dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom; + if (m_pDIBSource->IsOpaqueImage() && m_BitmapAlpha == 255) { + if (m_pRenderStatus->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_pRenderStatus->m_pDevice->StretchBitMaskWithFlags( + m_pDIBSource, dest_left, dest_top, dest_width, dest_height, + m_FillArgb, m_Flags)) { + return false; + } + } + if (m_pRenderStatus->m_bPrint && + !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { + m_Result = false; + return true; + } + + FX_RECT clip_box = m_pRenderStatus->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); + std::unique_ptr pStretched( + m_pDIBSource->StretchTo(dest_width, dest_height, m_Flags, &dest_clip)); + if (pStretched) { + m_pRenderStatus->CompositeDIBitmap(pStretched.get(), dest_rect.left, + dest_rect.top, m_FillArgb, m_BitmapAlpha, + m_BlendType, false); + } + return false; +} + +bool CPDF_ImageRenderer::StartBitmapAlpha() { + if (m_pDIBSource->IsOpaqueImage()) { + CFX_PathData path; + path.AppendRect(0, 0, 1, 1); + path.Transform(&m_ImageMatrix); + uint32_t fill_color = + ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha); + m_pRenderStatus->m_pDevice->DrawPath(&path, nullptr, nullptr, fill_color, 0, + FXFILL_WINDING); + return false; + } + const CFX_DIBSource* pAlphaMask = + m_pDIBSource->IsAlphaMask() ? m_pDIBSource : m_pDIBSource->GetAlphaMask(); + if (FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || + FXSYS_fabs(m_ImageMatrix.c) >= 0.5f) { + int left, top; + std::unique_ptr pTransformed( + pAlphaMask->TransformTo(&m_ImageMatrix, left, top)); + if (!pTransformed) + return true; + + m_pRenderStatus->m_pDevice->SetBitMask( + pTransformed.get(), left, top, + ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha)); + } else { + CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); + FX_RECT image_rect = image_rect_f.GetOuterRect(); + int dest_width = + m_ImageMatrix.a > 0 ? image_rect.Width() : -image_rect.Width(); + int dest_height = + m_ImageMatrix.d > 0 ? -image_rect.Height() : image_rect.Height(); + int left = dest_width > 0 ? image_rect.left : image_rect.right; + int top = dest_height > 0 ? image_rect.top : image_rect.bottom; + m_pRenderStatus->m_pDevice->StretchBitMask( + pAlphaMask, left, top, dest_width, dest_height, + ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha)); + } + if (m_pDIBSource != pAlphaMask) + delete pAlphaMask; + return false; +} + +bool CPDF_ImageRenderer::Continue(IFX_Pause* pPause) { + if (m_Status == 2) { + if (m_pTransformer->Continue(pPause)) + return true; + + std::unique_ptr 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_pRenderStatus->m_pDevice->SetBitMask( + pBitmap.get(), m_pTransformer->result().left, + m_pTransformer->result().top, m_FillArgb); + } else { + if (m_BitmapAlpha != 255) + pBitmap->MultiplyAlpha(m_BitmapAlpha); + m_Result = m_pRenderStatus->m_pDevice->SetDIBitsWithBlend( + pBitmap.get(), m_pTransformer->result().left, + m_pTransformer->result().top, m_BlendType); + } + return false; + } + if (m_Status == 3) + return m_pRenderStatus->m_pDevice->ContinueDIBits(m_DeviceHandle, pPause); + + if (m_Status == 4) { + if (m_Loader.Continue(pPause)) + return true; + + if (StartRenderDIBSource()) + return Continue(pPause); + } + return false; +} diff --git a/core/fpdfapi/render/cpdf_imagerenderer.h b/core/fpdfapi/render/cpdf_imagerenderer.h new file mode 100644 index 0000000000..b0550e7441 --- /dev/null +++ b/core/fpdfapi/render/cpdf_imagerenderer.h @@ -0,0 +1,71 @@ +// Copyright 2016 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 + +#ifndef CORE_FPDFAPI_RENDER_CPDF_IMAGERENDERER_H_ +#define CORE_FPDFAPI_RENDER_CPDF_IMAGERENDERER_H_ + +#include + +#include "core/fpdfapi/render/cpdf_imageloader.h" + +class CFX_ImageTransformer; +class CPDF_ImageObject; +class CPDF_PageObject; +class CPDF_Pattern; +class CPDF_RenderStatus; + +class CPDF_ImageRenderer { + public: + CPDF_ImageRenderer(); + ~CPDF_ImageRenderer(); + + bool Start(CPDF_RenderStatus* pStatus, + CPDF_PageObject* pObj, + const CFX_Matrix* pObj2Device, + bool bStdCS, + int blendType); + + bool Start(CPDF_RenderStatus* pStatus, + const CFX_DIBSource* pDIBSource, + FX_ARGB bitmap_argb, + int bitmap_alpha, + const CFX_Matrix* pImage2Device, + uint32_t flags, + bool bStdCS, + int blendType); + + bool Continue(IFX_Pause* pPause); + + bool m_Result; + + private: + bool StartBitmapAlpha(); + bool StartDIBSource(); + bool StartRenderDIBSource(); + bool StartLoadDIBSource(); + bool DrawMaskedImage(); + bool DrawPatternImage(const CFX_Matrix* pObj2Device); + + CPDF_RenderStatus* m_pRenderStatus; + CPDF_ImageObject* m_pImageObject; + int m_Status; + const CFX_Matrix* m_pObj2Device; + CFX_Matrix m_ImageMatrix; + CPDF_ImageLoader m_Loader; + const CFX_DIBSource* m_pDIBSource; + std::unique_ptr m_pClone; + int m_BitmapAlpha; + bool m_bPatternColor; + CPDF_Pattern* m_pPattern; + FX_ARGB m_FillArgb; + uint32_t m_Flags; + std::unique_ptr m_pTransformer; + void* m_DeviceHandle; + bool m_bStdCS; + int m_BlendType; +}; + +#endif // CORE_FPDFAPI_RENDER_CPDF_IMAGERENDERER_H_ diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp index aad9af04e3..7e0d30f286 100644 --- a/core/fpdfapi/render/cpdf_renderstatus.cpp +++ b/core/fpdfapi/render/cpdf_renderstatus.cpp @@ -34,6 +34,7 @@ #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/render/cpdf_charposlist.h" #include "core/fpdfapi/render/cpdf_docrenderdata.h" +#include "core/fpdfapi/render/cpdf_imagerenderer.h" #include "core/fpdfapi/render/cpdf_pagerendercache.h" #include "core/fpdfapi/render/cpdf_rendercontext.h" #include "core/fpdfapi/render/cpdf_renderoptions.h" @@ -1075,7 +1076,8 @@ bool CPDF_RenderStatus::ContinueSingleObject(CPDF_PageObject* pObj, if (pObj->IsImage()) { m_pImageRenderer.reset(new CPDF_ImageRenderer); - if (!m_pImageRenderer->Start(this, pObj, pObj2Device, false)) { + if (!m_pImageRenderer->Start(this, pObj, pObj2Device, false, + FXDIB_BLEND_NORMAL)) { if (!m_pImageRenderer->m_Result) DrawObjWithBackground(pObj, pObj2Device); m_pImageRenderer.reset(); @@ -1894,7 +1896,7 @@ bool CPDF_RenderStatus::ProcessType3Text(CPDF_TextObject* textobj, image_matrix.Concat(matrix); CPDF_ImageRenderer renderer; if (renderer.Start(this, pType3Char->m_pBitmap.get(), fill_argb, 255, - &image_matrix, 0, false)) { + &image_matrix, 0, false, FXDIB_BLEND_NORMAL)) { renderer.Continue(nullptr); } if (!renderer.m_Result) diff --git a/core/fpdfapi/render/fpdf_render_image.cpp b/core/fpdfapi/render/fpdf_render_image.cpp index b95828c0cc..da5eda2020 100644 --- a/core/fpdfapi/render/fpdf_render_image.cpp +++ b/core/fpdfapi/render/fpdf_render_image.cpp @@ -204,603 +204,6 @@ void CPDF_DIBTransferFunc::TranslateDownSamples(uint8_t* dest_buf, } } -CPDF_ImageRenderer::CPDF_ImageRenderer() { - m_pRenderStatus = nullptr; - m_pImageObject = nullptr; - m_Result = true; - m_Status = 0; - m_DeviceHandle = nullptr; - m_bStdCS = false; - m_bPatternColor = false; - m_BlendType = FXDIB_BLEND_NORMAL; - m_pPattern = nullptr; - m_pObj2Device = nullptr; -} - -CPDF_ImageRenderer::~CPDF_ImageRenderer() { - if (m_DeviceHandle) { - m_pRenderStatus->m_pDevice->CancelDIBits(m_DeviceHandle); - } -} - -bool CPDF_ImageRenderer::StartLoadDIBSource() { - CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); - FX_RECT image_rect = image_rect_f.GetOuterRect(); - if (!image_rect.Valid()) - return false; - - int dest_width = image_rect.Width(); - int dest_height = image_rect.Height(); - if (m_ImageMatrix.a < 0) { - dest_width = -dest_width; - } - if (m_ImageMatrix.d > 0) { - dest_height = -dest_height; - } - if (m_Loader.Start( - m_pImageObject, m_pRenderStatus->m_pContext->GetPageCache(), m_bStdCS, - m_pRenderStatus->m_GroupFamily, m_pRenderStatus->m_bLoadMask, - m_pRenderStatus, dest_width, dest_height)) { - m_Status = 4; - return true; - } - return false; -} - -bool CPDF_ImageRenderer::StartRenderDIBSource() { - if (!m_Loader.m_pBitmap) - return false; - - m_BitmapAlpha = - FXSYS_round(255 * m_pImageObject->m_GeneralState.GetFillAlpha()); - m_pDIBSource = m_Loader.m_pBitmap; - if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_ALPHA && - !m_Loader.m_pMask) { - return StartBitmapAlpha(); - } - if (m_pImageObject->m_GeneralState.GetTR()) { - if (!m_pImageObject->m_GeneralState.GetTransferFunc()) { - m_pImageObject->m_GeneralState.SetTransferFunc( - m_pRenderStatus->GetTransferFunc( - m_pImageObject->m_GeneralState.GetTR())); - } - if (m_pImageObject->m_GeneralState.GetTransferFunc() && - !m_pImageObject->m_GeneralState.GetTransferFunc()->m_bIdentity) { - m_pDIBSource = m_Loader.m_pBitmap = - m_pImageObject->m_GeneralState.GetTransferFunc()->TranslateImage( - m_Loader.m_pBitmap, !m_Loader.m_bCached); - if (m_Loader.m_bCached && m_Loader.m_pMask) { - m_Loader.m_pMask = m_Loader.m_pMask->Clone(); - } - m_Loader.m_bCached = false; - } - } - m_FillArgb = 0; - m_bPatternColor = false; - m_pPattern = nullptr; - if (m_pDIBSource->IsAlphaMask()) { - const CPDF_Color* pColor = m_pImageObject->m_ColorState.GetFillColor(); - if (pColor && pColor->IsPattern()) { - m_pPattern = pColor->GetPattern(); - if (m_pPattern) { - m_bPatternColor = true; - } - } - m_FillArgb = m_pRenderStatus->GetFillArgb(m_pImageObject); - } else if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_GRAY) { - m_pClone.reset(m_pDIBSource->Clone()); - m_pClone->ConvertColorScale(m_pRenderStatus->m_Options.m_BackColor, - m_pRenderStatus->m_Options.m_ForeColor); - m_pDIBSource = m_pClone.get(); - } - m_Flags = 0; - if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_DOWNSAMPLE) { - m_Flags |= RENDER_FORCE_DOWNSAMPLE; - } else if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_HALFTONE) { - m_Flags |= RENDER_FORCE_HALFTONE; - } - if (m_pRenderStatus->m_pDevice->GetDeviceClass() != FXDC_DISPLAY) { - CPDF_Object* pFilters = - m_pImageObject->GetImage()->GetStream()->GetDict()->GetDirectObjectFor( - "Filter"); - if (pFilters) { - if (pFilters->IsName()) { - CFX_ByteString bsDecodeType = pFilters->GetString(); - if (bsDecodeType == "DCTDecode" || bsDecodeType == "JPXDecode") { - m_Flags |= FXRENDER_IMAGE_LOSSY; - } - } else if (CPDF_Array* pArray = pFilters->AsArray()) { - for (size_t i = 0; i < pArray->GetCount(); i++) { - CFX_ByteString bsDecodeType = pArray->GetStringAt(i); - if (bsDecodeType == "DCTDecode" || bsDecodeType == "JPXDecode") { - m_Flags |= FXRENDER_IMAGE_LOSSY; - break; - } - } - } - } - } - if (m_pRenderStatus->m_Options.m_Flags & RENDER_NOIMAGESMOOTH) { - m_Flags |= FXDIB_NOSMOOTH; - } else if (m_pImageObject->GetImage()->IsInterpol()) { - m_Flags |= FXDIB_INTERPOL; - } - if (m_Loader.m_pMask) { - return DrawMaskedImage(); - } - if (m_bPatternColor) { - return DrawPatternImage(m_pObj2Device); - } - if (m_BitmapAlpha == 255 && m_pImageObject->m_GeneralState && - m_pImageObject->m_GeneralState.GetFillOP() && - m_pImageObject->m_GeneralState.GetOPMode() == 0 && - m_pImageObject->m_GeneralState.GetBlendType() == FXDIB_BLEND_NORMAL && - m_pImageObject->m_GeneralState.GetStrokeAlpha() == 1.0f && - m_pImageObject->m_GeneralState.GetFillAlpha() == 1.0f) { - CPDF_Document* pDocument = nullptr; - CPDF_Page* pPage = nullptr; - if (m_pRenderStatus->m_pContext->GetPageCache()) { - pPage = m_pRenderStatus->m_pContext->GetPageCache()->GetPage(); - pDocument = pPage->m_pDocument; - } else { - pDocument = m_pImageObject->GetImage()->GetDocument(); - } - CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : nullptr; - CPDF_Object* pCSObj = - m_pImageObject->GetImage()->GetStream()->GetDict()->GetDirectObjectFor( - "ColorSpace"); - CPDF_ColorSpace* pColorSpace = - pDocument->LoadColorSpace(pCSObj, pPageResources); - if (pColorSpace) { - int format = pColorSpace->GetFamily(); - if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION || - format == PDFCS_DEVICEN) { - m_BlendType = FXDIB_BLEND_DARKEN; - } - pDocument->GetPageData()->ReleaseColorSpace(pCSObj); - } - } - return StartDIBSource(); -} - -bool CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, - CPDF_PageObject* pObj, - const CFX_Matrix* pObj2Device, - bool bStdCS, - int blendType) { - m_pRenderStatus = pStatus; - m_bStdCS = bStdCS; - m_pImageObject = pObj->AsImage(); - m_BlendType = blendType; - m_pObj2Device = pObj2Device; - CPDF_Dictionary* pOC = m_pImageObject->GetImage()->GetOC(); - if (pOC && m_pRenderStatus->m_Options.m_pOCContext && - !m_pRenderStatus->m_Options.m_pOCContext->CheckOCGVisible(pOC)) { - return false; - } - m_ImageMatrix = m_pImageObject->matrix(); - m_ImageMatrix.Concat(*pObj2Device); - if (StartLoadDIBSource()) - return true; - return StartRenderDIBSource(); -} - -bool CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, - const CFX_DIBSource* pDIBSource, - FX_ARGB bitmap_argb, - int bitmap_alpha, - const CFX_Matrix* pImage2Device, - uint32_t flags, - bool bStdCS, - int blendType) { - m_pRenderStatus = pStatus; - m_pDIBSource = pDIBSource; - m_FillArgb = bitmap_argb; - m_BitmapAlpha = bitmap_alpha; - m_ImageMatrix = *pImage2Device; - m_Flags = flags; - m_bStdCS = bStdCS; - m_BlendType = blendType; - return StartDIBSource(); -} - -bool CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device) { - if (m_pRenderStatus->m_bPrint && - !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { - m_Result = false; - return false; - } - FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOuterRect(); - rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox()); - if (rect.IsEmpty()) { - return false; - } - CFX_Matrix new_matrix = m_ImageMatrix; - new_matrix.TranslateI(-rect.left, -rect.top); - int width = rect.Width(); - int height = rect.Height(); - CFX_FxgeDevice bitmap_device1; - if (!bitmap_device1.Create(rect.Width(), rect.Height(), FXDIB_Rgb32, nullptr)) - return true; - - bitmap_device1.GetBitmap()->Clear(0xffffff); - { - CPDF_RenderStatus bitmap_render; - bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device1, - nullptr, nullptr, nullptr, nullptr, - &m_pRenderStatus->m_Options, 0, - m_pRenderStatus->m_bDropObjects, nullptr, true); - CFX_Matrix patternDevice = *pObj2Device; - patternDevice.Translate((FX_FLOAT)-rect.left, (FX_FLOAT)-rect.top); - if (CPDF_TilingPattern* pTilingPattern = m_pPattern->AsTilingPattern()) { - bitmap_render.DrawTilingPattern(pTilingPattern, m_pImageObject, - &patternDevice, false); - } else if (CPDF_ShadingPattern* pShadingPattern = - m_pPattern->AsShadingPattern()) { - bitmap_render.DrawShadingPattern(pShadingPattern, m_pImageObject, - &patternDevice, false); - } - } - { - CFX_FxgeDevice bitmap_device2; - if (!bitmap_device2.Create(rect.Width(), rect.Height(), FXDIB_8bppRgb, - nullptr)) { - return true; - } - bitmap_device2.GetBitmap()->Clear(0); - CPDF_RenderStatus bitmap_render; - bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device2, - nullptr, nullptr, nullptr, nullptr, nullptr, 0, - m_pRenderStatus->m_bDropObjects, nullptr, true); - CPDF_ImageRenderer image_render; - if (image_render.Start(&bitmap_render, m_pDIBSource, 0xffffffff, 255, - &new_matrix, m_Flags, true)) { - image_render.Continue(nullptr); - } - if (m_Loader.m_MatteColor != 0xffffffff) { - int matte_r = FXARGB_R(m_Loader.m_MatteColor); - int matte_g = FXARGB_G(m_Loader.m_MatteColor); - int matte_b = FXARGB_B(m_Loader.m_MatteColor); - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = - (uint8_t*)bitmap_device1.GetBitmap()->GetScanline(row); - const uint8_t* mask_scan = bitmap_device2.GetBitmap()->GetScanline(row); - for (int col = 0; col < width; col++) { - int alpha = *mask_scan++; - if (alpha) { - int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; - if (orig < 0) { - orig = 0; - } else if (orig > 255) { - orig = 255; - } - *dest_scan++ = orig; - orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; - if (orig < 0) { - orig = 0; - } else if (orig > 255) { - orig = 255; - } - *dest_scan++ = orig; - orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; - if (orig < 0) { - orig = 0; - } else if (orig > 255) { - orig = 255; - } - *dest_scan++ = orig; - dest_scan++; - } else { - dest_scan += 4; - } - } - } - } - bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); - bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); - bitmap_device1.GetBitmap()->MultiplyAlpha(255); - } - m_pRenderStatus->m_pDevice->SetDIBitsWithBlend( - bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); - return false; -} - -bool CPDF_ImageRenderer::DrawMaskedImage() { - if (m_pRenderStatus->m_bPrint && - !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { - m_Result = false; - return false; - } - FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOuterRect(); - rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox()); - if (rect.IsEmpty()) { - return false; - } - CFX_Matrix new_matrix = m_ImageMatrix; - new_matrix.TranslateI(-rect.left, -rect.top); - int width = rect.Width(); - int height = rect.Height(); - CFX_FxgeDevice bitmap_device1; - if (!bitmap_device1.Create(width, height, FXDIB_Rgb32, nullptr)) - return true; - -#if defined _SKIA_SUPPORT_ - bitmap_device1.Clear(0xffffff); -#else - bitmap_device1.GetBitmap()->Clear(0xffffff); -#endif - { - CPDF_RenderStatus bitmap_render; - bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device1, - nullptr, nullptr, nullptr, nullptr, nullptr, 0, - m_pRenderStatus->m_bDropObjects, nullptr, true); - CPDF_ImageRenderer image_render; - if (image_render.Start(&bitmap_render, m_pDIBSource, 0, 255, &new_matrix, - m_Flags, true)) { - image_render.Continue(nullptr); - } - } - { - CFX_FxgeDevice bitmap_device2; - if (!bitmap_device2.Create(width, height, FXDIB_8bppRgb, nullptr)) - return true; - -#if defined _SKIA_SUPPORT_ - bitmap_device2.Clear(0); -#else - bitmap_device2.GetBitmap()->Clear(0); -#endif - CPDF_RenderStatus bitmap_render; - bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device2, - nullptr, nullptr, nullptr, nullptr, nullptr, 0, - m_pRenderStatus->m_bDropObjects, nullptr, true); - CPDF_ImageRenderer image_render; - if (image_render.Start(&bitmap_render, m_Loader.m_pMask, 0xffffffff, 255, - &new_matrix, m_Flags, true)) { - image_render.Continue(nullptr); - } - if (m_Loader.m_MatteColor != 0xffffffff) { - int matte_r = FXARGB_R(m_Loader.m_MatteColor); - int matte_g = FXARGB_G(m_Loader.m_MatteColor); - int matte_b = FXARGB_B(m_Loader.m_MatteColor); - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = - (uint8_t*)bitmap_device1.GetBitmap()->GetScanline(row); - const uint8_t* mask_scan = bitmap_device2.GetBitmap()->GetScanline(row); - for (int col = 0; col < width; col++) { - int alpha = *mask_scan++; - if (alpha) { - int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; - if (orig < 0) { - orig = 0; - } else if (orig > 255) { - orig = 255; - } - *dest_scan++ = orig; - orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; - if (orig < 0) { - orig = 0; - } else if (orig > 255) { - orig = 255; - } - *dest_scan++ = orig; - orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; - if (orig < 0) { - orig = 0; - } else if (orig > 255) { - orig = 255; - } - *dest_scan++ = orig; - dest_scan++; - } else { - dest_scan += 4; - } - } - } - } -#ifdef _SKIA_SUPPORT_ - m_pRenderStatus->m_pDevice->SetBitsWithMask( - bitmap_device1.GetBitmap(), bitmap_device2.GetBitmap(), rect.left, - rect.top, m_BitmapAlpha, m_BlendType); - } -#else - bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); - bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); - if (m_BitmapAlpha < 255) { - bitmap_device1.GetBitmap()->MultiplyAlpha(m_BitmapAlpha); - } - } - m_pRenderStatus->m_pDevice->SetDIBitsWithBlend( - bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); -#endif // _SKIA_SUPPORT_ - return false; -} - -bool CPDF_ImageRenderer::StartDIBSource() { - if (!(m_Flags & RENDER_FORCE_DOWNSAMPLE) && m_pDIBSource->GetBPP() > 1) { - FX_SAFE_SIZE_T image_size = m_pDIBSource->GetBPP(); - image_size /= 8; - image_size *= m_pDIBSource->GetWidth(); - image_size *= m_pDIBSource->GetHeight(); - if (!image_size.IsValid()) { - return false; - } - - if (image_size.ValueOrDie() > FPDF_HUGE_IMAGE_SIZE && - !(m_Flags & RENDER_FORCE_HALFTONE)) { - m_Flags |= RENDER_FORCE_DOWNSAMPLE; - } - } -#ifdef _SKIA_SUPPORT_ - CFX_DIBitmap* premultiplied = m_pDIBSource->Clone(); - if (m_pDIBSource->HasAlpha()) - CFX_SkiaDeviceDriver::PreMultiply(premultiplied); - if (m_pRenderStatus->m_pDevice->StartDIBitsWithBlend( - premultiplied, m_BitmapAlpha, m_FillArgb, &m_ImageMatrix, m_Flags, - m_DeviceHandle, m_BlendType)) { - if (m_DeviceHandle) { - m_Status = 3; - return true; - } - return false; - } -#else - if (m_pRenderStatus->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; - } -#endif - 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 ((FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) || - (FXSYS_fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) { - if (m_pRenderStatus->m_bPrint && - !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { - m_Result = false; - return false; - } - FX_RECT clip_box = m_pRenderStatus->m_pDevice->GetClipBox(); - clip_box.Intersect(image_rect); - m_Status = 2; - m_pTransformer.reset(new CFX_ImageTransformer(m_pDIBSource, &m_ImageMatrix, - m_Flags, &clip_box)); - m_pTransformer->Start(); - return true; - } - if (m_ImageMatrix.a < 0) - dest_width = -dest_width; - - if (m_ImageMatrix.d > 0) - dest_height = -dest_height; - - int dest_left = dest_width > 0 ? image_rect.left : image_rect.right; - int dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom; - if (m_pDIBSource->IsOpaqueImage() && m_BitmapAlpha == 255) { - if (m_pRenderStatus->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_pRenderStatus->m_pDevice->StretchBitMaskWithFlags( - m_pDIBSource, dest_left, dest_top, dest_width, dest_height, - m_FillArgb, m_Flags)) { - return false; - } - } - if (m_pRenderStatus->m_bPrint && - !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { - m_Result = false; - return true; - } - - FX_RECT clip_box = m_pRenderStatus->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); - std::unique_ptr pStretched( - m_pDIBSource->StretchTo(dest_width, dest_height, m_Flags, &dest_clip)); - if (pStretched) { - m_pRenderStatus->CompositeDIBitmap(pStretched.get(), dest_rect.left, - dest_rect.top, m_FillArgb, m_BitmapAlpha, - m_BlendType, false); - } - return false; -} - -bool CPDF_ImageRenderer::StartBitmapAlpha() { - if (m_pDIBSource->IsOpaqueImage()) { - CFX_PathData path; - path.AppendRect(0, 0, 1, 1); - path.Transform(&m_ImageMatrix); - uint32_t fill_color = - ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha); - m_pRenderStatus->m_pDevice->DrawPath(&path, nullptr, nullptr, fill_color, 0, - FXFILL_WINDING); - } else { - const CFX_DIBSource* pAlphaMask = m_pDIBSource->IsAlphaMask() - ? m_pDIBSource - : m_pDIBSource->GetAlphaMask(); - if (FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || - FXSYS_fabs(m_ImageMatrix.c) >= 0.5f) { - int left, top; - std::unique_ptr pTransformed( - pAlphaMask->TransformTo(&m_ImageMatrix, left, top)); - if (!pTransformed) - return true; - - m_pRenderStatus->m_pDevice->SetBitMask( - pTransformed.get(), left, top, - ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha)); - } else { - CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); - FX_RECT image_rect = image_rect_f.GetOuterRect(); - int dest_width = - m_ImageMatrix.a > 0 ? image_rect.Width() : -image_rect.Width(); - int dest_height = - m_ImageMatrix.d > 0 ? -image_rect.Height() : image_rect.Height(); - int left = dest_width > 0 ? image_rect.left : image_rect.right; - int top = dest_height > 0 ? image_rect.top : image_rect.bottom; - m_pRenderStatus->m_pDevice->StretchBitMask( - pAlphaMask, left, top, dest_width, dest_height, - ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha)); - } - if (m_pDIBSource != pAlphaMask) { - delete pAlphaMask; - } - } - return false; -} - -bool CPDF_ImageRenderer::Continue(IFX_Pause* pPause) { - if (m_Status == 2) { - if (m_pTransformer->Continue(pPause)) - return true; - - std::unique_ptr 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_pRenderStatus->m_pDevice->SetBitMask( - pBitmap.get(), m_pTransformer->result().left, - m_pTransformer->result().top, m_FillArgb); - } else { - if (m_BitmapAlpha != 255) - pBitmap->MultiplyAlpha(m_BitmapAlpha); - m_Result = m_pRenderStatus->m_pDevice->SetDIBitsWithBlend( - pBitmap.get(), m_pTransformer->result().left, - m_pTransformer->result().top, m_BlendType); - } - return false; - } - if (m_Status == 3) - return m_pRenderStatus->m_pDevice->ContinueDIBits(m_DeviceHandle, pPause); - - if (m_Status == 4) { - if (m_Loader.Continue(pPause)) - return true; - - if (StartRenderDIBSource()) - return Continue(pPause); - } - return false; -} - CCodec_ScanlineDecoder* FPDFAPI_CreateFlateDecoder( const uint8_t* src_buf, uint32_t src_size, diff --git a/core/fpdfapi/render/render_int.h b/core/fpdfapi/render/render_int.h index 3e35e14520..35b8cc529e 100644 --- a/core/fpdfapi/render/render_int.h +++ b/core/fpdfapi/render/render_int.h @@ -33,7 +33,6 @@ class CPDF_Font; class CPDF_FormObject; class CPDF_ImageCacheEntry; class CPDF_ImageObject; -class CPDF_ImageRenderer; class CPDF_Object; class CPDF_PageObject; class CPDF_PageObjectHolder; @@ -50,56 +49,6 @@ class CPDF_Type3Glyphs; class CPDF_Type3Char; class CPDF_Type3Font; -class CPDF_ImageRenderer { - public: - CPDF_ImageRenderer(); - ~CPDF_ImageRenderer(); - - bool Start(CPDF_RenderStatus* pStatus, - CPDF_PageObject* pObj, - const CFX_Matrix* pObj2Device, - bool bStdCS, - int blendType = FXDIB_BLEND_NORMAL); - bool Continue(IFX_Pause* pPause); - - bool Start(CPDF_RenderStatus* pStatus, - const CFX_DIBSource* pDIBSource, - FX_ARGB bitmap_argb, - int bitmap_alpha, - const CFX_Matrix* pImage2Device, - uint32_t flags, - bool bStdCS, - int blendType = FXDIB_BLEND_NORMAL); - - bool m_Result; - - protected: - bool StartBitmapAlpha(); - bool StartDIBSource(); - bool StartRenderDIBSource(); - bool StartLoadDIBSource(); - bool DrawMaskedImage(); - bool DrawPatternImage(const CFX_Matrix* pObj2Device); - - CPDF_RenderStatus* m_pRenderStatus; - CPDF_ImageObject* m_pImageObject; - int m_Status; - const CFX_Matrix* m_pObj2Device; - CFX_Matrix m_ImageMatrix; - CPDF_ImageLoader m_Loader; - const CFX_DIBSource* m_pDIBSource; - std::unique_ptr m_pClone; - int m_BitmapAlpha; - bool m_bPatternColor; - CPDF_Pattern* m_pPattern; - FX_ARGB m_FillArgb; - uint32_t m_Flags; - std::unique_ptr m_pTransformer; - void* m_DeviceHandle; - bool m_bStdCS; - int m_BlendType; -}; - class CPDF_ScaledRenderBuffer { public: CPDF_ScaledRenderBuffer(); -- cgit v1.2.3