e9115e6342294bed26c2423636d2bfbf56a75aee
[pdfium.git] / core / src / fpdfapi / fpdf_page / fpdf_page_graph_state.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_pageobj.h"\r
9 #include "../../../include/fpdfapi/fpdf_module.h"\r
10 #include "../../../include/fpdfapi/fpdf_render.h"\r
11 #include "pageint.h"\r
12 #include "../fpdf_render/render_int.h"\r
13 void CPDF_GraphicStates::DefaultStates()\r
14 {\r
15     m_ColorState.New()->Default();\r
16 }\r
17 void CPDF_GraphicStates::CopyStates(const CPDF_GraphicStates& src)\r
18 {\r
19     m_ClipPath = src.m_ClipPath;\r
20     m_GraphState = src.m_GraphState;\r
21     m_ColorState = src.m_ColorState;\r
22     m_TextState = src.m_TextState;\r
23     m_GeneralState = src.m_GeneralState;\r
24 }\r
25 CPDF_ClipPathData::CPDF_ClipPathData()\r
26 {\r
27     m_PathCount = 0;\r
28     m_pPathList = NULL;\r
29     m_pTypeList = NULL;\r
30     m_TextCount = 0;\r
31     m_pTextList = NULL;\r
32 }\r
33 CPDF_ClipPathData::~CPDF_ClipPathData()\r
34 {\r
35     int i;\r
36     if (m_pPathList) {\r
37         FX_DELETE_VECTOR(m_pPathList, CPDF_Path, m_PathCount);\r
38     }\r
39     if (m_pTypeList) {\r
40         FX_Free(m_pTypeList);\r
41     }\r
42     for (i = m_TextCount - 1; i > -1; i --)\r
43         if (m_pTextList[i]) {\r
44             delete m_pTextList[i];\r
45         }\r
46     if (m_pTextList) {\r
47         FX_Free(m_pTextList);\r
48     }\r
49 }\r
50 CPDF_ClipPathData::CPDF_ClipPathData(const CPDF_ClipPathData& src)\r
51 {\r
52     m_pPathList = NULL;\r
53     m_pPathList = NULL;\r
54     m_pTextList = NULL;\r
55     m_PathCount = src.m_PathCount;\r
56     if (m_PathCount) {\r
57         int alloc_size = m_PathCount;\r
58         if (alloc_size % 8) {\r
59             alloc_size += 8 - (alloc_size % 8);\r
60         }\r
61         FX_NEW_VECTOR(m_pPathList, CPDF_Path, alloc_size);\r
62         for (int i = 0; i < m_PathCount; i ++) {\r
63             m_pPathList[i] = src.m_pPathList[i];\r
64         }\r
65         m_pTypeList = FX_Alloc(FX_BYTE, alloc_size);\r
66         FXSYS_memcpy32(m_pTypeList, src.m_pTypeList, m_PathCount);\r
67     } else {\r
68         m_pPathList = NULL;\r
69         m_pTypeList = NULL;\r
70     }\r
71     m_TextCount = src.m_TextCount;\r
72     if (m_TextCount) {\r
73         m_pTextList = FX_Alloc(CPDF_TextObject*, m_TextCount);\r
74         FXSYS_memset32(m_pTextList, 0, sizeof(CPDF_TextObject*) * m_TextCount);\r
75         for (int i = 0; i < m_TextCount; i ++) {\r
76             if (src.m_pTextList[i]) {\r
77                 m_pTextList[i] = FX_NEW CPDF_TextObject;\r
78                 m_pTextList[i]->Copy(src.m_pTextList[i]);\r
79             } else {\r
80                 m_pTextList[i] = NULL;\r
81             }\r
82         }\r
83     } else {\r
84         m_pTextList = NULL;\r
85     }\r
86 }\r
87 void CPDF_ClipPathData::SetCount(int path_count, int text_count)\r
88 {\r
89     ASSERT(m_TextCount == 0 && m_PathCount == 0);\r
90     if (path_count) {\r
91         m_PathCount = path_count;\r
92         int alloc_size = (path_count + 7) / 8 * 8;\r
93         FX_NEW_VECTOR(m_pPathList, CPDF_Path, alloc_size);\r
94         m_pTypeList = FX_Alloc(FX_BYTE, alloc_size);\r
95     }\r
96     if (text_count) {\r
97         m_TextCount = text_count;\r
98         m_pTextList = FX_Alloc(CPDF_TextObject*, text_count);\r
99         FXSYS_memset32(m_pTextList, 0, sizeof(void*) * text_count);\r
100     }\r
101 }\r
102 CPDF_Rect CPDF_ClipPath::GetClipBox() const\r
103 {\r
104     CPDF_Rect rect;\r
105     FX_BOOL bStarted = FALSE;\r
106     int count = GetPathCount();\r
107     if (count) {\r
108         rect = GetPath(0).GetBoundingBox();\r
109         for (int i = 1; i < count; i ++) {\r
110             CPDF_Rect path_rect = GetPath(i).GetBoundingBox();\r
111             rect.Intersect(path_rect);\r
112         }\r
113         bStarted = TRUE;\r
114     }\r
115     count = GetTextCount();\r
116     if (count) {\r
117         CPDF_Rect layer_rect;\r
118         FX_BOOL bLayerStarted = FALSE;\r
119         for (int i = 0; i < count; i ++) {\r
120             CPDF_TextObject* pTextObj = GetText(i);\r
121             if (pTextObj == NULL) {\r
122                 if (!bStarted) {\r
123                     rect = layer_rect;\r
124                     bStarted = TRUE;\r
125                 } else {\r
126                     rect.Intersect(layer_rect);\r
127                 }\r
128                 bLayerStarted = FALSE;\r
129             } else {\r
130                 if (!bLayerStarted) {\r
131                     layer_rect = pTextObj->GetBBox(NULL);\r
132                     bLayerStarted = TRUE;\r
133                 } else {\r
134                     layer_rect.Union(pTextObj->GetBBox(NULL));\r
135                 }\r
136             }\r
137         }\r
138     }\r
139     return rect;\r
140 }\r
141 void CPDF_ClipPath::AppendPath(CPDF_Path path, int type, FX_BOOL bAutoMerge)\r
142 {\r
143     CPDF_ClipPathData* pData = GetModify();\r
144     if (pData->m_PathCount && bAutoMerge) {\r
145         CPDF_Path old_path = pData->m_pPathList[pData->m_PathCount - 1];\r
146         if (old_path.IsRect()) {\r
147             CPDF_Rect old_rect(old_path.GetPointX(0), old_path.GetPointY(0),\r
148                                old_path.GetPointX(2), old_path.GetPointY(2));\r
149             CPDF_Rect new_rect = path.GetBoundingBox();\r
150             if (old_rect.Contains(new_rect)) {\r
151                 pData->m_PathCount --;\r
152                 pData->m_pPathList[pData->m_PathCount].SetNull();\r
153             }\r
154         }\r
155     }\r
156     if (pData->m_PathCount % 8 == 0) {\r
157         CPDF_Path* pNewPath;\r
158         FX_NEW_VECTOR(pNewPath, CPDF_Path, pData->m_PathCount + 8);\r
159         for (int i = 0; i < pData->m_PathCount; i ++) {\r
160             pNewPath[i] = pData->m_pPathList[i];\r
161         }\r
162         if (pData->m_pPathList) {\r
163             FX_DELETE_VECTOR(pData->m_pPathList, CPDF_Path, pData->m_PathCount);\r
164         }\r
165         FX_BYTE* pNewType = FX_Alloc(FX_BYTE, pData->m_PathCount + 8);\r
166         FXSYS_memcpy32(pNewType, pData->m_pTypeList, pData->m_PathCount);\r
167         if (pData->m_pTypeList) {\r
168             FX_Free(pData->m_pTypeList);\r
169         }\r
170         pData->m_pPathList = pNewPath;\r
171         pData->m_pTypeList = pNewType;\r
172     }\r
173     pData->m_pPathList[pData->m_PathCount] = path;\r
174     pData->m_pTypeList[pData->m_PathCount] = (FX_BYTE)type;\r
175     pData->m_PathCount ++;\r
176 }\r
177 void CPDF_ClipPath::DeletePath(int index)\r
178 {\r
179     CPDF_ClipPathData* pData = GetModify();\r
180     if (index >= pData->m_PathCount) {\r
181         return;\r
182     }\r
183     pData->m_pPathList[index].SetNull();\r
184     for (int i = index; i < pData->m_PathCount - 1; i ++) {\r
185         pData->m_pPathList[i] = pData->m_pPathList[i + 1];\r
186     }\r
187     pData->m_pPathList[pData->m_PathCount - 1].SetNull();\r
188     FXSYS_memmove32(pData->m_pTypeList + index, pData->m_pTypeList + index + 1, pData->m_PathCount - index - 1);\r
189     pData->m_PathCount --;\r
190 }\r
191 #define FPDF_CLIPPATH_MAX_TEXTS 1024\r
192 void CPDF_ClipPath::AppendTexts(CPDF_TextObject** pTexts, int count)\r
193 {\r
194     CPDF_ClipPathData* pData = GetModify();\r
195     if (pData->m_TextCount + count > FPDF_CLIPPATH_MAX_TEXTS) {\r
196         for (int i = 0; i < count; i ++) {\r
197             pTexts[i]->Release();\r
198         }\r
199         return;\r
200     }\r
201     CPDF_TextObject** pNewList = FX_Alloc(CPDF_TextObject*, pData->m_TextCount + count + 1);\r
202     if (pData->m_pTextList) {\r
203         FXSYS_memcpy32(pNewList, pData->m_pTextList, pData->m_TextCount * sizeof(CPDF_TextObject*));\r
204         FX_Free(pData->m_pTextList);\r
205     }\r
206     pData->m_pTextList = pNewList;\r
207     for (int i = 0; i < count; i ++) {\r
208         pData->m_pTextList[pData->m_TextCount + i] = pTexts[i];\r
209     }\r
210     pData->m_pTextList[pData->m_TextCount + count] = NULL;\r
211     pData->m_TextCount += count + 1;\r
212 }\r
213 void CPDF_ClipPath::Transform(const CPDF_Matrix& matrix)\r
214 {\r
215     CPDF_ClipPathData* pData = GetModify();\r
216     int i;\r
217     for (i = 0; i < pData->m_PathCount; i ++) {\r
218         pData->m_pPathList[i].Transform(&matrix);\r
219     }\r
220     for (i = 0; i < pData->m_TextCount; i ++)\r
221         if (pData->m_pTextList[i]) {\r
222             pData->m_pTextList[i]->Transform(matrix);\r
223         }\r
224 }\r
225 CPDF_ColorStateData::CPDF_ColorStateData(const CPDF_ColorStateData& src)\r
226 {\r
227     m_FillColor.Copy(&src.m_FillColor);\r
228     m_FillRGB = src.m_FillRGB;\r
229     m_StrokeColor.Copy(&src.m_StrokeColor);\r
230     m_StrokeRGB = src.m_StrokeRGB;\r
231 }\r
232 void CPDF_ColorStateData::Default()\r
233 {\r
234     m_FillRGB = m_StrokeRGB = 0;\r
235     m_FillColor.SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY));\r
236     m_StrokeColor.SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY));\r
237 }\r
238 void CPDF_ColorState::SetFillColor(CPDF_ColorSpace* pCS, FX_FLOAT* pValue, int nValues)\r
239 {\r
240     CPDF_ColorStateData* pData = GetModify();\r
241     SetColor(pData->m_FillColor, pData->m_FillRGB, pCS, pValue, nValues);\r
242 }\r
243 void CPDF_ColorState::SetStrokeColor(CPDF_ColorSpace* pCS, FX_FLOAT* pValue, int nValues)\r
244 {\r
245     CPDF_ColorStateData* pData = GetModify();\r
246     SetColor(pData->m_StrokeColor, pData->m_StrokeRGB, pCS, pValue, nValues);\r
247 }\r
248 void CPDF_ColorState::SetColor(CPDF_Color& color, FX_DWORD& rgb, CPDF_ColorSpace* pCS, FX_FLOAT* pValue, int nValues)\r
249 {\r
250     if (pCS) {\r
251         color.SetColorSpace(pCS);\r
252     } else if (color.IsNull()) {\r
253         color.SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY));\r
254     }\r
255     if (color.m_pCS->CountComponents() > nValues) {\r
256         return;\r
257     }\r
258     color.SetValue(pValue);\r
259     int R, G, B;\r
260     rgb = color.GetRGB(R, G, B) ? FXSYS_RGB(R, G, B) : (FX_DWORD) - 1;\r
261 }\r
262 void CPDF_ColorState::SetFillPattern(CPDF_Pattern* pPattern, FX_FLOAT* pValue, int nValues)\r
263 {\r
264     CPDF_ColorStateData* pData = GetModify();\r
265     pData->m_FillColor.SetValue(pPattern, pValue, nValues);\r
266     int R, G, B;\r
267     FX_BOOL ret = pData->m_FillColor.GetRGB(R, G, B);\r
268     if (pPattern->m_PatternType == 1 && ((CPDF_TilingPattern*)pPattern)->m_bColored && !ret) {\r
269         pData->m_FillRGB = 0x00BFBFBF;\r
270         return;\r
271     }\r
272     pData->m_FillRGB = ret ? FXSYS_RGB(R, G, B) : (FX_DWORD) - 1;\r
273 }\r
274 void CPDF_ColorState::SetStrokePattern(CPDF_Pattern* pPattern, FX_FLOAT* pValue, int nValues)\r
275 {\r
276     CPDF_ColorStateData* pData = GetModify();\r
277     pData->m_StrokeColor.SetValue(pPattern, pValue, nValues);\r
278     int R, G, B;\r
279     FX_BOOL ret = pData->m_StrokeColor.GetRGB(R, G, B);\r
280     if (pPattern->m_PatternType == 1 && ((CPDF_TilingPattern*)pPattern)->m_bColored && !ret) {\r
281         pData->m_StrokeRGB = 0x00BFBFBF;\r
282         return;\r
283     }\r
284     pData->m_StrokeRGB = pData->m_StrokeColor.GetRGB(R, G, B) ? FXSYS_RGB(R, G, B) : (FX_DWORD) - 1;\r
285 }\r
286 CPDF_TextStateData::CPDF_TextStateData()\r
287 {\r
288     m_pFont = NULL;\r
289     m_FontSize = 1.0f;\r
290     m_WordSpace = 0;\r
291     m_CharSpace = 0;\r
292     m_TextMode = 0;\r
293     m_Matrix[0] = m_Matrix[3] = 1.0f;\r
294     m_Matrix[1] = m_Matrix[2] = 0;\r
295     m_CTM[0] = m_CTM[3] = 1.0f;\r
296     m_CTM[1] = m_CTM[2] = 0;\r
297 }\r
298 CPDF_TextStateData::CPDF_TextStateData(const CPDF_TextStateData& src)\r
299 {\r
300     FXSYS_memcpy32(this, &src, sizeof(CPDF_TextStateData));\r
301     if (m_pFont && m_pFont->m_pDocument) {\r
302         m_pFont = m_pFont->m_pDocument->GetPageData()->GetFont(m_pFont->GetFontDict(), FALSE);\r
303     }\r
304 }\r
305 CPDF_TextStateData::~CPDF_TextStateData()\r
306 {\r
307     CPDF_Font* pFont = m_pFont;\r
308     if (pFont && pFont->m_pDocument) {\r
309         pFont->m_pDocument->GetPageData()->ReleaseFont(pFont->GetFontDict());\r
310     }\r
311 }\r
312 void CPDF_TextState::SetFont(CPDF_Font* pFont)\r
313 {\r
314     CPDF_Font*& pStateFont = GetModify()->m_pFont;\r
315     CPDF_DocPageData* pDocPageData = NULL;\r
316     if (pStateFont && pStateFont->m_pDocument) {\r
317         pDocPageData = pStateFont->m_pDocument->GetPageData();\r
318         pDocPageData->ReleaseFont(pStateFont->GetFontDict());\r
319     }\r
320     pStateFont = pFont;\r
321 }\r
322 FX_FLOAT CPDF_TextState::GetFontSizeV() const\r
323 {\r
324     FX_FLOAT* pMatrix = GetMatrix();\r
325     FX_FLOAT unit = FXSYS_sqrt2(pMatrix[1], pMatrix[3]);\r
326     FX_FLOAT size = FXSYS_Mul(unit, GetFontSize());\r
327     return (FX_FLOAT)FXSYS_fabs(size);\r
328 }\r
329 FX_FLOAT CPDF_TextState::GetFontSizeH() const\r
330 {\r
331     FX_FLOAT* pMatrix = GetMatrix();\r
332     FX_FLOAT unit = FXSYS_sqrt2(pMatrix[0], pMatrix[2]);\r
333     FX_FLOAT size = FXSYS_Mul(unit, GetFontSize());\r
334     return (FX_FLOAT)FXSYS_fabs(size);\r
335 }\r
336 FX_FLOAT CPDF_TextState::GetBaselineAngle() const\r
337 {\r
338     FX_FLOAT* m_Matrix = GetMatrix();\r
339     return FXSYS_atan2(m_Matrix[2], m_Matrix[0]);\r
340 }\r
341 FX_FLOAT CPDF_TextState::GetShearAngle() const\r
342 {\r
343     FX_FLOAT* m_Matrix = GetMatrix();\r
344     FX_FLOAT shear_angle = FXSYS_atan2(m_Matrix[1], m_Matrix[3]);\r
345     return GetBaselineAngle() + shear_angle;\r
346 }\r
347 CPDF_GeneralStateData::CPDF_GeneralStateData()\r
348 {\r
349     FXSYS_memset32(this, 0, sizeof(CPDF_GeneralStateData));\r
350     FXSYS_strcpy((FX_LPSTR)m_BlendMode, (FX_LPCSTR)"Normal");\r
351     m_StrokeAlpha = 1.0f;\r
352     m_FillAlpha = 1.0f;\r
353     m_Flatness = 1.0f;\r
354     m_Matrix.SetIdentity();\r
355 }\r
356 CPDF_GeneralStateData::CPDF_GeneralStateData(const CPDF_GeneralStateData& src)\r
357 {\r
358     FXSYS_memcpy32(this, &src, sizeof(CPDF_GeneralStateData));\r
359     if (src.m_pTransferFunc && src.m_pTransferFunc->m_pPDFDoc) {\r
360         CPDF_DocRenderData* pDocCache = src.m_pTransferFunc->m_pPDFDoc->GetRenderData();\r
361         if (!pDocCache) {\r
362             return;\r
363         }\r
364         m_pTransferFunc = pDocCache->GetTransferFunc(m_pTR);\r
365     }\r
366 }\r
367 CPDF_GeneralStateData::~CPDF_GeneralStateData()\r
368 {\r
369     if (m_pTransferFunc && m_pTransferFunc->m_pPDFDoc) {\r
370         CPDF_DocRenderData* pDocCache = m_pTransferFunc->m_pPDFDoc->GetRenderData();\r
371         if (!pDocCache) {\r
372             return;\r
373         }\r
374         pDocCache->ReleaseTransferFunc(m_pTR);\r
375     }\r
376 }\r
377 static int GetBlendType(FX_BSTR mode)\r
378 {\r
379     switch (mode.GetID()) {\r
380         case FXBSTR_ID('N', 'o', 'r', 'm'):\r
381         case FXBSTR_ID('C', 'o', 'm', 'p'):\r
382             return FXDIB_BLEND_NORMAL;\r
383         case FXBSTR_ID('M', 'u', 'l', 't'):\r
384             return FXDIB_BLEND_MULTIPLY;\r
385         case FXBSTR_ID('S', 'c', 'r', 'e'):\r
386             return FXDIB_BLEND_SCREEN;\r
387         case FXBSTR_ID('O', 'v', 'e', 'r'):\r
388             return FXDIB_BLEND_OVERLAY;\r
389         case FXBSTR_ID('D', 'a', 'r', 'k'):\r
390             return FXDIB_BLEND_DARKEN;\r
391         case FXBSTR_ID('L', 'i', 'g', 'h'):\r
392             return FXDIB_BLEND_LIGHTEN;\r
393         case FXBSTR_ID('C', 'o', 'l', 'o'):\r
394             if (mode.GetLength() == 10) {\r
395                 return FXDIB_BLEND_COLORDODGE;\r
396             }\r
397             if (mode.GetLength() == 9) {\r
398                 return FXDIB_BLEND_COLORBURN;\r
399             }\r
400             return FXDIB_BLEND_COLOR;\r
401         case FXBSTR_ID('H', 'a', 'r', 'd'):\r
402             return FXDIB_BLEND_HARDLIGHT;\r
403         case FXBSTR_ID('S', 'o', 'f', 't'):\r
404             return FXDIB_BLEND_SOFTLIGHT;\r
405         case FXBSTR_ID('D', 'i', 'f', 'f'):\r
406             return FXDIB_BLEND_DIFFERENCE;\r
407         case FXBSTR_ID('E', 'x', 'c', 'l'):\r
408             return FXDIB_BLEND_EXCLUSION;\r
409         case FXBSTR_ID('H', 'u', 'e', 0):\r
410             return FXDIB_BLEND_HUE;\r
411         case FXBSTR_ID('S', 'a', 't', 'u'):\r
412             return FXDIB_BLEND_SATURATION;\r
413         case FXBSTR_ID('L', 'u', 'm', 'i'):\r
414             return FXDIB_BLEND_LUMINOSITY;\r
415     }\r
416     return FXDIB_BLEND_NORMAL;\r
417 }\r
418 void CPDF_GeneralStateData::SetBlendMode(FX_BSTR blend_mode)\r
419 {\r
420     if (blend_mode.GetLength() > 15) {\r
421         return;\r
422     }\r
423     FXSYS_memcpy32(m_BlendMode, (FX_LPCBYTE)blend_mode, blend_mode.GetLength());\r
424     m_BlendMode[blend_mode.GetLength()] = 0;\r
425     m_BlendType = ::GetBlendType(blend_mode);\r
426 }\r
427 int RI_StringToId(const CFX_ByteString& ri)\r
428 {\r
429     FX_DWORD id = ri.GetID();\r
430     if (id == FXBSTR_ID('A', 'b', 's', 'o')) {\r
431         return 1;\r
432     }\r
433     if (id == FXBSTR_ID('S', 'a', 't', 'u')) {\r
434         return 2;\r
435     }\r
436     if (id == FXBSTR_ID('P', 'e', 'r', 'c')) {\r
437         return 3;\r
438     }\r
439     return 0;\r
440 }\r
441 void CPDF_GeneralState::SetRenderIntent(const CFX_ByteString& ri)\r
442 {\r
443     GetModify()->m_RenderIntent = RI_StringToId(ri);\r
444 }\r
445 CPDF_AllStates::CPDF_AllStates()\r
446 {\r
447     m_TextX = m_TextY = m_TextLineX = m_TextLineY = 0;\r
448     m_TextLeading = 0;\r
449     m_TextRise = 0;\r
450     m_TextHorzScale = 1.0f;\r
451 }\r
452 CPDF_AllStates::~CPDF_AllStates()\r
453 {\r
454 }\r
455 void CPDF_AllStates::Copy(const CPDF_AllStates& src)\r
456 {\r
457     CopyStates(src);\r
458     m_TextMatrix.Copy(src.m_TextMatrix);\r
459     m_ParentMatrix.Copy(src.m_ParentMatrix);\r
460     m_CTM.Copy(src.m_CTM);\r
461     m_TextX = src.m_TextX;\r
462     m_TextY = src.m_TextY;\r
463     m_TextLineX = src.m_TextLineX;\r
464     m_TextLineY = src.m_TextLineY;\r
465     m_TextLeading = src.m_TextLeading;\r
466     m_TextRise = src.m_TextRise;\r
467     m_TextHorzScale = src.m_TextHorzScale;\r
468 }\r
469 void CPDF_AllStates::SetLineDash(CPDF_Array* pArray, FX_FLOAT phase, FX_FLOAT scale)\r
470 {\r
471     CFX_GraphStateData* pData = m_GraphState.GetModify();\r
472     pData->m_DashPhase = FXSYS_Mul(phase, scale);\r
473     pData->SetDashCount(pArray->GetCount());\r
474     for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {\r
475         pData->m_DashArray[i] = FXSYS_Mul(pArray->GetNumber(i), scale);\r
476     }\r
477 }\r
478 void CPDF_AllStates::ProcessExtGS(CPDF_Dictionary* pGS, CPDF_StreamContentParser* pParser)\r
479 {\r
480     CPDF_GeneralStateData* pGeneralState = m_GeneralState.GetModify();\r
481     FX_POSITION pos = pGS->GetStartPos();\r
482     while (pos) {\r
483         CFX_ByteString key_str;\r
484         CPDF_Object* pObject = pGS->GetNextElement(pos, key_str)->GetDirect();\r
485         if (pObject == NULL) {\r
486             continue;\r
487         }\r
488         FX_DWORD key = key_str.GetID();\r
489         switch (key) {\r
490             case FXBSTR_ID('L', 'W', 0, 0):\r
491                 m_GraphState.GetModify()->m_LineWidth = pObject->GetNumber();\r
492                 break;\r
493             case FXBSTR_ID('L', 'C', 0, 0):\r
494                 m_GraphState.GetModify()->m_LineCap = (CFX_GraphStateData::LineCap)pObject->GetInteger();\r
495                 break;\r
496             case FXBSTR_ID('L', 'J', 0, 0):\r
497                 m_GraphState.GetModify()->m_LineJoin = (CFX_GraphStateData::LineJoin)pObject->GetInteger();\r
498                 break;\r
499             case FXBSTR_ID('M', 'L', 0, 0):\r
500                 m_GraphState.GetModify()->m_MiterLimit = pObject->GetNumber();\r
501                 break;\r
502             case FXBSTR_ID('D', 0, 0, 0):       {\r
503                     if (pObject->GetType() != PDFOBJ_ARRAY) {\r
504                         break;\r
505                     }\r
506                     CPDF_Array* pDash = (CPDF_Array*)pObject;\r
507                     CPDF_Array* pArray = pDash->GetArray(0);\r
508                     if (pArray == NULL) {\r
509                         break;\r
510                     }\r
511                     SetLineDash(pArray, pDash->GetNumber(1), 1.0f);\r
512                     break;\r
513                 }\r
514             case FXBSTR_ID('R', 'I', 0, 0):\r
515                 m_GeneralState.SetRenderIntent(pObject->GetString());\r
516                 break;\r
517             case FXBSTR_ID('F', 'o', 'n', 't'): {\r
518                     if (pObject->GetType() != PDFOBJ_ARRAY) {\r
519                         break;\r
520                     }\r
521                     CPDF_Array* pFont = (CPDF_Array*)pObject;\r
522                     m_TextState.GetModify()->m_FontSize = pFont->GetNumber(1);\r
523                     m_TextState.SetFont(pParser->FindFont(pFont->GetString(0)));\r
524                     break;\r
525                 }\r
526             case FXBSTR_ID('T', 'R', 0, 0):\r
527                 if (pGS->KeyExist(FX_BSTRC("TR2"))) {\r
528                     continue;\r
529                 }\r
530             case FXBSTR_ID('T', 'R', '2', 0):\r
531                 if (pObject && pObject->GetType() != PDFOBJ_NAME) {\r
532                     pGeneralState->m_pTR = pObject;\r
533                 } else {\r
534                     pGeneralState->m_pTR = NULL;\r
535                 }\r
536                 break;\r
537             case FXBSTR_ID('B', 'M', 0, 0):     {\r
538                     CFX_ByteString mode;\r
539                     if (pObject->GetType() == PDFOBJ_ARRAY) {\r
540                         mode = ((CPDF_Array*)pObject)->GetString(0);\r
541                     } else {\r
542                         mode = pObject->GetString();\r
543                     }\r
544                     pGeneralState->SetBlendMode(mode);\r
545                     if (pGeneralState->m_BlendType > FXDIB_BLEND_MULTIPLY) {\r
546                         pParser->m_pObjectList->m_bBackgroundAlphaNeeded = TRUE;\r
547                     }\r
548                     break;\r
549                 }\r
550             case FXBSTR_ID('S', 'M', 'a', 's'):\r
551                 if (pObject && pObject->GetType() == PDFOBJ_DICTIONARY) {\r
552                     pGeneralState->m_pSoftMask = pObject;\r
553                     FXSYS_memcpy32(pGeneralState->m_SMaskMatrix, &pParser->m_pCurStates->m_CTM, sizeof(CPDF_Matrix));\r
554                 } else {\r
555                     pGeneralState->m_pSoftMask = NULL;\r
556                 }\r
557                 break;\r
558             case FXBSTR_ID('C', 'A', 0, 0):\r
559                 pGeneralState->m_StrokeAlpha = PDF_ClipFloat(pObject->GetNumber());\r
560                 break;\r
561             case FXBSTR_ID('c', 'a', 0, 0):\r
562                 pGeneralState->m_FillAlpha = PDF_ClipFloat(pObject->GetNumber());\r
563                 break;\r
564             case FXBSTR_ID('O', 'P', 0, 0):\r
565                 pGeneralState->m_StrokeOP = pObject->GetInteger();\r
566                 if (!pGS->KeyExist(FX_BSTRC("op"))) {\r
567                     pGeneralState->m_FillOP = pObject->GetInteger();\r
568                 }\r
569                 break;\r
570             case FXBSTR_ID('o', 'p', 0, 0):\r
571                 pGeneralState->m_FillOP = pObject->GetInteger();\r
572                 break;\r
573             case FXBSTR_ID('O', 'P', 'M', 0):\r
574                 pGeneralState->m_OPMode = pObject->GetInteger();\r
575                 break;\r
576             case FXBSTR_ID('B', 'G', 0, 0):\r
577                 if (pGS->KeyExist(FX_BSTRC("BG2"))) {\r
578                     continue;\r
579                 }\r
580             case FXBSTR_ID('B', 'G', '2', 0):\r
581                 pGeneralState->m_pBG = pObject;\r
582                 break;\r
583             case FXBSTR_ID('U', 'C', 'R', 0):\r
584                 if (pGS->KeyExist(FX_BSTRC("UCR2"))) {\r
585                     continue;\r
586                 }\r
587             case FXBSTR_ID('U', 'C', 'R', '2'):\r
588                 pGeneralState->m_pUCR = pObject;\r
589                 break;\r
590             case FXBSTR_ID('H', 'T', 0, 0):\r
591                 pGeneralState->m_pHT = pObject;\r
592                 break;\r
593             case FXBSTR_ID('F', 'L', 0, 0):\r
594                 pGeneralState->m_Flatness = pObject->GetNumber();\r
595                 break;\r
596             case FXBSTR_ID('S', 'M', 0, 0):\r
597                 pGeneralState->m_Smoothness = pObject->GetNumber();\r
598                 break;\r
599             case FXBSTR_ID('S', 'A', 0, 0):\r
600                 pGeneralState->m_StrokeAdjust = pObject->GetInteger();\r
601                 break;\r
602             case FXBSTR_ID('A', 'I', 'S', 0):\r
603                 pGeneralState->m_AlphaSource = pObject->GetInteger();\r
604                 break;\r
605             case FXBSTR_ID('T', 'K', 0, 0):\r
606                 pGeneralState->m_TextKnockout = pObject->GetInteger();\r
607                 break;\r
608         }\r
609     }\r
610     pGeneralState->m_Matrix = m_CTM;\r
611 }\r
612 CPDF_ContentMarkItem::CPDF_ContentMarkItem()\r
613 {\r
614     m_ParamType = None;\r
615 }\r
616 CPDF_ContentMarkItem::CPDF_ContentMarkItem(const CPDF_ContentMarkItem& src)\r
617 {\r
618     m_MarkName = src.m_MarkName;\r
619     m_ParamType = src.m_ParamType;\r
620     if (m_ParamType == DirectDict) {\r
621         m_pParam = ((CPDF_Dictionary*)src.m_pParam)->Clone();\r
622     } else {\r
623         m_pParam = src.m_pParam;\r
624     }\r
625 }\r
626 CPDF_ContentMarkItem::~CPDF_ContentMarkItem()\r
627 {\r
628     if (m_ParamType == DirectDict) {\r
629         ((CPDF_Dictionary*)m_pParam)->Release();\r
630     }\r
631 }\r
632 FX_BOOL CPDF_ContentMarkItem::HasMCID() const\r
633 {\r
634     if (m_pParam && (m_ParamType == DirectDict || m_ParamType == PropertiesDict)) {\r
635         return ((CPDF_Dictionary *)m_pParam)->KeyExist(FX_BSTRC("MCID"));\r
636     }\r
637     return FALSE;\r
638 }\r
639 CPDF_ContentMarkData::CPDF_ContentMarkData(const CPDF_ContentMarkData& src)\r
640 {\r
641     for (int i = 0; i < src.m_Marks.GetSize(); i ++) {\r
642         m_Marks.Add(src.m_Marks[i]);\r
643     }\r
644 }\r
645 int CPDF_ContentMarkData::GetMCID() const\r
646 {\r
647     CPDF_ContentMarkItem::ParamType type = CPDF_ContentMarkItem::None;\r
648     for (int i = 0; i < m_Marks.GetSize(); i ++) {\r
649         type = m_Marks[i].GetParamType();\r
650         if (type == CPDF_ContentMarkItem::PropertiesDict || type == CPDF_ContentMarkItem::DirectDict) {\r
651             CPDF_Dictionary *pDict = (CPDF_Dictionary *)m_Marks[i].GetParam();\r
652             if (pDict->KeyExist(FX_BSTRC("MCID"))) {\r
653                 return pDict->GetInteger(FX_BSTRC("MCID"));\r
654             }\r
655         }\r
656     }\r
657     return -1;\r
658 }\r
659 void CPDF_ContentMarkData::AddMark(const CFX_ByteString& name, CPDF_Dictionary* pDict, FX_BOOL bDirect)\r
660 {\r
661     CPDF_ContentMarkItem& item = m_Marks.Add();\r
662     item.SetName(name);\r
663     if (pDict == NULL) {\r
664         return;\r
665     }\r
666     item.SetParam(bDirect ? CPDF_ContentMarkItem::DirectDict : CPDF_ContentMarkItem::PropertiesDict,\r
667                   bDirect ? pDict->Clone() : pDict);\r
668 }\r
669 void CPDF_ContentMarkData::DeleteLastMark()\r
670 {\r
671     int size = m_Marks.GetSize();\r
672     if (size == 0) {\r
673         return;\r
674     }\r
675     m_Marks.RemoveAt(size - 1);\r
676 }\r
677 FX_BOOL CPDF_ContentMark::HasMark(FX_BSTR mark) const\r
678 {\r
679     if (m_pObject == NULL) {\r
680         return FALSE;\r
681     }\r
682     for (int i = 0; i < m_pObject->CountItems(); i ++) {\r
683         CPDF_ContentMarkItem& item = m_pObject->GetItem(i);\r
684         if (item.GetName() == mark) {\r
685             return TRUE;\r
686         }\r
687     }\r
688     return FALSE;\r
689 }\r
690 FX_BOOL CPDF_ContentMark::LookupMark(FX_BSTR mark, CPDF_Dictionary*& pDict) const\r
691 {\r
692     if (m_pObject == NULL) {\r
693         return FALSE;\r
694     }\r
695     for (int i = 0; i < m_pObject->CountItems(); i ++) {\r
696         CPDF_ContentMarkItem& item = m_pObject->GetItem(i);\r
697         if (item.GetName() == mark) {\r
698             pDict = NULL;\r
699             if (item.GetParamType() == CPDF_ContentMarkItem::PropertiesDict ||\r
700                     item.GetParamType() == CPDF_ContentMarkItem::DirectDict) {\r
701                 pDict = (CPDF_Dictionary*)item.GetParam();\r
702             }\r
703             return TRUE;\r
704         }\r
705     }\r
706     return FALSE;\r
707 }\r