1 // Copyright 2016 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/page/cpdf_allstates.h"
8
9 #include <algorithm>
10
11 #include "core/fpdfapi/page/cpdf_pageobjectholder.h"
12 #include "core/fpdfapi/page/cpdf_streamcontentparser.h"
13 #include "core/fpdfapi/parser/cpdf_array.h"
14 #include "core/fpdfapi/parser/cpdf_dictionary.h"
15 #include "core/fxge/cfx_graphstatedata.h"
16 #include "third_party/base/stl_util.h"
17
CPDF_AllStates()18 CPDF_AllStates::CPDF_AllStates()
19 : m_TextLeading(0), m_TextRise(0), m_TextHorzScale(1.0f) {}
20
~CPDF_AllStates()21 CPDF_AllStates::~CPDF_AllStates() {}
22
Copy(const CPDF_AllStates & src)23 void CPDF_AllStates::Copy(const CPDF_AllStates& src) {
24 CopyStates(src);
25 m_TextMatrix = src.m_TextMatrix;
26 m_ParentMatrix = src.m_ParentMatrix;
27 m_CTM = src.m_CTM;
28 m_TextPos = src.m_TextPos;
29 m_TextLinePos = src.m_TextLinePos;
30 m_TextLeading = src.m_TextLeading;
31 m_TextRise = src.m_TextRise;
32 m_TextHorzScale = src.m_TextHorzScale;
33 }
34
SetLineDash(CPDF_Array * pArray,float phase,float scale)35 void CPDF_AllStates::SetLineDash(CPDF_Array* pArray, float phase, float scale) {
36 m_GraphState.SetLineDash(pArray, phase, scale);
37 }
38
ProcessExtGS(CPDF_Dictionary * pGS,CPDF_StreamContentParser * pParser)39 void CPDF_AllStates::ProcessExtGS(CPDF_Dictionary* pGS,
40 CPDF_StreamContentParser* pParser) {
41 for (const auto& it : *pGS) {
42 const ByteString& key_str = it.first;
43 CPDF_Object* pElement = it.second.get();
44 CPDF_Object* pObject = pElement ? pElement->GetDirect() : nullptr;
45 if (!pObject)
46 continue;
47
48 uint32_t key = key_str.GetID();
49 switch (key) {
50 case FXBSTR_ID('L', 'W', 0, 0):
51 m_GraphState.SetLineWidth(pObject->GetNumber());
52 break;
53 case FXBSTR_ID('L', 'C', 0, 0):
54 m_GraphState.SetLineCap(
55 static_cast<CFX_GraphStateData::LineCap>(pObject->GetInteger()));
56 break;
57 case FXBSTR_ID('L', 'J', 0, 0):
58 m_GraphState.SetLineJoin(
59 static_cast<CFX_GraphStateData::LineJoin>(pObject->GetInteger()));
60 break;
61 case FXBSTR_ID('M', 'L', 0, 0):
62 m_GraphState.SetMiterLimit(pObject->GetNumber());
63 break;
64 case FXBSTR_ID('D', 0, 0, 0): {
65 CPDF_Array* pDash = pObject->AsArray();
66 if (!pDash)
67 break;
68
69 CPDF_Array* pArray = pDash->GetArrayAt(0);
70 if (!pArray)
71 break;
72
73 SetLineDash(pArray, pDash->GetNumberAt(1), 1.0f);
74 break;
75 }
76 case FXBSTR_ID('R', 'I', 0, 0):
77 m_GeneralState.SetRenderIntent(pObject->GetString());
78 break;
79 case FXBSTR_ID('F', 'o', 'n', 't'): {
80 CPDF_Array* pFont = pObject->AsArray();
81 if (!pFont)
82 break;
83
84 m_TextState.SetFontSize(pFont->GetNumberAt(1));
85 m_TextState.SetFont(pParser->FindFont(pFont->GetStringAt(0)));
86 break;
87 }
88 case FXBSTR_ID('T', 'R', 0, 0):
89 if (pGS->KeyExist("TR2")) {
90 continue;
91 }
92 case FXBSTR_ID('T', 'R', '2', 0):
93 m_GeneralState.SetTR(pObject && !pObject->IsName() ? pObject : nullptr);
94 break;
95 case FXBSTR_ID('B', 'M', 0, 0): {
96 CPDF_Array* pArray = pObject->AsArray();
97 m_GeneralState.SetBlendMode(pArray ? pArray->GetStringAt(0)
98 : pObject->GetString());
99 if (m_GeneralState.GetBlendType() > FXDIB_BLEND_MULTIPLY)
100 pParser->GetPageObjectHolder()->SetBackgroundAlphaNeeded(true);
101 break;
102 }
103 case FXBSTR_ID('S', 'M', 'a', 's'):
104 if (ToDictionary(pObject)) {
105 m_GeneralState.SetSoftMask(pObject);
106 m_GeneralState.SetSMaskMatrix(pParser->GetCurStates()->m_CTM);
107 } else {
108 m_GeneralState.SetSoftMask(nullptr);
109 }
110 break;
111 case FXBSTR_ID('C', 'A', 0, 0):
112 m_GeneralState.SetStrokeAlpha(
113 pdfium::clamp(pObject->GetNumber(), 0.0f, 1.0f));
114 break;
115 case FXBSTR_ID('c', 'a', 0, 0):
116 m_GeneralState.SetFillAlpha(
117 pdfium::clamp(pObject->GetNumber(), 0.0f, 1.0f));
118 break;
119 case FXBSTR_ID('O', 'P', 0, 0):
120 m_GeneralState.SetStrokeOP(!!pObject->GetInteger());
121 if (!pGS->KeyExist("op"))
122 m_GeneralState.SetFillOP(!!pObject->GetInteger());
123 break;
124 case FXBSTR_ID('o', 'p', 0, 0):
125 m_GeneralState.SetFillOP(!!pObject->GetInteger());
126 break;
127 case FXBSTR_ID('O', 'P', 'M', 0):
128 m_GeneralState.SetOPMode(pObject->GetInteger());
129 break;
130 case FXBSTR_ID('B', 'G', 0, 0):
131 if (pGS->KeyExist("BG2")) {
132 continue;
133 }
134 case FXBSTR_ID('B', 'G', '2', 0):
135 m_GeneralState.SetBG(pObject);
136 break;
137 case FXBSTR_ID('U', 'C', 'R', 0):
138 if (pGS->KeyExist("UCR2")) {
139 continue;
140 }
141 case FXBSTR_ID('U', 'C', 'R', '2'):
142 m_GeneralState.SetUCR(pObject);
143 break;
144 case FXBSTR_ID('H', 'T', 0, 0):
145 m_GeneralState.SetHT(pObject);
146 break;
147 case FXBSTR_ID('F', 'L', 0, 0):
148 m_GeneralState.SetFlatness(pObject->GetNumber());
149 break;
150 case FXBSTR_ID('S', 'M', 0, 0):
151 m_GeneralState.SetSmoothness(pObject->GetNumber());
152 break;
153 case FXBSTR_ID('S', 'A', 0, 0):
154 m_GeneralState.SetStrokeAdjust(!!pObject->GetInteger());
155 break;
156 case FXBSTR_ID('A', 'I', 'S', 0):
157 m_GeneralState.SetAlphaSource(!!pObject->GetInteger());
158 break;
159 case FXBSTR_ID('T', 'K', 0, 0):
160 m_GeneralState.SetTextKnockout(!!pObject->GetInteger());
161 break;
162 }
163 }
164 m_GeneralState.SetMatrix(m_CTM);
165 }
166