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