OLD | NEW |
| (Empty) |
1 // Copyright 2014 PDFium Authors. All rights reserved. | |
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/src/fpdfapi/fpdf_page/pageint.h" | |
8 | |
9 #include <vector> | |
10 | |
11 #include "core/include/fpdfapi/cpdf_array.h" | |
12 #include "core/include/fpdfapi/cpdf_dictionary.h" | |
13 #include "core/include/fpdfapi/cpdf_document.h" | |
14 #include "core/include/fpdfapi/cpdf_name.h" | |
15 #include "core/include/fpdfapi/cpdf_number.h" | |
16 #include "core/include/fpdfapi/cpdf_reference.h" | |
17 #include "core/include/fpdfapi/fpdf_module.h" | |
18 #include "core/include/fpdfapi/fpdf_page.h" | |
19 #include "core/include/fpdfapi/fpdf_parser_decode.h" | |
20 #include "core/include/fpdfapi/fpdf_serial.h" | |
21 | |
22 namespace { | |
23 | |
24 const char kPathOperatorSubpath = 'm'; | |
25 const char kPathOperatorLine = 'l'; | |
26 const char kPathOperatorCubicBezier1 = 'c'; | |
27 const char kPathOperatorCubicBezier2 = 'v'; | |
28 const char kPathOperatorCubicBezier3 = 'y'; | |
29 const char kPathOperatorClosePath = 'h'; | |
30 const char kPathOperatorRectangle[] = "re"; | |
31 | |
32 struct _FX_BSTR { | |
33 const FX_CHAR* m_Ptr; | |
34 int m_Size; | |
35 }; | |
36 #define _FX_BSTRC(str) \ | |
37 { str, sizeof(str) - 1 } | |
38 | |
39 struct PDF_AbbrPairs { | |
40 _FX_BSTR full_name; | |
41 _FX_BSTR abbr; | |
42 }; | |
43 | |
44 const PDF_AbbrPairs PDF_InlineKeyAbbr[] = { | |
45 {_FX_BSTRC("BitsPerComponent"), _FX_BSTRC("BPC")}, | |
46 {_FX_BSTRC("ColorSpace"), _FX_BSTRC("CS")}, | |
47 {_FX_BSTRC("Decode"), _FX_BSTRC("D")}, | |
48 {_FX_BSTRC("DecodeParms"), _FX_BSTRC("DP")}, | |
49 {_FX_BSTRC("Filter"), _FX_BSTRC("F")}, | |
50 {_FX_BSTRC("Height"), _FX_BSTRC("H")}, | |
51 {_FX_BSTRC("ImageMask"), _FX_BSTRC("IM")}, | |
52 {_FX_BSTRC("Interpolate"), _FX_BSTRC("I")}, | |
53 {_FX_BSTRC("Width"), _FX_BSTRC("W")}, | |
54 }; | |
55 | |
56 const PDF_AbbrPairs PDF_InlineValueAbbr[] = { | |
57 {_FX_BSTRC("DeviceGray"), _FX_BSTRC("G")}, | |
58 {_FX_BSTRC("DeviceRGB"), _FX_BSTRC("RGB")}, | |
59 {_FX_BSTRC("DeviceCMYK"), _FX_BSTRC("CMYK")}, | |
60 {_FX_BSTRC("Indexed"), _FX_BSTRC("I")}, | |
61 {_FX_BSTRC("ASCIIHexDecode"), _FX_BSTRC("AHx")}, | |
62 {_FX_BSTRC("ASCII85Decode"), _FX_BSTRC("A85")}, | |
63 {_FX_BSTRC("LZWDecode"), _FX_BSTRC("LZW")}, | |
64 {_FX_BSTRC("FlateDecode"), _FX_BSTRC("Fl")}, | |
65 {_FX_BSTRC("RunLengthDecode"), _FX_BSTRC("RL")}, | |
66 {_FX_BSTRC("CCITTFaxDecode"), _FX_BSTRC("CCF")}, | |
67 {_FX_BSTRC("DCTDecode"), _FX_BSTRC("DCT")}, | |
68 }; | |
69 | |
70 struct AbbrReplacementOp { | |
71 bool is_replace_key; | |
72 CFX_ByteString key; | |
73 CFX_ByteStringC replacement; | |
74 }; | |
75 | |
76 class CPDF_StreamParserAutoClearer { | |
77 public: | |
78 CPDF_StreamParserAutoClearer(CPDF_StreamParser** scoped_variable, | |
79 CPDF_StreamParser* new_parser) | |
80 : scoped_variable_(scoped_variable) { | |
81 *scoped_variable_ = new_parser; | |
82 } | |
83 ~CPDF_StreamParserAutoClearer() { *scoped_variable_ = NULL; } | |
84 | |
85 private: | |
86 CPDF_StreamParser** scoped_variable_; | |
87 }; | |
88 | |
89 CFX_ByteStringC PDF_FindFullName(const PDF_AbbrPairs* table, | |
90 size_t count, | |
91 const CFX_ByteStringC& abbr) { | |
92 for (size_t i = 0; i < count; ++i) { | |
93 if (abbr.GetLength() != table[i].abbr.m_Size) | |
94 continue; | |
95 if (memcmp(abbr.GetPtr(), table[i].abbr.m_Ptr, abbr.GetLength())) | |
96 continue; | |
97 return CFX_ByteStringC(table[i].full_name.m_Ptr, table[i].full_name.m_Size); | |
98 } | |
99 return CFX_ByteStringC(); | |
100 } | |
101 | |
102 } // namespace | |
103 | |
104 bool IsPathOperator(const uint8_t* buf, size_t len) { | |
105 if (len == 1) { | |
106 uint8_t op = buf[0]; | |
107 if (op == kPathOperatorSubpath || op == kPathOperatorLine || | |
108 op == kPathOperatorCubicBezier1 || op == kPathOperatorCubicBezier2 || | |
109 op == kPathOperatorCubicBezier3) { | |
110 return true; | |
111 } | |
112 } else if (len == 2) { | |
113 if (buf[0] == kPathOperatorRectangle[0] && | |
114 buf[1] == kPathOperatorRectangle[1]) { | |
115 return true; | |
116 } | |
117 } | |
118 return false; | |
119 } | |
120 | |
121 CPDF_StreamContentParser::CPDF_StreamContentParser( | |
122 CPDF_Document* pDocument, | |
123 CPDF_Dictionary* pPageResources, | |
124 CPDF_Dictionary* pParentResources, | |
125 CFX_Matrix* pmtContentToUser, | |
126 CPDF_PageObjectHolder* pObjHolder, | |
127 CPDF_Dictionary* pResources, | |
128 CFX_FloatRect* pBBox, | |
129 CPDF_ParseOptions* pOptions, | |
130 CPDF_AllStates* pStates, | |
131 int level) | |
132 : m_pDocument(pDocument), | |
133 m_pPageResources(pPageResources), | |
134 m_pParentResources(pParentResources), | |
135 m_pResources(pResources), | |
136 m_pObjectHolder(pObjHolder), | |
137 m_Level(level), | |
138 m_ParamStartPos(0), | |
139 m_ParamCount(0), | |
140 m_pCurStates(new CPDF_AllStates), | |
141 m_pLastTextObject(nullptr), | |
142 m_DefFontSize(0), | |
143 m_pPathPoints(nullptr), | |
144 m_PathPointCount(0), | |
145 m_PathAllocSize(0), | |
146 m_PathCurrentX(0.0f), | |
147 m_PathCurrentY(0.0f), | |
148 m_PathClipType(0), | |
149 m_pLastImage(nullptr), | |
150 m_pLastImageDict(nullptr), | |
151 m_pLastCloneImageDict(nullptr), | |
152 m_bReleaseLastDict(TRUE), | |
153 m_bColored(FALSE), | |
154 m_bResourceMissing(FALSE) { | |
155 if (pmtContentToUser) { | |
156 m_mtContentToUser = *pmtContentToUser; | |
157 } | |
158 if (pOptions) { | |
159 m_Options = *pOptions; | |
160 } | |
161 if (!m_pResources) { | |
162 m_pResources = m_pParentResources; | |
163 } | |
164 if (!m_pResources) { | |
165 m_pResources = m_pPageResources; | |
166 } | |
167 if (pBBox) { | |
168 m_BBox = *pBBox; | |
169 } | |
170 if (pStates) { | |
171 m_pCurStates->Copy(*pStates); | |
172 } else { | |
173 m_pCurStates->m_GeneralState.New(); | |
174 m_pCurStates->m_GraphState.New(); | |
175 m_pCurStates->m_TextState.New(); | |
176 m_pCurStates->m_ColorState.New(); | |
177 } | |
178 for (size_t i = 0; i < FX_ArraySize(m_Type3Data); ++i) { | |
179 m_Type3Data[i] = 0.0; | |
180 } | |
181 } | |
182 | |
183 CPDF_StreamContentParser::~CPDF_StreamContentParser() { | |
184 ClearAllParams(); | |
185 FX_Free(m_pPathPoints); | |
186 if (m_pLastImageDict) { | |
187 m_pLastImageDict->Release(); | |
188 } | |
189 if (m_pLastCloneImageDict) { | |
190 m_pLastCloneImageDict->Release(); | |
191 } | |
192 } | |
193 | |
194 int CPDF_StreamContentParser::GetNextParamPos() { | |
195 if (m_ParamCount == PARAM_BUF_SIZE) { | |
196 m_ParamStartPos++; | |
197 if (m_ParamStartPos == PARAM_BUF_SIZE) { | |
198 m_ParamStartPos = 0; | |
199 } | |
200 if (m_ParamBuf[m_ParamStartPos].m_Type == 0) { | |
201 if (CPDF_Object* pObject = m_ParamBuf[m_ParamStartPos].m_pObject) | |
202 pObject->Release(); | |
203 } | |
204 return m_ParamStartPos; | |
205 } | |
206 int index = m_ParamStartPos + m_ParamCount; | |
207 if (index >= PARAM_BUF_SIZE) { | |
208 index -= PARAM_BUF_SIZE; | |
209 } | |
210 m_ParamCount++; | |
211 return index; | |
212 } | |
213 | |
214 void CPDF_StreamContentParser::AddNameParam(const FX_CHAR* name, int len) { | |
215 int index = GetNextParamPos(); | |
216 if (len > 32) { | |
217 m_ParamBuf[index].m_Type = ContentParam::OBJECT; | |
218 m_ParamBuf[index].m_pObject = | |
219 new CPDF_Name(PDF_NameDecode(CFX_ByteStringC(name, len))); | |
220 } else { | |
221 m_ParamBuf[index].m_Type = ContentParam::NAME; | |
222 if (!FXSYS_memchr(name, '#', len)) { | |
223 FXSYS_memcpy(m_ParamBuf[index].m_Name.m_Buffer, name, len); | |
224 m_ParamBuf[index].m_Name.m_Len = len; | |
225 } else { | |
226 CFX_ByteString str = PDF_NameDecode(CFX_ByteStringC(name, len)); | |
227 FXSYS_memcpy(m_ParamBuf[index].m_Name.m_Buffer, str.c_str(), | |
228 str.GetLength()); | |
229 m_ParamBuf[index].m_Name.m_Len = str.GetLength(); | |
230 } | |
231 } | |
232 } | |
233 | |
234 void CPDF_StreamContentParser::AddNumberParam(const FX_CHAR* str, int len) { | |
235 int index = GetNextParamPos(); | |
236 m_ParamBuf[index].m_Type = ContentParam::NUMBER; | |
237 FX_atonum(CFX_ByteStringC(str, len), m_ParamBuf[index].m_Number.m_bInteger, | |
238 &m_ParamBuf[index].m_Number.m_Integer); | |
239 } | |
240 void CPDF_StreamContentParser::AddObjectParam(CPDF_Object* pObj) { | |
241 int index = GetNextParamPos(); | |
242 m_ParamBuf[index].m_Type = ContentParam::OBJECT; | |
243 m_ParamBuf[index].m_pObject = pObj; | |
244 } | |
245 void CPDF_StreamContentParser::ClearAllParams() { | |
246 FX_DWORD index = m_ParamStartPos; | |
247 for (FX_DWORD i = 0; i < m_ParamCount; i++) { | |
248 if (m_ParamBuf[index].m_Type == 0) { | |
249 if (CPDF_Object* pObject = m_ParamBuf[index].m_pObject) | |
250 pObject->Release(); | |
251 } | |
252 index++; | |
253 if (index == PARAM_BUF_SIZE) { | |
254 index = 0; | |
255 } | |
256 } | |
257 m_ParamStartPos = 0; | |
258 m_ParamCount = 0; | |
259 } | |
260 | |
261 CPDF_Object* CPDF_StreamContentParser::GetObject(FX_DWORD index) { | |
262 if (index >= m_ParamCount) { | |
263 return NULL; | |
264 } | |
265 int real_index = m_ParamStartPos + m_ParamCount - index - 1; | |
266 if (real_index >= PARAM_BUF_SIZE) { | |
267 real_index -= PARAM_BUF_SIZE; | |
268 } | |
269 ContentParam& param = m_ParamBuf[real_index]; | |
270 if (param.m_Type == ContentParam::NUMBER) { | |
271 CPDF_Number* pNumber = param.m_Number.m_bInteger | |
272 ? new CPDF_Number(param.m_Number.m_Integer) | |
273 : new CPDF_Number(param.m_Number.m_Float); | |
274 | |
275 param.m_Type = ContentParam::OBJECT; | |
276 param.m_pObject = pNumber; | |
277 return pNumber; | |
278 } | |
279 if (param.m_Type == ContentParam::NAME) { | |
280 CPDF_Name* pName = new CPDF_Name( | |
281 CFX_ByteString(param.m_Name.m_Buffer, param.m_Name.m_Len)); | |
282 param.m_Type = ContentParam::OBJECT; | |
283 param.m_pObject = pName; | |
284 return pName; | |
285 } | |
286 if (param.m_Type == ContentParam::OBJECT) { | |
287 return param.m_pObject; | |
288 } | |
289 ASSERT(FALSE); | |
290 return NULL; | |
291 } | |
292 | |
293 CFX_ByteString CPDF_StreamContentParser::GetString(FX_DWORD index) { | |
294 if (index >= m_ParamCount) { | |
295 return CFX_ByteString(); | |
296 } | |
297 int real_index = m_ParamStartPos + m_ParamCount - index - 1; | |
298 if (real_index >= PARAM_BUF_SIZE) { | |
299 real_index -= PARAM_BUF_SIZE; | |
300 } | |
301 ContentParam& param = m_ParamBuf[real_index]; | |
302 if (param.m_Type == ContentParam::NAME) { | |
303 return CFX_ByteString(param.m_Name.m_Buffer, param.m_Name.m_Len); | |
304 } | |
305 if (param.m_Type == 0 && param.m_pObject) { | |
306 return param.m_pObject->GetString(); | |
307 } | |
308 return CFX_ByteString(); | |
309 } | |
310 | |
311 FX_FLOAT CPDF_StreamContentParser::GetNumber(FX_DWORD index) { | |
312 if (index >= m_ParamCount) { | |
313 return 0; | |
314 } | |
315 int real_index = m_ParamStartPos + m_ParamCount - index - 1; | |
316 if (real_index >= PARAM_BUF_SIZE) { | |
317 real_index -= PARAM_BUF_SIZE; | |
318 } | |
319 ContentParam& param = m_ParamBuf[real_index]; | |
320 if (param.m_Type == ContentParam::NUMBER) { | |
321 return param.m_Number.m_bInteger ? (FX_FLOAT)param.m_Number.m_Integer | |
322 : param.m_Number.m_Float; | |
323 } | |
324 if (param.m_Type == 0 && param.m_pObject) { | |
325 return param.m_pObject->GetNumber(); | |
326 } | |
327 return 0; | |
328 } | |
329 | |
330 FX_FLOAT CPDF_StreamContentParser::GetNumber16(FX_DWORD index) { | |
331 return GetNumber(index); | |
332 } | |
333 | |
334 void CPDF_StreamContentParser::SetGraphicStates(CPDF_PageObject* pObj, | |
335 FX_BOOL bColor, | |
336 FX_BOOL bText, | |
337 FX_BOOL bGraph) { | |
338 pObj->m_GeneralState = m_pCurStates->m_GeneralState; | |
339 pObj->m_ClipPath = m_pCurStates->m_ClipPath; | |
340 pObj->m_ContentMark = m_CurContentMark; | |
341 if (bColor) { | |
342 pObj->m_ColorState = m_pCurStates->m_ColorState; | |
343 } | |
344 if (bGraph) { | |
345 pObj->m_GraphState = m_pCurStates->m_GraphState; | |
346 } | |
347 if (bText) { | |
348 pObj->m_TextState = m_pCurStates->m_TextState; | |
349 } | |
350 } | |
351 | |
352 // static | |
353 CPDF_StreamContentParser::OpCodes | |
354 CPDF_StreamContentParser::InitializeOpCodes() { | |
355 return OpCodes({ | |
356 {FXBSTR_ID('"', 0, 0, 0), | |
357 &CPDF_StreamContentParser::Handle_NextLineShowText_Space}, | |
358 {FXBSTR_ID('\'', 0, 0, 0), | |
359 &CPDF_StreamContentParser::Handle_NextLineShowText}, | |
360 {FXBSTR_ID('B', 0, 0, 0), | |
361 &CPDF_StreamContentParser::Handle_FillStrokePath}, | |
362 {FXBSTR_ID('B', '*', 0, 0), | |
363 &CPDF_StreamContentParser::Handle_EOFillStrokePath}, | |
364 {FXBSTR_ID('B', 'D', 'C', 0), | |
365 &CPDF_StreamContentParser::Handle_BeginMarkedContent_Dictionary}, | |
366 {FXBSTR_ID('B', 'I', 0, 0), &CPDF_StreamContentParser::Handle_BeginImage}, | |
367 {FXBSTR_ID('B', 'M', 'C', 0), | |
368 &CPDF_StreamContentParser::Handle_BeginMarkedContent}, | |
369 {FXBSTR_ID('B', 'T', 0, 0), &CPDF_StreamContentParser::Handle_BeginText}, | |
370 {FXBSTR_ID('C', 'S', 0, 0), | |
371 &CPDF_StreamContentParser::Handle_SetColorSpace_Stroke}, | |
372 {FXBSTR_ID('D', 'P', 0, 0), | |
373 &CPDF_StreamContentParser::Handle_MarkPlace_Dictionary}, | |
374 {FXBSTR_ID('D', 'o', 0, 0), | |
375 &CPDF_StreamContentParser::Handle_ExecuteXObject}, | |
376 {FXBSTR_ID('E', 'I', 0, 0), &CPDF_StreamContentParser::Handle_EndImage}, | |
377 {FXBSTR_ID('E', 'M', 'C', 0), | |
378 &CPDF_StreamContentParser::Handle_EndMarkedContent}, | |
379 {FXBSTR_ID('E', 'T', 0, 0), &CPDF_StreamContentParser::Handle_EndText}, | |
380 {FXBSTR_ID('F', 0, 0, 0), &CPDF_StreamContentParser::Handle_FillPathOld}, | |
381 {FXBSTR_ID('G', 0, 0, 0), | |
382 &CPDF_StreamContentParser::Handle_SetGray_Stroke}, | |
383 {FXBSTR_ID('I', 'D', 0, 0), | |
384 &CPDF_StreamContentParser::Handle_BeginImageData}, | |
385 {FXBSTR_ID('J', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetLineCap}, | |
386 {FXBSTR_ID('K', 0, 0, 0), | |
387 &CPDF_StreamContentParser::Handle_SetCMYKColor_Stroke}, | |
388 {FXBSTR_ID('M', 0, 0, 0), | |
389 &CPDF_StreamContentParser::Handle_SetMiterLimit}, | |
390 {FXBSTR_ID('M', 'P', 0, 0), &CPDF_StreamContentParser::Handle_MarkPlace}, | |
391 {FXBSTR_ID('Q', 0, 0, 0), | |
392 &CPDF_StreamContentParser::Handle_RestoreGraphState}, | |
393 {FXBSTR_ID('R', 'G', 0, 0), | |
394 &CPDF_StreamContentParser::Handle_SetRGBColor_Stroke}, | |
395 {FXBSTR_ID('S', 0, 0, 0), &CPDF_StreamContentParser::Handle_StrokePath}, | |
396 {FXBSTR_ID('S', 'C', 0, 0), | |
397 &CPDF_StreamContentParser::Handle_SetColor_Stroke}, | |
398 {FXBSTR_ID('S', 'C', 'N', 0), | |
399 &CPDF_StreamContentParser::Handle_SetColorPS_Stroke}, | |
400 {FXBSTR_ID('T', '*', 0, 0), | |
401 &CPDF_StreamContentParser::Handle_MoveToNextLine}, | |
402 {FXBSTR_ID('T', 'D', 0, 0), | |
403 &CPDF_StreamContentParser::Handle_MoveTextPoint_SetLeading}, | |
404 {FXBSTR_ID('T', 'J', 0, 0), | |
405 &CPDF_StreamContentParser::Handle_ShowText_Positioning}, | |
406 {FXBSTR_ID('T', 'L', 0, 0), | |
407 &CPDF_StreamContentParser::Handle_SetTextLeading}, | |
408 {FXBSTR_ID('T', 'c', 0, 0), | |
409 &CPDF_StreamContentParser::Handle_SetCharSpace}, | |
410 {FXBSTR_ID('T', 'd', 0, 0), | |
411 &CPDF_StreamContentParser::Handle_MoveTextPoint}, | |
412 {FXBSTR_ID('T', 'f', 0, 0), &CPDF_StreamContentParser::Handle_SetFont}, | |
413 {FXBSTR_ID('T', 'j', 0, 0), &CPDF_StreamContentParser::Handle_ShowText}, | |
414 {FXBSTR_ID('T', 'm', 0, 0), | |
415 &CPDF_StreamContentParser::Handle_SetTextMatrix}, | |
416 {FXBSTR_ID('T', 'r', 0, 0), | |
417 &CPDF_StreamContentParser::Handle_SetTextRenderMode}, | |
418 {FXBSTR_ID('T', 's', 0, 0), | |
419 &CPDF_StreamContentParser::Handle_SetTextRise}, | |
420 {FXBSTR_ID('T', 'w', 0, 0), | |
421 &CPDF_StreamContentParser::Handle_SetWordSpace}, | |
422 {FXBSTR_ID('T', 'z', 0, 0), | |
423 &CPDF_StreamContentParser::Handle_SetHorzScale}, | |
424 {FXBSTR_ID('W', 0, 0, 0), &CPDF_StreamContentParser::Handle_Clip}, | |
425 {FXBSTR_ID('W', '*', 0, 0), &CPDF_StreamContentParser::Handle_EOClip}, | |
426 {FXBSTR_ID('b', 0, 0, 0), | |
427 &CPDF_StreamContentParser::Handle_CloseFillStrokePath}, | |
428 {FXBSTR_ID('b', '*', 0, 0), | |
429 &CPDF_StreamContentParser::Handle_CloseEOFillStrokePath}, | |
430 {FXBSTR_ID('c', 0, 0, 0), &CPDF_StreamContentParser::Handle_CurveTo_123}, | |
431 {FXBSTR_ID('c', 'm', 0, 0), | |
432 &CPDF_StreamContentParser::Handle_ConcatMatrix}, | |
433 {FXBSTR_ID('c', 's', 0, 0), | |
434 &CPDF_StreamContentParser::Handle_SetColorSpace_Fill}, | |
435 {FXBSTR_ID('d', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetDash}, | |
436 {FXBSTR_ID('d', '0', 0, 0), | |
437 &CPDF_StreamContentParser::Handle_SetCharWidth}, | |
438 {FXBSTR_ID('d', '1', 0, 0), | |
439 &CPDF_StreamContentParser::Handle_SetCachedDevice}, | |
440 {FXBSTR_ID('f', 0, 0, 0), &CPDF_StreamContentParser::Handle_FillPath}, | |
441 {FXBSTR_ID('f', '*', 0, 0), &CPDF_StreamContentParser::Handle_EOFillPath}, | |
442 {FXBSTR_ID('g', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetGray_Fill}, | |
443 {FXBSTR_ID('g', 's', 0, 0), | |
444 &CPDF_StreamContentParser::Handle_SetExtendGraphState}, | |
445 {FXBSTR_ID('h', 0, 0, 0), &CPDF_StreamContentParser::Handle_ClosePath}, | |
446 {FXBSTR_ID('i', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetFlat}, | |
447 {FXBSTR_ID('j', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetLineJoin}, | |
448 {FXBSTR_ID('k', 0, 0, 0), | |
449 &CPDF_StreamContentParser::Handle_SetCMYKColor_Fill}, | |
450 {FXBSTR_ID('l', 0, 0, 0), &CPDF_StreamContentParser::Handle_LineTo}, | |
451 {FXBSTR_ID('m', 0, 0, 0), &CPDF_StreamContentParser::Handle_MoveTo}, | |
452 {FXBSTR_ID('n', 0, 0, 0), &CPDF_StreamContentParser::Handle_EndPath}, | |
453 {FXBSTR_ID('q', 0, 0, 0), | |
454 &CPDF_StreamContentParser::Handle_SaveGraphState}, | |
455 {FXBSTR_ID('r', 'e', 0, 0), &CPDF_StreamContentParser::Handle_Rectangle}, | |
456 {FXBSTR_ID('r', 'g', 0, 0), | |
457 &CPDF_StreamContentParser::Handle_SetRGBColor_Fill}, | |
458 {FXBSTR_ID('r', 'i', 0, 0), | |
459 &CPDF_StreamContentParser::Handle_SetRenderIntent}, | |
460 {FXBSTR_ID('s', 0, 0, 0), | |
461 &CPDF_StreamContentParser::Handle_CloseStrokePath}, | |
462 {FXBSTR_ID('s', 'c', 0, 0), | |
463 &CPDF_StreamContentParser::Handle_SetColor_Fill}, | |
464 {FXBSTR_ID('s', 'c', 'n', 0), | |
465 &CPDF_StreamContentParser::Handle_SetColorPS_Fill}, | |
466 {FXBSTR_ID('s', 'h', 0, 0), &CPDF_StreamContentParser::Handle_ShadeFill}, | |
467 {FXBSTR_ID('v', 0, 0, 0), &CPDF_StreamContentParser::Handle_CurveTo_23}, | |
468 {FXBSTR_ID('w', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetLineWidth}, | |
469 {FXBSTR_ID('y', 0, 0, 0), &CPDF_StreamContentParser::Handle_CurveTo_13}, | |
470 }); | |
471 } | |
472 | |
473 void CPDF_StreamContentParser::OnOperator(const FX_CHAR* op) { | |
474 int i = 0; | |
475 FX_DWORD opid = 0; | |
476 while (i < 4 && op[i]) { | |
477 opid = (opid << 8) + op[i]; | |
478 i++; | |
479 } | |
480 while (i < 4) { | |
481 opid <<= 8; | |
482 i++; | |
483 } | |
484 | |
485 static const OpCodes s_OpCodes = InitializeOpCodes(); | |
486 | |
487 auto it = s_OpCodes.find(opid); | |
488 if (it != s_OpCodes.end()) | |
489 (this->*it->second)(); | |
490 } | |
491 | |
492 void CPDF_StreamContentParser::Handle_CloseFillStrokePath() { | |
493 if (m_Options.m_bTextOnly) { | |
494 return; | |
495 } | |
496 Handle_ClosePath(); | |
497 AddPathObject(FXFILL_WINDING, TRUE); | |
498 } | |
499 | |
500 void CPDF_StreamContentParser::Handle_FillStrokePath() { | |
501 if (m_Options.m_bTextOnly) { | |
502 return; | |
503 } | |
504 AddPathObject(FXFILL_WINDING, TRUE); | |
505 } | |
506 | |
507 void CPDF_StreamContentParser::Handle_CloseEOFillStrokePath() { | |
508 if (m_Options.m_bTextOnly) { | |
509 return; | |
510 } | |
511 AddPathPoint(m_PathStartX, m_PathStartY, FXPT_LINETO | FXPT_CLOSEFIGURE); | |
512 AddPathObject(FXFILL_ALTERNATE, TRUE); | |
513 } | |
514 | |
515 void CPDF_StreamContentParser::Handle_EOFillStrokePath() { | |
516 if (m_Options.m_bTextOnly) { | |
517 return; | |
518 } | |
519 AddPathObject(FXFILL_ALTERNATE, TRUE); | |
520 } | |
521 | |
522 void CPDF_StreamContentParser::Handle_BeginMarkedContent_Dictionary() { | |
523 if (!m_Options.m_bMarkedContent) { | |
524 return; | |
525 } | |
526 CFX_ByteString tag = GetString(1); | |
527 CPDF_Object* pProperty = GetObject(0); | |
528 if (!pProperty) { | |
529 return; | |
530 } | |
531 FX_BOOL bDirect = TRUE; | |
532 if (pProperty->IsName()) { | |
533 pProperty = FindResourceObj("Properties", pProperty->GetString()); | |
534 if (!pProperty) | |
535 return; | |
536 bDirect = FALSE; | |
537 } | |
538 if (CPDF_Dictionary* pDict = pProperty->AsDictionary()) { | |
539 m_CurContentMark.GetModify()->AddMark(tag, pDict, bDirect); | |
540 } | |
541 } | |
542 | |
543 void CPDF_StreamContentParser::Handle_BeginImage() { | |
544 FX_FILESIZE savePos = m_pSyntax->GetPos(); | |
545 CPDF_Dictionary* pDict = new CPDF_Dictionary; | |
546 while (1) { | |
547 CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement(); | |
548 if (type == CPDF_StreamParser::Keyword) { | |
549 CFX_ByteString bsKeyword(m_pSyntax->GetWordBuf(), | |
550 m_pSyntax->GetWordSize()); | |
551 if (bsKeyword != "ID") { | |
552 m_pSyntax->SetPos(savePos); | |
553 pDict->Release(); | |
554 return; | |
555 } | |
556 } | |
557 if (type != CPDF_StreamParser::Name) { | |
558 break; | |
559 } | |
560 CFX_ByteString key((const FX_CHAR*)m_pSyntax->GetWordBuf() + 1, | |
561 m_pSyntax->GetWordSize() - 1); | |
562 std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>> pObj( | |
563 m_pSyntax->ReadNextObject()); | |
564 if (!key.IsEmpty()) { | |
565 FX_DWORD dwObjNum = pObj ? pObj->GetObjNum() : 0; | |
566 if (dwObjNum) | |
567 pDict->SetAtReference(key, m_pDocument, dwObjNum); | |
568 else | |
569 pDict->SetAt(key, pObj.release()); | |
570 } | |
571 } | |
572 PDF_ReplaceAbbr(pDict); | |
573 CPDF_Object* pCSObj = NULL; | |
574 if (pDict->KeyExist("ColorSpace")) { | |
575 pCSObj = pDict->GetElementValue("ColorSpace"); | |
576 if (pCSObj->IsName()) { | |
577 CFX_ByteString name = pCSObj->GetString(); | |
578 if (name != "DeviceRGB" && name != "DeviceGray" && name != "DeviceCMYK") { | |
579 pCSObj = FindResourceObj("ColorSpace", name); | |
580 if (pCSObj && !pCSObj->GetObjNum()) { | |
581 pCSObj = pCSObj->Clone(); | |
582 pDict->SetAt("ColorSpace", pCSObj); | |
583 } | |
584 } | |
585 } | |
586 } | |
587 CPDF_Stream* pStream = m_pSyntax->ReadInlineStream( | |
588 m_pDocument, pDict, pCSObj, m_Options.m_bDecodeInlineImage); | |
589 while (1) { | |
590 CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement(); | |
591 if (type == CPDF_StreamParser::EndOfData) { | |
592 break; | |
593 } | |
594 if (type != CPDF_StreamParser::Keyword) { | |
595 continue; | |
596 } | |
597 if (m_pSyntax->GetWordSize() == 2 && m_pSyntax->GetWordBuf()[0] == 'E' && | |
598 m_pSyntax->GetWordBuf()[1] == 'I') { | |
599 break; | |
600 } | |
601 } | |
602 if (m_Options.m_bTextOnly) { | |
603 if (pStream) { | |
604 pStream->Release(); | |
605 } else { | |
606 pDict->Release(); | |
607 } | |
608 return; | |
609 } | |
610 pDict->SetAtName("Subtype", "Image"); | |
611 CPDF_ImageObject* pImgObj = AddImage(pStream, NULL, TRUE); | |
612 if (!pImgObj) { | |
613 if (pStream) { | |
614 pStream->Release(); | |
615 } else { | |
616 pDict->Release(); | |
617 } | |
618 } | |
619 } | |
620 | |
621 void CPDF_StreamContentParser::Handle_BeginMarkedContent() { | |
622 if (!m_Options.m_bMarkedContent) { | |
623 return; | |
624 } | |
625 CFX_ByteString tag = GetString(0); | |
626 m_CurContentMark.GetModify()->AddMark(tag, NULL, FALSE); | |
627 } | |
628 | |
629 void CPDF_StreamContentParser::Handle_BeginText() { | |
630 m_pCurStates->m_TextMatrix.Set(1.0f, 0, 0, 1.0f, 0, 0); | |
631 OnChangeTextMatrix(); | |
632 m_pCurStates->m_TextX = 0; | |
633 m_pCurStates->m_TextY = 0; | |
634 m_pCurStates->m_TextLineX = 0; | |
635 m_pCurStates->m_TextLineY = 0; | |
636 } | |
637 | |
638 void CPDF_StreamContentParser::Handle_CurveTo_123() { | |
639 if (m_Options.m_bTextOnly) { | |
640 return; | |
641 } | |
642 AddPathPoint(GetNumber(5), GetNumber(4), FXPT_BEZIERTO); | |
643 AddPathPoint(GetNumber(3), GetNumber(2), FXPT_BEZIERTO); | |
644 AddPathPoint(GetNumber(1), GetNumber(0), FXPT_BEZIERTO); | |
645 } | |
646 | |
647 void CPDF_StreamContentParser::Handle_ConcatMatrix() { | |
648 FX_FLOAT a2 = GetNumber16(5), b2 = GetNumber16(4), c2 = GetNumber16(3), | |
649 d2 = GetNumber16(2); | |
650 FX_FLOAT e2 = GetNumber(1), f2 = GetNumber(0); | |
651 CFX_Matrix new_matrix(a2, b2, c2, d2, e2, f2); | |
652 new_matrix.Concat(m_pCurStates->m_CTM); | |
653 m_pCurStates->m_CTM = new_matrix; | |
654 OnChangeTextMatrix(); | |
655 } | |
656 | |
657 void CPDF_StreamContentParser::Handle_SetColorSpace_Fill() { | |
658 if (m_Options.m_bTextOnly) { | |
659 return; | |
660 } | |
661 CFX_ByteString csname = GetString(0); | |
662 CPDF_ColorSpace* pCS = FindColorSpace(csname); | |
663 if (!pCS) { | |
664 return; | |
665 } | |
666 m_pCurStates->m_ColorState.GetModify()->m_FillColor.SetColorSpace(pCS); | |
667 } | |
668 | |
669 void CPDF_StreamContentParser::Handle_SetColorSpace_Stroke() { | |
670 if (m_Options.m_bTextOnly) { | |
671 return; | |
672 } | |
673 CFX_ByteString csname = GetString(0); | |
674 CPDF_ColorSpace* pCS = FindColorSpace(csname); | |
675 if (!pCS) { | |
676 return; | |
677 } | |
678 m_pCurStates->m_ColorState.GetModify()->m_StrokeColor.SetColorSpace(pCS); | |
679 } | |
680 | |
681 void CPDF_StreamContentParser::Handle_SetDash() { | |
682 if (m_Options.m_bTextOnly) { | |
683 return; | |
684 } | |
685 CPDF_Array* pArray = GetObject(1) ? GetObject(1)->GetArray() : NULL; | |
686 if (!pArray) { | |
687 return; | |
688 } | |
689 m_pCurStates->SetLineDash(pArray, GetNumber(0), 1.0f); | |
690 } | |
691 | |
692 void CPDF_StreamContentParser::Handle_SetCharWidth() { | |
693 m_Type3Data[0] = GetNumber(1); | |
694 m_Type3Data[1] = GetNumber(0); | |
695 m_bColored = TRUE; | |
696 } | |
697 | |
698 void CPDF_StreamContentParser::Handle_SetCachedDevice() { | |
699 for (int i = 0; i < 6; i++) { | |
700 m_Type3Data[i] = GetNumber(5 - i); | |
701 } | |
702 m_bColored = FALSE; | |
703 } | |
704 | |
705 void CPDF_StreamContentParser::Handle_ExecuteXObject() { | |
706 CFX_ByteString name = GetString(0); | |
707 if (name == m_LastImageName && m_pLastImage && m_pLastImage->GetStream() && | |
708 m_pLastImage->GetStream()->GetObjNum()) { | |
709 AddImage(nullptr, m_pLastImage, FALSE); | |
710 return; | |
711 } | |
712 | |
713 if (m_Options.m_bTextOnly) { | |
714 if (!m_pResources) | |
715 return; | |
716 | |
717 CPDF_Dictionary* pList = m_pResources->GetDictBy("XObject"); | |
718 if (!pList && m_pPageResources && m_pResources != m_pPageResources) | |
719 pList = m_pPageResources->GetDictBy("XObject"); | |
720 if (!pList) | |
721 return; | |
722 CPDF_Reference* pRes = ToReference(pList->GetElement(name)); | |
723 if (!pRes) | |
724 return; | |
725 | |
726 FX_BOOL bForm; | |
727 if (m_pDocument->IsFormStream(pRes->GetRefObjNum(), bForm) && !bForm) | |
728 return; | |
729 } | |
730 | |
731 CPDF_Stream* pXObject = ToStream(FindResourceObj("XObject", name)); | |
732 if (!pXObject) { | |
733 m_bResourceMissing = TRUE; | |
734 return; | |
735 } | |
736 | |
737 CFX_ByteStringC type = pXObject->GetDict() | |
738 ? pXObject->GetDict()->GetConstStringBy("Subtype") | |
739 : CFX_ByteStringC(); | |
740 if (type == "Image") { | |
741 if (m_Options.m_bTextOnly) { | |
742 return; | |
743 } | |
744 CPDF_ImageObject* pObj = AddImage(pXObject, NULL, FALSE); | |
745 m_LastImageName = name; | |
746 m_pLastImage = pObj->m_pImage; | |
747 if (!m_pObjectHolder->HasImageMask()) | |
748 m_pObjectHolder->SetHasImageMask(m_pLastImage->IsMask()); | |
749 } else if (type == "Form") { | |
750 AddForm(pXObject); | |
751 } else { | |
752 return; | |
753 } | |
754 } | |
755 | |
756 void CPDF_StreamContentParser::AddForm(CPDF_Stream* pStream) { | |
757 if (!m_Options.m_bSeparateForm) { | |
758 CPDF_Dictionary* pResources = pStream->GetDict()->GetDictBy("Resources"); | |
759 CFX_Matrix form_matrix = pStream->GetDict()->GetMatrixBy("Matrix"); | |
760 form_matrix.Concat(m_pCurStates->m_CTM); | |
761 CPDF_Array* pBBox = pStream->GetDict()->GetArrayBy("BBox"); | |
762 CFX_FloatRect form_bbox; | |
763 CPDF_Path ClipPath; | |
764 if (pBBox) { | |
765 form_bbox = pStream->GetDict()->GetRectBy("BBox"); | |
766 ClipPath.New(); | |
767 ClipPath.AppendRect(form_bbox.left, form_bbox.bottom, form_bbox.right, | |
768 form_bbox.top); | |
769 ClipPath.Transform(&form_matrix); | |
770 form_bbox.Transform(&form_matrix); | |
771 } | |
772 CPDF_StreamContentParser parser(m_pDocument, m_pPageResources, m_pResources, | |
773 &m_mtContentToUser, m_pObjectHolder, | |
774 pResources, &form_bbox, &m_Options, | |
775 m_pCurStates.get(), m_Level + 1); | |
776 parser.m_pCurStates->m_CTM = form_matrix; | |
777 if (ClipPath.NotNull()) { | |
778 parser.m_pCurStates->m_ClipPath.AppendPath(ClipPath, FXFILL_WINDING, | |
779 TRUE); | |
780 } | |
781 CPDF_StreamAcc stream; | |
782 stream.LoadAllData(pStream, FALSE); | |
783 if (stream.GetSize() == 0) { | |
784 return; | |
785 } | |
786 parser.Parse(stream.GetData(), stream.GetSize(), 0); | |
787 return; | |
788 } | |
789 std::unique_ptr<CPDF_FormObject> pFormObj(new CPDF_FormObject); | |
790 pFormObj->m_pForm = | |
791 new CPDF_Form(m_pDocument, m_pPageResources, pStream, m_pResources); | |
792 pFormObj->m_FormMatrix = m_pCurStates->m_CTM; | |
793 pFormObj->m_FormMatrix.Concat(m_mtContentToUser); | |
794 CPDF_AllStates status; | |
795 status.m_GeneralState = m_pCurStates->m_GeneralState; | |
796 status.m_GraphState = m_pCurStates->m_GraphState; | |
797 status.m_ColorState = m_pCurStates->m_ColorState; | |
798 status.m_TextState = m_pCurStates->m_TextState; | |
799 pFormObj->m_pForm->ParseContent(&status, NULL, NULL, &m_Options, m_Level + 1); | |
800 if (!m_pObjectHolder->BackgroundAlphaNeeded() && | |
801 pFormObj->m_pForm->BackgroundAlphaNeeded()) { | |
802 m_pObjectHolder->SetBackgroundAlphaNeeded(TRUE); | |
803 } | |
804 pFormObj->CalcBoundingBox(); | |
805 SetGraphicStates(pFormObj.get(), TRUE, TRUE, TRUE); | |
806 m_pObjectHolder->GetPageObjectList()->push_back(std::move(pFormObj)); | |
807 } | |
808 | |
809 CPDF_ImageObject* CPDF_StreamContentParser::AddImage(CPDF_Stream* pStream, | |
810 CPDF_Image* pImage, | |
811 FX_BOOL bInline) { | |
812 if (!pStream && !pImage) { | |
813 return NULL; | |
814 } | |
815 CFX_Matrix ImageMatrix; | |
816 ImageMatrix.Copy(m_pCurStates->m_CTM); | |
817 ImageMatrix.Concat(m_mtContentToUser); | |
818 | |
819 std::unique_ptr<CPDF_ImageObject> pImageObj(new CPDF_ImageObject); | |
820 if (pImage) { | |
821 pImageObj->m_pImage = | |
822 m_pDocument->GetPageData()->GetImage(pImage->GetStream()); | |
823 } else if (pStream->GetObjNum()) { | |
824 pImageObj->m_pImage = m_pDocument->LoadImageF(pStream); | |
825 } else { | |
826 pImageObj->m_pImage = new CPDF_Image(m_pDocument); | |
827 pImageObj->m_pImage->LoadImageF(pStream, bInline); | |
828 } | |
829 SetGraphicStates(pImageObj.get(), pImageObj->m_pImage->IsMask(), FALSE, | |
830 FALSE); | |
831 pImageObj->m_Matrix = ImageMatrix; | |
832 pImageObj->CalcBoundingBox(); | |
833 CPDF_ImageObject* pRet = pImageObj.get(); | |
834 m_pObjectHolder->GetPageObjectList()->push_back(std::move(pImageObj)); | |
835 return pRet; | |
836 } | |
837 | |
838 void CPDF_StreamContentParser::Handle_MarkPlace_Dictionary() {} | |
839 | |
840 void CPDF_StreamContentParser::Handle_EndImage() {} | |
841 | |
842 void CPDF_StreamContentParser::Handle_EndMarkedContent() { | |
843 if (!m_Options.m_bMarkedContent) { | |
844 return; | |
845 } | |
846 if (m_CurContentMark.IsNull()) { | |
847 return; | |
848 } | |
849 int count = m_CurContentMark.GetObject()->CountItems(); | |
850 if (count == 1) { | |
851 m_CurContentMark.SetNull(); | |
852 return; | |
853 } | |
854 m_CurContentMark.GetModify()->DeleteLastMark(); | |
855 } | |
856 | |
857 void CPDF_StreamContentParser::Handle_EndText() { | |
858 int count = m_ClipTextList.GetSize(); | |
859 if (count == 0) { | |
860 return; | |
861 } | |
862 if (m_pCurStates->m_TextState.GetObject()->m_TextMode < 4) { | |
863 for (int i = 0; i < count; i++) { | |
864 delete m_ClipTextList.GetAt(i); | |
865 } | |
866 } else { | |
867 m_pCurStates->m_ClipPath.AppendTexts(m_ClipTextList.GetData(), count); | |
868 } | |
869 m_ClipTextList.RemoveAll(); | |
870 } | |
871 | |
872 void CPDF_StreamContentParser::Handle_FillPath() { | |
873 if (m_Options.m_bTextOnly) { | |
874 return; | |
875 } | |
876 AddPathObject(FXFILL_WINDING, FALSE); | |
877 } | |
878 | |
879 void CPDF_StreamContentParser::Handle_FillPathOld() { | |
880 if (m_Options.m_bTextOnly) { | |
881 return; | |
882 } | |
883 AddPathObject(FXFILL_WINDING, FALSE); | |
884 } | |
885 | |
886 void CPDF_StreamContentParser::Handle_EOFillPath() { | |
887 if (m_Options.m_bTextOnly) { | |
888 return; | |
889 } | |
890 AddPathObject(FXFILL_ALTERNATE, FALSE); | |
891 } | |
892 | |
893 void CPDF_StreamContentParser::Handle_SetGray_Fill() { | |
894 FX_FLOAT value = GetNumber(0); | |
895 CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY); | |
896 m_pCurStates->m_ColorState.SetFillColor(pCS, &value, 1); | |
897 } | |
898 | |
899 void CPDF_StreamContentParser::Handle_SetGray_Stroke() { | |
900 FX_FLOAT value = GetNumber(0); | |
901 CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY); | |
902 m_pCurStates->m_ColorState.SetStrokeColor(pCS, &value, 1); | |
903 } | |
904 | |
905 void CPDF_StreamContentParser::Handle_SetExtendGraphState() { | |
906 CFX_ByteString name = GetString(0); | |
907 CPDF_Dictionary* pGS = ToDictionary(FindResourceObj("ExtGState", name)); | |
908 if (!pGS) { | |
909 m_bResourceMissing = TRUE; | |
910 return; | |
911 } | |
912 m_pCurStates->ProcessExtGS(pGS, this); | |
913 } | |
914 | |
915 void CPDF_StreamContentParser::Handle_ClosePath() { | |
916 if (m_Options.m_bTextOnly) { | |
917 return; | |
918 } | |
919 if (m_PathPointCount == 0) { | |
920 return; | |
921 } | |
922 if (m_PathStartX != m_PathCurrentX || m_PathStartY != m_PathCurrentY) { | |
923 AddPathPoint(m_PathStartX, m_PathStartY, FXPT_LINETO | FXPT_CLOSEFIGURE); | |
924 } else if (m_pPathPoints[m_PathPointCount - 1].m_Flag != FXPT_MOVETO) { | |
925 m_pPathPoints[m_PathPointCount - 1].m_Flag |= FXPT_CLOSEFIGURE; | |
926 } | |
927 } | |
928 | |
929 void CPDF_StreamContentParser::Handle_SetFlat() { | |
930 m_pCurStates->m_GeneralState.GetModify()->m_Flatness = GetNumber(0); | |
931 } | |
932 | |
933 void CPDF_StreamContentParser::Handle_BeginImageData() {} | |
934 | |
935 void CPDF_StreamContentParser::Handle_SetLineJoin() { | |
936 m_pCurStates->m_GraphState.GetModify()->m_LineJoin = | |
937 (CFX_GraphStateData::LineJoin)GetInteger(0); | |
938 } | |
939 | |
940 void CPDF_StreamContentParser::Handle_SetLineCap() { | |
941 m_pCurStates->m_GraphState.GetModify()->m_LineCap = | |
942 (CFX_GraphStateData::LineCap)GetInteger(0); | |
943 } | |
944 | |
945 void CPDF_StreamContentParser::Handle_SetCMYKColor_Fill() { | |
946 if (m_ParamCount != 4) | |
947 return; | |
948 | |
949 FX_FLOAT values[4]; | |
950 for (int i = 0; i < 4; i++) { | |
951 values[i] = GetNumber(3 - i); | |
952 } | |
953 CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK); | |
954 m_pCurStates->m_ColorState.SetFillColor(pCS, values, 4); | |
955 } | |
956 | |
957 void CPDF_StreamContentParser::Handle_SetCMYKColor_Stroke() { | |
958 if (m_ParamCount != 4) | |
959 return; | |
960 | |
961 FX_FLOAT values[4]; | |
962 for (int i = 0; i < 4; i++) { | |
963 values[i] = GetNumber(3 - i); | |
964 } | |
965 CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK); | |
966 m_pCurStates->m_ColorState.SetStrokeColor(pCS, values, 4); | |
967 } | |
968 | |
969 void CPDF_StreamContentParser::Handle_LineTo() { | |
970 if (m_ParamCount != 2) | |
971 return; | |
972 | |
973 if (m_Options.m_bTextOnly) { | |
974 return; | |
975 } | |
976 AddPathPoint(GetNumber(1), GetNumber(0), FXPT_LINETO); | |
977 } | |
978 | |
979 void CPDF_StreamContentParser::Handle_MoveTo() { | |
980 if (m_ParamCount != 2) | |
981 return; | |
982 | |
983 if (m_Options.m_bTextOnly) { | |
984 m_pSyntax->SkipPathObject(); | |
985 return; | |
986 } | |
987 AddPathPoint(GetNumber(1), GetNumber(0), FXPT_MOVETO); | |
988 ParsePathObject(); | |
989 } | |
990 | |
991 void CPDF_StreamContentParser::Handle_SetMiterLimit() { | |
992 m_pCurStates->m_GraphState.GetModify()->m_MiterLimit = GetNumber(0); | |
993 } | |
994 | |
995 void CPDF_StreamContentParser::Handle_MarkPlace() {} | |
996 | |
997 void CPDF_StreamContentParser::Handle_EndPath() { | |
998 if (m_Options.m_bTextOnly) { | |
999 return; | |
1000 } | |
1001 AddPathObject(0, FALSE); | |
1002 } | |
1003 | |
1004 void CPDF_StreamContentParser::Handle_SaveGraphState() { | |
1005 std::unique_ptr<CPDF_AllStates> pStates(new CPDF_AllStates); | |
1006 pStates->Copy(*m_pCurStates); | |
1007 m_StateStack.push_back(std::move(pStates)); | |
1008 } | |
1009 | |
1010 void CPDF_StreamContentParser::Handle_RestoreGraphState() { | |
1011 if (m_StateStack.empty()) | |
1012 return; | |
1013 std::unique_ptr<CPDF_AllStates> pStates = std::move(m_StateStack.back()); | |
1014 m_StateStack.pop_back(); | |
1015 m_pCurStates->Copy(*pStates); | |
1016 } | |
1017 | |
1018 void CPDF_StreamContentParser::Handle_Rectangle() { | |
1019 if (m_Options.m_bTextOnly) { | |
1020 return; | |
1021 } | |
1022 FX_FLOAT x = GetNumber(3), y = GetNumber(2); | |
1023 FX_FLOAT w = GetNumber(1), h = GetNumber(0); | |
1024 AddPathRect(x, y, w, h); | |
1025 } | |
1026 | |
1027 void CPDF_StreamContentParser::AddPathRect(FX_FLOAT x, | |
1028 FX_FLOAT y, | |
1029 FX_FLOAT w, | |
1030 FX_FLOAT h) { | |
1031 AddPathPoint(x, y, FXPT_MOVETO); | |
1032 AddPathPoint(x + w, y, FXPT_LINETO); | |
1033 AddPathPoint(x + w, y + h, FXPT_LINETO); | |
1034 AddPathPoint(x, y + h, FXPT_LINETO); | |
1035 AddPathPoint(x, y, FXPT_LINETO | FXPT_CLOSEFIGURE); | |
1036 } | |
1037 | |
1038 void CPDF_StreamContentParser::Handle_SetRGBColor_Fill() { | |
1039 if (m_ParamCount != 3) | |
1040 return; | |
1041 | |
1042 FX_FLOAT values[3]; | |
1043 for (int i = 0; i < 3; i++) { | |
1044 values[i] = GetNumber(2 - i); | |
1045 } | |
1046 CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB); | |
1047 m_pCurStates->m_ColorState.SetFillColor(pCS, values, 3); | |
1048 } | |
1049 | |
1050 void CPDF_StreamContentParser::Handle_SetRGBColor_Stroke() { | |
1051 if (m_ParamCount != 3) | |
1052 return; | |
1053 | |
1054 FX_FLOAT values[3]; | |
1055 for (int i = 0; i < 3; i++) { | |
1056 values[i] = GetNumber(2 - i); | |
1057 } | |
1058 CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB); | |
1059 m_pCurStates->m_ColorState.SetStrokeColor(pCS, values, 3); | |
1060 } | |
1061 | |
1062 void CPDF_StreamContentParser::Handle_SetRenderIntent() {} | |
1063 | |
1064 void CPDF_StreamContentParser::Handle_CloseStrokePath() { | |
1065 if (m_Options.m_bTextOnly) { | |
1066 return; | |
1067 } | |
1068 Handle_ClosePath(); | |
1069 AddPathObject(0, TRUE); | |
1070 } | |
1071 | |
1072 void CPDF_StreamContentParser::Handle_StrokePath() { | |
1073 if (m_Options.m_bTextOnly) { | |
1074 return; | |
1075 } | |
1076 AddPathObject(0, TRUE); | |
1077 } | |
1078 | |
1079 void CPDF_StreamContentParser::Handle_SetColor_Fill() { | |
1080 if (m_Options.m_bTextOnly) { | |
1081 return; | |
1082 } | |
1083 FX_FLOAT values[4]; | |
1084 int nargs = m_ParamCount; | |
1085 if (nargs > 4) { | |
1086 nargs = 4; | |
1087 } | |
1088 for (int i = 0; i < nargs; i++) { | |
1089 values[i] = GetNumber(nargs - i - 1); | |
1090 } | |
1091 m_pCurStates->m_ColorState.SetFillColor(NULL, values, nargs); | |
1092 } | |
1093 | |
1094 void CPDF_StreamContentParser::Handle_SetColor_Stroke() { | |
1095 if (m_Options.m_bTextOnly) { | |
1096 return; | |
1097 } | |
1098 FX_FLOAT values[4]; | |
1099 int nargs = m_ParamCount; | |
1100 if (nargs > 4) { | |
1101 nargs = 4; | |
1102 } | |
1103 for (int i = 0; i < nargs; i++) { | |
1104 values[i] = GetNumber(nargs - i - 1); | |
1105 } | |
1106 m_pCurStates->m_ColorState.SetStrokeColor(NULL, values, nargs); | |
1107 } | |
1108 | |
1109 void CPDF_StreamContentParser::Handle_SetColorPS_Fill() { | |
1110 if (m_Options.m_bTextOnly) { | |
1111 return; | |
1112 } | |
1113 CPDF_Object* pLastParam = GetObject(0); | |
1114 if (!pLastParam) { | |
1115 return; | |
1116 } | |
1117 int nargs = m_ParamCount; | |
1118 int nvalues = nargs; | |
1119 if (pLastParam->IsName()) { | |
1120 nvalues--; | |
1121 } | |
1122 FX_FLOAT* values = NULL; | |
1123 if (nvalues) { | |
1124 values = FX_Alloc(FX_FLOAT, nvalues); | |
1125 for (int i = 0; i < nvalues; i++) { | |
1126 values[i] = GetNumber(nargs - i - 1); | |
1127 } | |
1128 } | |
1129 if (nvalues != nargs) { | |
1130 CPDF_Pattern* pPattern = FindPattern(GetString(0), FALSE); | |
1131 if (pPattern) { | |
1132 m_pCurStates->m_ColorState.SetFillPattern(pPattern, values, nvalues); | |
1133 } | |
1134 } else { | |
1135 m_pCurStates->m_ColorState.SetFillColor(NULL, values, nvalues); | |
1136 } | |
1137 FX_Free(values); | |
1138 } | |
1139 | |
1140 void CPDF_StreamContentParser::Handle_SetColorPS_Stroke() { | |
1141 if (m_Options.m_bTextOnly) { | |
1142 return; | |
1143 } | |
1144 CPDF_Object* pLastParam = GetObject(0); | |
1145 if (!pLastParam) { | |
1146 return; | |
1147 } | |
1148 int nargs = m_ParamCount; | |
1149 int nvalues = nargs; | |
1150 if (pLastParam->IsName()) | |
1151 nvalues--; | |
1152 | |
1153 FX_FLOAT* values = NULL; | |
1154 if (nvalues) { | |
1155 values = FX_Alloc(FX_FLOAT, nvalues); | |
1156 for (int i = 0; i < nvalues; i++) { | |
1157 values[i] = GetNumber(nargs - i - 1); | |
1158 } | |
1159 } | |
1160 if (nvalues != nargs) { | |
1161 CPDF_Pattern* pPattern = FindPattern(GetString(0), FALSE); | |
1162 if (pPattern) { | |
1163 m_pCurStates->m_ColorState.SetStrokePattern(pPattern, values, nvalues); | |
1164 } | |
1165 } else { | |
1166 m_pCurStates->m_ColorState.SetStrokeColor(NULL, values, nvalues); | |
1167 } | |
1168 FX_Free(values); | |
1169 } | |
1170 | |
1171 CFX_FloatRect GetShadingBBox(CPDF_Stream* pStream, | |
1172 ShadingType type, | |
1173 const CFX_Matrix* pMatrix, | |
1174 CPDF_Function** pFuncs, | |
1175 int nFuncs, | |
1176 CPDF_ColorSpace* pCS); | |
1177 | |
1178 void CPDF_StreamContentParser::Handle_ShadeFill() { | |
1179 if (m_Options.m_bTextOnly) { | |
1180 return; | |
1181 } | |
1182 CPDF_Pattern* pPattern = FindPattern(GetString(0), TRUE); | |
1183 if (!pPattern) { | |
1184 return; | |
1185 } | |
1186 if (pPattern->m_PatternType != CPDF_Pattern::SHADING) { | |
1187 return; | |
1188 } | |
1189 CPDF_ShadingPattern* pShading = static_cast<CPDF_ShadingPattern*>(pPattern); | |
1190 if (!pShading->m_bShadingObj) { | |
1191 return; | |
1192 } | |
1193 if (!pShading->Load()) { | |
1194 return; | |
1195 } | |
1196 std::unique_ptr<CPDF_ShadingObject> pObj(new CPDF_ShadingObject); | |
1197 pObj->m_pShading = pShading; | |
1198 SetGraphicStates(pObj.get(), FALSE, FALSE, FALSE); | |
1199 pObj->m_Matrix = m_pCurStates->m_CTM; | |
1200 pObj->m_Matrix.Concat(m_mtContentToUser); | |
1201 CFX_FloatRect bbox; | |
1202 if (!pObj->m_ClipPath.IsNull()) { | |
1203 bbox = pObj->m_ClipPath.GetClipBox(); | |
1204 } else { | |
1205 bbox = m_BBox; | |
1206 } | |
1207 if (pShading->IsMeshShading()) { | |
1208 bbox.Intersect(GetShadingBBox(ToStream(pShading->m_pShadingObj), | |
1209 pShading->m_ShadingType, &pObj->m_Matrix, | |
1210 pShading->m_pFunctions, pShading->m_nFuncs, | |
1211 pShading->m_pCS)); | |
1212 } | |
1213 pObj->m_Left = bbox.left; | |
1214 pObj->m_Right = bbox.right; | |
1215 pObj->m_Top = bbox.top; | |
1216 pObj->m_Bottom = bbox.bottom; | |
1217 m_pObjectHolder->GetPageObjectList()->push_back(std::move(pObj)); | |
1218 } | |
1219 | |
1220 void CPDF_StreamContentParser::Handle_SetCharSpace() { | |
1221 m_pCurStates->m_TextState.GetModify()->m_CharSpace = GetNumber(0); | |
1222 } | |
1223 | |
1224 void CPDF_StreamContentParser::Handle_MoveTextPoint() { | |
1225 m_pCurStates->m_TextLineX += GetNumber(1); | |
1226 m_pCurStates->m_TextLineY += GetNumber(0); | |
1227 m_pCurStates->m_TextX = m_pCurStates->m_TextLineX; | |
1228 m_pCurStates->m_TextY = m_pCurStates->m_TextLineY; | |
1229 } | |
1230 | |
1231 void CPDF_StreamContentParser::Handle_MoveTextPoint_SetLeading() { | |
1232 Handle_MoveTextPoint(); | |
1233 m_pCurStates->m_TextLeading = -GetNumber(0); | |
1234 } | |
1235 | |
1236 void CPDF_StreamContentParser::Handle_SetFont() { | |
1237 FX_FLOAT fs = GetNumber(0); | |
1238 if (fs == 0) { | |
1239 fs = m_DefFontSize; | |
1240 } | |
1241 m_pCurStates->m_TextState.GetModify()->m_FontSize = fs; | |
1242 CPDF_Font* pFont = FindFont(GetString(1)); | |
1243 if (pFont) { | |
1244 m_pCurStates->m_TextState.SetFont(pFont); | |
1245 } | |
1246 } | |
1247 | |
1248 CPDF_Object* CPDF_StreamContentParser::FindResourceObj( | |
1249 const CFX_ByteStringC& type, | |
1250 const CFX_ByteString& name) { | |
1251 if (!m_pResources) { | |
1252 return NULL; | |
1253 } | |
1254 if (m_pResources == m_pPageResources) { | |
1255 CPDF_Dictionary* pList = m_pResources->GetDictBy(type); | |
1256 if (!pList) { | |
1257 return NULL; | |
1258 } | |
1259 CPDF_Object* pRes = pList->GetElementValue(name); | |
1260 return pRes; | |
1261 } | |
1262 CPDF_Dictionary* pList = m_pResources->GetDictBy(type); | |
1263 if (!pList) { | |
1264 if (!m_pPageResources) { | |
1265 return NULL; | |
1266 } | |
1267 CPDF_Dictionary* pList = m_pPageResources->GetDictBy(type); | |
1268 if (!pList) { | |
1269 return NULL; | |
1270 } | |
1271 CPDF_Object* pRes = pList->GetElementValue(name); | |
1272 return pRes; | |
1273 } | |
1274 CPDF_Object* pRes = pList->GetElementValue(name); | |
1275 return pRes; | |
1276 } | |
1277 | |
1278 CPDF_Font* CPDF_StreamContentParser::FindFont(const CFX_ByteString& name) { | |
1279 CPDF_Dictionary* pFontDict = ToDictionary(FindResourceObj("Font", name)); | |
1280 if (!pFontDict) { | |
1281 m_bResourceMissing = TRUE; | |
1282 return CPDF_Font::GetStockFont(m_pDocument, "Helvetica"); | |
1283 } | |
1284 | |
1285 CPDF_Font* pFont = m_pDocument->LoadFont(pFontDict); | |
1286 if (pFont && pFont->IsType3Font()) { | |
1287 pFont->AsType3Font()->SetPageResources(m_pResources); | |
1288 pFont->AsType3Font()->CheckType3FontMetrics(); | |
1289 } | |
1290 return pFont; | |
1291 } | |
1292 | |
1293 CPDF_ColorSpace* CPDF_StreamContentParser::FindColorSpace( | |
1294 const CFX_ByteString& name) { | |
1295 if (name == "Pattern") { | |
1296 return CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN); | |
1297 } | |
1298 if (name == "DeviceGray" || name == "DeviceCMYK" || name == "DeviceRGB") { | |
1299 CFX_ByteString defname = "Default"; | |
1300 defname += name.Mid(7); | |
1301 CPDF_Object* pDefObj = FindResourceObj("ColorSpace", defname); | |
1302 if (!pDefObj) { | |
1303 if (name == "DeviceGray") { | |
1304 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY); | |
1305 } | |
1306 if (name == "DeviceRGB") { | |
1307 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB); | |
1308 } | |
1309 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK); | |
1310 } | |
1311 return m_pDocument->LoadColorSpace(pDefObj); | |
1312 } | |
1313 CPDF_Object* pCSObj = FindResourceObj("ColorSpace", name); | |
1314 if (!pCSObj) { | |
1315 m_bResourceMissing = TRUE; | |
1316 return NULL; | |
1317 } | |
1318 return m_pDocument->LoadColorSpace(pCSObj); | |
1319 } | |
1320 | |
1321 CPDF_Pattern* CPDF_StreamContentParser::FindPattern(const CFX_ByteString& name, | |
1322 FX_BOOL bShading) { | |
1323 CPDF_Object* pPattern = | |
1324 FindResourceObj(bShading ? "Shading" : "Pattern", name); | |
1325 if (!pPattern || (!pPattern->IsDictionary() && !pPattern->IsStream())) { | |
1326 m_bResourceMissing = TRUE; | |
1327 return NULL; | |
1328 } | |
1329 return m_pDocument->LoadPattern(pPattern, bShading, | |
1330 &m_pCurStates->m_ParentMatrix); | |
1331 } | |
1332 | |
1333 void CPDF_StreamContentParser::ConvertTextSpace(FX_FLOAT& x, FX_FLOAT& y) { | |
1334 m_pCurStates->m_TextMatrix.Transform(x, y, x, y); | |
1335 ConvertUserSpace(x, y); | |
1336 } | |
1337 | |
1338 void CPDF_StreamContentParser::ConvertUserSpace(FX_FLOAT& x, FX_FLOAT& y) { | |
1339 m_pCurStates->m_CTM.Transform(x, y, x, y); | |
1340 m_mtContentToUser.Transform(x, y, x, y); | |
1341 } | |
1342 | |
1343 void CPDF_StreamContentParser::AddTextObject(CFX_ByteString* pStrs, | |
1344 FX_FLOAT fInitKerning, | |
1345 FX_FLOAT* pKerning, | |
1346 int nsegs) { | |
1347 CPDF_Font* pFont = m_pCurStates->m_TextState.GetFont(); | |
1348 if (!pFont) { | |
1349 return; | |
1350 } | |
1351 if (fInitKerning != 0) { | |
1352 if (!pFont->IsVertWriting()) { | |
1353 m_pCurStates->m_TextX -= | |
1354 (fInitKerning * m_pCurStates->m_TextState.GetFontSize()) / 1000; | |
1355 } else { | |
1356 m_pCurStates->m_TextY -= | |
1357 (fInitKerning * m_pCurStates->m_TextState.GetFontSize()) / 1000; | |
1358 } | |
1359 } | |
1360 if (nsegs == 0) { | |
1361 return; | |
1362 } | |
1363 int textmode; | |
1364 if (pFont->IsType3Font()) { | |
1365 textmode = 0; | |
1366 } else { | |
1367 textmode = m_pCurStates->m_TextState.GetObject()->m_TextMode; | |
1368 } | |
1369 { | |
1370 std::unique_ptr<CPDF_TextObject> pText(new CPDF_TextObject); | |
1371 m_pLastTextObject = pText.get(); | |
1372 SetGraphicStates(m_pLastTextObject, TRUE, TRUE, TRUE); | |
1373 if (textmode && textmode != 3 && textmode != 4 && textmode != 7) { | |
1374 FX_FLOAT* pCTM = pText->m_TextState.GetModify()->m_CTM; | |
1375 pCTM[0] = m_pCurStates->m_CTM.a; | |
1376 pCTM[1] = m_pCurStates->m_CTM.c; | |
1377 pCTM[2] = m_pCurStates->m_CTM.b; | |
1378 pCTM[3] = m_pCurStates->m_CTM.d; | |
1379 } | |
1380 pText->SetSegments(pStrs, pKerning, nsegs); | |
1381 pText->m_PosX = m_pCurStates->m_TextX; | |
1382 pText->m_PosY = m_pCurStates->m_TextY + m_pCurStates->m_TextRise; | |
1383 ConvertTextSpace(pText->m_PosX, pText->m_PosY); | |
1384 FX_FLOAT x_advance; | |
1385 FX_FLOAT y_advance; | |
1386 pText->CalcPositionData(&x_advance, &y_advance, | |
1387 m_pCurStates->m_TextHorzScale, m_Level); | |
1388 m_pCurStates->m_TextX += x_advance; | |
1389 m_pCurStates->m_TextY += y_advance; | |
1390 if (textmode > 3) | |
1391 m_ClipTextList.Add(pText->Clone()); | |
1392 m_pObjectHolder->GetPageObjectList()->push_back(std::move(pText)); | |
1393 } | |
1394 if (pKerning && pKerning[nsegs - 1] != 0) { | |
1395 if (!pFont->IsVertWriting()) { | |
1396 m_pCurStates->m_TextX -= | |
1397 (pKerning[nsegs - 1] * m_pCurStates->m_TextState.GetFontSize()) / | |
1398 1000; | |
1399 } else { | |
1400 m_pCurStates->m_TextY -= | |
1401 (pKerning[nsegs - 1] * m_pCurStates->m_TextState.GetFontSize()) / | |
1402 1000; | |
1403 } | |
1404 } | |
1405 } | |
1406 | |
1407 void CPDF_StreamContentParser::Handle_ShowText() { | |
1408 CFX_ByteString str = GetString(0); | |
1409 if (str.IsEmpty()) { | |
1410 return; | |
1411 } | |
1412 AddTextObject(&str, 0, NULL, 1); | |
1413 } | |
1414 | |
1415 void CPDF_StreamContentParser::Handle_ShowText_Positioning() { | |
1416 CPDF_Array* pArray = GetObject(0) ? GetObject(0)->GetArray() : NULL; | |
1417 if (!pArray) { | |
1418 return; | |
1419 } | |
1420 int n = pArray->GetCount(); | |
1421 int nsegs = 0; | |
1422 for (int i = 0; i < n; i++) { | |
1423 if (pArray->GetElementValue(i)->IsString()) | |
1424 nsegs++; | |
1425 } | |
1426 if (nsegs == 0) { | |
1427 for (int i = 0; i < n; i++) { | |
1428 m_pCurStates->m_TextX -= | |
1429 (pArray->GetNumberAt(i) * m_pCurStates->m_TextState.GetFontSize()) / | |
1430 1000; | |
1431 } | |
1432 return; | |
1433 } | |
1434 CFX_ByteString* pStrs = new CFX_ByteString[nsegs]; | |
1435 FX_FLOAT* pKerning = FX_Alloc(FX_FLOAT, nsegs); | |
1436 int iSegment = 0; | |
1437 FX_FLOAT fInitKerning = 0; | |
1438 for (int i = 0; i < n; i++) { | |
1439 CPDF_Object* pObj = pArray->GetElementValue(i); | |
1440 if (pObj->IsString()) { | |
1441 CFX_ByteString str = pObj->GetString(); | |
1442 if (str.IsEmpty()) { | |
1443 continue; | |
1444 } | |
1445 pStrs[iSegment] = str; | |
1446 pKerning[iSegment++] = 0; | |
1447 } else { | |
1448 FX_FLOAT num = pObj ? pObj->GetNumber() : 0; | |
1449 if (iSegment == 0) { | |
1450 fInitKerning += num; | |
1451 } else { | |
1452 pKerning[iSegment - 1] += num; | |
1453 } | |
1454 } | |
1455 } | |
1456 AddTextObject(pStrs, fInitKerning, pKerning, iSegment); | |
1457 delete[] pStrs; | |
1458 FX_Free(pKerning); | |
1459 } | |
1460 | |
1461 void CPDF_StreamContentParser::Handle_SetTextLeading() { | |
1462 m_pCurStates->m_TextLeading = GetNumber(0); | |
1463 } | |
1464 | |
1465 void CPDF_StreamContentParser::Handle_SetTextMatrix() { | |
1466 m_pCurStates->m_TextMatrix.Set(GetNumber16(5), GetNumber16(4), GetNumber16(3), | |
1467 GetNumber16(2), GetNumber(1), GetNumber(0)); | |
1468 OnChangeTextMatrix(); | |
1469 m_pCurStates->m_TextX = 0; | |
1470 m_pCurStates->m_TextY = 0; | |
1471 m_pCurStates->m_TextLineX = 0; | |
1472 m_pCurStates->m_TextLineY = 0; | |
1473 } | |
1474 | |
1475 void CPDF_StreamContentParser::OnChangeTextMatrix() { | |
1476 CFX_Matrix text_matrix(m_pCurStates->m_TextHorzScale, 0.0f, 0.0f, 1.0f, 0.0f, | |
1477 0.0f); | |
1478 text_matrix.Concat(m_pCurStates->m_TextMatrix); | |
1479 text_matrix.Concat(m_pCurStates->m_CTM); | |
1480 text_matrix.Concat(m_mtContentToUser); | |
1481 FX_FLOAT* pTextMatrix = m_pCurStates->m_TextState.GetModify()->m_Matrix; | |
1482 pTextMatrix[0] = text_matrix.a; | |
1483 pTextMatrix[1] = text_matrix.c; | |
1484 pTextMatrix[2] = text_matrix.b; | |
1485 pTextMatrix[3] = text_matrix.d; | |
1486 } | |
1487 | |
1488 void CPDF_StreamContentParser::Handle_SetTextRenderMode() { | |
1489 int mode = GetInteger(0); | |
1490 if (mode < 0 || mode > 7) { | |
1491 return; | |
1492 } | |
1493 m_pCurStates->m_TextState.GetModify()->m_TextMode = mode; | |
1494 } | |
1495 | |
1496 void CPDF_StreamContentParser::Handle_SetTextRise() { | |
1497 m_pCurStates->m_TextRise = GetNumber(0); | |
1498 } | |
1499 | |
1500 void CPDF_StreamContentParser::Handle_SetWordSpace() { | |
1501 m_pCurStates->m_TextState.GetModify()->m_WordSpace = GetNumber(0); | |
1502 } | |
1503 | |
1504 void CPDF_StreamContentParser::Handle_SetHorzScale() { | |
1505 if (m_ParamCount != 1) { | |
1506 return; | |
1507 } | |
1508 m_pCurStates->m_TextHorzScale = GetNumber(0) / 100; | |
1509 OnChangeTextMatrix(); | |
1510 } | |
1511 | |
1512 void CPDF_StreamContentParser::Handle_MoveToNextLine() { | |
1513 m_pCurStates->m_TextLineY -= m_pCurStates->m_TextLeading; | |
1514 m_pCurStates->m_TextX = m_pCurStates->m_TextLineX; | |
1515 m_pCurStates->m_TextY = m_pCurStates->m_TextLineY; | |
1516 } | |
1517 | |
1518 void CPDF_StreamContentParser::Handle_CurveTo_23() { | |
1519 if (m_Options.m_bTextOnly) { | |
1520 return; | |
1521 } | |
1522 AddPathPoint(m_PathCurrentX, m_PathCurrentY, FXPT_BEZIERTO); | |
1523 AddPathPoint(GetNumber(3), GetNumber(2), FXPT_BEZIERTO); | |
1524 AddPathPoint(GetNumber(1), GetNumber(0), FXPT_BEZIERTO); | |
1525 } | |
1526 | |
1527 void CPDF_StreamContentParser::Handle_SetLineWidth() { | |
1528 FX_FLOAT width = GetNumber(0); | |
1529 m_pCurStates->m_GraphState.GetModify()->m_LineWidth = width; | |
1530 } | |
1531 | |
1532 void CPDF_StreamContentParser::Handle_Clip() { | |
1533 m_PathClipType = FXFILL_WINDING; | |
1534 } | |
1535 | |
1536 void CPDF_StreamContentParser::Handle_EOClip() { | |
1537 m_PathClipType = FXFILL_ALTERNATE; | |
1538 } | |
1539 | |
1540 void CPDF_StreamContentParser::Handle_CurveTo_13() { | |
1541 if (m_Options.m_bTextOnly) { | |
1542 return; | |
1543 } | |
1544 AddPathPoint(GetNumber(3), GetNumber(2), FXPT_BEZIERTO); | |
1545 AddPathPoint(GetNumber(1), GetNumber(0), FXPT_BEZIERTO); | |
1546 AddPathPoint(GetNumber(1), GetNumber(0), FXPT_BEZIERTO); | |
1547 } | |
1548 | |
1549 void CPDF_StreamContentParser::Handle_NextLineShowText() { | |
1550 Handle_MoveToNextLine(); | |
1551 Handle_ShowText(); | |
1552 } | |
1553 | |
1554 void CPDF_StreamContentParser::Handle_NextLineShowText_Space() { | |
1555 m_pCurStates->m_TextState.GetModify()->m_WordSpace = GetNumber(2); | |
1556 m_pCurStates->m_TextState.GetModify()->m_CharSpace = GetNumber(1); | |
1557 Handle_NextLineShowText(); | |
1558 } | |
1559 | |
1560 void CPDF_StreamContentParser::Handle_Invalid() {} | |
1561 | |
1562 void CPDF_StreamContentParser::AddPathPoint(FX_FLOAT x, FX_FLOAT y, int flag) { | |
1563 m_PathCurrentX = x; | |
1564 m_PathCurrentY = y; | |
1565 if (flag == FXPT_MOVETO) { | |
1566 m_PathStartX = x; | |
1567 m_PathStartY = y; | |
1568 if (m_PathPointCount && | |
1569 m_pPathPoints[m_PathPointCount - 1].m_Flag == FXPT_MOVETO) { | |
1570 m_pPathPoints[m_PathPointCount - 1].m_PointX = x; | |
1571 m_pPathPoints[m_PathPointCount - 1].m_PointY = y; | |
1572 return; | |
1573 } | |
1574 } else if (m_PathPointCount == 0) { | |
1575 return; | |
1576 } | |
1577 m_PathPointCount++; | |
1578 if (m_PathPointCount > m_PathAllocSize) { | |
1579 int newsize = m_PathPointCount + 256; | |
1580 FX_PATHPOINT* pNewPoints = FX_Alloc(FX_PATHPOINT, newsize); | |
1581 if (m_PathAllocSize) { | |
1582 FXSYS_memcpy(pNewPoints, m_pPathPoints, | |
1583 m_PathAllocSize * sizeof(FX_PATHPOINT)); | |
1584 FX_Free(m_pPathPoints); | |
1585 } | |
1586 m_pPathPoints = pNewPoints; | |
1587 m_PathAllocSize = newsize; | |
1588 } | |
1589 m_pPathPoints[m_PathPointCount - 1].m_Flag = flag; | |
1590 m_pPathPoints[m_PathPointCount - 1].m_PointX = x; | |
1591 m_pPathPoints[m_PathPointCount - 1].m_PointY = y; | |
1592 } | |
1593 | |
1594 void CPDF_StreamContentParser::AddPathObject(int FillType, FX_BOOL bStroke) { | |
1595 int PathPointCount = m_PathPointCount, PathClipType = m_PathClipType; | |
1596 m_PathPointCount = 0; | |
1597 m_PathClipType = 0; | |
1598 if (PathPointCount <= 1) { | |
1599 if (PathPointCount && PathClipType) { | |
1600 CPDF_Path path; | |
1601 path.New()->AppendRect(0, 0, 0, 0); | |
1602 m_pCurStates->m_ClipPath.AppendPath(path, FXFILL_WINDING, TRUE); | |
1603 } | |
1604 return; | |
1605 } | |
1606 if (PathPointCount && | |
1607 m_pPathPoints[PathPointCount - 1].m_Flag == FXPT_MOVETO) { | |
1608 PathPointCount--; | |
1609 } | |
1610 CPDF_Path Path; | |
1611 CFX_PathData* pPathData = Path.New(); | |
1612 pPathData->SetPointCount(PathPointCount); | |
1613 FXSYS_memcpy(pPathData->GetPoints(), m_pPathPoints, | |
1614 sizeof(FX_PATHPOINT) * PathPointCount); | |
1615 CFX_Matrix matrix = m_pCurStates->m_CTM; | |
1616 matrix.Concat(m_mtContentToUser); | |
1617 if (bStroke || FillType) { | |
1618 std::unique_ptr<CPDF_PathObject> pPathObj(new CPDF_PathObject); | |
1619 pPathObj->m_bStroke = bStroke; | |
1620 pPathObj->m_FillType = FillType; | |
1621 pPathObj->m_Path = Path; | |
1622 pPathObj->m_Matrix = matrix; | |
1623 SetGraphicStates(pPathObj.get(), TRUE, FALSE, TRUE); | |
1624 pPathObj->CalcBoundingBox(); | |
1625 m_pObjectHolder->GetPageObjectList()->push_back(std::move(pPathObj)); | |
1626 } | |
1627 if (PathClipType) { | |
1628 if (!matrix.IsIdentity()) { | |
1629 Path.Transform(&matrix); | |
1630 matrix.SetIdentity(); | |
1631 } | |
1632 m_pCurStates->m_ClipPath.AppendPath(Path, PathClipType, TRUE); | |
1633 } | |
1634 } | |
1635 | |
1636 FX_DWORD CPDF_StreamContentParser::Parse(const uint8_t* pData, | |
1637 FX_DWORD dwSize, | |
1638 FX_DWORD max_cost) { | |
1639 if (m_Level > _FPDF_MAX_FORM_LEVEL_) { | |
1640 return dwSize; | |
1641 } | |
1642 FX_DWORD InitObjCount = m_pObjectHolder->GetPageObjectList()->size(); | |
1643 CPDF_StreamParser syntax(pData, dwSize); | |
1644 CPDF_StreamParserAutoClearer auto_clearer(&m_pSyntax, &syntax); | |
1645 while (1) { | |
1646 FX_DWORD cost = m_pObjectHolder->GetPageObjectList()->size() - InitObjCount; | |
1647 if (max_cost && cost >= max_cost) { | |
1648 break; | |
1649 } | |
1650 switch (syntax.ParseNextElement()) { | |
1651 case CPDF_StreamParser::EndOfData: | |
1652 return m_pSyntax->GetPos(); | |
1653 case CPDF_StreamParser::Keyword: | |
1654 OnOperator((char*)syntax.GetWordBuf()); | |
1655 ClearAllParams(); | |
1656 break; | |
1657 case CPDF_StreamParser::Number: | |
1658 AddNumberParam((char*)syntax.GetWordBuf(), syntax.GetWordSize()); | |
1659 break; | |
1660 case CPDF_StreamParser::Name: | |
1661 AddNameParam((const FX_CHAR*)syntax.GetWordBuf() + 1, | |
1662 syntax.GetWordSize() - 1); | |
1663 break; | |
1664 default: | |
1665 AddObjectParam(syntax.GetObject()); | |
1666 } | |
1667 } | |
1668 return m_pSyntax->GetPos(); | |
1669 } | |
1670 | |
1671 void CPDF_StreamContentParser::ParsePathObject() { | |
1672 FX_FLOAT params[6] = {}; | |
1673 int nParams = 0; | |
1674 int last_pos = m_pSyntax->GetPos(); | |
1675 while (1) { | |
1676 CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement(); | |
1677 FX_BOOL bProcessed = TRUE; | |
1678 switch (type) { | |
1679 case CPDF_StreamParser::EndOfData: | |
1680 return; | |
1681 case CPDF_StreamParser::Keyword: { | |
1682 int len = m_pSyntax->GetWordSize(); | |
1683 if (len == 1) { | |
1684 switch (m_pSyntax->GetWordBuf()[0]) { | |
1685 case kPathOperatorSubpath: | |
1686 AddPathPoint(params[0], params[1], FXPT_MOVETO); | |
1687 nParams = 0; | |
1688 break; | |
1689 case kPathOperatorLine: | |
1690 AddPathPoint(params[0], params[1], FXPT_LINETO); | |
1691 nParams = 0; | |
1692 break; | |
1693 case kPathOperatorCubicBezier1: | |
1694 AddPathPoint(params[0], params[1], FXPT_BEZIERTO); | |
1695 AddPathPoint(params[2], params[3], FXPT_BEZIERTO); | |
1696 AddPathPoint(params[4], params[5], FXPT_BEZIERTO); | |
1697 nParams = 0; | |
1698 break; | |
1699 case kPathOperatorCubicBezier2: | |
1700 AddPathPoint(m_PathCurrentX, m_PathCurrentY, FXPT_BEZIERTO); | |
1701 AddPathPoint(params[0], params[1], FXPT_BEZIERTO); | |
1702 AddPathPoint(params[2], params[3], FXPT_BEZIERTO); | |
1703 nParams = 0; | |
1704 break; | |
1705 case kPathOperatorCubicBezier3: | |
1706 AddPathPoint(params[0], params[1], FXPT_BEZIERTO); | |
1707 AddPathPoint(params[2], params[3], FXPT_BEZIERTO); | |
1708 AddPathPoint(params[2], params[3], FXPT_BEZIERTO); | |
1709 nParams = 0; | |
1710 break; | |
1711 case kPathOperatorClosePath: | |
1712 Handle_ClosePath(); | |
1713 nParams = 0; | |
1714 break; | |
1715 default: | |
1716 bProcessed = FALSE; | |
1717 break; | |
1718 } | |
1719 } else if (len == 2) { | |
1720 if (m_pSyntax->GetWordBuf()[0] == kPathOperatorRectangle[0] && | |
1721 m_pSyntax->GetWordBuf()[1] == kPathOperatorRectangle[1]) { | |
1722 AddPathRect(params[0], params[1], params[2], params[3]); | |
1723 nParams = 0; | |
1724 } else { | |
1725 bProcessed = FALSE; | |
1726 } | |
1727 } else { | |
1728 bProcessed = FALSE; | |
1729 } | |
1730 if (bProcessed) { | |
1731 last_pos = m_pSyntax->GetPos(); | |
1732 } | |
1733 break; | |
1734 } | |
1735 case CPDF_StreamParser::Number: { | |
1736 if (nParams == 6) { | |
1737 break; | |
1738 } | |
1739 FX_BOOL bInteger; | |
1740 int value; | |
1741 FX_atonum( | |
1742 CFX_ByteStringC(m_pSyntax->GetWordBuf(), m_pSyntax->GetWordSize()), | |
1743 bInteger, &value); | |
1744 params[nParams++] = bInteger ? (FX_FLOAT)value : *(FX_FLOAT*)&value; | |
1745 break; | |
1746 } | |
1747 default: | |
1748 bProcessed = FALSE; | |
1749 } | |
1750 if (!bProcessed) { | |
1751 m_pSyntax->SetPos(last_pos); | |
1752 return; | |
1753 } | |
1754 } | |
1755 } | |
1756 | |
1757 void PDF_ReplaceAbbr(CPDF_Object* pObj) { | |
1758 switch (pObj->GetType()) { | |
1759 case CPDF_Object::DICTIONARY: { | |
1760 CPDF_Dictionary* pDict = pObj->AsDictionary(); | |
1761 std::vector<AbbrReplacementOp> replacements; | |
1762 for (const auto& it : *pDict) { | |
1763 CFX_ByteString key = it.first; | |
1764 CPDF_Object* value = it.second; | |
1765 CFX_ByteStringC fullname = PDF_FindFullName( | |
1766 PDF_InlineKeyAbbr, FX_ArraySize(PDF_InlineKeyAbbr), key); | |
1767 if (!fullname.IsEmpty()) { | |
1768 AbbrReplacementOp op; | |
1769 op.is_replace_key = true; | |
1770 op.key = key; | |
1771 op.replacement = fullname; | |
1772 replacements.push_back(op); | |
1773 key = fullname; | |
1774 } | |
1775 | |
1776 if (value->IsName()) { | |
1777 CFX_ByteString name = value->GetString(); | |
1778 fullname = PDF_FindFullName(PDF_InlineValueAbbr, | |
1779 FX_ArraySize(PDF_InlineValueAbbr), name); | |
1780 if (!fullname.IsEmpty()) { | |
1781 AbbrReplacementOp op; | |
1782 op.is_replace_key = false; | |
1783 op.key = key; | |
1784 op.replacement = fullname; | |
1785 replacements.push_back(op); | |
1786 } | |
1787 } else { | |
1788 PDF_ReplaceAbbr(value); | |
1789 } | |
1790 } | |
1791 for (const auto& op : replacements) { | |
1792 if (op.is_replace_key) | |
1793 pDict->ReplaceKey(op.key, op.replacement); | |
1794 else | |
1795 pDict->SetAtName(op.key, op.replacement); | |
1796 } | |
1797 break; | |
1798 } | |
1799 case CPDF_Object::ARRAY: { | |
1800 CPDF_Array* pArray = pObj->AsArray(); | |
1801 for (FX_DWORD i = 0; i < pArray->GetCount(); i++) { | |
1802 CPDF_Object* pElement = pArray->GetElement(i); | |
1803 if (pElement->IsName()) { | |
1804 CFX_ByteString name = pElement->GetString(); | |
1805 CFX_ByteStringC fullname = PDF_FindFullName( | |
1806 PDF_InlineValueAbbr, FX_ArraySize(PDF_InlineValueAbbr), name); | |
1807 if (!fullname.IsEmpty()) { | |
1808 pArray->SetAt(i, new CPDF_Name(fullname)); | |
1809 } | |
1810 } else { | |
1811 PDF_ReplaceAbbr(pElement); | |
1812 } | |
1813 } | |
1814 break; | |
1815 } | |
1816 default: | |
1817 break; | |
1818 } | |
1819 } | |
OLD | NEW |