xref: /aosp_15_r20/external/pdfium/core/fpdfdoc/cpdf_defaultappearance.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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   CPDF_SimpleParser syntax(m_csDA.AsStringView().raw_span());
88   if (FindTagParamFromStart(&syntax, "g", 1)) {
89     float gray = StringToFloat(syntax.GetWord());
90     return CFX_Color(CFX_Color::Type::kGray, gray);
91   }
92   if (FindTagParamFromStart(&syntax, "rg", 3)) {
93     float r = StringToFloat(syntax.GetWord());
94     float g = StringToFloat(syntax.GetWord());
95     float b = StringToFloat(syntax.GetWord());
96     return CFX_Color(CFX_Color::Type::kRGB, r, g, b);
97   }
98   if (FindTagParamFromStart(&syntax, "k", 4)) {
99     float c = StringToFloat(syntax.GetWord());
100     float m = StringToFloat(syntax.GetWord());
101     float y = StringToFloat(syntax.GetWord());
102     float k = StringToFloat(syntax.GetWord());
103     return CFX_Color(CFX_Color::Type::kCMYK, c, m, y, k);
104   }
105   return absl::nullopt;
106 }
107 
GetColorARGB() const108 absl::optional<CFX_Color::TypeAndARGB> CPDF_DefaultAppearance::GetColorARGB()
109     const {
110   absl::optional<CFX_Color> maybe_color = GetColor();
111   if (!maybe_color.has_value())
112     return absl::nullopt;
113 
114   const CFX_Color& color = maybe_color.value();
115   if (color.nColorType == CFX_Color::Type::kGray) {
116     int g = static_cast<int>(color.fColor1 * 255 + 0.5f);
117     return CFX_Color::TypeAndARGB(CFX_Color::Type::kGray,
118                                   ArgbEncode(255, g, g, g));
119   }
120   if (color.nColorType == CFX_Color::Type::kRGB) {
121     int r = static_cast<int>(color.fColor1 * 255 + 0.5f);
122     int g = static_cast<int>(color.fColor2 * 255 + 0.5f);
123     int b = static_cast<int>(color.fColor3 * 255 + 0.5f);
124     return CFX_Color::TypeAndARGB(CFX_Color::Type::kRGB,
125                                   ArgbEncode(255, r, g, b));
126   }
127   if (color.nColorType == CFX_Color::Type::kCMYK) {
128     float r = 1.0f - std::min(1.0f, color.fColor1 + color.fColor4);
129     float g = 1.0f - std::min(1.0f, color.fColor2 + color.fColor4);
130     float b = 1.0f - std::min(1.0f, color.fColor3 + color.fColor4);
131     return CFX_Color::TypeAndARGB(
132         CFX_Color::Type::kCMYK,
133         ArgbEncode(255, static_cast<int>(r * 255 + 0.5f),
134                    static_cast<int>(g * 255 + 0.5f),
135                    static_cast<int>(b * 255 + 0.5f)));
136   }
137   NOTREACHED_NORETURN();
138 }
139 
140 // static
FindTagParamFromStartForTesting(CPDF_SimpleParser * parser,ByteStringView token,int nParams)141 bool CPDF_DefaultAppearance::FindTagParamFromStartForTesting(
142     CPDF_SimpleParser* parser,
143     ByteStringView token,
144     int nParams) {
145   return FindTagParamFromStart(parser, token, nParams);
146 }
147