7#include "core/fpdfapi/render/cpdf_renderstatus.h"
18#include "build/build_config.h"
19#include "constants/transparency.h"
20#include "core/fpdfapi/font/cpdf_font.h"
21#include "core/fpdfapi/font/cpdf_type3char.h"
22#include "core/fpdfapi/font/cpdf_type3font.h"
23#include "core/fpdfapi/page/cpdf_docpagedata.h"
24#include "core/fpdfapi/page/cpdf_form.h"
25#include "core/fpdfapi/page/cpdf_formobject.h"
26#include "core/fpdfapi/page/cpdf_function.h"
27#include "core/fpdfapi/page/cpdf_graphicstates.h"
28#include "core/fpdfapi/page/cpdf_image.h"
29#include "core/fpdfapi/page/cpdf_imageobject.h"
30#include "core/fpdfapi/page/cpdf_occontext.h"
31#include "core/fpdfapi/page/cpdf_page.h"
32#include "core/fpdfapi/page/cpdf_pageimagecache.h"
33#include "core/fpdfapi/page/cpdf_pageobject.h"
34#include "core/fpdfapi/page/cpdf_pathobject.h"
35#include "core/fpdfapi/page/cpdf_shadingobject.h"
36#include "core/fpdfapi/page/cpdf_shadingpattern.h"
37#include "core/fpdfapi/page/cpdf_textobject.h"
38#include "core/fpdfapi/page/cpdf_tilingpattern.h"
39#include "core/fpdfapi/page/cpdf_transferfunc.h"
40#include "core/fpdfapi/parser/cpdf_array.h"
41#include "core/fpdfapi/parser/cpdf_document.h"
42#include "core/fpdfapi/parser/cpdf_stream.h"
43#include "core/fpdfapi/parser/fpdf_parser_utility.h"
44#include "core/fpdfapi/render/charposlist.h"
45#include "core/fpdfapi/render/cpdf_docrenderdata.h"
46#include "core/fpdfapi/render/cpdf_imagerenderer.h"
47#include "core/fpdfapi/render/cpdf_rendercontext.h"
48#include "core/fpdfapi/render/cpdf_renderoptions.h"
49#include "core/fpdfapi/render/cpdf_rendershading.h"
50#include "core/fpdfapi/render/cpdf_rendertiling.h"
51#include "core/fpdfapi/render/cpdf_scaledrenderbuffer.h"
52#include "core/fpdfapi/render/cpdf_textrenderer.h"
53#include "core/fpdfapi/render/cpdf_type3cache.h"
54#include "core/fxcrt/autorestorer.h"
55#include "core/fxcrt/data_vector.h"
56#include "core/fxcrt/fx_2d_size.h"
57#include "core/fxcrt/fx_safe_types.h"
58#include "core/fxcrt/fx_system.h"
59#include "core/fxcrt/span_util.h"
60#include "core/fxcrt/unowned_ptr.h"
61#include "core/fxge/cfx_defaultrenderdevice.h"
62#include "core/fxge/cfx_fillrenderoptions.h"
63#include "core/fxge/cfx_glyphbitmap.h"
64#include "core/fxge/cfx_path.h"
65#include "core/fxge/dib/cfx_dibitmap.h"
66#include "core/fxge/fx_font.h"
67#include "core/fxge/renderdevicedriver_iface.h"
68#include "core/fxge/text_char_pos.h"
69#include "core/fxge/text_glyph_pos.h"
70#include "third_party/base/check.h"
71#include "third_party/base/containers/contains.h"
72#include "third_party/base/containers/span.h"
73#include "third_party/base/notreached.h"
77constexpr int kRenderMaxRecursionDepth = 64;
78int g_CurrentRecursionDepth = 0;
82 const CPDF_PathObject* path_obj,
109 const CPDF_TextObject* text_obj,
113 if (is_stroke && is_fill) {
127FXDIB_Format GetFormatForLuminosity(
bool is_luminosity) {
130#if BUILDFLAG(IS_APPLE)
131 return FXDIB_Format::kRgb32;
140bool IsAvailableMatrix(
const CFX_Matrix& matrix) {
141 if (matrix
.a == 0 || matrix
.d == 0)
142 return matrix
.b != 0 && matrix
.c != 0;
144 if (matrix
.b == 0 || matrix
.c == 0)
145 return matrix
.a != 0 && matrix
.d != 0;
160 return pChar && (!pChar
->colored() || MissingFillColor(pColorState));
165 return pChar && (!pChar
->colored() || MissingStrokeColor(pColorState));
178 m_bPrint = m_pDevice->GetDeviceType() != DeviceType::kDisplay;
179 m_pPageResource.Reset(m_pContext->GetPageResources());
180 if (pInitialStates && !m_pType3Char) {
181 m_InitialStates = *pInitialStates;
183 if (!m_InitialStates.color_state().HasFillColor()) {
184 m_InitialStates.mutable_color_state().SetFillColorRef(
185 pParentStatus->m_InitialStates.color_state().GetFillColorRef());
186 *m_InitialStates.mutable_color_state().GetMutableFillColor() =
187 *pParentStatus->m_InitialStates.color_state().GetFillColor();
189 if (!m_InitialStates.color_state().HasStrokeColor()) {
190 m_InitialStates.mutable_color_state().SetStrokeColorRef(
191 pParentStatus->m_InitialStates.color_state().GetFillColorRef());
192 *m_InitialStates.mutable_color_state().GetMutableStrokeColor() =
193 *pParentStatus->m_InitialStates.color_state().GetStrokeColor();
197 m_InitialStates.SetDefaultStates();
204 CFX_FloatRect clip_rect = mtObj2Device.GetInverse().TransformRect(
205 CFX_FloatRect(m_pDevice->GetClipBox()));
206 for (
const auto& pCurObj : *pObjectHolder) {
207 if (pCurObj.get() == m_pStopObj) {
214 if (pCurObj->GetRect().left > clip_rect.right ||
215 pCurObj->GetRect().right < clip_rect.left ||
216 pCurObj->GetRect().bottom > clip_rect.top ||
217 pCurObj->GetRect().top < clip_rect.bottom) {
220 RenderSingleObject(pCurObj.get(), mtObj2Device);
229 if (++g_CurrentRecursionDepth > kRenderMaxRecursionDepth) {
233 if (!m_Options.CheckPageObjectVisible(pObj)) {
237 if (ProcessTransparency(pObj, mtObj2Device)) {
240 ProcessObjectNoClip(pObj, mtObj2Device);
246 if (m_pImageRenderer) {
247 if (m_pImageRenderer->Continue(pPause))
250 if (!m_pImageRenderer->GetResult())
251 DrawObjWithBackground(pObj, mtObj2Device);
252 m_pImageRenderer.reset();
257 if (!m_Options.CheckPageObjectVisible(pObj))
261 if (ProcessTransparency(pObj, mtObj2Device))
265 ProcessObjectNoClip(pObj, mtObj2Device);
269 m_pImageRenderer = std::make_unique<CPDF_ImageRenderer>(
this);
270 if (!m_pImageRenderer->Start(pObj->AsImage(), mtObj2Device,
false,
271 BlendMode::kNormal)) {
272 if (!m_pImageRenderer->GetResult())
273 DrawObjWithBackground(pObj, mtObj2Device);
274 m_pImageRenderer.reset();
284 rect.Intersect(m_pDevice->GetClipBox());
293 bRet = ProcessText(pObj
->AsText(), mtObj2Device,
nullptr);
296 bRet = ProcessPath(pObj
->AsPath(), mtObj2Device);
299 bRet = ProcessImage(pObj
->AsImage(), mtObj2Device);
305 bRet = ProcessForm(pObj
->AsForm(), mtObj2Device);
309 DrawObjWithBackground(pObj, mtObj2Device);
316 return ProcessPath(pObj
->AsPath(), mtObj2Device);
318 return ProcessImage(pObj
->AsImage(), mtObj2Device);
320 return ProcessForm(pObj
->AsForm(), mtObj2Device);
328 FX_RECT rect = GetObjectClippedRect(pObj, mtObj2Device);
334 if (!buffer.Initialize(m_pContext, m_pDevice, rect, pObj, &m_Options, res)) {
337 RetainPtr<
const CPDF_Dictionary> pFormResource;
339 const CPDF_FormObject* pFormObj = pObj
->AsForm();
341 pFormResource = pFormObj
->form()->GetDict()->GetDictFor(
"Resources");
343 status.SetOptions(m_Options);
356 pFormObj->form()->GetDict()->GetDictFor(
"OC");
357 if (pOC && !m_Options.CheckOCGDictVisible(pOC.Get()))
361 RetainPtr<
const CPDF_Dictionary> pResources =
362 pFormObj->form()->GetDict()->GetDictFor(
"Resources");
364 status.SetOptions(m_Options);
365 status.SetStopObject(m_pStopObj);
370 status.m_curBlend = m_curBlend;
374 m_bStopped = status.m_bStopped;
383 ProcessPathPattern(path_obj, mtObj2Device, &fill_type, &stroke);
390 if (m_Options.ColorModeIs(CPDF_RenderOptions::Type::kForcedColor) &&
391 options.bConvertFillToStroke &&
392 fill_type != CFX_FillRenderOptions::FillType::kNoFill) {
400 uint32_t stroke_argb = stroke ? GetStrokeArgb(path_obj) : 0;
402 if (!IsAvailableMatrix(path_matrix))
405 return m_pDevice->DrawPathWithBlend(
406 *path_obj->path().GetObject(), &path_matrix,
407 path_obj->graph_state().GetObject(), fill_argb, stroke_argb,
408 GetFillOptionsForDrawPathWithBlend(options, path_obj, fill_type, stroke,
416 auto* pDocCache = CPDF_DocRenderData::FromDocument(m_pContext->GetDocument());
417 return pDocCache ? pDocCache->GetTransferFunc(
std::move(pObj)) :
nullptr;
421 if (Type3CharMissingFillColor(m_pType3Char, &pObj->color_state())) {
422 return m_T3FillColor;
430 if (MissingFillColor(pColorState))
431 pColorState = &m_InitialStates.color_state();
434 if (colorref == 0xFFFFFFFF)
442 pObj->mutable_general_state().SetTransferFunc(
443 GetTransferFunc(std::move(pTR)));
447 pObj->general_state().GetTransferFunc()->TranslateColor(colorref);
450 return m_Options.TranslateObjectFillColor(
451 AlphaAndColorRefToArgb(alpha, colorref), pObj->GetType());
456 if (Type3CharMissingStrokeColor(m_pType3Char, pColorState))
457 return m_T3FillColor;
459 if (MissingStrokeColor(pColorState))
460 pColorState = &m_InitialStates.color_state();
463 if (colorref == 0xFFFFFFFF)
471 pObj->mutable_general_state().SetTransferFunc(
472 GetTransferFunc(std::move(pTR)));
476 pObj->general_state().GetTransferFunc()->TranslateColor(colorref);
479 return m_Options.TranslateObjectStrokeColor(
480 AlphaAndColorRefToArgb(alpha, colorref), pObj->GetType());
486 if (m_LastClipPath.HasRef()) {
487 m_pDevice->RestoreState(
true);
488 m_LastClipPath.SetNull();
492 if (m_LastClipPath == ClipPath)
495 m_LastClipPath = ClipPath;
496 m_pDevice->RestoreState(
true);
497 for (size_t i = 0; i < ClipPath.GetPathCount(); ++i) {
498 const CFX_Path* pPath = ClipPath.GetPath(i).GetObject();
502 if (pPath->GetPoints().empty()) {
505 m_pDevice->SetClip_PathFill(empty_path,
nullptr,
506 CFX_FillRenderOptions::WindingOptions());
508 m_pDevice->SetClip_PathFill(
509 *pPath, &mtObj2Device,
510 CFX_FillRenderOptions{ClipPath.GetClipType(i)});
514 if (ClipPath.GetTextCount() == 0)
522 std::unique_ptr<CFX_Path> pTextClippingPath;
523 for (size_t i = 0; i < ClipPath.GetTextCount(); ++i) {
524 CPDF_TextObject* pText = ClipPath.GetText(i);
526 if (!pTextClippingPath)
528 ProcessText(pText, mtObj2Device, pTextClippingPath.get());
532 if (!pTextClippingPath)
536 if (m_Options.GetOptions().bNoTextSmooth) {
539 m_pDevice->SetClip_PathFill(*pTextClippingPath,
nullptr, fill_options);
540 pTextClippingPath.reset();
548 return SelectClipPath(page_obj
->AsPath(), mtObj2Device, stroke);
550 m_pDevice->SetClip_Rect(page_obj->GetTransformedBBox(mtObj2Device));
561 return m_pDevice->SetClip_PathStroke(*path_obj->path().GetObject(),
563 path_obj->graph_state().GetObject());
566 if (m_Options.GetOptions().bNoPathSmooth) {
569 return m_pDevice->SetClip_PathFill(*path_obj->path().GetObject(),
570 &path_matrix, fill_options);
577 pPageObj->mutable_general_state().GetMutableSoftMask();
579 if (pPageObj->IsImage() &&
580 pPageObj->AsImage()->GetImage()->GetDict()->KeyExist(
"SMask")) {
581 pSMaskDict =
nullptr;
584 RetainPtr<
const CPDF_Dictionary> pFormResource;
585 float group_alpha = 1.0f;
587 bool bGroupTransparent =
false;
588 const CPDF_FormObject* pFormObj = pPageObj
->AsForm();
593 pFormResource = pFormObj
->form()->GetDict()->GetDictFor(
"Resources");
596 (pPageObj->clip_path().HasRef() &&
597 pPageObj->clip_path().GetTextCount() > 0 && !m_bPrint &&
600 !bTextClip && !bGroupTransparent) {
605 int rendCaps = m_pDevice->GetRenderCaps();
606 if (!(transparency
.IsIsolated() || pSMaskDict || bTextClip) &&
609 m_curBlend = blend_type;
610 bRet = DrawObjWithBlend(pPageObj, mtObj2Device);
611 m_curBlend = oldBlend;
614 DrawObjWithBackground(pPageObj, mtObj2Device);
619 rect.Intersect(m_pDevice->GetClipBox());
625 CFX_DefaultRenderDevice bitmap_device;
627 if (!transparency.IsIsolated() &&
629 backdrop = pdfium::MakeRetain<CFX_DIBitmap>();
630 if (!m_pDevice->CreateCompatibleBitmap(backdrop, width, height))
632 m_pDevice->GetDIBits(backdrop, rect.left, rect.top);
642 pTextMask = pdfium::MakeRetain<CFX_DIBitmap>();
646 CFX_DefaultRenderDevice text_device;
648 for (size_t i = 0; i < pPageObj
->clip_path().GetTextCount(); ++i) {
655 &text_device
, textobj->GetCharCodes()
, textobj->GetCharPositions()
,
663 bitmap_render.SetOptions(m_Options);
664 bitmap_render.SetStopObject(m_pStopObj);
669 bitmap_render.ProcessObjectNoClip(pPageObj, new_matrix);
670#if defined(PDF_USE_SKIA)
671 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
674 bitmap_device.GetBitmap()->ForcePreMultiply();
677 m_bStopped = bitmap_render.m_bStopped;
682 LoadSMask(pSMaskDict.Get(), &rect, smask_matrix);
693 transparency
= m_Transparency;
697#if defined(PDF_USE_SKIA)
698 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
699 bitmap_device.GetBitmap()->UnPreMultiply();
703 0
, 1.0f
, blend_type
, transparency
);
709 bbox.Intersect(m_pDevice->GetClipBox());
716 bool bBackAlphaRequired) {
719 auto pBackdrop = pdfium::MakeRetain<CFX_DIBitmap>();
720 if (bBackAlphaRequired && !m_bDropObjects) {
725 if (!m_pDevice->CreateCompatibleBitmap(pBackdrop, width, height)) {
730 const int cap_to_check =
732 if (m_pDevice->GetRenderCaps() & cap_to_check) {
733 m_pDevice->GetDIBits(pBackdrop, bbox.left, bbox.top);
738 if (!pBackdrop->IsAlphaFormat()) {
739 pBackdrop->Clear(0xffffffff);
742 CFX_DefaultRenderDevice device;
744 m_pContext->Render(&device, pObj, &m_Options, &FinalMatrix);
759 pStates->mutable_color_state().SetFillColorRef(
762 pStates->mutable_color_state().SetStrokeColorRef(
763 pStates->color_state().GetFillColorRef());
771 if (textobj->GetCharCodes().empty())
780 if (pFont->IsType3Font())
781 return ProcessType3Text(textobj, mtObj2Device);
783 bool is_fill =
false;
784 bool is_stroke =
false;
785 bool is_clip =
false;
789 switch (text_render_mode) {
796 if (pFont->HasFace())
804 if (pFont->HasFace())
810 NOTREACHED_NORETURN();
814 NOTREACHED_NORETURN();
817 FX_ARGB stroke_argb = 0;
818 FX_ARGB fill_argb = 0;
819 bool bPattern =
false;
824 stroke_argb = GetStrokeArgb(textobj);
835 if (!IsAvailableMatrix(text_matrix))
840 DrawTextPathWithPattern(textobj, mtObj2Device, pFont.Get(), font_size,
841 text_matrix, is_fill, is_stroke);
844 if (is_clip || is_stroke) {
845 const CFX_Matrix* pDeviceMatrix = &mtObj2Device;
848 pdfium::span<
const float> pCTM = textobj->text_state().GetCTM();
849 if (pCTM[0] != 1.0f || pCTM[3] != 1.0f) {
850 CFX_Matrix ctm(pCTM[0], pCTM[1], pCTM[2], pCTM[3], 0, 0);
852 device_matrix
= ctm
* mtObj2Device;
853 pDeviceMatrix = &device_matrix;
856 return CPDF_TextRenderer::DrawTextPath(
857 m_pDevice, textobj->GetCharCodes(), textobj->GetCharPositions(),
858 pFont.Get(), font_size, text_matrix, pDeviceMatrix,
859 textobj->graph_state().GetObject(), fill_argb, stroke_argb,
861 GetFillOptionsForDrawTextPath(m_Options.GetOptions(), textobj,
862 is_stroke, is_fill));
865 return CPDF_TextRenderer::DrawNormalText(
866 m_pDevice, textobj->GetCharCodes(), textobj->GetCharPositions(),
867 pFont.Get(), font_size, text_matrix, fill_argb, m_Options);
873 CPDF_Type3Font* pType3Font = textobj
->text_state().GetFont()->AsType3Font();
874 if (pdfium::Contains(m_Type3FontCache, pType3Font))
878 int fill_alpha =
FXARGB_A(fill_argb);
879 if (m_bPrint && fill_alpha < 255)
888 std::set<RetainPtr<CPDF_Type3Cache>> refTypeCache;
889 std::vector<TextGlyphPos> glyphs;
891 glyphs.resize(textobj->GetCharCodes().size());
893 for (size_t iChar = 0; iChar < textobj->GetCharCodes().size(); ++iChar) {
894 uint32_t charcode = textobj->GetCharCodes()[iChar];
895 if (charcode ==
static_cast<uint32_t>(-1))
903 matrix
.e += iChar > 0 ? textobj->GetCharPositions()[iChar - 1] : 0;
907 if (!glyphs.empty()) {
908 for (size_t i = 0; i < iChar; ++i) {
913 absl::optional<CFX_Point> point = glyph.GetOrigin({0, 0});
914 if (!point.has_value())
917 m_pDevice->SetBitMask(glyph.m_pGlyph->GetBitmap(), point->x, point->y,
923 std::unique_ptr<CPDF_GraphicStates> pStates =
924 CloneObjStates(&textobj->graphic_states(),
false);
929 const auto* pForm =
static_cast<
const CPDF_Form*>(pType3Char
->form());
930 RetainPtr<
const CPDF_Dictionary> pFormResource =
931 pForm->GetDict()->GetDictFor(
"Resources");
933 if (fill_alpha == 255) {
942 status.m_Type3FontCache = m_Type3FontCache;
943 status.m_Type3FontCache.emplace_back(pType3Font);
949 matrix.TransformRect(pForm->CalcBoundingBox()).GetOuterRect();
953 CFX_DefaultRenderDevice bitmap_device;
966 status.m_Type3FontCache = m_Type3FontCache;
967 status.m_Type3FontCache.emplace_back(pType3Font);
970 m_pDevice->SetDIBits(bitmap_device.GetBitmap(), rect.left, rect.top);
976 if (renderer.Start(pType3Char
->GetBitmap(), fill_argb, image_matrix,
985 CPDF_DocRenderData::FromDocument(pDoc)->GetCachedType3(pType3Font);
991 refTypeCache.insert(
std::move(pCache));
993 CFX_Point origin(FXSYS_roundf(matrix.e), FXSYS_roundf(matrix.f));
994 if (glyphs.empty()) {
995 FX_SAFE_INT32 left = origin.x;
1000 FX_SAFE_INT32 top = origin.y;
1005 m_pDevice->SetBitMask(pBitmap->GetBitmap(), left.ValueOrDie(),
1006 top.ValueOrDie(), fill_argb);
1008 glyphs[iChar].m_pGlyph = pBitmap;
1009 glyphs[iChar].m_Origin = origin;
1018 FX_RECT rect = GetGlyphsBBox(glyphs, 0);
1019 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1023 for (
const TextGlyphPos& glyph : glyphs) {
1024 if (!glyph.m_pGlyph || !glyph.m_pGlyph->GetBitmap()->IsMaskFormat())
1027 absl::optional<CFX_Point> point = glyph.GetOrigin({rect.left, rect.top});
1028 if (!point.has_value())
1031 pBitmap->CompositeMask(
1032 point->x, point->y, glyph.m_pGlyph->GetBitmap()->GetWidth(),
1033 glyph.m_pGlyph->GetBitmap()->GetHeight(), glyph.m_pGlyph->GetBitmap(),
1034 fill_argb, 0, 0, BlendMode::kNormal,
nullptr,
false);
1036 m_pDevice->SetBitMask(pBitmap, rect.left, rect.top, fill_argb);
1048 std::vector<std::unique_ptr<CPDF_TextObject>> pCopy;
1049 pCopy.push_back(textobj->Clone());
1051 CPDF_PathObject path;
1053 path.mutable_clip_path().CopyClipPath(m_LastClipPath);
1065 std::vector<TextCharPos> char_pos_list = GetCharPosList(
1066 textobj->GetCharCodes(), textobj->GetCharPositions(), pFont, font_size);
1067 for (
const TextCharPos& charpos : char_pos_list) {
1068 auto* font = charpos.m_FallbackFontPosition == -1
1070 : pFont->GetFontFallback(charpos.m_FallbackFontPosition);
1071 const CFX_Path* pPath =
1072 font->LoadGlyphPath(charpos.m_GlyphIndex, charpos.m_FontCharWidth);
1076 CPDF_PathObject path;
1077 path.mutable_graph_state() = textobj->graph_state();
1078 path.mutable_color_state() = textobj->color_state();
1080 CFX_Matrix matrix = charpos.GetEffectiveMatrix(CFX_Matrix(
1081 font_size, 0, 0, font_size, charpos.m_Origin.x, charpos.m_Origin.y));
1082 matrix.Concat(mtTextMatrix);
1083 path.set_stroke(stroke);
1084 path.set_filltype(fill ? CFX_FillRenderOptions::FillType::kWinding
1085 : CFX_FillRenderOptions::FillType::kNoFill);
1086 path.path().Append(*pPath, &matrix);
1087 path.SetPathMatrix(CFX_Matrix());
1088 ProcessPath(&path, mtObj2Device);
1100 if (!ClipPattern(pPageObj, mtObj2Device, stroke))
1103 FX_RECT rect = GetObjectClippedRect(pPageObj, mtObj2Device);
1111 CPDF_RenderShading::Draw(m_pDevice, m_pContext, m_pCurObj, pattern, matrix,
1112 rect, alpha, m_Options);
1117 FX_RECT rect = GetObjectClippedRect(pShadingObj, mtObj2Device);
1122 CPDF_RenderShading::Draw(
1123 m_pDevice, m_pContext, m_pCurObj, pShadingObj->pattern(), matrix, rect,
1124 FXSYS_roundf(255 * pShadingObj->general_state().GetFillAlpha()),
1132 const std::unique_ptr<CPDF_Form> pPatternForm = pattern->Load(pPageObj);
1137 if (!ClipPattern(pPageObj, mtObj2Device, stroke))
1140 FX_RECT clip_box = m_pDevice->GetClipBox();
1145 CPDF_RenderTiling::Draw(
this, pPageObj, pattern, pPatternForm.get(),
1146 mtObj2Device, clip_box, stroke);
1150 constexpr FX_ARGB kMask = 0;
1163 if (CPDF_TilingPattern* pTilingPattern = pattern->AsTilingPattern())
1165 else if (CPDF_ShadingPattern* pShadingPattern = pattern->AsShadingPattern())
1170 CPDF_PathObject* path_obj,
1180 DrawPathWithPattern(path_obj, mtObj2Device, &FillColor,
false);
1187 DrawPathWithPattern(path_obj, mtObj2Device, &StrokeColor,
true);
1196 if (render
.Start(pImageObj
, mtObj2Device
, m_bStdCS
, m_curBlend
))
1202 const RetainPtr<CFX_DIBitmap>& pDIBitmap,
1212 if (!pDIBitmap->IsMaskFormat()) {
1213 if (alpha != 1.0f) {
1215 std::unique_ptr<CFX_ImageRenderer> dummy;
1216 CFX_Matrix matrix = CFX_RenderDevice::GetFlipMatrix(
1217 pDIBitmap->GetWidth(), pDIBitmap->GetHeight(), left, top);
1218 m_pDevice->StartDIBits(std::move(pDIBitmap), alpha, 0,
1219 matrix, FXDIB_ResampleOptions(), &dummy);
1222 pDIBitmap->MultiplyAlpha(alpha);
1224 if (m_pDevice->SetDIBits(pDIBitmap, left, top)) {
1228 uint32_t fill_argb = m_Options.TranslateColor(mask_argb);
1229 if (alpha != 1.0f) {
1230 uint8_t* fill_argb8 =
reinterpret_cast<uint8_t*>(&fill_argb);
1233 if (m_pDevice->SetBitMask(pDIBitmap, left, top, fill_argb)) {
1239 bool bBackAlphaRequired =
1241 bool bGetBackGround =
1244 (m_pDevice->GetRenderCaps() &
FXRC_GET_BITS) && !bBackAlphaRequired);
1245 if (bGetBackGround) {
1247 if (!pDIBitmap->IsMaskFormat())
1248 m_pDevice->SetDIBitsWithBlend(pDIBitmap, left, top, blend_mode);
1252 FX_RECT rect(left, top, left + pDIBitmap->GetWidth(),
1253 top + pDIBitmap->GetHeight());
1254 rect.Intersect(m_pDevice->GetClipBox());
1256 if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) {
1257 pClone = m_pDevice->GetBackDrop()->ClipTo(rect);
1261 pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(),
1262 m_pDevice->GetBitmap(), rect.left, rect.top,
1263 BlendMode::kNormal,
nullptr,
false);
1264 left =
std::min(left, 0);
1265 top =
std::min(top, 0);
1266 if (pDIBitmap->IsMaskFormat()) {
1267 pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(),
1268 pDIBitmap, mask_argb, left, top, blend_mode,
1271 pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(),
1272 pDIBitmap, left, top, blend_mode,
nullptr,
1278 if (m_pDevice->GetBackDrop()) {
1279 m_pDevice->SetDIBits(pClone, rect.left, rect.top);
1281 if (!pDIBitmap->IsMaskFormat()) {
1282 m_pDevice->SetDIBitsWithBlend(pDIBitmap, rect.left, rect.top,
1288 FX_RECT bbox = GetClippedBBox(FX_RECT(left, top, left + pDIBitmap->GetWidth(),
1289 top + pDIBitmap->GetHeight()));
1290 RetainPtr<CFX_DIBitmap> pBackdrop = GetBackdrop(
1291 m_pCurObj, bbox, blend_mode != BlendMode::kNormal && bIsolated);
1295 if (pDIBitmap->IsMaskFormat()) {
1296 pBackdrop->CompositeMask(left - bbox.left, top - bbox.top,
1297 pDIBitmap->GetWidth(), pDIBitmap->GetHeight(),
1298 pDIBitmap, mask_argb, 0, 0, blend_mode,
nullptr,
1301 pBackdrop->CompositeBitmap(left - bbox.left, top - bbox.top,
1302 pDIBitmap->GetWidth(), pDIBitmap->GetHeight(),
1303 pDIBitmap, 0, 0, blend_mode,
nullptr,
false);
1306 auto pBackdrop1 = pdfium::MakeRetain<CFX_DIBitmap>();
1307 pBackdrop1->Create(pBackdrop->GetWidth(), pBackdrop->GetHeight(),
1309 pBackdrop1->Clear((uint32_t)-1);
1310 pBackdrop1->CompositeBitmap(0, 0, pBackdrop->GetWidth(),
1311 pBackdrop->GetHeight(), pBackdrop, 0, 0,
1313 pBackdrop =
std::move(pBackdrop1);
1314 m_pDevice->SetDIBits(pBackdrop, bbox.left, bbox.top);
1318 CPDF_Dictionary* pSMaskDict,
1325 pSMaskDict->GetMutableStreamFor(pdfium::transparency::kG);
1329 std::unique_ptr<CPDF_Function> pFunc;
1331 pSMaskDict->GetDirectObjectFor(pdfium::transparency::kTR);
1332 if (pFuncObj && (pFuncObj->IsDictionary() || pFuncObj->IsStream()))
1333 pFunc = CPDF_Function::Load(
std::move(pFuncObj));
1338 CPDF_Form form(m_pContext->GetDocument(),
1339 m_pContext->GetMutablePageResources(), pGroup);
1342 CFX_DefaultRenderDevice bitmap_device;
1348 FXDIB_Format format = GetFormatForLuminosity(bLuminosity);
1349 if (!bitmap_device
.Create(width, height, format,
nullptr))
1353 const FX_ARGB background_color =
1355 ? GetBackgroundColor(pSMaskDict, pGroup->GetDict().Get(), &nCSFamily)
1357 bitmap_device
.Clear(background_color
);
1359 RetainPtr<
const CPDF_Dictionary> pFormResource =
1360 form.GetDict()->GetDictFor(
"Resources");
1374 auto pMask = pdfium::MakeRetain<CFX_DIBitmap>();
1378 pdfium::span<uint8_t> dest_buf = pMask->GetWritableBuffer();
1379 RetainPtr<
const CFX_DIBitmap> bitmap = bitmap_device.GetBitmap();
1380 pdfium::span<
const uint8_t> src_buf = bitmap->GetBuffer();
1381 int dest_pitch = pMask->GetPitch();
1382 int src_pitch = bitmap->GetPitch();
1383 DataVector<uint8_t> transfers(256);
1385 std::vector<
float> results(pFunc->CountOutputs());
1386 for (size_t i = 0; i < transfers.size(); ++i) {
1387 float input = i / 255.0f;
1388 pFunc->Call(pdfium::span_from_ref(input), results);
1389 transfers[i] = FXSYS_roundf(results[0] * 255);
1393 std::iota(transfers.begin(), transfers.end(), 0);
1396 const int Bpp = bitmap->GetBPP() / 8;
1397 for (
int row = 0; row < height; row++) {
1398 const size_t dest_offset = Fx2DSizeOrDie(row, dest_pitch);
1399 const size_t src_offset = Fx2DSizeOrDie(row, src_pitch);
1400 uint8_t* dest_pos = dest_buf.subspan(dest_offset).data();
1401 const uint8_t* src_pos = src_buf.subspan(src_offset).data();
1402 for (
int col = 0; col < width; col++) {
1403 *dest_pos++ = transfers[
FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos)];
1408 int size = dest_pitch * height;
1409 for (
int i = 0; i < size; i++) {
1410 dest_buf[i] = transfers[src_buf[i]];
1413 fxcrt::spancpy(dest_buf, src_buf.first(dest_pitch * height));
1419 const CPDF_Dictionary* pSMaskDict,
1420 const CPDF_Dictionary* pGroupDict,
1424 pSMaskDict->GetArrayFor(pdfium::transparency::kBC);
1426 return kDefaultColor;
1429 RetainPtr<
const CPDF_Dictionary> pGroup =
1430 pGroupDict ? pGroupDict->GetDictFor(
"Group") :
nullptr;
1434 CPDF_DocPageData::FromDocument(m_pContext->GetDocument())
1435 ->GetColorSpace(pCSObj.Get(),
nullptr);
1437 return kDefaultColor;
1442 return kDefaultColor;
1446 *pCSFamily = family;
1448 uint32_t comps =
std::max(8u, pCS->CountComponents());
1449 size_t count = std::min<size_t>(8, pBC->size());
1450 std::vector<
float> floats = ReadArrayElementsToVector(pBC.Get(), count);
1451 floats.resize(comps);
1456 pCS->GetRGB(floats, &R, &G, &B);
1457 return ArgbEncode(255
, static_cast<
int>(R * 255)
, static_cast<
int>(G * 255)
,
1458 static_cast<
int>(B * 255)
);
static bool UseSkiaRenderer()
bool Create(int width, int height, FXDIB_Format format, RetainPtr< CFX_DIBitmap > pBackdropBitmap)
bool Attach(RetainPtr< CFX_DIBitmap > pBitmap)
void Clear(uint32_t color)
CFX_Matrix & operator=(const CFX_Matrix &other)=default
CFX_Matrix & operator*=(const CFX_Matrix &other)
CFX_Matrix operator*(const CFX_Matrix &right) const
void Translate(int32_t x, int32_t y)
CFX_Matrix GetInverse() const
void Scale(float sx, float sy)
void Concat(const CFX_Matrix &right)
void AppendRect(float left, float bottom, float right, float top)
bool MultiplyAlpha(float alpha)
bool MultiplyAlphaMask(const RetainPtr< const CFX_DIBBase > &mask)
FX_COLORREF GetStrokeColorRef() const
FX_COLORREF GetFillColorRef() const
const CPDF_Color * GetStrokeColor() const
const CPDF_Color * GetFillColor() const
ByteString GetByteStringFor(const ByteString &key) const
CPDF_Document * GetDocument() const
float GetStrokeAlpha() const
float GetFillAlpha() const
RetainPtr< CPDF_TransferFunc > GetTransferFunc() const
BlendMode GetBlendType() const
const CFX_Matrix * GetSMaskMatrix() const
const CPDF_ColorState & color_state() const
CPDF_ImageRenderer(CPDF_RenderStatus *pStatus)
bool Continue(PauseIndicatorIface *pPause)
bool Start(CPDF_ImageObject *pImageObject, const CFX_Matrix &mtObj2Device, bool bStdCS, BlendMode blendType)
const CPDF_Transparency & GetTransparency() const
const CPDF_GraphicStates & graphic_states() const
virtual const CPDF_PathObject * AsPath() const
void SetRect(const CFX_FloatRect &rect)
const CPDF_ColorState & color_state() const
const CPDF_GeneralState & general_state() const
virtual bool IsImage() const
const CPDF_ClipPath & clip_path() const
virtual Type GetType() const =0
CPDF_GeneralState & mutable_general_state()
FX_RECT GetTransformedBBox(const CFX_Matrix &matrix) const
virtual CPDF_ShadingObject * AsShading()
const CFX_FloatRect & GetRect() const
virtual CPDF_ImageObject * AsImage()
virtual CPDF_FormObject * AsForm()
virtual CPDF_TextObject * AsText()
const CPDF_TextState & text_state() const
virtual CPDF_PathObject * AsPath()
const CFX_GraphState & graph_state() const
virtual bool IsForm() const
CPDF_ClipPath & mutable_clip_path()
virtual bool IsPath() const
CPDF_ColorState & mutable_color_state()
void set_filltype(CFX_FillRenderOptions::FillType fill_type)
const CFX_Matrix & matrix() const
CFX_FillRenderOptions::FillType filltype() const
void AppendFloatRect(const CFX_FloatRect &rect)
const CFX_Matrix & pattern_to_form() const
void SetColorMode(Type mode)
void SetDropObjects(bool bDropObjects)
void SetType3Char(CPDF_Type3Char *pType3Char)
RetainPtr< CPDF_TransferFunc > GetTransferFunc(RetainPtr< const CPDF_Object > pObject) const
void SetDeviceMatrix(const CFX_Matrix &matrix)
CPDF_RenderStatus(CPDF_RenderContext *pContext, CFX_RenderDevice *pDevice)
void SetFillColor(FX_ARGB color)
void SetOptions(const CPDF_RenderOptions &options)
void RenderSingleObject(CPDF_PageObject *pObj, const CFX_Matrix &mtObj2Device)
bool ContinueSingleObject(CPDF_PageObject *pObj, const CFX_Matrix &mtObj2Device, PauseIndicatorIface *pPause)
void SetTransparency(const CPDF_Transparency &transparency)
void RenderObjectList(const CPDF_PageObjectHolder *pObjectHolder, const CFX_Matrix &mtObj2Device)
void SetStdCS(bool bStdCS)
FX_ARGB GetFillArgbForType3(CPDF_PageObject *pObj) const
void SetGroupFamily(CPDF_ColorSpace::Family family)
void DrawShadingPattern(CPDF_ShadingPattern *pattern, const CPDF_PageObject *pPageObj, const CFX_Matrix &mtObj2Device, bool stroke)
void Initialize(const CPDF_RenderStatus *pParentStatus, const CPDF_GraphicStates *pInitialStates)
void CompositeDIBitmap(const RetainPtr< CFX_DIBitmap > &pDIBitmap, int left, int top, FX_ARGB mask_argb, float alpha, BlendMode blend_mode, const CPDF_Transparency &transparency)
void DrawTilingPattern(CPDF_TilingPattern *pattern, CPDF_PageObject *pPageObj, const CFX_Matrix &mtObj2Device, bool stroke)
void SetFormResource(RetainPtr< const CPDF_Dictionary > pRes)
FX_ARGB GetFillArgb(CPDF_PageObject *pObj) const
void SetLoadMask(bool bLoadMask)
void ProcessClipPath(const CPDF_ClipPath &ClipPath, const CFX_Matrix &mtObj2Device)
const CFX_Matrix & GetMatrix() const
const CFX_Matrix & matrix() const
CFX_Matrix GetTextMatrix() const
static bool DrawTextPath(CFX_RenderDevice *pDevice, pdfium::span< const uint32_t > char_codes, pdfium::span< const float > char_pos, CPDF_Font *pFont, float font_size, const CFX_Matrix &mtText2User, const CFX_Matrix *pUser2Device, const CFX_GraphStateData *pGraphState, FX_ARGB fill_argb, FX_ARGB stroke_argb, CFX_Path *pClippingPath, const CFX_FillRenderOptions &fill_options)
CPDF_Transparency & operator=(const CPDF_Transparency &other)
const CFX_Matrix & matrix() const
RetainPtr< CFX_DIBitmap > GetBitmap()
const CPDF_Font::FormIface * form() const
bool LoadBitmapFromSoleImageOfForm()
CPDF_Type3Char * LoadChar(uint32_t charcode)
CFX_Matrix & GetFontMatrix()
bool operator!=(const char *ptr) const
#define FXRGB2GRAY(r, g, b)
constexpr FX_ARGB ArgbEncode(uint32_t a, uint32_t r, uint32_t g, uint32_t b)
int FXSYS_roundf(float f)
const char kSoftMaskSubType[]
#define FXRC_ALPHA_OUTPUT
constexpr CFX_FillRenderOptions()
constexpr CFX_FillRenderOptions(FillType fill_type)
static constexpr CFX_FillRenderOptions WindingOptions()