1: /* 2: * bitmap - routines that help build a bitmap of a graphical image 3: * 4: * These are primarily used to implement all of the drawing primitives 5: * (except for lines) 6: * 7: * History: 8: *28-aug-85 John Mellor-Crummey added flush_bitmap which is used instead 9: * of print_bitmap if current page is not outputted 10: * 11: * 17-jun-85 ed flint bitmap width(bm_width) must be multiple of 32 12: * bits for print services 12 (?) 13: * 14: * Copyright (c) 1984, 1985 Xerox Corp. 15: * 16: */ 17: 18: # include <stdio.h> 19: # include "iptokens.h" 20: # include "literal.h" 21: # include "operator.h" 22: 23: # define local static 24: # define No 0 25: # define Yes 1 26: 27: # define INCH 2540 /* micas per inch */ 28: 29: extern int drawidth; 30: extern double drawscale; 31: 32: char *malloc(); 33: 34: local int minx; 35: local int miny; 36: local int maxx; 37: local int maxy; 38: local int bm_width; /* in real bytes */ 39: local int bm_size; 40: local char *bitmap; 41: local char *bm_prelude; 42: local char bm_active = No; 43: 44: # define scale_x(x) x = (double)x * drawscale 45: # define scale_y(y) y = (double)y * drawscale 46: 47: /* 48: * new_bitmap(x1, y1, x2, y2) - prepare for a new bitmap, the extreme x and y 49: * values are x1, y1, x2, and y2. 50: */ 51: 52: new_bitmap(stroke, x1, y1, x2, y2) 53: 54: int stroke, x1, y1, x2, y2; 55: 56: { 57: int new_size; 58: register int temp; 59: 60: #ifdef DEBUG 61: fprintf(stderr, "new_bitmap(%d, %d, %d, %d, %d)\n", stroke,x1, y1, x2, y2); 62: #endif 63: drawidth = stroke * drawscale; 64: scale_x(x1); 65: scale_y(y1); 66: scale_x(x2); 67: scale_y(y2); 68: #ifdef DEBUG 69: fprintf(stderr, "after scaling: width %d: %d, %d and %d, %d\n", drawidth, x1, y1, x2, y2); 70: #endif 71: 72: /* insure that x1, y1 is the lower left */ 73: if (x1 > x2) 74: { 75: #ifdef DEBUG 76: fprintf(stderr, "exchanging pairs ... "); 77: #endif 78: temp = x1; /* exchange x1 and x2 */ 79: x1 = x2; 80: x2 = temp; 81: temp = y1; /* exchange y1 and y2 */ 82: y1 = y2; 83: y2 = temp; 84: #ifdef DEBUG 85: fprintf(stderr, "now %d, %d and %d, %d\n", x1, y1, x2, y2); 86: #endif 87: } 88: 89: /* adjust the extremes to allow for pen thickness */ 90: temp = (drawidth + 1) / 2; 91: x1 -= temp; 92: y1 -= temp; 93: x2 += temp; 94: y2 += temp; 95: 96: if (!bm_active || !(x1 >= minx && y1 >= miny && x2 <= maxx && y2 <= maxy)) 97: { 98: /* we need to set up a new map */ 99: /* but first, print the old one if it is still active */ 100: #ifdef DEBUG 101: fprintf(stderr, "setting up new map, bm_active is %d\n", bm_active); 102: #endif 103: print_bitmap(); 104: 105: minx = x1; 106: miny = y1; 107: maxx = x2; 108: maxy = y2; 109: 110: bm_width = (y2 - y1 + 7) / 8; 111: 112: /* print services 12 (?) wants packed pixel vectors to produce each */ 113: /* scan line as a mutliple of 32 bits, this is backward compatible */ 114: /* with previous versions of services */ 115: /* (the previous version of bitmap produced 16 bit multiples which */ 116: /* will NOT work with services 12 (?) and beyond) */ 117: 118: if ( bm_width%4 != 0 ) 119: { 120: bm_width= bm_width + (4 - bm_width%4); 121: } 122: new_size = (x2 - x1) * bm_width; 123: if (new_size > bm_size) 124: { 125: /* need to allocate a larger area for the bitmap */ 126: if (bitmap != NULL) 127: { 128: free(bitmap); 129: } 130: /* leave space for the ppv prelude (leading 4 bytes) */ 131: bm_prelude = malloc((unsigned)(new_size + 4)); 132: bitmap = bm_prelude + 4; 133: bm_size = new_size; 134: } 135: #ifdef DEBUG 136: fprintf(stderr, "bm_width %d, bm_size %d\n", bm_width, bm_size); 137: #endif 138: 139: bzero(bitmap, bm_size); 140: } 141: } 142: 143: set_pixel(x, y) 144: 145: int x; 146: int y; 147: 148: { 149: int mask; 150: int half_drawidth; 151: register int i; 152: register int ybit, temp; 153: register char *ptr; 154: 155: scale_x(x); 156: scale_y(y); 157: 158: bm_active = Yes; 159: 160: #ifdef DEBUG 161: if (x < minx || x > maxx || y < miny || y > maxy) 162: { 163: fprintf(stderr, "point off map: (%d, %d)\n", x, y); 164: return; 165: } 166: #endif 167: x -= minx; 168: y = maxy - y; /* yes, it works */ 169: half_drawidth = drawidth >> 1; 170: 171: /* Remember the bitmap is built in increasing y */ 172: 173: /* draw the "x" line vertically */ 174: mask = 0x80 >> (y & 007); 175: ptr = (x - half_drawidth) * bm_width + (y >> 3) + bitmap; 176: for (i = 0; i < drawidth; i++, ptr += bm_width) 177: { 178: *ptr |= mask; 179: } 180: 181: /* draw the "y" line horizontally */ 182: y -= half_drawidth; 183: ptr = (x * bm_width) + (y >> 3) + bitmap; 184: ybit = y & 007; 185: temp = ybit + drawidth; 186: if (temp < 8) 187: { 188: /* special case -- less than one byte */ 189: *ptr |= (0xff >> ybit) ^ (0xff >> temp); 190: } 191: else 192: { 193: *ptr |= (0xff >> ybit); 194: for (i = drawidth - 8 + ybit; i > 8; i -= 8) 195: { 196: *++ptr |= 0xff; 197: } 198: *++ptr |= ~(0xff >> i); 199: } 200: } 201: 202: flush_bitmap() 203: { 204: bm_active = No; 205: } 206: 207: print_bitmap() 208: 209: { 210: register int bits; 211: register char *prelude = bm_prelude; 212: int totalbits, size, bm_xdelta, bm_x = minx; 213: 214: #ifdef DEBUG2 215: int x; 216: int y; 217: int i; 218: char *ptr; 219: #endif 220: 221: if (!bm_active) 222: { 223: /* don't bother */ 224: return; 225: } 226: 227: #ifdef DEBUG2 228: /* debugging version for now */ 229: ptr = bitmap; 230: for (x = minx; x <= maxx; x++) 231: { 232: for (y = miny; y <= maxy; y += 8, ptr++) 233: { 234: for (i = 0x80; i != 0; i >>= 1) 235: { 236: if (*ptr & i) 237: { 238: putchar('*'); 239: } 240: else 241: { 242: putchar(' '); 243: } 244: } 245: } 246: putchar('\n'); 247: } 248: #endif 249: 250: /* The following is conservative (might actually be twice as big) */ 251: #define MAXPPVSAMPS 262144 252: bm_xdelta = maxx - minx; 253: bits = bm_width << 3; /* (* 8) */ 254: totalbits = bits * bm_xdelta; 255: if (totalbits > MAXPPVSAMPS) { 256: bm_xdelta = MAXPPVSAMPS / bits; 257: } 258: while (bm_x < maxx) { 259: /* Check for last time through loop */ 260: if (bm_xdelta > (maxx - bm_x)) { 261: bm_xdelta = maxx - bm_x; 262: } 263: size = (bits * bm_xdelta) >> 3; /* Could hand optimize! */ 264: /* inside a dosavesimplebody to preserve transform */ 265: Op(dosavesimplebody); 266: Op(beginBody); 267: AppendInteger((long) bm_xdelta); /* xPixels */ 268: AppendInteger((long) bits); /* yPixels */ 269: AppendInteger(1L); /* samplesPerPixel */ 270: AppendInteger(1L); /* maxSampleValue */ 271: AppendInteger(1L); /* samplesInterleaved */ 272: Translate(0.0, 0.0); /* (null) transform */ 273: 274: /* spew out the packed pixel vector */ 275: prelude[0] = 0; 276: prelude[1] = 1; 277: prelude[2] = (char)((bits & 0xff00) >> 8); /* high order byte */ 278: prelude[3] = (char) (bits & 0x00ff); /* low order byte */ 279: append_Sequence(sequencePackedPixelVector, size + 4, 280: (unsigned char *) prelude); 281: 282: /* make the pixel array */ 283: Op(makepixelarray); 284: 285: /* set the transform to the right scale and position */ 286: /* transform must scale back to micas and position bitmap */ 287: AppendInteger((long) bm_x); 288: AppendInteger((long) ((11 * INCH * drawscale) - maxy)); 289: Op(translate); 290: AppendInteger(5L); 291: Op(scale); 292: Op(concat); 293: Op(concatt); 294: 295: /* mask it and finish the simple-body */ 296: Op(maskpixel); 297: Op(endBody); 298: prelude += size; 299: bm_x += bm_xdelta; 300: } 301: 302: /* no longer active, now is it? */ 303: bm_active = No; 304: }