@@ -212,19 +212,37 @@ if(pict[i]->meth) load_rotate(pict[i]); } fclose(fp); } -static inline void show_cursor_xy(int x,int y) { +static inline void show_cursor_xy(int x,int y,int xx,int yy) { char buf[64]; - if(x>=0) snprintf(buf,64,"(%d,%d)%63s",x,y,""); + if(x>=0 && xx>=0) snprintf(buf,64,"[%d,%d]:(%d,%d)%63s",xx,yy,x,y,""); + else if(x>=0) snprintf(buf,64,"(%d,%d)%63s",x,y,""); + else if(xx>=0) snprintf(buf,64,"[%d,%d]%63s",xx,yy,""); else snprintf(buf,64,"%63s",""); SDL_LockSurface(screen); draw_text(0,32,buf,0xF0,0xF9); SDL_UnlockSurface(screen); SDL_Flip(screen); } + +static void draw_line(Uint8*p,Uint8 s,Uint8 x0,Uint8 y0,Uint8 x1,Uint8 y1,Uint8 c) { + int dx=abs(x1-x0); + int sx=x0=dy) e+=dy,x0+=sx; + if(e2<=dx) e+=dx,y0+=sy; + } +} static inline void edit_picture_1(Picture**pict,const char*name) { static const Uint8 shade[64]= "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" @@ -233,26 +251,42 @@ ; 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]={ + "Draw", + "Mark", + "Pick", + "Line", + "Rect", + "Fillrect", + "Circle", + "fIllcirc", + "Ellipse", + "fillellipSe", + }; static Picture*pclip=0; Uint8*p; Uint8*q; Uint8 sel=0; Uint8 cc=0; - SDL_Rect r; + Uint8 t=2; + SDL_Rect r,m; SDL_Event ev; int i,j,x,y,z; + int xx=-1; + int yy=-1; unsigned char buf[256]; + m.x=m.y=m.w=m.h=0; set_cursor(XC_arrow); redraw: if((sel&~15) || !pict[sel]) sel=0; z=screen->w-pict[sel]->size-169; if(z>screen->h-49) z=screen->h-49; z/=pict[sel]->size; - if(z<2) return; + if(z<3) return; if(z>32) z=32; SDL_LockSurface(screen); p=screen->pixels; r.x=r.y=0; r.w=screen->w; r.h=screen->h; SDL_FillRect(screen,&r,0xF0); @@ -260,10 +294,18 @@ x=strlen(name)+1; for(i=0;i<16;i++) if(pict[i]) { j=snprintf(buf,255,"%c%d%c",i==sel?'<':' ',pict[i]->size,i==sel?'>':' '); draw_text(x<<3,0,buf,0xF0,i==sel?0xFF:0xF8); 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 All",0xF0,0xFB); + x=0; + for(i=0;i<10;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; q=pict[sel]->data+pict[sel]->size; for(y=0;ysize;y++) { memcpy(p,q,pict[sel]->size); @@ -292,10 +334,15 @@ for(i=1;ipitch]=i&1?0xF8:0xFF; if(*q) memset(p+i*screen->pitch+1,*q,z-1); else memcpy(p+i*screen->pitch+1,shade+(i&15),z-1); } + if(xx==x && yy==y) { + memset(p+(z/2)*screen->pitch,0xFA,z); + memset(p+(z/2+1)*screen->pitch,0xF2,z); + for(i=1;ipitch+z/2,"\xF2\xFA",2); + } p+=z; q++; } for(i=1;ipitch]=i&1?0xF8:0xFF; p+=z*(screen->pitch-pict[sel]->size); @@ -302,46 +349,176 @@ } for(x=0;xsize;x++) { memcpy(p,gridlines,z); p+=z; } + if(m.h) { + r.x=m.x*z+pict[sel]->size+4; + r.y=m.y*z+43; + r.w=m.w*z-4; + r.h=m.h*z-4; + p=screen->pixels+r.y*screen->pitch+r.x; + for(i=0;ipitch; + } + for(i=0;isize+2 || ev.motion.x>=pict[sel]->size*(z+1)+2 - || ev.motion.y<41 || ev.motion.y>=z*pict[sel]->size+41) { + if(ev.motion.xsize+2 || ev.motion.x>=pict[sel]->size*(z+1)+2 || ev.motion.y<41 || ev.motion.y>=z*pict[sel]->size+41) { x=-1; set_cursor(XC_arrow); } else { x=(ev.motion.x-pict[sel]->size-2)/z; y=(ev.motion.y-41)/z; set_cursor(XC_tcross); + if(ev.motion.state && !t) { + pict[sel]->data[(y+1)*pict[sel]->size+x]=(ev.motion.state&SDL_BUTTON(1)?cc:0); + goto redraw; + } } - show_cursor_xy(x,y); + show_cursor_xy(x,y,xx,yy); break; case SDL_MOUSEBUTTONDOWN: 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: 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(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(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; + } + goto redraw; + } else if(ev.button.x>=pict[sel]->size+2 && ev.button.xsize*(z+1)+2 && ev.button.y>=41 && ev.button.ysize+41) { + x=(ev.button.x-pict[sel]->size-2)/z; + y=(ev.button.y-41)/z; + i=ev.button.button; + if(i>3) break; + switch(t) { + case 0: // Draw + pict[sel]->data[(y+1)*pict[sel]->size+x]=(i==1?cc:0); + break; + case 1: // Mark + if(i==1) { + xx=x; yy=y; + } else if(i==3) { + m.x=(xdata[(y+1)*pict[sel]->size+x]; + goto pick; + case 3: // Line + if((i&2) && xx!=-1) draw_line(pict[sel]->data+pict[sel]->size,pict[sel]->size,x,y,xx,yy,cc); + if(i&1) xx=x,yy=y; + break; + case 4: // Rect + if(i==1) { + xx=x; yy=y; + } else if(xx!=-1) { + p=pict[sel]->data+(j=pict[sel]->size); + if(xxsize; + free(pclip); + pclip=malloc(sizeof(Picture)+(m.h+1)*m.w); + if(!pclip) fatal("Allocation failed\n"); + pclip->meth=m.w; + pclip->size=m.h; + memset(pclip->data,0,m.w); + p=pict[sel]->data+(m.y+1)*pict[sel]->size+m.x; + q=pclip->data+m.w; + for(y=0;ysize; + q+=m.w; + } + goto redraw; + case SDLK_INSERT: case SDLK_KP0: paste: + if(!pclip) break; + if(!m.w) { + m.w=pclip->meth; + m.h=pclip->size; + if(m.w>pict[sel]->size) m.w=pict[sel]->size; + if(m.h>pict[sel]->size) m.h=pict[sel]->size; + } + p=pclip->data+pclip->meth; + q=pict[sel]->data+(m.y+1)*pict[sel]->size+m.x; + for(y=0;ymeth)/m.w; + j=(y*pclip->size)/m.h; + q[x]=p[j*pclip->meth+i]; + } + q+=pict[sel]->size; + } + goto redraw; + case SDLK_DELETE: case SDLK_KP_PERIOD: + if(!m.w) break; + p=pict[sel]->data+(m.y+1)*pict[sel]->size+m.x; + for(y=0;ysize; + goto redraw; + case SDLK_F8: + m.x=m.y=0; + m.w=m.h=pict[sel]->size; + goto redraw; } break; case SDL_VIDEOEXPOSE: goto redraw; }