1.1. 좌표계의 종류

coords_system.png
[PNG image (39.29 KB)]
위 그림은 아래 설명을 위해서 작성한 하나의 가상 화면입니다.

  • 하나의 점은 16K color 수를 표현할수 있다고 가정합니다.
  • 흰색(White) 부분이 실제 모니터에 표시되는 점이며 검은색이 비 가시영역으로 볼수 있습니다. 모니터를 자세히 들여다 보세요. 점의 집합으로 표현되는 이러한 화면에서 좌표계의 선택은 매우 중요한 요소입니다.
  • 파란색(Blue) 사각형 하나는 실제 화면에 표시되는 점을 기준으로 하는 좌표계를 가정합니다. (Pixel 좌표계)
  • 초록색(Green) 사각형은 실제 화면에 보이지 않는 비가시영역을 기준으로 하는 좌표계를 가정합니다. ( Bound 좌표계: 이 영역은 Paging unit의 효율을 위해서 하나의 Row당 Padding되는 영역으로 설명될수 있습니다. )
  • 이와 같이 실제 표시되는 점을 기준으로 하는 좌표표현 방법(Pixel 좌표계)과 표시되는 점의 외곽의 비가시영역을 기준으로 하는 좌표표현 방법(Bound 좌표계)이 존재합니다. 어느것이 더 좋다고 하는 것 보다는 자신의 그래픽 구현이 어느것에 더 유리한지 고민후에 좌표계를 결정하는 개발자의 판단 몫이라고 할수 있겠습니다.

1.2. Pixel 좌표계

실제 화면에 표시되는 점을 하나의 단위로 보는 좌표계입니다.

위에서 화면전체는 Pixel좌표계로는 다음과 같이 표시될수 있습니다.
typedef struct hwport_rectangle_ts {
    int x, y;
    unsigned int width, height;
}__hwport_rectangle_t;
#define hwport_rectangle_t __hwport_rectangle_t

typedef struct hwport_screen_ts {
    int bits_per_pixel;
    size_t bytes_per_line;
    hwport_rectangle_t rectangle;
}__hwport_screen_t;
#define hwport_screen_t __hwport_screen_t

static hwport_screen_t my_screen = {
    16,                                /* bits_per_pixel = <위 그림에서 하나의 점은 16K 의 Color수를 표현한다고 가정하면 하나의 점을 표현하는데는 16bits가 필요합니다.> */
    (size_t)((32u + 4u) * (16u / 8u)), /* bytes_per_line = 가시영역인 32개의 가로 Pixel수와 비가시영역 4개의 Pixel을 더하고 bits_per_pixel을 bytes_per_pixel로 곱한것입니다. */
    { 0, 0, 32u, 32u }                 /* rectangle = 비가시영역을 제외한 부분을 뜻합니다. 여기서 x, y는 항상 0이라고 할수는 없고 Over scan등이 고려될때는 0이 아닐수 있습니다. */
};


위의 그림에서 붉은색 사각형은 다음과 같이 표현될수 있습니다.
hwport_rectangle_t my_rectangle = {
    2, 2, 9u, 9u
};


또 다른 표현으로는 다음과 같이도 표현합니다.
typedef struct hwport_region_ts {
    int x1, y1, x2, y2;
}__hwport_region_t;
#define hwport_region_t __hwport_region_t

hwport_region_t my_region = {
    2, 2, 10, 10
};


만약 hwport_region_t 를 hwport_rectangle_t 로 변환하려면 다음과 같은 공식이 성립합니다.
#define MIN(m_left,m_right) ((m_left < m_right) ? (m_left) : (m_right))
#define MAX(m_left,m_right) ((m_left > m_right) ? (m_left) : (m_right))

my_rectangle.x = MIN(my_region.x1, my_region.x2);
my_rectangle.y = MIN(my_region.y1, my_region.y2);
my_rectangle.width = (unsigned int)( MAX(my_region.x1, my_region.x2) - MIN(my_region.x1, my_region.x2) + 1 );
my_rectangle.height = (unsigned int)( MAX(my_region.y1, my_region.y2) - MIN(my_region.y1, my_region.y2) + 1 );


반대로 hwport_rectangle_t 를 hwport_region_t 로 변환하려면 다음과 같은 공식이 성립합니다.
if((my_rectangle.width <= 0u) || (my_rectangle.height <= 0u)) {
    /* ERROR: invalid width or height */
}

my_region.x1 = my_rectangle.x;
my_region.y1 = my_rectangle.y;
my_region.x2 = ((int)my_rectangle.width) - my_rectangle.x - 1;
my_region.y2 = ((int)my_rectangle.height) - my_rectangle.y - 1;


1.3. Bound(Screen) 좌표계

하나의 점 마저도 크게 확대해보면 사각형 또는 어느 범위안의 구역이라는 시점으로 바라본 좌표계로써 보이는 점들의 외곽영역을 기준으로 하는 좌표계
typedef struct hwport_bound_ts {
    int left, top, right, bottom;
}__hwport_bound_t;
#define hwport_bound_t __hwport_bound_t

typedef struct hwport_screen_ts {
    int bits_per_pixel;
    size_t bytes_per_line;
    hwport_bound_t bound;
}__hwport_screen_t;
#define hwport_screen_t __hwport_screen_t

static hwport_screen_t my_screen = {
    16,                  /* bits_per_pixel */
    (32 + 4) * (16 / 8), /* bytes_per_line */
    { 0, 0, 32, 32 }     /* bound */
};


위의 그림에서 붉은색 사각형은 다음과 같이 표현될수 있습니다.
hwport_bound_t my_bound = {
    2, 2, 11, 11
};


1.4. Pixel 좌표계와 Bound 좌표계의 분석

hwport_bound_t를 hwport_rectangle_t 로 변환하려면 다음과 같은 공식이 성립합니다. hwport_region_t를 hwport_rectangle_t 로 변환할때는 1을 더해주어야 했다는 점이 주목해야 될 부분입니다.
my_rectangle.x = my_bound.left;
my_rectangle.y = my_bound.top;
my_rectangle.width = (unsigned int)(my_bound.right - my_bound.left);
my_rectangle.height = (unsigned int)(my_bound.bottom - my_bound.top);


1.5. 2개의 window(Pixel 좌표계 기준) 가 겹치는 영역을 계산하는 예제

이 예제는 2개의 Window 사각 영역에 대하여 겹쳐지는 영역과 겹쳐지지 않는 영역을 계산하는 예제입니다. 보통 Windows Manager 개발에 필요한 요소로 볼 수 있으며 겹쳐지지 않는 영역은 완벽하게 식별하기 위해서는 4개의 영역으로 나뉘어 다룰수 있습니다. 실제 이 연산을 기반으로 Windows Manager를 개발하게 되면 재귀적 연산부가 심도있게 다루어져야 하는데 통상 재귀적 Stack 이용률이 매우 크기 때문에 재귀적인 부분을 비 재귀적 연산으로 개발하는 고려가 되어야 바람직합니다.
/*

    ************************
    *[deal]         |      *
    *     (0)       |      *
    *               |      *
    *------**********      *
    *      *[other] *  (1) *
    *      *        *      *
    *      *Overlap *      *
    * (3)  *        *      *
    *      *        *      *
    *      **********------*
    *      |               *
    *      |     (2)       *
    *      |               *
    ************************

*/

#if !defined(hwport_rectangle_t)
# pragma pack(push,8)
typedef struct hwport_rectangle_ts {
    int m_x;
    int m_y;
    unsigned int m_w;
    unsigned int m_h;
}__hwport_rectangle_t;
# pragma pack(pop)
# define hwport_rectangle_t __hwport_rectangle_t
#endif

int hwport_sep_overlap_window(const hwport_rectangle_t *s_deal_region, const hwport_rectangle_t *s_other_region, hwport_rectangle_t *s_overlap_region, hwport_rectangle_t *s_no_overlap_region /* array[4] */)
{
    int s_temp1;
    int s_temp2;
    hwport_rectangle_t s_temp_window;

    if(hwport_unlikely((s_deal_region == ((hwport_rectangle_t *)0)) || (s_other_region == ((hwport_rectangle_t *)0)))) {
        return(-1);
    }

    /* wide region select to s_temp_window */
    s_temp_window.m_x = (s_deal_region->m_x <= s_other_region->m_x) ? s_deal_region->m_x : s_other_region->m_x;
    s_temp_window.m_y = (s_deal_region->m_y <= s_other_region->m_y) ? s_deal_region->m_y : s_other_region->m_y;

    s_temp1 = s_deal_region->m_x + ((int)s_deal_region->m_w);
    s_temp2 = s_other_region->m_x + ((int)s_other_region->m_w);
    if(s_temp2 > s_temp1) {
        s_temp1 = s_temp2;
    }
    s_temp_window.m_w = (unsigned int)(s_temp1 - s_temp_window.m_x);

    s_temp1 = s_deal_region->m_y + ((int)s_deal_region->m_h);
    s_temp2 = s_other_region->m_y + ((int)s_other_region->m_h);
    if(s_temp2 > s_temp1) {
        s_temp1 = s_temp2;
    }
    s_temp_window.m_h = (unsigned int)(s_temp1 - s_temp_window.m_y);

    if(((s_deal_region->m_w + s_other_region->m_w) <= s_temp_window.m_w) || ((s_deal_region->m_h + s_other_region->m_h) <= s_temp_window.m_h)) {
        /* no overlap */
        return(0);
    }

    if(s_overlap_region == ((hwport_rectangle_t *)0)) {
        s_overlap_region = (hwport_rectangle_t *)(&s_temp_window);
    }

    /* overlap region select */
    s_overlap_region->m_x = (s_deal_region->m_x >= s_other_region->m_x) ? s_deal_region->m_x : s_other_region->m_x;
    s_overlap_region->m_y = (s_deal_region->m_y >= s_other_region->m_y) ? s_deal_region->m_y : s_other_region->m_y;
    s_overlap_region->m_w = s_deal_region->m_w + s_other_region->m_w - s_temp_window.m_w;
    s_overlap_region->m_h = s_deal_region->m_h + s_other_region->m_h - s_temp_window.m_h;

    /* no overlap region select */
    if(s_no_overlap_region != ((hwport_rectangle_t *)0)) {
        s_no_overlap_region[0].m_x = s_deal_region->m_x;
        s_no_overlap_region[0].m_y = s_deal_region->m_y;
        s_no_overlap_region[0].m_w = (unsigned int)(s_overlap_region->m_x + ((int)s_overlap_region->m_w) - s_deal_region->m_x);
        s_no_overlap_region[0].m_h = (unsigned int)(s_overlap_region->m_y - s_deal_region->m_y);

        s_no_overlap_region[1].m_x = s_overlap_region->m_x + ((int)s_overlap_region->m_w);
        s_no_overlap_region[1].m_y = s_deal_region->m_y;
        s_no_overlap_region[1].m_w = (unsigned int)((s_deal_region->m_x + ((int)s_deal_region->m_w)) - (s_overlap_region->m_x + ((int)s_overlap_region->m_w)));
        s_no_overlap_region[1].m_h = (unsigned int)((s_overlap_region->m_y + ((int)s_overlap_region->m_h)) - s_deal_region->m_y);

        s_no_overlap_region[2].m_x = s_overlap_region->m_x;
        s_no_overlap_region[2].m_y = s_overlap_region->m_y + ((int)s_overlap_region->m_h);
        s_no_overlap_region[2].m_w = (unsigned int)(((int)s_deal_region->m_w) - (s_overlap_region->m_x - s_deal_region->m_x));
        s_no_overlap_region[2].m_h = (unsigned int)((s_deal_region->m_y + ((int)s_deal_region->m_h)) - (s_overlap_region->m_y + ((int)s_overlap_region->m_h)));

        s_no_overlap_region[3].m_x = s_deal_region->m_x;
        s_no_overlap_region[3].m_y = s_overlap_region->m_y;
        s_no_overlap_region[3].m_w = (unsigned int)(s_overlap_region->m_x - s_deal_region->m_x);
        s_no_overlap_region[3].m_h = (unsigned int)(((int)s_deal_region->m_h) - (s_overlap_region->m_y - s_deal_region->m_y));
    }

    return(1);
}


1.6. 예제소스

  • @bitblit.tar.gz (1.22 KB) : Text console 상에서 구현하는 간략한 FrameBuffer 에 대한 개념을 이해하기 위한 예제
  • @fbinfo.tar.gz (1.6 KB) : Linux Frame Buffer 를 이해하기 위한 간략한 FrameBuffer 정보추출 기초 예제
  • @fbclock.tar.gz (2.81 KB) : Linux Frame Buffer 상에서 시계바늘을 그리는 간략한 예제 (점, 선, 회전각에 대한 이해를 위한...)
  • @fbfire.tar.gz (2.44 KB) : Linux Frame Buffer 상에서 좀더 가시적인 효과를 어떻게 구현하는지에 대한 예제 (불타오르는 화면효과 연출, 색상을 다루는 예제)
  • @bitmap.tar.gz (17.46 KB) : Text console 상에서 간략히 글자를 어떻게 Bitmap으로 다루고 이를 Frame Buffer에 도입할수 있는지에 대한 예제
  • @mz3d.tar.gz (16.39 KB) : Linux frame buffer 상에서 동작하는 3차원를 다루는 예제
  • @mz3dx_simple.tar.gz (6.27 KB) : X-Windows 상에서 동작하는 3차원을 다루는 예제




/*

[ FrontPage | PrintView | RawView | RSS ]

Copyright ⓒ MINZKN.COM
All Rights Reserved.

MINZKN

----

*/