|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T p
Length: 6495 (0x195f)
Types: TextFile
Names: »pr_helpers.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/Sun/Sdi/pr_helpers.c«
/**************************** pr_helpers.c *************************/
#include <pixrect/pixrect_hs.h>
/*
* Copyright 1987 by Mark Weiser.
* Permission to reproduce and use in any manner whatsoever on Suns is granted
* so long as this copyright and other identifying marks of authorship
* in the code and the game remain intact and visible. Use of this code
* in other products is reserved to me--I'm working on Mac and IBM versions.
*/
/* These routines are pure pixrect operators, used mostly for city operations */
static short pattern[] = {
0x8000, 0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100,
0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1
};
static short *end_of_pattern_ptr = &pattern[16];
#define lefthalf(x) (((x) & 0xff00) >> 8)
#define righthalf(x) ((x) & 0xff)
/*
* Does an incremental melt of old into target, replacing
* old, by dropping pixels down until they hit target
* pixels. Melts 'speed' pixels per call. Old and target should be
* memory pixrects. Probably won't work as written for color.
*
* Pretty dumb and slow, undoubtedly could be done better.
*/
/* alg: drop topmost pixels by speed pixels. Any pixels which were on
in the old which matched on's in the target, still stay on.
Warning: the speed parameter does not work for any value but 1.
*/
melt(old, target, speed)
struct pixrect *old, *target;
int speed;
{
short x_count, y_count, max_x, count, base = 0, bit_count;
int w = old->pr_size.x, h = old->pr_size.y;
struct pixrect *final;
struct mpr_data *mpr_final, *mpr_old;
short num_shorts, speed_inc;
short *old_image, *final_image;
unsigned short *remember_all_bits;
unsigned short *remember_bits, *bit_ptr;
register short *pattern_ptr, *old_image_ptr, *final_image_ptr;
if (w != target->pr_size.x || h != target->pr_size.y) {
/* never leave here */
printf("melt requires equal size pixrects.\n");
abort();
}
mpr_old = mpr_d(old);
if (mpr_old->md_offset.x != 0 || mpr_old->md_offset.y != 0) {
/* Never leave here */
printf("Can't handle region pixrects in 'melt'.\n");
abort();
};
final = mem_create(w, h, 1);
/* see if there is any work to do */
pr_rop(final, 0, 0, w, h, PIX_SRC, old, 0, 0);
pr_rop(final, 0, 0, w, h, PIX_NOT(PIX_SRC) & PIX_DST, target, 0, 0);
if (all_zero_bits(final)) {
pr_destroy(final);
return;
}
/* remember what was ok from before */
pr_rop(final, 0, 0, w, h, PIX_SRC, old, 0, 0);
pr_rop(final, 0, 0, w, h, PIX_SRC & PIX_DST, target, 0, 0);
/* melt some bits */
mpr_final = mpr_d(final);
num_shorts = mpr_final->md_linebytes / 2;
speed_inc = num_shorts*speed;
final_image = mpr_final->md_image;
old_image = mpr_old->md_image;
remember_all_bits = (unsigned short *)calloc(num_shorts+1, 2);
remember_bits = (unsigned short *)calloc(w+1, 2);
/* Melt the top */
for(y_count = 0; y_count < h - speed; y_count += 1) {
if (all_ones(remember_all_bits, num_shorts))
goto next;
bit_ptr = remember_bits;
old_image_ptr = &old_image[base];
final_image_ptr = &final_image[base];
for (x_count = 0; x_count < num_shorts; x_count += 1) {
remember_all_bits[x_count] |= *old_image_ptr;
for(pattern_ptr = pattern; pattern_ptr < end_of_pattern_ptr; pattern_ptr++) {
/* for each bit... */
if (*old_image_ptr & *pattern_ptr) {
/* if you saw one in this 'x' position before... */
if (*bit_ptr) {
/* just copy this one in place. */
*final_image_ptr |= *pattern_ptr;
} else {
/* if this one is the first one here, melt it. */
*bit_ptr = 1;
*(final_image_ptr+speed_inc) |= *pattern_ptr;
}
}
bit_ptr++;
}
old_image_ptr++;
final_image_ptr++;
}
base += num_shorts;
}
/* Move the rest of the image as is */
next:
for(; y_count < h - speed; y_count += 1) {
old_image_ptr = &old_image[base];
final_image_ptr = &final_image[base];
for (x_count = 0; x_count < num_shorts; x_count += 1) {
*final_image_ptr |= *old_image_ptr;
old_image_ptr++;
final_image_ptr++;
}
base += num_shorts;
}
/* return value in old */
pr_rop(old, 0, 0, w, h, PIX_SRC, final, 0, 0);
pr_destroy(final);
free(remember_bits);
free(remember_all_bits);
}
static lookup[] = {
#include "lookup.h"
};
/*
* Count the number of bits in a pixrect.
Not tested on, and may not work for, color.
*/
count_bits(pr)
struct pixrect *pr; /* should be a memory pixrect for dvc ind. */
{
register short x_count, y_count, max_x, count, base = 0, num_shorts;
struct mpr_data *mpr = mpr_d(pr);
if (mpr->md_offset.x != 0 || mpr->md_offset.y != 0) {
/* Never leave here */
printf("Can't handle region pixrects in 'count_bits'.\n");
abort();
};
count = 0;
num_shorts = mpr->md_linebytes / 2;
for(y_count = 0; y_count < pr->pr_size.y; y_count++) {
for (x_count = 0; x_count < num_shorts; x_count += 1) {
count += lookup[lefthalf(mpr->md_image[base+x_count])]
+lookup[righthalf(mpr->md_image[base+x_count])];
}
base += num_shorts;
}
return count;
}
/*
* See if a memory pixrect is all zero.
*/
all_zero_bits(pr)
struct pixrect *pr; /* should be a memory pixrect */
{
register short x_count, y_count, max_x, count, base = 0, num_shorts;
struct mpr_data *mpr = mpr_d(pr);
if (mpr->md_offset.x != 0 || mpr->md_offset.y != 0) {
/* Never leave here */
printf("Can't handle region pixrects in 'count_bits'.\n");
abort();
};
count = 0;
num_shorts = mpr->md_linebytes / 2;
for(y_count = 0; y_count < pr->pr_size.y; y_count++) {
for (x_count = 0; x_count < num_shorts; x_count += 1) {
if (mpr->md_image[base+x_count])
return 0;
}
base += num_shorts;
}
return 1;
}
/*
* See if an array of shorts contains all ones.
*/
all_ones(x, len)
register len;
register unsigned short *x;
{
for(; len; len--) {
if (*x++ != 0xffff) {
return 0;
}
}
return 1;
}
/*
* Grow could, and possibly should, be made to work like melt, and
* grow only at the edge of black areas, but growing linearly up
* from the bottom looks ok too. (Which is not true in revese for melting!).
* Unfortunately they are now asymmetrical, because grow needs a 'position'
* parameter which says how far from the bottom we are.
*
* Grow only works for 64x64 bit pixrects (because of hardwired constants),
* unlike melt which can melt anything.
*/
grow(old, target, position)
struct pixrect *old, *target;
{
if (position < 1 || position > 64)
return;
pr_rop(old, 0, 64 - position, 64, position, PIX_SRC,
target, 0, 64 - position);
}