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