# Subversion RepositoriesKolibri OS

Rev
1.
2. #define CLIP_TOP        1
3. #define CLIP_BOTTOM     2
4. #define CLIP_RIGHT      4
5. #define CLIP_LEFT       8
6.
7.
8. static int _L1OutCode( clip_t *clip, int x, int y )
9. /*=================================
10.
11.     Verify that a point is inside or outside the active viewport.   */
12. {
13.     int   flag;
14.
15.     flag = 0;
16.     if( x < clip->xmin ) {
17.         flag |= CLIP_LEFT;
18.     } else if( x > clip->xmax ) {
19.         flag |= CLIP_RIGHT;
20.     }
21.     if( y < clip->ymin ) {
22.         flag |= CLIP_TOP;
23.     } else if( y > clip->ymax ) {
24.         flag |= CLIP_BOTTOM;
25.     }
26.     return( flag );
27. }
28.
29.
30. static void line_inter( int * x1, int* y1, int x2, int y2, int x )
31. /*===========================================================================
32.
33.     Find the intersection of a line with a boundary of the viewport.
34.     (x1, y1) is outside and ( x2, y2 ) is inside the viewport.
35.     NOTE : the signs of denom and ( x - *x1 ) cancel out during division
36.            so make both of them positive before rounding.   */
37. {
38.     int            numer;
39.     int            denom;
40.
41.     denom = abs( x2 - *x1 );
42.     numer = 2L * (long)( y2 - *y1 ) * abs( x - *x1 );
43.     if( numer > 0 ) {
44.         numer += denom;                     /* round to closest pixel   */
45.     } else {
46.         numer -= denom;
47.     }
48.     *y1 += numer / ( denom << 1 );
49.     *x1 = x;
50. }
51.
52.
53. int LineClip( clip_t *clip, int *x1, int *y1, int *x2, int *y2 )
54. /*=============================================================
55.
56.     Clips the line with end points (x1,y1) and (x2,y2) to the active
57.     viewport using the Cohen-Sutherland clipping algorithm. Return the
58.     clipped coordinates and a decision drawing flag.    */
59. {
60.     int    flag1;
61.     int    flag2;
62.
63.     flag1 = _L1OutCode( clip, *x1, *y1 );
64.     flag2 = _L1OutCode( clip, *x2, *y2 );
65.     for( ;; ) {
66.         if( flag1 & flag2 ) break;                  /* trivially outside    */
67.         if( flag1 == flag2 ) break;                 /* completely inside    */
68.         if( flag1 == 0 ) {                          /* first point inside   */
69.             if( flag2 & CLIP_TOP ) {
70.                 line_inter( y2, x2, *y1, *x1, clip->ymin );
71.             } else if( flag2 & CLIP_BOTTOM ) {
72.                 line_inter( y2, x2, *y1, *x1, clip->ymax );
73.             } else if( flag2 & CLIP_RIGHT ) {
74.                 line_inter( x2, y2, *x1, *y1, clip->xmax );
75.             } else if( flag2 & CLIP_LEFT ) {
76.                 line_inter( x2, y2, *x1, *y1, clip->xmin );
77.             }
78.             flag2 = _L1OutCode( clip, *x2, *y2 );
79.         } else {                                    /* second point inside  */
80.             if( flag1 & CLIP_TOP ) {
81.                 line_inter( y1, x1, *y2, *x2, clip->ymin );
82.             } else if( flag1 & CLIP_BOTTOM ) {
83.                 line_inter( y1, x1, *y2, *x2, clip->ymax );
84.             } else if( flag1 & CLIP_RIGHT ) {
85.                 line_inter( x1, y1, *x2, *y2, clip->xmax );
86.             } else if( flag1 & CLIP_LEFT ) {
87.                 line_inter( x1, y1, *x2, *y2, clip->xmin );
88.             }
89.             flag1 = _L1OutCode( clip, *x1, *y1 );
90.         }
91.     }
92.     return( flag1 & flag2 );
93. }
94.
95.
96. static void block_inter( clip_t *clip, int *x, int *y, int flag )
97. /*======================================================
98.
99.     Find the intersection of a block with a boundary of the viewport.   */
100. {
101.     if( flag & CLIP_TOP ) {
102.         *y = clip->ymin;
103.     } else if( flag & CLIP_BOTTOM ) {
104.         *y = clip->ymax;
105.     } else if( flag & CLIP_RIGHT ) {
106.         *x = clip->xmax;
107.     } else if( flag & CLIP_LEFT ) {
108.         *x = clip->xmin;
109.     }
110. }
111.
112.
113. int BlockClip(clip_t *clip, int *x1, int *y1, int *x2, int* y2 )
114. /*==============================================================
115.
116.     Clip a block with opposite corners (x1,y1) and (x2,y2) to the
117.     active viewport based on the Cohen-Sutherland algorithm for line
118.     clipping. Return the clipped coordinates and a decision drawing
119.     flag ( 0 draw : 1 don't draw ). */
120. {
121.    int  flag1;
122.    int  flag2;
123.
124.    flag1 = _L1OutCode( clip, *x1, *y1 );
125.    flag2 = _L1OutCode( clip, *x2, *y2 );
126.    for( ;; ) {
127.        if( flag1 & flag2 ) break;                  /* trivially outside    */
128.        if( flag1 == flag2 ) break;                 /* completely inside    */
129.        if( flag1 == 0 ) {
130.            block_inter( clip, x2, y2, flag2 );
131.            flag2 = _L1OutCode( clip,  *x2, *y2 );
132.        } else {
133.            block_inter( clip, x1, y1, flag1 );
134.            flag1 = _L1OutCode( clip, *x1, *y1 );
135.        }
136.    }
137.    return( flag1 & flag2 );
138. }
139.
140.
141. int blit_clip(clip_t *dst_clip,int *dst_x,int *dst_y,
142.              clip_t *src_clip,int *src_x, int *src_y,
143.              int *w, int *h)
144. {
145.    int sx0, sy0, sx1, sy1;
146.
147.    sx0 = *src_x;
148.    sy0 = *src_y;
149.
150.    sx1 = sx0 + *w - 1;
151.    sy1 = sy0 + *h - 1;
152.
153.
154.    if( ! BlockClip( src_clip, &sx0, &sy0, &sx1, &sy1))
155.    {
156.      int dx0, dy0, dx1, dy1;
157.
158.      dx0 = *dst_x + sx0 - *src_x;
159.      dy0 = *dst_y + sy0 - *src_y;
160.
161.      dx1 = dx0 + sx1 - sx0;
162.      dy1 = dy0 + sy1 - sy0;
163.
164.      if( ! BlockClip( dst_clip, &dx0, &dy0, &dx1, &dy1))
165.      {
166.         *w = dx1 - dx0 + 1;
167.         *h = dy1 - dy0 + 1;
168.
169.         *src_x += dx0 - *dst_x;
170.         *src_y += dy0 - *dst_y;
171.
172.         *dst_x = dx0;
173.         *dst_y = dy0;
174.
175.         return 0;
176.      };
177.      return 1;
178.    }
179.    return 1;
180. };
181.
182.