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