index 57ba651f42c745c48eb489093d2c65a226c2dd8c..e6eb9b79c93a88802362c4987e583fe595dc5e25 100644 (file)
* 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.
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);
}
};
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);
}
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]);
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);
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];
}
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]);
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]);
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]);
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:
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;
}
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)) {
} else {
s = vector_index(NR_GRADIENT_VECTOR_LENGTH - 1, rgr->vector);
}
-
+
compose::compose(pb, d, &spb, s);
d += compose::bpp;
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;
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;