|
|
1.1 ! root 1: #ifndef lint ! 2: static char *rcsid_spixline_c = "$Header: spixline.c,v 10.1 86/11/19 10:44:12 jg Exp $"; ! 3: #endif lint ! 4: /* spixline.c - single pixel wide line drawing routine ! 5: * ! 6: * SinglePixelLine draws solid, dashed and patterned lines ! 7: * that are only one pixel wide ! 8: * ! 9: * Author: ! 10: * Scott Bates ! 11: * Brown University ! 12: * IRIS, Box 1946 ! 13: * Providence, RI 02912 ! 14: * ! 15: * ! 16: * Copyright (c) 1986 Brown University ! 17: * ! 18: * Permission to use, copy, modify and distribute this software and its ! 19: * documentation for any purpose and without fee is hereby granted, provided ! 20: * that the above copyright notice appear in all copies, and that both ! 21: * that copyright notice and this permission notice appear in supporting ! 22: * documentation, and that the name of Brown University not be used in ! 23: * advertising or publicity pertaining to distribution of the software ! 24: * without specific, written prior permission. Brown University makes no ! 25: * representations about the suitability of this software for any purpose. ! 26: * It is provided "as-is" without express or implied warranty. ! 27: */ ! 28: ! 29: #include "private.h" ! 30: #include "bitblt.h" ! 31: #include "spixline.h" ! 32: ! 33: /* ! 34: * Draw single pixel wide line ! 35: */ ! 36: ! 37: SinglePixelLine (BitMap, StartX, StartY, StopX, StopY, Clip, Rule, Mode, ! 38: SrcPix, AltPix, Pattern, PatternLength, PatternMultiplier) ! 39: BITMAP *BitMap; ! 40: int StartX, StartY; ! 41: int StopX, StopY; ! 42: CLIP *Clip; ! 43: int Rule, Mode; ! 44: int SrcPix, AltPix; ! 45: u_short Pattern; ! 46: int PatternLength; ! 47: int PatternMultiplier; ! 48: { ! 49: register u_short MaskBit, *Destination, Source; ! 50: register BitsLeftToDraw, Sentinel, NumberOfBytes; ! 51: int DeltaX, DeltaY, Temp, RepeatCount; ! 52: u_short AltSource, PatternFirstBit, PatternBit; ! 53: int NumberOfShorts; ! 54: #if (defined(AED) || defined(APA8) || defined(APA8C)) ! 55: struct Blt_Rectangle Rect; ! 56: #endif (AED || APA8 || APA8C) ! 57: #if (defined(APA8) || defined(APA8C)) ! 58: long DestinationIncrement; ! 59: #endif (APA8 || APA8C) ! 60: #ifdef AED ! 61: int EchoLine = 1; ! 62: ! 63: /* ! 64: * If the destination is the screen and were not drawing a patterned ! 65: * line use the AED microcode to draw it. If the microcode is used ! 66: * then the blt does not have to be echoed to the AED to make visible. ! 67: * ! 68: * NOTE: If we are drawing a dashed line and the multiplier ! 69: * is equal to one then use the AED microcode. Otherwise, ! 70: * do it in software and then echo it to the AED. ! 71: */ ! 72: ! 73: if(BitMap == SCREEN_BITMAP && Mode != DrawPatternedLine) { ! 74: ! 75: if (Mode == DrawSolidLine) { ! 76: ClipToRect(Clip, &Rect); ! 77: aed_draw_line(StartX, StartY, StopX, StopY, Rule, 1, ! 78: (SrcPix & 1), (u_short)0, 0, &Rect); ! 79: EchoLine = 0; ! 80: } else if (PatternMultiplier < 2) { ! 81: ClipToRect(Clip, &Rect); ! 82: aed_draw_line(StartX, StartY, StopX, StopY, Rule, 1, ! 83: (SrcPix & 1), Pattern, PatternLength, &Rect); ! 84: EchoLine = 0; ! 85: } ! 86: } ! 87: #endif AED ! 88: ! 89: #ifdef TRACE_X ! 90: fprintf(stderr, "In SinglePixelLine\n"); ! 91: fflush(stderr); ! 92: #endif TRACE_X ! 93: ! 94: /* ! 95: * Clip line. If nothing to draw after clip ! 96: * return to caller. ! 97: */ ! 98: ! 99: ClipLine(StartX, StartY, StopX, StopY, Clip); ! 100: ! 101: /* ! 102: * Always draw left to right ! 103: */ ! 104: ! 105: if (StopX < StartX) { ! 106: Temp = StopX, StopX = StartX, StartX = Temp; ! 107: Temp = StopY, StopY = StartY, StartY = Temp; ! 108: } ! 109: ! 110: /* ! 111: * Compute delta values and bitmap width in shorts ! 112: */ ! 113: ! 114: DeltaX = StopX - StartX; ! 115: DeltaY = StopY - StartY; ! 116: ! 117: NumberOfShorts = (BitMap->width + 15) / 16; ! 118: ! 119: #if (defined(APA8) || defined(APA8C)) ! 120: if (DeltaY > 0) { /* drawing top to bottom */ ! 121: if (BitMap == SCREEN_BITMAP) ! 122: NumberOfBytes = NumberOfShorts << 2; ! 123: else ! 124: NumberOfBytes = NumberOfShorts << 1; ! 125: } else { /* drawing bottom to top */ ! 126: if (BitMap == SCREEN_BITMAP) ! 127: NumberOfBytes = -(NumberOfShorts << 2); ! 128: else ! 129: NumberOfBytes = -(NumberOfShorts << 1); ! 130: DeltaY = -DeltaY; ! 131: } ! 132: #else ! 133: if (DeltaY > 0) { /* drawing top to bottom */ ! 134: NumberOfBytes = NumberOfShorts << 1; ! 135: } else { /* drawing bottom to top */ ! 136: NumberOfBytes = -(NumberOfShorts << 1); ! 137: DeltaY = -DeltaY; ! 138: } ! 139: #endif (APA8 || APA8C) ! 140: ! 141: /* ! 142: * Get source and alternate tiles ! 143: */ ! 144: ! 145: Source = *ConstantTiles[SrcPix & 1]; ! 146: if(Mode == DrawPatternedLine) ! 147: AltSource = *ConstantTiles[AltPix & 1]; ! 148: ! 149: /* ! 150: * Compute starting destination address ! 151: */ ! 152: ! 153: #if (defined(APA8) || defined (APA8C)) ! 154: if (BitMap == SCREEN_BITMAP) { ! 155: Destination = (u_short *) BitMap->data + ! 156: ((StartX / 16 + StartY * NumberOfShorts) << 1); ! 157: DestinationIncrement = 4; ! 158: } else { ! 159: Destination = (u_short *) BitMap->data + ! 160: StartX / 16 + StartY * NumberOfShorts; ! 161: DestinationIncrement = 2; ! 162: } ! 163: #else ! 164: Destination = (u_short *) BitMap->data + ! 165: StartX / 16 + StartY * NumberOfShorts; ! 166: #endif (APA8 || APA8C) ! 167: ! 168: /* ! 169: * set mask to select starting bit ! 170: */ ! 171: ! 172: MaskBit = 0x8000 >> (StartX & 0x0F); ! 173: ! 174: /* ! 175: * If this is not a solid line setup pattern values ! 176: */ ! 177: ! 178: if (Mode != DrawSolidLine) { ! 179: RepeatCount = PatternMultiplier; ! 180: PatternFirstBit = 1 << (PatternLength - 1); ! 181: PatternBit = PatternFirstBit; ! 182: } ! 183: ! 184: #ifdef SOFTWARE_CURSOR ! 185: /* ! 186: * Save cursor if blt is to screen ! 187: */ ! 188: ! 189: if (BitMap == SCREEN_BITMAP) { ! 190: if (save_cursor(MIN(StopX, StartX), MIN(StopY, StartY), ! 191: MAX(StopX, StartX) + 1, MAX(StopY, StartY) + 1) < 0) ! 192: { ! 193: DeviceError( ! 194: "SinglePixelLine: ioctl QIOCHIDECUR failed.\n" ! 195: ); ! 196: } ! 197: } ! 198: #endif SOFTWARE_CURSOR ! 199: ! 200: /* ! 201: * draw the line ! 202: */ ! 203: ! 204: if (DeltaX > DeltaY) { /* This is a horizontal line */ ! 205: Sentinel = DeltaX >> 1; ! 206: BitsLeftToDraw = DeltaX; ! 207: ! 208: switch (Rule) { ! 209: case (GXor): ! 210: HORIZONTAL_LINE ( ! 211: {*Destination |= (Source & MaskBit);}, ! 212: {*Destination |= (AltSource & MaskBit);} ! 213: ); ! 214: break; ! 215: case (GXcopy): ! 216: HORIZONTAL_LINE ( ! 217: {*Destination = (*Destination & ~MaskBit) | ! 218: (Source & MaskBit);}, ! 219: {*Destination = (*Destination & ~MaskBit) | ! 220: (AltSource & MaskBit);} ! 221: ); ! 222: break; ! 223: case (GXxor): ! 224: HORIZONTAL_LINE ( ! 225: {*Destination ^= (Source & MaskBit);}, ! 226: {*Destination ^= (AltSource & MaskBit);} ! 227: ); ! 228: break; ! 229: case (GXset): ! 230: HORIZONTAL_LINE ( ! 231: {*Destination |= MaskBit;}, ! 232: {*Destination |= MaskBit;} ! 233: ); ! 234: break; ! 235: case (GXclear): ! 236: HORIZONTAL_LINE ( ! 237: {*Destination &= ~MaskBit;}, ! 238: {*Destination &= ~MaskBit;} ! 239: ); ! 240: break; ! 241: case (GXinvert): ! 242: HORIZONTAL_LINE ( ! 243: {*Destination ^= MaskBit;}, ! 244: {*Destination ^= MaskBit;} ! 245: ); ! 246: break; ! 247: case (GXcopyInverted): ! 248: HORIZONTAL_LINE ( ! 249: {*Destination = (*Destination & ~MaskBit) | ! 250: (~Source & MaskBit);}, ! 251: {*Destination = (*Destination & ~MaskBit) | ! 252: (~AltSource & MaskBit);} ! 253: ); ! 254: break; ! 255: case (GXandInverted): ! 256: HORIZONTAL_LINE ( ! 257: {*Destination &= ~(Source & MaskBit);}, ! 258: {*Destination &= ~(AltSource & MaskBit);} ! 259: ); ! 260: break; ! 261: case (GXorReverse): ! 262: HORIZONTAL_LINE ( ! 263: {*Destination = (*Destination & ~MaskBit) | ! 264: ((~*Destination | Source) & MaskBit);}, ! 265: {*Destination = (*Destination & ~MaskBit) | ! 266: ((~*Destination | AltSource) & MaskBit);} ! 267: ); ! 268: break; ! 269: case (GXequiv): ! 270: HORIZONTAL_LINE ( ! 271: {*Destination = (*Destination & ~MaskBit) | ! 272: ((*Destination ^ ~Source) & MaskBit);}, ! 273: {*Destination = (*Destination & ~MaskBit) | ! 274: ((*Destination ^ ~AltSource) & MaskBit);} ! 275: ); ! 276: break; ! 277: case (GXnand): ! 278: HORIZONTAL_LINE ( ! 279: {*Destination = (*Destination & ~MaskBit) | ! 280: ((~*Destination | ~Source) & MaskBit);}, ! 281: {*Destination = (*Destination & ~MaskBit) | ! 282: ((~*Destination | ~AltSource) & MaskBit);} ! 283: ); ! 284: break; ! 285: case (GXnor): ! 286: HORIZONTAL_LINE ( ! 287: {*Destination = (*Destination & ~MaskBit) | ! 288: ((~*Destination & ~Source) & MaskBit);}, ! 289: {*Destination = (*Destination & ~MaskBit) | ! 290: ((~*Destination & ~AltSource) & MaskBit);} ! 291: ); ! 292: break; ! 293: case (GXandReverse): ! 294: HORIZONTAL_LINE ( ! 295: {*Destination = (*Destination & ~MaskBit) | ! 296: ((~*Destination & Source) & MaskBit);}, ! 297: {*Destination = (*Destination & ~MaskBit) | ! 298: ((~*Destination & AltSource) & MaskBit);} ! 299: ); ! 300: break; ! 301: case (GXand): ! 302: HORIZONTAL_LINE ( ! 303: {*Destination = (*Destination & ~MaskBit) | ! 304: ((*Destination & Source) & MaskBit);}, ! 305: {*Destination = (*Destination & ~MaskBit) | ! 306: ((*Destination & AltSource) & MaskBit);} ! 307: ); ! 308: break; ! 309: case (GXorInverted): ! 310: HORIZONTAL_LINE ( ! 311: {*Destination = (*Destination & ~MaskBit) | ! 312: ((*Destination | ~Source) & MaskBit);}, ! 313: {*Destination = (*Destination & ~MaskBit) | ! 314: ((*Destination | ~AltSource) & MaskBit);} ! 315: ); ! 316: } ! 317: } else { /* This is a vertical line */ ! 318: Sentinel = DeltaY >> 1; ! 319: BitsLeftToDraw = DeltaY; ! 320: ! 321: switch (Rule) { ! 322: case (GXor): ! 323: VERTICAL_LINE ( ! 324: {*Destination |= (Source & MaskBit);}, ! 325: {*Destination |= (AltSource & MaskBit);} ! 326: ); ! 327: break; ! 328: case (GXcopy): ! 329: VERTICAL_LINE ( ! 330: {*Destination = (*Destination & ~MaskBit) | ! 331: (Source & MaskBit);}, ! 332: {*Destination = (*Destination & ~MaskBit) | ! 333: (AltSource & MaskBit);} ! 334: ); ! 335: break; ! 336: case (GXxor): ! 337: VERTICAL_LINE ( ! 338: {*Destination ^= (Source & MaskBit);}, ! 339: {*Destination ^= (AltSource & MaskBit);} ! 340: ); ! 341: break; ! 342: case (GXset): ! 343: VERTICAL_LINE ( ! 344: {*Destination |= MaskBit;}, ! 345: {*Destination |= MaskBit;} ! 346: ); ! 347: break; ! 348: case (GXclear): ! 349: VERTICAL_LINE( ! 350: {*Destination &= ~MaskBit;}, ! 351: {*Destination &= ~MaskBit;} ! 352: ); ! 353: break; ! 354: case (GXinvert): ! 355: VERTICAL_LINE ( ! 356: {*Destination ^= MaskBit;}, ! 357: {*Destination ^= MaskBit;} ! 358: ); ! 359: break; ! 360: case (GXcopyInverted): ! 361: VERTICAL_LINE ( ! 362: {*Destination = (*Destination & ~MaskBit) | ! 363: (~Source & MaskBit);}, ! 364: {*Destination = (*Destination & ~MaskBit) | ! 365: (~AltSource & MaskBit);} ! 366: ); ! 367: break; ! 368: case (GXandInverted): ! 369: VERTICAL_LINE ( ! 370: {*Destination &= ~(Source & MaskBit);}, ! 371: {*Destination &= ~(AltSource & MaskBit);} ! 372: ); ! 373: break; ! 374: case (GXorReverse): ! 375: VERTICAL_LINE ( ! 376: {*Destination = (*Destination & ~MaskBit) | ! 377: ((~*Destination | Source) & MaskBit);}, ! 378: {*Destination = (*Destination & ~MaskBit) | ! 379: ((~*Destination | AltSource) & MaskBit);} ! 380: ); ! 381: break; ! 382: case (GXequiv): ! 383: VERTICAL_LINE ( ! 384: {*Destination = (*Destination & ~MaskBit) | ! 385: ((*Destination ^ ~Source) & MaskBit);}, ! 386: {*Destination = (*Destination & ~MaskBit) | ! 387: ((*Destination ^ ~AltSource) & MaskBit);} ! 388: ); ! 389: break; ! 390: case (GXnand): ! 391: VERTICAL_LINE ( ! 392: {*Destination = (*Destination & ~MaskBit) | ! 393: ((~*Destination | ~Source) & MaskBit);}, ! 394: {*Destination = (*Destination & ~MaskBit) | ! 395: ((~*Destination | ~AltSource) & MaskBit);} ! 396: ); ! 397: break; ! 398: case (GXnor): ! 399: VERTICAL_LINE ( ! 400: {*Destination = (*Destination & ~MaskBit) | ! 401: ((~*Destination & ~Source) & MaskBit);}, ! 402: {*Destination = (*Destination & ~MaskBit) | ! 403: ((~*Destination & ~AltSource) & MaskBit);} ! 404: ); ! 405: break; ! 406: case (GXandReverse): ! 407: VERTICAL_LINE ( ! 408: {*Destination = (*Destination & ~MaskBit) | ! 409: ((~*Destination & Source) & MaskBit);}, ! 410: {*Destination = (*Destination & ~MaskBit) | ! 411: ((~*Destination & AltSource) & MaskBit);} ! 412: ); ! 413: break; ! 414: case (GXand): ! 415: VERTICAL_LINE ( ! 416: {*Destination = (*Destination & ~MaskBit) | ! 417: ((*Destination & Source) & MaskBit);}, ! 418: {*Destination = (*Destination & ~MaskBit) | ! 419: ((*Destination & AltSource) & MaskBit);} ! 420: ); ! 421: break; ! 422: case (GXorInverted): ! 423: VERTICAL_LINE ( ! 424: {*Destination = (*Destination & ~MaskBit) | ! 425: ((*Destination | ~Source) & MaskBit);}, ! 426: {*Destination = (*Destination & ~MaskBit) | ! 427: ((*Destination | ~AltSource) & MaskBit);} ! 428: ); ! 429: } ! 430: } ! 431: ! 432: #ifdef SOFTWARE_CURSOR ! 433: /* ! 434: * Restore cursor to screen ! 435: */ ! 436: ! 437: if (BitMap == SCREEN_BITMAP) { ! 438: if (restore_cursor() < 0) { ! 439: DeviceError("SinglePixelLine: ioctl QIOCSHOWCUR failed.\n"); ! 440: } ! 441: } ! 442: #endif SOFTWARE_CURSOR ! 443: ! 444: #ifdef AED ! 445: /* ! 446: * Unable to use microcode to draw the line. ! 447: * Therefore, it must be echoed to the ! 448: * AED screen to become visible. ! 449: */ ! 450: ! 451: if (EchoLine) { ! 452: changed_rect.origin_y = MIN(StopY, StartY); ! 453: changed_rect.origin_x = MIN(StopX, StartX); ! 454: changed_rect.corner_y = MAX(StopY, StartY) + 1; ! 455: changed_rect.corner_x = MAX(StopX, StartX) + 1; ! 456: aed_echo_rect(&changed_rect); ! 457: } ! 458: #endif AED ! 459: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.