From 31c9d97d7757968e8275b611fab047125aad01cd Mon Sep 17 00:00:00 2001 From: kramm Date: Wed, 20 Aug 2008 13:25:14 +0000 Subject: [PATCH] implemented gradients --- lib/devices/render.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 113 insertions(+), 9 deletions(-) diff --git a/lib/devices/render.c b/lib/devices/render.c index 0170621..b8dc813 100644 --- a/lib/devices/render.c +++ b/lib/devices/render.c @@ -28,6 +28,7 @@ #define PNG_INLINE_EXPORTS #include "../types.h" #include "../png.c" +#include "../log.h" #include "render.h" typedef gfxcolor_t RGBA; @@ -76,15 +77,16 @@ typedef struct _internal { internal_result_t*result_next; } internal_t; -typedef enum {filltype_solid,filltype_clip,filltype_bitmap} filltype_t; +typedef enum {filltype_solid,filltype_clip,filltype_bitmap,filltype_gradient} filltype_t; typedef struct _fillinfo { - filltype_t type; //0=solid,1=clip + filltype_t type; gfxcolor_t*color; gfximage_t*image; gfxmatrix_t*matrix; gfxcxform_t*cxform; - char clip; + RGBA*gradient; + char clip_or_radial; } fillinfo_t; @@ -333,7 +335,7 @@ static void fill_line_bitmap(RGBA*line, U32*z, int y, int x1, int x2, fillinfo_t int yy = (int)(yy1 - x * yinc1); int ainv; - if(info->clip) { + if(info->clip_or_radial) { if(xx<0) xx=0; if(xx>=b->width) xx = b->width-1; if(yy<0) yy=0; @@ -361,6 +363,61 @@ static void fill_line_bitmap(RGBA*line, U32*z, int y, int x1, int x2, fillinfo_t } while(++xmatrix; + RGBA*g= info->gradient; + + double det = m->m00*m->m11 - m->m01*m->m10; + if(fabs(det) < 0.0005) { + /* x direction equals y direction */ + return; + } + det = 1.0/det; + double xx1 = ( (-m->tx) * m->m11 - (y - m->ty) * m->m10) * det; + double yy1 = (- (-m->tx) * m->m01 + (y - m->ty) * m->m00) * det; + double xinc1 = m->m11 * det; + double yinc1 = m->m01 * det; + + U32 bit = 1<<(x1&31); + int bitpos = (x1/32); + + do { + if(z[bitpos]&bit) { + RGBA col; + int ainv; + + int pos = 0; + if(info->clip_or_radial) { + double xx = xx1 + x * xinc1; + double yy = yy1 + y * yinc1; + double r = sqrt(xx*xx + yy*yy); + if(r>1) r = 1; + pos = (int)(r*255.999); + } else { + double r = xx1 + x * xinc1; + if(r>1) r = 1; + if(r<-1) r = -1; + pos = (int)((r+1)*127.999); + } + col = g[pos]; + ainv = 255-col.a; + + /* needs bitmap with premultiplied alpha */ + line[x].r = ((line[x].r*ainv)>>8)+col.r; + line[x].g = ((line[x].g*ainv)>>8)+col.g; + line[x].b = ((line[x].b*ainv)>>8)+col.b; + line[x].a = 255; + } + bit <<= 1; + if(!bit) { + bit = 1;bitpos++; + } + } while(++xtype == filltype_bitmap) fill_line_bitmap(line, zline, y, startx, endx, fill); - // etc. + else if(fill->type == filltype_gradient) + fill_line_gradient(line, zline, y, startx, endx, fill); } void fill(gfxdevice_t*dev, fillinfo_t*fill) @@ -615,8 +673,6 @@ void render_fillbitmap(struct _gfxdevice*dev, gfxline_t*line, gfximage_t*img, gf { internal_t*i = (internal_t*)dev->internal; - gfxcolor_t black = {255,0,0,0}; - gfxmatrix_t m2 = *matrix; draw_line(dev, line); @@ -638,10 +694,58 @@ void render_fillgradient(struct _gfxdevice*dev, gfxline_t*line, gfxgradient_t*gr { internal_t*i = (internal_t*)dev->internal; - gfxcolor_t black = {255,0,0,0}; + gfxmatrix_t m2 = *matrix; draw_line(dev, line); - fill_solid(dev, &black); + + RGBA g[256]; + fillinfo_t info; + memset(&info, 0, sizeof(info)); + info.type = filltype_gradient; + info.gradient = g; + info.matrix = &m2; + + m2.m00 *= i->zoom; m2.m01 *= i->zoom; m2.tx *= i->zoom; + m2.m10 *= i->zoom; m2.m11 *= i->zoom; m2.ty *= i->zoom; + + info.clip_or_radial = type == gfxgradient_radial; + + int pos = 0; + gfxcolor_t color = {0,0,0,0}; + pos=0; + while(gradient) { + int nextpos = gradient->pos*256; + int t; + if(nextpos>256) { + msg(" Invalid gradient- contains values > 1.0"); + return; + } + + gfxcolor_t nextcolor = gradient->color; + if(nextpos!=pos) { + double p0 = 1.0; + double p1 = 0.0; + double step = 1.0/(nextpos-pos); + int t; + for(t=pos;tnext; + } + if(pos!=256) { + msg(" Invalid gradient- doesn't end with 1.0"); + } + + fill(dev, &info); } void render_addfont(struct _gfxdevice*dev, gfxfont_t*font) -- 1.7.10.4