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