mirror of
https://github.com/ctm/executor.git
synced 2024-06-16 04:29:29 +00:00
606 lines
15 KiB
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);
|
|
}
|