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