
#include "gfd.h"
#include "math.h"

#include "gfd_p_.h"

#define GFD_PI 3.14159265358979323846
#define GFD_PI2 (2*GFD_PI)

#define DX45(n_) (n_*(GFD_PI/4))

#define D180 GFD_PI
#define D360 GFD_PI2
#define D90 (GFD_PI/2)
#define D270 (GFD_PI+D90)
#define D178 (GFD_PI-0.03490658503988659154)


void gfd_clip_rect(gfd_rect_t* const r, int x0, int y0, int x1, int y1)
{
	/*
  if (r->p0.x<x0)
    r->p0.x=x0;
  if (r->p0.x>=x1)
    r->p0.x=x1-1;

  if (r->p1.x<x0)
    r->p1.x=x0;
  if (r->p1.x>=x1)
    r->p1.x=x1-1;

  if (r->p0.y<y0)
    r->p0.y=y0;
  if (r->p0.y>=y1)
    r->p0.y=y1-1;

  if (r->p1.y<y0)
    r->p1.y=y0;
  if (r->p1.y>=y1)
    r->p1.y=y1-1;
    */
  if (r->p0.x<x0)
	r->p0.x=x0;
  if (r->p0.x>x1)
	r->p0.x=x1;

  if (r->p1.x<x0)
	r->p1.x=x0;
  if (r->p1.x>x1)
	r->p1.x=x1;

  if (r->p0.y<y0)
	r->p0.y=y0;
  if (r->p0.y>y1)
	r->p0.y=y1;

  if (r->p1.y<y0)
	r->p1.y=y0;
  if (r->p1.y>y1)
	r->p1.y=y1;
}

#define p_inside(r_, x_, y_) p_inside_((r_), (x_), (y_))
#define p_inside_(r_, x_, y_) (x_>=r_.p0.x && x_<=r_.p1.x && y_>=r_.p0.y && y_<=r_.p1.y)
/*
static int p_inside(const gfd_rect_t* const r, int x, int y)
{
  if (x<r->p0.x)
    return 0;
  if (y<r->p0.y)
    return 0;
  if (x>r->p1.x)
    return 0;
  if (y>r->p1.y)
    return 0;
  return 1;
}
*/

#define circ_draw_pixel(fb_, bb_, x0_, x_, y0_, y_, c_) \
  (p_inside(bb_, (x_), (y_)) ? (fb_set_pixel_no_clip(fb_, x0_+(x_), y0_+(y_), c_)) : (void)(0))

static void gfd_fb_draw_circle_bb(gfd_framebuffer_t* const fb, const gfd_rect_t* const bb, int x0, int y0, int radius, int cc)
{
  int f = 1 - radius;
  int ddF_x = 1;
  int ddF_y = -2 * radius;
  int x = 0;
  int y = radius;
  gfd_rect_t rect=*bb;

  gfd_pixel_t color=GFD_PIXEL(cc);

  gfd_clip_rect(&rect, fb->ox-x0, fb->oy-y0, fb->ex-x0, fb->ey-y0);

  while(x <= y)
  {

    circ_draw_pixel(fb, rect, x0, + x, y0, + y, color);
    circ_draw_pixel(fb, rect, x0, - x, y0, + y, color);
    circ_draw_pixel(fb, rect, x0, + x, y0, - y, color);
    circ_draw_pixel(fb, rect, x0, - x, y0, - y, color);
    circ_draw_pixel(fb, rect, x0, + y, y0, + x, color);
    circ_draw_pixel(fb, rect, x0, - y, y0, + x, color);
    circ_draw_pixel(fb, rect, x0, + y, y0, - x, color);
    circ_draw_pixel(fb, rect, x0, - y, y0, - x, color);

    if(f >= 0)
    {
      y--;
      ddF_y += 2;
      f += ddF_y;
    }
    x++;
    ddF_x += 2;
    f += ddF_x;
  }
}

static void gfd_fb_draw_circle_bb_2cols(gfd_framebuffer_t* const fb, const gfd_rect_t* const bb, int x0, int y0, int radius, int c1, int c2)
{
  int f = 1 - radius;
  int ddF_x = 1;
  int ddF_y = -2 * radius;
  int x = 0;
  int y = radius;
  gfd_rect_t rect=*bb;

  gfd_pixel_t color1=GFD_PIXEL(c1);
  gfd_pixel_t color2=GFD_PIXEL(c2);

  gfd_clip_rect(&rect, fb->ox-x0, fb->oy-y0, fb->ex-x0, fb->ey-y0);

  while(x <= y)
  {

    circ_draw_pixel(fb, rect, x0, + x, y0, + y, color2);
    circ_draw_pixel(fb, rect, x0, - x, y0, + y, color1);
    circ_draw_pixel(fb, rect, x0, + x, y0, - y, color1);
    circ_draw_pixel(fb, rect, x0, - x, y0, - y, color2);
    circ_draw_pixel(fb, rect, x0, + y, y0, + x, color1);
    circ_draw_pixel(fb, rect, x0, - y, y0, + x, color2);
    circ_draw_pixel(fb, rect, x0, + y, y0, - x, color2);
    circ_draw_pixel(fb, rect, x0, - y, y0, - x, color1);

    if(f >= 0)
    {
      y--;
      ddF_y += 2;
      f += ddF_y;
    }
    x++;
    ddF_x += 2;
    f += ddF_x;
  }
}

static const struct {
  int s;
  int c;
} k_sc[]=
{
  { 0,  1}, /*0*/
  { 1,  0}, /*90*/
  { 0, -1}, /*180*/
  {-1,  0}, /*270*/
  { 0,  1},  /*360*/
  { 1,  0}, /*90*/
  { 0, -1}, /*180*/
  {-1,  0} /*270*/
};

/*
static void arc_p2xy(gfd_point_t* const p, double angle, double r)
{
  double tmp=r*cos(angle);
  p->x=gfd_round(tmp);
  tmp=r*sin(angle);
  p->y=gfd_round(tmp);
}
*/

static void arc_limit_angles(double* const start, double* const stop)
{
  double angleStart=*start;
  double angleStop=*stop;

  while(angleStart<0)
    angleStart=angleStart+GFD_PI2;
  while(angleStart>=D360)
    angleStart=angleStart-GFD_PI2;
  while(angleStop<0)
    angleStop=angleStop+GFD_PI2;
  while(angleStop>=D360)
    angleStop=angleStop-GFD_PI2;

  if (angleStop<angleStart)
    angleStop+=D360;

  *start=angleStart;
  *stop=angleStop;
}

static void arc_calc_bb(gfd_rect_t* const bb, int x0, int y0, int radius, double angleStart, double angleStop)
{
  int i, k;
  int x, y;
  double r=radius;
  gfd_rect_t rect;
  const int samples=sizeof(k_sc)/sizeof(k_sc[0]);
  double a;

  //arc_p2xy(&rect.p0, angleStart, r);

  rect.p0.x=gfd_round(r*cos(angleStart));
  rect.p0.y=gfd_round(r*sin(angleStart));

  rect.p1=rect.p0;

  x=gfd_round(r*cos(angleStop));
  y=gfd_round(r*sin(angleStop));

  if (x<rect.p0.x)
    rect.p0.x=x;
  if (x>rect.p1.x)
    rect.p1.x=x;
  if (y<rect.p0.y)
    rect.p0.y=y;
  if (y>rect.p1.y)
    rect.p1.y=y;

  for(k=0, i=0; i<samples; ++i)
  {
    a=D90*(double)(i);
    if (angleStart<a && angleStop>a)
    {
      x=radius*k_sc[i].c;
      y=radius*k_sc[i].s;

      if (x<rect.p0.x)
        rect.p0.x=x;
      if (x>rect.p1.x)
        rect.p1.x=x;
      if (y<rect.p0.y)
        rect.p0.y=y;
      if (y>rect.p1.y)
        rect.p1.y=y;

      if (k>=3)
        break;

      ++k;
    }
  }

  rect.p0.x+=x0;
  rect.p1.x+=x0;
  rect.p0.y+=y0;
  rect.p1.y+=y0;

  *bb=rect;
}

void gfd_calc_arc_bb(gfd_rect_t* const bb, int x0, int y0, int radius, double angleStart, double angleStop)
{
  arc_limit_angles(&angleStart, &angleStop);
  arc_calc_bb(bb, x0, y0, radius, angleStart, angleStop);
}


void gfd_fb_draw_arc179(gfd_framebuffer_t* const fb, int x0, int y0, int radius, double angleStart, double angleStop, int color)
{
  gfd_fb_draw_arc179_func(gfd_fb_draw_circle_bb, fb, x0, y0, radius, angleStart, angleStop, color);
}

void gfd_fb_draw_arc179_func(gfd_fb_draw_circle_bb_function_t f, gfd_framebuffer_t* const fb, int x0, int y0, int radius, double angleStart, double angleStop, int color)
{
  gfd_rect_t bb;

  angleStart+=D90;
  angleStop+=D90;

  arc_limit_angles(&angleStart, &angleStop);
  if (angleStop-angleStart>=D360)
  {
    gfd_fb_draw_circle(fb, x0, y0, radius, color);
    return;
  }
  if (angleStop-angleStart>D178)
  {
    double tmp=angleStart+D178;
    arc_limit_angles(&angleStart, &tmp);
    arc_calc_bb(&bb, 0, 0, radius, angleStart, tmp);
    f(fb, &bb, x0, y0, radius, color);

    //tmp=angleStop-D90;
    //arc_limit_angles(&tmp, &angleStop);

    arc_calc_bb(&bb, 0, 0, radius, tmp, angleStop);
    f(fb, &bb, x0, y0, radius, color);
  }
  else
  {
    arc_calc_bb(&bb, 0, 0, radius, angleStart, angleStop);
    f(fb, &bb, x0, y0, radius, color);
  }
}

void gfd_fb_draw_circle(gfd_framebuffer_t* const fb, int x0, int y0, int radius, int color)
{
  gfd_rect_t bb;
  bb.p0.x=-fb->dx;
  bb.p0.y=-fb->dy;
  bb.p1.x=fb->dx;
  bb.p1.y=fb->dy;

  gfd_fb_draw_circle_bb(fb, &bb, x0, y0, radius, color);
}

void gfd_fb_draw_circle_2cols(gfd_framebuffer_t* const fb, int x0, int y0, int radius, int color1, int color2)
{
  gfd_rect_t bb;
  bb.p0.x=-fb->dx;
  bb.p0.y=-fb->dy;
  bb.p1.x=fb->dx;
  bb.p1.y=fb->dy;

  gfd_fb_draw_circle_bb_2cols(fb, &bb, x0, y0, radius, color1, color2);
}

/*
void gfd_fb_draw_circle(gfd_framebuffer_t* const fb, int x0, int y0, int radius, int color)
{
  int f = 1 - radius;
  int ddF_x = 1;
  int ddF_y = -2 * radius;
  int x = 0;
  int y = radius;

  gfd_fb_set_pixel(fb, x0, y0 + radius, color);
  gfd_fb_set_pixel(fb, x0, y0 - radius, color);
  gfd_fb_set_pixel(fb, x0 + radius, y0, color);
  gfd_fb_set_pixel(fb, x0 - radius, y0, color);

  while(x < y)
  {
    // ddF_x == 2 * x + 1;
    // ddF_y == -2 * y;
    // f == x*x + y*y - radius*radius + 2*x - y + 1;
    if(f >= 0)
    {
      y--;
      ddF_y += 2;
      f += ddF_y;
    }
    x++;
    ddF_x += 2;
    f += ddF_x;

    gfd_fb_set_pixel(fb, x0 + x, y0 + y, color);
    gfd_fb_set_pixel(fb, x0 - x, y0 + y, color);
    gfd_fb_set_pixel(fb, x0 + x, y0 - y, color);
    gfd_fb_set_pixel(fb, x0 - x, y0 - y, color);
    gfd_fb_set_pixel(fb, x0 + y, y0 + x, color);
    gfd_fb_set_pixel(fb, x0 - y, y0 + x, color);
    gfd_fb_set_pixel(fb, x0 + y, y0 - x, color);
    gfd_fb_set_pixel(fb, x0 - y, y0 - x, color);
  }
}
*/

void gfd_fb_draw_arc_(gfd_framebuffer_t* const fb, int x0, int y0, int radius, double angleStart, double angleStop, int color)
{
  int i;
  int s_start;
  int s_stop;
  int sec[8];

  arc_limit_angles(&angleStart, &angleStop);

  s_start=(int)(angleStart/(D360/8));
  s_stop=(int)(angleStop/(D360/8));

  if (s_start>7)
    s_start-=8;

  for(i=0; i<8; ++i)
    sec[i]=0;

  for(i=s_start; i<s_stop; ++i)
  {
    int s=i>7 ? i-8 : i;
    sec[s]=1;
  }

  if (s_stop>7)
    s_stop-=8;
  sec[s_start]=2;
  sec[s_stop]=2;


#define if_sect(n_, x_, y_, test_)  \
  if (sec[n_])\
  {\
    if (sec[n_]==1)\
      gfd_fb_set_pixel(fb, x0+(x_), y0+(y_), color);\
    else if (test_)\
      gfd_fb_set_pixel(fb, x0+(x_), y0+(y_), color);\
    else\
      gfd_fb_set_pixel(fb, x0+(x_), y0+(y_), 1);\
  }

  {
    int f = 1 - radius;
    int ddF_x = 1;
    int ddF_y = -2 * radius;
    int x = 0;
    int y = radius;
    //int mirrow=0;
    double startAngle=angleStart;
    double endAngle=angleStop;

    if (endAngle>D360)
    {
      double offset=D360-endAngle;
      //mirrow=1;
      startAngle-=offset;
      endAngle-=offset;
    }

    while(x <= y)
    {
      double angle=atan2((double)y, (double)x);  /*between 0..45deg*/

      if_sect(0, -y, -x, D90 - angle >= startAngle && D90 - angle <= endAngle)

      if_sect(1, -x, -y, angle >= startAngle && angle <= endAngle)

      if_sect(2, +x, -y, D180 - angle >= startAngle && D180 - angle <= endAngle)

      if_sect(3, +y, -x, angle + D90 >= startAngle && angle + D90 <= endAngle)

      if_sect(4, +y, +x, D270 - angle >= startAngle && D270 - angle <= endAngle)

      if_sect(5, +x, +y, angle + D180 >= startAngle && angle + D180 <= endAngle)

      if_sect(6, -x, +y, D360 - angle >= startAngle && D360 - angle <= endAngle)

      if_sect(7, -y, +x, angle + D270 >= startAngle && angle + D270 <= endAngle)

      if(f >= 0)
      {
        y--;
        ddF_y += 2;
        f += ddF_y;
      }
      x++;
      ddF_x += 2;
      f += ddF_x;

    }
  }
}

int gfd_count_circle_pix(int radius)
{
  int f = 1 - radius;
  int ddF_x = 1;
  int ddF_y = -2 * radius;
  int x = 0;
  int y = radius;
  int cnt = 0;

  while(x <= y)
  {
    cnt += 8;

    if(f >= 0)
    {
      y--;
      ddF_y += 2;
      f += ddF_y;
    }
    x++;
    ddF_x += 2;
    f += ddF_x;
  }
  return cnt;
}

static void gfd_fb_draw_circle_bbNew(gfd_framebuffer_t* const fb, const gfd_rect_t* const bb, int x0, int y0, int radius, int cc, int oc, bool occlusion, int cnt)
{
  int f = 1 - radius;
  int ddF_x = 1;
  int ddF_y = -2 * radius;
  int x = 0;
  int y = radius;
  gfd_rect_t rect=*bb;

  gfd_pixel_t color=GFD_PIXEL(cc);
  gfd_pixel_t ocl=GFD_PIXEL(oc);

  gfd_clip_rect(&rect, fb->ox-x0, fb->oy-y0, fb->ex-x0, fb->ey-y0);

  if(occlusion)
  {
    while(x <= y)
    {
      if(cnt == 8)
      {
        if(p_inside(rect, x, y))
        {
          // SE
          int fx = x0+(x);
          int fy = y0+(y);
          GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_Y2(fb,fy+1))
            GFD_PIXEL_AT_(fb, fx, fy+1)=GFD_PIXEL(ocl);
          if(GFD_CHECK_X2(fb,fx+1))
            GFD_PIXEL_AT_(fb, fx+1, fy)=GFD_PIXEL(ocl);
        }

        if(p_inside(rect, -x, y))
        {
          // SW
          int fx = x0+(-x);
          int fy = y0+(y);
          GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_Y2(fb,fy+1))
            GFD_PIXEL_AT_(fb, fx, fy+1)=GFD_PIXEL(ocl);
          if(GFD_CHECK_X2(fb,fx-1))
            GFD_PIXEL_AT_(fb, fx-1, fy)=GFD_PIXEL(ocl);
        }

        if(p_inside(rect, x, -y))
        {
          // NE
          int fx = x0+(x);
          int fy = y0+(-y);
          GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_Y2(fb,fy-1))
            GFD_PIXEL_AT_(fb, fx, fy-1)=GFD_PIXEL(ocl);
          if(GFD_CHECK_X2(fb,fx+1))
            GFD_PIXEL_AT_(fb, fx+1, fy)=GFD_PIXEL(ocl);
        }

        if(p_inside(rect, -x, -y))
        {
          // NW
          int fx = x0+(-x);
          int fy = y0+(-y);
          GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_Y2(fb,fy-1))
            GFD_PIXEL_AT_(fb, fx, fy-1)=GFD_PIXEL(ocl);
          if(GFD_CHECK_X2(fb,fx-1))
            GFD_PIXEL_AT_(fb, fx-1, fy)=GFD_PIXEL(ocl);
        }

        if(p_inside(rect, y, x))
        {
          // ES
          int fx = x0+(y);
          int fy = y0+(x);
          GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_X2(fb,fx-1))
            GFD_PIXEL_AT_(fb, fx-1, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_X2(fb,fx+1))
            GFD_PIXEL_AT_(fb, fx+1, fy)=GFD_PIXEL(ocl);
          if(GFD_CHECK_Y2(fb,fy+1))
            GFD_PIXEL_AT_(fb, fx, fy+1)=GFD_PIXEL(ocl);
        }

        if(p_inside(rect, -y, x))
        {
          // WS
          int fx = x0+(-y);
          int fy = y0+(x);
          GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_X2(fb,fx+1))
            GFD_PIXEL_AT_(fb, fx+1, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_X2(fb,fx-1))
            GFD_PIXEL_AT_(fb, fx-1, fy)=GFD_PIXEL(ocl);
          if(GFD_CHECK_Y2(fb,fy+1))
            GFD_PIXEL_AT_(fb, fx, fy+1)=GFD_PIXEL(ocl);
        }

        if(p_inside(rect, y, -x))
        {
          // EN
          int fx = x0+(y);
          int fy = y0+(-x);
          GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_X2(fb,fx-1))
            GFD_PIXEL_AT_(fb, fx-1, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_X2(fb,fx+1))
            GFD_PIXEL_AT_(fb, fx+1, fy)=GFD_PIXEL(ocl);
          if(GFD_CHECK_Y2(fb,fy-1))
            GFD_PIXEL_AT_(fb, fx, fy-1)=GFD_PIXEL(ocl);
        }

        if(p_inside(rect, -y, -x))
        {
          // WN
          int fx = x0+(-y);
          int fy = y0+(-x);
          GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_X2(fb,fx+1))
            GFD_PIXEL_AT_(fb, fx+1, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_X2(fb,fx-1))
            GFD_PIXEL_AT_(fb, fx-1, fy)=GFD_PIXEL(ocl);
          if(GFD_CHECK_Y2(fb,fy-1))
            GFD_PIXEL_AT_(fb, fx, fy-1)=GFD_PIXEL(ocl);
        }
      }
      else
      {
        if(p_inside(rect, x, y))
        {
          // SE
          int fx = x0+(x);
          int fy = y0+(y);
          GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_Y2(fb,fy-1))
            GFD_PIXEL_AT_(fb, fx, fy-1)=GFD_PIXEL(color);
          if(GFD_CHECK_Y2(fb,fy+1))
            GFD_PIXEL_AT_(fb, fx, fy+1)=GFD_PIXEL(ocl);
          if(GFD_CHECK_Y2(fb,fy-2))
            GFD_PIXEL_AT_(fb, fx, fy-2)=GFD_PIXEL(ocl);
        }

        if(p_inside(rect, -x, y))
        {
          // SW
          int fx = x0+(-x);
          int fy = y0+(y);
          GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_Y2(fb,fy-1))
            GFD_PIXEL_AT_(fb, fx, fy-1)=GFD_PIXEL(color);
          if(GFD_CHECK_Y2(fb,fy+1))
            GFD_PIXEL_AT_(fb, fx, fy+1)=GFD_PIXEL(ocl);
          if(GFD_CHECK_Y2(fb,fy-2))
            GFD_PIXEL_AT_(fb, fx, fy-2)=GFD_PIXEL(ocl);
        }

        if(p_inside(rect, x, -y))
        {
          // NE
          int fx = x0+(x);
          int fy = y0+(-y);
          GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_Y2(fb,fy+1))
            GFD_PIXEL_AT_(fb, fx, fy+1)=GFD_PIXEL(color);
          if(GFD_CHECK_Y2(fb,fy+2))
            GFD_PIXEL_AT_(fb, fx, fy+2)=GFD_PIXEL(ocl);
          if(GFD_CHECK_Y2(fb,fy-1))
            GFD_PIXEL_AT_(fb, fx, fy-1)=GFD_PIXEL(ocl);
        }

        if(p_inside(rect, -x, -y))
        {
          // NW
          int fx = x0+(-x);
          int fy = y0+(-y);
          GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_Y2(fb,fy+1))
            GFD_PIXEL_AT_(fb, fx, fy+1)=GFD_PIXEL(color);
          if(GFD_CHECK_Y2(fb,fy+2))
            GFD_PIXEL_AT_(fb, fx, fy+2)=GFD_PIXEL(ocl);
          if(GFD_CHECK_Y2(fb,fy-1))
            GFD_PIXEL_AT_(fb, fx, fy-1)=GFD_PIXEL(ocl);
        }

        if(p_inside(rect, y, x))
        {
          // ES
          int fx = x0+(y);
          int fy = y0+(x);
          GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_X2(fb,fx-1))
            GFD_PIXEL_AT_(fb, fx-1, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_X2(fb,fx+1))
            GFD_PIXEL_AT_(fb, fx+1, fy)=GFD_PIXEL(ocl);
          if(GFD_CHECK_X2(fb,fx-2))
            GFD_PIXEL_AT_(fb, fx-2, fy)=GFD_PIXEL(ocl);
        }

        if(p_inside(rect, -y, x))
        {
          // WS
          int fx = x0+(-y);
          int fy = y0+(x);
          GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_X2(fb,fx+1))
            GFD_PIXEL_AT_(fb, fx+1, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_X2(fb,fx-1))
            GFD_PIXEL_AT_(fb, fx-1, fy)=GFD_PIXEL(ocl);
          if(GFD_CHECK_X2(fb,fx+2))
            GFD_PIXEL_AT_(fb, fx+2, fy)=GFD_PIXEL(ocl);

        }

        if(p_inside(rect, y, -x))
        {
          // EN
          int fx = x0+(y);
          int fy = y0+(-x);
          GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_X2(fb,fx-1))
            GFD_PIXEL_AT_(fb, fx-1, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_X2(fb,fx+1))
            GFD_PIXEL_AT_(fb, fx+1, fy)=GFD_PIXEL(ocl);
          if(GFD_CHECK_X2(fb,fx-2))
            GFD_PIXEL_AT_(fb, fx-2, fy)=GFD_PIXEL(ocl);
        }

        if(p_inside(rect, -y, -x))
        {
          // WN
          int fx = x0+(-y);
          int fy = y0+(-x);
          GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_X2(fb,fx+1))
            GFD_PIXEL_AT_(fb, fx+1, fy)=GFD_PIXEL(color);
          if(GFD_CHECK_X2(fb,fx+2))
            GFD_PIXEL_AT_(fb, fx+2, fy)=GFD_PIXEL(ocl);
          if(GFD_CHECK_X2(fb,fx-1))
            GFD_PIXEL_AT_(fb, fx-1, fy)=GFD_PIXEL(ocl);
        }
      }
      cnt -=8;

      if(f >= 0)
      {
        y--;
        ddF_y += 2;
        f += ddF_y;
      }
      x++;
      ddF_x += 2;
      f += ddF_x;
    }
  }
  else
  {
    while(x <= y)
    {
      if(p_inside(rect, x, y))
      {
        // SE
        int fx = x0+(x);
        int fy = y0+(y);
        GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
        if(GFD_CHECK_Y2(fb,fy-1))
          GFD_PIXEL_AT_(fb, fx, fy-1)=GFD_PIXEL(color);
      }

      if(p_inside(rect, -x, y))
      {
        // SW
        int fx = x0+(-x);
        int fy = y0+(y);
        GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
        if(GFD_CHECK_Y2(fb,fy-1))
          GFD_PIXEL_AT_(fb, fx, fy-1)=GFD_PIXEL(color);
      }

      if(p_inside(rect, x, -y))
      {
        // NE
        int fx = x0+(x);
        int fy = y0+(-y);
        GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
        if(GFD_CHECK_Y2(fb,fy+1))
          GFD_PIXEL_AT_(fb, fx, fy+1)=GFD_PIXEL(color);
      }

      if(p_inside(rect, -x, -y))
      {
        // NW
        int fx = x0+(-x);
        int fy = y0+(-y);
        GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
        if(GFD_CHECK_Y2(fb,fy+1))
          GFD_PIXEL_AT_(fb, fx, fy+1)=GFD_PIXEL(color);
      }

      if(p_inside(rect, y, x))
      {
        // ES
        int fx = x0+(y);
        int fy = y0+(x);
        GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
        if(GFD_CHECK_X2(fb,fx-1))
          GFD_PIXEL_AT_(fb, fx-1, fy)=GFD_PIXEL(color);
      }

      if(p_inside(rect, -y, x))
      {
        // WS
        int fx = x0+(-y);
        int fy = y0+(x);
        GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
        if(GFD_CHECK_X2(fb,fx+1))
          GFD_PIXEL_AT_(fb, fx+1, fy)=GFD_PIXEL(color);
      }

      if(p_inside(rect, y, -x))
      {
        // EN
        int fx = x0+(y);
        int fy = y0+(-x);
        GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
        if(GFD_CHECK_X2(fb,fx-1))
          GFD_PIXEL_AT_(fb, fx-1, fy)=GFD_PIXEL(color);
      }

      if(p_inside(rect, -y, -x))
      {
        // WN
        int fx = x0+(-y);
        int fy = y0+(-x);
        GFD_PIXEL_AT_(fb, fx, fy)=GFD_PIXEL(color);
        if(GFD_CHECK_X2(fb,fx+1))
          GFD_PIXEL_AT_(fb, fx+1, fy)=GFD_PIXEL(color);
      }

      if(f >= 0)
      {
        y--;
        ddF_y += 2;
        f += ddF_y;
      }
      x++;
      ddF_x += 2;
      f += ddF_x;
    }
  }
}

void gfd_fb_draw_arc179_w2_occ(gfd_framebuffer_t* const fb, int x0, int y0, int radius, double angleStart, double angleStop, int color, int occolor, bool occlusion, int cnt)
{
  gfd_fb_draw_arc179_func_w2_occ(gfd_fb_draw_circle_bbNew, fb, x0, y0, radius, angleStart, angleStop, color, occolor, occlusion, cnt);
}

void gfd_fb_draw_arc179_func_w2_occ(gfd_fb_draw_circle_bb_function_w2_occ_t f, gfd_framebuffer_t* const fb, int x0, int y0, int radius, double angleStart, double angleStop, int color, int occolor, bool occlusion, int cnt)
{
  gfd_rect_t bb;

  angleStart+=D90;
  angleStop+=D90;

  arc_limit_angles(&angleStart, &angleStop);
  arc_calc_bb(&bb, 0, 0, radius, angleStart, angleStop);
  f(fb, &bb, x0, y0, radius, color, occolor, occlusion, cnt);
}

