|
|
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.