executor/src/qPixMapConv.c

606 lines
15 KiB
C

/* Copyright 1994, 1995 by Abacus Research and
* Development, Inc. All rights reserved.
*/
#if !defined (OMIT_RCSID_STRINGS)
char ROMlib_rcsid_qPixMapConv[] =
"$Id: qPixMapConv.c 87 2005-05-25 01:57:33Z ctm $";
#endif
#include "rsys/common.h"
#include "QuickDraw.h"
#include "CQuickDraw.h"
#include "MemoryMgr.h"
#include "rsys/depthconv.h"
#include "rsys/cquick.h"
#include "rsys/rgbutil.h"
#include "rsys/prefs.h"
#include "rsys/tempalloc.h"
#include "rsys/picture.h"
#include "rsys/mman.h"
#include "rsys/vdriver.h"
static uint32 depth_table_space[DEPTHCONV_MAX_UINT32_TABLE_SIZE];
static depthconv_func_t conversion_func = NULL;
static int32 cached_src_bpp = -1, cached_dst_bpp = -1;
static int32 cached_src_seed_x = CLC (-1), cached_dst_seed_x = CLC (-1);
static ITabHandle target_itab;
rgb_spec_t mac_16bpp_rgb_spec, mac_32bpp_rgb_spec;
void
pixmap_black_white (const PixMap *pixmap,
uint32 *black_return, uint32 *white_return)
{
if (pixmap->pixelType == CWC (RGBDirect))
{
const rgb_spec_t *rgb_spec;
rgb_spec = pixmap_rgb_spec (pixmap);
*black_return = rgb_spec->black_pixel;
*white_return = rgb_spec->white_pixel;
}
else
{
int bpp;
bpp = CW (pixmap->pixelSize);
*black_return = (1 << bpp) - 1;
*white_return = 0;
}
}
void
gd_black_white (GDHandle gdh,
uint32 *black_return, uint32 *white_return)
{
GDPtr gd;
PixMapPtr gd_pmap;
gd = STARH (gdh);
gd_pmap = STARH (MR (gd->gdPMap));
pixmap_black_white (gd_pmap, black_return, white_return);
}
void
pixmap_free_copy (PixMap *pm)
{
DisposPtr (MR (pm->baseAddr));
}
void
pixmap_copy (const PixMap *src_pm, const Rect *src_rect,
PixMap *return_pm, Rect *return_rect)
{
/* alas, we must copy to a scratch bitmap */
/* src is the bitmap in the active screen which cannot be
accessed dirctly */
int row_bytes;
int width, height;
width = RECT_WIDTH (src_rect);
height = RECT_HEIGHT (src_rect);
*return_rect = *src_rect;
/* default pixmap field values are the same for src and return
pixmaps */
*return_pm = *src_pm;
row_bytes = ((width * CW (src_pm->pixelSize) + 31) / 32) * 4;
return_pm->baseAddr = RM (NewPtr (height * row_bytes));
return_pm->rowBytes = CW ( row_bytes
| PIXMAP_DEFAULT_ROW_BYTES);
return_pm->bounds = *return_rect;
{
uint32 black_pixel, white_pixel;
RgnHandle rgn;
Rect tmp_rect;
rgn = NewRgn ();
SectRect (return_rect, &return_pm->bounds, &tmp_rect);
RectRgn (rgn, &tmp_rect);
pixmap_black_white (src_pm, &black_pixel, &white_pixel);
ROMlib_blt_rgn_update_dirty_rect (rgn, srcCopy,
FALSE, CW (src_pm->pixelSize),
src_pm, return_pm,
src_rect, return_rect,
black_pixel, white_pixel);
DisposeRgn (rgn);
}
}
boolean_t
pixmap_copy_if_screen (const PixMap *src_pm, const Rect *src_rect,
write_back_data_t *write_back_data)
{
#if defined (VDRIVER_SUPPORTS_REAL_SCREEN_BLITS)
if (VDRIVER_BYPASS_INTERNAL_FBUF_P ()
&& active_screen_addr_p (src_pm))
{
write_back_data->dst_pm = *src_pm;
write_back_data->dst_rect = *src_rect;
pixmap_copy (src_pm, src_rect,
&write_back_data->src_pm, &write_back_data->src_rect);
return TRUE;
}
#endif
return FALSE;
}
uint32
pixel_from_rgb (RGBColor *color,
const rgb_spec_t *rgb_spec)
{
if (rgb_spec)
return ((rgb_spec->rgbcolor_to_pixel)
(rgb_spec, color, TRUE));
else
return Color2Index (color);
}
void
canonical_from_bogo_color (uint32 index,
const rgb_spec_t *rgb_spec,
uint32 *pixel_out,
RGBColor *rgb_out)
{
if (rgb_spec)
{
RGBColor t_color;
rgb_spec_t *mac_rgb_spec;
if (rgb_spec->bpp == 16)
{
mac_rgb_spec = &mac_16bpp_rgb_spec;
if (rgb_spec == mac_rgb_spec)
{
if (pixel_out)
*pixel_out = CW (index);
if (rgb_out)
(rgb_spec->pixel_to_rgbcolor) (rgb_spec, index, rgb_out);
return;
}
}
else if (rgb_spec->bpp == 32)
{
mac_rgb_spec = &mac_32bpp_rgb_spec;
if (rgb_spec == mac_rgb_spec)
{
if (pixel_out)
*pixel_out = CL (index);
if (rgb_out)
(rgb_spec->pixel_to_rgbcolor) (rgb_spec, index, rgb_out);
return;
}
}
else
gui_fatal ("unknown bpp");
(mac_rgb_spec->pixel_to_rgbcolor) (mac_rgb_spec, index, &t_color);
if (pixel_out)
*pixel_out = (rgb_spec->rgbcolor_to_pixel) (rgb_spec, &t_color, TRUE);
if (rgb_out)
*rgb_out = t_color;
}
else
{
if (pixel_out)
*pixel_out = index;
if (rgb_out)
Index2Color (index, rgb_out);
}
}
void
ROMlib_fg_bk (uint32 *fg_pixel_out, uint32 *bk_pixel_out,
RGBColor *fg_rgb_out, RGBColor *bk_rgb_out,
const rgb_spec_t *rgb_spec,
boolean_t active_screen_addr_p,
boolean_t indirect_p)
{
GrafPtr current_port;
uint32 fg_pixel, bk_pixel;
RGBColor fg_rgb, bk_rgb;
current_port = thePort;
if (CGrafPort_p (current_port))
{
if (indirect_p)
{
fg_rgb = CPORT_RGB_FG_COLOR (current_port);
fg_pixel = pixel_from_rgb (&fg_rgb, rgb_spec);
bk_rgb = CPORT_RGB_BK_COLOR (current_port);
bk_pixel = pixel_from_rgb (&bk_rgb, rgb_spec);
}
else
{
canonical_from_bogo_color (PORT_FG_COLOR (current_port), rgb_spec,
&fg_pixel, &fg_rgb);
canonical_from_bogo_color (PORT_BK_COLOR (current_port), rgb_spec,
&bk_pixel, &bk_rgb);
}
}
else
{
if (active_screen_addr_p)
{
uint32 fg_color, bk_color;
fg_color = PORT_FG_COLOR (current_port);
fg_rgb = *ROMlib_qd_color_to_rgb (fg_color);
fg_pixel = pixel_from_rgb (&fg_rgb, rgb_spec);
bk_color = PORT_BK_COLOR (current_port);
bk_rgb = *ROMlib_qd_color_to_rgb (bk_color);
bk_pixel = pixel_from_rgb (&bk_rgb, rgb_spec);
}
else
{
uint32 black_pixel, white_pixel;
black_pixel = pixel_from_rgb (&ROMlib_black_rgb_color,
rgb_spec);
white_pixel = pixel_from_rgb (&ROMlib_white_rgb_color,
rgb_spec);
if (PORT_FG_COLOR (current_port) == whiteColor)
{
fg_pixel = white_pixel;
fg_rgb = ROMlib_white_rgb_color;
}
else
{
fg_pixel = black_pixel;
fg_rgb = ROMlib_black_rgb_color;
}
if (PORT_BK_COLOR (current_port) == whiteColor)
{
bk_pixel = white_pixel;
bk_rgb = ROMlib_white_rgb_color;
}
else
{
bk_pixel = black_pixel;
bk_rgb = ROMlib_black_rgb_color;
}
}
}
if (fg_pixel_out)
*fg_pixel_out = fg_pixel;
if (bk_pixel_out)
*bk_pixel_out = bk_pixel;
if (fg_rgb_out)
*fg_rgb_out = fg_rgb;
if (bk_rgb_out)
*bk_rgb_out = bk_rgb;
}
const rgb_spec_t *
pixmap_rgb_spec (const PixMap *pixmap)
{
if (pixmap->pixelType == CWC (RGBDirect)
|| pixmap->pixelType == CWC (vdriver_rgb_pixel_type))
{
if (vdriver_rgb_spec
&& (active_screen_addr_p (pixmap)
|| pixmap->pixelType == CWC (vdriver_rgb_pixel_type)))
return vdriver_rgb_spec;
else if (pixmap->pixelSize == CWC (16))
return &mac_16bpp_rgb_spec;
else if (pixmap->pixelSize == CWC (32))
return &mac_32bpp_rgb_spec;
else
gui_fatal ("unknown pixel size");
}
else
return NULL;
}
void
pixmap_set_pixel_fields (PixMap *pixmap, int bpp)
{
pixmap->packType = pixmap->packSize = CWC (0);
if (bpp <= 8)
{
pixmap->pixelType = CWC (Indirect);
pixmap->cmpSize = pixmap->pixelSize = CW (bpp);
pixmap->cmpCount = CWC (1);
}
else
{
pixmap->pixelType = CWC (RGBDirect);
pixmap->pixelSize = CW (bpp);
pixmap->cmpCount = CWC (3);
switch (bpp)
{
case 16:
pixmap->cmpSize = CWC (5);
break;
case 32:
pixmap->cmpSize = CWC (8);
break;
}
}
}
static void
sort_color_table (CTabHandle dsth, const CTabHandle srch)
{
CTabPtr src, dst;
INTEGER src_ct_size;
src = STARH (srch);
dst = STARH (dsth);
/* Claris Home Page has some PICTs with color tables that are too large,
so we make sure we don't try to copy too much. */
src_ct_size = MIN (CW (src->ctSize), CW (dst->ctSize));
if (src->ctFlags & CTAB_GDEVICE_BIT_X)
{
dst->ctSeed = src->ctSeed;
memcpy (dst->ctTable, src->ctTable,
sizeof src->ctTable[0] * (src_ct_size + 1));
}
else
{
ColorSpec *src_table, *dst_table;
int max_ctab_elt;
int i;
src_table = src->ctTable;
dst_table = dst->ctTable;
max_ctab_elt = CW (dst->ctSize);
dst->ctSeed = src->ctSeed;
for (i = src_ct_size; i >= 0; i--)
dst_table[CW (src_table[i].value) & max_ctab_elt].rgb
= src_table[i].rgb;
}
}
void
convert_pixmap (const PixMap *src, PixMap *dst,
const Rect *rect,
CTabPtr conv_table)
{
GDHandle the_gd;
int src_bpp, dst_bpp;
int width, height;
int32 dst_seed_x, src_seed_x;
const rgb_spec_t *src_rgb_spec, *dst_rgb_spec;
uint8 *src_base, *dst_base;
int16 src_row_bytes, dst_row_bytes;
write_back_data_t write_back;
boolean_t copy_p;
TEMP_ALLOC_DECL (temp_scratch_pm_bits);
/* Grab some useful information about the PixMaps. */
src_bpp = CW (src->pixelSize);
dst_bpp = CW (dst->pixelSize);
width = RECT_WIDTH (rect);
height = RECT_HEIGHT (rect);
/* Make sure both bits per pixel are powers of 2 less than or equal
to 32. */
gui_assert (src_bpp <= 32 && dst_bpp <= 32
&& (src_bpp & (src_bpp - 1)) == 0
&& (dst_bpp & (dst_bpp - 1)) == 0);
the_gd = MR (TheGDevice);
#define BPP_PIXEL_TYPE(bpp) ((bpp) > 8 ? RGBDirect : Indirect)
#define MUNGE(a, b) ((a) + (b) * 0x100)
switch (MUNGE (BPP_PIXEL_TYPE (src_bpp),
BPP_PIXEL_TYPE (dst_bpp)))
{
case MUNGE (Indirect, Indirect):
{
src_seed_x = CTAB_SEED_X (MR (src->pmTable)); /* big endian */
dst_seed_x = CTAB_SEED_X (PIXMAP_TABLE (GD_PMAP (the_gd)));
if ( src_bpp != cached_src_bpp || dst_bpp != cached_dst_bpp
|| src_seed_x != cached_src_seed_x || dst_seed_x != cached_dst_seed_x
|| conv_table)
{
if (conv_table)
{
conversion_func
= depthconv_make_ind_to_ind_table (depth_table_space,
src_bpp, dst_bpp, NULL,
conv_table->ctTable);
/* Remember the specs for the table we just created. */
cached_src_seed_x = CLC (-1);
cached_dst_seed_x = CLC (-1);
}
else
{
CTabHandle target_table, src_table;
CTabHandle mapping;
int max_mapping_elt, max_src_elt;
src_table = MR (src->pmTable);
max_src_elt = CTAB_SIZE (src_table);
max_mapping_elt = (1 << src_bpp) - 1;
mapping
= (CTabHandle) (NewHandle
(CTAB_STORAGE_FOR_SIZE (max_mapping_elt)));
CTAB_SIZE_X (mapping) = CW (max_mapping_elt);
CTAB_FLAGS_X (mapping) = CWC (0);
/* the source color table may not specify all possible
colors, so set unspecified colors to some sane value
really, we only need to set the `value' field
of the color specs */
if (max_mapping_elt > max_src_elt)
memset (&CTAB_TABLE (mapping)[max_src_elt + 1], 0,
(max_mapping_elt - max_src_elt) * sizeof (ColorSpec));
sort_color_table (mapping, src_table);
if (dst_bpp == 1 && BITMAP_P (dst))
target_table = ROMlib_bw_ctab;
else
target_table = NULL;
GetSubTable (mapping, DEFAULT_ITABLE_RESOLUTION,
target_table);
conversion_func
= depthconv_make_ind_to_ind_table (depth_table_space,
src_bpp, dst_bpp, NULL,
CTAB_TABLE (mapping));
/* free up the mapping table */
DisposHandle ((Handle) mapping);
/* Remember the specs for the table we just created. */
cached_src_seed_x = src_seed_x;
cached_dst_seed_x = dst_seed_x;
}
}
break;
}
case MUNGE (Indirect, RGBDirect):
{
CTabHandle src_table;
src_table = MR (src->pmTable);
src_seed_x = CTAB_SEED_X (src_table);
dst_rgb_spec = pixmap_rgb_spec (dst);
dst_seed_x = dst_rgb_spec->seed_x;
if ( src_bpp != cached_src_bpp || dst_bpp != cached_dst_bpp
|| src_seed_x != cached_src_seed_x || dst_seed_x != cached_dst_seed_x)
{
conversion_func
= depthconv_make_ind_to_rgb_table (depth_table_space, src_bpp,
NULL, CTAB_TABLE (src_table),
dst_rgb_spec);
}
break;
}
case MUNGE (RGBDirect, Indirect):
{
CTabHandle target_table;
static CTabHandle cached_target_table;
src_rgb_spec = pixmap_rgb_spec (src);
src_seed_x = src_rgb_spec->seed_x;
if (dst_bpp == 1 && BITMAP_P (dst))
target_table = ROMlib_bw_ctab;
else
target_table = PIXMAP_TABLE (GD_PMAP (the_gd));
if (!target_itab)
{
ZONE_SAVE_EXCURSION
(SysZone,
{
target_itab = (ITabHandle) NewHandle (sizeof (ITab));
ITAB_SEED_X (target_itab) = -1;
});
}
#warning ctm added questionable caching here
if (target_table != cached_target_table ||
ITAB_SEED_X (target_itab) != CTAB_SEED_X (target_table))
{
MakeITable (target_table, target_itab, DEFAULT_ITABLE_RESOLUTION);
cached_target_table = target_table;
}
dst_seed_x = CTAB_SEED_X (target_table);
if ( src_bpp != cached_src_bpp || dst_bpp != cached_dst_bpp
|| src_seed_x != cached_src_seed_x || dst_seed_x != cached_dst_seed_x)
{
conversion_func
= depthconv_make_rgb_to_ind_table (depth_table_space, dst_bpp,
NULL,
target_table, target_itab,
src_rgb_spec);
}
break;
}
case MUNGE (RGBDirect, RGBDirect):
{
src_rgb_spec = pixmap_rgb_spec (src);
dst_rgb_spec = pixmap_rgb_spec (dst);
src_seed_x = src_rgb_spec->seed_x;
dst_seed_x = dst_rgb_spec->seed_x;
if ( src_bpp != cached_src_bpp || dst_bpp != cached_dst_bpp
|| src_seed_x != cached_src_seed_x || dst_seed_x != cached_dst_seed_x)
{
conversion_func
= depthconv_make_rgb_to_rgb_table (depth_table_space, NULL,
src_rgb_spec, dst_rgb_spec);
}
break;
}
default:
gui_fatal ("unknown pixel types");
}
/* Make sure we're doing something useful. */
gui_assert ((src_seed_x != dst_seed_x
|| conv_table)
|| src_bpp != dst_bpp);
cached_src_bpp = src_bpp;
cached_dst_bpp = dst_bpp;
copy_p = pixmap_copy_if_screen (src, rect, &write_back);
if (copy_p)
{
src = &write_back.src_pm;
rect = &write_back.src_rect;
}
PIXMAP_ASSERT_NOT_SCREEN (dst);
/* using BITMAP_... on a PixMap * is slimy */
src_row_bytes = BITMAP_ROWBYTES (src);
src_base = (uint8 *) (MR (src->baseAddr)
+ (CW (rect->top) - CW (src->bounds.top)) * src_row_bytes
+ (CW (rect->left) - CW (src->bounds.left)) * src_bpp / 8);
dst_row_bytes = BITMAP_ROWBYTES (dst);
dst_base = (uint8 *) MR (dst->baseAddr);
(*conversion_func) (depth_table_space,
src_base, src_row_bytes, dst_base, dst_row_bytes,
0, 0, height, width);
dst->bounds = *rect;
if (copy_p)
pixmap_free_copy (&write_back.src_pm);
TEMP_ALLOC_FREE (temp_scratch_pm_bits);
}