Index: picedit.c ================================================================== --- picedit.c +++ picedit.c @@ -91,11 +91,11 @@ } static int vt_graph_connect(sqlite3*db,void*aux,int argc,const char*const*argv,sqlite3_vtab**vt,char**ex) { *vt=sqlite3_malloc(sizeof(sqlite3_vtab)); if(!*vt) return SQLITE_NOMEM; - sqlite3_declare_vtab(db,"CREATE TABLE `GRID`(`X` INT, `Y` INT, `C` INT);"); + sqlite3_declare_vtab(db,"CREATE TABLE `GRAPH`(`X` INT, `Y` INT, `C` INT);"); return SQLITE_OK; } static int vt_graph_disconnect(sqlite3_vtab*vt) { sqlite3_free(vt); @@ -541,10 +541,37 @@ ry=0.5*(y1-y0); for(y=y0;y<=y1;y++) for(x=x0;x<=x1;x++) { if(pow((x-cx)/rx,2.0)+pow((y-cy)/ry,2.0)<=1.0) p[y*s+x]=c; } } + +static void flood(Uint8 x,Uint8 y,Uint8 mx,Uint8 my,Uint8 mw,Uint8 mh,Uint8 c,Uint8 c0,Uint8 b) { + sqlite3_stmt*st; + if(c0==c) return; + if(sqlite3_prepare_v2(userdb, + // This isn't as efficient as it should be, since it has to scan the entire table every time. + "INSERT INTO GRAPH(X,Y,C) WITH R(XX,YY) AS (" + "SELECT ?1,?2 UNION SELECT X,Y FROM R,GRAPH WHERE C=?4" + " AND ABS(X-XX)+ABS(Y-YY)<>?5 AND ABS(X-XX)<2 AND ABS(Y-YY)<2" + " AND X>=?6 AND X=?7 AND Yformat->palette->colors; int a,b,i,j,x,y; Uint8 buf[16]; @@ -626,11 +653,11 @@ ; static const Uint8 gridlines[32]= "\xF8\xFF\xF8\xFF\xF8\xFF\xF8\xFF\xF8\xFF\xF8\xFF\xF8\xFF\xF8\xFF" "\xF8\xFF\xF8\xFF\xF8\xFF\xF8\xFF\xF8\xFF\xF8\xFF\xF8\xFF\xF8\xFF" ; - static const char*const tool[10]={ + static const char*const tool[11]={ "Draw", "Mark", "Pick", "Line", "Rect", @@ -637,10 +664,11 @@ "Fillrect", "Circle", "fIllcirc", "Ellipse", "fillellipSe", + "flOod", }; static Picture*pclip=0; Uint8*p; Uint8*q; Uint8 sel=0; @@ -674,11 +702,11 @@ x+=j; } draw_text(0,8," Exit <1-9> Sel Unmark Copy Paste Erase",0xF0,0xFB); draw_text(0,16," CW CCW \x12 \x1D Size Add Del Mark In Out",0xF0,0xFB); x=0; - for(i=0;i<10;i++) { + for(i=0;i<11;i++) { j=snprintf(buf,255,"%c%s%c",i==t?'<':' ',tool[i],i==t?'>':' '); draw_text(x<<3,24,buf,0xF0,i==t?0xFE:0xF8); x+=j; } p=screen->pixels+40*screen->pitch; @@ -767,23 +795,28 @@ if(ev.button.x>=screen->w-161 && ev.button.xw-1 && ev.button.y>=40 && ev.button.y<200) { x=(ev.button.x+161-screen->w)/10; y=(ev.button.y-40)/10; i=y*16+x; pick: + y=SDL_GetModState(); switch(ev.button.button) { case 1: cc=i; break; case 2: for(x=(m.y+1)*pict[sel]->size+m.x;xsize*(pict[sel]->size+1);x++) { - if(pict[sel]->data[x]==cc) pict[sel]->data[x]=i; + if(!y || ((y&(KMOD_CTRL|KMOD_SHIFT)) && (((x-x/pict[sel]->size)^(y&KMOD_CTRL?1:0))&1))) { + if(pict[sel]->data[x]==cc) pict[sel]->data[x]=i; + } if(m.w && x%pict[sel]->size==m.x+m.w-1) x+=pict[sel]->size-m.w; if(m.h && x/pict[sel]->size>m.h+m.y) break; } break; case 3: for(x=(m.y+1)*pict[sel]->size+m.x;xsize*(pict[sel]->size+1);x++) { - if(pict[sel]->data[x]==cc) pict[sel]->data[x]=i; - else if(pict[sel]->data[x]==i) pict[sel]->data[x]=cc; + if(!y || ((y&(KMOD_CTRL|KMOD_SHIFT)) && (((x-x/pict[sel]->size)^(y&KMOD_CTRL?1:0))&1))) { + if(pict[sel]->data[x]==cc) pict[sel]->data[x]=i; + else if(pict[sel]->data[x]==i) pict[sel]->data[x]=cc; + } if(m.w && x%pict[sel]->size==m.x+m.w-1) x+=pict[sel]->size-m.w; if(m.h && x/pict[sel]->size>m.h+m.y) break; } break; } @@ -868,10 +901,13 @@ } else if(xx!=-1) { fill_ellipse(pict[sel]->data+pict[sel]->size,pict[sel]->size,x,y,xx,yy,cc); draw_ellipse(pict[sel]->data+pict[sel]->size,pict[sel]->size,x,y,xx,yy,cc); } break; + case 10: // Flood + if(!m.w) m.x=m.y=m.h=0; + flood(x,y,m.x,m.y,m.w?:pict[sel]->size,m.h?:pict[sel]->size,cc,pict[sel]->data[(y+1)*pict[sel]->size+x],i); } goto redraw; } break; case SDL_KEYDOWN: @@ -885,10 +921,11 @@ case SDLK_e: t=8; xx=yy=-1; goto redraw; case SDLK_f: t=5; xx=yy=-1; goto redraw; case SDLK_i: t=7; xx=yy=-1; goto redraw; case SDLK_l: t=3; xx=yy=-1; goto redraw; case SDLK_m: t=1; xx=yy=-1; goto redraw; + case SDLK_o: t=10; xx=yy=-1; goto redraw; case SDLK_p: t=2; xx=yy=-1; goto redraw; case SDLK_r: t=4; xx=yy=-1; goto redraw; case SDLK_s: t=9; xx=yy=-1; goto redraw; case SDLK_TAB: if(ev.key.keysym.mod&KMOD_SHIFT) --sel; else ++sel; m.x=m.y=m.w=m.h=0; goto redraw; case SDLK_SPACE: Index: picedit.doc ================================================================== --- picedit.doc +++ picedit.doc @@ -188,10 +188,20 @@ Filled ellipse (S) Click the left button on one corner of the bounding rectangle of the ellipse, and then click the middle or right button on the other side. +Flood (O) + Click any button to flood an area of a solid colour with the current + colour. Which button decides the directions to use, where the left + button means the von Neumann neighbourhood and the right button means + the Moore neighbourhood. + +For clicking in the palette or the Pick mode, with the middle or right +mouse button, you can also push CTRL or SHIFT keys with it in order to +affect only odd or only even coordinates. + === Dependent pictures === A depedent picture depends on one or more independent pictures. It consists of any combination of the following items, in any order: