Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Public Attributes | List of all members
SkColor4fXformer Struct Reference

#include <SkGradientBaseShader.h>

Public Types

using ColorStorage = skia_private::STArray< 4, SkPMColor4f >
 
using PositionStorage = skia_private::STArray< 4, float >
 

Public Member Functions

 SkColor4fXformer (const SkGradientBaseShader *shader, SkColorSpace *dst, bool forceExplicitPositions=false)
 

Public Attributes

ColorStorage fColors
 
PositionStorage fPositionStorage
 
float * fPositions
 
sk_sp< SkColorSpacefIntermediateColorSpace
 

Detailed Description

Definition at line 173 of file SkGradientBaseShader.h.

Member Typedef Documentation

◆ ColorStorage

Definition at line 178 of file SkGradientBaseShader.h.

◆ PositionStorage

Definition at line 179 of file SkGradientBaseShader.h.

Constructor & Destructor Documentation

◆ SkColor4fXformer()

SkColor4fXformer::SkColor4fXformer ( const SkGradientBaseShader shader,
SkColorSpace dst,
bool  forceExplicitPositions = false 
)

Definition at line 735 of file SkGradientBaseShader.cpp.

737 {
740
741 int colorCount = shader->fColorCount;
742 const SkGradientShader::Interpolation interpolation = shader->fInterpolation;
743
744 // 0) Copy the shader's position pointer. Certain interpolation modes might force us to add
745 // new stops, in which case we'll allocate & edit the positions.
746 fPositions = shader->fPositions;
747
748 // 1) Determine the color space of our intermediate colors.
750
751 // 2) Convert all colors to the intermediate color space
753
754 auto dstInfo = info.makeColorSpace(fIntermediateColorSpace);
755 auto srcInfo = info.makeColorSpace(shader->fColorSpace);
756
757 fColors.reset(colorCount);
759 fColors.begin(),
760 info.minRowBytes(),
761 srcInfo,
762 shader->fColors,
763 info.minRowBytes()));
764
765 // 3) Transform to the interpolation color space (if it's special)
766 ConvertColorProc convertFn = nullptr;
767 switch (interpolation.fColorSpace) {
768 case ColorSpace::kHSL: convertFn = srgb_to_hsl; break;
769 case ColorSpace::kHWB: convertFn = srgb_to_hwb; break;
770 case ColorSpace::kLab: convertFn = xyzd50_to_lab; break;
771 case ColorSpace::kLCH: convertFn = xyzd50_to_hcl; break;
772 case ColorSpace::kOKLab: convertFn = lin_srgb_to_oklab; break;
773 case ColorSpace::kOKLabGamutMap: convertFn = lin_srgb_to_oklab; break;
774 case ColorSpace::kOKLCH: convertFn = lin_srgb_to_okhcl; break;
775 case ColorSpace::kOKLCHGamutMap: convertFn = lin_srgb_to_okhcl; break;
776 default: break;
777 }
778
779 skia_private::STArray<4, bool> hueIsPowerless;
780 bool anyPowerlessHue = false;
781 hueIsPowerless.push_back_n(colorCount, false);
782 if (convertFn) {
783 for (int i = 0; i < colorCount; ++i) {
784 fColors[i] = convertFn(fColors[i], hueIsPowerless.data() + i);
785 anyPowerlessHue = anyPowerlessHue || hueIsPowerless[i];
786 }
787 }
788
789 if (anyPowerlessHue) {
790 // In theory, if we knew we were just going to adjust the existing colors (without adding
791 // new ones), we could do it all in-place. To keep things simple, we always generate the
792 // new colors in separate storage.
793 ColorStorage newColors;
794 PositionStorage newPositions;
795
796 for (int i = 0; i < colorCount; ++i) {
797 const SkPMColor4f& curColor = fColors[i];
798 float curPos = shader->getPos(i);
799
800 if (!hueIsPowerless[i]) {
801 newColors.push_back(curColor);
802 newPositions.push_back(curPos);
803 continue;
804 }
805
806 auto colorWithHueFrom = [](const SkPMColor4f& color, const SkPMColor4f& hueColor) {
807 // If we have any powerless hue, then all colors are already in (some) polar space,
808 // and they all store their hue in the red channel.
809 return SkPMColor4f{hueColor.fR, color.fG, color.fB, color.fA};
810 };
811
812 // In each case, we might be copying a powerless (invalid) hue from the neighbor, but
813 // that should be fine, as it will match that neighbor perfectly, and any hue is ok.
814 if (i != 0) {
815 newPositions.push_back(curPos);
816 newColors.push_back(colorWithHueFrom(curColor, fColors[i - 1]));
817 }
818 if (i != colorCount - 1) {
819 newPositions.push_back(curPos);
820 newColors.push_back(colorWithHueFrom(curColor, fColors[i + 1]));
821 }
822 }
823
824 fColors.swap(newColors);
825 fPositionStorage.swap(newPositions);
827 colorCount = fColors.size();
828 }
829
830 // 4) For polar colors, adjust hue values to respect the hue method. We're using a trick here...
831 // The specification looks at adjacent colors, and adjusts one or the other. Because we store
832 // the stops in uniforms (and our backend conversions normalize the hue angle), we can
833 // instead always apply the adjustment to the *second* color. That lets us keep a running
834 // total, and do a single pass across all the colors to respect the requested hue method,
835 // without needing to do any extra work per-pixel.
836 if (color_space_is_polar(interpolation.fColorSpace)) {
837 float delta = 0;
838 for (int i = 0; i < colorCount - 1; ++i) {
839 float h1 = fColors[i].fR;
840 float& h2 = fColors[i + 1].fR;
841 h2 += delta;
842 switch (interpolation.fHueMethod) {
843 case HueMethod::kShorter:
844 if (h2 - h1 > 180) {
845 h2 -= 360; // i.e. h1 += 360
846 delta -= 360;
847 } else if (h2 - h1 < -180) {
848 h2 += 360;
849 delta += 360;
850 }
851 break;
852 case HueMethod::kLonger:
853 if ((i == 0 && shader->fFirstStopIsImplicit) ||
854 (i == colorCount - 2 && shader->fLastStopIsImplicit)) {
855 // Do nothing. We don't want to introduce a full revolution for these stops
856 // Full rationale at skbug.com/13941
857 } else if (0 < h2 - h1 && h2 - h1 < 180) {
858 h2 -= 360; // i.e. h1 += 360
859 delta -= 360;
860 } else if (-180 < h2 - h1 && h2 - h1 <= 0) {
861 h2 += 360;
862 delta += 360;
863 }
864 break;
865 case HueMethod::kIncreasing:
866 if (h2 < h1) {
867 h2 += 360;
868 delta += 360;
869 }
870 break;
871 case HueMethod::kDecreasing:
872 if (h1 < h2) {
873 h2 -= 360; // i.e. h1 += 360;
874 delta -= 360;
875 }
876 break;
877 }
878 }
879 }
880
881 // 5) Apply premultiplication
882 PremulColorProc premulFn = nullptr;
883 if (static_cast<bool>(interpolation.fInPremul)) {
884 switch (interpolation.fColorSpace) {
885 case ColorSpace::kHSL:
886 case ColorSpace::kHWB:
887 case ColorSpace::kLCH:
888 case ColorSpace::kOKLCH:
889 premulFn = premul_polar;
890 break;
891 default:
892 premulFn = premul_rgb;
893 break;
894 }
895 }
896
897 if (premulFn) {
898 for (int i = 0; i < colorCount; ++i) {
899 fColors[i] = premulFn(fColors[i]);
900 }
901 }
902
903 // Ganesh requires that the positions be explicit (rather than implicitly evenly spaced)
904 if (forceExplicitPositions && !fPositions) {
906 float posScale = 1.0f / (colorCount - 1);
907 for (int i = 0; i < colorCount; i++) {
908 fPositionStorage.push_back(i * posScale);
909 }
911 }
912}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
SkColor4f color
kUnpremul_SkAlphaType
#define SkAssertResult(cond)
Definition SkAssert.h:123
@ kRGBA_F32_SkColorType
pixel using C float for red, green, blue, alpha; in 128-bit word
Definition SkColorType.h:40
bool SkConvertPixels(const SkImageInfo &dstInfo, void *dstPixels, size_t dstRB, const SkImageInfo &srcInfo, const void *srcPixels, size_t srcRB)
static SkPMColor4f srgb_to_hwb(SkPMColor4f rgb, bool *hueIsPowerless)
static SkPMColor4f lin_srgb_to_okhcl(SkPMColor4f rgb, bool *hueIsPowerless)
static SkPMColor4f xyzd50_to_lab(SkPMColor4f xyz, bool *)
SkPMColor4f(*)(SkPMColor4f, bool *) ConvertColorProc
static SkPMColor4f srgb_to_hsl(SkPMColor4f rgb, bool *hueIsPowerless)
static bool color_space_is_polar(SkGradientShader::Interpolation::ColorSpace cs)
SkPMColor4f(*)(SkPMColor4f) PremulColorProc
static SkPMColor4f xyzd50_to_hcl(SkPMColor4f xyz, bool *hueIsPowerless)
static SkPMColor4f premul_polar(SkPMColor4f hsl)
static SkPMColor4f premul_rgb(SkPMColor4f rgb)
static SkPMColor4f lin_srgb_to_oklab(SkPMColor4f rgb, bool *)
static sk_sp< SkColorSpace > intermediate_color_space(SkGradientShader::Interpolation::ColorSpace cs, SkColorSpace *dst)
SkScalar getPos(int i) const
sk_sp< SkColorSpace > fColorSpace
T * push_back_n(int n)
Definition SkTArray.h:262
void reset(int n)
Definition SkTArray.h:139
int size() const
Definition SkTArray.h:416
void swap(TArray &that)
Definition SkTArray.h:353
void reserve_exact(int n)
Definition SkTArray.h:176
ColorSpace
Definition image.h:16
skia_private::STArray< 4, SkPMColor4f > ColorStorage
PositionStorage fPositionStorage
sk_sp< SkColorSpace > fIntermediateColorSpace
skia_private::STArray< 4, float > PositionStorage
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
float fR
red component
Definition SkColor.h:263

Member Data Documentation

◆ fColors

ColorStorage SkColor4fXformer::fColors

Definition at line 181 of file SkGradientBaseShader.h.

◆ fIntermediateColorSpace

sk_sp<SkColorSpace> SkColor4fXformer::fIntermediateColorSpace

Definition at line 184 of file SkGradientBaseShader.h.

◆ fPositions

float* SkColor4fXformer::fPositions

Definition at line 183 of file SkGradientBaseShader.h.

◆ fPositionStorage

PositionStorage SkColor4fXformer::fPositionStorage

Definition at line 182 of file SkGradientBaseShader.h.


The documentation for this struct was generated from the following files: