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