1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:17:36 +00:00

LibGfx: A few small radial gradient tweaks/fixups

A few very minor changes seemed to small to commit separately:

- Fix typo postive -> positive
- Remove swap(start, end) FIXME, that is the correct thing to do
- Add FIXME for start_radius == end_radius case
- Formatting tweaks
This commit is contained in:
MacDue 2023-08-22 22:29:32 +01:00 committed by Andreas Kling
parent 2b8a9ff2ae
commit df58fa8653

View file

@ -445,16 +445,17 @@ void CanvasConicGradientPaintStyle::paint(IntRect physical_bounding_box, PaintFu
static auto create_radial_gradient_between_two_circles(Gfx::FloatPoint start_center, float start_radius, Gfx::FloatPoint end_center, float end_radius, ReadonlySpan<ColorStop> color_stops, Optional<float> repeat_length) static auto create_radial_gradient_between_two_circles(Gfx::FloatPoint start_center, float start_radius, Gfx::FloatPoint end_center, float end_radius, ReadonlySpan<ColorStop> color_stops, Optional<float> repeat_length)
{ {
if (fabs(start_radius - end_radius) < 1)
start_radius += 1;
// Needed for the start circle > end circle case, but FIXME, this seems kind of hacky.
bool reverse_gradient = end_radius < start_radius; bool reverse_gradient = end_radius < start_radius;
if (reverse_gradient) { if (reverse_gradient) {
swap(end_radius, start_radius); swap(end_radius, start_radius);
swap(end_center, start_center); swap(end_center, start_center);
} }
// FIXME: Handle the start_radius == end_radius special case separately.
// This hack is not quite correct.
if (end_radius - start_radius < 1)
end_radius += 1;
// Spec steps: Useless for writing an actual implementation (give it a go :P): // Spec steps: Useless for writing an actual implementation (give it a go :P):
// //
// 2. Let x(ω) = (x1-x0)ω + x0 // 2. Let x(ω) = (x1-x0)ω + x0
@ -495,48 +496,49 @@ static auto create_radial_gradient_between_two_circles(Gfx::FloatPoint start_cen
auto circle_distance_finder = [=](auto radius, auto center) { auto circle_distance_finder = [=](auto radius, auto center) {
auto radius2 = radius * radius; auto radius2 = radius * radius;
auto delta = center - start_point; auto delta = center - start_point;
auto dx2_factor = (radius2 - delta.y() * delta.y()); auto delta_xy = delta.x() * delta.y();
auto dy2_factor = (radius2 - delta.x() * delta.x()); auto dx2_factor = radius2 - delta.y() * delta.y();
return [=](bool postive_root, auto vec) { auto dy2_factor = radius2 - delta.x() * delta.x();
return [=](bool positive_root, auto vec) {
// This works out the distance to the nearest point on the circle // This works out the distance to the nearest point on the circle
// in the direction of the "vec" vector. // in the direction of the "vec" vector.
auto dx2 = vec.x() * vec.x(); auto dx2 = vec.x() * vec.x();
auto dy2 = vec.y() * vec.y(); auto dy2 = vec.y() * vec.y();
auto root = sqrtf(dx2 * dx2_factor + dy2 * dy2_factor auto root = sqrtf(dx2 * dx2_factor + dy2 * dy2_factor
+ 2 * vec.x() * vec.y() * delta.x() * delta.y()); + 2 * vec.x() * vec.y() * delta_xy);
auto dot = vec.x() * delta.x() + vec.y() * delta.y(); auto dot = vec.x() * delta.x() + vec.y() * delta.y();
return (((postive_root ? root : -root) + dot) / (dx2 + dy2)); return ((positive_root ? root : -root) + dot) / (dx2 + dy2);
}; };
}; };
auto end_circle_dist = circle_distance_finder(end_radius, end_center); auto end_circle_dist = circle_distance_finder(end_radius, end_center);
auto start_circle_dist = [=, dist = circle_distance_finder(start_radius, start_center)](bool postive_root, auto vec) { auto start_circle_dist = [=, dist = circle_distance_finder(start_radius, start_center)](bool positive_root, auto vec) {
if (start_center == start_point) if (start_center == start_point)
return start_radius; return start_radius;
return dist(postive_root, vec); return dist(positive_root, vec);
}; };
return Gradient { return Gradient {
move(gradient_line), move(gradient_line),
[=](float x, float y) { [=](float x, float y) {
auto get_gradient_location = [&] { auto loc = [&] {
FloatPoint point { x, y }; FloatPoint point { x, y };
auto dist = point.distance_from(start_point); auto dist = point.distance_from(start_point);
if (dist == 0) if (dist == 0)
return 0.0f; return 0.0f;
// The "vec" (unit) vector points from the focal point to the current point. // The "vec" (unit) vector points from the focal point to the current point.
auto dist = point.distance_from(start_point);
auto vec = (point - start_point) / dist; auto vec = (point - start_point) / dist;
bool use_postive_root = inner_contained || reverse_gradient; bool use_positive_root = inner_contained || reverse_gradient;
auto dist_end = end_circle_dist(use_postive_root, vec); auto dist_end = end_circle_dist(use_positive_root, vec);
auto dist_start = start_circle_dist(use_postive_root, vec); auto dist_start = start_circle_dist(use_positive_root, vec);
// FIXME: Returning nan is a hack for "Don't paint me!" // FIXME: Returning nan is a hack for "Don't paint me!"
if (dist_end < 0) if (dist_end < 0)
return AK::NaN<float>; return AK::NaN<float>;
if (dist_end - dist_start < 0) if (dist_end - dist_start < 0)
return float(gradient_length); return float(gradient_length);
return (dist - dist_start) / (dist_end - dist_start); return (dist - dist_start) / (dist_end - dist_start);
}; }();
auto loc = get_gradient_location();
if (reverse_gradient) if (reverse_gradient)
loc = 1.0f - loc; loc = 1.0f - loc;
return loc * gradient_length; return loc * gradient_length;