1 // Copyright 2016 The PDFium Authors
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/fpdfdoc/cpdf_defaultappearance.h"
8
9 #include <algorithm>
10 #include <vector>
11
12 #include "core/fpdfapi/parser/cpdf_simple_parser.h"
13 #include "core/fpdfapi/parser/fpdf_parser_utility.h"
14 #include "core/fxcrt/fx_string.h"
15 #include "core/fxge/cfx_color.h"
16 #include "third_party/base/notreached.h"
17
18 namespace {
19
20 // Find the token and its |nParams| parameters from the start of data,
21 // and move the current position to the start of those parameters.
FindTagParamFromStart(CPDF_SimpleParser * parser,ByteStringView token,int nParams)22 bool FindTagParamFromStart(CPDF_SimpleParser* parser,
23 ByteStringView token,
24 int nParams) {
25 nParams++;
26
27 std::vector<uint32_t> pBuf(nParams);
28 int buf_index = 0;
29 int buf_count = 0;
30
31 parser->SetCurPos(0);
32 while (true) {
33 pBuf[buf_index++] = parser->GetCurPos();
34 if (buf_index == nParams)
35 buf_index = 0;
36
37 buf_count++;
38 if (buf_count > nParams)
39 buf_count = nParams;
40
41 ByteStringView word = parser->GetWord();
42 if (word.IsEmpty())
43 return false;
44
45 if (word == token) {
46 if (buf_count < nParams)
47 continue;
48
49 parser->SetCurPos(pBuf[buf_index]);
50 return true;
51 }
52 }
53 }
54
55 } // namespace
56
57 CPDF_DefaultAppearance::CPDF_DefaultAppearance() = default;
58
CPDF_DefaultAppearance(const ByteString & csDA)59 CPDF_DefaultAppearance::CPDF_DefaultAppearance(const ByteString& csDA)
60 : m_csDA(csDA) {}
61
62 CPDF_DefaultAppearance::CPDF_DefaultAppearance(
63 const CPDF_DefaultAppearance& cDA) = default;
64
65 CPDF_DefaultAppearance::~CPDF_DefaultAppearance() = default;
66
GetFont(float * fFontSize) const67 absl::optional<ByteString> CPDF_DefaultAppearance::GetFont(
68 float* fFontSize) const {
69 *fFontSize = 0.0f;
70 if (m_csDA.IsEmpty())
71 return absl::nullopt;
72
73 ByteString csFontNameTag;
74 CPDF_SimpleParser syntax(m_csDA.AsStringView().raw_span());
75 if (FindTagParamFromStart(&syntax, "Tf", 2)) {
76 csFontNameTag = ByteString(syntax.GetWord());
77 csFontNameTag.Delete(0, 1);
78 *fFontSize = StringToFloat(syntax.GetWord());
79 }
80 return PDF_NameDecode(csFontNameTag.AsStringView());
81 }
82
GetColor() const83 absl::optional<CFX_Color> CPDF_DefaultAppearance::GetColor() const {
84 if (m_csDA.IsEmpty())
85 return absl::nullopt;
86
87 float fc[4];
88 CPDF_SimpleParser syntax(m_csDA.AsStringView().raw_span());
89 if (FindTagParamFromStart(&syntax, "g", 1)) {
90 fc[0] = StringToFloat(syntax.GetWord());
91 return CFX_Color(CFX_Color::Type::kGray, fc[0]);
92 }
93 if (FindTagParamFromStart(&syntax, "rg", 3)) {
94 fc[0] = StringToFloat(syntax.GetWord());
95 fc[1] = StringToFloat(syntax.GetWord());
96 fc[2] = StringToFloat(syntax.GetWord());
97 return CFX_Color(CFX_Color::Type::kRGB, fc[0], fc[1], fc[2]);
98 }
99 if (FindTagParamFromStart(&syntax, "k", 4)) {
100 fc[0] = StringToFloat(syntax.GetWord());
101 fc[1] = StringToFloat(syntax.GetWord());
102 fc[2] = StringToFloat(syntax.GetWord());
103 fc[3] = StringToFloat(syntax.GetWord());
104 return CFX_Color(CFX_Color::Type::kCMYK, fc[0], fc[1], fc[2], fc[3]);
105 }
106 return absl::nullopt;
107 }
108
GetColorARGB() const109 absl::optional<CFX_Color::TypeAndARGB> CPDF_DefaultAppearance::GetColorARGB()
110 const {
111 absl::optional<CFX_Color> maybe_color = GetColor();
112 if (!maybe_color.has_value())
113 return absl::nullopt;
114
115 const CFX_Color& color = maybe_color.value();
116 if (color.nColorType == CFX_Color::Type::kGray) {
117 int g = static_cast<int>(color.fColor1 * 255 + 0.5f);
118 return CFX_Color::TypeAndARGB(CFX_Color::Type::kGray,
119 ArgbEncode(255, g, g, g));
120 }
121 if (color.nColorType == CFX_Color::Type::kRGB) {
122 int r = static_cast<int>(color.fColor1 * 255 + 0.5f);
123 int g = static_cast<int>(color.fColor2 * 255 + 0.5f);
124 int b = static_cast<int>(color.fColor3 * 255 + 0.5f);
125 return CFX_Color::TypeAndARGB(CFX_Color::Type::kRGB,
126 ArgbEncode(255, r, g, b));
127 }
128 if (color.nColorType == CFX_Color::Type::kCMYK) {
129 float r = 1.0f - std::min(1.0f, color.fColor1 + color.fColor4);
130 float g = 1.0f - std::min(1.0f, color.fColor2 + color.fColor4);
131 float b = 1.0f - std::min(1.0f, color.fColor3 + color.fColor4);
132 return CFX_Color::TypeAndARGB(
133 CFX_Color::Type::kCMYK,
134 ArgbEncode(255, static_cast<int>(r * 255 + 0.5f),
135 static_cast<int>(g * 255 + 0.5f),
136 static_cast<int>(b * 255 + 0.5f)));
137 }
138 NOTREACHED();
139 return absl::nullopt;
140 }
141
142 // static
FindTagParamFromStartForTesting(CPDF_SimpleParser * parser,ByteStringView token,int nParams)143 bool CPDF_DefaultAppearance::FindTagParamFromStartForTesting(
144 CPDF_SimpleParser* parser,
145 ByteStringView token,
146 int nParams) {
147 return FindTagParamFromStart(parser, token, nParams);
148 }
149