ReactOS 0.4.15-dev-7842-g558ab78
stretchblt.c
Go to the documentation of this file.
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
31 SURFOBJ* InputObj,
33 XLATEOBJ* ColorTranslation,
34 RECTL* OutputRect,
35 RECTL* InputRect,
36 POINTL* MaskOrigin,
38 POINTL* BrushOrigin,
39 ROP4 Rop4);
40
41static BOOLEAN APIENTRY
43 SURFOBJ* psoSource,
45 XLATEOBJ* ColorTranslation,
46 RECTL* OutputRect,
47 RECTL* InputRect,
48 POINTL* MaskOrigin,
50 POINTL* BrushOrigin,
51 ROP4 Rop4)
52{
53 POINTL RealBrushOrigin;
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 {
75
76 if (!psoPattern) return FALSE;
77 }
78 else
79 {
81 }
82
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 */
96BOOL
99 IN SURFOBJ *psoDest,
100 IN SURFOBJ *psoSource,
101 IN SURFOBJ *Mask,
102 IN CLIPOBJ *ClipRegion,
103 IN XLATEOBJ *ColorTranslation,
105 IN POINTL *BrushOrigin,
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;
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 ?
364 }
365 else
366 {
367 Direction = OutputRect.left < InputRect.left ?
369 }
370 }
371 else
372 {
374 }
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 */
437BOOL
440 IN SURFOBJ *psoDest,
441 IN SURFOBJ *psoSource,
442 IN SURFOBJ *Mask,
443 IN CLIPOBJ *ClipRegion,
444 IN XLATEOBJ *ColorTranslation,
446 IN POINTL *BrushOrigin,
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,
466}
467
470 SURFOBJ *psoSource,
471 SURFOBJ *MaskSurf,
472 CLIPOBJ *ClipRegion,
473 XLATEOBJ *ColorTranslation,
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,
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,
848 pbo,
849 Rop4);
850 }
851
852 return ret;
853}
854
855BOOL
858 IN SURFOBJ *psoDest,
859 IN SURFOBJ *psoSource,
860 IN SURFOBJ *Mask,
861 IN CLIPOBJ *ClipRegion,
862 IN XLATEOBJ *ColorTranslation,
864 IN POINTL *BrushOrigin,
867 IN POINTL *MaskOrigin,
868 IN ULONG Mode)
869{
871 POINTL lBrushOrigin;
872 RECTL rclDest;
873 RECTL rclSrc;
874 POINTL lMaskOrigin;
875
877 {
878 if (pca)
879 {
880 ProbeForRead(pca, sizeof(COLORADJUSTMENT), 1);
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 }
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 */
unsigned char BOOLEAN
#define R3_OPINDEX_SRCCOPY
Definition: bitblt.h:27
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define APIENTRY
Definition: api.h:79
static const WCHAR ca[]
Definition: main.c:455
static BOOLEAN APIENTRY CallDibStretchBlt(SURFOBJ *psoDest, SURFOBJ *psoSource, SURFOBJ *Mask, XLATEOBJ *ColorTranslation, RECTL *OutputRect, RECTL *InputRect, POINTL *MaskOrigin, BRUSHOBJ *pbo, POINTL *BrushOrigin, ROP4 Rop4)
Definition: stretchblt.c:42
BOOL 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)
Definition: stretchblt.c:857
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)
Definition: stretchblt.c:469
BOOL 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)
Definition: stretchblt.c:98
BOOL 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)
Definition: stretchblt.c:439
BOOLEAN(APIENTRY * PSTRETCHRECTFUNC)(SURFOBJ *OutputObj, SURFOBJ *InputObj, SURFOBJ *Mask, XLATEOBJ *ColorTranslation, RECTL *OutputRect, RECTL *InputRect, POINTL *MaskOrigin, BRUSHOBJ *pbo, POINTL *BrushOrigin, ROP4 Rop4)
Definition: stretchblt.c:30
BOOL APIENTRY IntEngEnter(PINTENG_ENTER_LEAVE EnterLeave, SURFOBJ *psoDest, RECTL *DestRect, BOOL ReadOnly, POINTL *Translate, SURFOBJ **ppsoOutput)
Definition: engmisc.c:15
BOOL APIENTRY IntEngLeave(PINTENG_ENTER_LEAVE EnterLeave)
Definition: engmisc.c:162
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define abs(i)
Definition: fconv.c:206
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned int Mask
Definition: fpcontrol.c:82
#define BRUSHOBJ_psoPattern(pbo)
Definition: brush.h:175
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_In_ ULONG Mode
Definition: hubbusif.h:303
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ROP4_FROM_INDEX(index)
Definition: inteng.h:42
#define ROP4_NOOP
Definition: inteng.h:54
#define ROP4_USES_PATTERN(Rop4)
Definition: inteng.h:46
#define IS_VALID_ROP4(rop)
Definition: inteng.h:49
#define ROP4_USES_SOURCE(Rop4)
Definition: inteng.h:45
#define ASSERT(a)
Definition: mode.c:44
#define BOOLEAN
Definition: pedump.c:73
long LONG
Definition: pedump.c:60
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define DPRINT
Definition: sndvol32.h:71
PFN_DIB_StretchBlt DIB_StretchBlt
Definition: dib.h:51
long bottom
Definition: polytest.cpp:53
long right
Definition: polytest.cpp:53
long top
Definition: polytest.cpp:53
long left
Definition: polytest.cpp:53
BYTE iDComplexity
Definition: winddi.h:278
RECTL rclBounds
Definition: winddi.h:277
LONG y
Definition: windef.h:330
LONG x
Definition: windef.h:329
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
FLONG flags
Definition: surface.h:10
SIZEL sizlBitmap
Definition: winddi.h:1209
ULONG iBitmapFormat
Definition: winddi.h:1215
LONG lDelta
Definition: winddi.h:1213
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
int ret
WDF_EXTERN_C_START typedef _In_ WDFDEVICE _In_ WDFCONTEXT _In_ WDF_DMA_DIRECTION Direction
DIB_FUNCTIONS DibFunctionsForBitmapFormat[]
Definition: dib.c:20
BOOL APIENTRY IntEngBitBlt(SURFOBJ *psoTrg, SURFOBJ *psoSrc, SURFOBJ *psoMask, CLIPOBJ *pco, XLATEOBJ *pxlo, RECTL *prclTrg, POINTL *pptlSrc, POINTL *pptlMask, BRUSHOBJ *pbo, POINTL *pptlBrush, ROP4 Rop4)
Definition: bitblt.c:656
XCLIPOBJ gxcoTrivial
Definition: bitblt.c:20
#define GDIDEVFUNCS(SurfObj)
Definition: surface.h:106
VOID FASTCALL RECTL_vMakeWellOrdered(_Inout_ RECTL *prcl)
Definition: rect.c:81
BOOL FASTCALL RECTL_bIntersectRect(_Out_ RECTL *prclDst, _In_ const RECTL *prcl1, _In_ const RECTL *prcl2)
Definition: rect.c:55
#define DC_TRIVIAL
Definition: winddi.h:259
_Inout_ SURFOBJ _In_opt_ SURFOBJ * psoPattern
Definition: winddi.h:3960
#define CT_RECTANGLES
Definition: winddi.h:1317
ENGAPI BOOL APIENTRY CLIPOBJ_bEnum(_In_ CLIPOBJ *pco, _In_ ULONG cj, _Out_bytecap_(cj) ULONG *pul)
Definition: clip.c:319
#define CD_RIGHTUP
Definition: winddi.h:1323
_Inout_ SURFOBJ _In_opt_ SURFOBJ _In_ CLIPOBJ _In_opt_ XLATEOBJ _In_opt_ COLORADJUSTMENT * pca
Definition: winddi.h:3779
#define CD_LEFTDOWN
Definition: winddi.h:1321
#define DC_COMPLEX
Definition: winddi.h:261
_In_ SURFOBJ _In_ CLIPOBJ _In_opt_ XLATEOBJ _In_ RECTL _In_ RECTL * prclSrc
Definition: winddi.h:3418
ENGAPI ULONG APIENTRY CLIPOBJ_cEnumStart(_Inout_ CLIPOBJ *pco, _In_ BOOL bAll, _In_ ULONG iType, _In_ ULONG iDirection, _In_ ULONG cLimit)
Definition: clip.c:255
#define DC_RECT
Definition: winddi.h:260
#define CD_RIGHTDOWN
Definition: winddi.h:1320
#define CD_ANY
Definition: winddi.h:1326
#define HOOK_STRETCHBLTROP
Definition: winddi.h:1432
_In_opt_ SURFOBJ _In_opt_ SURFOBJ _In_ CLIPOBJ _In_opt_ XLATEOBJ _In_ RECTL _In_opt_ POINTL _In_opt_ POINTL _In_opt_ BRUSHOBJ * pbo
Definition: winddi.h:3440
ULONG ROP4
Definition: winddi.h:128
#define CD_LEFTUP
Definition: winddi.h:1325
_In_ SURFOBJ _In_ CLIPOBJ _In_opt_ XLATEOBJ _In_ RECTL * prclDest
Definition: winddi.h:3417
#define COLORONCOLOR
Definition: wingdi.h:954
unsigned char BYTE
Definition: xxhash.c:193