|
|
1.1 root 1: /******************************Module*Header*******************************\
2: * Module Name: Stroke.c
3: *
4: * DrvStrokePath for VGA driver
5: *
6: * Copyright (c) 1992 Microsoft Corporation
7: \**************************************************************************/
8:
9: #include "driver.h"
10: #include "lines.h"
11:
12: // Style array for alternate style (alternates one pixel on, one pixel off):
13:
14: STYLEPOS gaspAlternateStyle[] = { 1 };
15:
16: // Array to compute ROP masks:
17:
18: LONG gaiLineMix[] = {
19: AND_ZERO | XOR_ONE,
20: AND_ZERO | XOR_ZERO,
21: AND_NOTPEN | XOR_NOTPEN,
22: AND_NOTPEN | XOR_ZERO,
23: AND_ZERO | XOR_NOTPEN,
24: AND_PEN | XOR_PEN,
25: AND_ONE | XOR_ONE,
26: AND_ONE | XOR_PEN,
27: AND_PEN | XOR_ONE,
28: AND_PEN | XOR_ZERO,
29: AND_ONE | XOR_NOTPEN,
30: AND_ONE | XOR_ZERO,
31: AND_PEN | XOR_NOTPEN,
32: AND_ZERO | XOR_PEN,
33: AND_NOTPEN | XOR_ONE,
34: AND_NOTPEN | XOR_PEN
35: };
36:
37: // We have 4 basic strip drawers, one for every semi-octant. The near-
38: // horizontal semi-octant is number 0, and the rest are numbered
39: // consecutively.
40:
41: // Prototypes to go to the screen and handle any ROPs:
42:
43: VOID vStripSolid0(STRIP*, LINESTATE*, LONG*);
44: VOID vStripSolid1(STRIP*, LINESTATE*, LONG*);
45: VOID vStripSolid2(STRIP*, LINESTATE*, LONG*);
46: VOID vStripSolid3(STRIP*, LINESTATE*, LONG*);
47:
48: VOID vStripStyled0(STRIP*, LINESTATE*, LONG*);
49: VOID vStripStyled123(STRIP*, LINESTATE*, LONG*);
50:
51: // Prototypes to go to the screen and handle only set-style ROPs:
52:
53: VOID vStripSolidSet0(STRIP*, LINESTATE*, LONG*);
54: VOID vStripSolidSet1(STRIP*, LINESTATE*, LONG*);
55: VOID vStripSolidSet2(STRIP*, LINESTATE*, LONG*);
56: VOID vStripSolidSet3(STRIP*, LINESTATE*, LONG*);
57:
58: VOID vStripStyledSet0(STRIP*, LINESTATE*, LONG*);
59: VOID vStripStyledSet123(STRIP*, LINESTATE*, LONG*);
60:
61: PFNSTRIP gapfnStrip[] = {
62: vStripSolid0,
63: vStripSolid3,
64: vStripSolid1,
65: vStripSolid2,
66:
67: vStripStyled0,
68: vStripStyled123,
69: vStripStyled123,
70: vStripStyled123,
71:
72: vStripSolidSet0,
73: vStripSolidSet3,
74: vStripSolidSet1,
75: vStripSolidSet2,
76:
77: vStripStyledSet0,
78: vStripStyledSet123,
79: vStripStyledSet123,
80: vStripStyledSet123,
81: };
82:
83: /******************************Public*Routine******************************\
84: * BOOL DrvStrokePath(pso, ppo, pco, pxo, pbo, pptlBrushOrg, pla, mix)
85: *
86: * Strokes the path.
87: \**************************************************************************/
88:
89: BOOL DrvStrokePath(
90: SURFOBJ* pso,
91: PATHOBJ* ppo,
92: CLIPOBJ* pco,
93: XFORMOBJ* pxo,
94: BRUSHOBJ* pbo,
95: POINTL* pptlBrushOrg,
96: LINEATTRS* pla,
97: MIX mix)
98: {
99: STYLEPOS aspLtoR[STYLE_MAX_COUNT];
100: STYLEPOS aspRtoL[STYLE_MAX_COUNT];
101: LINESTATE ls;
102: PFNSTRIP* apfn;
103: FLONG fl;
104: PPDEV ppdev = (PPDEV) pso->dhsurf;
105:
106: UNREFERENCED_PARAMETER(pxo);
107: UNREFERENCED_PARAMETER(pptlBrushOrg);
108:
109: // Fast lines can't handle trivial clipping, ROPs other than R2_COPYPEN, or
110: // styles:
111:
112: mix &= 0xf;
113: if ((mix == 0x0d) &&
114: (pco->iDComplexity == DC_TRIVIAL) &&
115: (pla->pstyle == NULL) && !(pla->fl & LA_ALTERNATE))
116: {
117: vFastLine(ppdev, ppo, ppdev->lNextScan,
118: (pbo->iSolidColor << 8) | (pbo->iSolidColor & 0xff));
119: return(TRUE);
120: }
121:
122: fl = 0;
123:
124: // Look after styling initialization:
125:
126: if (pla->fl & LA_ALTERNATE)
127: {
128: ASSERTVGA(pla->pstyle == (FLOAT_LONG*) NULL && pla->cstyle == 0,
129: "Non-empty style array for PS_ALTERNATE");
130:
131: ls.bStartIsGap = 0; // First pel is a dash
132: ls.cStyle = 1; // Size of style array
133: ls.spTotal = 1; // Sum of style array
134: ls.spTotal2 = 2; // Twice the sum
135: ls.aspRtoL = &gaspAlternateStyle[0]; // Right-to-left array
136: ls.aspLtoR = &gaspAlternateStyle[0]; // Left-to-right array
137: ls.spNext = HIWORD(pla->elStyleState.l) & 1;
138: // Light first pixel if
139: // a multiple of 2
140: ls.xyDensity = 1; // Each 'dot' is one
141: // pixel long
142: fl |= FL_ARBITRARYSTYLED;
143: }
144: else if (pla->pstyle != (FLOAT_LONG*) NULL)
145: {
146: FLOAT_LONG* pstyle;
147: STYLEPOS* pspDown;
148: STYLEPOS* pspUp;
149:
150: ASSERTVGA(pla->cstyle <= STYLE_MAX_COUNT, "Style array too large");
151:
152: // Compute length of style array:
153:
154: pstyle = &pla->pstyle[pla->cstyle];
155:
156: ls.xyDensity = STYLE_DENSITY;
157: ls.spTotal = 0;
158: while (pstyle-- > pla->pstyle)
159: {
160: ls.spTotal += pstyle->l;
161: }
162:
163: // The style array is given in 'style' units. Since we're going to
164: // assign each unit to be STYLE_DENSITY (3) pixels long, multiply:
165:
166: ls.spTotal *= STYLE_DENSITY;
167: ls.spTotal2 = 2 * ls.spTotal;
168:
169: // Compute starting style position (this is guaranteed not to overflow).
170: // Note that since the array repeats infinitely, this number might
171: // actually be more than ls.spTotal2, but we take care of that later
172: // in our code:
173:
174: ls.spNext = HIWORD(pla->elStyleState.l) * STYLE_DENSITY +
175: LOWORD(pla->elStyleState.l);
176:
177: fl |= FL_ARBITRARYSTYLED;
178: ls.cStyle = pla->cstyle;
179: ls.aspRtoL = aspRtoL; // Style array in right-to-left order
180: ls.aspLtoR = aspLtoR; // Style array in left-to-right order
181:
182: // ulStartMask determines if the first entry in the style array is for
183: // a dash or a gap:
184:
185: ls.bStartIsGap = (pla->fl & LA_STARTGAP) ? -1L : 0L;
186:
187: pstyle = pla->pstyle;
188: pspDown = &ls.aspRtoL[ls.cStyle - 1];
189: pspUp = &ls.aspLtoR[0];
190:
191: // We always draw strips left-to-right, but styles have to be laid
192: // down in the direction of the original line. This means that in
193: // the strip code we have to traverse the style array in the
194: // opposite direction;
195:
196: while (pspDown >= &ls.aspRtoL[0])
197: {
198: ASSERTVGA(pstyle->l > 0 && pstyle->l <= STYLE_MAX_VALUE,
199: "Illegal style array value");
200:
201: *pspDown = pstyle->l * STYLE_DENSITY;
202: *pspUp = *pspDown;
203:
204: pspUp++;
205: pspDown--;
206: pstyle++;
207: }
208: }
209:
210: {
211: // All ROPs are handled in a single pass:
212:
213: ULONG achColor[4];
214: LONG iIndex;
215: ULONG iColor = (pbo->iSolidColor & 0xff);
216:
217: achColor[AND_ZERO] = 0;
218: achColor[AND_PEN] = pbo->iSolidColor;
219: achColor[AND_NOTPEN] = ~pbo->iSolidColor;
220: achColor[AND_ONE] = (ULONG) -1L;
221:
222: iIndex = gaiLineMix[mix];
223:
224: // We have special strip drawers for set-style ROPs (where we don't
225: // have to read video memory):
226:
227: if ((iIndex & 0xff) == AND_ZERO)
228: fl |= FL_SET;
229:
230: // Put the AND index in the low byte, and the XOR index in the next:
231:
232: *((BYTE*) &ls.chAndXor) = (BYTE) achColor[iIndex & 0xff];
233: *((BYTE*) &ls.chAndXor + 1) = (BYTE) achColor[iIndex >> MIX_XOR_OFFSET];
234: }
235:
236: apfn = &gapfnStrip[4 * ((fl & FL_STRIP_ARRAY_MASK) >> FL_STRIP_ARRAY_SHIFT)];
237:
238: // Set up to enumerate the path:
239:
240: if (pco->iDComplexity != DC_COMPLEX)
241: {
242: RECTL arclClip[4]; // For rectangular clipping
243: PATHDATA pd;
244: RECTL* prclClip = (RECTL*) NULL;
245: BOOL bMore;
246: ULONG cptfx;
247: POINTFIX ptfxStartFigure;
248: POINTFIX ptfxLast;
249: POINTFIX* pptfxFirst;
250: POINTFIX* pptfxBuf;
251:
252: if (pco->iDComplexity == DC_RECT)
253: {
254: fl |= FL_SIMPLE_CLIP;
255:
256: arclClip[0] = pco->rclBounds;
257:
258: // FL_FLIP_D:
259:
260: arclClip[1].top = pco->rclBounds.left;
261: arclClip[1].left = pco->rclBounds.top;
262: arclClip[1].bottom = pco->rclBounds.right;
263: arclClip[1].right = pco->rclBounds.bottom;
264:
265: // FL_FLIP_V:
266:
267: arclClip[2].top = -pco->rclBounds.bottom + 1;
268: arclClip[2].left = pco->rclBounds.left;
269: arclClip[2].bottom = -pco->rclBounds.top + 1;
270: arclClip[2].right = pco->rclBounds.right;
271:
272: // FL_FLIP_V | FL_FLIP_D:
273:
274: arclClip[3].top = pco->rclBounds.left;
275: arclClip[3].left = -pco->rclBounds.bottom + 1;
276: arclClip[3].bottom = pco->rclBounds.right;
277: arclClip[3].right = -pco->rclBounds.top + 1;
278:
279: prclClip = arclClip;
280: }
281:
282: do {
283: bMore = PATHOBJ_bEnum(ppo, &pd);
284:
285: cptfx = pd.count;
286: if (cptfx == 0)
287: {
288: ASSERTVGA(!bMore, "Empty path record in non-empty path");
289: break;
290: }
291:
292: if (pd.flags & PD_BEGINSUBPATH)
293: {
294: ptfxStartFigure = *pd.pptfx;
295: pptfxFirst = pd.pptfx;
296: pptfxBuf = pd.pptfx + 1;
297: cptfx--;
298: }
299: else
300: {
301: pptfxFirst = &ptfxLast;
302: pptfxBuf = pd.pptfx;
303: }
304:
305: if (pd.flags & PD_RESETSTYLE)
306: ls.spNext = 0;
307:
308: // We have to check for cptfx == 0 because the only point in the
309: // subpath may have been the StartFigure point:
310:
311: if (cptfx > 0)
312: {
313: if (!bLines(ppdev,
314: pptfxFirst,
315: pptfxBuf,
316: (RUN*) NULL,
317: cptfx,
318: &ls,
319: prclClip,
320: apfn,
321: fl))
322: return(FALSE);
323: }
324:
325: ptfxLast = pd.pptfx[pd.count - 1];
326:
327: if (pd.flags & PD_CLOSEFIGURE)
328: {
329: if (!bLines(ppdev,
330: &ptfxLast,
331: &ptfxStartFigure,
332: (RUN*) NULL,
333: 1,
334: &ls,
335: prclClip,
336: apfn,
337: fl))
338: return(FALSE);
339: }
340: } while (bMore);
341:
342: if (fl & FL_STYLED)
343: {
344: // Save the style state:
345:
346: ULONG ulHigh;
347: ULONG ulLow;
348:
349: ulHigh = ls.spNext / ls.xyDensity;
350: ulLow = ls.spNext % ls.xyDensity;
351:
352: pla->elStyleState.l = MAKELONG(ulLow, ulHigh);
353: }
354: }
355: else
356: {
357: // Local state for path enumeration:
358:
359: BOOL bMore;
360: union {
361: BYTE aj[offsetof(CLIPLINE, arun) + RUN_MAX * sizeof(RUN)];
362: CLIPLINE cl;
363: } cl;
364:
365: fl |= FL_COMPLEX_CLIP;
366:
367: // We use the clip object when non-simple clipping is involved:
368:
369: PATHOBJ_vEnumStartClipLines(ppo, pco, pso, pla);
370:
371: do {
372: bMore = PATHOBJ_bEnumClipLines(ppo, sizeof(cl), &cl.cl);
373: if (cl.cl.c != 0)
374: {
375: if (fl & FL_STYLED)
376: {
377: ls.spComplex = HIWORD(cl.cl.lStyleState) * ls.xyDensity
378: + LOWORD(cl.cl.lStyleState);
379: }
380: if (!bLines(ppdev,
381: &cl.cl.ptfxA,
382: &cl.cl.ptfxB,
383: &cl.cl.arun[0],
384: cl.cl.c,
385: &ls,
386: (RECTL*) NULL,
387: apfn,
388: fl))
389: return(FALSE);
390: }
391: } while (bMore);
392: }
393:
394: return(TRUE);
395: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.