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