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_textrenderer.h"
52#include "core/fpdfapi/render/cpdf_type3cache.h"
53#include "core/fxcrt/autorestorer.h"
54#include "core/fxcrt/check.h"
55#include "core/fxcrt/compiler_specific.h"
56#include "core/fxcrt/containers/contains.h"
57#include "core/fxcrt/data_vector.h"
58#include "core/fxcrt/fx_2d_size.h"
59#include "core/fxcrt/fx_safe_types.h"
60#include "core/fxcrt/fx_system.h"
61#include "core/fxcrt/notreached.h"
62#include "core/fxcrt/span.h"
63#include "core/fxcrt/stl_util.h"
64#include "core/fxcrt/unowned_ptr.h"
65#include "core/fxge/agg/cfx_agg_imagerenderer.h"
66#include "core/fxge/cfx_defaultrenderdevice.h"
67#include "core/fxge/cfx_fillrenderoptions.h"
68#include "core/fxge/cfx_glyphbitmap.h"
69#include "core/fxge/cfx_path.h"
70#include "core/fxge/dib/cfx_dibitmap.h"
71#include "core/fxge/fx_font.h"
72#include "core/fxge/renderdevicedriver_iface.h"
73#include "core/fxge/text_char_pos.h"
74#include "core/fxge/text_glyph_pos.h"
77#include "core/fpdfapi/render/cpdf_scaledrenderbuffer.h"
82constexpr int kRenderMaxRecursionDepth = 64;
83int g_CurrentRecursionDepth = 0;
87 const CPDF_PathObject* path_obj,
114 const CPDF_TextObject* text_obj,
118 if (is_stroke && is_fill) {
132FXDIB_Format GetFormatForLuminosity(
bool is_luminosity) {
135#if BUILDFLAG(IS_APPLE)
136 return FXDIB_Format::kBgrx;
145bool IsAvailableMatrix(
const CFX_Matrix& matrix) {
146 if (matrix
.a == 0 || matrix
.d == 0)
147 return matrix
.b != 0 && matrix
.c != 0;
149 if (matrix
.b == 0 || matrix
.c == 0)
150 return matrix
.a != 0 && matrix
.d != 0;
165 return pChar && (!pChar
->colored() || MissingFillColor(pColorState));
170 return pChar && (!pChar
->colored() || MissingStrokeColor(pColorState));
184 m_bPrint = m_pDevice->GetDeviceType() == DeviceType::kPrinter;
186 m_pPageResource.Reset(m_pContext->GetPageResources());
187 if (pInitialStates && !m_pType3Char) {
188 m_InitialStates = *pInitialStates;
190 if (!m_InitialStates.color_state().HasFillColor()) {
191 m_InitialStates.mutable_color_state().SetFillColorRef(
192 pParentStatus->m_InitialStates.color_state().GetFillColorRef());
193 *m_InitialStates.mutable_color_state().GetMutableFillColor() =
194 *pParentStatus->m_InitialStates.color_state().GetFillColor();
196 if (!m_InitialStates.color_state().HasStrokeColor()) {
197 m_InitialStates.mutable_color_state().SetStrokeColorRef(
198 pParentStatus->m_InitialStates.color_state().GetFillColorRef());
199 *m_InitialStates.mutable_color_state().GetMutableStrokeColor() =
200 *pParentStatus->m_InitialStates.color_state().GetStrokeColor();
204 m_InitialStates.SetDefaultStates();
211 CFX_FloatRect clip_rect = mtObj2Device.GetInverse().TransformRect(
212 CFX_FloatRect(m_pDevice->GetClipBox()));
213 for (
const auto& pCurObj : *pObjectHolder) {
214 if (pCurObj.get() == m_pStopObj) {
221 if (pCurObj->GetRect().left > clip_rect.right ||
222 pCurObj->GetRect().right < clip_rect.left ||
223 pCurObj->GetRect().bottom > clip_rect.top ||
224 pCurObj->GetRect().top < clip_rect.bottom) {
227 RenderSingleObject(pCurObj.get(), mtObj2Device);
236 if (++g_CurrentRecursionDepth > kRenderMaxRecursionDepth) {
240 if (!m_Options.CheckPageObjectVisible(pObj)) {
244 if (ProcessTransparency(pObj, mtObj2Device)) {
247 ProcessObjectNoClip(pObj, mtObj2Device);
253 if (m_pImageRenderer) {
254 if (m_pImageRenderer->Continue(pPause))
257 if (!m_pImageRenderer->GetResult())
258 DrawObjWithBackground(pObj, mtObj2Device);
259 m_pImageRenderer.reset();
264 if (!m_Options.CheckPageObjectVisible(pObj))
268 if (ProcessTransparency(pObj, mtObj2Device))
272 ProcessObjectNoClip(pObj, mtObj2Device);
276 m_pImageRenderer = std::make_unique<CPDF_ImageRenderer>(
this);
277 if (!m_pImageRenderer->Start(pObj->AsImage(), mtObj2Device,
279 if (!m_pImageRenderer->GetResult())
280 DrawObjWithBackground(pObj, mtObj2Device);
281 m_pImageRenderer.reset();
291 rect.Intersect(m_pDevice->GetClipBox());
300 bRet = ProcessText(pObj
->AsText(), mtObj2Device,
nullptr);
303 bRet = ProcessPath(pObj
->AsPath(), mtObj2Device);
306 bRet = ProcessImage(pObj
->AsImage(), mtObj2Device);
312 bRet = ProcessForm(pObj
->AsForm(), mtObj2Device);
316 DrawObjWithBackground(pObj, mtObj2Device);
323 return ProcessPath(pObj
->AsPath(), mtObj2Device);
325 return ProcessImage(pObj
->AsImage(), mtObj2Device);
327 return ProcessForm(pObj
->AsForm(), mtObj2Device);
336 FX_RECT rect = GetObjectClippedRect(pObj, mtObj2Device);
340 const bool needs_buffer =
343 DrawObjWithBackgroundToDevice(pObj, mtObj2Device, m_pDevice, CFX_Matrix());
348 CPDF_ScaledRenderBuffer buffer(m_pDevice, rect);
349 int res = (pObj->IsImage() && IsPrint()) ? 0 : 300;
350 if (!buffer.Initialize(m_pContext, pObj, m_Options, res)) {
354 DrawObjWithBackgroundToDevice(pObj, mtObj2Device, buffer.GetDevice(),
356 buffer.OutputToDevice();
368 const CPDF_FormObject* pFormObj = obj
->AsForm();
370 pFormResource = pFormObj
->form()->GetDict()->GetDictFor(
"Resources");
374 status.SetOptions(m_Options);
387 pFormObj->form()->GetDict()->GetDictFor(
"OC");
388 if (pOC && !m_Options.CheckOCGDictVisible(pOC.Get()))
393 pFormObj->form()->GetDict()->GetDictFor(
"Resources");
395 status.SetOptions(m_Options);
396 status.SetStopObject(m_pStopObj);
405 m_bStopped = status.m_bStopped;
414 ProcessPathPattern(path_obj, mtObj2Device, &fill_type, &stroke);
421 if (m_Options.ColorModeIs(CPDF_RenderOptions::Type::kForcedColor) &&
422 options.bConvertFillToStroke &&
423 fill_type != CFX_FillRenderOptions::FillType::kNoFill) {
431 uint32_t stroke_argb = stroke ? GetStrokeArgb(path_obj) : 0;
433 if (!IsAvailableMatrix(path_matrix)) {
437 return m_pDevice->DrawPath(
438 *path_obj->path().GetObject(), &path_matrix,
439 path_obj->graph_state().GetObject(), fill_argb, stroke_argb,
440 GetFillOptionsForDrawPathWithBlend(options, path_obj, fill_type, stroke,
447 auto* pDocCache = CPDF_DocRenderData::FromDocument(m_pContext->GetDocument());
448 return pDocCache ? pDocCache->GetTransferFunc(
std::move(pObj)) :
nullptr;
452 if (Type3CharMissingFillColor(m_pType3Char, &pObj->color_state())) {
453 return m_T3FillColor;
461 if (MissingFillColor(pColorState))
462 pColorState = &m_InitialStates.color_state();
465 if (colorref == 0xFFFFFFFF)
473 pObj->mutable_general_state().SetTransferFunc(
474 GetTransferFunc(std::move(pTR)));
478 pObj->general_state().GetTransferFunc()->TranslateColor(colorref);
481 return m_Options.TranslateObjectFillColor(
482 AlphaAndColorRefToArgb(alpha, colorref), pObj->GetType());
487 if (Type3CharMissingStrokeColor(m_pType3Char, pColorState))
488 return m_T3FillColor;
490 if (MissingStrokeColor(pColorState))
491 pColorState = &m_InitialStates.color_state();
494 if (colorref == 0xFFFFFFFF)
502 pObj->mutable_general_state().SetTransferFunc(
503 GetTransferFunc(std::move(pTR)));
507 pObj->general_state().GetTransferFunc()->TranslateColor(colorref);
510 return m_Options.TranslateObjectStrokeColor(
511 AlphaAndColorRefToArgb(alpha, colorref), pObj->GetType());
517 if (m_LastClipPath.HasRef()) {
518 m_pDevice->RestoreState(
true);
519 m_LastClipPath.SetNull();
523 if (m_LastClipPath == ClipPath)
526 m_LastClipPath = ClipPath;
527 m_pDevice->RestoreState(
true);
528 for (size_t i = 0; i < ClipPath.GetPathCount(); ++i) {
529 const CFX_Path* pPath = ClipPath.GetPath(i).GetObject();
533 if (pPath->GetPoints().empty()) {
536 m_pDevice->SetClip_PathFill(empty_path,
nullptr,
537 CFX_FillRenderOptions::WindingOptions());
539 m_pDevice->SetClip_PathFill(
540 *pPath, &mtObj2Device,
541 CFX_FillRenderOptions{ClipPath.GetClipType(i)});
545 if (ClipPath.GetTextCount() == 0)
553 std::unique_ptr<CFX_Path> pTextClippingPath;
554 for (size_t i = 0; i < ClipPath.GetTextCount(); ++i) {
555 CPDF_TextObject* pText = ClipPath.GetText(i);
557 if (!pTextClippingPath)
559 ProcessText(pText, mtObj2Device, pTextClippingPath.get());
563 if (!pTextClippingPath)
567 if (m_Options.GetOptions().bNoTextSmooth) {
570 m_pDevice->SetClip_PathFill(*pTextClippingPath,
nullptr, fill_options);
571 pTextClippingPath.reset();
579 return SelectClipPath(page_obj
->AsPath(), mtObj2Device, stroke);
581 m_pDevice->SetClip_Rect(page_obj->GetTransformedBBox(mtObj2Device));
592 return m_pDevice->SetClip_PathStroke(*path_obj->path().GetObject(),
594 path_obj->graph_state().GetObject());
597 if (m_Options.GetOptions().bNoPathSmooth) {
600 return m_pDevice->SetClip_PathFill(*path_obj->path().GetObject(),
601 &path_matrix, fill_options);
608 pPageObj->mutable_general_state().GetMutableSoftMask();
610 if (pPageObj->IsImage() &&
611 pPageObj->AsImage()->GetImage()->GetDict()->KeyExist(
"SMask")) {
612 pSMaskDict =
nullptr;
616 float group_alpha = 1.0f;
617 float initial_alpha = 1.0f;
619 bool bGroupTransparent =
false;
620 const CPDF_FormObject* pFormObj = pPageObj
->AsForm();
625 pFormResource = pFormObj
->form()->GetDict()->GetDictFor(
"Resources");
626 initial_alpha = m_InitialStates.general_state().GetFillAlpha();
629 !IsPrint() && pPageObj->clip_path().HasRef() &&
630 pPageObj->clip_path().GetTextCount() > 0 &&
633 !bTextClip && !bGroupTransparent && initial_alpha == 1.0f) {
638 DrawObjWithBackground(pPageObj, mtObj2Device);
643 rect.Intersect(m_pDevice->GetClipBox());
649 CFX_DefaultRenderDevice bitmap_device;
651 if (!transparency.IsIsolated() &&
653 backdrop =
pdfium::MakeRetain<CFX_DIBitmap>();
654 if (!m_pDevice->CreateCompatibleBitmap(backdrop, width, height))
656 m_pDevice->GetDIBits(backdrop, rect.left, rect.top);
659 width
, height
, GetCompatibleArgbFormat()
, std::move(backdrop)
)) {
666 RetainPtr<CFX_DIBitmap> text_mask_bitmap;
668 text_mask_bitmap =
pdfium::MakeRetain<CFX_DIBitmap>();
673 CFX_DefaultRenderDevice text_device;
675 for (size_t i = 0; i < pPageObj
->clip_path().GetTextCount(); ++i) {
681 CPDF_TextRenderer::DrawTextPath(
682 &text_device, textobj->GetCharCodes(), textobj->GetCharPositions(),
685 &new_matrix, textobj
->graph_state().GetObject(), 0xffffffff, 0,
690 bitmap_render.SetOptions(m_Options);
691 bitmap_render.SetStopObject(m_pStopObj);
697 bitmap_render.ProcessObjectNoClip(pPageObj, new_matrix);
698 m_bStopped = bitmap_render.m_bStopped;
703 LoadSMask(pSMaskDict.Get(), rect, smask_matrix);
708 if (text_mask_bitmap) {
714 if (initial_alpha != 1.0f && !m_bInGroup) {
717 transparency
= m_Transparency;
722 0
, 1.0f
, blend_type
, transparency
);
728 bbox.Intersect(m_pDevice->GetClipBox());
735 bool bBackAlphaRequired) {
738 auto backdrop =
pdfium::MakeRetain<CFX_DIBitmap>();
739 if (bBackAlphaRequired && !m_bDropObjects) {
746 if (!m_pDevice->CreateCompatibleBitmap(backdrop, width, height)) {
751 const int cap_to_check =
753 if (m_pDevice->GetRenderCaps() & cap_to_check) {
754 m_pDevice->GetDIBits(backdrop, bbox.left, bbox.top);
759 if (!backdrop->IsAlphaFormat()) {
760 backdrop->Clear(0xffffffff);
763 CFX_DefaultRenderDevice device;
765 m_pContext->Render(&device, pObj, &m_Options, &FinalMatrix);
780 pStates->mutable_color_state().SetFillColorRef(
783 pStates->mutable_color_state().SetStrokeColorRef(
784 pStates->color_state().GetFillColorRef());
792 if (textobj->GetCharCodes().empty())
801 if (pFont->IsType3Font())
802 return ProcessType3Text(textobj, mtObj2Device);
804 bool is_fill =
false;
805 bool is_stroke =
false;
806 bool is_clip =
false;
810 switch (text_render_mode) {
817 if (pFont->HasFace())
825 if (pFont->HasFace())
840 bool bPattern =
false;
845 stroke_argb = GetStrokeArgb(textobj);
856 if (!IsAvailableMatrix(text_matrix))
861 DrawTextPathWithPattern(textobj, mtObj2Device, pFont.Get(), font_size,
862 text_matrix, is_fill, is_stroke);
865 if (is_clip || is_stroke) {
866 const CFX_Matrix* pDeviceMatrix = &mtObj2Device;
869 pdfium::span<
const float> pCTM = textobj
->text_state().GetCTM();
870 if (pCTM[0] != 1.0f || pCTM[3] != 1.0f) {
871 CFX_Matrix ctm(pCTM[0], pCTM[1], pCTM[2], pCTM[3], 0, 0);
873 device_matrix
= ctm
* mtObj2Device;
874 pDeviceMatrix = &device_matrix;
877 return CPDF_TextRenderer::DrawTextPath(
878 m_pDevice, textobj->GetCharCodes(), textobj->GetCharPositions(),
879 pFont.Get(), font_size, text_matrix, pDeviceMatrix,
880 textobj->graph_state().GetObject(), fill_argb, stroke_argb,
882 GetFillOptionsForDrawTextPath(m_Options.GetOptions(), textobj,
883 is_stroke, is_fill));
886 return CPDF_TextRenderer::DrawNormalText(
887 m_pDevice, textobj->GetCharCodes(), textobj->GetCharPositions(),
888 pFont.Get(), font_size, text_matrix, fill_argb, m_Options);
894 CPDF_Type3Font* pType3Font = textobj
->text_state().GetFont()->AsType3Font();
895 if (pdfium::Contains(m_Type3FontCache, pType3Font))
899 int fill_alpha =
FXARGB_A(fill_argb);
901 if (IsPrint() && fill_alpha < 255) {
912 std::set<RetainPtr<CPDF_Type3Cache>> refTypeCache;
913 std::vector<TextGlyphPos> glyphs;
915 glyphs.resize(textobj->GetCharCodes().size());
918 for (size_t iChar = 0; iChar < textobj->GetCharCodes().size(); ++iChar) {
919 uint32_t charcode = textobj->GetCharCodes()[iChar];
920 if (charcode ==
static_cast<uint32_t>(-1))
928 matrix
.e += iChar > 0 ? textobj->GetCharPositions()[iChar - 1] : 0;
932 if (!glyphs.empty()) {
933 for (size_t i = 0; i < iChar; ++i) {
938 std::optional<
CFX_Point> point = glyph.GetOrigin({0, 0});
939 if (!point.has_value())
942 m_pDevice->SetBitMask(glyph.m_pGlyph->GetBitmap(), point->x, point->y,
948 std::unique_ptr<CPDF_GraphicStates> pStates =
949 CloneObjStates(&textobj->graphic_states(),
false);
954 const auto* pForm =
static_cast<
const CPDF_Form*>(pType3Char
->form());
956 pForm->GetDict()->GetDictFor(
"Resources");
958 if (fill_alpha == 255) {
967 status.m_Type3FontCache = m_Type3FontCache;
968 status.m_Type3FontCache.emplace_back(pType3Font);
974 matrix.TransformRect(pForm->CalcBoundingBox()).GetOuterRect();
978 CFX_DefaultRenderDevice bitmap_device;
993 status.m_Type3FontCache = m_Type3FontCache;
994 status.m_Type3FontCache.emplace_back(pType3Font);
997 m_pDevice->SetDIBits(bitmap_device.GetBitmap(), rect.left, rect.top);
1000#if BUILDFLAG(IS_WIN)
1002 CFX_Matrix image_matrix = pType3Char->matrix() * matrix;
1003 CPDF_ImageRenderer renderer(
this);
1004 if (renderer.Start(pType3Char->GetBitmap(), fill_argb, image_matrix,
1005 FXDIB_ResampleOptions(),
false)) {
1006 renderer.Continue(
nullptr);
1008 if (!renderer.GetResult()) {
1017 CPDF_DocRenderData::FromDocument(pDoc)->GetCachedType3(pType3Font);
1024 refTypeCache.insert(
std::move(pCache));
1026 CFX_Point origin(FXSYS_roundf(matrix.e), FXSYS_roundf(matrix.f));
1027 if (glyphs.empty()) {
1030 if (!left.IsValid()) {
1036 if (!top.IsValid()) {
1040 m_pDevice->SetBitMask(pBitmap->GetBitmap(), left.ValueOrDie(),
1041 top.ValueOrDie(), fill_argb);
1043 glyphs[iChar].m_pGlyph = pBitmap;
1044 glyphs[iChar].m_Origin = origin;
1052 FX_RECT rect = GetGlyphsBBox(glyphs, 0);
1053 auto bitmap =
pdfium::MakeRetain<CFX_DIBitmap>();
1058 for (
const TextGlyphPos& glyph : glyphs) {
1059 if (!glyph.m_pGlyph || !glyph.m_pGlyph->GetBitmap()->IsMaskFormat())
1062 std::optional<CFX_Point> point = glyph.GetOrigin({rect.left, rect.top});
1063 if (!point.has_value())
1066 bitmap->CompositeMask(
1067 point->x, point->y, glyph.m_pGlyph->GetBitmap()->GetWidth(),
1068 glyph.m_pGlyph->GetBitmap()->GetHeight(), glyph.m_pGlyph->GetBitmap(),
1069 fill_argb, 0, 0, BlendMode::kNormal,
nullptr,
false);
1071 m_pDevice->SetBitMask(std::move(bitmap), rect.left, rect.top, fill_argb);
1083 std::vector<std::unique_ptr<CPDF_TextObject>> pCopy;
1084 pCopy.push_back(textobj->Clone());
1086 CPDF_PathObject path;
1088 path.mutable_clip_path().CopyClipPath(m_LastClipPath);
1100 std::vector<TextCharPos> char_pos_list = GetCharPosList(
1101 textobj->GetCharCodes(), textobj->GetCharPositions(), pFont, font_size);
1102 for (
const TextCharPos& charpos : char_pos_list) {
1103 auto* font = charpos.m_FallbackFontPosition == -1
1105 : pFont->GetFontFallback(charpos.m_FallbackFontPosition);
1106 const CFX_Path* pPath =
1107 font->LoadGlyphPath(charpos.m_GlyphIndex, charpos.m_FontCharWidth);
1111 CPDF_PathObject path;
1112 path.mutable_graph_state() = textobj->graph_state();
1113 path.mutable_color_state() = textobj->color_state();
1115 CFX_Matrix matrix = charpos.GetEffectiveMatrix(CFX_Matrix(
1116 font_size, 0, 0, font_size, charpos.m_Origin.x, charpos.m_Origin.y));
1117 matrix.Concat(mtTextMatrix);
1118 path.set_stroke(stroke);
1119 path.set_filltype(fill ? CFX_FillRenderOptions::FillType::kWinding
1120 : CFX_FillRenderOptions::FillType::kNoFill);
1121 path.path().Append(*pPath, &matrix);
1122 path.SetPathMatrix(CFX_Matrix());
1123 ProcessPath(&path, mtObj2Device);
1135 if (!ClipPattern(pPageObj, mtObj2Device, stroke))
1138 FX_RECT rect = GetObjectClippedRect(pPageObj, mtObj2Device);
1146 CPDF_RenderShading::Draw(m_pDevice, m_pContext, m_pCurObj, pattern, matrix,
1147 rect, alpha, m_Options);
1152 FX_RECT rect = GetObjectClippedRect(pShadingObj, mtObj2Device);
1157 CPDF_RenderShading::Draw(
1158 m_pDevice, m_pContext, m_pCurObj, pShadingObj->pattern(), matrix, rect,
1159 FXSYS_roundf(255 * pShadingObj->general_state().GetFillAlpha()),
1167 const std::unique_ptr<CPDF_Form> pPatternForm = pattern->Load(pPageObj);
1172 if (!ClipPattern(pPageObj, mtObj2Device, stroke))
1175 FX_RECT clip_box = m_pDevice->GetClipBox();
1180 CPDF_RenderTiling::Draw(
this, pPageObj, pattern, pPatternForm.get(),
1181 mtObj2Device, clip_box, stroke);
1199 if (CPDF_TilingPattern* pTilingPattern = pattern->AsTilingPattern())
1201 else if (CPDF_ShadingPattern* pShadingPattern = pattern->AsShadingPattern())
1206 CPDF_PathObject* path_obj,
1216 DrawPathWithPattern(path_obj, mtObj2Device, &FillColor,
false);
1223 DrawPathWithPattern(path_obj, mtObj2Device, &StrokeColor,
true);
1232 if (render
.Start(pImageObj
, mtObj2Device
, m_bStdCS
)) {
1249 if (bitmap->IsMaskFormat()) {
1250#if BUILDFLAG(IS_WIN)
1251 FX_ARGB fill_argb = m_Options.TranslateColor(mask_argb);
1252 if (alpha != 1.0f) {
1253 auto& bgra =
reinterpret_cast<FX_BGRA_STRUCT<uint8_t>&>(fill_argb);
1254 bgra.alpha *= FXSYS_roundf(alpha * 255) / 255;
1256 if (m_pDevice->SetBitMask(bitmap, left, top, fill_argb)) {
1263 if (alpha != 1.0f) {
1266 bitmap->GetWidth()
, bitmap->GetHeight()
, left
, top
);
1267 m_pDevice->StartDIBits(std::move(bitmap), alpha, 0, matrix,
1268 FXDIB_ResampleOptions());
1271 bitmap->MultiplyAlpha(alpha);
1273 if (m_pDevice->SetDIBits(bitmap, left, top)) {
1279 bool bBackAlphaRequired =
1281 bool bGetBackGround =
1284 (m_pDevice->GetRenderCaps() &
FXRC_GET_BITS) && !bBackAlphaRequired);
1285 if (bGetBackGround) {
1287 if (!bitmap->IsMaskFormat()) {
1288 m_pDevice->SetDIBitsWithBlend(std::move(bitmap), left, top, blend_mode);
1293 FX_RECT rect(left, top, left + bitmap->GetWidth(),
1294 top + bitmap->GetHeight());
1295 rect.Intersect(m_pDevice->GetClipBox());
1297 if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) {
1298 pClone = m_pDevice->GetBackDrop()->ClipTo(rect);
1302 pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(),
1303 m_pDevice->GetBitmap(), rect.left, rect.top,
1304 BlendMode::kNormal,
nullptr,
false);
1305 left =
std::min(left, 0);
1306 top =
std::min(top, 0);
1307 if (bitmap->IsMaskFormat()) {
1308#if BUILDFLAG(IS_WIN)
1309 pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(),
1310 bitmap, mask_argb, left, top, blend_mode,
nullptr,
1316 pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(),
1317 bitmap, left, top, blend_mode,
nullptr,
false);
1322 if (m_pDevice->GetBackDrop()) {
1323 m_pDevice->SetDIBits(pClone, rect.left, rect.top);
1325 if (!bitmap->IsMaskFormat()) {
1326 m_pDevice->SetDIBitsWithBlend(std::move(bitmap), rect.left, rect.top,
1333 FX_RECT bbox = GetClippedBBox(
1334 FX_RECT(left, top, left + bitmap->GetWidth(), top + bitmap->GetHeight()));
1335 RetainPtr<CFX_DIBitmap> backdrop = GetBackdrop(
1336 m_pCurObj, bbox, blend_mode != BlendMode::kNormal && bIsolated);
1341 const int width = bitmap->GetWidth();
1342 const int height = bitmap->GetHeight();
1343 if (bitmap->IsMaskFormat()) {
1344#if BUILDFLAG(IS_WIN)
1345 backdrop->CompositeMask(left - bbox.left, top - bbox.top, width, height,
1346 std::move(bitmap), mask_argb, 0, 0, blend_mode,
1352 backdrop->CompositeBitmap(left - bbox
.left, top - bbox
.top, width, height,
1353 std::move(bitmap), 0, 0, blend_mode,
nullptr,
1357 auto new_backdrop =
pdfium::MakeRetain<CFX_DIBitmap>();
1358 CHECK(new_backdrop->Create(backdrop->GetWidth(), backdrop->GetHeight(),
1360 new_backdrop->Clear(0xffffffff);
1361 new_backdrop->CompositeBitmap(0, 0, new_backdrop->GetWidth(),
1362 new_backdrop->GetHeight(),
std::move(backdrop),
1364 m_pDevice->SetDIBits(std::move(new_backdrop), bbox.left, bbox.top);
1372 smask_dict->GetMutableStreamFor(pdfium::transparency::kG);
1376 std::unique_ptr<CPDF_Function> pFunc;
1378 smask_dict->GetDirectObjectFor(pdfium::transparency::kTR);
1379 if (pFuncObj && (pFuncObj->IsDictionary() || pFuncObj->IsStream()))
1380 pFunc = CPDF_Function::Load(
std::move(pFuncObj));
1385 CPDF_Form form(m_pContext->GetDocument(),
1386 m_pContext->GetMutablePageResources(), pGroup);
1389 CFX_DefaultRenderDevice bitmap_device;
1393 const int width = clip_rect
.Width();
1395 const FXDIB_Format format = GetFormatForLuminosity(bLuminosity);
1396 if (!bitmap_device
.Create(width
, height
, format
)) {
1401 const FX_ARGB background_color =
1403 ? GetBackgroundColor(smask_dict, pGroup->GetDict().Get(), &nCSFamily)
1405 bitmap_device
.Clear(background_color
);
1408 form.GetDict()->GetDictFor(
"Resources");
1422 auto result_mask =
pdfium::MakeRetain<CFX_DIBitmap>();
1427 pdfium::span<uint8_t> dest_buf = result_mask->GetWritableBuffer();
1428 RetainPtr<
const CFX_DIBitmap> bitmap = bitmap_device.GetBitmap();
1429 pdfium::span<
const uint8_t> src_buf = bitmap->GetBuffer();
1430 const int dest_pitch = result_mask->GetPitch();
1431 const int src_pitch = bitmap->GetPitch();
1432 DataVector<uint8_t> transfers(256);
1434 std::vector<
float> results(pFunc->OutputCount());
1435 for (size_t i = 0; i < transfers.size(); ++i) {
1436 float input = i / 255.0f;
1437 pFunc->Call(
pdfium::span_from_ref(input), results);
1438 transfers[i] = FXSYS_roundf(results[0] * 255);
1442 std::iota(transfers.begin(), transfers.end(), 0);
1445 const int bytes_per_pixel = bitmap->GetBPP() / 8;
1446 for (
int row = 0; row < height; row++) {
1447 const size_t dest_offset = Fx2DSizeOrDie(row, dest_pitch);
1448 const size_t src_offset = Fx2DSizeOrDie(row, src_pitch);
1449 uint8_t* dest_pos = dest_buf.subspan(dest_offset).data();
1450 const uint8_t* src_pos = src_buf.subspan(src_offset).data();
1451 for (
int col = 0; col < width; col++) {
1453 *dest_pos++ = transfers[
FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos)];
1454 src_pos += bytes_per_pixel;
1459 int size = dest_pitch * height;
1460 for (
int i = 0; i < size; i++) {
1461 dest_buf[i] = transfers[src_buf[i]];
1464 fxcrt::Copy(src_buf.first(dest_pitch * height), dest_buf);
1475 pSMaskDict->GetArrayFor(pdfium::transparency::kBC);
1477 return kDefaultColor;
1481 pGroupDict ? pGroupDict->GetDictFor(
"Group") :
nullptr;
1485 CPDF_DocPageData::FromDocument(m_pContext->GetDocument())
1486 ->GetColorSpace(pCSObj.Get(),
nullptr);
1488 return kDefaultColor;
1493 return kDefaultColor;
1497 *pCSFamily = family;
1499 uint32_t comps =
std::max(8u, pCS->ComponentCount());
1500 size_t count = std::min<size_t>(8, pBC->size());
1501 std::vector<
float> floats = ReadArrayElementsToVector(pBC.Get(), count);
1502 floats.resize(comps);
1504 auto rgb = pCS->GetRGBOrZerosOnError(floats);
1506 static_cast<
int>(rgb.green * 255)
,
1507 static_cast<
int>(rgb.blue * 255)
);
1511#if defined(PDF_USE_SKIA)
1512 if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_PREMULTIPLIED_ALPHA) {
1513 return FXDIB_Format::kBgraPremul;
static bool UseSkiaRenderer()
bool Attach(RetainPtr< CFX_DIBitmap > pBitmap)
bool CreateWithBackdrop(int width, int height, FXDIB_Format format, RetainPtr< CFX_DIBitmap > backdrop)
bool Create(int width, int height, FXDIB_Format format)
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(RetainPtr< const CFX_DIBitmap > mask)
static CFX_Matrix GetFlipMatrix(float width, float height, float left, float top)
std::vector< RetainPtr< CPDF_Object > >::const_iterator const_iterator
FX_COLORREF GetStrokeColorRef() const
FX_COLORREF GetFillColorRef() const
const CPDF_Color * GetStrokeColor() const
const CPDF_Color * GetFillColor() const
ByteString GetByteStringFor(const ByteString &key) const
std::map< ByteString, RetainPtr< CPDF_Object >, std::less<> > DictMap
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 Start(CPDF_ImageObject *pImageObject, const CFX_Matrix &mtObj2Device, bool bStdCS)
bool Continue(PauseIndicatorIface *pPause)
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 DrawTilingPattern(CPDF_TilingPattern *pattern, CPDF_PageObject *pPageObj, const CFX_Matrix &mtObj2Device, bool stroke)
void SetInGroup(bool bInGroup)
void SetFormResource(RetainPtr< const CPDF_Dictionary > pRes)
FX_ARGB GetFillArgb(CPDF_PageObject *pObj) const
void CompositeDIBitmap(RetainPtr< CFX_DIBitmap > bitmap, int left, int top, FX_ARGB mask_argb, float alpha, BlendMode blend_mode, const CPDF_Transparency &transparency)
void SetLoadMask(bool bLoadMask)
void ProcessClipPath(const CPDF_ClipPath &ClipPath, const CFX_Matrix &mtObj2Device)
const CFX_Matrix & matrix() const
CFX_Matrix GetTextMatrix() const
CPDF_Transparency & operator=(const CPDF_Transparency &other)
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
CFX_PTemplate< int32_t > CFX_Point
#define FXRGB2GRAY(r, g, b)
constexpr FX_ARGB ArgbEncode(uint32_t a, uint32_t r, uint32_t g, uint32_t b)
pdfium::CheckedNumeric< int32_t > FX_SAFE_INT32
int FXSYS_roundf(float f)
const char kSoftMaskSubType[]
#define NOTREACHED_NORETURN()
#define FXRC_ALPHA_OUTPUT
constexpr CFX_FillRenderOptions()
constexpr CFX_FillRenderOptions(FillType fill_type)
static constexpr CFX_FillRenderOptions WindingOptions()