RelativeLuminanceUtils.h (2943B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_RelativeLuminanceUtils_h 8 #define mozilla_RelativeLuminanceUtils_h 9 10 #include "nsColor.h" 11 12 namespace mozilla { 13 14 // Utilities for calculating relative luminance based on the algorithm 15 // defined in https://www.w3.org/TR/WCAG20/#relativeluminancedef 16 class RelativeLuminanceUtils { 17 public: 18 // Compute the relative luminance. 19 static float Compute(nscolor aColor) { 20 float r = ComputeComponent(NS_GET_R(aColor)); 21 float g = ComputeComponent(NS_GET_G(aColor)); 22 float b = ComputeComponent(NS_GET_B(aColor)); 23 return ComputeFromComponents(r, g, b); 24 } 25 26 static float Compute(float aR, float aG, float aB) { 27 float r = ComputeComponent(aR); 28 float g = ComputeComponent(aG); 29 float b = ComputeComponent(aB); 30 return ComputeFromComponents(r, g, b); 31 } 32 33 // Adjust the relative luminance of the given color. 34 static nscolor Adjust(nscolor aColor, float aLuminance) { 35 float r = ComputeComponent(NS_GET_R(aColor)); 36 float g = ComputeComponent(NS_GET_G(aColor)); 37 float b = ComputeComponent(NS_GET_B(aColor)); 38 float luminance = ComputeFromComponents(r, g, b); 39 float factor = (aLuminance + 0.05f) / (luminance + 0.05f); 40 uint8_t r1 = 41 DecomputeComponent(std::max(0.0f, (r + 0.05f) * factor - 0.05f)); 42 uint8_t g1 = 43 DecomputeComponent(std::max(0.0f, (g + 0.05f) * factor - 0.05f)); 44 uint8_t b1 = 45 DecomputeComponent(std::max(0.0f, (b + 0.05f) * factor - 0.05f)); 46 return NS_RGBA(r1, g1, b1, NS_GET_A(aColor)); 47 } 48 49 // https://www.w3.org/TR/WCAG21/#dfn-contrast-ratio 50 static float ContrastRatio(nscolor aColor1, nscolor aColor2) { 51 float l1 = Compute(aColor1); 52 float l2 = Compute(aColor2); 53 if (l1 < l2) { 54 std::swap(l1, l2); 55 } 56 return (l1 + 0.05f) / (l2 + 0.05f); 57 } 58 59 private: 60 static float ComputeComponent(float aComponent) { 61 if (aComponent <= 0.03928f) { 62 return aComponent / 12.92f; 63 } 64 return std::pow((aComponent + 0.055f) / 1.055f, 2.4f); 65 } 66 67 static float ComputeComponent(uint8_t aComponent) { 68 return ComputeComponent(float(aComponent) / 255.0f); 69 } 70 71 static constexpr float ComputeFromComponents(float aR, float aG, float aB) { 72 return 0.2126f * aR + 0.7152f * aG + 0.0722f * aB; 73 } 74 75 // Inverse function of ComputeComponent. 76 static uint8_t DecomputeComponent(float aComponent) { 77 if (aComponent <= 0.03928f / 12.92f) { 78 aComponent *= 12.92f; 79 } else { 80 aComponent = std::pow(aComponent, 1.0f / 2.4f) * 1.055f - 0.055f; 81 } 82 return ClampColor(aComponent * 255.0f); 83 } 84 }; 85 86 } // namespace mozilla 87 88 #endif // mozilla_RelativeLuminanceUtils_h