|
|
1.1 root 1: /******************************Module*Header*******************************\
2: * Module Name: copybits.c
3: *
4: * DrvCopyBits
5: *
6: * Copyright (c) 1992 Microsoft Corporation
7: \**************************************************************************/
8: #include "driver.h"
9: #include "bitblt.h"
10:
11: BOOL DrvCopyBits
12: (
13: SURFOBJ *psoTrg,
14: SURFOBJ *psoSrc,
15: CLIPOBJ *pco,
16: XLATEOBJ *pxlo,
17: PRECTL prclTrg,
18: PPOINTL pptlSrc
19: )
20: {
21: PDEVSURF pdsurf; // Pointer to a device surface
22:
23: LONG lDelta; // Delta to next scan of destination
24: PVOID pjDstScan0; // Pointer to scan 0 of destination DIB
25: ULONG *pulXlate; // Pointer to color xlate vector
26:
27: BOOL bMore; // Clip continuation flag
28: ULONG ircl; // Clip enumeration rectangle index
29: RECT_ENUM cben; // Clip enumerator
30: RECTL rclTemp;
31: PRECTL prcl;
32: POINTL ptlTemp;
33: DEVSURF dsurfSrc;
34: PDEVSURF pdsurfTrg; // Pointer for target
35: PDEVSURF pdsurfSrc; // Pointer for source if present
36: INT iCopyDir;
37: PFN_ScreenToScreenBlt pfn_Blt;
38: RECT_ENUM bben; // Clip enumerator
39: BYTE jClipping;
40: UCHAR *pucDIB4ToVGAConvTables;
41:
42:
43: // ASSERT(psoTrg != (SURFOBJ *) NULL, "DrvCopyBits: NULL Pointer for Target\n");
44: // ASSERT(psoSrc != (SURFOBJ *) NULL, "DrvCopyBits: NULL Pointer for Source\n");
45: // ASSERT(prclTrg != (RECTL *) NULL, "DrvCopyBits: NULL Pointer for Rect\n");
46: // ASSERT(pptlSrc != (POINTL *) NULL, "DrvCopyBits: NULL Pointer for Point\n");
47:
48: // ASSERT(((psoTrg->dhsurf != (DHSURF) 0) || (psoSrc->dhsurf != (DHSURF) 0)),
49: // "DrvCopyBits: No device surface involved\n");
50:
51: // Check for device surface to device surface
52:
53: if ((psoTrg->iType == STYPE_DEVICE) && (psoSrc->iType == STYPE_DEVICE))
54: {
55: pdsurfTrg = (PDEVSURF) psoTrg->dhsurf;
56: pdsurfSrc = (PDEVSURF) psoSrc->dhsurf;
57:
58: // It's a screen-to-screen aligned SRCCOPY; special-case it
59:
60: // Determine the direction in which the copy must proceed
61: // Note that although we could detect cases where the source
62: // and dest don't overlap and handle them top to bottom, all
63: // copy directions are equally fast, so there's no reason to go
64: // top to bottom except possibly that it looks better. But it
65: // also takes time to detect non-overlap, so I'm not doing it
66:
67: // Set up the clipping type
68:
69: if (pco == (CLIPOBJ *) NULL)
70: {
71: // No CLIPOBJ provided, so we don't have to worry about clipping
72:
73: jClipping = DC_TRIVIAL;
74: }
75: else
76: {
77: // Use the CLIPOBJ-provided clipping
78:
79: jClipping = pco->iDComplexity;
80: }
81:
82:
83: if (pptlSrc->y >= prclTrg->top) {
84: if (pptlSrc->x >= prclTrg->left) {
85: iCopyDir = CD_RIGHTDOWN;
86: } else {
87: iCopyDir = CD_LEFTDOWN;
88: }
89: } else {
90: if (pptlSrc->x >= prclTrg->left) {
91: iCopyDir = CD_RIGHTUP;
92: } else {
93: iCopyDir = CD_LEFTUP;
94: }
95: }
96:
97: // These values are expected by vAlignedSrcCopy
98: // ASSERT(((CD_RIGHTDOWN == 0) && (CD_LEFTDOWN == 1) &&
99: // (CD_RIGHTUP == 2) && (CD_LEFTUP == 3)),
100: // "DrvBitBlt: Bad clip enumeration direction constants");
101:
102: switch(jClipping) {
103:
104: case DC_TRIVIAL:
105: // Just copy the rectangle
106: if ((((prclTrg->left ^ pptlSrc->x) & 0x07) == 0)) {
107: vAlignedSrcCopy(pdsurfTrg, prclTrg,
108: pptlSrc, iCopyDir);
109: } else {
110: vNonAlignedSrcCopy(pdsurfTrg, prclTrg,
111: pptlSrc, iCopyDir);
112: }
113: break;
114:
115: case DC_RECT:
116: // Clip the solid fill to the clip rectangle
117: if (!DrvIntersectRect(&rclTemp, prclTrg,
118: &pco->rclBounds)) {
119: // Nothing to draw; completely clipped
120: return TRUE;
121: }
122:
123: // Adjust the source point for clipping too
124: ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
125: ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
126:
127: // Copy the clipped rectangle
128: if ((((prclTrg->left ^ pptlSrc->x) & 0x07) == 0)) {
129: vAlignedSrcCopy(pdsurfTrg, &rclTemp, &ptlTemp,
130: iCopyDir);
131: } else {
132: vNonAlignedSrcCopy(pdsurfTrg, &rclTemp, &ptlTemp,
133: iCopyDir);
134: }
135: break;
136:
137: case DC_COMPLEX:
138:
139: if ((((prclTrg->left ^ pptlSrc->x) & 0x07) == 0)) {
140: pfn_Blt = vAlignedSrcCopy;
141: } else {
142: pfn_Blt = vNonAlignedSrcCopy;
143: }
144:
145: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
146: iCopyDir, ENUM_RECT_LIMIT);
147:
148: do {
149: bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
150: (PVOID) &bben);
151:
152: prcl = bben.arcl;
153: for (ircl = 0; ircl < bben.c; ircl++, prcl++) {
154:
155: DrvIntersectRect(prcl,prcl,prclTrg);
156: // Adjust the source point for clipping too
157: ptlTemp.x = pptlSrc->x + prcl->left -
158: prclTrg->left;
159: ptlTemp.y = pptlSrc->y + prcl->top -
160: prclTrg->top;
161: pfn_Blt(pdsurfTrg, prcl,
162: &ptlTemp, iCopyDir);
163:
164: }
165: } while(bMore);
166: break;
167: }
168: return TRUE;
169: }
170:
171: if (psoSrc->iType == STYPE_BITMAP) {
172:
173: // DIB to screen
174:
175: switch(psoSrc->iBitmapFormat)
176: {
177: case BMF_4BPP: // special case compatible DIBs with no translation
178:
179: if ((pxlo == NULL) || (pxlo->flXlate == XO_TRIVIAL)) {
180:
181: pucDIB4ToVGAConvTables =
182: ((PDEVSURF) psoTrg->dhsurf)->ppdev->
183: pucDIB4ToVGAConvTables;
184:
185: // Make just enough of a fake DEVSURF for the source so that
186: // the DIB to VGA code can work
187:
188: dsurfSrc.lNextScan = psoSrc->lDelta;
189: dsurfSrc.pvBitmapStart = psoSrc->pvScan0;
190:
191: // Clip as needed
192:
193: if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL)) {
194:
195: // No clipping, just copy the DIB to the VGA
196:
197: vDIB2VGA((PDEVSURF) psoTrg->dhsurf, &dsurfSrc, prclTrg,
198: pptlSrc, pucDIB4ToVGAConvTables);
199:
200: } else if (pco->iDComplexity == DC_RECT) {
201:
202: // Clip the destination to the clip rectangle; we
203: // should never get a NULL result
204: if (DrvIntersectRect(&rclTemp, prclTrg, &pco->rclBounds)) {
205:
206: // Adjust the source point for clipping too
207: ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
208: ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
209:
210: // Blt the clipped rectangle
211: vDIB2VGA((PDEVSURF) psoTrg->dhsurf, &dsurfSrc,
212: &rclTemp, &ptlTemp, pucDIB4ToVGAConvTables);
213: }
214: return(TRUE);
215:
216: } else { // DC_COMPLEX:
217:
218: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
219: CD_ANY, ENUM_RECT_LIMIT);
220:
221: do {
222: bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
223: (PVOID) &bben);
224: prcl = bben.arcl;
225: for (ircl = 0; ircl < bben.c; ircl++, prcl++) {
226:
227: // Clip the destination to the clip rectangle;
228: // we should never get a NULL result
229: DrvIntersectRect(prcl,prcl,prclTrg);
230:
231: // Adjust the source point for clipping too
232: ptlTemp.x = pptlSrc->x + prcl->left -
233: prclTrg->left;
234: ptlTemp.y = pptlSrc->y + prcl->top -
235: prclTrg->top;
236:
237: // Blt the clipped rectangle
238: vDIB2VGA((PDEVSURF) psoTrg->dhsurf,
239: &dsurfSrc, prcl, &ptlTemp,
240: pucDIB4ToVGAConvTables);
241: }
242: } while(bMore);
243:
244: }
245:
246: return(TRUE);
247: }
248:
249: case BMF_1BPP:
250: case BMF_8BPP:
251:
252: return(DrvBitBlt(psoTrg,
253: psoSrc,
254: (SURFOBJ *) NULL,
255: pco,
256: pxlo,
257: prclTrg,
258: pptlSrc,
259: (POINTL *) NULL,
260: (BRUSHOBJ *) NULL,
261: (POINTL *) NULL,
262: 0x0000cccc));
263:
264: case BMF_8RLE:
265: case BMF_4RLE:
266: return(bRleBlt(psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc));
267:
268: }
269: }
270: else
271: {
272: // screen to DIB
273:
274: // ASSERT(psoTrg->iType == STYPE_BITMAP, "ERROR CopyBits got 2 DIBs");
275:
276: if (psoTrg->iBitmapFormat == BMF_4BPP)
277: {
278: pdsurf = (PDEVSURF) psoSrc->dhsurf;
279:
280: // Get the data for the destination DIB.
281:
282: lDelta = psoTrg->lDelta;
283: pjDstScan0 = (PBYTE) psoTrg->pvScan0;
284:
285: // Setup for any color translation which may be needed !!! Is any needed at all?
286:
287: if (pxlo == NULL)
288: {
289: pulXlate = NULL;
290: }
291: else
292: {
293: if (pxlo->flXlate & XO_TABLE)
294: pulXlate = pxlo->pulXlate;
295: else
296: {
297: // ASSERT(pxlo->flXlate & XO_TRIVIAL, "DrvCopyBits: Hopelessly complex translation\n");
298: pulXlate = (PULONG) NULL;
299: }
300: }
301:
302: // Set up for clip enumeration.
303:
304: if (pco != (CLIPOBJ *) NULL)
305: {
306: switch(pco->iDComplexity)
307: {
308: case DC_TRIVIAL:
309: bMore = FALSE;
310: cben.c = 1;
311: cben.arcl[0] = *prclTrg; // Use the target for clipping
312: break;
313:
314: case DC_RECT:
315: bMore = FALSE;
316: cben.c = 1;
317: cben.arcl[0] = pco->rclBounds; // Use the bounds for clipping
318: break;
319:
320: case DC_COMPLEX:
321: bMore = TRUE;
322: cben.c = 0;
323: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT);
324: break;
325: }
326: }
327: else
328: {
329: bMore = FALSE;
330: cben.c = 1;
331: cben.arcl[0] = *prclTrg; // Use the target for clipping
332: }
333:
334: // Call the VGA conversion routine, adjusted for each rectangle
335:
336: do
337: {
338: LONG xSrc;
339: LONG ySrc;
340: RECTL *prcl;
341:
342: if (bMore)
343: bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(cben), (PVOID) &cben);
344:
345: for (ircl = 0; ircl < cben.c; ircl++)
346: {
347: prcl = &cben.arcl[ircl];
348:
349: xSrc = pptlSrc->x + prcl->left - prclTrg->left;
350: ySrc = pptlSrc->y + prcl->top - prclTrg->top;
351:
352: vConvertVGA2DIB(pdsurf,
353: xSrc,
354: ySrc,
355: pjDstScan0,
356: prcl->left,
357: prcl->top,
358: prcl->right - prcl->left,
359: prcl->bottom - prcl->top,
360: lDelta,
361: psoTrg->iBitmapFormat,
362: pulXlate);
363: }
364: } while (bMore);
365:
366: return(TRUE);
367: }
368: }
369:
370: // This is how we do any formats that we don't support in our inner loops.
371:
372: return(SimCopyBits(psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc));
373: }
374:
375: /******************************Public*Routine******************************\
376: * SimCopyBits
377: *
378: * This function simulates CopyBits for the driver when the driver is asked
379: * to blt to formats it does not support. It converts any blt to be between
380: * the device's preferred format and the screen.
381: *
382: \**************************************************************************/
383:
384: BOOL SimCopyBits
385: (
386: SURFOBJ *psoTrg,
387: SURFOBJ *psoSrc,
388: CLIPOBJ *pco,
389: XLATEOBJ *pxlo,
390: PRECTL prclTrg,
391: PPOINTL pptlSrc
392: )
393: {
394: HBITMAP hbmTmp;
395: SURFOBJ *psoTmp;
396: RECTL rclTmp;
397: SIZEL sizlTmp;
398: BOOL bReturn = FALSE;
399: static POINTL ptl00 = {0,0};
400:
401: rclTmp.top = rclTmp.left = 0;
402: rclTmp.right = sizlTmp.cx = prclTrg->right - prclTrg->left;
403: rclTmp.bottom = sizlTmp.cy = prclTrg->bottom - prclTrg->top;
404:
405: // Create bitmap in our compatible format.
406:
407: hbmTmp = EngCreateBitmap(sizlTmp, sizlTmp.cx / 2, BMF_4BPP, 0, NULL);
408:
409: if (hbmTmp)
410: {
411: if ((psoTmp = EngLockSurface((HSURF)hbmTmp)) != NULL)
412: {
413: if (psoSrc->iType == STYPE_BITMAP)
414: {
415: // blting from DIB to screen
416:
417: if (EngCopyBits(psoTmp, psoSrc, NULL, pxlo, &rclTmp, pptlSrc))
418: {
419: // Let DrvCopyBits do this easy case copy to screen.
420:
421: bReturn = DrvCopyBits(psoTrg, psoTmp, pco, NULL, prclTrg, &ptl00);
422: }
423: }
424: else
425: {
426: // blting from screen to DIB
427:
428: if (DrvCopyBits(psoTmp, psoSrc, NULL, NULL, &rclTmp, pptlSrc))
429: {
430: // Let EngCopyBits copy between DIBS
431:
432: bReturn = EngCopyBits(psoTrg, psoTmp, pco, pxlo, prclTrg, &ptl00);
433: }
434: }
435:
436: EngUnlockSurface(psoTmp);
437: }
438:
439: EngDeleteSurface((HSURF)hbmTmp);
440: }
441:
442: return(bReturn);
443: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.