369 lines
8.9 KiB
C
369 lines
8.9 KiB
C
/* Copyright 1995, 1996 by Abacus Research and
|
|
* Development, Inc. All rights reserved.
|
|
*/
|
|
|
|
#if !defined (OMIT_RCSID_STRINGS)
|
|
char ROMlib_rcsid_qPic2[] =
|
|
"$Id: qPict2.c 88 2005-05-25 03:59:37Z ctm $";
|
|
#endif
|
|
|
|
#include "rsys/common.h"
|
|
|
|
#include "QuickDraw.h"
|
|
#include "CQuickDraw.h"
|
|
#include "MemoryMgr.h"
|
|
|
|
#include "rsys/picture.h"
|
|
#include "rsys/cquick.h"
|
|
#include "rsys/rgbutil.h"
|
|
|
|
P1 (PUBLIC pascal trap, OSErr, DisposePictInfo,
|
|
PictInfoID, pict_info_id)
|
|
{
|
|
gui_fatal ("unimplemented");
|
|
}
|
|
|
|
P2 (PUBLIC pascal trap, OSErr, RecordPictInfo,
|
|
PictInfoID, pict_info_id, PicHandle, pic_h)
|
|
{
|
|
gui_fatal ("unimplemented");
|
|
}
|
|
|
|
P2 (PUBLIC pascal trap, OSErr, RecordPixMapInfo,
|
|
PictInfoID, pict_info_id, PixMapHandle, pixmap)
|
|
{
|
|
gui_fatal ("unimplemented");
|
|
}
|
|
|
|
P3 (PUBLIC pascal trap, OSErr, RetrievePictInfo,
|
|
PictInfoID, pict_info_id, PictInfo *, pict_info,
|
|
int16, colors_requested)
|
|
{
|
|
gui_fatal ("unimplemented");
|
|
}
|
|
|
|
P5 (PUBLIC pascal trap, OSErr, NewPictInfo,
|
|
PictInfoID *, pict_info_id, int16, verb,
|
|
int16, colors_requested, int16, color_pick_method,
|
|
int16, version)
|
|
{
|
|
gui_fatal ("unimplemented");
|
|
#if !defined (LETGCCWAIL)
|
|
return paramErr;
|
|
#endif
|
|
}
|
|
|
|
P6 (PUBLIC pascal trap, OSErr, GetPictInfo,
|
|
PicHandle, pic_h, PictInfo *, pict_info,
|
|
int16, verb, int16, color_version, int16, color_pick_method,
|
|
int16, version)
|
|
{
|
|
gui_fatal ("unimplemented");
|
|
#if !defined (LETGCCWAIL)
|
|
return paramErr;
|
|
#endif
|
|
}
|
|
|
|
#define INDIRECT_PIXEL_TO_RGB(pixel, r, g, b, color_table) \
|
|
((void) \
|
|
({ \
|
|
const RGBColor *color; \
|
|
color = &CTAB_TABLE (color_table)[pixel].rgb; \
|
|
(r) = CW (color->red); \
|
|
(g) = CW (color->green); \
|
|
(b) = CW (color->blue); \
|
|
}))
|
|
#define DIRECT_PIXEL_TO_RGB(bpp, pixel, red_out, green_out, blue_out, \
|
|
dummy_color_table) \
|
|
((void) \
|
|
({ \
|
|
RGBColor color; \
|
|
\
|
|
(*rgb_spec->pixel_to_rgbcolor) (rgb_spec, (pixel), &color); \
|
|
(red_out) = CW (color.red); \
|
|
(green_out) = CW (color.green); \
|
|
(blue_out) = CW (color.blue); \
|
|
}))
|
|
#define PIXEL_TO_RGB(bpp, pixel, red, green, blue, color_table) \
|
|
((void) \
|
|
((bpp) == 32 || (bpp) == 16 \
|
|
? DIRECT_PIXEL_TO_RGB (bpp, pixel, red, green, blue, color_table) \
|
|
: INDIRECT_PIXEL_TO_RGB (pixel, red, green, blue, color_table)))
|
|
#define SHIFT_COUNT(x, bpp) (8 - (bpp) - (bpp) * ((x) & (7 / (bpp))))
|
|
#define READ_INDIRECT_PIXEL(b, x, bpp) \
|
|
((bpp) == 8 \
|
|
? b[x] \
|
|
: ((b[(x) * (bpp) / 8] >> SHIFT_COUNT ((x), (bpp))) & ((1 << (bpp)) - 1)))
|
|
#define READ_DIRECT16_PIXEL(b, x, bpp) \
|
|
((uint16 *) b)[x]
|
|
#define READ_DIRECT32_PIXEL(b, x, bpp) \
|
|
((uint32 *) b)[x]
|
|
#define RECORD_COLORS(read, record, bpp) \
|
|
({ \
|
|
int x, y; \
|
|
\
|
|
for (y = 0; y < height; y ++) \
|
|
{ \
|
|
for (x = 0; x < width; x ++) \
|
|
{ \
|
|
uint32 r, g, b; \
|
|
uint32 pixel; \
|
|
\
|
|
pixel = read (row_base, x, bpp); \
|
|
\
|
|
PIXEL_TO_RGB (bpp, pixel, r, g, b, pixmap_color_table); \
|
|
\
|
|
record (r, g, b); \
|
|
} \
|
|
row_base += row_bytes; \
|
|
} \
|
|
})
|
|
|
|
#define systemMethod 0
|
|
#define popularMethod 1
|
|
#define medianMethod 2
|
|
|
|
#define returnColorTable 1
|
|
#define returnPalette 2
|
|
#define suppressBlackAndWhite 16
|
|
|
|
struct link
|
|
{
|
|
int bank_index;
|
|
int count;
|
|
struct link *next, *prev;
|
|
};
|
|
|
|
P6 (PUBLIC pascal trap, OSErr, GetPixMapInfo,
|
|
PixMapHandle, pixmap, PictInfo *, pict_info,
|
|
int16, verb, int16, colors_requested, int16, color_pick_method,
|
|
int16, version)
|
|
{
|
|
CTabHandle pixmap_color_table;
|
|
uint8 *row_base;
|
|
int row_bytes, bpp;
|
|
const rgb_spec_t *rgb_spec;
|
|
uint16 *bank;
|
|
int32 unique_colors;
|
|
int height, width;
|
|
struct link *head, *tail;
|
|
OSErr retval;
|
|
|
|
retval = noErr;
|
|
head = tail = NULL;
|
|
|
|
/* suck out the relevent pixmap bits */
|
|
row_bytes = PIXMAP_ROWBYTES (pixmap);
|
|
row_base = (uint8 *) PIXMAP_BASEADDR (pixmap);
|
|
|
|
bpp = PIXMAP_PIXEL_SIZE (pixmap);
|
|
|
|
pixmap_color_table = PIXMAP_TABLE (pixmap);
|
|
|
|
rgb_spec = pixmap_rgb_spec (STARH (pixmap));
|
|
|
|
width = RECT_WIDTH (&PIXMAP_BOUNDS (pixmap));
|
|
height = RECT_HEIGHT (&PIXMAP_BOUNDS (pixmap));
|
|
|
|
if (color_pick_method != systemMethod
|
|
/* currently system method defaults to popular method */
|
|
&& color_pick_method != popularMethod)
|
|
{
|
|
warning_unimplemented ("unknown pick method `%d', using popularMethod",
|
|
color_pick_method);
|
|
|
|
}
|
|
color_pick_method = popularMethod;
|
|
|
|
bank = (uint16 *) NewPtr (32768 * sizeof *bank);
|
|
if (MemError () != noErr)
|
|
return MemError ();
|
|
memset (bank, '\000', 32768 * sizeof *bank);
|
|
|
|
unique_colors = 0;
|
|
|
|
#define RECORD_555(red, green, blue) \
|
|
({ \
|
|
int bank_index; \
|
|
const uint16 mask = 0xF100; \
|
|
uint16 count; \
|
|
\
|
|
bank_index \
|
|
= ((red & mask) >> 1) | ((green & mask) >> 6) | ((blue & mask) >> 11); \
|
|
\
|
|
count = CW (bank[bank_index]); \
|
|
if (! count) \
|
|
unique_colors ++; \
|
|
bank[bank_index] = CW (count + 1); \
|
|
})
|
|
|
|
switch (bpp)
|
|
{
|
|
case 1:
|
|
RECORD_COLORS (READ_INDIRECT_PIXEL, RECORD_555, 1);
|
|
break;
|
|
case 2:
|
|
RECORD_COLORS (READ_INDIRECT_PIXEL, RECORD_555, 2);
|
|
break;
|
|
case 4:
|
|
RECORD_COLORS (READ_INDIRECT_PIXEL, RECORD_555, 4);
|
|
break;
|
|
case 8:
|
|
RECORD_COLORS (READ_INDIRECT_PIXEL, RECORD_555, 8);
|
|
break;
|
|
case 16:
|
|
RECORD_COLORS (READ_DIRECT16_PIXEL, RECORD_555, 16);
|
|
break;
|
|
case 32:
|
|
RECORD_COLORS (READ_DIRECT32_PIXEL, RECORD_555, 32);
|
|
break;
|
|
}
|
|
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < colors_requested; i ++)
|
|
{
|
|
struct link *t;
|
|
|
|
t = (struct link *) NewPtr (sizeof *t);
|
|
if (MemError () != noErr)
|
|
{
|
|
retval = MemError ();
|
|
goto cleanup_and_return;
|
|
}
|
|
memset (t, '\000', sizeof *t);
|
|
|
|
if (head)
|
|
head->prev = t;
|
|
t->next = head;
|
|
head = t;
|
|
|
|
if (tail == NULL)
|
|
tail = t;
|
|
}
|
|
|
|
for (i = 0; i < 32768; i ++)
|
|
{
|
|
if ((verb & suppressBlackAndWhite)
|
|
&& (!i
|
|
|| i == 32767))
|
|
continue;
|
|
|
|
if (tail->count < bank[i])
|
|
{
|
|
struct link *t;
|
|
|
|
t = tail;
|
|
|
|
t->bank_index = i;
|
|
t->count = bank[i];
|
|
|
|
if (t->count > t->prev->count)
|
|
{
|
|
tail = t->prev;
|
|
tail->next = NULL;
|
|
t->next = t->prev = NULL;
|
|
|
|
if (t->count > head->count)
|
|
{
|
|
head->prev = t;
|
|
t->next = head;
|
|
head = t;
|
|
}
|
|
else
|
|
{
|
|
struct link *current;
|
|
|
|
/* insert sorted */
|
|
for (current = head; current; current = current->next)
|
|
{
|
|
if (t->count <= current->count
|
|
&& current->next
|
|
&& current->next->count < t->count)
|
|
{
|
|
/* insert */
|
|
t->next = current->next;
|
|
t->prev = current;
|
|
|
|
t->next->prev = t;
|
|
t->prev->next = t;
|
|
break;
|
|
}
|
|
}
|
|
if (current == NULL)
|
|
gui_abort ();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
CTabHandle color_table;
|
|
ColorSpec *table;
|
|
|
|
color_table
|
|
= (CTabHandle) NewHandle (CTAB_STORAGE_FOR_SIZE (colors_requested));
|
|
|
|
CTAB_SEED_X (color_table) = CL (GetCTSeed ());
|
|
CTAB_FLAGS_X (color_table) = CW (0);
|
|
CTAB_SIZE_X (color_table) = CW (colors_requested);
|
|
|
|
table = CTAB_TABLE (color_table);
|
|
|
|
{
|
|
struct link *t;
|
|
|
|
for (i = 0, t = head; i < colors_requested && t; i ++, t = t->next)
|
|
{
|
|
table[i].value = CW (i);
|
|
|
|
#define TILE(x) (((uint32) (x) * 0x8421UL) >> 4)
|
|
|
|
table[i].rgb.red = TILE (t->bank_index >> 10);
|
|
table[i].rgb.green = TILE (t->bank_index >> 5);
|
|
table[i].rgb.blue = TILE (t->bank_index >> 0);
|
|
}
|
|
gui_assert (t == NULL && i == colors_requested);
|
|
}
|
|
|
|
/* `head' now points to a list, in sorted order, of the most
|
|
popular colors in the pixmap */
|
|
memset (pict_info, '\000', sizeof *pict_info);
|
|
|
|
pict_info->uniqueColors = CL (unique_colors);
|
|
|
|
if (verb & returnPalette)
|
|
{
|
|
PaletteHandle palette;
|
|
|
|
palette = NewPalette (colors_requested, color_table,
|
|
/* #### verify correct default values */
|
|
pmTolerant, 0);
|
|
pict_info->thePalette = RM (palette);
|
|
}
|
|
|
|
if (verb & returnColorTable)
|
|
pict_info->theColorTable = RM (color_table);
|
|
else
|
|
DisposHandle ((Handle) color_table);
|
|
}
|
|
|
|
cleanup_and_return:
|
|
{
|
|
struct link *t, *next;
|
|
|
|
DisposPtr ((Ptr) bank);
|
|
|
|
for (t = head, next = t->next;
|
|
t;
|
|
t = next, next = t ? t->next : NULL)
|
|
{
|
|
if (t)
|
|
DisposPtr ((Ptr) t);
|
|
}
|
|
return retval;
|
|
}
|
|
}
|
|
}
|