Subversion Repositories Kolibri OS

Rev

Rev 882 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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.    }
  178.    return 1;
  179. };
  180.  
  181.