bitblt.c

changeset 43
b80cb5a4282a
parent 42
9c85a4cd88a3
child 47
bfc6aaa089b0
     1.1 --- a/bitblt.c	Wed Jan 02 16:39:39 2002 +0000
     1.2 +++ b/bitblt.c	Tue Jan 22 09:42:42 2002 +0000
     1.3 @@ -6,7 +6,7 @@
     1.4  #include "bitblt.h"
     1.5  
     1.6  
     1.7 -#define CALC_ROWBYTES(width) (((width) - 1) / 8 + 1)
     1.8 +#define DIV_ROUND_UP(count,pow2) (((count) - 1) / (pow2) + 1)
     1.9  
    1.10  
    1.11  static const u8 bit_reverse_byte [0x100] =
    1.12 @@ -45,8 +45,16 @@
    1.13    0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
    1.14  };
    1.15  
    1.16 +static word_type bit_reverse_word (word_type d)
    1.17 +{
    1.18 +  return (bit_reverse_byte [d >> 24] |
    1.19 +	  (bit_reverse_byte [(d >> 16) & 0xff] << 8) |
    1.20 +	  (bit_reverse_byte [(d >> 8) & 0xff] << 16) |
    1.21 +	  (bit_reverse_byte [d & 0xff] << 24));
    1.22 +}
    1.23  
    1.24 -static u8 *temp_buffer;
    1.25 +
    1.26 +static u32 *temp_buffer;
    1.27  static u32 temp_buffer_size;
    1.28  
    1.29  static void realloc_temp_buffer (u32 size)
    1.30 @@ -63,12 +71,12 @@
    1.31  }
    1.32  
    1.33  
    1.34 -static inline u8 pixel_mask (x)
    1.35 +static inline word_type pixel_mask (x)
    1.36  {
    1.37  #ifdef LSB_LEFT
    1.38    return (1 << x);
    1.39  #else
    1.40 -  return (1 << (7 - x));
    1.41 +  return (1 << ((BITS_PER_WORD - 1) - x));
    1.42  #endif
    1.43  };
    1.44  
    1.45 @@ -85,8 +93,8 @@
    1.46    if (! bitmap)
    1.47      return (NULL);
    1.48    bitmap->rect = * rect;
    1.49 -  bitmap->rowbytes = CALC_ROWBYTES (width);
    1.50 -  bitmap->bits = calloc (height * bitmap->rowbytes, 1);
    1.51 +  bitmap->row_words = DIV_ROUND_UP (width, BITS_PER_WORD);
    1.52 +  bitmap->bits = calloc (1, height * bitmap->row_words * sizeof (word_type));
    1.53    if (! bitmap->bits)
    1.54      {
    1.55        free (bitmap);
    1.56 @@ -103,33 +111,33 @@
    1.57  
    1.58  boolean get_pixel (Bitmap *bitmap, Point coord)
    1.59  {
    1.60 -  u8 *p;
    1.61 +  word_type *p;
    1.62    if ((coord.x < bitmap->rect.min.x) ||
    1.63        (coord.x >= bitmap->rect.max.x) ||
    1.64        (coord.y < bitmap->rect.min.y) ||
    1.65        (coord.y >= bitmap->rect.max.y))
    1.66      return (0);
    1.67    p = bitmap->bits +
    1.68 -    (coord.y - bitmap->rect.min.y) * bitmap->rowbytes +
    1.69 -    (coord.x - bitmap->rect.min.x) / 8;
    1.70 -  return ((*p & pixel_mask (coord.x & 7)) != 0);
    1.71 +    (coord.y - bitmap->rect.min.y) * bitmap->row_words +
    1.72 +    (coord.x - bitmap->rect.min.x) / BITS_PER_WORD;
    1.73 +  return ((*p & pixel_mask (coord.x & (BITS_PER_WORD - 1))) != 0);
    1.74  }
    1.75  
    1.76  void set_pixel (Bitmap *bitmap, Point coord, boolean value)
    1.77  {
    1.78 -  u8 *p;
    1.79 +  word_type *p;
    1.80    if ((coord.x < bitmap->rect.min.x) ||
    1.81        (coord.x >= bitmap->rect.max.x) ||
    1.82        (coord.y < bitmap->rect.min.y) ||
    1.83        (coord.y >= bitmap->rect.max.y))
    1.84      return;
    1.85    p = bitmap->bits +
    1.86 -    (coord.y - bitmap->rect.min.y) * bitmap->rowbytes +
    1.87 -    (coord.x - bitmap->rect.min.x) / 8;
    1.88 +    (coord.y - bitmap->rect.min.y) * bitmap->row_words +
    1.89 +    (coord.x - bitmap->rect.min.x) / BITS_PER_WORD;
    1.90    if (value)
    1.91 -    *p |= pixel_mask (coord.x & 7);
    1.92 +    *p |= pixel_mask (coord.x & (BITS_PER_WORD - 1));
    1.93    else
    1.94 -    *p &= (0xff ^ pixel_mask (coord.x & 7));
    1.95 +    *p &= ~pixel_mask (coord.x & (BITS_PER_WORD - 1));
    1.96  }
    1.97  
    1.98  
    1.99 @@ -166,11 +174,210 @@
   1.100  }
   1.101  
   1.102  
   1.103 +#if 0
   1.104 +static void blt_background (Bitmap *dest_bitmap,
   1.105 +			    Rect *dest_rect)
   1.106 +{
   1.107 +  s32 y;
   1.108 +  word_type *rp;
   1.109 +
   1.110 +  /* This function requires a non-null dest rect */
   1.111 +  assert (dest_rect->min.x < dest_rect->max.x);
   1.112 +  assert (dest_rect->min.y < dest_rect->max.y);
   1.113 + 
   1.114 +  /* and that the rows of the dest rect lie entirely within the dest bitmap */
   1.115 +  assert (dest_rect->min.y >= dest_bitmap->rect->min.y);
   1.116 +  assert (dest_rect->max.y <= dest_bitmap->rect->max.y);
   1.117 +
   1.118 +  /* clip the x axis of the dest_rect to the bounds of the dest bitmap */
   1.119 +  if (dest_rect->min.x < dest_bitmap->rect.min.x)
   1.120 +    dest_rect->min.x = dest_bitmap->rect.min.x;
   1.121 +  if (dest_rect->max.x > dest_bitmap->rect.max.x)
   1.122 +    dest_rect->max.x = dest_bitmap->rect.max.x;
   1.123 +
   1.124 +  rp = ???;
   1.125 +  for (y = 0; y < rect_height (dest_rect); y++)
   1.126 +    {
   1.127 +  ???;
   1.128 +      rp += dest_bitmap->row_words;
   1.129 +    }
   1.130 +}
   1.131 +
   1.132 +
   1.133 +static void blt (Bitmap *src_bitmap,
   1.134 +		 Rect *src_rect,
   1.135 +		 Bitmap *dest_bitmap,
   1.136 +		 Rect *dest_rect)
   1.137 +{
   1.138 +  s32 y;
   1.139 +  word_type *rp;
   1.140 +
   1.141 +  /* This function requires a non-null src rect */
   1.142 +  assert (dest_rect->min.x < dest_rect->max.x);
   1.143 +  assert (dest_rect->min.y < dest_rect->max.y);
   1.144 + 
   1.145 +  /* and a non-null dest rect */
   1.146 +  assert (dest_rect->min.x < dest_rect->max.x);
   1.147 +  assert (dest_rect->min.y < dest_rect->max.y);
   1.148 +
   1.149 +  /* and that the widths and heights of the rects match */
   1.150 +  assert (rect_width (src_rect) == rect_width (dest_rect));
   1.151 +  assert (rect_height (src_rect) == rect_height (dest_rect));
   1.152 + 
   1.153 +  /* and that the rows of the src rect lie entirely within the src bitmap */
   1.154 +  assert (dest_rect->min.y >= dest_bitmap->rect->min.y);
   1.155 +  assert (dest_rect->max.y <= dest_bitmap->rect->max.y);
   1.156 +
   1.157 +  /* and that the rows of the dest rect lie entirely within the dest bitmap */
   1.158 +  assert (dest_rect->min.y >= dest_bitmap->rect->min.y);
   1.159 +  assert (dest_rect->max.y <= dest_bitmap->rect->max.y);
   1.160 +
   1.161 +  /* clip the x axis of the dest_rect to the bounds of the dest bitmap,
   1.162 +     and adjust the src_rect to match */
   1.163 +  if (dest_rect->min.x < dest_bitmap->rect.min.x)
   1.164 +    {
   1.165 +      src_rect->min.x += ???;
   1.166 +      dest_rect->min.x = dest_bitmap->rect.min.x;
   1.167 +    }
   1.168 +  if (dest_rect->max.x > dest_bitmap->rect.max.x)
   1.169 +    {
   1.170 +      dest_rect->max.x = dest_bitmap->rect.max.x;
   1.171 +    }
   1.172 +
   1.173 +  rp = ???;
   1.174 +  for (y = 0; y < rect_height (dest_rect); y++)
   1.175 +    {
   1.176 +  ???;
   1.177 +      rp += dest_bitmap->row_words;
   1.178 +    }
   1.179 +}
   1.180 +
   1.181 +
   1.182  Bitmap *bitblt (Bitmap *src_bitmap,
   1.183  		Rect   *src_rect,
   1.184  		Bitmap *dest_bitmap,
   1.185  		Point  *dest_min,
   1.186 -		int tfn)
   1.187 +		int tfn,
   1.188 +		int background)
   1.189 +{
   1.190 +  Rect sr, dr;     /* src and dest rects, clipped to visible portion of
   1.191 +		      dest rect */
   1.192 +  u32 drw, drh;    /* dest rect width, height - gets adjusted */
   1.193 +  Point src_point, dest_point;
   1.194 +
   1.195 +  {
   1.196 +    sr = * src_rect;
   1.197 +
   1.198 +    u32 srw = rect_width (& sr);
   1.199 +    u32 srh = rect_height (& sr);
   1.200 +
   1.201 +    if ((srw < 0) || (srh < 0))
   1.202 +      goto done;  /* the source rect is empty! */
   1.203 +
   1.204 +    dr.min = * dest_min;
   1.205 +    dr.max.x = dr.min.x + srw;
   1.206 +    dr.max.y = dr.min.y + srh;
   1.207 +  }
   1.208 +
   1.209 +  if (! dest_bitmap)
   1.210 +    {
   1.211 +      dest_bitmap = create_bitmap (& dr);
   1.212 +      if (! dest_bitmap)
   1.213 +	return (NULL);
   1.214 +    }
   1.215 +
   1.216 +  if ((dr.min.x >= dest_bitmap->rect.max.x) ||
   1.217 +      (dr.min.y >= dest_bitmap->rect.max.y))
   1.218 +    goto done;  /* the dest rect isn't even in the dest bitmap! */
   1.219 +
   1.220 +  /* crop dest rect to dest bitmap */
   1.221 +
   1.222 +  delta = dest_bitmap->rect.min.x - dr.min.x;
   1.223 +  if (delta > 0)
   1.224 +    {
   1.225 +      sr.min.x += delta;
   1.226 +      dr.min.x += delta;
   1.227 +    }
   1.228 +
   1.229 +  delta = dest_bitmap->rect.min.y - dr.min.y;
   1.230 +  if (delta > 0)
   1.231 +    {
   1.232 +      sr.min.y += delta;
   1.233 +      dr.min.y += delta;
   1.234 +    }
   1.235 +
   1.236 +  delta = dr.max.x - dest_bitmap->rect.max.x;
   1.237 +  if (delta > 0)
   1.238 +    {
   1.239 +      sr.max.x -= delta;
   1.240 +      dr.max.x -= delta;
   1.241 +    }
   1.242 +
   1.243 +  delta = dr.max.y - dest_bitmap->rect.max.y;
   1.244 +  if (delta > 0)
   1.245 +    {
   1.246 +      sr.max.x -= delta;
   1.247 +      dr.max.x -= delta;
   1.248 +    }
   1.249 +
   1.250 +  drw = rect_width (& dr);
   1.251 +  drh = rect_height (& dh);
   1.252 +
   1.253 +  /* if the source rect min y is >= the source bitmap max y,
   1.254 +     we transfer background color to the entire dest rect */
   1.255 +  if (sr.min.y >= src->rect.max.y)
   1.256 +    {
   1.257 +      blt_background (dest_bitmap, & dr);
   1.258 +      goto done;
   1.259 +    }
   1.260 +
   1.261 +  /* if the source rect min y is less than the source bitmap min y,
   1.262 +     we need to transfer some backgound color to the top part of the dest
   1.263 +     rect */
   1.264 +  if (sr.min.y < src->rect.min.y)
   1.265 +    {
   1.266 +      Rect dr2;
   1.267 +      uint32 bg_height;
   1.268 +
   1.269 +      bg_height = src->rect.min.y - sr.min.y;
   1.270 +      if (bg_height > sh)
   1.271 +	bg_height = sh;
   1.272 +
   1.273 +      dr2 = dr;
   1.274 +      dr2.max.y = dr2.min.y + bg_height;
   1.275 +
   1.276 +      blt_background (dest_bitmap, & dr2);
   1.277 +
   1.278 +      /* now reduce the rect height by the number of lines of background
   1.279 +	 color */
   1.280 +      sr.min.y += bg_height;
   1.281 +      dr.min.y += bg_height;
   1.282 +      sh -= bg_height;
   1.283 +      dh -= bg_height;
   1.284 +
   1.285 +      if (sr.min.y == sr.max.y)
   1.286 +	goto done;
   1.287 +    }
   1.288 +
   1.289 +  /* now blt the available rows of the source rect */
   1.290 +
   1.291 +  /* now transfer the background color to any remaining rows of the
   1.292 +     dest rect */
   1.293 +  if (??? )
   1.294 +    {
   1.295 +      blt_background (dest_bitmap, & dr);
   1.296 +    }
   1.297 +
   1.298 + done:
   1.299 +  return (dest_bitmap);
   1.300 +}
   1.301 +#else
   1.302 +Bitmap *bitblt (Bitmap *src_bitmap,
   1.303 +		Rect   *src_rect,
   1.304 +		Bitmap *dest_bitmap,
   1.305 +		Point  *dest_min,
   1.306 +		int tfn,
   1.307 +		int background)
   1.308  {
   1.309    Point src_point, dest_point;
   1.310  
   1.311 @@ -206,73 +413,77 @@
   1.312      }
   1.313    return (dest_bitmap);
   1.314  }
   1.315 +#endif
   1.316  
   1.317  
   1.318  /* in-place transformations */
   1.319  void flip_h (Bitmap *src)
   1.320  {
   1.321 -  u8 *rp;  /* row pointer */
   1.322 -  u8 *p1;  /* work src ptr */
   1.323 -  u8 *p2;  /* work dest ptr */
   1.324 -  u16 d;
   1.325 +  word_type *rp;  /* row pointer */
   1.326 +  word_type *p1;  /* work src ptr */
   1.327 +  word_type *p2;  /* work dest ptr */
   1.328    s32 y;
   1.329 -  int shift;
   1.330 +  int shift1, shift2;
   1.331  
   1.332 -  realloc_temp_buffer (src->rowbytes + 1);
   1.333 +  realloc_temp_buffer ((src->row_words + 1) * sizeof (word_type));
   1.334  
   1.335    rp = src->bits;
   1.336    if ((rect_width (& src->rect) & 7) == 0)
   1.337      {
   1.338        for (y = src->rect.min.y; y < src->rect.max.y; y++)
   1.339  	{
   1.340 -	  memcpy (temp_buffer, rp, src->rowbytes);
   1.341 -	  p1 = temp_buffer + src->rowbytes - 1;
   1.342 +	  memcpy (temp_buffer, rp, src->row_words * sizeof (word_type));
   1.343 +	  p1 = temp_buffer + src->row_words;
   1.344  	  p2 = rp;
   1.345  
   1.346  	  while (p1 >= temp_buffer)
   1.347 -	    *(p2++) = bit_reverse_byte [*(p1--)];
   1.348 +	    *(p2++) = bit_reverse_word (*(p1--));
   1.349        
   1.350 -	  rp += src->rowbytes;
   1.351 +	  rp += src->row_words;
   1.352  	}
   1.353        return;
   1.354      }
   1.355  
   1.356    temp_buffer [0] = 0;
   1.357 -  shift = 8 - (rect_width (& src->rect) & 7);
   1.358 +  shift1 = rect_width (& src->rect) & (BITS_PER_WORD - 1);
   1.359 +  shift2 = BITS_PER_WORD - shift1;
   1.360  
   1.361    for (y = src->rect.min.y; y < src->rect.max.y; y++)
   1.362      {
   1.363 -      memcpy (temp_buffer + 1, rp, src->rowbytes);
   1.364 -      p1 = temp_buffer + src->rowbytes;
   1.365 +      word_type d1, d2;
   1.366 +
   1.367 +      memcpy (temp_buffer + 1, rp, src->row_words * sizeof (word_type));
   1.368 +      p1 = temp_buffer + src->row_words;
   1.369        p2 = rp;
   1.370  
   1.371 -      d = *(p1--);
   1.372 +      d2 = *(p1--);
   1.373  
   1.374        while (p1 >= temp_buffer)
   1.375  	{
   1.376 -	  d = (d >> 8) | ((*(p1--)) << 8);
   1.377 -	  *(p2++) = bit_reverse_byte [(d >> shift) & 0xff];
   1.378 +	  d1 = *(p1--);
   1.379 +	  *(p2++) = bit_reverse_word ((d1 << shift1) | (d2 >> shift2));
   1.380 +	  d2 = d1;
   1.381  	}      
   1.382  
   1.383 -      rp += src->rowbytes;
   1.384 +      rp += src->row_words;
   1.385      }
   1.386  }
   1.387  
   1.388  void flip_v (Bitmap *src)
   1.389  {
   1.390 -  u8 *p1, *p2;
   1.391 +  word_type *p1, *p2;
   1.392  
   1.393 -  realloc_temp_buffer (src->rowbytes);
   1.394 +  realloc_temp_buffer (src->row_words * sizeof (word_type));
   1.395  
   1.396    p1 = src->bits;
   1.397 -  p2 = src->bits + src->rowbytes * (rect_height (& src->rect) - 1);
   1.398 +  p2 = src->bits + src->row_words * (rect_height (& src->rect) - 1);
   1.399    while (p1 < p2)
   1.400      {
   1.401 -      memcpy (temp_buffer, p1, src->rowbytes);
   1.402 -      memcpy (p1, p2, src->rowbytes);
   1.403 -      memcpy (p2, temp_buffer, src->rowbytes);
   1.404 -      p1 += src->rowbytes;
   1.405 -      p2 -= src->rowbytes;
   1.406 +      memcpy (temp_buffer, p1, src->row_words * sizeof (word_type));
   1.407 +      memcpy (p1, p2, src->row_words * sizeof (word_type));
   1.408 +      memcpy (p2, temp_buffer, src->row_words * sizeof (word_type));
   1.409 +      p1 += src->row_words;
   1.410 +      p2 -= src->row_words;
   1.411      }
   1.412  }
   1.413  
   1.414 @@ -285,10 +496,10 @@
   1.415  /* "in-place" transformations - will allocate new memory and free old */
   1.416  void transpose (Bitmap *src)
   1.417  {
   1.418 -  u32 new_rowbytes = CALC_ROWBYTES (rect_height (& src->rect));
   1.419 -  u8 *new_bits;
   1.420 +  u32 new_row_words = DIV_ROUND_UP (rect_height (& src->rect), 32);
   1.421 +  word_type *new_bits;
   1.422  
   1.423 -  new_bits = calloc (1, new_rowbytes * rect_width (& src->rect));
   1.424 +  new_bits = calloc (1, new_row_words * rect_width (& src->rect) * sizeof (word_type));
   1.425  
   1.426    /* $$$ more code needed here */
   1.427  }