• 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_transferfuncdib.h"
8 
9 #include <utility>
10 
11 #include "build/build_config.h"
12 #include "core/fpdfapi/page/cpdf_transferfunc.h"
13 #include "core/fxcrt/check.h"
14 #include "core/fxcrt/zip.h"
15 #include "core/fxge/calculate_pitch.h"
16 
17 #if defined(PDF_USE_SKIA)
18 #include "core/fxcrt/notreached.h"
19 #endif
20 
21 namespace {
22 
MakePlatformRGBStruct(uint8_t red,uint8_t green,uint8_t blue)23 CFX_DIBBase::kPlatformRGBStruct MakePlatformRGBStruct(uint8_t red,
24                                                       uint8_t green,
25                                                       uint8_t blue) {
26   // Note that the return value may have an alpha value that will be set to 0.
27   return {
28       .blue = blue,
29       .green = green,
30       .red = red,
31   };
32 }
33 
34 }  // namespace
35 
CPDF_TransferFuncDIB(RetainPtr<const CFX_DIBBase> src,RetainPtr<CPDF_TransferFunc> transfer_func)36 CPDF_TransferFuncDIB::CPDF_TransferFuncDIB(
37     RetainPtr<const CFX_DIBBase> src,
38     RetainPtr<CPDF_TransferFunc> transfer_func)
39     : src_(std::move(src)),
40       transfer_func_(std::move(transfer_func)),
41       r_samples_(transfer_func_->GetSamplesR()),
42       g_samples_(transfer_func_->GetSamplesG()),
43       b_samples_(transfer_func_->GetSamplesB()) {
44   SetWidth(src_->GetWidth());
45   SetHeight(src_->GetHeight());
46   SetFormat(GetDestFormat());
47   SetPitch(fxge::CalculatePitch32OrDie(GetBPP(), GetWidth()));
48   scanline_.resize(GetPitch());
49   CHECK(!HasPalette());
50 }
51 
52 CPDF_TransferFuncDIB::~CPDF_TransferFuncDIB() = default;
53 
GetDestFormat() const54 FXDIB_Format CPDF_TransferFuncDIB::GetDestFormat() const {
55   if (src_->IsMaskFormat()) {
56     return FXDIB_Format::k8bppMask;
57   }
58 
59   if (src_->IsAlphaFormat()) {
60     // TODO(crbug.com/355676038): Consider adding support for
61     // `FXDIB_Format::kBgraPremul`
62     return FXDIB_Format::kBgra;
63   }
64 
65   return CFX_DIBBase::kPlatformRGBFormat;
66 }
67 
TranslateScanline(pdfium::span<const uint8_t> src_span) const68 void CPDF_TransferFuncDIB::TranslateScanline(
69     pdfium::span<const uint8_t> src_span) const {
70   auto scanline_span = pdfium::make_span(scanline_);
71   switch (src_->GetFormat()) {
72     case FXDIB_Format::kInvalid: {
73       break;
74     }
75     case FXDIB_Format::k1bppRgb: {
76       const auto color0 =
77           MakePlatformRGBStruct(r_samples_[0], g_samples_[0], b_samples_[0]);
78       const auto color1 = MakePlatformRGBStruct(
79           r_samples_[255], g_samples_[255], b_samples_[255]);
80       auto dest = fxcrt::reinterpret_span<kPlatformRGBStruct>(scanline_span);
81       for (int i = 0; i < GetWidth(); i++) {
82         const bool is_on = (src_span[i / 8] & (1 << (7 - i % 8)));
83         dest[i] = is_on ? color1 : color0;
84       }
85       break;
86     }
87     case FXDIB_Format::k1bppMask: {
88       const int m0 = r_samples_[0];
89       const int m1 = r_samples_[255];
90       for (int i = 0; i < GetWidth(); i++) {
91         const bool is_on = (src_span[i / 8] & (1 << (7 - i % 8)));
92         scanline_[i] = is_on ? m1 : m0;
93       }
94       break;
95     }
96     case FXDIB_Format::k8bppRgb: {
97       pdfium::span<const uint32_t> src_palette = src_->GetPaletteSpan();
98       auto dest = fxcrt::reinterpret_span<kPlatformRGBStruct>(scanline_span);
99       auto zip = fxcrt::Zip(src_span.first(GetWidth()), dest);
100       if (src_->HasPalette()) {
101         for (auto [input, output] : zip) {
102           const FX_ARGB src_argb = src_palette[input];
103           output = MakePlatformRGBStruct(r_samples_[FXARGB_B(src_argb)],
104                                          g_samples_[FXARGB_G(src_argb)],
105                                          b_samples_[FXARGB_R(src_argb)]);
106         }
107       } else {
108         for (auto [input, output] : zip) {
109           output = MakePlatformRGBStruct(r_samples_[input], g_samples_[input],
110                                          b_samples_[input]);
111         }
112       }
113       break;
114     }
115     case FXDIB_Format::k8bppMask: {
116       for (auto [input, output] :
117            fxcrt::Zip(src_span.first(GetWidth()), scanline_span)) {
118         output = r_samples_[input];
119       }
120       break;
121     }
122     case FXDIB_Format::kBgr: {
123       auto src =
124           fxcrt::reinterpret_span<const FX_BGR_STRUCT<uint8_t>>(src_span);
125       auto dest = fxcrt::reinterpret_span<kPlatformRGBStruct>(scanline_span);
126       for (auto [input, output] : fxcrt::Zip(src.first(GetWidth()), dest)) {
127         output = MakePlatformRGBStruct(r_samples_[input.red],
128                                        g_samples_[input.green],
129                                        b_samples_[input.blue]);
130       }
131       break;
132     }
133     case FXDIB_Format::kBgrx: {
134       auto src =
135           fxcrt::reinterpret_span<const FX_BGRA_STRUCT<uint8_t>>(src_span);
136       auto dest = fxcrt::reinterpret_span<kPlatformRGBStruct>(scanline_span);
137       for (auto [input, output] : fxcrt::Zip(src.first(GetWidth()), dest)) {
138         output = MakePlatformRGBStruct(r_samples_[input.red],
139                                        g_samples_[input.green],
140                                        b_samples_[input.blue]);
141       }
142       break;
143     }
144     case FXDIB_Format::kBgra: {
145       auto src =
146           fxcrt::reinterpret_span<const FX_BGRA_STRUCT<uint8_t>>(src_span);
147       auto dest =
148           fxcrt::reinterpret_span<FX_BGRA_STRUCT<uint8_t>>(scanline_span);
149       for (auto [input, output] : fxcrt::Zip(src.first(GetWidth()), dest)) {
150         output = {
151             .blue = b_samples_[input.blue],
152             .green = g_samples_[input.green],
153             .red = r_samples_[input.red],
154             .alpha = input.alpha,
155         };
156       }
157       break;
158     }
159 #if defined(PDF_USE_SKIA)
160     case FXDIB_Format::kBgraPremul: {
161       // TODO(crbug.com/355676038): Consider adding support for
162       // `FXDIB_Format::kBgraPremul`
163       NOTREACHED_NORETURN();
164     }
165 #endif
166   }
167 }
168 
GetScanline(int line) const169 pdfium::span<const uint8_t> CPDF_TransferFuncDIB::GetScanline(int line) const {
170   TranslateScanline(src_->GetScanline(line));
171   return scanline_;
172 }
173