/* Copyright 1986, 1988, 1989, 1990, 1995 by Abacus Research and * Development, Inc. All rights reserved. */ #if !defined (OMIT_RCSID_STRINGS) char ROMlib_rcsid_qStdBits[] = "$Id: qStdBits.c 87 2005-05-25 01:57:33Z ctm $"; #endif /* Forward declarations in QuickDraw.h (DO NOT DELETE THIS LINE) */ #include "rsys/common.h" #include "QuickDraw.h" #include "CQuickDraw.h" #include "MemoryMgr.h" #include "ToolboxUtil.h" #include "rsys/stdbits.h" #include "rsys/quick.h" #include "rsys/cquick.h" #include "rsys/region.h" #include "rsys/gworld.h" #include "rsys/picture.h" #include "rsys/mman.h" #include "rsys/flags.h" #include "rsys/host.h" #include "rsys/tempalloc.h" static void ROMlib_real_copy_bits (PixMap *src, PixMap *dst, const Rect *src_rect, const Rect *dst_rect, INTEGER mode, RgnHandle mask); static boolean_t src_dst_overlap_and_dst_below_src_p (const Rect *srcr, const Rect *dstr, int dh, int dv) { if ( (CW (dstr->top)) < (CW (srcr->bottom) + dv) && (CW (srcr->top) + dv) <= (CW (dstr->top)) && (CW (srcr->left) + dh) < (CW (dstr->right)) && (CW (dstr->left)) < (CW (srcr->right) + dh)) return TRUE; else return FALSE; } static inline boolean_t dy_zero_p (const Rect *srcr, const Rect *dstr, int dh, int dv) { return (CW (srcr->top) + dv) == CW (dstr->top); } void canonicalize_bogo_map_cleanup (BitMap *bogo_map, struct cleanup_info *info) { switch (info->cleanup_type) { case cleanup_state: HSetState (info->data.handle, info->h_state); break; case cleanup_free: DisposHandle (info->data.handle); break; case cleanup_unlock_gworld_pixels: UnlockPixels (info->data.pixmap_handle); break; case cleanup_unlock_gworld_pixels_update: { gw_info_t *gw_info; gw_info = info->data.gw_info; UnlockPixels (gw_info->gw_pixmap); BITMAP_BASEADDR_X ((PixMap *) bogo_map) = PIXMAP_BASEADDR_X (gw_info->gw_pixmap); break; } case cleanup_none: break; default: gui_fatal ("unknown cleanup type `%d'", info->cleanup_type); } } void canonicalize_bogo_map (BitMap *bogo_map, PixMap **canonical_addr, struct cleanup_info *info) { int high_bits = ((unsigned short) CW (bogo_map->rowBytes)) >> 14; int low_bit = ((unsigned short) CW (bogo_map->rowBytes)) & 1; switch (high_bits) { /* (BitMap *) */ case 0: { PixMapHandle gd_pmap; PixMap *canonical = *canonical_addr; canonical->baseAddr = bogo_map->baseAddr; canonical->bounds = bogo_map->bounds; canonical->pmVersion = CWC (0); /* no packing currently supported */ canonical->packType = CWC (0); canonical->packSize = CWC (0); canonical->vRes = canonical->hRes = CWC (72); gd_pmap = GD_PMAP (MR (TheGDevice)); if (canonical->baseAddr == PIXMAP_BASEADDR_X (gd_pmap)) { pixmap_set_pixel_fields (canonical, PIXMAP_PIXEL_SIZE (gd_pmap)); canonical->rowBytes = (PIXMAP_ROWBYTES_X (gd_pmap) | PIXMAP_DEFAULT_ROW_BYTES_X); canonical->pmTable = PIXMAP_TABLE_X (gd_pmap); info->cleanup_type = cleanup_none; } else { pixmap_set_pixel_fields (canonical, 1); canonical->rowBytes = (bogo_map->rowBytes | PIXMAP_DEFAULT_ROW_BYTES_X); info->cleanup_type = cleanup_none; canonical->pmTable = RM (validate_relative_bw_ctab ()); } canonical->planeBytes = CWC (0); canonical->pmReserved = CWC (0); break; } /* (unknown) */ case 1: gui_abort (); /* pointer to pixmap */ case 2: { gw_info_t *gw_info; gw_info = (lookup_gw_info_by_gw_pixmap_baseaddr (BITMAP_BASEADDR ((PixMap *) bogo_map))); if (gw_info) { LockPixels (gw_info->gw_pixmap); BITMAP_BASEADDR_X ((PixMap *) bogo_map) = PIXMAP_BASEADDR_X (gw_info->gw_pixmap); info->cleanup_type = cleanup_unlock_gworld_pixels_update; info->data.gw_info = gw_info; } else info->cleanup_type = cleanup_none; *canonical_addr = (PixMap *) bogo_map; break; } /* (CGrafPtr spew) */ case 3: if (low_bit) { CGrafPtr gw; PixMapHandle pixmap; gw = (CGrafPtr) ((char *) bogo_map - 2); pixmap = CPORT_PIXMAP (gw); *canonical_addr = STARH (pixmap); info->cleanup_type = cleanup_unlock_gworld_pixels; info->data.pixmap_handle = pixmap; /* lock the pixels */ LockPixels (pixmap); } else { PixMapHandle pixmap_handle = MR (*(PixMapHandle *) bogo_map); *canonical_addr = STARH (pixmap_handle); info->cleanup_type = cleanup_state; info->data.pixmap_handle = pixmap_handle; info->h_state = HGetState ((Handle) pixmap_handle); /* lock the pixmap handle */ HSetState ((Handle) pixmap_handle, info->h_state | LOCKBIT); break; } } #if !defined (NDEBUG) if ( (RECT_WIDTH (&BITMAP_BOUNDS (*canonical_addr)) * CW ((*canonical_addr)->pixelSize) / 8) > BITMAP_ROWBYTES (*canonical_addr)) warning_unexpected ("unlikely map"); #endif } static void write_copybits_picdata (PixMap *src, PixMap *dst, const Rect *src_rect, const Rect *dst_rect, int16 mode, RgnHandle mask) { int32 zero = 0; int16 opcode; int16 swapped_mode; int16 row_bytes; int16 temp_pixmap_row_bytes; int16 pack_type; int16 pixel_size; int height; int i; boolean_t direct_bits_p; { /* always copy the src pixmap since the code below, as it is written, will always record the _entire_ src, which is very bad if the src is the screen, or some other large image */ /* it is also necessary to copy when we are the src is the actual screen */ PixMap *_src; Rect *_src_rect; _src = alloca (sizeof *_src); _src_rect = alloca (sizeof *_src_rect); ZONE_SAVE_EXCURSION (ApplZone, { if (FreeMemSys () >= FreeMem ()) TheZone = SysZone; pixmap_copy (src, src_rect, _src, _src_rect); }); src = _src; src_rect = _src_rect; } row_bytes = BITMAP_ROWBYTES (src); pixel_size = CW (src->pixelSize); direct_bits_p = (pixel_size == 16 || pixel_size == 32); if (pixel_size == 32) pack_type = CWC (2); else pack_type = CWC (0); if (direct_bits_p) opcode = mask ? OP_DirectBitsRgn : OP_DirectBitsRect; else if (row_bytes < 8) opcode = mask ? OP_BitsRgn : OP_BitsRect; else opcode = mask ? OP_PackBitsRgn : OP_PackBitsRect; ROMlib_drawingpicupdate (); PICOP (opcode); if (direct_bits_p) { int32 swapped_bogo_baseaddr = CLC (0xFF); PICWRITE (&swapped_bogo_baseaddr, sizeof swapped_bogo_baseaddr); } temp_pixmap_row_bytes = src->rowBytes | PIXMAP_DEFAULT_ROWBYTES_X; PICWRITE (&temp_pixmap_row_bytes, sizeof temp_pixmap_row_bytes); PICWRITE (&src->bounds, sizeof src->bounds); PICWRITE (&src->pmVersion, sizeof src->pmVersion); /* pack type of bits stored in the picture may not necessarily match the pack type of the actual pixmap */ PICWRITE (&pack_type, sizeof pack_type); PICWRITE (&src->packSize, sizeof src->packSize); PICWRITE (&src->hRes, sizeof src->hRes); PICWRITE (&src->vRes, sizeof src->vRes); PICWRITE (&src->pixelType, sizeof src->pixelType); PICWRITE (&src->pixelSize, sizeof src->pixelSize); PICWRITE (&src->cmpCount, sizeof src->cmpCount); PICWRITE (&src->cmpSize, sizeof src->cmpSize); PICWRITE (&src->planeBytes, sizeof src->planeBytes); PICWRITE (&zero, sizeof zero); PICWRITE (&src->pmReserved, sizeof src->pmReserved); if (! direct_bits_p) { LOCK_HANDLE_EXCURSION_1 (MR (src->pmTable), { CTabPtr ctab; ctab = STARH (MR (src->pmTable)); /* write out the src color table */ PICWRITE (&zero, sizeof zero); PICWRITE (&ctab->ctFlags, sizeof ctab->ctFlags); PICWRITE (&ctab->ctSize, sizeof ctab->ctSize); for (i = 0; i <= CW (ctab->ctSize); i ++) { ColorSpec *elt; elt = &ctab->ctTable[i]; PICWRITE (&elt->value, sizeof elt->value); PICWRITE (&elt->rgb, sizeof elt->rgb); } }); } PICWRITE (src_rect, sizeof *src_rect); PICWRITE (dst_rect, sizeof *dst_rect); swapped_mode = CW (mode); PICWRITE (&swapped_mode, sizeof swapped_mode); if (mask) { LOCK_HANDLE_EXCURSION_1 (mask, { PICWRITE (STARH (mask), Hx (mask, rgnSize)); }); } height = RECT_HEIGHT (&src->bounds); if (row_bytes < 8 || pack_type == CWC (2)) { if (pack_type == CWC (2)) { uint8 *current, *end; current = (uint8 *) MR (src->baseAddr) + 1; end = current + row_bytes * height; while (current < end) { PICWRITE (current, 3 * sizeof *current); current += 4; } if ((row_bytes / 4 * height) & 1) PICWRITE ("", 1); } else PICWRITE (MR (src->baseAddr), row_bytes * height); } else { HIDDEN_Ptr ip, op; int parity; uint8 *packed_line; int8 *countloc; int16 count, swappedcount, countsize; uint8 *baseaddr; /* i copied the code below from the executor 1.2 implementation of StdBits pic recording. i can't say i fully understand it */ /* #### why the extra 5 bytes? */ packed_line = alloca (row_bytes + 5); baseaddr = (uint8 *) MR (src->baseAddr); ip.p = (Ptr) baseaddr; parity = 0; if (row_bytes > 250) { countloc = (int8 *) &swappedcount; countsize = 2; } else { countloc = (int8 *) &swappedcount + 1; countsize = 1; } for (i = 0; i < height; i ++) { op.p = (Ptr) RM (packed_line); gui_assert ((uint8 *) ip.p == &baseaddr[row_bytes * i]); ip.p = RM (ip.p); PackBits (&ip, &op, row_bytes); op.p = MR (op.p); ip.p = MR (ip.p); count = op.p - (Ptr) packed_line; parity += count + countsize; swappedcount = CW (count); PICWRITE (countloc, countsize); PICWRITE (packed_line, count); } /* even things up */ if (parity & 1) PICWRITE ("", 1); } pixmap_free_copy (src); } void ROMlib_bogo_stdbits (BitMap *src_bogo_map, BitMap *dst_bogo_map, const Rect *src_rect, const Rect *dst_rect, short mode, RgnHandle mask) { Rect dummy_rect; PixMap dummy_space[2]; PixMap *src = &dummy_space[0], *dst = &dummy_space[1]; struct cleanup_info cleanup_info[2]; if (CW (dst_rect->bottom) <= CW (dst_rect->top) || CW (dst_rect->right) <= CW (dst_rect->left) || (mask && !SectRect (dst_rect, &HxX (mask, rgnBBox), &dummy_rect))) return; /* the incoming source and destinations can be any one of the following; a `BitMap *', the high two bits of rowBytes must be zero, or CGrafPort coerced to a GrafPort with the PortBits passed in; in this case the high two bits of rowBytes must be `11'; and the baseAddr field is a `PixMapHandle' each of these types are canonicalized into a `PixMap *', which is what we work with here */ /* these functions lock the PixMapHandle if src or dst are from a coerced CGrafPort; we must make sure to unlock those handles on the way out */ canonicalize_bogo_map (src_bogo_map, &src, &cleanup_info[0]); canonicalize_bogo_map (dst_bogo_map, &dst, &cleanup_info[1]); PIC_SAVE_EXCURSION ({ write_copybits_picdata (src, dst, src_rect, dst_rect, mode, mask); }); if (PORT_PEN_VIS (thePort) < 0) return; ROMlib_real_copy_bits (src, dst, src_rect, dst_rect, mode, mask); canonicalize_bogo_map_cleanup (src_bogo_map, &cleanup_info[0]); canonicalize_bogo_map_cleanup (dst_bogo_map, &cleanup_info[1]); } void StdBitsPicSaveFlag (BitMap *src_bogo_map, const Rect *src_rect, const Rect *dst_rect, INTEGER mode, RgnHandle mask, BOOLEAN savepic) { Rect dummy_rect; /* we want the actual port bits, no fooling; so don't use the accessor macros */ BitMap *dst_bogo_map = &thePort->portBits; PixMap dummy_space[2]; PixMap *src = &dummy_space[0], *dst = &dummy_space[1]; struct cleanup_info cleanup_info[2]; if (CW (dst_rect->bottom) <= CW (dst_rect->top) || CW (dst_rect->right) <= CW (dst_rect->left) || (mask && !SectRect (dst_rect, &HxX (mask, rgnBBox), &dummy_rect))) return; /* the incoming source and destinations can be any one of the following; a `BitMap *', the high two bits of rowBytes must be zero, or CGrafPort coerced to a GrafPort with the PortBits passed in; in this case the high two bits of rowBytes must be `11'; and the baseAddr field is a `PixMapHandle' each of these types are canonicalized into a `PixMap *', which is what we work with here */ /* these functions lock the PixMapHandle if src or dst are from a coerced CGrafPort; we must make sure to unlock those handles on the way out */ canonicalize_bogo_map (src_bogo_map, &src, &cleanup_info[0]); canonicalize_bogo_map (dst_bogo_map, &dst, &cleanup_info[1]); if (savepic) { PIC_SAVE_EXCURSION ({ write_copybits_picdata (src, dst, src_rect, dst_rect, mode, mask); }); } if (PORT_PEN_VIS (thePort) < 0) return; ROMlib_real_copy_bits (src, dst, src_rect, dst_rect, mode, mask); canonicalize_bogo_map_cleanup (src_bogo_map, &cleanup_info[0]); canonicalize_bogo_map_cleanup (dst_bogo_map, &cleanup_info[1]); } P5 (PUBLIC pascal trap, void, StdBits, /* destination is alawys the current port */ BitMap *, src_bogo_map, const Rect *, src_rect, const Rect *, dst_rect, INTEGER, mode, RgnHandle, mask) { StdBitsPicSaveFlag (src_bogo_map, src_rect, dst_rect, mode, mask, TRUE); } static void ROMlib_real_copy_bits_helper (PixMap *src, PixMap *dst, const Rect *src_rect, const Rect *dst_rect, INTEGER mode, RgnHandle mask) { GDHandle the_gd; PixMapHandle the_gd_pmap; GrafPtr current_port; Rect tmp_mask_rect; uint32 bk_color, fg_color; /* region used to compute the complete mask region */ RgnHandle mask_region; /* bits of a pixel position in `src' that have a resolution below that of a byte */ int dst_sub_byte_bits; /* final depth of the destination */ int dst_depth; const rgb_spec_t *dst_rgb_spec; #if defined (SAVE_CURSOR) int save_cursor_visible_p = FALSE; int screen_src_p; #endif /* SAVE_CURSOR */ TEMP_ALLOC_DECL (temp_depth_bits); TEMP_ALLOC_DECL (temp_scale_bits); TEMP_ALLOC_DECL (temp_overlap_bits); the_gd = MR (TheGDevice); the_gd_pmap = GD_PMAP (the_gd); current_port = thePort; #if defined (SAVE_CURSOR) screen_src_p = active_screen_addr_p (src); #endif dst_rgb_spec = pixmap_rgb_spec (dst); dst_depth = CW (dst->pixelSize); switch (dst_depth) { case 1: dst_sub_byte_bits = 7; break; case 2: dst_sub_byte_bits = 3; break; case 4: dst_sub_byte_bits = 1; break; default: dst_sub_byte_bits = 0; break; } ROMlib_fg_bk (&fg_color, &bk_color, NULL, NULL, dst_rgb_spec, active_screen_addr_p (dst), dst_depth <= 8); /* if the source and dest differ in depths, perform a depth conversion on the src, so it matches that of the depth */ if (src->pixelSize != dst->pixelSize || (src->pmTable != dst->pmTable && (CW (src->pixelSize) < 16 && (CTAB_SEED_X (MR (src->pmTable)) /* we assume the destination has the same color table as the current graphics device */ != CTAB_SEED_X (PIXMAP_TABLE (GD_PMAP (the_gd))) && CTAB_SEED_X (MR (src->pmTable)) != CLC (0))))) { PixMap *new_src = (PixMap *) alloca (sizeof (PixMap)); /* convert_pixmap expects the src rect to be aligned to byte boundaries; compute that in `widened_src_rect' */ Rect *widened_src_rect = (Rect *) alloca (sizeof (Rect)); int src_depth, src_sub_byte_bits; void *new_src_bits; int n_bytes_needed; #if defined (SAVE_CURSOR) if (screen_src_p) { save_cursor_visible_p = host_set_cursor_visible (FALSE); screen_src_p = FALSE; } #endif /* SAVE_CURSOR */ src_depth = CW (src->pixelSize); switch (src_depth) { case 1: src_sub_byte_bits = 7; break; case 2: src_sub_byte_bits = 3; break; case 4: src_sub_byte_bits = 1; break; default: src_sub_byte_bits = 0; break; } widened_src_rect->top = src_rect->top; widened_src_rect->bottom = src_rect->bottom; /* translate the left (right) src_rect coords to absolute bitmap coordinates; and round down (up) to the byte boundary, and re-translate to boundary-relative bitmap coords */ widened_src_rect->left = CW (((CW (src_rect->left) - CW (src->bounds.left)) & ~src_sub_byte_bits) + CW (src->bounds.left)); widened_src_rect->right = CW ((((CW (src_rect->right) - CW (src->bounds.left)) + src_sub_byte_bits) & ~src_sub_byte_bits) + CW (src->bounds.left)); /* the new_src should `be a pixmap' (have the pixmap bits set in the rowBytes) only if the dst is a pixmap; convert_pixmap does different things if the destination is a bitmap */ new_src->rowBytes = ( PIXMAP_DEFAULT_ROW_BYTES_X | CW ((((RECT_WIDTH (widened_src_rect) * dst_depth) + 31) / 32) * 4)); /* Allocate temporary storage for the new_src_bits bitmap. */ n_bytes_needed = (BITMAP_ROWBYTES (new_src) * (CW (src_rect->bottom) - CW (src_rect->top))); TEMP_ALLOC_ALLOCATE (new_src_bits, temp_depth_bits, n_bytes_needed); new_src->baseAddr = RM (new_src_bits); pixmap_set_pixel_fields (new_src, dst_depth); new_src->pmTable = PIXMAP_TABLE_X (the_gd_pmap); /* don't initialize the color table of new_src; we assume that it has the same color space as the current graphics device */ convert_pixmap (src, new_src, widened_src_rect, NULL); src = new_src; /* `convert_pixmap ()' jukes the coordinates of the new_src bitmap so that `src_rect' is still correct */ } /* if the source and dest rectangles are not equivalent, scale the source rectangle */ if (RECT_WIDTH (src_rect) != RECT_WIDTH (dst_rect) || RECT_HEIGHT (src_rect) != RECT_HEIGHT (dst_rect)) { PixMap *new_src = (PixMap *) alloca (sizeof (PixMap)); int new_src_row_bytes; void *scale_base; #if defined (SAVE_CURSOR) if (screen_src_p) { save_cursor_visible_p = host_set_cursor_visible (FALSE); screen_src_p = FALSE; } #endif /* SAVE_CURSOR */ new_src_row_bytes = (((RECT_WIDTH (dst_rect) * dst_depth + /* dst_sub_byte_bits */ 7) / 8) + 3) & ~3; new_src->rowBytes = CW (new_src_row_bytes) | PIXMAP_DEFAULT_ROW_BYTES_X; TEMP_ALLOC_ALLOCATE (scale_base, temp_scale_bits, new_src_row_bytes * RECT_HEIGHT (dst_rect)); new_src->baseAddr = (Ptr) RM (scale_base); pixmap_set_pixel_fields (new_src, dst_depth); scale_blt_bitmap ((blt_bitmap_t *) src, (blt_bitmap_t *) new_src, src_rect, dst_rect, ROMlib_log2[dst_depth]); src = new_src; src_rect = dst_rect; } /* compute the mask region before checking if the source and dest overlap becuase we only double buffer if dy is nonzero */ /* intersect the region mask with thePort bounds, thePort rect, the destination rect, and the port {clip, vis} regions */ mask_region = NewRgn (); SectRect (dst_rect, &dst->bounds, &tmp_mask_rect); RectRgn (mask_region, &tmp_mask_rect); SectRgn (PORT_CLIP_REGION (current_port), mask_region, mask_region); SectRgn (PORT_VIS_REGION (current_port), mask_region, mask_region); if (mask) SectRgn (mask, mask_region, mask_region); if (src->baseAddr == dst->baseAddr && (src_dst_overlap_and_dst_below_src_p (src_rect, dst_rect, CW (dst->bounds.left) - CW (src->bounds.left), CW (dst->bounds.top) - CW (src->bounds.top))) && (! RGN_SMALL_P (mask_region) || dy_zero_p (src_rect, dst_rect, CW (dst->bounds.left) - CW (src->bounds.left), CW (dst->bounds.top) - CW (src->bounds.top)))) { PixMap *new_src; void *overlap_bits; Rect copy_rect; Rect clipped_src_rect; int height, offset; /* the source and destination are overlapped; create a new src bitmap */ new_src = (PixMap *) alloca (sizeof *new_src); #if defined (SAVE_CURSOR) if (screen_src_p) { save_cursor_visible_p = host_set_cursor_visible (FALSE); screen_src_p = FALSE; } #endif /* SAVE_CURSOR */ SectRect (&src->bounds, src_rect, &clipped_src_rect); height = RECT_HEIGHT (&clipped_src_rect); offset = CW (clipped_src_rect.top) - CW (src_rect->top); copy_rect.top = CW (CW (src_rect->top) + offset); copy_rect.bottom = CW (CW (src_rect->top) + offset + height); copy_rect.left = src->bounds.left; copy_rect.right = src->bounds.right; new_src->rowBytes = src->rowBytes; TEMP_ALLOC_ALLOCATE (overlap_bits, temp_overlap_bits, height * BITMAP_ROWBYTES (src)); new_src->baseAddr = (Ptr) RM (overlap_bits); new_src->bounds = copy_rect; pixmap_set_pixel_fields (new_src, dst_depth); new_src->pmTable = src->pmTable; /* pause picture recording since we don't want the recursive call to copy the overlapping image to be recorded */ { uint32 black_pixel, white_pixel; RgnHandle rgn; rgn = NewRgn (); RectRgn (rgn, ©_rect); pixmap_black_white (new_src, &black_pixel, &white_pixel); ROMlib_blt_rgn_update_dirty_rect (rgn, srcCopy, FALSE, dst_depth, src, new_src, ©_rect, ©_rect, black_pixel, white_pixel); DisposeRgn (rgn); } src = new_src; } ROMlib_blt_rgn_update_dirty_rect (mask_region, mode, FALSE, dst_depth, src, dst, src_rect, dst_rect, fg_color, bk_color); #if defined (SAVE_CURSOR) if (save_cursor_visible_p) host_set_cursor_visible (TRUE); #endif DisposeRgn (mask_region); TEMP_ALLOC_FREE (temp_overlap_bits); TEMP_ALLOC_FREE (temp_scale_bits); TEMP_ALLOC_FREE (temp_depth_bits); } #if 1 /* * If we're copying a big 1-bpp bitmap to a small 8-bpp pixmap, we really * want to first copy to a temporary small 1-bpp bitmap and then copy that * to a small 8-bpp pixmap, otherwise we expand our large bitmap by a factor * of 8, which can be excessive. */ static void ROMlib_real_copy_bits (PixMap *src, PixMap *dst, const Rect *src_rect, const Rect *dst_rect, INTEGER mode, RgnHandle mask) { boolean_t shrink_first_p; if (src->pixelSize == dst->pixelSize) shrink_first_p = FALSE; else { int default_nbits, new_nbits; default_nbits = (RECT_WIDTH (src_rect) * CW (dst->pixelSize) * RECT_HEIGHT (src_rect)); new_nbits = ((RECT_WIDTH (dst_rect) * CW (src->pixelSize) * RECT_HEIGHT (dst_rect)) + (RECT_WIDTH (dst_rect) * CW (dst->pixelSize) * RECT_HEIGHT (dst_rect))); shrink_first_p = (new_nbits < default_nbits); } if (!shrink_first_p) ROMlib_real_copy_bits_helper (src, dst, src_rect, dst_rect, mode, mask); else { PixMap *new_src; int temp_bytes_needed; void *temp_bits; INTEGER temp_row_bytes; int src_depth; #if defined (SAVE_CURSOR) int save_cursor_visible_p = FALSE; int screen_src_p; #endif /* SAVE_CURSOR */ TEMP_ALLOC_DECL (temp_alloc_bits); #if defined (SAVE_CURSOR) screen_src_p = active_screen_addr_p (src); if (screen_src_p) { save_cursor_visible_p = host_set_cursor_visible (FALSE); screen_src_p = FALSE; } #endif /* SAVE_CURSOR */ new_src = (PixMap *) alloca (sizeof *new_src); src_depth = CW (src->pixelSize); temp_row_bytes = (RECT_WIDTH (dst_rect) * src_depth + 31) / 32 * 4; temp_bytes_needed = temp_row_bytes * RECT_HEIGHT (dst_rect); TEMP_ALLOC_ALLOCATE (temp_bits, temp_alloc_bits, temp_bytes_needed); *new_src = *src; new_src->baseAddr = RM (temp_bits); new_src->rowBytes = CW (temp_row_bytes | PIXMAP_DEFAULT_ROWBYTES); new_src->bounds = *dst_rect; scale_blt_bitmap ((blt_bitmap_t *) src, (blt_bitmap_t *) new_src, src_rect, dst_rect, ROMlib_log2[src_depth]); ROMlib_real_copy_bits_helper (new_src, dst, dst_rect, dst_rect, mode, mask); TEMP_ALLOC_FREE (temp_alloc_bits); } } #endif