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_meshstream.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_meshstream.h"
8
9#include <utility>
10
11#include "core/fpdfapi/page/cpdf_colorspace.h"
12#include "core/fpdfapi/page/cpdf_function.h"
13#include "core/fpdfapi/parser/cpdf_array.h"
14#include "core/fpdfapi/parser/cpdf_dictionary.h"
15#include "core/fpdfapi/parser/cpdf_stream.h"
16#include "core/fpdfapi/parser/cpdf_stream_acc.h"
17#include "core/fxcrt/cfx_bitstream.h"
18#include "core/fxcrt/check.h"
19#include "core/fxcrt/compiler_specific.h"
20#include "core/fxcrt/span.h"
21
22namespace {
23
24// See PDF Reference 1.7, page 315, table 4.32. (Also table 4.33 and 4.34)
25bool ShouldCheckBPC(ShadingType type) {
26 switch (type) {
31 return true;
32 default:
33 return false;
34 }
35}
36
37// Same references as ShouldCheckBPC() above.
38bool IsValidBitsPerComponent(uint32_t x) {
39 switch (x) {
40 case 1:
41 case 2:
42 case 4:
43 case 8:
44 case 12:
45 case 16:
46 return true;
47 default:
48 return false;
49 }
50}
51
52// Same references as ShouldCheckBPC() above.
53bool IsValidBitsPerCoordinate(uint32_t x) {
54 switch (x) {
55 case 1:
56 case 2:
57 case 4:
58 case 8:
59 case 12:
60 case 16:
61 case 24:
62 case 32:
63 return true;
64 default:
65 return false;
66 }
67}
68
69// See PDF Reference 1.7, page 315, table 4.32. (Also table 4.34)
70bool ShouldCheckBitsPerFlag(ShadingType type) {
71 switch (type) {
75 return true;
76 default:
77 return false;
78 }
79}
80
81// Same references as ShouldCheckBitsPerFlag() above.
82bool IsValidBitsPerFlag(uint32_t x) {
83 switch (x) {
84 case 2:
85 case 4:
86 case 8:
87 return true;
88 default:
89 return false;
90 }
91}
92
93} // namespace
94
96
98
100
102 ShadingType type,
103 const std::vector<std::unique_ptr<CPDF_Function>>& funcs,
104 RetainPtr<const CPDF_Stream> pShadingStream,
106 : m_type(type),
107 m_funcs(funcs),
109 m_pCS(std::move(pCS)),
111
112CPDF_MeshStream::~CPDF_MeshStream() = default;
113
115 m_pStream->LoadAllDataFiltered();
116 m_BitStream = std::make_unique<CFX_BitStream>(m_pStream->GetSpan());
117
118 RetainPtr<const CPDF_Dictionary> pDict = m_pShadingStream->GetDict();
119 m_nCoordBits = pDict->GetIntegerFor("BitsPerCoordinate");
120 m_nComponentBits = pDict->GetIntegerFor("BitsPerComponent");
121 if (ShouldCheckBPC(m_type)) {
122 if (!IsValidBitsPerCoordinate(m_nCoordBits))
123 return false;
124 if (!IsValidBitsPerComponent(m_nComponentBits))
125 return false;
126 }
127
128 m_nFlagBits = pDict->GetIntegerFor("BitsPerFlag");
129 if (ShouldCheckBitsPerFlag(m_type) && !IsValidBitsPerFlag(m_nFlagBits))
130 return false;
131
132 uint32_t nComponents = m_pCS->ComponentCount();
133 if (nComponents > kMaxComponents)
134 return false;
135
136 m_nComponents = m_funcs.empty() ? nComponents : 1;
137 RetainPtr<const CPDF_Array> pDecode = pDict->GetArrayFor("Decode");
138 if (!pDecode || pDecode->size() != 4 + m_nComponents * 2)
139 return false;
140
141 m_xmin = pDecode->GetFloatAt(0);
142 m_xmax = pDecode->GetFloatAt(1);
143 m_ymin = pDecode->GetFloatAt(2);
144 m_ymax = pDecode->GetFloatAt(3);
145 for (uint32_t i = 0; i < m_nComponents; ++i) {
146 m_ColorMin[i] = pDecode->GetFloatAt(i * 2 + 4);
147 m_ColorMax[i] = pDecode->GetFloatAt(i * 2 + 5);
148 }
149 if (ShouldCheckBPC(m_type)) {
150 m_CoordMax = m_nCoordBits == 32 ? -1 : (1 << m_nCoordBits) - 1;
151 m_ComponentMax = (1 << m_nComponentBits) - 1;
152 }
153 return true;
154}
155
156void CPDF_MeshStream::SkipBits(uint32_t nbits) {
157 m_BitStream->SkipBits(nbits);
158}
159
161 m_BitStream->ByteAlign();
162}
163
164bool CPDF_MeshStream::IsEOF() const {
165 return m_BitStream->IsEOF();
166}
167
169 return m_BitStream->BitsRemaining() >= m_nFlagBits;
170}
171
173 return m_BitStream->BitsRemaining() / 2 >= m_nCoordBits;
174}
175
177 return m_BitStream->BitsRemaining() / m_nComponentBits >= m_nComponents;
178}
179
180uint32_t CPDF_MeshStream::ReadFlag() const {
181 DCHECK(ShouldCheckBitsPerFlag(m_type));
182 return m_BitStream->GetBits(m_nFlagBits) & 0x03;
183}
184
186 DCHECK(ShouldCheckBPC(m_type));
187
188 CFX_PointF pos;
189 if (m_nCoordBits == 32) {
190 pos.x = m_xmin + m_BitStream->GetBits(m_nCoordBits) * (m_xmax - m_xmin) /
191 static_cast<double>(m_CoordMax);
192 pos.y = m_ymin + m_BitStream->GetBits(m_nCoordBits) * (m_ymax - m_ymin) /
193 static_cast<double>(m_CoordMax);
194 } else {
195 pos.x = m_xmin +
196 m_BitStream->GetBits(m_nCoordBits) * (m_xmax - m_xmin) / m_CoordMax;
197 pos.y = m_ymin +
198 m_BitStream->GetBits(m_nCoordBits) * (m_ymax - m_ymin) / m_CoordMax;
199 }
200 return pos;
201}
202
204 DCHECK(ShouldCheckBPC(m_type));
205
206 std::array<float, kMaxComponents> color_value;
207 for (uint32_t i = 0; i < m_nComponents; ++i) {
208 color_value[i] = m_ColorMin[i] + m_BitStream->GetBits(m_nComponentBits) *
209 (m_ColorMax[i] - m_ColorMin[i]) /
210 m_ComponentMax;
211 }
212 if (m_funcs.empty()) {
213 return m_pCS->GetRGBOrZerosOnError(color_value);
214 }
215 float result[kMaxComponents] = {};
216 for (const auto& func : m_funcs) {
217 if (func && func->OutputCount() <= kMaxComponents) {
218 func->Call(pdfium::make_span(color_value).first<1u>(), result);
219 }
220 }
221 return m_pCS->GetRGBOrZerosOnError(result);
222}
223
224bool CPDF_MeshStream::ReadVertex(const CFX_Matrix& pObject2Bitmap,
225 CPDF_MeshVertex* vertex,
226 uint32_t* flag) {
227 if (!CanReadFlag())
228 return false;
229 *flag = ReadFlag();
230
231 if (!CanReadCoords())
232 return false;
233 vertex->position = pObject2Bitmap.Transform(ReadCoords());
234
235 if (!CanReadColor())
236 return false;
237 vertex->rgb = ReadColor();
238 m_BitStream->ByteAlign();
239 return true;
240}
241
243 const CFX_Matrix& pObject2Bitmap,
244 int count) {
245 std::vector<CPDF_MeshVertex> vertices;
246 for (int i = 0; i < count; ++i) {
247 if (m_BitStream->IsEOF() || !CanReadCoords())
248 return std::vector<CPDF_MeshVertex>();
249
250 vertices.emplace_back();
251 CPDF_MeshVertex& vertex = vertices.back();
252 vertex.position = pObject2Bitmap.Transform(ReadCoords());
253 if (!CanReadColor())
254 return std::vector<CPDF_MeshVertex>();
255
256 vertex.rgb = ReadColor();
257 m_BitStream->ByteAlign();
258 }
259 return vertices;
260}
#define DCHECK
Definition check.h:33
std::vector< RetainPtr< CPDF_Object > >::const_iterator const_iterator
Definition cpdf_array.h:29
std::map< ByteString, RetainPtr< CPDF_Object >, std::less<> > DictMap
CFX_PointF ReadCoords() const
uint32_t ReadFlag() const
bool CanReadCoords() const
bool CanReadFlag() const
bool ReadVertex(const CFX_Matrix &pObject2Bitmap, CPDF_MeshVertex *vertex, uint32_t *flag)
void SkipBits(uint32_t nbits)
FX_RGB_STRUCT< float > ReadColor() const
bool CanReadColor() const
CPDF_MeshStream(ShadingType type, const std::vector< std::unique_ptr< CPDF_Function > > &funcs, RetainPtr< const CPDF_Stream > pShadingStream, RetainPtr< CPDF_ColorSpace > pCS)
std::vector< CPDF_MeshVertex > ReadVertexRow(const CFX_Matrix &pObject2Bitmap, int count)
CPDF_MeshVertex(const CPDF_MeshVertex &)
@ kCoonsPatchMeshShading
@ kTensorProductPatchMeshShading
@ kLatticeFormGouraudTriangleMeshShading
@ kFreeFormGouraudTriangleMeshShading
CFX_PTemplate< float > CFX_PointF