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