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