@@ -20,6 +20,21 @@ struct ColorStop {
2020
2121 // / The color of the gradient stop.
2222 ColorU color;
23+
24+ bool operator <(const ColorStop &rhs) const {
25+ if (offset != rhs.offset ) {
26+ return offset < rhs.offset ;
27+ }
28+ return color < rhs.color ;
29+ }
30+
31+ bool operator ==(const ColorStop &rhs) const {
32+ return offset == rhs.offset && color == rhs.color ;
33+ }
34+
35+ bool operator !=(const ColorStop &rhs) const {
36+ return !(*this == rhs);
37+ }
2338};
2439
2540struct GradientRadial {
@@ -130,22 +145,38 @@ class Gradient {
130145
131146 // For being used as ordered key.
132147 bool operator <(const Gradient &rhs) const {
133- if (wrap == rhs.wrap ) {
134- if (geometry.type == rhs.geometry .type ) {
135- if (geometry.type == GradientGeometry::Type::Linear) {
136- return geometry.linear < rhs.geometry .linear ;
137- } else {
138- bool res = geometry.radial .line < rhs.geometry .radial .line ;
139- res = res && geometry.radial .radii < rhs.geometry .radial .radii ;
140- res = res && geometry.radial .transform < rhs.geometry .radial .transform ;
141- return res;
142- }
143- } else {
144- return geometry.type < rhs.geometry .type ;
145- }
146- } else {
148+ // 1. Compare the outer wrap mode first.
149+ if (wrap != rhs.wrap ) {
147150 return wrap < rhs.wrap ;
148151 }
152+
153+ // 2. Compare the gradient geometry type.
154+ if (geometry.type != rhs.geometry .type ) {
155+ return geometry.type < rhs.geometry .type ;
156+ }
157+
158+ // 3. Branch based on the type and perform strict lexicographical comparison.
159+ if (geometry.type == GradientGeometry::Type::Linear) {
160+ // Standard total-ordering chain for linear gradient.
161+ if (geometry.linear < rhs.geometry .linear ) return true ;
162+ if (rhs.geometry .linear < geometry.linear ) return false ;
163+ } else { // Radial
164+ // CRITICAL FIX: Replaced the incorrect '&&' logic with lexicographical comparison
165+ // using std::forward_as_tuple to maintain Strict Weak Ordering for rvalues/lvalues.
166+ auto tuple_lhs =
167+ std::forward_as_tuple (geometry.radial .line , geometry.radial .radii , geometry.radial .transform );
168+ auto tuple_rhs = std::forward_as_tuple (rhs.geometry .radial .line ,
169+ rhs.geometry .radial .radii ,
170+ rhs.geometry .radial .transform );
171+ if (tuple_lhs != tuple_rhs) {
172+ return tuple_lhs < tuple_rhs;
173+ }
174+ }
175+
176+ // 4. CRITICAL FIX: Compare the 'stops' vector (color stops).
177+ // If all geometry attributes are identical, gradients with different colors must not be treated as equivalent.
178+ // std::vector's operator< automatically performs a sequential lexicographical comparison on its elements.
179+ return stops < rhs.stops ;
149180 }
150181
151182private:
0 commit comments