DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T p

⟦a45aadd27⟧ TextFile

    Length: 6495 (0x195f)
    Types: TextFile
    Names: »pr_helpers.c«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/Sun/Sdi/pr_helpers.c« 

TextFile

/****************************  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); 
}