summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorTeruaki Kawashima <teru@rockbox.org>2010-11-14 14:03:00 +0000
committerTeruaki Kawashima <teru@rockbox.org>2010-11-14 14:03:00 +0000
commite95bca0f8ee9a17d2eb081e699fef3d6d7bf9dcf (patch)
tree128a1aca0d818642ec1db920cff29ae39ebabad5 /apps
parent4480e3a82cc12bddde528331f0838f4f232a148c (diff)
downloadrockbox-e95bca0f8ee9a17d2eb081e699fef3d6d7bf9dcf.tar.gz
rockbox-e95bca0f8ee9a17d2eb081e699fef3d6d7bf9dcf.tar.bz2
rockbox-e95bca0f8ee9a17d2eb081e699fef3d6d7bf9dcf.zip
rockpaint: fix gradient functions.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28585 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/rockpaint.c262
1 files changed, 127 insertions, 135 deletions
diff --git a/apps/plugins/rockpaint.c b/apps/plugins/rockpaint.c
index ab1eb5e3db..6f030d9927 100644
--- a/apps/plugins/rockpaint.c
+++ b/apps/plugins/rockpaint.c
@@ -1587,7 +1587,7 @@ static void draw_line( int x1, int y1, int x2, int y2 )
yerr <<= 1;
/* to leave off the last pixel of the line, leave off the "+ 1" */
- for (i = abs(deltay) + 1; i; --i)
+ for (i = err + 1; i; --i)
{
draw_pixel(x, y);
y += ystep;
@@ -1605,7 +1605,7 @@ static void draw_line( int x1, int y1, int x2, int y2 )
xerr <<= 1;
yerr <<= 1;
- for (i = abs(deltax) + 1; i; --i)
+ for (i = err + 1; i; --i)
{
draw_pixel(x, y);
x += xstep;
@@ -1677,6 +1677,7 @@ static void draw_curve( int x1, int y1, int x2, int y2,
a3 = buffer->bezier[i].x3; \
b3 = buffer->bezier[i].y3; \
d = buffer->bezier[i].depth;
+
PUSH( x1<<4, y1<<4, xb<<4, yb<<4, x2<<4, y2<<4, 0 );
while( i )
{
@@ -1936,124 +1937,103 @@ static void draw_fill( int x0, int y0 )
}
/* For preview purposes only */
+/* use same algorithm as draw_line() to draw line. */
static void line_gradient( int x1, int y1, int x2, int y2 )
{
- int r1, g1, b1;
- int r2, g2, b2;
int h1, s1, v1, h2, s2, v2, r, g, b;
- int w, h, x, y;
-
- bool a = false;
-
- x1 <<= 1;
- y1 <<= 1;
- x2 <<= 1;
- y2 <<= 1;
+ int xerr = x2 - x1, yerr = y2 - y1, xstep, ystep;
+ int i, delta, err;
+ fb_data color1, color2;
- w = x1 - x2;
- h = y1 - y2;
-
- if( w == 0 && h == 0 )
+ if( xerr == 0 && yerr == 0 )
{
- draw_pixel( x1>>1, y1>>1 );
+ draw_pixel( x1, y1 );
return;
}
- r1 = RGB_UNPACK_RED( rp_colors[ bgdrawcolor ] );
- g1 = RGB_UNPACK_GREEN( rp_colors[ bgdrawcolor ] );
- b1 = RGB_UNPACK_BLUE( rp_colors[ bgdrawcolor ] );
- r2 = RGB_UNPACK_RED( rp_colors[ drawcolor ] );
- g2 = RGB_UNPACK_GREEN( rp_colors[ drawcolor ] );
- b2 = RGB_UNPACK_BLUE( rp_colors[ drawcolor ] );
+ xstep = xerr > 0 ? 1 : -1;
+ ystep = yerr > 0 ? 1 : -1;
+ xerr = abs(xerr) << 1;
+ yerr = abs(yerr) << 1;
- if( w < 0 )
- {
- w *= -1;
- a = true;
- }
- if( h < 0 )
- {
- h *= -1;
- a = !a;
- }
- if( a )
- {
- r = r1;
- r1 = r2;
- r2 = r;
- g = g1;
- g1 = g2;
- g2 = g;
- b = b1;
- b1 = b2;
- b2 = b;
- }
+ color1 = rp_colors[ bgdrawcolor ];
+ color2 = rp_colors[ drawcolor ];
- rgb2hsv( r1, g1, b1, &h1, &s1, &v1 );
- rgb2hsv( r2, g2, b2, &h2, &s2, &v2 );
+ r = RGB_UNPACK_RED( color1 );
+ g = RGB_UNPACK_GREEN( color1 );
+ b = RGB_UNPACK_BLUE( color1 );
+ rgb2hsv( r, g, b, &h1, &s1, &v1 );
- if( w > h )
+ r = RGB_UNPACK_RED( color2 );
+ g = RGB_UNPACK_GREEN( color2 );
+ b = RGB_UNPACK_BLUE( color2 );
+ rgb2hsv( r, g, b, &h2, &s2, &v2 );
+
+ if( xerr > yerr )
{
- if( x1 > x2 )
- {
- x = x2;
- y = y2;
- x2 = x1;
- y2 = y1;
- x1 = x;
- y1 = y;
- }
- w = x1 - x2;
- h = y1 - y2;
- while( x1 <= x2 )
+ err = xerr>>1;
+ delta = err+1;
+ /* to leave off the last pixel of the line, leave off the "+ 1" */
+ for (i = delta; i; --i)
{
- hsv2rgb( h1+((h2-h1)*(x1-x2))/w,
- s1+((s2-s1)*(x1-x2))/w,
- v1+((v2-v1)*(x1-x2))/w,
+ hsv2rgb( h2+((h1-h2)*i)/delta,
+ s2+((s1-s2)*i)/delta,
+ v2+((v1-v2)*i)/delta,
&r, &g, &b );
rp_colors[ drawcolor ] = LCD_RGBPACK( r, g, b );
rb->lcd_set_foreground( rp_colors[ drawcolor ] );
- draw_pixel( (x1+1)>>1, (y1+1)>>1 );
- x1+=2;
- y1 = y2 - ( x2 - x1 ) * h / w;
+ draw_pixel(x1, y1);
+ x1 += xstep;
+ err -= yerr;
+ if (err < 0) {
+ y1 += ystep;
+ err += xerr;
+ }
}
}
- else /* h > w */
+ else /* yerr >= xerr */
{
- if( y1 > y2 )
+ err = yerr>>1;
+ delta = err+1;
+ for (i = delta; i; --i)
{
- x = x2;
- y = y2;
- x2 = x1;
- y2 = y1;
- x1 = x;
- y1 = y;
- }
- w = x1 - x2;
- h = y1 - y2;
- while( y1 <= y2 )
- {
- hsv2rgb( h1+((h2-h1)*(y1-y2))/h,
- s1+((s2-s1)*(y1-y2))/h,
- v1+((v2-v1)*(y1-y2))/h,
+ hsv2rgb( h2+((h1-h2)*i)/delta,
+ s2+((s1-s2)*i)/delta,
+ v2+((v1-v2)*i)/delta,
&r, &g, &b );
rp_colors[ drawcolor ] = LCD_RGBPACK( r, g, b );
rb->lcd_set_foreground( rp_colors[ drawcolor ] );
- draw_pixel( (x1+1)>>1, (y1+1)>>1 );
- y1+=2;
- x1 = x2 - ( y2 - y1 ) * w / h;
+ draw_pixel(x1, y1);
+ y1 += ystep;
+ err -= xerr;
+ if (err < 0) {
+ x1 += xstep;
+ err += yerr;
+ }
}
}
- if( a )
- {
- rp_colors[ drawcolor ] = LCD_RGBPACK( r1, g1, b1 );
- }
- else
- {
- rp_colors[ drawcolor ] = LCD_RGBPACK( r2, g2, b2 );
- }
+ rp_colors[ drawcolor ] = color2;
}
+/* macros used by linear_gradient() and radial_gradient(). */
+#define PUSH( _x, _y ) \
+ save_buffer[(_x)+(_y)*COLS] = mark_color; \
+ buffer->coord[i].x = (short)(_x); \
+ buffer->coord[i].y = (short)(_y); \
+ i++;
+#define POP( _x, _y ) \
+ i--; \
+ _x = (int)buffer->coord[i].x; \
+ _y = (int)buffer->coord[i].y;
+#define PUSH2( _x, _y ) \
+ j--; \
+ buffer->coord[j].x = (short)(_x); \
+ buffer->coord[j].y = (short)(_y);
+#define POP2( _x, _y ) \
+ _x = (int)buffer->coord[j].x; \
+ _y = (int)buffer->coord[j].y; \
+ j++;
+
static void linear_gradient( int x1, int y1, int x2, int y2 )
{
int r1 = RGB_UNPACK_RED( rp_colors[ bgdrawcolor ] );
@@ -2062,16 +2042,19 @@ static void linear_gradient( int x1, int y1, int x2, int y2 )
int r2 = RGB_UNPACK_RED( rp_colors[ drawcolor ] );
int g2 = RGB_UNPACK_GREEN( rp_colors[ drawcolor ] );
int b2 = RGB_UNPACK_BLUE( rp_colors[ drawcolor ] );
+ fb_data color = rp_colors[ drawcolor ];
int h1, s1, v1, h2, s2, v2, r, g, b;
/* radius^2 */
int radius2 = ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 );
- int dist2, i=0;
+ int dist2, i=0, j=COLS*ROWS;
/* We only propagate the gradient to neighboring pixels with the same
* color as ( x1, y1 ) */
- unsigned int prev_color = save_buffer[ x1+y1*COLS ];
+ fb_data prev_color = save_buffer[ x1+y1*COLS ];
+ /* to mark pixel that the pixel is already in LIFO. */
+ fb_data mark_color = ~prev_color;
int x = x1;
int y = y1;
@@ -2081,22 +2064,18 @@ static void linear_gradient( int x1, int y1, int x2, int y2 )
{
line_gradient( x1, y1, x2, y2 );
}
+ if( rp_colors[ drawcolor ] == rp_colors[ bgdrawcolor ] )
+ {
+ draw_fill( x1, y1 );
+ return;
+ }
rgb2hsv( r1, g1, b1, &h1, &s1, &v1 );
rgb2hsv( r2, g2, b2, &h2, &s2, &v2 );
-#define PUSH( x0, y0 ) \
- buffer->coord[i].x = (short)(x0); \
- buffer->coord[i].y = (short)(y0); \
- i++;
-#define POP( a, b ) \
- i--; \
- a = (int)buffer->coord[i].x; \
- b = (int)buffer->coord[i].y;
-
PUSH( x, y );
- while( i != 0 )
+ while( i > 0 )
{
POP( x, y );
@@ -2115,14 +2094,13 @@ static void linear_gradient( int x1, int y1, int x2, int y2 )
}
else
{
- rp_colors[ drawcolor ] = LCD_RGBPACK( r2, g2, b2 );
+ rp_colors[ drawcolor ] = color;
}
if( rp_colors[ drawcolor ] == prev_color )
{
- if( rp_colors[ drawcolor ])
- rp_colors[ drawcolor ]--; /* GRUIK */
- else
- rp_colors[ drawcolor ]++; /* GRUIK */
+ /* "mark" that pixel was checked. correct color later. */
+ PUSH2( x, y );
+ rp_colors[ drawcolor ] = mark_color;
}
rb->lcd_set_foreground( rp_colors[ drawcolor ] );
draw_pixel( x, y );
@@ -2144,10 +2122,15 @@ static void linear_gradient( int x1, int y1, int x2, int y2 )
PUSH( x, y+1 );
}
}
-#undef PUSH
-#undef POP
-
- rp_colors[ drawcolor ] = LCD_RGBPACK( r2, g2, b2 );
+ while (j < COLS*ROWS)
+ {
+ /* correct color. */
+ POP2( x, y );
+ rp_colors[ drawcolor ] = prev_color;
+ rb->lcd_set_foreground( rp_colors[ drawcolor ] );
+ draw_pixel( x, y );
+ }
+ rp_colors[ drawcolor ] = color;
}
static void radial_gradient( int x1, int y1, int x2, int y2 )
@@ -2158,16 +2141,19 @@ static void radial_gradient( int x1, int y1, int x2, int y2 )
int r2 = RGB_UNPACK_RED( rp_colors[ drawcolor ] );
int g2 = RGB_UNPACK_GREEN( rp_colors[ drawcolor ] );
int b2 = RGB_UNPACK_BLUE( rp_colors[ drawcolor ] );
+ fb_data color = rp_colors[ drawcolor ];
int h1, s1, v1, h2, s2, v2, r, g, b;
/* radius^2 */
int radius2 = ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 );
- int dist2, i=0;
+ int dist2, i=0, j=COLS*ROWS;
/* We only propagate the gradient to neighboring pixels with the same
* color as ( x1, y1 ) */
- unsigned int prev_color = save_buffer[ x1+y1*COLS ];
+ fb_data prev_color = save_buffer[ x1+y1*COLS ];
+ /* to mark pixel that the pixel is already in LIFO. */
+ fb_data mark_color = ~prev_color;
int x = x1;
int y = y1;
@@ -2177,26 +2163,23 @@ static void radial_gradient( int x1, int y1, int x2, int y2 )
{
line_gradient( x1, y1, x2, y2 );
}
+ if( rp_colors[ drawcolor ] == rp_colors[ bgdrawcolor ] )
+ {
+ draw_fill( x1, y1 );
+ return;
+ }
rgb2hsv( r1, g1, b1, &h1, &s1, &v1 );
rgb2hsv( r2, g2, b2, &h2, &s2, &v2 );
-#define PUSH( x0, y0 ) \
- buffer->coord[i].x = (short)(x0); \
- buffer->coord[i].y = (short)(y0); \
- i++;
-#define POP( a, b ) \
- i--; \
- a = (int)buffer->coord[i].x; \
- b = (int)buffer->coord[i].y;
-
PUSH( x, y );
- while( i != 0 )
+ while( i > 0 )
{
POP( x, y );
- if( ( dist2 = (x1-(x))*(x1-(x))+(y1-(y))*(y1-(y)) ) < radius2 )
+ dist2 = ( x - x1 ) * ( x - x1 ) + ( y - y1 ) * ( y - y1 );
+ if( dist2 < radius2 )
{
hsv2rgb( h1+((h2-h1)*dist2)/radius2,
s1+((s2-s1)*dist2)/radius2,
@@ -2206,14 +2189,13 @@ static void radial_gradient( int x1, int y1, int x2, int y2 )
}
else
{
- rp_colors[ drawcolor ] = LCD_RGBPACK( r2, g2, b2 );
+ rp_colors[ drawcolor ] = color;
}
if( rp_colors[ drawcolor ] == prev_color )
{
- if( rp_colors[ drawcolor ])
- rp_colors[ drawcolor ]--; /* GRUIK */
- else
- rp_colors[ drawcolor ]++; /* GRUIK */
+ /* "mark" that pixel was checked. correct color later. */
+ PUSH2( x, y );
+ rp_colors[ drawcolor ] = mark_color;
}
rb->lcd_set_foreground( rp_colors[ drawcolor ] );
draw_pixel( x, y );
@@ -2235,11 +2217,21 @@ static void radial_gradient( int x1, int y1, int x2, int y2 )
PUSH( x, y+1 );
}
}
+ while (j < COLS*ROWS)
+ {
+ /* correct color. */
+ POP2( x, y );
+ rp_colors[ drawcolor ] = prev_color;
+ rb->lcd_set_foreground( rp_colors[ drawcolor ] );
+ draw_pixel( x, y );
+ }
+ rp_colors[ drawcolor ] = color;
+}
+
#undef PUSH
#undef POP
-
- rp_colors[ drawcolor ] = LCD_RGBPACK( r2, g2, b2 );
-}
+#undef PUSH2
+#undef POP2
static void draw_toolbars(bool update)
{