1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: GDI stretch blt functions
5 * FILE: win32ss/gdi/eng/stretchblt.c
6 * PROGRAMERS: Jason Filby
7 * Doug Lyons
8 */
9
10 #include <win32k.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15 /***************************************************************************************************************************
16 We want to receive and send the flip state along to existing functions without changing their parameter lists.
17 So a way that we can do this is to use the DestRect to carry this information along with it.
18 Since there are four values, we can use their relative positions (coordinates) to indicate the four flip conditions.
19 if delta-x == 0 then there can be no Left-to-Right flip. If delta-y == 0 there can be no Top-to-Bottom flip.
20 So we can set the four flip conditions based on BOOLEAN flags as follows:
21
22 We will use internal bits bTopToBottom and bLeftToRight as follows:
23
24 !bTopToBottom && !bLeftToRight means no flips therefore left < right and top < bottom (normal well-formed rectangle)
25 bTopToBottom means there is a Top-To-Bottom flip therefore left < right and top > bottom
26 bLeftToRight means there is a Left-To-Right flip therefore left > right and top < bottom
27 bLeftToRight && bTopToBottom means both flips therefore left > right and top > bottom
28 ****************************************************************************************************************************/
29
30 typedef BOOLEAN (APIENTRY *PSTRETCHRECTFUNC)(SURFOBJ* OutputObj,
31 SURFOBJ* InputObj,
32 SURFOBJ* Mask,
33 XLATEOBJ* ColorTranslation,
34 RECTL* OutputRect,
35 RECTL* InputRect,
36 POINTL* MaskOrigin,
37 BRUSHOBJ* pbo,
38 POINTL* BrushOrigin,
39 ROP4 Rop4);
40
41 static BOOLEAN APIENTRY
CallDibStretchBlt(SURFOBJ * psoDest,SURFOBJ * psoSource,SURFOBJ * Mask,XLATEOBJ * ColorTranslation,RECTL * OutputRect,RECTL * InputRect,POINTL * MaskOrigin,BRUSHOBJ * pbo,POINTL * BrushOrigin,ROP4 Rop4)42 CallDibStretchBlt(SURFOBJ* psoDest,
43 SURFOBJ* psoSource,
44 SURFOBJ* Mask,
45 XLATEOBJ* ColorTranslation,
46 RECTL* OutputRect,
47 RECTL* InputRect,
48 POINTL* MaskOrigin,
49 BRUSHOBJ* pbo,
50 POINTL* BrushOrigin,
51 ROP4 Rop4)
52 {
53 POINTL RealBrushOrigin;
54 SURFOBJ* psoPattern;
55 BOOL bResult;
56
57 DPRINT("Entering CallDibStretchBlt: psoSource cx/cy (%d/%d), psoDest cx/cy (%d/%d) OutputRect: (%d,%d)-(%d,%d)\n",
58 psoSource->sizlBitmap.cx, psoSource->sizlBitmap.cy,
59 psoDest->sizlBitmap.cx, psoDest->sizlBitmap.cy,
60 OutputRect->left, OutputRect->top, OutputRect->right, OutputRect->bottom);
61
62 if (BrushOrigin == NULL)
63 {
64 RealBrushOrigin.x = RealBrushOrigin.y = 0;
65 }
66 else
67 {
68 RealBrushOrigin = *BrushOrigin;
69 }
70
71 /* Pattern brush */
72 if (ROP4_USES_PATTERN(Rop4) && pbo && pbo->iSolidColor == 0xFFFFFFFF)
73 {
74 psoPattern = BRUSHOBJ_psoPattern(pbo);
75
76 if (!psoPattern) return FALSE;
77 }
78 else
79 {
80 psoPattern = NULL;
81 }
82
83 bResult = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_StretchBlt(
84 psoDest, psoSource, Mask, psoPattern,
85 OutputRect, InputRect, MaskOrigin, pbo, &RealBrushOrigin,
86 ColorTranslation, Rop4);
87
88 return bResult;
89 }
90
91
92
93 /*
94 * @implemented
95 */
96 BOOL
97 APIENTRY
EngStretchBltROP(IN SURFOBJ * psoDest,IN SURFOBJ * psoSource,IN SURFOBJ * Mask,IN CLIPOBJ * ClipRegion,IN XLATEOBJ * ColorTranslation,IN COLORADJUSTMENT * pca,IN POINTL * BrushOrigin,IN RECTL * prclDest,IN RECTL * prclSrc,IN POINTL * MaskOrigin,IN ULONG Mode,IN BRUSHOBJ * pbo,IN ROP4 Rop4)98 EngStretchBltROP(
99 IN SURFOBJ *psoDest,
100 IN SURFOBJ *psoSource,
101 IN SURFOBJ *Mask,
102 IN CLIPOBJ *ClipRegion,
103 IN XLATEOBJ *ColorTranslation,
104 IN COLORADJUSTMENT *pca,
105 IN POINTL *BrushOrigin,
106 IN RECTL *prclDest,
107 IN RECTL *prclSrc,
108 IN POINTL *MaskOrigin,
109 IN ULONG Mode,
110 IN BRUSHOBJ *pbo,
111 IN ROP4 Rop4)
112 {
113 RECTL InputRect;
114 RECTL OutputRect;
115 POINTL Translate;
116 INTENG_ENTER_LEAVE EnterLeaveSource;
117 INTENG_ENTER_LEAVE EnterLeaveDest;
118 SURFOBJ* psoInput;
119 SURFOBJ* psoOutput;
120 PSTRETCHRECTFUNC BltRectFunc;
121 BOOLEAN Ret = TRUE;
122 POINTL AdjustedBrushOrigin;
123 BOOL UsesSource = ROP4_USES_SOURCE(Rop4);
124
125 BYTE clippingType;
126 RECTL ClipRect;
127 RECT_ENUM RectEnum;
128 BOOL EnumMore;
129 ULONG Direction;
130 RECTL CombinedRect;
131 RECTL InputToCombinedRect;
132 unsigned i;
133
134 LONG DstHeight;
135 LONG DstWidth;
136 LONG SrcHeight;
137 LONG SrcWidth;
138
139 LONG cxSrc, cySrc, cxDest, cyDest;
140 BOOLEAN bLeftToRight, bTopToBottom;
141 LONG lTmp;
142
143 DPRINT("Entering EngStretchBltROP: prclSrc: (%d/%d)-(%d/%d) prclDest: (%d,%d)-(%d,%d)\n",
144 prclSrc->left, prclSrc->top, prclSrc->right, prclSrc->bottom,
145 prclDest->left, prclDest->top, prclDest->right, prclDest->bottom);
146
147 cxSrc = prclSrc->right - prclSrc->left;
148 cySrc = prclSrc->bottom - prclSrc->top;
149 cxDest = prclDest->right - prclDest->left;
150 cyDest = prclDest->bottom - prclDest->top;
151
152 /* Here we do the tests and set our conditions */
153 if (((cxSrc < 0) && (cxDest < 0)) || ((cxSrc >= 0) && (cxDest >= 0)))
154 bLeftToRight = FALSE;
155 else
156 bLeftToRight = TRUE;
157
158 if (((cySrc < 0) && (cyDest < 0)) || ((cySrc >= 0) && (cyDest >= 0)))
159 bTopToBottom = FALSE;
160 else
161 bTopToBottom = TRUE;
162
163 /* Make Well Ordered to start */
164 OutputRect = *prclDest;
165 RECTL_vMakeWellOrdered(&OutputRect);
166 *prclDest = OutputRect;
167
168 if (Rop4 == ROP4_NOOP)
169 {
170 /* Copy destination onto itself: nop */
171 return TRUE;
172 }
173
174
175 /* Determine clipping type */
176 if (ClipRegion == (CLIPOBJ *) NULL)
177 {
178 clippingType = DC_TRIVIAL;
179 }
180 else
181 {
182 clippingType = ClipRegion->iDComplexity;
183 }
184
185 OutputRect = *prclDest;
186 if (OutputRect.right < OutputRect.left)
187 {
188 OutputRect.left = prclDest->right;
189 OutputRect.right = prclDest->left;
190 }
191 if (OutputRect.bottom < OutputRect.top)
192 {
193 OutputRect.top = prclDest->bottom;
194 OutputRect.bottom = prclDest->top;
195 }
196
197 if (UsesSource)
198 {
199 if (NULL == prclSrc)
200 {
201 return FALSE;
202 }
203 InputRect = *prclSrc;
204
205 if (! IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE,
206 &Translate, &psoInput))
207 {
208 return FALSE;
209 }
210
211 InputRect.left += Translate.x;
212 InputRect.right += Translate.x;
213 InputRect.top += Translate.y;
214 InputRect.bottom += Translate.y;
215 }
216 else
217 {
218 InputRect.left = 0;
219 InputRect.right = OutputRect.right - OutputRect.left;
220 InputRect.top = 0;
221 InputRect.bottom = OutputRect.bottom - OutputRect.top;
222 psoInput = NULL;
223 }
224
225 if (NULL != ClipRegion)
226 {
227 if (OutputRect.left < ClipRegion->rclBounds.left)
228 {
229 InputRect.left += ClipRegion->rclBounds.left - OutputRect.left;
230 OutputRect.left = ClipRegion->rclBounds.left;
231 }
232 if (ClipRegion->rclBounds.right < OutputRect.right)
233 {
234 InputRect.right -= OutputRect.right - ClipRegion->rclBounds.right;
235 OutputRect.right = ClipRegion->rclBounds.right;
236 }
237 if (OutputRect.top < ClipRegion->rclBounds.top)
238 {
239 InputRect.top += ClipRegion->rclBounds.top - OutputRect.top;
240 OutputRect.top = ClipRegion->rclBounds.top;
241 }
242 if (ClipRegion->rclBounds.bottom < OutputRect.bottom)
243 {
244 InputRect.bottom -= OutputRect.bottom - ClipRegion->rclBounds.bottom;
245 OutputRect.bottom = ClipRegion->rclBounds.bottom;
246 }
247 }
248
249 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
250 nothing to do */
251 if (OutputRect.right <= OutputRect.left || OutputRect.bottom <= OutputRect.top)
252 {
253 if (UsesSource)
254 {
255 IntEngLeave(&EnterLeaveSource);
256 }
257 return TRUE;
258 }
259
260 if (! IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &psoOutput))
261 {
262 if (UsesSource)
263 {
264 IntEngLeave(&EnterLeaveSource);
265 }
266 return FALSE;
267 }
268
269 OutputRect.left += Translate.x;
270 OutputRect.right += Translate.x;
271 OutputRect.top += Translate.y;
272 OutputRect.bottom += Translate.y;
273
274 if (BrushOrigin)
275 {
276 AdjustedBrushOrigin.x = BrushOrigin->x + Translate.x;
277 AdjustedBrushOrigin.y = BrushOrigin->y + Translate.y;
278 }
279 else
280 {
281 AdjustedBrushOrigin = Translate;
282 }
283
284 BltRectFunc = CallDibStretchBlt;
285
286 DstHeight = OutputRect.bottom - OutputRect.top;
287 DstWidth = OutputRect.right - OutputRect.left;
288 SrcHeight = InputRect.bottom - InputRect.top;
289 SrcWidth = InputRect.right - InputRect.left;
290
291 DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
292
293 switch (clippingType)
294 {
295 case DC_TRIVIAL:
296 if (bLeftToRight)
297 {
298 lTmp = OutputRect.left;
299 OutputRect.left = OutputRect.right;
300 OutputRect.right = lTmp;
301 }
302
303 if (bTopToBottom)
304 {
305 lTmp = OutputRect.top;
306 OutputRect.top = OutputRect.bottom;
307 OutputRect.bottom = lTmp;
308 }
309
310 DPRINT("About to call CallDibStretchBlt: OutputRect: (%d,%d)-(%d,%d)\n",
311 OutputRect.left, OutputRect.top, OutputRect.right, OutputRect.bottom);
312
313 Ret = (*BltRectFunc)(psoOutput, psoInput, Mask,
314 ColorTranslation, &OutputRect, &InputRect, MaskOrigin,
315 pbo, &AdjustedBrushOrigin, Rop4);
316 break;
317 case DC_RECT:
318 // Clip the blt to the clip rectangle
319 ClipRect.left = ClipRegion->rclBounds.left + Translate.x;
320 ClipRect.right = ClipRegion->rclBounds.right + Translate.x;
321 ClipRect.top = ClipRegion->rclBounds.top + Translate.y;
322 ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y;
323 if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
324 {
325 InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight;
326 InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight;
327 InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth;
328 InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth;
329
330 if (bLeftToRight)
331 {
332 lTmp = CombinedRect.left;
333 CombinedRect.left = CombinedRect.right;
334 CombinedRect.right = lTmp;
335 }
336
337 if (bTopToBottom)
338 {
339 lTmp = CombinedRect.top;
340 CombinedRect.top = CombinedRect.bottom;
341 CombinedRect.bottom = lTmp;
342 }
343
344 DPRINT("About to call CallDibStretchBlt: CombinedRect: (%d,%d)-(%d,%d)\n",
345 CombinedRect.left, CombinedRect.top, CombinedRect.right, CombinedRect.bottom);
346
347 Ret = (*BltRectFunc)(psoOutput, psoInput, Mask,
348 ColorTranslation,
349 &CombinedRect,
350 &InputToCombinedRect,
351 MaskOrigin,
352 pbo,
353 &AdjustedBrushOrigin,
354 Rop4);
355 }
356 break;
357 case DC_COMPLEX:
358 if (psoOutput == psoInput)
359 {
360 if (OutputRect.top < InputRect.top)
361 {
362 Direction = OutputRect.left < InputRect.left ?
363 CD_RIGHTDOWN : CD_LEFTDOWN;
364 }
365 else
366 {
367 Direction = OutputRect.left < InputRect.left ?
368 CD_RIGHTUP : CD_LEFTUP;
369 }
370 }
371 else
372 {
373 Direction = CD_ANY;
374 }
375 CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, 0);
376 do
377 {
378 EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum),
379 (PVOID) &RectEnum);
380 for (i = 0; i < RectEnum.c; i++)
381 {
382 ClipRect.left = RectEnum.arcl[i].left + Translate.x;
383 ClipRect.right = RectEnum.arcl[i].right + Translate.x;
384 ClipRect.top = RectEnum.arcl[i].top + Translate.y;
385 ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y;
386 if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
387 {
388 InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight;
389 InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight;
390 InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth;
391 InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth;
392
393 if (bLeftToRight)
394 {
395 lTmp = CombinedRect.left;
396 CombinedRect.left = CombinedRect.right;
397 CombinedRect.right = lTmp;
398 }
399
400 if (bTopToBottom)
401 {
402 lTmp = CombinedRect.top;
403 CombinedRect.top = CombinedRect.bottom;
404 CombinedRect.bottom = lTmp;
405 }
406
407 DPRINT("About to call CallDibStretchBlt: CombinedRect: (%d,%d)-(%d,%d)\n",
408 CombinedRect.left, CombinedRect.top, CombinedRect.right, CombinedRect.bottom);
409
410 Ret = (*BltRectFunc)(psoOutput, psoInput, Mask,
411 ColorTranslation,
412 &CombinedRect,
413 &InputToCombinedRect,
414 MaskOrigin,
415 pbo,
416 &AdjustedBrushOrigin,
417 Rop4);
418 }
419 }
420 }
421 while (EnumMore);
422 break;
423 }
424
425 IntEngLeave(&EnterLeaveDest);
426 if (UsesSource)
427 {
428 IntEngLeave(&EnterLeaveSource);
429 }
430
431 return Ret;
432 }
433
434 /*
435 * @implemented
436 */
437 BOOL
438 APIENTRY
EngStretchBlt(IN SURFOBJ * psoDest,IN SURFOBJ * psoSource,IN SURFOBJ * Mask,IN CLIPOBJ * ClipRegion,IN XLATEOBJ * ColorTranslation,IN COLORADJUSTMENT * pca,IN POINTL * BrushOrigin,IN RECTL * prclDest,IN RECTL * prclSrc,IN POINTL * MaskOrigin,IN ULONG Mode)439 EngStretchBlt(
440 IN SURFOBJ *psoDest,
441 IN SURFOBJ *psoSource,
442 IN SURFOBJ *Mask,
443 IN CLIPOBJ *ClipRegion,
444 IN XLATEOBJ *ColorTranslation,
445 IN COLORADJUSTMENT *pca,
446 IN POINTL *BrushOrigin,
447 IN RECTL *prclDest,
448 IN RECTL *prclSrc,
449 IN POINTL *MaskOrigin,
450 IN ULONG Mode)
451 {
452 return EngStretchBltROP(
453 psoDest,
454 psoSource,
455 Mask,
456 ClipRegion,
457 ColorTranslation,
458 pca,
459 BrushOrigin,
460 prclDest,
461 prclSrc,
462 MaskOrigin,
463 Mode,
464 NULL,
465 ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
466 }
467
468 BOOL APIENTRY
IntEngStretchBlt(SURFOBJ * psoDest,SURFOBJ * psoSource,SURFOBJ * MaskSurf,CLIPOBJ * ClipRegion,XLATEOBJ * ColorTranslation,COLORADJUSTMENT * pca,RECTL * DestRect,RECTL * SourceRect,POINTL * pMaskOrigin,BRUSHOBJ * pbo,POINTL * BrushOrigin,DWORD Rop4)469 IntEngStretchBlt(SURFOBJ *psoDest,
470 SURFOBJ *psoSource,
471 SURFOBJ *MaskSurf,
472 CLIPOBJ *ClipRegion,
473 XLATEOBJ *ColorTranslation,
474 COLORADJUSTMENT *pca,
475 RECTL *DestRect,
476 RECTL *SourceRect,
477 POINTL *pMaskOrigin,
478 BRUSHOBJ *pbo,
479 POINTL *BrushOrigin,
480 DWORD Rop4)
481 {
482 BOOLEAN ret;
483 POINTL MaskOrigin = {0, 0};
484 SURFACE *psurfDest;
485 //SURFACE *psurfSource = NULL;
486 RECTL InputClippedRect;
487 RECTL InputRect;
488 RECTL OutputRect;
489 BOOL UsesSource = ROP4_USES_SOURCE(Rop4);
490 LONG InputClWidth, InputClHeight, InputWidth, InputHeight;
491 LONG lTmp, cxSrc, cySrc, cxDest, cyDest;
492 BOOLEAN bTopToBottom, bLeftToRight;
493 INT Case0000, Case0001, Case0010, Case0011;
494 INT Case0100, Case0101, Case0110, Case0111;
495 INT Case1000, Case1001, Case1010, Case1011;
496 INT Case1100, Case1101, Case1110;
497
498 DPRINT("Source cx/cy (%d/%d) and Destination cx/cy (%d/%d).\n",
499 psoSource->sizlBitmap.cx, psoSource->sizlBitmap.cy, psoDest->sizlBitmap.cx, psoDest->sizlBitmap.cy);
500
501 DPRINT("Source lDelta is '%d' and Destination lDelta is '%d'.\n",
502 psoSource->lDelta, psoDest->lDelta);
503
504 ASSERT(psoDest);
505 //ASSERT(psoSource); // FIXME!
506 ASSERT(DestRect);
507 ASSERT(SourceRect);
508 //ASSERT(!RECTL_bIsEmptyRect(SourceRect)); // FIXME!
509
510 /* If no clip object is given, use trivial one */
511 if (!ClipRegion)
512 {
513 DPRINT("Using trivial clip region.\n");
514 ClipRegion = (CLIPOBJ *)&gxcoTrivial;
515 }
516 else
517 {
518 DPRINT("ClipRegion->rclBounds is (%d,%d)-(%d,%d).\n",
519 ClipRegion->rclBounds.left, ClipRegion->rclBounds.top,
520 ClipRegion->rclBounds.right, ClipRegion->rclBounds.bottom);
521 }
522
523 psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
524
525 /* Sanity check */
526 ASSERT(IS_VALID_ROP4(Rop4));
527
528 cxSrc = SourceRect->right - SourceRect->left;
529 cySrc = SourceRect->bottom - SourceRect->top;
530 cxDest = DestRect->right - DestRect->left;
531 cyDest = DestRect->bottom - DestRect->top;
532
533 Case1110 = ((cxDest > 0) && (cyDest > 0) && (cxSrc > 0) && (cySrc < 0));
534 Case1101 = ((cxDest > 0) && (cyDest > 0) && (cxSrc < 0) && (cySrc > 0));
535 Case1100 = ((cxDest > 0) && (cyDest > 0) && (cxSrc < 0) && (cySrc < 0));
536 Case1011 = ((cxDest > 0) && (cyDest < 0) && (cxSrc > 0) && (cySrc > 0));
537 Case1010 = ((cxDest > 0) && (cyDest < 0) && (cxSrc > 0) && (cySrc < 0));
538 Case1001 = ((cxDest > 0) && (cyDest < 0) && (cxSrc < 0) && (cySrc > 0));
539 Case1000 = ((cxDest > 0) && (cyDest < 0) && (cxSrc < 0) && (cySrc < 0));
540 Case0111 = ((cxDest < 0) && (cyDest > 0) && (cxSrc > 0) && (cySrc > 0));
541 Case0110 = ((cxDest < 0) && (cyDest > 0) && (cxSrc > 0) && (cySrc < 0));
542 Case0101 = ((cxDest < 0) && (cyDest > 0) && (cxSrc < 0) && (cySrc > 0));
543 Case0100 = ((cxDest < 0) && (cyDest > 0) && (cxSrc < 0) && (cySrc < 0));
544 Case0011 = ((cxDest < 0) && (cyDest < 0) && (cxSrc > 0) && (cySrc > 0));
545 Case0010 = ((cxDest < 0) && (cyDest < 0) && (cxSrc > 0) && (cySrc < 0));
546 Case0001 = ((cxDest < 0) && (cyDest < 0) && (cxSrc < 0) && (cySrc > 0));
547 Case0000 = ((cxDest < 0) && (cyDest < 0) && (cxSrc < 0) && (cySrc < 0));
548
549 /* Make DestRect & OutputRect Well Ordered to start */
550 RECTL_vMakeWellOrdered(DestRect);
551 OutputRect = *DestRect;
552
553 /* Here we do the tests and set our conditions */
554 if (((cxSrc < 0) && (cxDest < 0)) || ((cxSrc >= 0) && (cxDest >= 0)))
555 bLeftToRight = FALSE;
556 else
557 bLeftToRight = TRUE;
558
559 if (((cySrc < 0) && (cyDest < 0)) || ((cySrc >= 0) && (cyDest >= 0)))
560 bTopToBottom = FALSE;
561 else
562 bTopToBottom = TRUE;
563
564 DPRINT("bTopToBottom is '%d' and bLeftToRight is '%d'.\n", bTopToBottom, bLeftToRight);
565
566 /* Check if source and dest size are equal */
567 if ((abs(DestRect->right - DestRect->left) == abs(SourceRect->right - SourceRect->left)) &&
568 (abs(DestRect->bottom - DestRect->top) == abs(SourceRect->bottom - SourceRect->top)))
569 {
570 DPRINT("source and dest size are equal.\n");
571
572 DPRINT("IntEngStretchBlt: dstRect: (%d,%d)-(%d,%d)\n",
573 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
574
575 if (Case0000 || Case0001 || Case0010 || Case0011) // Destinations X & Y are both negative
576 {
577 lTmp = SourceRect->left;
578 SourceRect->left = SourceRect->right;
579 SourceRect->right = lTmp;
580
581 lTmp = SourceRect->top;
582 SourceRect->top = SourceRect->bottom;
583 SourceRect->bottom = lTmp;
584 }
585
586 if (Case0100 || Case0101 || Case0110 || Case0111) // Destination X is negative and Y is positive
587 {
588 lTmp = SourceRect->left;
589 SourceRect->left = SourceRect->right;
590 SourceRect->right = lTmp;
591 }
592
593 if (Case1000 || Case1001 || Case1010 || Case1011) // Destination X is positive and Y is negative
594 {
595 lTmp = SourceRect->top;
596 SourceRect->top = SourceRect->bottom;
597 SourceRect->bottom = lTmp;
598 }
599
600 if (bLeftToRight)
601 {
602 lTmp = DestRect->left;
603 DestRect->left = DestRect->right;
604 DestRect->right = lTmp;
605 }
606
607 if (bTopToBottom)
608 {
609 lTmp = DestRect->top;
610 DestRect->top = DestRect->bottom;
611 DestRect->bottom = lTmp;
612 }
613
614 DPRINT("Calling IntEngBitBlt: SourceRect (%d,%d)-(%d,%d) DestRect: (%d,%d)-(%d,%d)\n",
615 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
616 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
617
618 /* Pass the request to IntEngBitBlt */
619 return IntEngBitBlt(psoDest,
620 psoSource,
621 MaskSurf,
622 ClipRegion,
623 ColorTranslation,
624 DestRect,
625 (PPOINTL)SourceRect,
626 pMaskOrigin,
627 pbo,
628 BrushOrigin,
629 Rop4);
630 }
631
632 DPRINT("source and dest size are NOT equal.\n");
633
634 DPRINT("SourceRect: (%d,%d)-(%d,%d) and DestRect: (%d,%d)-(%d,%d)\n",
635 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
636 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
637
638 /* if cxSrc < 0 then we change the signs for both cxSrc and cxDest and
639 * we reverse their coordinates, because these outcomes are the same.
640 */
641 if (cxSrc < 0)
642 {
643 lTmp = SourceRect->left;
644 SourceRect->left = SourceRect->right;
645 SourceRect->right = lTmp;
646 lTmp = DestRect->left;
647 DestRect->left = DestRect->right;
648 DestRect->right = lTmp;
649 cxSrc = -cxSrc;
650 cxDest = -cxDest;
651 }
652 /* if cySrc < 0 then we change the signs for both cySrc and cyDest and
653 * we reverse their coordinates, because these outcomes are the same.
654 */
655 if (cySrc < 0)
656 {
657 lTmp = DestRect->top;
658 DestRect->top = DestRect->bottom;
659 DestRect->bottom = lTmp;
660 lTmp = SourceRect->top;
661 SourceRect->top = SourceRect->bottom;
662 SourceRect->bottom = lTmp;
663 cySrc = -cySrc;
664 cyDest = -cyDest;
665 }
666
667 if (Case0010 || Case0111) // Horizontal Flips
668 {
669 DestRect->left--;
670 }
671
672 if (Case0010 || Case0111 || Case1000 || Case1101) // Horizontal Flips
673 {
674 SourceRect->left--;
675 SourceRect->right--;
676 }
677
678 if (Case0001 || Case0100 || Case1011 || Case1110) // Vertical Flips
679 {
680 SourceRect->top--;
681 SourceRect->bottom--;
682 }
683
684 if (Case0011 || Case0110 || Case1001 || Case1100) // Horizontal and Vertical Flips
685 {
686 SourceRect->left--;
687 SourceRect->right--;
688
689 SourceRect->top--;
690 SourceRect->bottom--;
691 }
692
693 if (Case0000 || Case1010) // No Flip - Just Copy
694 {
695 SourceRect->top++;
696 SourceRect->bottom++;
697
698 DestRect->top++;
699 DestRect->bottom++;
700 }
701
702 if (Case0000 || Case0101) // No Flip - Just Copy
703 {
704 SourceRect->left++;
705 SourceRect->right++;
706
707 DestRect->left++;
708 DestRect->right++;
709
710 }
711
712 DPRINT("SourceRect: (%d,%d)-(%d,%d) and DestRect: (%d,%d)-(%d,%d)\n",
713 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
714 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
715
716 InputClippedRect = *DestRect;
717 if (InputClippedRect.right < InputClippedRect.left)
718 {
719 InputClippedRect.left = DestRect->right;
720 InputClippedRect.right = DestRect->left;
721 }
722 if (InputClippedRect.bottom < InputClippedRect.top)
723 {
724 InputClippedRect.top = DestRect->bottom;
725 InputClippedRect.bottom = DestRect->top;
726 }
727
728 if (NULL == psoSource)
729 {
730 DPRINT("Returning FALSE.\n");
731 return FALSE;
732 }
733 InputRect = *SourceRect;
734
735 if (InputRect.right < InputRect.left ||
736 InputRect.bottom < InputRect.top)
737 {
738 DPRINT("Returning TRUE.\n");
739 /* Everything clipped away, nothing to do */
740 return TRUE;
741 }
742
743 DPRINT("InputRect: (%d,%d)-(%d,%d) and InputClippedRect: (%d,%d)-(%d,%d)\n",
744 InputRect.left, InputRect.top, InputRect.right, InputRect.bottom,
745 InputClippedRect.left, InputClippedRect.top, InputClippedRect.right, InputClippedRect.bottom);
746
747 if (ClipRegion->iDComplexity != DC_TRIVIAL)
748 {
749 if (!RECTL_bIntersectRect(&OutputRect, &InputClippedRect,
750 &ClipRegion->rclBounds))
751 {
752 DPRINT("Returning TRUE.\n");
753 return TRUE;
754 }
755
756 DPRINT("InputClippedRect: (%d,%d)-(%d,%d) and OutputRect: (%d,%d)-(%d,%d)\n",
757 InputClippedRect.left, InputClippedRect.top, InputClippedRect.right, InputClippedRect.bottom,
758 OutputRect.left, OutputRect.top, OutputRect.right, OutputRect.bottom);
759
760 /* Update source rect */
761 InputClWidth = InputClippedRect.right - InputClippedRect.left;
762 InputClHeight = InputClippedRect.bottom - InputClippedRect.top;
763 InputWidth = InputRect.right - InputRect.left;
764 InputHeight = InputRect.bottom - InputRect.top;
765
766 InputRect.left += (InputWidth * (OutputRect.left - InputClippedRect.left)) / InputClWidth;
767 InputRect.right -= (InputWidth * (InputClippedRect.right - OutputRect.right)) / InputClWidth;
768 InputRect.top += (InputHeight * (OutputRect.top - InputClippedRect.top)) / InputClHeight;
769 InputRect.bottom -= (InputHeight * (InputClippedRect.bottom - OutputRect.bottom)) / InputClHeight;
770 }
771 else
772 {
773 DPRINT("Complexity = DC_TRIVIAL.\n");
774 OutputRect = InputClippedRect;
775 }
776
777
778 DPRINT("InputRect: (%d,%d)-(%d,%d) and OutputRect: (%d,%d)-(%d,%d)\n",
779 InputRect.left, InputRect.top, InputRect.right, InputRect.bottom,
780 OutputRect.left, OutputRect.top, OutputRect.right, OutputRect.bottom);
781
782 if (pMaskOrigin != NULL)
783 {
784 MaskOrigin.x = pMaskOrigin->x;
785 MaskOrigin.y = pMaskOrigin->y;
786 }
787
788 /* No success yet */
789 ret = FALSE;
790
791 if (UsesSource)
792 {
793 //psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj);
794 }
795
796 /* Call the driver's DrvStretchBlt if available */
797 if (psurfDest->flags & HOOK_STRETCHBLTROP)
798 {
799 DPRINT("About to call GDIDEVFUNCS(psoDest).StretchBltROP.\n");
800 /* Drv->StretchBltROP (look at http://www.osronline.com/ddkx/graphics/ddifncs_0z3b.htm ) */
801 ret = GDIDEVFUNCS(psoDest).StretchBltROP(psoDest,
802 psoSource,
803 MaskSurf,
804 ClipRegion,
805 ColorTranslation,
806 pca,
807 BrushOrigin,
808 &OutputRect,
809 &InputRect,
810 &MaskOrigin,
811 COLORONCOLOR,
812 pbo,
813 Rop4);
814 }
815
816 if (! ret)
817 {
818 /* set OutputRect to follow flip */
819 if (bLeftToRight)
820 {
821 lTmp = OutputRect.left;
822 OutputRect.left = OutputRect.right;
823 OutputRect.right = lTmp;
824 }
825
826 if (bTopToBottom)
827 {
828 lTmp = OutputRect.top;
829 OutputRect.top = OutputRect.bottom;
830 OutputRect.bottom = lTmp;
831 }
832
833 DPRINT("Calling EngStretchBltROP: InputRect: (%d,%d)-(%d,%d) and OutputRect: (%d,%d)-(%d,%d)\n",
834 InputRect.left, InputRect.top, InputRect.right, InputRect.bottom,
835 OutputRect.left, OutputRect.top, OutputRect.right, OutputRect.bottom);
836
837 ret = EngStretchBltROP(psoDest,
838 psoSource,
839 MaskSurf,
840 ClipRegion,
841 ColorTranslation,
842 pca,
843 BrushOrigin,
844 &OutputRect,
845 &InputRect,
846 &MaskOrigin,
847 COLORONCOLOR,
848 pbo,
849 Rop4);
850 }
851
852 return ret;
853 }
854
855 BOOL
856 APIENTRY
NtGdiEngStretchBlt(IN SURFOBJ * psoDest,IN SURFOBJ * psoSource,IN SURFOBJ * Mask,IN CLIPOBJ * ClipRegion,IN XLATEOBJ * ColorTranslation,IN COLORADJUSTMENT * pca,IN POINTL * BrushOrigin,IN RECTL * prclDest,IN RECTL * prclSrc,IN POINTL * MaskOrigin,IN ULONG Mode)857 NtGdiEngStretchBlt(
858 IN SURFOBJ *psoDest,
859 IN SURFOBJ *psoSource,
860 IN SURFOBJ *Mask,
861 IN CLIPOBJ *ClipRegion,
862 IN XLATEOBJ *ColorTranslation,
863 IN COLORADJUSTMENT *pca,
864 IN POINTL *BrushOrigin,
865 IN RECTL *prclDest,
866 IN RECTL *prclSrc,
867 IN POINTL *MaskOrigin,
868 IN ULONG Mode)
869 {
870 COLORADJUSTMENT ca;
871 POINTL lBrushOrigin;
872 RECTL rclDest;
873 RECTL rclSrc;
874 POINTL lMaskOrigin;
875
876 _SEH2_TRY
877 {
878 if (pca)
879 {
880 ProbeForRead(pca, sizeof(COLORADJUSTMENT), 1);
881 RtlCopyMemory(&ca,pca, sizeof(COLORADJUSTMENT));
882 pca = &ca;
883 }
884
885 ProbeForRead(BrushOrigin, sizeof(POINTL), 1);
886 RtlCopyMemory(&lBrushOrigin, BrushOrigin, sizeof(POINTL));
887
888 ProbeForRead(prclDest, sizeof(RECTL), 1);
889 RtlCopyMemory(&rclDest, prclDest, sizeof(RECTL));
890
891 ProbeForRead(prclSrc, sizeof(RECTL), 1);
892 RtlCopyMemory(&rclSrc, prclSrc, sizeof(RECTL));
893
894 ProbeForRead(MaskOrigin, sizeof(POINTL), 1);
895 RtlCopyMemory(&lMaskOrigin, MaskOrigin, sizeof(POINTL));
896
897 }
898 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
899 {
900 _SEH2_YIELD(return FALSE);
901 }
902 _SEH2_END;
903
904 return EngStretchBlt(psoDest, psoSource, Mask, ClipRegion, ColorTranslation, pca, &lBrushOrigin, &rclDest, &rclSrc, &lMaskOrigin, Mode);
905 }
906
907 /* EOF */
908