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/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/fxge/cfx_color.h"
15 #include "third_party/base/notreached.h"
16
17 namespace {
18
19 // Find the token and its |nParams| parameters from the start of data,
20 // and move the current position to the start of those parameters.
FindTagParamFromStart(CPDF_SimpleParser * parser,ByteStringView token,int nParams)21 bool FindTagParamFromStart(CPDF_SimpleParser* parser,
22 ByteStringView token,
23 int nParams) {
24 nParams++;
25
26 std::vector<uint32_t> pBuf(nParams);
27 int buf_index = 0;
28 int buf_count = 0;
29
30 parser->SetCurPos(0);
31 while (1) {
32 pBuf[buf_index++] = parser->GetCurPos();
33 if (buf_index == nParams)
34 buf_index = 0;
35
36 buf_count++;
37 if (buf_count > nParams)
38 buf_count = nParams;
39
40 ByteStringView word = parser->GetWord();
41 if (word.IsEmpty())
42 return false;
43
44 if (word == token) {
45 if (buf_count < nParams)
46 continue;
47
48 parser->SetCurPos(pBuf[buf_index]);
49 return true;
50 }
51 }
52 return false;
53 }
54
55 } // namespace
56
GetFont(float * fFontSize)57 Optional<ByteString> CPDF_DefaultAppearance::GetFont(float* fFontSize) {
58 *fFontSize = 0.0f;
59 if (m_csDA.IsEmpty())
60 return {};
61
62 ByteString csFontNameTag;
63 CPDF_SimpleParser syntax(m_csDA.AsStringView().raw_span());
64 if (FindTagParamFromStart(&syntax, "Tf", 2)) {
65 csFontNameTag = ByteString(syntax.GetWord());
66 csFontNameTag.Delete(0, 1);
67 *fFontSize = StringToFloat(syntax.GetWord());
68 }
69 return {PDF_NameDecode(csFontNameTag.AsStringView())};
70 }
71
GetColor(float fc[4])72 Optional<CFX_Color::Type> CPDF_DefaultAppearance::GetColor(float fc[4]) {
73 for (int c = 0; c < 4; c++)
74 fc[c] = 0;
75
76 if (m_csDA.IsEmpty())
77 return {};
78
79 CPDF_SimpleParser syntax(m_csDA.AsStringView().raw_span());
80 if (FindTagParamFromStart(&syntax, "g", 1)) {
81 fc[0] = StringToFloat(syntax.GetWord());
82 return {CFX_Color::kGray};
83 }
84 if (FindTagParamFromStart(&syntax, "rg", 3)) {
85 fc[0] = StringToFloat(syntax.GetWord());
86 fc[1] = StringToFloat(syntax.GetWord());
87 fc[2] = StringToFloat(syntax.GetWord());
88 return {CFX_Color::kRGB};
89 }
90 if (FindTagParamFromStart(&syntax, "k", 4)) {
91 fc[0] = StringToFloat(syntax.GetWord());
92 fc[1] = StringToFloat(syntax.GetWord());
93 fc[2] = StringToFloat(syntax.GetWord());
94 fc[3] = StringToFloat(syntax.GetWord());
95 return {CFX_Color::kCMYK};
96 }
97
98 return {};
99 }
100
101 std::pair<Optional<CFX_Color::Type>, FX_ARGB>
GetColor()102 CPDF_DefaultAppearance::GetColor() {
103 float values[4];
104 Optional<CFX_Color::Type> type = GetColor(values);
105 if (!type)
106 return {type, 0};
107
108 if (*type == CFX_Color::kGray) {
109 int g = static_cast<int>(values[0] * 255 + 0.5f);
110 return {type, ArgbEncode(255, g, g, g)};
111 }
112 if (*type == CFX_Color::kRGB) {
113 int r = static_cast<int>(values[0] * 255 + 0.5f);
114 int g = static_cast<int>(values[1] * 255 + 0.5f);
115 int b = static_cast<int>(values[2] * 255 + 0.5f);
116 return {type, ArgbEncode(255, r, g, b)};
117 }
118 if (*type == CFX_Color::kCMYK) {
119 float r = 1.0f - std::min(1.0f, values[0] + values[3]);
120 float g = 1.0f - std::min(1.0f, values[1] + values[3]);
121 float b = 1.0f - std::min(1.0f, values[2] + values[3]);
122 return {type, ArgbEncode(255, static_cast<int>(r * 255 + 0.5f),
123 static_cast<int>(g * 255 + 0.5f),
124 static_cast<int>(b * 255 + 0.5f))};
125 }
126 NOTREACHED();
127 return {{}, 0};
128 }
129
FindTagParamFromStartForTesting(CPDF_SimpleParser * parser,ByteStringView token,int nParams)130 bool CPDF_DefaultAppearance::FindTagParamFromStartForTesting(
131 CPDF_SimpleParser* parser,
132 ByteStringView token,
133 int nParams) {
134 return FindTagParamFromStart(parser, token, nParams);
135 }
136