
/*From: http://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland */

#include "gfd.h"

#include "gfd_p_.h"

#ifndef __cplusplus
#define bool int
#define true 1
#define false 0
#endif

int gfd_fb_liang_barsky_line_clip(gfd_framebuffer_t* const fb,  int* const ix0, int* const iy0, int* const ix1, int* const iy1)
//int gfd_fb_liang_barsky_line_clip(gfd_framebuffer_t* const fb,  int* const ix0, int* const iy0, int* const ix1, int* const iy1)
{
  double edgeLeft=fb->ox;
  double edgeRight=fb->ex-1;
  double edgeTop=fb->ey-1;
  double edgeBottom=fb->oy;
  double x0src=*ix0;
  double y0src=*iy0;
  double x1src=*ix1;
  double y1src=*iy1;

    double t0 = 0.0;    double t1 = 1.0;
    double xdelta = x1src-x0src;
    double ydelta = y1src-y0src;
    double p,q,r;
    int edge;

    q=0;
    p=1;

    for(edge=0; edge<4; edge++) {   // Traverse through left, right, bottom, top edges.
        if (edge==0) {  p = -xdelta;    q = -(edgeLeft-x0src);  }
        if (edge==1) {  p = xdelta;     q =  (edgeRight-x0src); }
        if (edge==2) {  p = -ydelta;    q = -(edgeBottom-y0src);}
        if (edge==3) {  p = ydelta;     q =  (edgeTop-y0src);   }   
        r = q/p;
        if(p==0 && q<0) return 0;   // Don't draw line at all. (parallel line outside)

        if(p<0) {
            if(r>t1) return 0;         // Don't draw line at all.
            else if(r>t0) t0=r;            // Line is clipped!
        } else if(p>0) {
            if(r<t0) return 0;      // Don't draw line at all.
            else if(r<t1) t1=r;         // Line is clipped!
        }
    }

    *ix0=gfd_nint(x0src + t0*xdelta);
    *iy0=gfd_nint(y0src + t0*ydelta);
    *ix1=gfd_nint(x0src + t1*xdelta);
    *iy1=gfd_nint(y0src + t1*ydelta);

    //Debug:
    {
      int really_ok=
       ((*ix0<fb->ox) || (*ix0>=fb->ex)) ||
       ((*ix1<fb->ox) || (*ix1>=fb->ex)) ||
       ((*iy0<fb->oy) || (*iy0>=fb->ey)) ||
       ((*iy0<fb->oy) || (*iy0>=fb->ey));

      if (really_ok)
        return 0;
    }

    return 1;        // (clipped) line is drawn
}

