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