gx 라이브러리에 이번에는 원 그리기를 추가했습니다. 실은 원 그리기 함수를 넣지 않으려고 했습니다. 타원 그리기로도 원을 그릴 수 있기 때문이죠. 그러나 임베디드 보드가 조금 느리다라는 생각과 여기 강좌란에서 완벽한 그래픽 라이브러리를 만든다는 것 보다는 교육을 위한 필요도 있어서 추가하기로 했습니다.

역시 Device Context의 pen_color와 brush_color을 사용하여 테두리와 내부를 채웁니다. 한번의 원 그리기 루틴으로 내부의 선을 긋고 테두리에 점을 찍으면 빠르겠습니다만, 칼라 처리와 원의 테두리를 적용한다든지의 업그레이드를 위해 2번에 나누어 처리하겠습니다.

한번은 내부의 선을 긋고, 2번째 호출로 테두리 점을 찍습니다.

gx_circle()

형태 void gx_circle ( dc_t dc, int center_x, int center_y, int radius);
인수 dc_t dc 출력 대상 Device Context
  int center_x
int center_y
원의 중심 좌표
  int radius 원의 반지름

gx_circle()은 gx_rectangle와 마찬가지로 dc의 pen_color로 테두리를 그리고 brush_color로 내부 색을 채웁니다. 또한 pen_color 나 brush_color 가 clr_clear 일 경우 칠해지지 않습니다.

gx_circle()은 원을 그리는 함수 circle()을 호출하면서 내부의 색을 칠해주는 함수의 포인터와 외부의 테두리에 점을 찍은 함수의 포인터를 넘겨 줌으로써 하나의 원 그리기 루틴으로 두가지 작업을 처리합니다.

void gx_circle( dc_t *dc, int center_x, int center_y, int radius)
{
   if ( 0 == radius) return;

   if ( clr_clear != dc->brush_color)  circle( dc, center_x, center_y, radius, dc->brush_color, dc->hline);
   if ( clr_clear != dc->pen_color  )  circle( dc, center_x, center_y, radius, dc->pen_color  , circle_dot);
}

gx_circle()에서 색상에 따라 두번의 호출을 하면서 선을 그리는 hline()과 circle_dot() 함수를 넘겨 줍니다.

static void  circle( dc_t *dc, int center_x, int center_y, int radius, int color,
                                         void (*fun)( dc_t *dc, int, int, int, int))
{
   int      coor_x;
   int      coor_y;
   int      p_value;

   coor_x   = 0;
   coor_y   = radius;
   p_value   = 3 - 2 * radius;
   while   ( coor_x < coor_y)
   {
      draw_circle( dc, center_x, center_y, coor_x, coor_y, color, fun);  // 1/8의 원 출력
      if ( p_value < 0)
      {
         p_value   += 4 * coor_x +6;
      }
      else
      {
         p_value   += 4 * ( coor_x -coor_y) +10;
         coor_y--;
      }
      coor_x++;
   }
   if ( coor_x == coor_y)
      draw_circle( dc, center_x, center_y, coor_x, coor_y, color, fun); // 1/8의 원 출력
}

원의 1/8 부분을 대칭으로 8개의 부분을 모두 그리는 루틴입니다.

static void draw_circle( dc_t *dc, int center_x, int center_y, 
          int coor_x, int coor_y, int color, 
            void (*fun)( dc_t *c, int, int, int, int))
{
   int      y_dot;

   y_dot   = center_y +coor_y;
   fun( dc, center_x-coor_x, center_x+coor_x, y_dot, color);

   y_dot   = center_y -coor_y;
   fun( dc, center_x-coor_x, center_x+coor_x, y_dot, color);

   y_dot   = center_y +coor_x;
   fun( dc, center_x-coor_y, center_x+coor_y, y_dot, color);

   y_dot   = center_y -coor_x;
   fun( dc, center_x-coor_y, center_x+coor_y, y_dot, color);
}

이 함수에서 실제로 원을 그리는 함수는 fun() 입니다. 이 함수에 따라서 점의 테두리를 위한 점을 찍을 수 있으며, 또는 원의 내부를 칠할 수 있습니다.

원의 테두리 점을 찍는 함수는 인수로 받은 좌표를 좌우로 해서 점을 출력하게 됩니다.

static void circle_dot( dc_t *dc, int fst_x , int snd_x , int coor_y, int color)
{
   dc->set_pixel( dc, fst_x, coor_y, color);
   dc->set_pixel( dc, snd_x, coor_y, color);
}

sample 소스 설명

int   rand_color( dc_t *dc)     // 색상을 랜덤하게 구한다.
{
   return ( gx_color( dc, rand() %128 +128, rand() %128 +128, rand() %128 +128));
}

void  test_rectangle( dc_t *dc)
{
   int         coor_x, coor_y;
   int         radius;
   static int  ndx         = 0;
                                  
   coor_x         = rand() % dc->width;    // 원의 좌표를 랜덤으로 구합니다.
   coor_y         = rand() % dc->height;
   radius         = rand() % 100;

   if ( !( ndx % 60))   gx_clear( dc, clr_black); // 매 호출 60번째 마다
                                                  // 검정색으로 Clear
   switch ( (ndx++ / 20) % 3)                    // 매번 20번째 마다 
   {                                              // 테두리와 브러쉬 색상 처리를 바꿈
   case 0   :
            dc->pen_color     = rand_color( dc);
            dc->brush_color   = clr_clear;
            break;
   case 1   :
            dc->pen_color     = clr_clear;
            dc->brush_color   = rand_color( dc);
            break;
   default  :
            dc->pen_color     = rand_color( dc);
            dc->brush_color   = rand_color( dc);
            break;
   }
   gx_circle( dc, coor_x, coor_y, radius);
   usleep( 150 *1000);
}

void  test( void)
{
   화면에 대한 Device Context를 구하고 성공하면 test_circle() 호출
}

int   main( void)
{
   gx 라이브러리를 초기화하고 성공하면 test() 호출
}

프로그램을 실행하면 아래와 같이 계속 원을 출력하게 됩니다.

 태그: *그래픽 *라이브러리 *그래픽라이브러리