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