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