4.3BSD/usr/contrib/dipress/src/bin/dipress/bitmap.c

Compare this file to the similar file:
Show the results in this format:

/*
 *  bitmap - routines that help build a bitmap of a graphical image
 *
 *  These are primarily used to implement all of the drawing primitives
 *  (except for lines)
 *
 *  History:
 *28-aug-85 John Mellor-Crummey	added flush_bitmap which is used instead
 *				of print_bitmap if current page is not outputted
 *
 *	17-jun-85  ed flint	bitmap width(bm_width) must be multiple of 32
 *				bits for print services 12 (?)
 *
 * Copyright (c) 1984, 1985 Xerox Corp.
 *
 */

# include <stdio.h>
# include "iptokens.h"
# include "literal.h"
# include "operator.h"

# define    local	static
# define    No		0
# define    Yes		1

# define    INCH	2540		/* micas per inch */

extern int drawidth;
extern double drawscale;

char *malloc();

local int minx;
local int miny;
local int maxx;
local int maxy;
local int bm_width;		/* in real bytes */
local int bm_size;
local char *bitmap;
local char *bm_prelude;
local char  bm_active = No;

# define    scale_x(x)		x = (double)x * drawscale
# define    scale_y(y)		y = (double)y * drawscale

/*
 *  new_bitmap(x1, y1, x2, y2) - prepare for a new bitmap, the extreme x and y
 *				 values are x1, y1, x2, and y2.
 */

new_bitmap(stroke, x1, y1, x2, y2)

int stroke, x1, y1, x2, y2;

{
    int new_size;
    register int temp;

#ifdef DEBUG
    fprintf(stderr, "new_bitmap(%d, %d, %d, %d, %d)\n", stroke,x1, y1, x2, y2);
#endif
    drawidth = stroke * drawscale;
    scale_x(x1);
    scale_y(y1);
    scale_x(x2);
    scale_y(y2);
#ifdef DEBUG
    fprintf(stderr, "after scaling: width %d: %d, %d and %d, %d\n", drawidth, x1, y1, x2, y2);
#endif

    /* insure that x1, y1 is the lower left */
    if (x1 > x2)
    {
#ifdef DEBUG
	fprintf(stderr, "exchanging pairs ... ");
#endif
	temp = x1;	/* exchange x1 and x2 */
	x1   = x2;
	x2   = temp;
	temp = y1;	/* exchange y1 and y2 */
	y1   = y2;
	y2   = temp;
#ifdef DEBUG
	fprintf(stderr, "now %d, %d and %d, %d\n", x1, y1, x2, y2);
#endif
    }

    /* adjust the extremes to allow for pen thickness */
    temp = (drawidth + 1) / 2;
    x1 -= temp;
    y1 -= temp;
    x2 += temp;
    y2 += temp;

    if (!bm_active || !(x1 >= minx && y1 >= miny && x2 <= maxx && y2 <= maxy))
    {
	/* we need to set up a new map */
	/* but first, print the old one if it is still active */
#ifdef DEBUG
	fprintf(stderr, "setting up new map, bm_active is %d\n", bm_active);
#endif
	print_bitmap();

	minx = x1;
	miny = y1;
	maxx = x2;
	maxy = y2;

	bm_width = (y2 - y1 + 7) / 8;

	/* print services 12 (?) wants packed pixel vectors to produce each */
	/* scan line as a mutliple of 32 bits, this is backward compatible  */
	/* with previous versions of services				    */
	/* (the previous version of bitmap produced 16 bit multiples which  */
	/* will NOT work with services 12 (?) and beyond)		    */

	if ( bm_width%4 != 0 )
	{
	    bm_width= bm_width + (4 - bm_width%4);
	}
	new_size = (x2 - x1) * bm_width;
	if (new_size > bm_size)
	{
	    /* need to allocate a larger area for the bitmap */
	    if (bitmap != NULL)
	    {
		free(bitmap);
	    }
	    /* leave space for the ppv prelude (leading 4 bytes) */
	    bm_prelude = malloc((unsigned)(new_size + 4));
	    bitmap = bm_prelude + 4;
	    bm_size = new_size;
	}
#ifdef DEBUG
	fprintf(stderr, "bm_width %d, bm_size %d\n", bm_width, bm_size);
#endif
    
	bzero(bitmap, bm_size);
    }
}

set_pixel(x, y)

int x;
int y;

{
    int mask;
    int half_drawidth;
    register int i;
    register int ybit, temp;
    register char *ptr;

    scale_x(x);
    scale_y(y);

    bm_active = Yes;

#ifdef DEBUG
    if (x < minx || x > maxx || y < miny || y > maxy)
    {
	fprintf(stderr, "point off map: (%d, %d)\n", x, y);
	return;
    }
#endif
    x -= minx;
    y  = maxy - y;	/* yes, it works */
    half_drawidth = drawidth >> 1;

    /* Remember the bitmap is built in increasing y */

    /* draw the "x" line vertically */
    mask = 0x80 >> (y & 007);
    ptr = (x - half_drawidth) * bm_width + (y >> 3) + bitmap;
    for (i = 0; i < drawidth; i++, ptr += bm_width)
    {
	*ptr |= mask;
    }

    /* draw the "y" line horizontally */
    y -= half_drawidth;
    ptr = (x * bm_width) + (y >> 3) + bitmap;
    ybit = y & 007;
    temp = ybit + drawidth;
    if (temp < 8)
    {
	/* special case -- less than one byte */
	*ptr |= (0xff >> ybit) ^ (0xff >> temp);
    }
    else
    {
	*ptr |= (0xff >> ybit);
	for (i = drawidth - 8 + ybit; i > 8; i -= 8)
	{
	    *++ptr |= 0xff;
	}
	*++ptr |= ~(0xff >> i);
    }
}

flush_bitmap()
{
	bm_active = No;
}

print_bitmap()

{
    register int bits;
    register char *prelude = bm_prelude;
    int totalbits, size, bm_xdelta, bm_x = minx;

#ifdef DEBUG2
    int x;
    int y;
    int i;
    char *ptr;
#endif

    if (!bm_active)
    {
	/* don't bother */
	return;
    }

#ifdef DEBUG2
    /* debugging version for now */
    ptr = bitmap;
    for (x = minx; x <= maxx; x++)
    {
	for (y = miny; y <= maxy; y += 8, ptr++)
	{
	    for (i = 0x80; i != 0; i >>= 1)
	    {
		if (*ptr & i)
		{
		    putchar('*');
		}
		else
		{
		    putchar(' ');
		}
	    }
	}
	putchar('\n');
    }
#endif

/* The following is conservative (might actually be twice as big) */
#define MAXPPVSAMPS 262144
    bm_xdelta = maxx - minx;
    bits = bm_width << 3;			/* (* 8) */
    totalbits = bits * bm_xdelta;
    if (totalbits > MAXPPVSAMPS) {
	bm_xdelta = MAXPPVSAMPS / bits;
    }
    while (bm_x < maxx) {
	/* Check for last time through loop */
	if (bm_xdelta > (maxx - bm_x)) {
	    bm_xdelta = maxx - bm_x;
	}
	size = (bits * bm_xdelta) >> 3;		/* Could hand optimize! */
	/* inside a dosavesimplebody to preserve transform */
	Op(dosavesimplebody);
	Op(beginBody);
	AppendInteger((long) bm_xdelta);	/* xPixels */
	AppendInteger((long) bits);		/* yPixels */
	AppendInteger(1L);			/* samplesPerPixel */
	AppendInteger(1L);			/* maxSampleValue */
	AppendInteger(1L);			/* samplesInterleaved */
	Translate(0.0, 0.0);			/* (null) transform */

	/* spew out the packed pixel vector */
	prelude[0] = 0;
	prelude[1] = 1;
	prelude[2] = (char)((bits & 0xff00) >> 8);	/* high order byte */
	prelude[3] = (char) (bits & 0x00ff);		/* low  order byte */
	append_Sequence(sequencePackedPixelVector, size + 4,
						(unsigned char *) prelude);

	/* make the pixel array */
	Op(makepixelarray);

	/* set the transform to the right scale and position */
	/* transform must scale back to micas and position bitmap */
	AppendInteger((long) bm_x);
	AppendInteger((long) ((11 * INCH * drawscale) - maxy));
	Op(translate);
	AppendInteger(5L);
	Op(scale);
	Op(concat);
	Op(concatt);

	/* mask it and finish the simple-body */
	Op(maskpixel);
	Op(endBody);
	prelude += size;
	bm_x += bm_xdelta;
    }

    /* no longer active, now is it? */
    bm_active = No;
}