Remove out parameters from CPDF_ColorSpace::GetRGB().
Use std::optional<> to convey failure. This may avoid potentially
uninit variables.
-- introduce GetRGBOrZerosOnError() helper method.
Change-Id: I9aaa33fe0945ac0d08baaa5bd8c461852dd61b4c
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/120497
Reviewed-by: Thomas Sepez <tsepez@google.com>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_colorspace.cpp b/core/fpdfapi/page/cpdf_colorspace.cpp
index fab3fab..d9eb5ab 100644
--- a/core/fpdfapi/page/cpdf_colorspace.cpp
+++ b/core/fpdfapi/page/cpdf_colorspace.cpp
@@ -125,10 +125,8 @@
~CPDF_CalGray() override;
// CPDF_ColorSpace:
- bool GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const override;
+ std::optional<FX_RGB_STRUCT<float>> GetRGB(
+ pdfium::span<const float> pBuf) const override;
uint32_t v_Load(CPDF_Document* pDoc,
const CPDF_Array* pArray,
std::set<const CPDF_Object*>* pVisited) override;
@@ -155,10 +153,8 @@
~CPDF_CalRGB() override;
// CPDF_ColorSpace:
- bool GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const override;
+ std::optional<FX_RGB_STRUCT<float>> GetRGB(
+ pdfium::span<const float> pBuf) const override;
void TranslateImageLine(pdfium::span<uint8_t> dest_span,
pdfium::span<const uint8_t> src_span,
int pixels,
@@ -189,10 +185,8 @@
~CPDF_LabCS() override;
// CPDF_ColorSpace:
- bool GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const override;
+ std::optional<FX_RGB_STRUCT<float>> GetRGB(
+ pdfium::span<const float> pBuf) const override;
void GetDefaultValue(int iComponent,
float* value,
float* min,
@@ -223,10 +217,8 @@
~CPDF_ICCBasedCS() override;
// CPDF_ColorSpace:
- bool GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const override;
+ std::optional<FX_RGB_STRUCT<float>> GetRGB(
+ pdfium::span<const float> pBuf) const override;
void TranslateImageLine(pdfium::span<uint8_t> dest_span,
pdfium::span<const uint8_t> src_span,
int pixels,
@@ -262,10 +254,8 @@
~CPDF_SeparationCS() override;
// CPDF_ColorSpace:
- bool GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const override;
+ std::optional<FX_RGB_STRUCT<float>> GetRGB(
+ pdfium::span<const float> pBuf) const override;
void GetDefaultValue(int iComponent,
float* value,
float* min,
@@ -287,10 +277,8 @@
~CPDF_DeviceNCS() override;
// CPDF_ColorSpace:
- bool GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const override;
+ std::optional<FX_RGB_STRUCT<float>> GetRGB(
+ pdfium::span<const float> pBuf) const override;
void GetDefaultValue(int iComponent,
float* value,
float* min,
@@ -384,25 +372,19 @@
return kSRGBSamples2[scale / 4 - 48] / 255.0f;
}
-void XYZ_to_sRGB(float X, float Y, float Z, float* R, float* G, float* B) {
- float R1 = 3.2410f * X - 1.5374f * Y - 0.4986f * Z;
- float G1 = -0.9692f * X + 1.8760f * Y + 0.0416f * Z;
- float B1 = 0.0556f * X - 0.2040f * Y + 1.0570f * Z;
-
- *R = RGB_Conversion(R1);
- *G = RGB_Conversion(G1);
- *B = RGB_Conversion(B1);
+FX_RGB_STRUCT<float> XYZ_to_sRGB(float X, float Y, float Z) {
+ const float R1 = 3.2410f * X - 1.5374f * Y - 0.4986f * Z;
+ const float G1 = -0.9692f * X + 1.8760f * Y + 0.0416f * Z;
+ const float B1 = 0.0556f * X - 0.2040f * Y + 1.0570f * Z;
+ return {RGB_Conversion(R1), RGB_Conversion(G1), RGB_Conversion(B1)};
}
-void XYZ_to_sRGB_WhitePoint(float X,
- float Y,
- float Z,
- float Xw,
- float Yw,
- float Zw,
- float* R,
- float* G,
- float* B) {
+FX_RGB_STRUCT<float> XYZ_to_sRGB_WhitePoint(float X,
+ float Y,
+ float Z,
+ float Xw,
+ float Yw,
+ float Zw) {
// The following RGB_xyz is based on
// sRGB value {Rx,Ry}={0.64, 0.33}, {Gx,Gy}={0.30, 0.60}, {Bx,By}={0.15, 0.06}
@@ -423,9 +405,7 @@
Matrix_3by3 M = RGB_xyz.Multiply(RGB_SUM_XYZ_DIAG);
Vector_3by1 RGB = M.Inverse().TransformVector(XYZ);
- *R = RGB_Conversion(RGB.a);
- *G = RGB_Conversion(RGB.b);
- *B = RGB_Conversion(RGB.c);
+ return {RGB_Conversion(RGB.a), RGB_Conversion(RGB.b), RGB_Conversion(RGB.c)};
}
class StockColorSpaces {
@@ -626,16 +606,13 @@
std::optional<FX_COLORREF> CPDF_ColorSpace::GetColorRef(
pdfium::span<const float> buffer) {
- float r;
- float g;
- float b;
- if (!GetRGB(buffer, &r, &g, &b)) {
+ auto maybe_rgb = GetRGB(buffer);
+ if (!maybe_rgb.has_value()) {
return std::nullopt;
}
-
- r = std::clamp(r, 0.0f, 1.0f);
- g = std::clamp(g, 0.0f, 1.0f);
- b = std::clamp(b, 0.0f, 1.0f);
+ const float r = std::clamp(maybe_rgb.value().red, 0.0f, 1.0f);
+ const float g = std::clamp(maybe_rgb.value().green, 0.0f, 1.0f);
+ const float b = std::clamp(maybe_rgb.value().blue, 0.0f, 1.0f);
return FXSYS_BGR(FXSYS_roundf(b * 255), FXSYS_roundf(g * 255),
FXSYS_roundf(r * 255));
}
@@ -662,19 +639,16 @@
uint8_t* dest_buf = dest_span.data();
const uint8_t* src_buf = src_span.data();
std::vector<float> src(m_nComponents);
- float R;
- float G;
- float B;
const int divisor = m_Family != Family::kIndexed ? 255 : 1;
UNSAFE_TODO({
for (int i = 0; i < pixels; i++) {
for (uint32_t j = 0; j < m_nComponents; j++) {
src[j] = static_cast<float>(*src_buf++) / divisor;
}
- GetRGB(src, &R, &G, &B);
- *dest_buf++ = static_cast<int32_t>(B * 255);
- *dest_buf++ = static_cast<int32_t>(G * 255);
- *dest_buf++ = static_cast<int32_t>(R * 255);
+ auto rgb = GetRGBOrZerosOnError(src);
+ *dest_buf++ = static_cast<int32_t>(rgb.blue * 255);
+ *dest_buf++ = static_cast<int32_t>(rgb.green * 255);
+ *dest_buf++ = static_cast<int32_t>(rgb.red * 255);
}
});
}
@@ -731,14 +705,10 @@
return 1;
}
-bool CPDF_CalGray::GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const {
- *R = pBuf[0];
- *G = pBuf[0];
- *B = pBuf[0];
- return true;
+std::optional<FX_RGB_STRUCT<float>> CPDF_CalGray::GetRGB(
+ pdfium::span<const float> pBuf) const {
+ const float gray = pBuf[0];
+ return FX_RGB_STRUCT<float>{gray, gray, gray};
}
void CPDF_CalGray::TranslateImageLine(pdfium::span<uint8_t> dest_span,
@@ -796,10 +766,8 @@
return 3;
}
-bool CPDF_CalRGB::GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const {
+std::optional<FX_RGB_STRUCT<float>> CPDF_CalRGB::GetRGB(
+ pdfium::span<const float> pBuf) const {
UNSAFE_TODO({
float A_ = pBuf[0];
float B_ = pBuf[1];
@@ -822,10 +790,9 @@
Y = B_;
Z = C_;
}
- XYZ_to_sRGB_WhitePoint(X, Y, Z, m_WhitePoint[0], m_WhitePoint[1],
- m_WhitePoint[2], R, G, B);
+ return XYZ_to_sRGB_WhitePoint(X, Y, Z, m_WhitePoint[0], m_WhitePoint[1],
+ m_WhitePoint[2]);
});
- return true;
}
void CPDF_CalRGB::TranslateImageLine(pdfium::span<uint8_t> dest_span,
@@ -885,10 +852,8 @@
return 3;
}
-bool CPDF_LabCS::GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const {
+std::optional<FX_RGB_STRUCT<float>> CPDF_LabCS::GetRGB(
+ pdfium::span<const float> pBuf) const {
float Lstar = pBuf[0];
float astar = pBuf[1];
float bstar = pBuf[2];
@@ -913,8 +878,7 @@
else
Z = 1.0889f * N * N * N;
- XYZ_to_sRGB(X, Y, Z, R, G, B);
- return true;
+ return XYZ_to_sRGB(X, Y, Z);
}
void CPDF_LabCS::TranslateImageLine(pdfium::span<uint8_t> dest_span,
@@ -929,18 +893,15 @@
const uint8_t* pSrcBuf = src_span.data();
UNSAFE_TODO({
for (int i = 0; i < pixels; i++) {
- float lab[3];
- lab[0] = pSrcBuf[0] * 100 / 255.0f;
- lab[1] = pSrcBuf[1] - 128;
- lab[2] = pSrcBuf[2] - 128;
-
- float R;
- float G;
- float B;
- GetRGB(lab, &R, &G, &B);
- pDestBuf[0] = static_cast<int32_t>(B * 255);
- pDestBuf[1] = static_cast<int32_t>(G * 255);
- pDestBuf[2] = static_cast<int32_t>(R * 255);
+ const float lab[3] = {
+ static_cast<float>(pSrcBuf[0] * 100) / 255.0f,
+ static_cast<float>(pSrcBuf[1] - 128),
+ static_cast<float>(pSrcBuf[2] - 128),
+ };
+ auto rgb = GetRGBOrZerosOnError(lab);
+ pDestBuf[0] = static_cast<int32_t>(rgb.blue * 255);
+ pDestBuf[1] = static_cast<int32_t>(rgb.green * 255);
+ pDestBuf[2] = static_cast<int32_t>(rgb.red * 255);
pDestBuf += 3;
pSrcBuf += 3;
}
@@ -990,32 +951,20 @@
return nComponents;
}
-bool CPDF_ICCBasedCS::GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const {
- DCHECK(profile_);
+std::optional<FX_RGB_STRUCT<float>> CPDF_ICCBasedCS::GetRGB(
+ pdfium::span<const float> pBuf) const {
if (profile_->IsSRGB()) {
- *R = pBuf[0];
- *G = pBuf[1];
- *B = pBuf[2];
- return true;
+ return FX_RGB_STRUCT<float>{pBuf[0], pBuf[1], pBuf[2]};
}
if (profile_->IsSupported()) {
float rgb[3];
profile_->Translate(pBuf.first(ComponentCount()), rgb);
- *R = rgb[0];
- *G = rgb[1];
- *B = rgb[2];
- return true;
+ return FX_RGB_STRUCT<float>{rgb[0], rgb[1], rgb[2]};
}
- if (m_pBaseCS)
- return m_pBaseCS->GetRGB(pBuf, R, G, B);
-
- *R = 0.0f;
- *G = 0.0f;
- *B = 0.0f;
- return true;
+ if (m_pBaseCS) {
+ return m_pBaseCS->GetRGB(pBuf);
+ }
+ return FX_RGB_STRUCT<float>{};
}
void CPDF_ICCBasedCS::TranslateImageLine(pdfium::span<uint8_t> dest_span,
@@ -1197,37 +1146,29 @@
return 1;
}
-bool CPDF_SeparationCS::GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const {
- if (m_IsNoneType)
- return false;
-
+std::optional<FX_RGB_STRUCT<float>> CPDF_SeparationCS::GetRGB(
+ pdfium::span<const float> pBuf) const {
+ if (m_IsNoneType) {
+ return std::nullopt;
+ }
if (!m_pFunc) {
- if (!m_pBaseCS)
- return false;
-
- int nComps = m_pBaseCS->ComponentCount();
- std::vector<float> results(nComps);
- for (int i = 0; i < nComps; i++)
- results[i] = pBuf[0];
- return m_pBaseCS->GetRGB(results, R, G, B);
+ if (!m_pBaseCS) {
+ return std::nullopt;
+ }
+ std::vector<float> results(m_pBaseCS->ComponentCount(), pBuf[0]);
+ return m_pBaseCS->GetRGB(results);
}
// Using at least 16 elements due to the call m_pAltCS->GetRGB() below.
std::vector<float> results(std::max(m_pFunc->OutputCount(), 16u));
uint32_t nresults = m_pFunc->Call(pBuf.first(1), results).value_or(0);
- if (nresults == 0)
- return false;
-
- if (m_pBaseCS)
- return m_pBaseCS->GetRGB(results, R, G, B);
-
- *R = 0.0f;
- *G = 0.0f;
- *B = 0.0f;
- return false;
+ if (nresults == 0) {
+ return std::nullopt;
+ }
+ if (m_pBaseCS) {
+ return m_pBaseCS->GetRGB(results);
+ }
+ return std::nullopt;
}
CPDF_DeviceNCS::CPDF_DeviceNCS() : CPDF_BasedCS(Family::kDeviceN) {}
@@ -1269,21 +1210,19 @@
return fxcrt::CollectionSize<uint32_t>(*pObj);
}
-bool CPDF_DeviceNCS::GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const {
- if (!m_pFunc)
- return false;
-
+std::optional<FX_RGB_STRUCT<float>> CPDF_DeviceNCS::GetRGB(
+ pdfium::span<const float> pBuf) const {
+ if (!m_pFunc) {
+ return std::nullopt;
+ }
// Using at least 16 elements due to the call m_pAltCS->GetRGB() below.
std::vector<float> results(std::max(m_pFunc->OutputCount(), 16u));
uint32_t nresults =
m_pFunc->Call(pBuf.first(ComponentCount()), pdfium::make_span(results))
.value_or(0);
- if (nresults == 0)
- return false;
-
- return m_pBaseCS->GetRGB(results, R, G, B);
+ if (nresults == 0) {
+ return std::nullopt;
+ }
+ return m_pBaseCS->GetRGB(results);
}
diff --git a/core/fpdfapi/page/cpdf_colorspace.h b/core/fpdfapi/page/cpdf_colorspace.h
index c747524..769eb60 100644
--- a/core/fpdfapi/page/cpdf_colorspace.h
+++ b/core/fpdfapi/page/cpdf_colorspace.h
@@ -104,11 +104,16 @@
// components are integers.
std::optional<FX_COLORREF> GetColorRef(pdfium::span<const float> buffer);
+ // Wrapper around GetRGB() that returns black (0, 0, 0) when an actual value
+ // can not be determined.
+ FX_RGB_STRUCT<float> GetRGBOrZerosOnError(
+ pdfium::span<const float> pBuf) const {
+ return GetRGB(pBuf).value_or(FX_RGB_STRUCT<float>{});
+ }
+
// Use CPDF_Pattern::GetPatternColorRef() instead of GetRGB() for patterns.
- virtual bool GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const = 0;
+ virtual std::optional<FX_RGB_STRUCT<float>> GetRGB(
+ pdfium::span<const float> pBuf) const = 0;
virtual void GetDefaultValue(int iComponent,
float* value,
diff --git a/core/fpdfapi/page/cpdf_devicecs.cpp b/core/fpdfapi/page/cpdf_devicecs.cpp
index c3b25e7..5887dd3 100644
--- a/core/fpdfapi/page/cpdf_devicecs.cpp
+++ b/core/fpdfapi/page/cpdf_devicecs.cpp
@@ -43,45 +43,37 @@
NOTREACHED_NORETURN();
}
-bool CPDF_DeviceCS::GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const {
+std::optional<FX_RGB_STRUCT<float>> CPDF_DeviceCS::GetRGB(
+ pdfium::span<const float> pBuf) const {
switch (GetFamily()) {
case Family::kDeviceGray: {
const float pix = NormalizeChannel(pBuf.front());
- *R = pix;
- *G = pix;
- *B = pix;
- return true;
+ return FX_RGB_STRUCT<float>{pix, pix, pix};
}
case Family::kDeviceRGB: {
- auto rgb =
- fxcrt::truncating_reinterpret_span<const FX_RGB_STRUCT<float>>(pBuf);
- *R = NormalizeChannel(rgb.front().red);
- *G = NormalizeChannel(rgb.front().green);
- *B = NormalizeChannel(rgb.front().blue);
- return true;
+ const auto& rgb =
+ fxcrt::truncating_reinterpret_span<const FX_RGB_STRUCT<float>>(pBuf)
+ .front();
+ return FX_RGB_STRUCT<float>{
+ NormalizeChannel(rgb.red),
+ NormalizeChannel(rgb.green),
+ NormalizeChannel(rgb.blue),
+ };
}
case Family::kDeviceCMYK: {
- auto cmyk =
- fxcrt::truncating_reinterpret_span<const FX_CMYK_STRUCT<float>>(pBuf);
+ const auto& cmyk =
+ fxcrt::truncating_reinterpret_span<const FX_CMYK_STRUCT<float>>(pBuf)
+ .front();
if (IsStdConversionEnabled()) {
- float k = cmyk.front().key;
- *R = 1.0f - std::min(1.0f, cmyk.front().cyan + k);
- *G = 1.0f - std::min(1.0f, cmyk.front().magenta + k);
- *B = 1.0f - std::min(1.0f, cmyk.front().yellow + k);
- return true;
+ return FX_RGB_STRUCT<float>{
+ 1.0f - std::min(1.0f, cmyk.cyan + cmyk.key),
+ 1.0f - std::min(1.0f, cmyk.magenta + cmyk.key),
+ 1.0f - std::min(1.0f, cmyk.yellow + cmyk.key),
+ };
}
- FX_RGB_STRUCT<float> rgb =
- AdobeCMYK_to_sRGB(NormalizeChannel(cmyk.front().cyan),
- NormalizeChannel(cmyk.front().magenta),
- NormalizeChannel(cmyk.front().yellow),
- NormalizeChannel(cmyk.front().key));
- *R = rgb.red;
- *G = rgb.green;
- *B = rgb.blue;
- return true;
+ return AdobeCMYK_to_sRGB(
+ NormalizeChannel(cmyk.cyan), NormalizeChannel(cmyk.magenta),
+ NormalizeChannel(cmyk.yellow), NormalizeChannel(cmyk.key));
}
default:
NOTREACHED_NORETURN();
diff --git a/core/fpdfapi/page/cpdf_devicecs.h b/core/fpdfapi/page/cpdf_devicecs.h
index 8e8ca66..788c36e 100644
--- a/core/fpdfapi/page/cpdf_devicecs.h
+++ b/core/fpdfapi/page/cpdf_devicecs.h
@@ -18,10 +18,8 @@
~CPDF_DeviceCS() override;
// CPDF_ColorSpace:
- bool GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const override;
+ std::optional<FX_RGB_STRUCT<float>> GetRGB(
+ pdfium::span<const float> pBuf) const override;
void TranslateImageLine(pdfium::span<uint8_t> dest_span,
pdfium::span<const uint8_t> src_span,
int pixels,
diff --git a/core/fpdfapi/page/cpdf_devicecs_unittest.cpp b/core/fpdfapi/page/cpdf_devicecs_unittest.cpp
index 4c3c348..a50d19a 100644
--- a/core/fpdfapi/page/cpdf_devicecs_unittest.cpp
+++ b/core/fpdfapi/page/cpdf_devicecs_unittest.cpp
@@ -10,110 +10,120 @@
#include "testing/gtest/include/gtest/gtest.h"
TEST(CPDF_DeviceCSTest, GetRGBFromGray) {
- float R;
- float G;
- float B;
auto device_gray =
pdfium::MakeRetain<CPDF_DeviceCS>(CPDF_ColorSpace::Family::kDeviceGray);
// Test normal values. For gray, only first value from buf should be used.
float buf[3] = {0.43f, 0.11f, 0.34f};
- ASSERT_TRUE(device_gray->GetRGB(buf, &R, &G, &B));
- EXPECT_FLOAT_EQ(0.43f, R);
- EXPECT_FLOAT_EQ(0.43f, G);
- EXPECT_FLOAT_EQ(0.43f, B);
+ auto maybe_rgb = device_gray->GetRGB(buf);
+ ASSERT_TRUE(maybe_rgb.has_value());
+ EXPECT_FLOAT_EQ(0.43f, maybe_rgb.value().red);
+ EXPECT_FLOAT_EQ(0.43f, maybe_rgb.value().green);
+ EXPECT_FLOAT_EQ(0.43f, maybe_rgb.value().blue);
+
buf[0] = 0.872f;
- ASSERT_TRUE(device_gray->GetRGB(buf, &R, &G, &B));
- EXPECT_FLOAT_EQ(0.872f, R);
- EXPECT_FLOAT_EQ(0.872f, G);
- EXPECT_FLOAT_EQ(0.872f, B);
+ maybe_rgb = device_gray->GetRGB(buf);
+ ASSERT_TRUE(maybe_rgb.has_value());
+ EXPECT_FLOAT_EQ(0.872f, maybe_rgb.value().red);
+ EXPECT_FLOAT_EQ(0.872f, maybe_rgb.value().green);
+ EXPECT_FLOAT_EQ(0.872f, maybe_rgb.value().blue);
// Test boundary values
buf[0] = {0.0f};
- ASSERT_TRUE(device_gray->GetRGB(buf, &R, &G, &B));
- EXPECT_FLOAT_EQ(0.0f, R);
- EXPECT_FLOAT_EQ(0.0f, G);
- EXPECT_FLOAT_EQ(0.0f, B);
+ maybe_rgb = device_gray->GetRGB(buf);
+ ASSERT_TRUE(maybe_rgb.has_value());
+ EXPECT_FLOAT_EQ(0.0f, maybe_rgb.value().red);
+ EXPECT_FLOAT_EQ(0.0f, maybe_rgb.value().green);
+ EXPECT_FLOAT_EQ(0.0f, maybe_rgb.value().blue);
+
buf[0] = 1.0f;
- ASSERT_TRUE(device_gray->GetRGB(buf, &R, &G, &B));
- EXPECT_FLOAT_EQ(1.0f, R);
- EXPECT_FLOAT_EQ(1.0f, G);
- EXPECT_FLOAT_EQ(1.0f, B);
+ maybe_rgb = device_gray->GetRGB(buf);
+ ASSERT_TRUE(maybe_rgb.has_value());
+ EXPECT_FLOAT_EQ(1.0f, maybe_rgb.value().red);
+ EXPECT_FLOAT_EQ(1.0f, maybe_rgb.value().green);
+ EXPECT_FLOAT_EQ(1.0f, maybe_rgb.value().blue);
// Test out of range values
buf[0] = -0.01f;
- ASSERT_TRUE(device_gray->GetRGB(buf, &R, &G, &B));
- EXPECT_FLOAT_EQ(0.0f, R);
- EXPECT_FLOAT_EQ(0.0f, G);
- EXPECT_FLOAT_EQ(0.0f, B);
+ maybe_rgb = device_gray->GetRGB(buf);
+ ASSERT_TRUE(maybe_rgb.has_value());
+ EXPECT_FLOAT_EQ(0.0f, maybe_rgb.value().red);
+ EXPECT_FLOAT_EQ(0.0f, maybe_rgb.value().green);
+ EXPECT_FLOAT_EQ(0.0f, maybe_rgb.value().blue);
+
buf[0] = 12.5f;
- ASSERT_TRUE(device_gray->GetRGB(buf, &R, &G, &B));
- EXPECT_FLOAT_EQ(1.0f, R);
- EXPECT_FLOAT_EQ(1.0f, G);
- EXPECT_FLOAT_EQ(1.0f, B);
+ maybe_rgb = device_gray->GetRGB(buf);
+ ASSERT_TRUE(maybe_rgb.has_value());
+ EXPECT_FLOAT_EQ(1.0f, maybe_rgb.value().red);
+ EXPECT_FLOAT_EQ(1.0f, maybe_rgb.value().green);
+ EXPECT_FLOAT_EQ(1.0f, maybe_rgb.value().blue);
}
TEST(CPDF_DeviceCSTest, GetRGBFromRGB) {
- float R;
- float G;
- float B;
auto device_rgb =
pdfium::MakeRetain<CPDF_DeviceCS>(CPDF_ColorSpace::Family::kDeviceRGB);
// Test normal values
float buf[3] = {0.13f, 1.0f, 0.652f};
- ASSERT_TRUE(device_rgb->GetRGB(buf, &R, &G, &B));
- EXPECT_FLOAT_EQ(0.13f, R);
- EXPECT_FLOAT_EQ(1.0f, G);
- EXPECT_FLOAT_EQ(0.652f, B);
+ auto maybe_rgb = device_rgb->GetRGB(buf);
+ ASSERT_TRUE(maybe_rgb.has_value());
+ EXPECT_FLOAT_EQ(0.13f, maybe_rgb.value().red);
+ EXPECT_FLOAT_EQ(1.0f, maybe_rgb.value().green);
+ EXPECT_FLOAT_EQ(0.652f, maybe_rgb.value().blue);
+
buf[0] = 0.0f;
buf[1] = 0.52f;
buf[2] = 0.78f;
- ASSERT_TRUE(device_rgb->GetRGB(buf, &R, &G, &B));
- EXPECT_FLOAT_EQ(0.0f, R);
- EXPECT_FLOAT_EQ(0.52f, G);
- EXPECT_FLOAT_EQ(0.78f, B);
+ maybe_rgb = device_rgb->GetRGB(buf);
+ ASSERT_TRUE(maybe_rgb.has_value());
+ EXPECT_FLOAT_EQ(0.0f, maybe_rgb.value().red);
+ EXPECT_FLOAT_EQ(0.52f, maybe_rgb.value().green);
+ EXPECT_FLOAT_EQ(0.78f, maybe_rgb.value().blue);
// Test out of range values
buf[0] = -10.5f;
buf[1] = 100.0f;
- ASSERT_TRUE(device_rgb->GetRGB(buf, &R, &G, &B));
- EXPECT_FLOAT_EQ(0.0f, R);
- EXPECT_FLOAT_EQ(1.0f, G);
- EXPECT_FLOAT_EQ(0.78f, B);
+ maybe_rgb = device_rgb->GetRGB(buf);
+ ASSERT_TRUE(maybe_rgb.has_value());
+ EXPECT_FLOAT_EQ(0.0f, maybe_rgb.value().red);
+ EXPECT_FLOAT_EQ(1.0f, maybe_rgb.value().green);
+ EXPECT_FLOAT_EQ(0.78f, maybe_rgb.value().blue);
}
TEST(CPDF_DeviceCSTest, GetRGBFromCMYK) {
- float R;
- float G;
- float B;
auto device_cmyk =
pdfium::MakeRetain<CPDF_DeviceCS>(CPDF_ColorSpace::Family::kDeviceCMYK);
// Test normal values
float buf[4] = {0.6f, 0.5f, 0.3f, 0.9f};
- ASSERT_TRUE(device_cmyk->GetRGB(buf, &R, &G, &B));
- EXPECT_FLOAT_EQ(0.0627451f, R);
- EXPECT_FLOAT_EQ(0.0627451f, G);
- EXPECT_FLOAT_EQ(0.10588236f, B);
+ auto maybe_rgb = device_cmyk->GetRGB(buf);
+ ASSERT_TRUE(maybe_rgb.has_value());
+ EXPECT_FLOAT_EQ(0.0627451f, maybe_rgb.value().red);
+ EXPECT_FLOAT_EQ(0.0627451f, maybe_rgb.value().green);
+ EXPECT_FLOAT_EQ(0.10588236f, maybe_rgb.value().blue);
+
buf[0] = 0.15f;
buf[2] = 0.0f;
- ASSERT_TRUE(device_cmyk->GetRGB(buf, &R, &G, &B));
- EXPECT_FLOAT_EQ(0.2f, R);
- EXPECT_FLOAT_EQ(0.0862745f, G);
- EXPECT_FLOAT_EQ(0.16470589f, B);
+ maybe_rgb = device_cmyk->GetRGB(buf);
+ ASSERT_TRUE(maybe_rgb.has_value());
+ EXPECT_FLOAT_EQ(0.2f, maybe_rgb.value().red);
+ EXPECT_FLOAT_EQ(0.0862745f, maybe_rgb.value().green);
+ EXPECT_FLOAT_EQ(0.16470589f, maybe_rgb.value().blue);
+
buf[2] = 1.0f;
buf[3] = 0.0f;
- ASSERT_TRUE(device_cmyk->GetRGB(buf, &R, &G, &B));
- EXPECT_FLOAT_EQ(0.85098046f, R);
- EXPECT_FLOAT_EQ(0.552941f, G);
- EXPECT_FLOAT_EQ(0.15686275f, B);
+ maybe_rgb = device_cmyk->GetRGB(buf);
+ ASSERT_TRUE(maybe_rgb.has_value());
+ EXPECT_FLOAT_EQ(0.85098046f, maybe_rgb.value().red);
+ EXPECT_FLOAT_EQ(0.552941f, maybe_rgb.value().green);
+ EXPECT_FLOAT_EQ(0.15686275f, maybe_rgb.value().blue);
// Test out of range values
buf[2] = 1.5f;
buf[3] = -0.6f;
- ASSERT_TRUE(device_cmyk->GetRGB(buf, &R, &G, &B));
- EXPECT_FLOAT_EQ(0.85098046f, R);
- EXPECT_FLOAT_EQ(0.552941f, G);
- EXPECT_FLOAT_EQ(0.15686275f, B);
+ maybe_rgb = device_cmyk->GetRGB(buf);
+ ASSERT_TRUE(maybe_rgb.has_value());
+ EXPECT_FLOAT_EQ(0.85098046f, maybe_rgb.value().red);
+ EXPECT_FLOAT_EQ(0.552941f, maybe_rgb.value().green);
+ EXPECT_FLOAT_EQ(0.15686275f, maybe_rgb.value().blue);
}
diff --git a/core/fpdfapi/page/cpdf_dib.cpp b/core/fpdfapi/page/cpdf_dib.cpp
index 8bb6e2a..b33f04f 100644
--- a/core/fpdfapi/page/cpdf_dib.cpp
+++ b/core/fpdfapi/page/cpdf_dib.cpp
@@ -876,12 +876,10 @@
std::vector<float> colors =
ReadArrayElementsToVector(pMatte.Get(), m_nComponents);
- float R;
- float G;
- float B;
- m_pColorSpace->GetRGB(colors, &R, &G, &B);
- m_MatteColor = ArgbEncode(0, FXSYS_roundf(R * 255), FXSYS_roundf(G * 255),
- FXSYS_roundf(B * 255));
+ auto rgb = m_pColorSpace->GetRGBOrZerosOnError(colors);
+ m_MatteColor =
+ ArgbEncode(0, FXSYS_roundf(rgb.red * 255),
+ FXSYS_roundf(rgb.green * 255), FXSYS_roundf(rgb.blue * 255));
}
return StartLoadMaskDIB(std::move(mask));
}
@@ -955,13 +953,10 @@
std::fill(std::begin(color_values), std::end(color_values),
m_CompData[0].m_DecodeMin);
- float R = 0.0f;
- float G = 0.0f;
- float B = 0.0f;
- m_pColorSpace->GetRGB(color_values, &R, &G, &B);
-
- FX_ARGB argb0 = ArgbEncode(255, FXSYS_roundf(R * 255),
- FXSYS_roundf(G * 255), FXSYS_roundf(B * 255));
+ auto rgb = m_pColorSpace->GetRGBOrZerosOnError(color_values);
+ FX_ARGB argb0 =
+ ArgbEncode(255, FXSYS_roundf(rgb.red * 255),
+ FXSYS_roundf(rgb.green * 255), FXSYS_roundf(rgb.blue * 255));
FX_ARGB argb1;
const CPDF_IndexedCS* indexed_cs = m_pColorSpace->AsIndexedCS();
if (indexed_cs && indexed_cs->GetMaxIndex() == 0) {
@@ -973,9 +968,10 @@
color_values[0] += m_CompData[0].m_DecodeStep;
color_values[1] += m_CompData[0].m_DecodeStep;
color_values[2] += m_CompData[0].m_DecodeStep;
- m_pColorSpace->GetRGB(color_values, &R, &G, &B);
- argb1 = ArgbEncode(255, FXSYS_roundf(R * 255), FXSYS_roundf(G * 255),
- FXSYS_roundf(B * 255));
+ auto result = m_pColorSpace->GetRGBOrZerosOnError(color_values);
+ argb1 = ArgbEncode(255, FXSYS_roundf(result.red * 255),
+ FXSYS_roundf(result.green * 255),
+ FXSYS_roundf(result.blue * 255));
}
if (argb0 != 0xFF000000 || argb1 != 0xFFFFFFFF) {
@@ -1001,21 +997,18 @@
color_values[j] = m_CompData[j].m_DecodeMin +
m_CompData[j].m_DecodeStep * encoded_component;
}
- float R = 0;
- float G = 0;
- float B = 0;
+ FX_RGB_STRUCT<float> rgb;
if (m_nComponents == 1 && m_Family == CPDF_ColorSpace::Family::kICCBased &&
m_pColorSpace->ComponentCount() > 1) {
- int nComponents = m_pColorSpace->ComponentCount();
- std::vector<float> temp_buf(nComponents);
- for (int k = 0; k < nComponents; ++k)
- temp_buf[k] = color_values[0];
- m_pColorSpace->GetRGB(temp_buf, &R, &G, &B);
+ const size_t nComponents = m_pColorSpace->ComponentCount();
+ std::vector<float> temp_buf(nComponents, color_values[0]);
+ rgb = m_pColorSpace->GetRGBOrZerosOnError(temp_buf);
} else {
- m_pColorSpace->GetRGB(color_values, &R, &G, &B);
+ rgb = m_pColorSpace->GetRGBOrZerosOnError(color_values);
}
- SetPaletteArgb(i, ArgbEncode(255, FXSYS_roundf(R * 255),
- FXSYS_roundf(G * 255), FXSYS_roundf(B * 255)));
+ SetPaletteArgb(i, ArgbEncode(255, FXSYS_roundf(rgb.red * 255),
+ FXSYS_roundf(rgb.green * 255),
+ FXSYS_roundf(rgb.blue * 255)));
}
}
@@ -1055,9 +1048,7 @@
// Using at least 16 elements due to the call m_pColorSpace->GetRGB().
std::vector<float> color_values(std::max(m_nComponents, 16u));
- float R = 0.0f;
- float G = 0.0f;
- float B = 0.0f;
+ FX_RGB_STRUCT<float> rgb = {};
uint64_t src_bit_pos = 0;
uint64_t src_byte_pos = 0;
size_t dest_byte_pos = 0;
@@ -1075,18 +1066,17 @@
src_bit_pos += m_bpc;
}
}
-
if (TransMask()) {
float k = 1.0f - color_values[3];
- R = (1.0f - color_values[0]) * k;
- G = (1.0f - color_values[1]) * k;
- B = (1.0f - color_values[2]) * k;
+ rgb.red = (1.0f - color_values[0]) * k;
+ rgb.green = (1.0f - color_values[1]) * k;
+ rgb.blue = (1.0f - color_values[2]) * k;
} else if (m_Family != CPDF_ColorSpace::Family::kPattern) {
- m_pColorSpace->GetRGB(color_values, &R, &G, &B);
+ rgb = m_pColorSpace->GetRGBOrZerosOnError(color_values);
}
- R = std::clamp(R, 0.0f, 1.0f);
- G = std::clamp(G, 0.0f, 1.0f);
- B = std::clamp(B, 0.0f, 1.0f);
+ const float R = std::clamp(rgb.red, 0.0f, 1.0f);
+ const float G = std::clamp(rgb.green, 0.0f, 1.0f);
+ const float B = std::clamp(rgb.blue, 0.0f, 1.0f);
dest_scan[dest_byte_pos] = static_cast<uint8_t>(B * 255);
dest_scan[dest_byte_pos + 1] = static_cast<uint8_t>(G * 255);
dest_scan[dest_byte_pos + 2] = static_cast<uint8_t>(R * 255);
diff --git a/core/fpdfapi/page/cpdf_indexedcs.cpp b/core/fpdfapi/page/cpdf_indexedcs.cpp
index 7ec1925..7f3a259 100644
--- a/core/fpdfapi/page/cpdf_indexedcs.cpp
+++ b/core/fpdfapi/page/cpdf_indexedcs.cpp
@@ -89,13 +89,11 @@
return 1;
}
-bool CPDF_IndexedCS::GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const {
+std::optional<FX_RGB_STRUCT<float>> CPDF_IndexedCS::GetRGB(
+ pdfium::span<const float> pBuf) const {
int32_t index = static_cast<int32_t>(pBuf[0]);
if (index < 0 || index > max_index_) {
- return false;
+ return std::nullopt;
}
DCHECK(!component_min_max_.empty());
@@ -105,10 +103,7 @@
length += 1;
length *= component_min_max_.size();
if (!length.IsValid() || length.ValueOrDie() > lookup_table_.size()) {
- *R = 0;
- *G = 0;
- *B = 0;
- return false;
+ return std::nullopt;
}
DataVector<float> comps(component_min_max_.size());
@@ -118,5 +113,5 @@
comp.min +
comp.max * lookup_table_[index * component_min_max_.size() + i] / 255;
}
- return m_pBaseCS->GetRGB(comps, R, G, B);
+ return m_pBaseCS->GetRGB(comps);
}
diff --git a/core/fpdfapi/page/cpdf_indexedcs.h b/core/fpdfapi/page/cpdf_indexedcs.h
index b3d774f..99a80e8 100644
--- a/core/fpdfapi/page/cpdf_indexedcs.h
+++ b/core/fpdfapi/page/cpdf_indexedcs.h
@@ -28,10 +28,8 @@
~CPDF_IndexedCS() override;
// CPDF_ColorSpace:
- bool GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const override;
+ std::optional<FX_RGB_STRUCT<float>> GetRGB(
+ pdfium::span<const float> pBuf) const override;
const CPDF_IndexedCS* AsIndexedCS() const override;
uint32_t v_Load(CPDF_Document* pDoc,
const CPDF_Array* pArray,
diff --git a/core/fpdfapi/page/cpdf_meshstream.cpp b/core/fpdfapi/page/cpdf_meshstream.cpp
index 4cb16c3..51208d1 100644
--- a/core/fpdfapi/page/cpdf_meshstream.cpp
+++ b/core/fpdfapi/page/cpdf_meshstream.cpp
@@ -209,22 +209,16 @@
(m_ColorMax[i] - m_ColorMin[i]) /
m_ComponentMax;
}
-
- FX_RGB_STRUCT<float> rgb = {};
if (m_funcs.empty()) {
- m_pCS->GetRGB(color_value, &rgb.red, &rgb.green, &rgb.blue);
- return rgb;
+ return m_pCS->GetRGBOrZerosOnError(color_value);
}
-
float result[kMaxComponents] = {};
for (const auto& func : m_funcs) {
if (func && func->OutputCount() <= kMaxComponents) {
func->Call(pdfium::make_span(color_value).first(1u), result);
}
}
-
- m_pCS->GetRGB(result, &rgb.red, &rgb.green, &rgb.blue);
- return rgb;
+ return m_pCS->GetRGBOrZerosOnError(result);
}
bool CPDF_MeshStream::ReadVertex(const CFX_Matrix& pObject2Bitmap,
diff --git a/core/fpdfapi/page/cpdf_patterncs.cpp b/core/fpdfapi/page/cpdf_patterncs.cpp
index fea5416..5c37dbd 100644
--- a/core/fpdfapi/page/cpdf_patterncs.cpp
+++ b/core/fpdfapi/page/cpdf_patterncs.cpp
@@ -44,10 +44,8 @@
return m_pBaseCS->ComponentCount() + 1;
}
-bool CPDF_PatternCS::GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const {
+std::optional<FX_RGB_STRUCT<float>> CPDF_PatternCS::GetRGB(
+ pdfium::span<const float> pBuf) const {
NOTREACHED_NORETURN();
}
diff --git a/core/fpdfapi/page/cpdf_patterncs.h b/core/fpdfapi/page/cpdf_patterncs.h
index 07d6f54..d55b200 100644
--- a/core/fpdfapi/page/cpdf_patterncs.h
+++ b/core/fpdfapi/page/cpdf_patterncs.h
@@ -26,10 +26,8 @@
void InitializeStockPattern();
// CPDF_ColorSpace:
- bool GetRGB(pdfium::span<const float> pBuf,
- float* R,
- float* G,
- float* B) const override;
+ std::optional<FX_RGB_STRUCT<float>> GetRGB(
+ pdfium::span<const float> pBuf) const override;
const CPDF_PatternCS* AsPatternCS() const override;
uint32_t v_Load(CPDF_Document* pDoc,
const CPDF_Array* pArray,
diff --git a/core/fpdfapi/render/cpdf_rendershading.cpp b/core/fpdfapi/render/cpdf_rendershading.cpp
index 325cee1..4601d39 100644
--- a/core/fpdfapi/render/cpdf_rendershading.cpp
+++ b/core/fpdfapi/render/cpdf_rendershading.cpp
@@ -83,12 +83,10 @@
if (nresults.has_value())
result_span = result_span.subspan(nresults.value());
}
- float R = 0.0f;
- float G = 0.0f;
- float B = 0.0f;
- pCS->GetRGB(result_array, &R, &G, &B);
- shading_steps[i] = ArgbEncode(alpha, FXSYS_roundf(R * 255),
- FXSYS_roundf(G * 255), FXSYS_roundf(B * 255));
+ auto rgb = pCS->GetRGBOrZerosOnError(result_array);
+ shading_steps[i] =
+ ArgbEncode(alpha, FXSYS_roundf(rgb.red * 255),
+ FXSYS_roundf(rgb.green * 255), FXSYS_roundf(rgb.blue * 255));
}
return shading_steps;
}
@@ -314,13 +312,10 @@
if (nresults.has_value())
result_span = result_span.subspan(nresults.value());
}
- float R = 0.0f;
- float G = 0.0f;
- float B = 0.0f;
- pCS->GetRGB(result_array, &R, &G, &B);
- dib_buf[column] = ArgbEncode(alpha, static_cast<int32_t>(R * 255),
- static_cast<int32_t>(G * 255),
- static_cast<int32_t>(B * 255));
+ auto rgb = pCS->GetRGBOrZerosOnError(result_array);
+ dib_buf[column] = ArgbEncode(alpha, static_cast<int32_t>(rgb.red * 255),
+ static_cast<int32_t>(rgb.green * 255),
+ static_cast<int32_t>(rgb.blue * 255));
}
}
}
@@ -911,13 +906,10 @@
std::vector<float> comps = ReadArrayElementsToVector(
pBackColor.Get(), pColorSpace->ComponentCount());
- float R = 0.0f;
- float G = 0.0f;
- float B = 0.0f;
- pColorSpace->GetRGB(comps, &R, &G, &B);
- background = ArgbEncode(255, static_cast<int32_t>(R * 255),
- static_cast<int32_t>(G * 255),
- static_cast<int32_t>(B * 255));
+ auto rgb = pColorSpace->GetRGBOrZerosOnError(comps);
+ background = ArgbEncode(255, static_cast<int32_t>(rgb.red * 255),
+ static_cast<int32_t>(rgb.green * 255),
+ static_cast<int32_t>(rgb.blue * 255));
}
}
FX_RECT clip_rect_bbox = clip_rect;
diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp
index 9c2dd94..94ab6c1 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.cpp
+++ b/core/fpdfapi/render/cpdf_renderstatus.cpp
@@ -1457,10 +1457,8 @@
std::vector<float> floats = ReadArrayElementsToVector(pBC.Get(), count);
floats.resize(comps);
- float R;
- float G;
- float B;
- pCS->GetRGB(floats, &R, &G, &B);
- return ArgbEncode(255, static_cast<int>(R * 255), static_cast<int>(G * 255),
- static_cast<int>(B * 255));
+ auto rgb = pCS->GetRGBOrZerosOnError(floats);
+ return ArgbEncode(255, static_cast<int>(rgb.red * 255),
+ static_cast<int>(rgb.green * 255),
+ static_cast<int>(rgb.blue * 255));
}