view draw_outputs.pde @ 0:ebd5689e2985

Initial import of Multipaint sketch version 22.5.2017.
author Tero Heikkinen
date Tue, 03 Jul 2018 20:56:55 +0300
parents
children 5eb3559e1778
line wrap: on
line source

// Collect all that "writes" the virtual image in some way or other
// plus other active manipulations

void createpoint(int x,int y,int mo)
{
  if(mo==LEFT)makepoint(x,y);
  if(mo==RIGHT)clearpoint(x,y);
}

void doborx(int xf,int yf,int xt,int yt)
{
  //rectangle for brush drawing
  for(int ii=xf;ii<=xt;ii++){
    for(int jj=yf;jj<=yt;jj++){
      createpoint(ii,jj,g_button);
    }
  }
}

void docircx(int xf,int yf,int hh,int vv)
{
  //circle for brush drawing
  float prop,fh,fv;
  fh=hh;fv=vv;
  if(vv>0){prop=fh/fv;}else{prop=1;}
  hh++;
  for(int ii=-hh;ii<=hh;ii++){
    for(int jj=-vv;jj<=vv;jj++){
      if(dist(xf+ii,yf+jj*prop,xf,yf)<=hh-1){
        createpoint(xf+ii,yf+jj,g_button);
      }
    }
  }
}

void craft(int x,int y, int c)
{
  //foundational brush control
  //whether hard coded, circular or bitmap brush
  int calc,mb;
  int a1,b1,s1,x0,y0,midx,midy,molox,passes,ofx,ofy;
  ofx=x;ofy=y;mb=g_button;
  if(g_btype==1){
    if(g_bsize<4){
      //some hardcoded brushes
          switch(g_bsize)
          {
          case 0:
            doborx(ofx,ofy,ofx+1,ofy+1);
          break;
          case 1:
            if(g_data['c']==1||g_shift==true){
              ofx=ofx+1;ofy=ofy+1;
            }
            doborx(ofx-1,ofy-1,ofx+1,ofy+1);
          break;
          case 2:
            if(g_data['c']==1||g_shift==true){
              ofx=ofx+2;ofy=ofy+2;
            }
            doborx(ofx-2,ofy-2,ofx+1,ofy+1);
          break;
          case 3:
          if(g_data['c']==1||g_shift==true){
              ofx=ofx+3;ofy=ofy+3;
            }
            doborx(ofx-3,ofy-3,ofx+4,ofy+4);
          break;
          }
    }
    else
    {  //larger size brushes
      calc=g_bsize-3;
      calc=calc*calc;calc=calc+4;
      doborx(x-calc,y-calc,x+calc,y+calc);
    }
  return;
  }

  if(g_btype==9){ //bitmap brush
    passes=2;
    molox=1;
    int tempox,tempoy,tempx,tempy,moloy;
    moloy=1;
    tempox=g_bsourcex;tempoy=g_bsourcey;
    tempx=g_bsourcex2;tempy=g_bsourcey2;
    if(g_data['t']==1){
        if(tempx>g_bsourcex+16)tempx=g_bsourcex+16;
        if(tempy>g_bsourcey+16)tempy=g_bsourcey+16;
    }
    midx=(g_bsourcex2-g_bsourcex)/2;
    midy=(g_bsourcey2-g_bsourcey)/2;
    if(g_data['c']==1||g_shift==true){
      if(g_data['q']==1){
        midy=midy/g_gridx;midy=midy*g_gridx;
        midx=midx/g_gridx;midx=midx*g_gridx;
      }
    }
    int orient;
    orient=g_data['x']*100+g_data['y']*10+g_data['q'];
    if(g_multic==1||g_hzoomer==2){x=x/2;x=x*2;molox=2;passes=1;}

    for(int pp=1;pp<=passes;pp++){
      for(int yy=tempoy;yy<=tempy;yy=yy+moloy){
        for(int xx=tempox;xx<=tempx;xx=xx+molox){
          s1=int(g_brush[1024+xx+yy*X]);
          if(g_multic==0)s1=getabsa(xx,yy,1);
          if(g_multic>0)s1=getmultibrush(xx,yy);
          if(s1!=g_backg){ 
            x0=x+xx-g_bsourcex;
            y0=y+yy-g_bsourcey;
    
            if(g_data['q']==1){
              x0=x-(yy-g_bsourcey2);
              y0=y+(xx-g_bsourcex);
              x0=x0+midx;x0=x0-midy;
              y0=y0+midy;y0=y0-midx;
            }  
    
            if(g_data['x']==1){
              x0=x0-(x+midx);
              x0=-x0;
              x0=x0+(x+midx);  
            }

            if(g_data['y']==1){
              y0=y0-(y+midy);
              y0=-y0;
              y0=y0+(y+midy);
            }
          
           if(g_data['c']==1||g_shift){
              if(orient==10)y0=y0+1;
              if(orient==11)y0=y0+g_gridy-molox;
              if(orient==100)x0=x0+1;
              if(orient==101)x0=x0+g_gridx-1;
              if(orient==110){x0=x0+1;y0=y0+1;}
              if(orient==111){x0=x0+g_gridx-1;y0=y0+g_gridy-molox;}
           }
            
           if(mb==LEFT){  
             if(g_multic>0){
                g_farge=s1;
                if(g_data['p']==1)g_farge=g_ofarge;
                if(g_multic==1||g_hzoomer==2){
                  if(g_data['q']==0)makepoint(x0,y0);
                  if(g_data['q']==1){
                    makepoint(x0-x+x0,y+(y0-y));
                    makepoint(x0-x+x0,y+(y0-y)+1);
                  }
                }else{    
               makepoint(x0,y0);
               }              
              }else
              {
                g_farge=s1;
                if(zxcolor(g_farge)!=zxcolor(g_backg)){
                  if(g_data['p']==1)g_farge=g_ofarge;
                  makepoint(x0,y0);
                }
              }
            }
  
            if(mb==RIGHT){

              if(g_multic>0){
                if(g_multic==1||g_hzoomer==2){
                  if(g_data['q']==0)clearpoint(x0,y0);
                  if(g_data['q']==1){
                    clearpoint(x0-x+x0,y+(y0-y));
                    clearpoint(x0-x+x0,y+(y0-y)+1);
                  }
                }else{              
               clearpoint(x0,y0);}
              }else
              {
               clearpoint(x0,y0);
              }
             }
            }
           }
          }
         }
    g_farge=g_ofarge;
    return;
  }

  if(g_bsize<4){
    switch(g_bsize)
    {
    case 0:
      createpoint(x,y,g_button);
    break;
    case 1:
      createpoint(x,y+1,g_button);createpoint(x,y-1,g_button);
      createpoint(x,y,g_button);
      createpoint(x-1,y,g_button);createpoint(x+1,y,g_button);
    break;
    case 2:        
      doborx(x-1,y-2,x+1,y+2);doborx(x-2,y-1,x+2,y+1);       
    break;
    case 3:
      doborx(x-3,y-1,x+3,y+1);
      doborx(x-1,y-3,x+1,y+3);
      doborx(x-2,y-2,x+2,y+2);
    break;
    }
  }else
  {
    calc=g_bsize-3;
    calc=calc*calc;calc=calc+4;
    docircx(x,y,calc,calc);
  }
}

void doline(int xfrom,int yfrom,int xto,int yto,int prevent)
{
  //bresenham almost exactly from Wikipedia
  int swap,molox,pex,pey;
  boolean steep;
  molox=1;
  //multicolor 160 pixel reso
  if(g_multic==1||g_hzoomer==2){xfrom=xfrom/2;xfrom=xfrom*2;xto=xto/2;xto=xto*2;}

  craft(xfrom,yfrom,0);
  pex=xfrom;pey=yfrom;
  
  if(prevent==0)craft(xto,yto,0);  
  
  if(g_multic==1||g_hzoomer==2){xfrom=xfrom/2;xto=xto/2;molox=2;}
  
  int x0=xfrom;
  int y0=yfrom;
  int x1=xto;
  int y1=yto;
  
  steep=abs(y1 - y0) > abs(x1 - x0);

  if(steep){
    swap=x0;x0=y0;y0=swap;
    swap=x1;x1=y1;y1=swap;
  }  

  float deltax = abs(x1 - x0);
  float deltay = abs(y1 - y0);
  float error = deltax/2;
  int ystep;
   
  if(deltax==0)return;
  
  int y = y0;
  int inc;
   
  if(x0<x1){inc=1;}else{inc=-1;}
  if(y0<y1){ystep=1;}else{ystep=-1;}
  int x;
  x=x0;
  while(x!=x1){
    if(steep){
      if(y*molox!=pex||x!=pey){
        craft(y*molox,x,0);
        pex=y*molox;pey=x;
      }
    }
    else
    {
      if(x*molox!=pex||y!=pey){
        craft(x*molox,y,0);
        pex=x*molox;pey=y;
      }
    }
     
    error=error-deltay;
    if(error<0){
      y=y+ystep;
      error=error+deltax;  
    }
    x=x+inc;
  }
}

void docircle_new(int x1,int y1,int x2,int y2)
{
  int hh,vv;
  float prop;
  int xf,yf;
  float fh,fv;
  if(x2<x1)x2=x1-(x2-x1);
  if(y2<y1)y2=y1-(y2-y1);
  xf=x1;yf=y1;
  hh=x2-x1;vv=y2-y1;
  fh=hh;fv=vv;
  if(vv>0){
    prop=fh/fv;}else{prop=1;}
    hh++;
    for(int ii=-hh;ii<=hh;ii++){
      for(int jj=-vv;jj<=vv;jj++){
        if(dist(xf+ii,yf+jj*prop,xf,yf)<=hh-1){
          createpoint(xf+ii,yf+jj,g_button);
        }
      }
    }
}
  
void docircle(int x1,int y1,int x2,int y2)
{
  float dds,a,t,sx,sy,gear1,gear2,x0,y0;
  int kimea,prex,prey;
  dds=dist(x1,y1,x2,y2);
  gear1=int(dds);
  if(gear1<=12)gear1=12;
  if(gear1>120)gear1=120;
  gear2=int(gear1*2);

  if(x2<x1)x2=x1-(x2-x1);
  if(y2<y1)y2=y1-(y2-y1);
  
  if(g_data['t']==1&&x2>x1+15)x2=x1+16;
  if(g_data['t']==1&&y2>y1+15)y2=y1+16; 
  
  prex=0;prey=0;
  kimea=y1-(y2-y1);
  
  if(g_data['f']==1&&g_btype!=9){
    if(g_multic==1&&g_data['d']==0){
      g_farge=g_map[1];
      docircx(x1,y1,abs(x2-int(x1)),abs(y2-int(y1)));
      g_farge=g_ofarge;     
    }
    docircx(x1,y1,abs(x2-int(x1)),abs(y2-int(y1)));
  }
     
  for(t=0;t<=(gear2);t++){
   a=t/(gear1)*PI;
   sx=(x2-x1)*sin(a);sy=(y1-y2)*cos(a);
   if(t>0)doline(prex,prey,x1+int(sx),y1+int(sy),1);  
   prex=(x1+int(sx));prey=(y1+int(sy)); 
  }
}

void rectangle(int x1,int y1,int x2,int y2)
{
  int x0,y0,molox;
  int yt,xt;
  int xf,yf;
  xf=x1/8;xf=xf*8;xt=x2/8;xt=xt*8;
  yf=y1/8;yf=yf*8;yt=y2/8;yt=yt*8;yt=yt+7;xt=xt+6;
  molox=1;
  if(g_multic==1||g_hzoomer==2)molox=2;
  if(x2<x1){x0=x2;x2=x1;x1=x0;}
  if(y2<y1){y0=y2;y2=y1;y1=y0;}
  
  if(g_data['t']==1&&x2>x1+15)x2=x1+16;
  if(g_data['t']==1&&y2>y1+15)y2=y1+16;  
  
  if(g_btype!=9){
    if(g_data['c']==1||g_shift){
      if(x2>x1)x2--;
      if(y2>y1)y2--;
    }
  }

  if(g_data['f']==1&&g_btype!=9){
    if(g_multic==1&&g_data['d']==0){
       g_farge=g_map[1];
       for(int y=y1;y<=y2;y++){
        for(int x=x1;x<=x2;x=x+molox){
          if(x>=xf&&y>=yf&&x<=xt&&y<=yt){
           makepoint(x,y);
          }
        }
      }
    }
    g_farge=g_ofarge;
    if(g_button==RIGHT)g_farge=g_backg;
    for(int y=y1;y<=y2;y++){
      for(int x=x1;x<=x2;x=x+molox){
        makepoint(x,y);
      }
    }
  }
  if(g_data['f']==0||g_btype==9){
    if(g_data['c']==1&&g_btype==1){
      if(x2>x1){
        if(g_bsize==0)x2--;
        if(g_bsize==1)x2=x2-2;
        if(g_bsize==2)x2=x2-3;
        if(g_bsize==3)x2++;
      }
      if(y2>y1){
        if(g_bsize==0)y2--;
        if(g_bsize==1)y2=y2-2;
        if(g_bsize==2)y2=y2-3;
        if(g_bsize==3)y2++;
      }      
    }
    doline(x1,y1,x2,y1,0);
    doline(x1,y1,x1,y2,0);
    doline(x1,y2,x2,y2,0);
    doline(x2,y2,x2,y1,0);
  }
  g_farge=g_ofarge;
}

void makepoint(int xx,int yy)
{
  //central pixelmaking function
  //has become very messy but what are you gonna do
    int uses[]=new int[8];
    int fars[]=new int[8];
    int mirrix=0;
    int mirriy=0;
    int tiler=0;
    int ignore=0;
    int fari;
      
  //for the X/Y mirrors & tiler, the function calls itself with x+10000 or y+10000
  //resolved here
    if(xx>=20000){
      xx=xx-20000;mirrix=0;mirriy=0;tiler=1;
    }
    if(xx>=10000){xx=xx-10000;mirrix=1;mirriy=1;}
    if(yy>=10000){yy=yy-10000;mirriy=1;mirrix=1;}
    if(xx<0)return;
    if(yy<0)return;
    if(xx>=X)return;
    if(yy>=Y)return;
    
    // adaptive color unless with floodfill (which has its own system)
    if(int(g_map[12])!=5){
      if(g_multic==2)skaveri(xx,yy,g_farge,0);
      
      if(g_multic!=2){
      if(g_data['b']==0){ 
         if(g_multic==1){
           mkaveri(xx,yy,g_farge,0);
         }else{ 
           kaveri(xx,yy,g_farge,0);
         }
       }
       else
       {
         //old iq
         kaveri_iq(xx,yy,g_farge,0);
       }
      }
    }
    
    if(g_multic==1||g_hzoomer==2){
      xx=xx/2;xx=xx*2;
    }

    if(g_data['r']==1){//simple raster
      if(get_raster(xx,yy)==0)ignore=1;
    }
  
  if(g_data['R']==1){//user defined raster
    if(g_bsourcex2>g_bsourcex&&g_bsourcey2>g_bsourcey){

    int x0=xx/((g_bsourcex2+1)-g_bsourcex);
    int y0=yy/((g_bsourcey2+1)-g_bsourcey);
    int x1=xx-x0*((g_bsourcex2+1)-g_bsourcex);
    int y1=yy-y0*((g_bsourcey2+1)-g_bsourcey);
    int xr=g_bsourcex+x1;
    int yr=g_bsourcey+y1;
    if(g_multic==1||g_hzoomer==2){
       x0=xx/((g_bsourcex2+2)-g_bsourcex);
       y0=yy/((g_bsourcey2+1)-g_bsourcey);
       x1=xx-x0*((g_bsourcex2+2)-g_bsourcex);x1=x1/2;x1=x1*2;
       y1=yy-y0*((g_bsourcey2+1)-g_bsourcey);
       xr=g_bsourcex+x1;xr=xr/2;xr=xr*2;
       yr=g_bsourcey+y1;    
       if(getmultic(xr,yr,1)==g_backg)ignore=1;
    }else{
       if(getabsa(xr,yr,1)==g_backg)ignore=1;
    }
//    if(g_brush[1024+xr+yr*X]==0){ignore=1;}
    }
  }
  
 int xc,yc;
 
 if(ignore==0&&g_data['d']==1&&g_attrimode<=1){
   int aba,baba,ii,jj,miny,maxy,ojox,ojoy;
    aba=getattra(xx,yy,0);
    baba=getattra(xx,yy,1);
    if(g_multic==0){
       ojox=xx/8;ojoy=yy/8;
       ojox=ojox*8;ojoy=ojoy*8;
       miny=(yy-ojoy);maxy=miny;
       if(g_attrimode==1){miny=0;maxy=7;}
       if(baba==g_backg)simplepaint(xx,yy,1,g_farge);
       if(aba==g_backg)simplepaint(xx,yy,0,g_farge);
       ignore=1;
       if(g_farge==baba&&g_farge==aba){
          for(jj=miny;jj<=maxy;jj++){
             for(ii=0;ii<8;ii++){
               g_map[1024+ojox+ojoy*X+ii+jj*X]=0;
             }
           }
         }
    }
    else
    {
      if(aba==g_backg){
        ignore=0;}else{ignore=1;}
    }
    xc=xx/8;
    yc=yy/8;
    g_redo[xc+yc*MX]=byte(0);//block update
    g_remdo[xc+yc*MX]=byte(1);//block update
 }
 
 if(ignore==0){
   xc=xx/8;yc=yy/8;
   g_redo[xc+yc*MX]=byte(0);//block update
   g_remdo[xc+yc*MX]=byte(1);//block update    

   switch (g_multic)
   {
   case 0://1-bit + attribute i.e. spectrum
     fari=g_farge;
     if(machine==MSX&&fari==int(g_map[1]))fari=0;
     if(g_britemode==1&&fari==8)fari=0;

     if(getattra(xx,yy,1)==0&&fari==g_map[1]){
       g_map[1024+xx+yy*X]=byte(0); 
     }else
     {
     if(getattra(xx,yy,1)==fari){
        g_map[1024+xx+yy*X]=byte(0);
     }else
     {
       int ojox=xx/8;
       int ojoy=yy/8;
       int mac,macpre,maxos;
       int maxoy,miny,maxy;
       ojox=ojox*8;ojoy=ojoy*8;mac=0;macpre=0;
       miny=0;maxy=7;maxos=64;
       if(g_attrimode==0){miny=(yy-ojoy);maxy=miny;maxos=8;}//MSX
       for(int j=miny;j<=maxy;j++){
         for(int i=0;i<8;i++){
           if(g_map[1024+ojox+ojoy*X+j*X]==1)macpre++;
         }
       }
       g_map[1024+xx+yy*X]=byte(1);
       for(int j=miny;j<=maxy;j++){
         for(int i=0;i<8;i++){
           if(g_map[1024+ojox+ojoy*X+i+j*X]==1)mac++;
         }
       }
       if(mac==maxos){
         for(int j=miny;j<=maxy;j++){
           int vad=1024+ojox+(ojoy+j)*X;
           for(int i=0;i<8;i++){
             g_map[vad]=0;vad++;
           }
         }
         simplepaint(xx,yy,1,fari);   
       }else{
         simplepaint(xx,yy,0,fari);
       }
     }
     }
 break;
 case 1: //c64 style zoomed multicolour
    
      //foreg
      int looks,skippo;
      byte bit1,bit2,valu1,valu2;
      int metax,metay,mex,mey,metamax;
      fari=g_farge;
      int zeroc=int(g_map[1]);int zeroc2=int(g_map[2]);
      boolean cut=false;
      if(fari==zeroc){ //shortcut
           g_map[1024+xx+yy*X]=byte(0);g_map[1024+xx+yy*X+1]=byte(0);
           cut=true;
      }
      if(machine==PLUS4M&&fari==zeroc2){ //shortcut
           g_map[1024+xx+yy*X]=byte(1);g_map[1024+xx+yy*X+1]=byte(1);
           cut=true;
      }
      if(cut){
           // X Y mirrors      
           if(g_data['t']==1){
             if(tiler==0){
               int ex=X/g_gridx;
               int ey=Y/g_gridy;
               for(int tilx=-ex;tilx<=ex;tilx++){
                 for(int tily=-ey;tily<=ey;tily++){
                     makepoint(20000+xx+(X/ex)*tilx,yy+(Y/ey)*tily);
                 }
               }
             }
             return;
           }           
           if(g_data['X']==1&&mirrix==0)makepoint(10000+(X-1)-xx,yy);
           if(g_data['Y']==1&&mirriy==0)makepoint(xx,10000+(Y-1)-yy);
           if(g_data['X']==1&&g_data['Y']==1){if(mirrix==0){makepoint(10000+(X-1)-xx,10000+(Y-1)-yy);}}
           return;
      }     
      
      uses[0]=0;uses[1]=0;uses[2]=0;uses[3]=0;
      fars[0]=zeroc;fars[1]=zeroc;fars[2]=zeroc;fars[3]=zeroc;
      mex=xx/8;mey=yy/8;looks=65536+mex+mey*MX;
      mex=mex*8;mey=mey*8;
      int saps=1024+mex+mey*X;
       
      for(metay=0;metay<=7;metay++){
       for(metax=0;metax<=3;metax++){
         int pars=g_map[saps]+g_map[saps+1]*2;
         uses[pars]=1;
         if(pars==0)fars[0]=zeroc;
         if(pars==1)fars[1]=int(g_map[looks]);
         if(pars==2)fars[2]=int(g_map[looks+1000]);
         if(pars==3){
           if(machine==C64M)fars[3]=int(g_map[looks+2000]);
           if(machine==PLUS4M)fars[3]=zeroc2;
         }   
         saps=saps+2;    
       }
       saps=saps-8+X;
      }

      bit1=0;bit2=0;skippo=0;
      
      // mega-escape, if it's not possible to draw at all don't bother
      if(uses[0]==1&&uses[1]==1&&uses[2]==1&&uses[3]==1){
        if(fari!=fars[0]&&fari!=fars[1]&&fari!=fars[2]&&fari!=fars[3])skippo=100;
      }
 
      if(skippo==0){
        int okay=0;
        metamax=3;
        if(machine==PLUS4M)metamax=2;
        
        // if the color is already in the 4x8 area?
        
        for(metay=0;metay<=metamax;metay++){
          if(uses[metay]==1){
              if(fars[metay]==fari){
                if(metay==1){bit1=1;bit2=0;g_map[looks]=byte(fari);}
                if(metay==2){bit1=0;bit2=1;g_map[looks+1000]=byte(fari);}
                if(metay==3){
                  bit1=1;bit2=1;
                  if(machine==C64M)g_map[looks+2000]=byte(fari);
                  if(machine==PLUS4M)g_map[looks+2000]=byte(zeroc2);
                }
                g_map[1024+xx+yy*X]=bit1;
                g_map[1024+xx+yy*X+1]=bit2;
                okay=1;       
            }
          }
        }
    
        //if the color is not in the 4x8 area
        
        if(okay==0){
          for(metay=1;metay<=metamax;metay++){
            if(uses[metay]==0){
               uses[metay]=1;
               if(metay==1){bit1=1;bit2=0;g_map[looks]=byte(fari);uses[2]=1;}
               if(metay==2){bit1=0;bit2=1;g_map[looks+1000]=byte(fari);uses[3]=1;}
               if(metay==3){bit1=1;bit2=1;
                 if(machine==C64M)g_map[looks+2000]=byte(fari);
                 if(machine==PLUS4M)g_map[looks+2000]=byte(zeroc2);
               }   
               g_map[1024+xx+yy*X]=bit1;
               g_map[1024+xx+yy*X+1]=bit2;    
            }
          }  
        }
    
    }//skippo0
    
 break;
 
 case 2: // VGA style i.e. Amiga, CPC
   fari=g_farge;
      
   if(g_data['d']==1){
       if(g_map[1024+xx+yy*X]==byte(g_backg)){
         g_map[1024+xx+yy*X]=byte(g_farge);
         if(g_hzoomer==2)g_map[1024+xx+yy*X+1]=byte(g_farge);
       }
     }
     else
     {
       g_map[1024+xx+yy*X]=byte(g_farge);
       if(g_hzoomer==2)g_map[1024+xx+yy*X+1]=byte(g_farge);
     }
   break;
 }
 }
 
 // end ignore
 
 // X Y mirrors & tiler
 
 if(g_data['t']==1){
   if(tiler==0){
     int ex=X/g_gridx;
     int ey=Y/g_gridy;
     for(int tilx=-(ex);tilx<=ex;tilx++){
       for(int tily=-(ey);tily<=ey;tily++){
           makepoint(20000+xx+(X/ex)*tilx,yy+(Y/ey)*tily);
         }
       }
   }
   return;
 }
 if(g_data['X']==1&&mirrix==0)makepoint(10000+(X-1)-xx,yy);
 if(g_data['Y']==1&&mirriy==0)makepoint(xx,10000+(Y-1)-yy); 
 if(g_data['X']==1&&g_data['Y']==1){if(mirrix==0){makepoint(10000+(X-1)-xx,10000+(Y-1)-yy);}}
}

void clearpoint(int xx,int yy)
{
  if(g_multic==2){
    g_farge=g_backg;makepoint(xx,yy);g_farge=g_ofarge;return;
  }
  if(g_multic==1){
    xx=xx/2;xx=xx*2;
  }
  g_farge=g_backg;makepoint(xx,yy);g_farge=g_ofarge;return;
}


void absolute_clearpoint(int xx,int yy)
{
  int mirrix=0;
  int mirriy=0;
  int ignore=0;
  if(xx>=10000){xx=xx-10000;mirrix=1;mirriy=1;}
  if(yy>=10000){yy=yy-10000;mirriy=1;mirrix=1;}
  if(xx<0)return;
  if(yy<0)return;
  if(xx>=X)return;
  if(yy>=Y)return;
  
  if(g_multic==2&&g_hzoomer!=2){
    g_farge=g_backg;makepoint(xx,yy);g_farge=g_ofarge;return;
  }
  if(g_multic==1||g_hzoomer==2){
    xx=xx/2;xx=xx*2;
  }
  if(g_data['b']==1)return;
  if(g_data['r']==1){//raster
    if(get_raster(xx,yy)==0)ignore=1;
  }
  
  if(g_data['R']==1){ //user defined raster
    if(g_bsourcex2>g_bsourcex&&g_bsourcey2>g_bsourcey){
      int x0=xx/((g_bsourcex2+1)-g_bsourcex);
      int y0=yy/((g_bsourcey2+1)-g_bsourcey);
      int x1=xx-x0*((g_bsourcex2+1)-g_bsourcex);
      int y1=yy-y0*((g_bsourcey2+1)-g_bsourcey);
      int xr=g_bsourcex+x1;
      int yr=g_bsourcey+y1;
      if(g_brush[1024+xr+yr*X]==0)ignore=1;
    }
  }
  
  if(ignore==0){
    g_map[1024+xx+yy*X]=byte(0);
    if(g_multic==1||g_hzoomer==2)g_map[1024+xx+yy*X+1]=byte(0);
    int xc=xx/8;
    int yc=yy/8;
    g_redo[xc+yc*MX]=byte(0);//block update
    g_remdo[xc+yc*MX]=byte(1);//block update
  }
  if(g_data['X']==1&&mirrix==0)clearpoint(10000+(X-1)-xx,yy);
  if(g_data['Y']==1&&mirriy==0)clearpoint(xx,10000+(Y-1)-yy);
  if(g_data['X']==1&&g_data['Y']==1){
    if(mirrix==0)clearpoint(10000+(X-1)-xx,10000+(Y-1)-yy);
  }
}

void simplepaint(int xx,int yy,int mode,int attr)
{
  int ad,swad,j,miny,maxy,ojyx;
  xx=xx/8;
  ojyx=yy/8;ojyx=ojyx*8;
  ad=0;swad=0;
  miny=yy-ojyx;maxy=miny;
  if(g_attrimode==1){
    miny=0;maxy=7;
  }
  for(j=miny;j<=maxy;j++){
     if(mode==0){ad=65536+xx+(ojyx+j)*MX;swad=65536+xx+(ojyx+j)*MX+(MX*MY)*8;}
     if(mode==1){ad=65536+xx+(ojyx+j)*MX+(MX*MY)*8;swad=65536+xx+(ojyx+j)*MX;}
     if(g_britemode==1){
       if(attr==8)attr=0;
       if(attr>0){
         if(attr>=8&&g_map[swad]<=7)g_map[swad]=byte(g_map[swad]+8);
         if(attr<=7&&g_map[swad]>=8)g_map[swad]=byte(g_map[swad]-8);
       }
     }
     g_map[ad]=byte(attr);
  }
}

void do_tool(int x,int y,int mb)
{
  int tt,ox,oy,psizex,psizey;
  tt=tool();
  psizex=g_magpix[magmode()];
  psizey=g_magpiy[magmode()];
  
  //handles different tool behavior
  
  if(g_data['m']==0&&g_data['M']==0){
    if(g_uizoom==1){x=x/2;y=y/2;}
    if(g_uizoom==2){x=x/3;y=y/3;}
    if(g_uizoom==3){x=x/4;y=y/4;}
  }
  
  if(g_data['m']==1||g_data['M']==1){
      x=x/psizex;y=y/psizey;
      x=x+g_ofx*8;
      y=y+g_ofy*8;
  }

  ox=x;oy=y;g_storedcoordx=x;g_storedcoordy=y;
 
  int midx=0;
  int midy=0;
  //brush handle mid point
  //some tools are exempted
  if(g_btype==9&&tool()!=4&&tool()!=0&&mb!=255){
      midx=(g_bsourcex2-g_bsourcex)/2;
      midy=(g_bsourcey2-g_bsourcey)/2;
      x=x-midx;y=y-midy;
  } 
  if(g_data['c']==1||g_shift){
      x=x/g_gridx;x=x*g_gridx;
      y=y/g_gridy;y=y*g_gridy;
  }
  
  if(g_multic==1||g_hzoomer==2){x=x/2;x=x*2;ox=ox/2;ox=ox*2;}

  if(mb==254){//block picker
      switcher(2);g_data['n']=0;g_data['x']=0;g_data['y']=0;g_data['q']=0;g_data['z']=0;
      x=ox/g_gridx;x=x*g_gridx;y=oy/g_gridy;y=y*g_gridy;
      g_bsourcex=x;g_bsourcey=y;
      g_bsourcex2=x+g_gridx-1;g_bsourcey2=y+g_gridy-1;
      //set_tool(1);
      g_btype=9;
      return;
  }
  
  if(mb==255){ // color picker
    if(g_multic==2){
        if(g_hzoomer==2){ox=ox/2;ox=ox*2;}
        selectcolor(0,getmultic(ox,oy,0));return;
    }
    selectcolor(0,getabsa(ox,oy,0));
    if(g_multic==1||g_hzoomer==2){
      ox=ox/2;ox=ox*2;
      selectcolor(0,getattra(ox,oy,0));
    }
    g_ofarge=g_farge;
    if(g_btype==9)g_data['p']=1;
    g_realfront=byte(g_farge);
    return;
  }
  
  if(x>=0&&y>=0&&x<X&&y<Y&&g_mx<width-g_hedge&&g_my<height-g_vedge)help(1000+x+y*X);
  if(g_phase>0)help(1000+x+y*X);
  
  if(tt==1)craft(x,y,0); //pixeller
  
  if(tt==2){ //spraycan
    //if(random(100)<50){fixed_raster_command('x');}
    //if(random(100)<50){fixed_raster_command('y');}    
    for(int i=0;i<=12;i++){
      int rx=x-10+int(random((10)*2));
      int ry=y-10+int(random((10)*2));
      if(mb==LEFT){
        if(dist(x,y,rx,ry)<10)craft(rx,ry,0);
      }
      else
      {
        if(dist(x,y,rx,ry)<10)craft(rx,ry,0);
      }     
    }
  }
  
  if(tt==3){//cont line
    if(g_phase==0){
      g_prex=x;g_prey=y;craft(x,y,0);
    }
    doline(x,y,g_prex,g_prey,0);
    g_prex=x;g_prey=y;
  }  
   
  if(tt==5){//floodfill
    if(g_klikkeri==0){
      g_klikkeri=1;
      storeparameters();
      g_data['X']=0;g_data['Y']=0;
      g_data['c']=0;g_data['t']=0;
      if(ox>=0&&ox<X&&oy>=0&oy<Y){
        store_undo();// exceptional!
        if(g_multic!=0){floodfillmc(ox,oy,mb);}
          else
          {floodfill_iq(ox,oy,mb);}
      }
      restoreparameters();
    }
  }
  
  if(tt==6||tt==7||tt==8){//line,circle,rect
    if(g_phase==0){g_rx=x;g_ry=y;g_rx2=x;g_ry2=y;g_rubbermode=0;}
    if(g_phase==1){g_rx2=x;g_ry2=y;}
  }

  if(tt==0){ // magnifier graphic tool
    g_data['m']=1;
    g_rx=x-(magx()/2)*8;g_orx=x;
    g_ry=y-(magy()/2)*8;g_ory=y;
    g_rx2=x+(magx()/2+odd(magx()))*8;
    g_ry2=y+(magy()/2+odd(magy()))*8;
    g_data['m']=0;
    g_rubbermode=1;
    if(g_phase==1){
       g_rubbermode=0;g_data['m']=1;set_tool(g_prevtool);g_phase=0;
       g_ofx=x/8-magx()/2;g_ofy=y/8-magy()/2;
       refresh();g_repanel=-2;
    }
  }
  
  if(tt==4){ //brush grabber grab brush
    if(g_phase==0){
       g_rx=x;g_orx=x;
       g_ry=y;g_ory=y;
       g_rx2=x;g_ry2=y;
    }
  
    if(g_phase==1){
      g_rx2=x;g_rx=g_orx;
      g_ry2=y;g_ry=g_ory;
      if(x<g_orx){g_rx2=g_orx;g_rx=x;}
      if(y<g_ory){g_ry2=g_ory;g_ry=y;}
      if(g_data['c']==1||g_shift){
        g_rx2--;g_ry2--;
        if(g_multic==1||g_hzoomer==2)g_rx2--;
      }
    }
    g_rubbermode=1;
  }
  
  if(tt==0||tt==4){
    if(g_rubbermode==1){
      for(int xx=g_rx;xx<=g_rx2+2;xx++){
        updatepoint(xx,g_ry);
        updatepoint(xx,g_ry2);
      }
      for(int yy=g_ry;yy<=g_ry2;yy++){
        updatepoint(g_rx,yy);
        updatepoint(g_rx2,yy);
      }
    }
  }
}