summaryrefslogtreecommitdiff
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
parent4480e3a82cc12bddde528331f0838f4f232a148c (diff)
downloadrockbox-e95bca0f8ee9a17d2eb081e699fef3d6d7bf9dcf.tar.gz
rockbox-e95bca0f8ee9a17d2eb081e699fef3d6d7bf9dcf.zip
rockpaint: fix gradient functions.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28585 a1c6a512-1295-4272-9138-f99709370657
-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 )
1587 yerr <<= 1; 1587 yerr <<= 1;
1588 1588
1589 /* to leave off the last pixel of the line, leave off the "+ 1" */ 1589 /* to leave off the last pixel of the line, leave off the "+ 1" */
1590 for (i = abs(deltay) + 1; i; --i) 1590 for (i = err + 1; i; --i)
1591 { 1591 {
1592 draw_pixel(x, y); 1592 draw_pixel(x, y);
1593 y += ystep; 1593 y += ystep;
@@ -1605,7 +1605,7 @@ static void draw_line( int x1, int y1, int x2, int y2 )
1605 xerr <<= 1; 1605 xerr <<= 1;
1606 yerr <<= 1; 1606 yerr <<= 1;
1607 1607
1608 for (i = abs(deltax) + 1; i; --i) 1608 for (i = err + 1; i; --i)
1609 { 1609 {
1610 draw_pixel(x, y); 1610 draw_pixel(x, y);
1611 x += xstep; 1611 x += xstep;
@@ -1677,6 +1677,7 @@ static void draw_curve( int x1, int y1, int x2, int y2,
1677 a3 = buffer->bezier[i].x3; \ 1677 a3 = buffer->bezier[i].x3; \
1678 b3 = buffer->bezier[i].y3; \ 1678 b3 = buffer->bezier[i].y3; \
1679 d = buffer->bezier[i].depth; 1679 d = buffer->bezier[i].depth;
1680
1680 PUSH( x1<<4, y1<<4, xb<<4, yb<<4, x2<<4, y2<<4, 0 ); 1681 PUSH( x1<<4, y1<<4, xb<<4, yb<<4, x2<<4, y2<<4, 0 );
1681 while( i ) 1682 while( i )
1682 { 1683 {
@@ -1936,124 +1937,103 @@ static void draw_fill( int x0, int y0 )
1936} 1937}
1937 1938
1938/* For preview purposes only */ 1939/* For preview purposes only */
1940/* use same algorithm as draw_line() to draw line. */
1939static void line_gradient( int x1, int y1, int x2, int y2 ) 1941static void line_gradient( int x1, int y1, int x2, int y2 )
1940{ 1942{
1941 int r1, g1, b1;
1942 int r2, g2, b2;
1943 int h1, s1, v1, h2, s2, v2, r, g, b; 1943 int h1, s1, v1, h2, s2, v2, r, g, b;
1944 int w, h, x, y; 1944 int xerr = x2 - x1, yerr = y2 - y1, xstep, ystep;
1945 1945 int i, delta, err;
1946 bool a = false; 1946 fb_data color1, color2;
1947
1948 x1 <<= 1;
1949 y1 <<= 1;
1950 x2 <<= 1;
1951 y2 <<= 1;
1952 1947
1953 w = x1 - x2; 1948 if( xerr == 0 && yerr == 0 )
1954 h = y1 - y2;
1955
1956 if( w == 0 && h == 0 )
1957 { 1949 {
1958 draw_pixel( x1>>1, y1>>1 ); 1950 draw_pixel( x1, y1 );
1959 return; 1951 return;
1960 } 1952 }
1961 1953
1962 r1 = RGB_UNPACK_RED( rp_colors[ bgdrawcolor ] ); 1954 xstep = xerr > 0 ? 1 : -1;
1963 g1 = RGB_UNPACK_GREEN( rp_colors[ bgdrawcolor ] ); 1955 ystep = yerr > 0 ? 1 : -1;
1964 b1 = RGB_UNPACK_BLUE( rp_colors[ bgdrawcolor ] ); 1956 xerr = abs(xerr) << 1;
1965 r2 = RGB_UNPACK_RED( rp_colors[ drawcolor ] ); 1957 yerr = abs(yerr) << 1;
1966 g2 = RGB_UNPACK_GREEN( rp_colors[ drawcolor ] );
1967 b2 = RGB_UNPACK_BLUE( rp_colors[ drawcolor ] );
1968 1958
1969 if( w < 0 ) 1959 color1 = rp_colors[ bgdrawcolor ];
1970 { 1960 color2 = rp_colors[ drawcolor ];
1971 w *= -1;
1972 a = true;
1973 }
1974 if( h < 0 )
1975 {
1976 h *= -1;
1977 a = !a;
1978 }
1979 if( a )
1980 {
1981 r = r1;
1982 r1 = r2;
1983 r2 = r;
1984 g = g1;
1985 g1 = g2;
1986 g2 = g;
1987 b = b1;
1988 b1 = b2;
1989 b2 = b;
1990 }
1991 1961
1992 rgb2hsv( r1, g1, b1, &h1, &s1, &v1 ); 1962 r = RGB_UNPACK_RED( color1 );
1993 rgb2hsv( r2, g2, b2, &h2, &s2, &v2 ); 1963 g = RGB_UNPACK_GREEN( color1 );
1964 b = RGB_UNPACK_BLUE( color1 );
1965 rgb2hsv( r, g, b, &h1, &s1, &v1 );
1994 1966
1995 if( w > h ) 1967 r = RGB_UNPACK_RED( color2 );
1968 g = RGB_UNPACK_GREEN( color2 );
1969 b = RGB_UNPACK_BLUE( color2 );
1970 rgb2hsv( r, g, b, &h2, &s2, &v2 );
1971
1972 if( xerr > yerr )
1996 { 1973 {
1997 if( x1 > x2 ) 1974 err = xerr>>1;
1998 { 1975 delta = err+1;
1999 x = x2; 1976 /* to leave off the last pixel of the line, leave off the "+ 1" */
2000 y = y2; 1977 for (i = delta; i; --i)
2001 x2 = x1;
2002 y2 = y1;
2003 x1 = x;
2004 y1 = y;
2005 }
2006 w = x1 - x2;
2007 h = y1 - y2;
2008 while( x1 <= x2 )
2009 { 1978 {
2010 hsv2rgb( h1+((h2-h1)*(x1-x2))/w, 1979 hsv2rgb( h2+((h1-h2)*i)/delta,
2011 s1+((s2-s1)*(x1-x2))/w, 1980 s2+((s1-s2)*i)/delta,
2012 v1+((v2-v1)*(x1-x2))/w, 1981 v2+((v1-v2)*i)/delta,
2013 &r, &g, &b ); 1982 &r, &g, &b );
2014 rp_colors[ drawcolor ] = LCD_RGBPACK( r, g, b ); 1983 rp_colors[ drawcolor ] = LCD_RGBPACK( r, g, b );
2015 rb->lcd_set_foreground( rp_colors[ drawcolor ] ); 1984 rb->lcd_set_foreground( rp_colors[ drawcolor ] );
2016 draw_pixel( (x1+1)>>1, (y1+1)>>1 ); 1985 draw_pixel(x1, y1);
2017 x1+=2; 1986 x1 += xstep;
2018 y1 = y2 - ( x2 - x1 ) * h / w; 1987 err -= yerr;
1988 if (err < 0) {
1989 y1 += ystep;
1990 err += xerr;
1991 }
2019 } 1992 }
2020 } 1993 }
2021 else /* h > w */ 1994 else /* yerr >= xerr */
2022 { 1995 {
2023 if( y1 > y2 ) 1996 err = yerr>>1;
1997 delta = err+1;
1998 for (i = delta; i; --i)
2024 { 1999 {
2025 x = x2; 2000 hsv2rgb( h2+((h1-h2)*i)/delta,
2026 y = y2; 2001 s2+((s1-s2)*i)/delta,
2027 x2 = x1; 2002 v2+((v1-v2)*i)/delta,
2028 y2 = y1;
2029 x1 = x;
2030 y1 = y;
2031 }
2032 w = x1 - x2;
2033 h = y1 - y2;
2034 while( y1 <= y2 )
2035 {
2036 hsv2rgb( h1+((h2-h1)*(y1-y2))/h,
2037 s1+((s2-s1)*(y1-y2))/h,
2038 v1+((v2-v1)*(y1-y2))/h,
2039 &r, &g, &b ); 2003 &r, &g, &b );
2040 rp_colors[ drawcolor ] = LCD_RGBPACK( r, g, b ); 2004 rp_colors[ drawcolor ] = LCD_RGBPACK( r, g, b );
2041 rb->lcd_set_foreground( rp_colors[ drawcolor ] ); 2005 rb->lcd_set_foreground( rp_colors[ drawcolor ] );
2042 draw_pixel( (x1+1)>>1, (y1+1)>>1 ); 2006 draw_pixel(x1, y1);
2043 y1+=2; 2007 y1 += ystep;
2044 x1 = x2 - ( y2 - y1 ) * w / h; 2008 err -= xerr;
2009 if (err < 0) {
2010 x1 += xstep;
2011 err += yerr;
2012 }
2045 } 2013 }
2046 } 2014 }
2047 if( a ) 2015 rp_colors[ drawcolor ] = color2;
2048 {
2049 rp_colors[ drawcolor ] = LCD_RGBPACK( r1, g1, b1 );
2050 }
2051 else
2052 {
2053 rp_colors[ drawcolor ] = LCD_RGBPACK( r2, g2, b2 );
2054 }
2055} 2016}
2056 2017
2018/* macros used by linear_gradient() and radial_gradient(). */
2019#define PUSH( _x, _y ) \
2020 save_buffer[(_x)+(_y)*COLS] = mark_color; \
2021 buffer->coord[i].x = (short)(_x); \
2022 buffer->coord[i].y = (short)(_y); \
2023 i++;
2024#define POP( _x, _y ) \
2025 i--; \
2026 _x = (int)buffer->coord[i].x; \
2027 _y = (int)buffer->coord[i].y;
2028#define PUSH2( _x, _y ) \
2029 j--; \
2030 buffer->coord[j].x = (short)(_x); \
2031 buffer->coord[j].y = (short)(_y);
2032#define POP2( _x, _y ) \
2033 _x = (int)buffer->coord[j].x; \
2034 _y = (int)buffer->coord[j].y; \
2035 j++;
2036
2057static void linear_gradient( int x1, int y1, int x2, int y2 ) 2037static void linear_gradient( int x1, int y1, int x2, int y2 )
2058{ 2038{
2059 int r1 = RGB_UNPACK_RED( rp_colors[ bgdrawcolor ] ); 2039 int r1 = RGB_UNPACK_RED( rp_colors[ bgdrawcolor ] );
@@ -2062,16 +2042,19 @@ static void linear_gradient( int x1, int y1, int x2, int y2 )
2062 int r2 = RGB_UNPACK_RED( rp_colors[ drawcolor ] ); 2042 int r2 = RGB_UNPACK_RED( rp_colors[ drawcolor ] );
2063 int g2 = RGB_UNPACK_GREEN( rp_colors[ drawcolor ] ); 2043 int g2 = RGB_UNPACK_GREEN( rp_colors[ drawcolor ] );
2064 int b2 = RGB_UNPACK_BLUE( rp_colors[ drawcolor ] ); 2044 int b2 = RGB_UNPACK_BLUE( rp_colors[ drawcolor ] );
2045 fb_data color = rp_colors[ drawcolor ];
2065 2046
2066 int h1, s1, v1, h2, s2, v2, r, g, b; 2047 int h1, s1, v1, h2, s2, v2, r, g, b;
2067 2048
2068 /* radius^2 */ 2049 /* radius^2 */
2069 int radius2 = ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ); 2050 int radius2 = ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 );
2070 int dist2, i=0; 2051 int dist2, i=0, j=COLS*ROWS;
2071 2052
2072 /* We only propagate the gradient to neighboring pixels with the same 2053 /* We only propagate the gradient to neighboring pixels with the same
2073 * color as ( x1, y1 ) */ 2054 * color as ( x1, y1 ) */
2074 unsigned int prev_color = save_buffer[ x1+y1*COLS ]; 2055 fb_data prev_color = save_buffer[ x1+y1*COLS ];
2056 /* to mark pixel that the pixel is already in LIFO. */
2057 fb_data mark_color = ~prev_color;
2075 2058
2076 int x = x1; 2059 int x = x1;
2077 int y = y1; 2060 int y = y1;
@@ -2081,22 +2064,18 @@ static void linear_gradient( int x1, int y1, int x2, int y2 )
2081 { 2064 {
2082 line_gradient( x1, y1, x2, y2 ); 2065 line_gradient( x1, y1, x2, y2 );
2083 } 2066 }
2067 if( rp_colors[ drawcolor ] == rp_colors[ bgdrawcolor ] )
2068 {
2069 draw_fill( x1, y1 );
2070 return;
2071 }
2084 2072
2085 rgb2hsv( r1, g1, b1, &h1, &s1, &v1 ); 2073 rgb2hsv( r1, g1, b1, &h1, &s1, &v1 );
2086 rgb2hsv( r2, g2, b2, &h2, &s2, &v2 ); 2074 rgb2hsv( r2, g2, b2, &h2, &s2, &v2 );
2087 2075
2088#define PUSH( x0, y0 ) \
2089 buffer->coord[i].x = (short)(x0); \
2090 buffer->coord[i].y = (short)(y0); \
2091 i++;
2092#define POP( a, b ) \
2093 i--; \
2094 a = (int)buffer->coord[i].x; \
2095 b = (int)buffer->coord[i].y;
2096
2097 PUSH( x, y ); 2076 PUSH( x, y );
2098 2077
2099 while( i != 0 ) 2078 while( i > 0 )
2100 { 2079 {
2101 POP( x, y ); 2080 POP( x, y );
2102 2081
@@ -2115,14 +2094,13 @@ static void linear_gradient( int x1, int y1, int x2, int y2 )
2115 } 2094 }
2116 else 2095 else
2117 { 2096 {
2118 rp_colors[ drawcolor ] = LCD_RGBPACK( r2, g2, b2 ); 2097 rp_colors[ drawcolor ] = color;
2119 } 2098 }
2120 if( rp_colors[ drawcolor ] == prev_color ) 2099 if( rp_colors[ drawcolor ] == prev_color )
2121 { 2100 {
2122 if( rp_colors[ drawcolor ]) 2101 /* "mark" that pixel was checked. correct color later. */
2123 rp_colors[ drawcolor ]--; /* GRUIK */ 2102 PUSH2( x, y );
2124 else 2103 rp_colors[ drawcolor ] = mark_color;
2125 rp_colors[ drawcolor ]++; /* GRUIK */
2126 } 2104 }
2127 rb->lcd_set_foreground( rp_colors[ drawcolor ] ); 2105 rb->lcd_set_foreground( rp_colors[ drawcolor ] );
2128 draw_pixel( x, y ); 2106 draw_pixel( x, y );
@@ -2144,10 +2122,15 @@ static void linear_gradient( int x1, int y1, int x2, int y2 )
2144 PUSH( x, y+1 ); 2122 PUSH( x, y+1 );
2145 } 2123 }
2146 } 2124 }
2147#undef PUSH 2125 while (j < COLS*ROWS)
2148#undef POP 2126 {
2149 2127 /* correct color. */
2150 rp_colors[ drawcolor ] = LCD_RGBPACK( r2, g2, b2 ); 2128 POP2( x, y );
2129 rp_colors[ drawcolor ] = prev_color;
2130 rb->lcd_set_foreground( rp_colors[ drawcolor ] );
2131 draw_pixel( x, y );
2132 }
2133 rp_colors[ drawcolor ] = color;
2151} 2134}
2152 2135
2153static void radial_gradient( int x1, int y1, int x2, int y2 ) 2136static 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 )
2158 int r2 = RGB_UNPACK_RED( rp_colors[ drawcolor ] ); 2141 int r2 = RGB_UNPACK_RED( rp_colors[ drawcolor ] );
2159 int g2 = RGB_UNPACK_GREEN( rp_colors[ drawcolor ] ); 2142 int g2 = RGB_UNPACK_GREEN( rp_colors[ drawcolor ] );
2160 int b2 = RGB_UNPACK_BLUE( rp_colors[ drawcolor ] ); 2143 int b2 = RGB_UNPACK_BLUE( rp_colors[ drawcolor ] );
2144 fb_data color = rp_colors[ drawcolor ];
2161 2145
2162 int h1, s1, v1, h2, s2, v2, r, g, b; 2146 int h1, s1, v1, h2, s2, v2, r, g, b;
2163 2147
2164 /* radius^2 */ 2148 /* radius^2 */
2165 int radius2 = ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ); 2149 int radius2 = ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 );
2166 int dist2, i=0; 2150 int dist2, i=0, j=COLS*ROWS;
2167 2151
2168 /* We only propagate the gradient to neighboring pixels with the same 2152 /* We only propagate the gradient to neighboring pixels with the same
2169 * color as ( x1, y1 ) */ 2153 * color as ( x1, y1 ) */
2170 unsigned int prev_color = save_buffer[ x1+y1*COLS ]; 2154 fb_data prev_color = save_buffer[ x1+y1*COLS ];
2155 /* to mark pixel that the pixel is already in LIFO. */
2156 fb_data mark_color = ~prev_color;
2171 2157
2172 int x = x1; 2158 int x = x1;
2173 int y = y1; 2159 int y = y1;
@@ -2177,26 +2163,23 @@ static void radial_gradient( int x1, int y1, int x2, int y2 )
2177 { 2163 {
2178 line_gradient( x1, y1, x2, y2 ); 2164 line_gradient( x1, y1, x2, y2 );
2179 } 2165 }
2166 if( rp_colors[ drawcolor ] == rp_colors[ bgdrawcolor ] )
2167 {
2168 draw_fill( x1, y1 );
2169 return;
2170 }
2180 2171
2181 rgb2hsv( r1, g1, b1, &h1, &s1, &v1 ); 2172 rgb2hsv( r1, g1, b1, &h1, &s1, &v1 );
2182 rgb2hsv( r2, g2, b2, &h2, &s2, &v2 ); 2173 rgb2hsv( r2, g2, b2, &h2, &s2, &v2 );
2183 2174
2184#define PUSH( x0, y0 ) \
2185 buffer->coord[i].x = (short)(x0); \
2186 buffer->coord[i].y = (short)(y0); \
2187 i++;
2188#define POP( a, b ) \
2189 i--; \
2190 a = (int)buffer->coord[i].x; \
2191 b = (int)buffer->coord[i].y;
2192
2193 PUSH( x, y ); 2175 PUSH( x, y );
2194 2176
2195 while( i != 0 ) 2177 while( i > 0 )
2196 { 2178 {
2197 POP( x, y ); 2179 POP( x, y );
2198 2180
2199 if( ( dist2 = (x1-(x))*(x1-(x))+(y1-(y))*(y1-(y)) ) < radius2 ) 2181 dist2 = ( x - x1 ) * ( x - x1 ) + ( y - y1 ) * ( y - y1 );
2182 if( dist2 < radius2 )
2200 { 2183 {
2201 hsv2rgb( h1+((h2-h1)*dist2)/radius2, 2184 hsv2rgb( h1+((h2-h1)*dist2)/radius2,
2202 s1+((s2-s1)*dist2)/radius2, 2185 s1+((s2-s1)*dist2)/radius2,
@@ -2206,14 +2189,13 @@ static void radial_gradient( int x1, int y1, int x2, int y2 )
2206 } 2189 }
2207 else 2190 else
2208 { 2191 {
2209 rp_colors[ drawcolor ] = LCD_RGBPACK( r2, g2, b2 ); 2192 rp_colors[ drawcolor ] = color;
2210 } 2193 }
2211 if( rp_colors[ drawcolor ] == prev_color ) 2194 if( rp_colors[ drawcolor ] == prev_color )
2212 { 2195 {
2213 if( rp_colors[ drawcolor ]) 2196 /* "mark" that pixel was checked. correct color later. */
2214 rp_colors[ drawcolor ]--; /* GRUIK */ 2197 PUSH2( x, y );
2215 else 2198 rp_colors[ drawcolor ] = mark_color;
2216 rp_colors[ drawcolor ]++; /* GRUIK */
2217 } 2199 }
2218 rb->lcd_set_foreground( rp_colors[ drawcolor ] ); 2200 rb->lcd_set_foreground( rp_colors[ drawcolor ] );
2219 draw_pixel( x, y ); 2201 draw_pixel( x, y );
@@ -2235,11 +2217,21 @@ static void radial_gradient( int x1, int y1, int x2, int y2 )
2235 PUSH( x, y+1 ); 2217 PUSH( x, y+1 );
2236 } 2218 }
2237 } 2219 }
2220 while (j < COLS*ROWS)
2221 {
2222 /* correct color. */
2223 POP2( x, y );
2224 rp_colors[ drawcolor ] = prev_color;
2225 rb->lcd_set_foreground( rp_colors[ drawcolor ] );
2226 draw_pixel( x, y );
2227 }
2228 rp_colors[ drawcolor ] = color;
2229}
2230
2238#undef PUSH 2231#undef PUSH
2239#undef POP 2232#undef POP
2240 2233#undef PUSH2
2241 rp_colors[ drawcolor ] = LCD_RGBPACK( r2, g2, b2 ); 2234#undef POP2
2242}
2243 2235
2244static void draw_toolbars(bool update) 2236static void draw_toolbars(bool update)
2245{ 2237{