Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cpdf_shadingpattern.cpp
Go to the documentation of this file.
1// Copyright 2016 The PDFium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "core/fpdfapi/page/cpdf_shadingpattern.h"
8
9#include <algorithm>
10#include <utility>
11
12#include "core/fpdfapi/page/cpdf_docpagedata.h"
13#include "core/fpdfapi/page/cpdf_function.h"
14#include "core/fpdfapi/parser/cpdf_array.h"
15#include "core/fpdfapi/parser/cpdf_dictionary.h"
16#include "core/fpdfapi/parser/cpdf_document.h"
17#include "core/fpdfapi/parser/cpdf_object.h"
18#include "core/fpdfapi/parser/cpdf_stream.h"
19#include "core/fxcrt/fx_safe_types.h"
20#include "third_party/base/check.h"
21#include "third_party/base/notreached.h"
22
23namespace {
24
25ShadingType ToShadingType(int type) {
26 return (type > kInvalidShading && type < kMaxShading)
27 ? static_cast<ShadingType>(type)
29}
30
31} // namespace
32
33CPDF_ShadingPattern::CPDF_ShadingPattern(CPDF_Document* pDoc,
34 RetainPtr<CPDF_Object> pPatternObj,
35 bool bShading,
36 const CFX_Matrix& parentMatrix)
37 : CPDF_Pattern(pDoc, std::move(pPatternObj), parentMatrix),
38 m_bShading(bShading) {
39 DCHECK(document());
40 if (!bShading)
42}
43
44CPDF_ShadingPattern::~CPDF_ShadingPattern() = default;
45
46CPDF_ShadingPattern* CPDF_ShadingPattern::AsShadingPattern() {
47 return this;
48}
49
50bool CPDF_ShadingPattern::Load() {
51 if (m_ShadingType != kInvalidShading)
52 return true;
53
54 RetainPtr<const CPDF_Object> pShadingObj = GetShadingObject();
55 RetainPtr<const CPDF_Dictionary> pShadingDict =
56 pShadingObj ? pShadingObj->GetDict() : nullptr;
57 if (!pShadingDict)
58 return false;
59
60 m_pFunctions.clear();
61 RetainPtr<const CPDF_Object> pFunc =
62 pShadingDict->GetDirectObjectFor("Function");
63 if (pFunc) {
64 if (const CPDF_Array* pArray = pFunc->AsArray()) {
65 m_pFunctions.resize(std::min<size_t>(pArray->size(), 4));
66 for (size_t i = 0; i < m_pFunctions.size(); ++i) {
67 m_pFunctions[i] = CPDF_Function::Load(pArray->GetDirectObjectAt(i));
68 }
69 } else {
70 m_pFunctions.push_back(CPDF_Function::Load(std::move(pFunc)));
71 }
72 }
73 RetainPtr<const CPDF_Object> pCSObj =
74 pShadingDict->GetDirectObjectFor("ColorSpace");
75 if (!pCSObj)
76 return false;
77
78 auto* pDocPageData = CPDF_DocPageData::FromDocument(document());
79 m_pCS = pDocPageData->GetColorSpace(pCSObj.Get(), nullptr);
80
81 // The color space is required and cannot be a Pattern space, according to the
82 // PDF 1.7 spec, page 305.
83 if (!m_pCS || m_pCS->GetFamily() == CPDF_ColorSpace::Family::kPattern)
84 return false;
85
86 m_ShadingType = ToShadingType(pShadingDict->GetIntegerFor("ShadingType"));
87 return Validate();
88}
89
90RetainPtr<const CPDF_Object> CPDF_ShadingPattern::GetShadingObject() const {
91 return m_bShading ? pattern_obj()
92 : pattern_obj()->GetDict()->GetDirectObjectFor("Shading");
93}
94
95bool CPDF_ShadingPattern::Validate() const {
96 if (m_ShadingType == kInvalidShading)
97 return false;
98
99 // We expect to have a stream if our shading type is a mesh.
100 if (IsMeshShading() && !ToStream(GetShadingObject()))
101 return false;
102
103 // Validate color space
104 switch (m_ShadingType) {
106 case kAxialShading:
107 case kRadialShading: {
108 if (m_pCS->GetFamily() == CPDF_ColorSpace::Family::kIndexed)
109 return false;
110 break;
111 }
116 if (!m_pFunctions.empty() &&
117 m_pCS->GetFamily() == CPDF_ColorSpace::Family::kIndexed) {
118 return false;
119 }
120 break;
121 }
122 default: {
123 NOTREACHED_NORETURN();
124 }
125 }
126
127 uint32_t nNumColorSpaceComponents = m_pCS->CountComponents();
128 switch (m_ShadingType) {
130 // Either one 2-to-N function or N 2-to-1 functions.
131 return ValidateFunctions(1, 2, nNumColorSpaceComponents) ||
132 ValidateFunctions(nNumColorSpaceComponents, 2, 1);
133 }
134 case kAxialShading:
135 case kRadialShading: {
136 // Either one 1-to-N function or N 1-to-1 functions.
137 return ValidateFunctions(1, 1, nNumColorSpaceComponents) ||
138 ValidateFunctions(nNumColorSpaceComponents, 1, 1);
139 }
144 // Either no function, one 1-to-N function, or N 1-to-1 functions.
145 return m_pFunctions.empty() ||
146 ValidateFunctions(1, 1, nNumColorSpaceComponents) ||
147 ValidateFunctions(nNumColorSpaceComponents, 1, 1);
148 }
149 default:
150 NOTREACHED_NORETURN();
151 }
152}
153
154bool CPDF_ShadingPattern::ValidateFunctions(
155 uint32_t nExpectedNumFunctions,
156 uint32_t nExpectedNumInputs,
157 uint32_t nExpectedNumOutputs) const {
158 if (m_pFunctions.size() != nExpectedNumFunctions)
159 return false;
160
161 FX_SAFE_UINT32 nTotalOutputs = 0;
162 for (const auto& function : m_pFunctions) {
163 if (!function)
164 return false;
165
166 if (function->CountInputs() != nExpectedNumInputs ||
167 function->CountOutputs() != nExpectedNumOutputs) {
168 return false;
169 }
170
171 nTotalOutputs += function->CountOutputs();
172 }
173
174 return nTotalOutputs.IsValid();
175}
static CPDF_DocPageData * FromDocument(const CPDF_Document *pDoc)
void SetPatternToFormMatrix()
CPDF_Document * document() const
CPDF_ShadingPattern * AsShadingPattern() override
~CPDF_ShadingPattern() override
RetainPtr< const CPDF_Object > GetShadingObject() const
@ kRadialShading
@ kAxialShading
@ kInvalidShading
@ kCoonsPatchMeshShading
@ kMaxShading
@ kTensorProductPatchMeshShading
@ kLatticeFormGouraudTriangleMeshShading
@ kFreeFormGouraudTriangleMeshShading
@ kFunctionBasedShading