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 "third_party/base/check.h"
19#include "third_party/base/containers/span.h"
20
21namespace {
22
23// See PDF Reference 1.7, page 315, table 4.32. (Also table 4.33 and 4.34)
24bool ShouldCheckBPC(ShadingType type) {
25 switch (type) {
30 return true;
31 default:
32 return false;
33 }
34}
35
36// Same references as ShouldCheckBPC() above.
37bool IsValidBitsPerComponent(uint32_t x) {
38 switch (x) {
39 case 1:
40 case 2:
41 case 4:
42 case 8:
43 case 12:
44 case 16:
45 return true;
46 default:
47 return false;
48 }
49}
50
51// Same references as ShouldCheckBPC() above.
52bool IsValidBitsPerCoordinate(uint32_t x) {
53 switch (x) {
54 case 1:
55 case 2:
56 case 4:
57 case 8:
58 case 12:
59 case 16:
60 case 24:
61 case 32:
62 return true;
63 default:
64 return false;
65 }
66}
67
68// See PDF Reference 1.7, page 315, table 4.32. (Also table 4.34)
69bool ShouldCheckBitsPerFlag(ShadingType type) {
70 switch (type) {
74 return true;
75 default:
76 return false;
77 }
78}
79
80// Same references as ShouldCheckBitsPerFlag() above.
81bool IsValidBitsPerFlag(uint32_t x) {
82 switch (x) {
83 case 2:
84 case 4:
85 case 8:
86 return true;
87 default:
88 return false;
89 }
90}
91
92} // namespace
93
95
97
99
101 ShadingType type,
102 const std::vector<std::unique_ptr<CPDF_Function>>& funcs,
103 RetainPtr<const CPDF_Stream> pShadingStream,
105 : m_type(type),
106 m_funcs(funcs),
108 m_pCS(std::move(pCS)),
110
111CPDF_MeshStream::~CPDF_MeshStream() = default;
112
114 m_pStream->LoadAllDataFiltered();
115 m_BitStream = std::make_unique<CFX_BitStream>(m_pStream->GetSpan());
116
117 RetainPtr<const CPDF_Dictionary> pDict = m_pShadingStream->GetDict();
118 m_nCoordBits = pDict->GetIntegerFor("BitsPerCoordinate");
119 m_nComponentBits = pDict->GetIntegerFor("BitsPerComponent");
120 if (ShouldCheckBPC(m_type)) {
121 if (!IsValidBitsPerCoordinate(m_nCoordBits))
122 return false;
123 if (!IsValidBitsPerComponent(m_nComponentBits))
124 return false;
125 }
126
127 m_nFlagBits = pDict->GetIntegerFor("BitsPerFlag");
128 if (ShouldCheckBitsPerFlag(m_type) && !IsValidBitsPerFlag(m_nFlagBits))
129 return false;
130
131 uint32_t nComponents = m_pCS->CountComponents();
132 if (nComponents > kMaxComponents)
133 return false;
134
135 m_nComponents = m_funcs.empty() ? nComponents : 1;
136 RetainPtr<const CPDF_Array> pDecode = pDict->GetArrayFor("Decode");
137 if (!pDecode || pDecode->size() != 4 + m_nComponents * 2)
138 return false;
139
140 m_xmin = pDecode->GetFloatAt(0);
141 m_xmax = pDecode->GetFloatAt(1);
142 m_ymin = pDecode->GetFloatAt(2);
143 m_ymax = pDecode->GetFloatAt(3);
144 for (uint32_t i = 0; i < m_nComponents; ++i) {
145 m_ColorMin[i] = pDecode->GetFloatAt(i * 2 + 4);
146 m_ColorMax[i] = pDecode->GetFloatAt(i * 2 + 5);
147 }
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
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
203std::tuple<float, float, float> CPDF_MeshStream::ReadColor() {
204 DCHECK(ShouldCheckBPC(m_type));
205
206 float color_value[kMaxComponents];
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
213 float r = 0.0;
214 float g = 0.0;
215 float b = 0.0;
216 if (m_funcs.empty()) {
217 m_pCS->GetRGB(color_value, &r, &g, &b);
218 return std::tuple<float, float, float>(r, g, b);
219 }
220
221 float result[kMaxComponents] = {};
222 for (const auto& func : m_funcs) {
223 if (func && func->CountOutputs() <= kMaxComponents)
224 func->Call(pdfium::make_span(color_value, 1u), result);
225 }
226
227 m_pCS->GetRGB(result, &r, &g, &b);
228 return std::tuple<float, float, float>(r, g, b);
229}
230
231bool CPDF_MeshStream::ReadVertex(const CFX_Matrix& pObject2Bitmap,
232 CPDF_MeshVertex* vertex,
233 uint32_t* flag) {
234 if (!CanReadFlag())
235 return false;
236 *flag = ReadFlag();
237
238 if (!CanReadCoords())
239 return false;
240 vertex->position = pObject2Bitmap.Transform(ReadCoords());
241
242 if (!CanReadColor())
243 return false;
244 std::tie(vertex->r, vertex->g, vertex->b) = ReadColor();
245 m_BitStream->ByteAlign();
246 return true;
247}
248
250 const CFX_Matrix& pObject2Bitmap,
251 int count) {
252 std::vector<CPDF_MeshVertex> vertices;
253 for (int i = 0; i < count; ++i) {
254 if (m_BitStream->IsEOF() || !CanReadCoords())
255 return std::vector<CPDF_MeshVertex>();
256
257 vertices.emplace_back();
258 CPDF_MeshVertex& vertex = vertices.back();
259 vertex.position = pObject2Bitmap.Transform(ReadCoords());
260 if (!CanReadColor())
261 return std::vector<CPDF_MeshVertex>();
262
263 std::tie(vertex.r, vertex.g, vertex.b) = ReadColor();
264 m_BitStream->ByteAlign();
265 }
266 return vertices;
267}
CFX_PointF ReadCoords()
bool CanReadCoords() const
bool CanReadFlag() const
bool ReadVertex(const CFX_Matrix &pObject2Bitmap, CPDF_MeshVertex *vertex, uint32_t *flag)
void SkipBits(uint32_t nbits)
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)
std::tuple< float, float, float > ReadColor()
CPDF_MeshVertex(const CPDF_MeshVertex &)
@ kCoonsPatchMeshShading
@ kTensorProductPatchMeshShading
@ kLatticeFormGouraudTriangleMeshShading
@ kFreeFormGouraudTriangleMeshShading