• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/fpdfapi/page/cpdf_color.h"
8 
9 #include <optional>
10 #include <utility>
11 
12 #include "core/fpdfapi/page/cpdf_patterncs.h"
13 #include "core/fxcrt/check.h"
14 #include "core/fxcrt/check_op.h"
15 
16 CPDF_Color::CPDF_Color() = default;
17 
CPDF_Color(const CPDF_Color & that)18 CPDF_Color::CPDF_Color(const CPDF_Color& that) {
19   *this = that;
20 }
21 
22 CPDF_Color::~CPDF_Color() = default;
23 
IsNull() const24 bool CPDF_Color::IsNull() const {
25   return absl::holds_alternative<absl::monostate>(color_data_);
26 }
27 
IsPattern() const28 bool CPDF_Color::IsPattern() const {
29   return cs_ && IsPatternInternal();
30 }
31 
IsPatternInternal() const32 bool CPDF_Color::IsPatternInternal() const {
33   return cs_->GetFamily() == CPDF_ColorSpace::Family::kPattern;
34 }
35 
SetColorSpace(RetainPtr<CPDF_ColorSpace> colorspace)36 void CPDF_Color::SetColorSpace(RetainPtr<CPDF_ColorSpace> colorspace) {
37   cs_ = std::move(colorspace);
38   if (IsPatternInternal()) {
39     color_data_ = std::make_unique<PatternValue>();
40   } else {
41     color_data_ = cs_->CreateBufAndSetDefaultColor();
42   }
43 }
44 
SetValueForNonPattern(std::vector<float> values)45 void CPDF_Color::SetValueForNonPattern(std::vector<float> values) {
46   CHECK(!IsPatternInternal());
47   CHECK_LE(cs_->ComponentCount(), values.size());
48   color_data_ = std::move(values);
49 }
50 
SetValueForPattern(RetainPtr<CPDF_Pattern> pattern,pdfium::span<float> values)51 void CPDF_Color::SetValueForPattern(RetainPtr<CPDF_Pattern> pattern,
52                                     pdfium::span<float> values) {
53   if (values.size() > kMaxPatternColorComps) {
54     return;
55   }
56 
57   if (!IsPattern()) {
58     SetColorSpace(
59         CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kPattern));
60   }
61 
62   auto& pattern_value = absl::get<std::unique_ptr<PatternValue>>(color_data_);
63   pattern_value->SetPattern(std::move(pattern));
64   pattern_value->SetComps(values);
65 }
66 
operator =(const CPDF_Color & that)67 CPDF_Color& CPDF_Color::operator=(const CPDF_Color& that) {
68   if (this == &that) {
69     return *this;
70   }
71 
72   cs_ = that.cs_;
73 
74   if (absl::holds_alternative<std::vector<float>>(that.color_data_)) {
75     color_data_ = absl::get<std::vector<float>>(that.color_data_);
76   } else if (absl::holds_alternative<std::unique_ptr<PatternValue>>(
77                  that.color_data_)) {
78     auto& pattern_value =
79         absl::get<std::unique_ptr<PatternValue>>(that.color_data_);
80     color_data_ = std::make_unique<PatternValue>(*pattern_value);
81   } else {
82     color_data_ = absl::monostate();
83   }
84 
85   return *this;
86 }
87 
ComponentCount() const88 uint32_t CPDF_Color::ComponentCount() const {
89   return cs_->ComponentCount();
90 }
91 
IsColorSpaceRGB() const92 bool CPDF_Color::IsColorSpaceRGB() const {
93   return cs_ ==
94          CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceRGB);
95 }
96 
IsColorSpaceGray() const97 bool CPDF_Color::IsColorSpaceGray() const {
98   return cs_ ==
99          CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceGray);
100 }
101 
GetColorRef() const102 std::optional<FX_COLORREF> CPDF_Color::GetColorRef() const {
103   std::optional<FX_RGB_STRUCT<float>> maybe_rgb = GetRGB();
104   if (!maybe_rgb.has_value()) {
105     return std::nullopt;
106   }
107 
108   const float r = std::clamp(maybe_rgb.value().red, 0.0f, 1.0f);
109   const float g = std::clamp(maybe_rgb.value().green, 0.0f, 1.0f);
110   const float b = std::clamp(maybe_rgb.value().blue, 0.0f, 1.0f);
111   return FXSYS_BGR(FXSYS_roundf(b * 255.0f), FXSYS_roundf(g * 255.0f),
112                    FXSYS_roundf(r * 255.0f));
113 }
114 
GetRGB() const115 std::optional<FX_RGB_STRUCT<float>> CPDF_Color::GetRGB() const {
116   if (IsPatternInternal()) {
117     if (absl::holds_alternative<std::unique_ptr<PatternValue>>(color_data_)) {
118       const auto& pattern_value =
119           absl::get<std::unique_ptr<PatternValue>>(color_data_);
120       return cs_->AsPatternCS()->GetPatternRGB(*pattern_value);
121     }
122   } else {
123     if (absl::holds_alternative<std::vector<float>>(color_data_)) {
124       const auto& buffer = absl::get<std::vector<float>>(color_data_);
125       return cs_->GetRGB(buffer);
126     }
127   }
128   return std::nullopt;
129 }
130 
GetPattern() const131 RetainPtr<CPDF_Pattern> CPDF_Color::GetPattern() const {
132   DCHECK(IsPattern());
133 
134   const auto& pattern_value =
135       absl::get<std::unique_ptr<PatternValue>>(color_data_);
136   return pattern_value->GetPattern();
137 }
138