Code

Fix behavior when loading a document
[inkscape.git] / src / libnr / nr-gradient.cpp
index 57ba651f42c745c48eb489093d2c65a226c2dd8c..e6eb9b79c93a88802362c4987e583fe595dc5e25 100644 (file)
@@ -6,7 +6,9 @@
  * Authors:
  *   Lauris Kaplinski <lauris@kaplinski.com>
  *   MenTaLguY <mental@rydia.net>
+ *...Jasper van de Gronde <th.v.d.gronde@hccnet.nl>
  *
+ * Copyright (C) 2009 Jasper van de Gronde
  * Copyright (C) 2007 MenTaLguY 
  * Copyright (C) 2001-2002 Lauris Kaplinski
  * Copyright (C) 2001-2002 Ximian, Inc.
@@ -43,30 +45,44 @@ template <NRGradientSpread spread> struct Spread;
 
 template <>
 struct Spread<NR_GRADIENT_SPREAD_PAD> {
+static double index_at(NR::Coord r, double const unity = 1.0) {
+    return r<0.0?0.0:r>unity?unity:r;
+}
 static unsigned char const *color_at(NR::Coord r,
                                      unsigned char const *vector)
 {
-  return vector_index((int)CLAMP(r, 0, (double)(NR_GRADIENT_VECTOR_LENGTH - 1)), vector);
+    return vector_index((int)(index_at(r, NR_GRADIENT_VECTOR_LENGTH - 1)+.5), vector);
+  //return vector_index((int)CLAMP(r, 0, (double)(NR_GRADIENT_VECTOR_LENGTH - 1)), vector);
 }
 };
 
 template <>
 struct Spread<NR_GRADIENT_SPREAD_REPEAT> {
+static double index_at(NR::Coord r, double const unity = 1.0) {
+    return r<0.0?(unity+fmod(r,unity)):fmod(r,unity);
+}
 static unsigned char const *color_at(NR::Coord r,
                                      unsigned char const *vector)
 {
-  return vector_index((int)((long long)r & NRG_MASK), vector);
+    return vector_index((int)(index_at(r, NR_GRADIENT_VECTOR_LENGTH - 1)+.5), vector);
+  //return vector_index((int)((long long)r & NRG_MASK), vector);
 }
 };
 
 template <>
 struct Spread<NR_GRADIENT_SPREAD_REFLECT> {
+static double index_at(NR::Coord r, double const unity = 1.0) {
+    r = r<0.0?(2*unity+fmod(r,2*unity)):fmod(r,2*unity);
+    if (r>unity) r=2*unity-r;
+    return r;
+}
 static unsigned char const *color_at(NR::Coord r,
                                      unsigned char const *vector)
 {
-  int idx = (int) ((long long)r & NRG_2MASK);
-  if (idx > NRG_MASK) idx = NRG_2MASK - idx;
-  return vector_index(idx, vector);
+    return vector_index((int)(index_at(r, NR_GRADIENT_VECTOR_LENGTH - 1)+.5), vector);
+  //int idx = (int) ((long long)r & NRG_2MASK);
+  //if (idx > NRG_MASK) idx = NRG_2MASK - idx;
+  //return vector_index(idx, vector);
 }
 };
 
@@ -105,8 +121,8 @@ static void compose(NRPixBlock *pb, unsigned char *dest,
 template <>
 struct Compose<NR_PIXBLOCK_MODE_R8G8B8A8N, true> {
 static const unsigned bpp=4;
-static void compose(NRPixBlock *pb, unsigned char *dest,
-                    NRPixBlock *spb, unsigned char const *src)
+static void compose(NRPixBlock */*pb*/, unsigned char *dest,
+                    NRPixBlock */*spb*/, unsigned char const *src)
 {
     std::memcpy(dest, src, 4);
 }
@@ -115,8 +131,8 @@ static void compose(NRPixBlock *pb, unsigned char *dest,
 template <>
 struct Compose<NR_PIXBLOCK_MODE_R8G8B8A8P, true> {
 static const unsigned bpp=4;
-static void compose(NRPixBlock *pb, unsigned char *dest,
-                    NRPixBlock *spb, unsigned char const *src)
+static void compose(NRPixBlock */*pb*/, unsigned char *dest,
+                    NRPixBlock */*spb*/, unsigned char const *src)
 {
     dest[0] = NR_PREMUL_111(src[0], src[3]);
     dest[1] = NR_PREMUL_111(src[1], src[3]);
@@ -128,8 +144,8 @@ static void compose(NRPixBlock *pb, unsigned char *dest,
 template <>
 struct Compose<NR_PIXBLOCK_MODE_R8G8B8, true> {
 static const unsigned bpp=3;
-static void compose(NRPixBlock *pb, unsigned char *dest,
-                    NRPixBlock *spb, unsigned char const *src)
+static void compose(NRPixBlock */*pb*/, unsigned char *dest,
+                    NRPixBlock */*spb*/, unsigned char const *src)
 {
     dest[0] = NR_COMPOSEN11_1111(src[0], src[3], 255);
     dest[1] = NR_COMPOSEN11_1111(src[1], src[3], 255);
@@ -140,8 +156,8 @@ static void compose(NRPixBlock *pb, unsigned char *dest,
 template <>
 struct Compose<NR_PIXBLOCK_MODE_A8, true> {
 static const unsigned bpp=1;
-static void compose(NRPixBlock *pb, unsigned char *dest,
-                    NRPixBlock *spb, unsigned char const *src)
+static void compose(NRPixBlock */*pb*/, unsigned char *dest,
+                    NRPixBlock */*spb*/, unsigned char const *src)
 {
     dest[0] = src[3];
 }
@@ -150,8 +166,8 @@ static void compose(NRPixBlock *pb, unsigned char *dest,
 template <>
 struct Compose<NR_PIXBLOCK_MODE_R8G8B8A8N, false> {
 static const unsigned bpp=4;
-static void compose(NRPixBlock *pb, unsigned char *dest,
-                    NRPixBlock *spb, unsigned char const *src)
+static void compose(NRPixBlock */*pb*/, unsigned char *dest,
+                    NRPixBlock */*spb*/, unsigned char const *src)
 {
     unsigned int ca;
     ca = NR_COMPOSEA_112(src[3], dest[3]);
@@ -165,8 +181,8 @@ static void compose(NRPixBlock *pb, unsigned char *dest,
 template <>
 struct Compose<NR_PIXBLOCK_MODE_R8G8B8A8P, false> {
 static const unsigned bpp=4;
-static void compose(NRPixBlock *pb, unsigned char *dest,
-                    NRPixBlock *spb, unsigned char const *src)
+static void compose(NRPixBlock */*pb*/, unsigned char *dest,
+                    NRPixBlock */*spb*/, unsigned char const *src)
 {
     dest[0] = NR_COMPOSENPP_1111(src[0], src[3], dest[0]);
     dest[1] = NR_COMPOSENPP_1111(src[1], src[3], dest[1]);
@@ -178,8 +194,8 @@ static void compose(NRPixBlock *pb, unsigned char *dest,
 template <>
 struct Compose<NR_PIXBLOCK_MODE_R8G8B8, false> {
 static const unsigned bpp=3;
-static void compose(NRPixBlock *pb, unsigned char *dest,
-                    NRPixBlock *spb, unsigned char const *src)
+static void compose(NRPixBlock */*pb*/, unsigned char *dest,
+                    NRPixBlock */*spb*/, unsigned char const *src)
 {
     dest[0] = NR_COMPOSEN11_1111(src[0], src[3], dest[0]);
     dest[1] = NR_COMPOSEN11_1111(src[1], src[3], dest[1]);
@@ -233,11 +249,9 @@ render_spread(NRGradientRenderer *gr, NRPixBlock *pb)
 
 template <typename Subtype>
 static void
-render(NRRenderer *r, NRPixBlock *pb, NRPixBlock *m)
+render(NRRenderer *r, NRPixBlock *pb, NRPixBlock */*m*/)
 {
-    NRGradientRenderer *gr;
-
-    gr = static_cast<NRGradientRenderer *>(r);
+    NRGradientRenderer *gr = static_cast<NRGradientRenderer *>(r);
 
     switch (gr->spread) {
     case NR_GRADIENT_SPREAD_REPEAT:
@@ -321,10 +335,10 @@ nr_lgradient_renderer_setup (NRLGradientRenderer *lgr,
        n2px = n2gs * (*gs2px);
        px2n = n2px.inverse();
 
-       lgr->x0 = n2px[4] - 0.5;
+       lgr->x0 = n2px[4] - 0.5; // These -0.5 offsets make sure that the gradient is sampled in the MIDDLE of each pixel.
        lgr->y0 = n2px[5] - 0.5;
-       lgr->dx = px2n[0] * NR_GRADIENT_VECTOR_LENGTH;
-       lgr->dy = px2n[2] * NR_GRADIENT_VECTOR_LENGTH;
+       lgr->dx = px2n[0] * (NR_GRADIENT_VECTOR_LENGTH-1);
+       lgr->dy = px2n[2] * (NR_GRADIENT_VECTOR_LENGTH-1);
 
        return (NRRenderer *) lgr;
 }
@@ -424,7 +438,7 @@ static void render(NRGradientRenderer *gr, NRPixBlock *pb)
             NR::Coord const pxgx = gx + sqrt(qgx2_4);
             /* We can safely divide by 0 here */
             /* If we are sure pxgx cannot be -0 */
-            NR::Coord const pos = gxy2 / pxgx * NR_GRADIENT_VECTOR_LENGTH;
+            NR::Coord const pos = gxy2 / pxgx * (NR_GRADIENT_VECTOR_LENGTH-1);
 
             unsigned char const *s;
             if (pos < (1U << 31)) {
@@ -432,7 +446,7 @@ static void render(NRGradientRenderer *gr, NRPixBlock *pb)
             } else {
                 s = vector_index(NR_GRADIENT_VECTOR_LENGTH - 1, rgr->vector);
             }
-            
+
             compose::compose(pb, d, &spb, s);
             d += compose::bpp;
 
@@ -468,14 +482,16 @@ nr_rgradient_renderer_setup(NRRGradientRenderer *rgr,
         rgr->render = render<SymmetricRadial>;
 
         rgr->px2gs = gs2px->inverse();
-        rgr->px2gs[0] *= (NR_GRADIENT_VECTOR_LENGTH / r);
-        rgr->px2gs[1] *= (NR_GRADIENT_VECTOR_LENGTH / r);
-        rgr->px2gs[2] *= (NR_GRADIENT_VECTOR_LENGTH / r);
-        rgr->px2gs[3] *= (NR_GRADIENT_VECTOR_LENGTH / r);
+        rgr->px2gs[0] *= (NR_GRADIENT_VECTOR_LENGTH-1) / r;
+        rgr->px2gs[1] *= (NR_GRADIENT_VECTOR_LENGTH-1) / r;
+        rgr->px2gs[2] *= (NR_GRADIENT_VECTOR_LENGTH-1) / r;
+        rgr->px2gs[3] *= (NR_GRADIENT_VECTOR_LENGTH-1) / r;
         rgr->px2gs[4] -= cx;
         rgr->px2gs[5] -= cy;
-        rgr->px2gs[4] *= (NR_GRADIENT_VECTOR_LENGTH / r);
-        rgr->px2gs[5] *= (NR_GRADIENT_VECTOR_LENGTH / r);
+        rgr->px2gs[4] *= (NR_GRADIENT_VECTOR_LENGTH-1) / r;
+        rgr->px2gs[5] *= (NR_GRADIENT_VECTOR_LENGTH-1) / r;
+        rgr->px2gs[4] += 0.5*(rgr->px2gs[0]+rgr->px2gs[2]); // These offsets make sure the gradient is sampled in the MIDDLE of each pixel
+        rgr->px2gs[5] += 0.5*(rgr->px2gs[1]+rgr->px2gs[3]);
 
         rgr->cx = 0.0;
         rgr->cy = 0.0;
@@ -502,6 +518,8 @@ nr_rgradient_renderer_setup(NRRGradientRenderer *rgr,
         NR::Matrix n2px;
         n2px = n2gs * (*gs2px);
         rgr->px2gs = n2px.inverse();
+        rgr->px2gs[4] += 0.5*(rgr->px2gs[0]+rgr->px2gs[2]); // These offsets make sure the gradient is sampled in the MIDDLE of each pixel
+        rgr->px2gs[5] += 0.5*(rgr->px2gs[1]+rgr->px2gs[3]);
 
         rgr->cx = 1.0;
         rgr->cy = 0.0;