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