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