sammycage / plutovg

Tiny 2D vector graphics library in C

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

RadialGradient: if fr > cr, nothing is rendered

ZhUyU1997 opened this issue · comments

fr: 100, cr: 5

#include "plutovg.h"

int main(void)
{
    const int width = 150;
    const int height = 150;

    plutovg_surface_t *surface = plutovg_surface_create(width, height);
    plutovg_t *pluto = plutovg_create(surface);

    plutovg_save(pluto);
    plutovg_gradient_t *g = plutovg_gradient_create_radial(75, 50, 5, 75, 50, 100);
    plutovg_gradient_add_stop_rgba(g, 0, 1, 0, 0, 1);
    plutovg_gradient_add_stop_rgba(g, 1, 1, 1, 1, 1);
    plutovg_set_source_gradient(pluto, g);
    plutovg_rect(pluto, 10, 10, 150, 100);
    plutovg_fill_preserve(pluto);

    plutovg_restore(pluto);

    plutovg_surface_write_to_png(surface, "smiley.png");
    plutovg_surface_destroy(surface);
    plutovg_destroy(pluto);

    return 0;
}

I can get the result from html canvas with same input.

<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>

<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var grd = ctx.createRadialGradient(90, 60, 100, 75, 50, 5);
grd.addColorStop(0, "red");
grd.addColorStop(1, "white");
ctx.fillStyle = grd;
ctx.fillRect(10, 10, 150, 100);
</script>

</body>
</html>

image

I tried to fix it, although I am not an expert in it. Just for reference.
Note: I removed if(gradient->radial.fr + v->dr * w >= 0), but lack mathematical proof

diff --git a/source/plutovg-blend.c b/source/plutovg-blend.c
index 9dd7541..c43b4c4 100644
--- a/source/plutovg-blend.c
+++ b/source/plutovg-blend.c
@@ -239,22 +239,39 @@ static void fetch_radial_gradient(uint32_t* buffer, const radial_gradient_values
     const uint32_t* end = buffer + length;
     if(v->extended)
     {
-        while(buffer < end)
+        if(v->dr >= 0)
         {
-            uint32_t result = 0;
-            if(det >= 0)
+            while(buffer < end)
             {
-                double w = sqrt(det) - b;
-                if(gradient->radial.fr + v->dr * w >= 0)
-                    result = gradient_pixel(gradient, w);
+                uint32_t result = 0;
+                if(det >= 0)
+                {
+                    result = gradient_pixel(gradient, sqrt(det) - b);
+                }
+                *buffer = result;
+                det += delta_det;
+                delta_det += delta_delta_det;
+                b += delta_b;
+                ++buffer;
             }
-
-            *buffer = result;
-            det += delta_det;
-            delta_det += delta_delta_det;
-            b += delta_b;
-            ++buffer;
         }
+        else
+        {
+            while(buffer < end)
+            {
+                uint32_t result = 0;
+                if(det >= 0)
+                {
+                    result = gradient_pixel(gradient, -sqrt(det) - b);
+                }
+                *buffer = result;
+                det += delta_det;
+                delta_det += delta_delta_det;
+                b += delta_b;
+                ++buffer;
+            }
+        }
+
     }
     else
     {