3 #include "../diblib/DibLib_interface.h"
4 DBG_DEFAULT_CHANNEL(GdiFont
);
6 #define SURFOBJ_flags(pso) (CONTAINING_RECORD(pso, SURFACE, SurfObj)->flags)
8 // FIXME this needs to be updated, once we use the new structure
9 extern XCLIPOBJ gxcoTrivial
;
12 {0, {LONG_MIN, LONG_MIN, LONG_MAX, LONG_MAX}, DC_TRIVIAL, FC_RECT, TC_RECTANGLES, 0},
30 /* Calculate width and height of this rect */
31 pbltdata
->ulWidth
= prclClipped
->right
- prclClipped
->left
;
32 pbltdata
->ulHeight
= prclClipped
->bottom
- prclClipped
->top
;
34 /* Calculate the x offset to the origin coordinates */
35 if (pbltdata
->siDst
.iFormat
== 0)
36 cx
= (prclClipped
->right
- 1 - prclOrg
->left
);
38 cx
= (prclClipped
->left
- prclOrg
->left
);
40 /* Calculate the y offset to the origin coordinates */
42 cy
= (prclClipped
->bottom
- 1 - prclOrg
->top
);
44 cy
= (prclClipped
->top
- prclOrg
->top
);
46 /* Calculate the target start point */
47 pbltdata
->siDst
.ptOrig
.x
= prclOrg
->left
+ cx
;
48 pbltdata
->siDst
.ptOrig
.y
= prclOrg
->top
+ cy
;
50 /* Calculate start position for target */
51 pbltdata
->siDst
.pjBase
= pbltdata
->siDst
.pvScan0
;
52 pbltdata
->siDst
.pjBase
+= pbltdata
->siDst
.ptOrig
.y
* pbltdata
->siDst
.lDelta
;
53 pbltdata
->siDst
.pjBase
+= pbltdata
->siDst
.ptOrig
.x
* pbltdata
->siDst
.jBpp
/ 8;
57 /* Calculate start point and bitpointer for source */
58 pbltdata
->siSrc
.ptOrig
.x
= pptlSrc
->x
+ cx
;
59 pbltdata
->siSrc
.ptOrig
.y
= pptlSrc
->y
+ cy
;
60 pbltdata
->siSrc
.pjBase
= pbltdata
->siSrc
.pvScan0
;
61 pbltdata
->siSrc
.pjBase
+= pbltdata
->siSrc
.ptOrig
.y
* pbltdata
->siSrc
.lDelta
;
62 pbltdata
->siSrc
.pjBase
+= pbltdata
->siSrc
.ptOrig
.x
* pbltdata
->siSrc
.jBpp
/ 8;
67 /* Calculate start point and bitpointer for mask */
68 pbltdata
->siMsk
.ptOrig
.x
= pptlMask
->x
+ cx
;
69 pbltdata
->siMsk
.ptOrig
.y
= pptlMask
->y
+ cy
;
70 pbltdata
->siMsk
.pjBase
= pbltdata
->siMsk
.pvScan0
;
71 pbltdata
->siMsk
.pjBase
+= pbltdata
->siMsk
.ptOrig
.y
* pbltdata
->siMsk
.lDelta
;
72 pbltdata
->siMsk
.pjBase
+= pbltdata
->siMsk
.ptOrig
.x
* pbltdata
->siMsk
.jBpp
/ 8;
77 /* Calculate start point and bitpointer for pattern */
78 pbltdata
->siPat
.ptOrig
.x
= (pptlPat
->x
+ cx
) % psizlPat
->cx
;
79 pbltdata
->siPat
.ptOrig
.y
= (pptlPat
->y
+ cy
) % psizlPat
->cy
;
80 pbltdata
->siPat
.pjBase
= pbltdata
->siPat
.pvScan0
;
82 /* Check for bottom-up case */
85 pbltdata
->siPat
.pjBase
+= (psizlPat
->cy
- 1) * pbltdata
->siPat
.lDelta
;
86 pbltdata
->siPat
.ptOrig
.y
= psizlPat
->cy
- 1 - pbltdata
->siPat
.ptOrig
.y
;
89 /* Check for right-to-left case */
90 if (pbltdata
->siDst
.iFormat
== 0)
92 pbltdata
->siPat
.pjBase
+= (psizlPat
->cx
- 1) * pbltdata
->siMsk
.jBpp
/ 8;
93 pbltdata
->siPat
.ptOrig
.x
= psizlPat
->cx
- 1 - pbltdata
->siPat
.ptOrig
.x
;
101 _Inout_ SURFOBJ
*psoTrg
,
102 _In_opt_ SURFOBJ
*psoSrc
,
103 _In_opt_ SURFOBJ
*psoMask
,
104 _In_opt_ CLIPOBJ
*pco
,
105 _In_opt_ XLATEOBJ
*pxlo
,
107 _When_(psoSrc
, _In_
) POINTL
*pptlSrc
,
108 _When_(psoMask
, _In_
) POINTL
*pptlMask
,
109 _In_opt_ BRUSHOBJ
*pbo
,
110 _When_(pbo
, _In_
) POINTL
*pptlBrush
,
114 ULONG i
, iFunctionIndex
, iDirection
= CD_ANY
;
116 PFN_DIBFUNCTION pfnBitBlt
;
122 //static int count = 0;
123 //if (++count >= 1230) __debugbreak();
127 ASSERT(psoTrg
->iBitmapFormat
>= BMF_1BPP
);
128 ASSERT(psoTrg
->iBitmapFormat
<= BMF_32BPP
);
130 ASSERT(prclTrg
->left
>= 0);
131 ASSERT(prclTrg
->top
>= 0);
132 ASSERT(prclTrg
->right
<= psoTrg
->sizlBitmap
.cx
);
133 ASSERT(prclTrg
->bottom
<= psoTrg
->sizlBitmap
.cy
);
139 bltdata
.apfnDoRop
[0] = gapfnRop
[ROP4_BKGND(rop4
)];
140 bltdata
.apfnDoRop
[1] = gapfnRop
[ROP4_FGND(rop4
)];
141 if (!pxlo
) pxlo
= &gexloTrivial
.xlo
;
143 bltdata
.pfnXlate
= XLATEOBJ_pfnXlate(pxlo
);
145 /* Check if the ROP uses a source */
146 if (ROP4_USES_SOURCE(rop4
))
150 ASSERT(psoSrc
->iBitmapFormat
>= BMF_1BPP
);
151 ASSERT(psoSrc
->iBitmapFormat
<= BMF_32BPP
);
153 ASSERT(pptlSrc
->x
>= 0);
154 ASSERT(pptlSrc
->y
>= 0);
155 ASSERT(pptlSrc
->x
<= psoSrc
->sizlBitmap
.cx
);
156 ASSERT(pptlSrc
->y
<= psoSrc
->sizlBitmap
.cy
);
158 /* Check if source and target are equal */
159 if (psoSrc
== psoTrg
)
161 /* Analyze the copying direction */
162 if (rcTrg
.top
> pptlSrc
->y
)
164 /* Need to copy from bottom to top */
165 iDirection
= rcTrg
.left
< pptlSrc
->x
? CD_RIGHTUP
: CD_LEFTUP
;
169 iDirection
= rcTrg
.left
< pptlSrc
->x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
171 /* Check for special right to left case */
172 if ((rcTrg
.top
== pptlSrc
->y
) && (rcTrg
.left
> pptlSrc
->x
))
174 /* Use 0 as target format to get special right to left versions */
175 bltdata
.siDst
.iFormat
= 0;
176 bltdata
.siSrc
.iFormat
= psoSrc
->iBitmapFormat
;
181 /* Use 0 as source format to get special equal surface versions */
182 bltdata
.siDst
.iFormat
= psoTrg
->iBitmapFormat
;
183 bltdata
.siSrc
.iFormat
= 0;
188 bltdata
.siDst
.iFormat
= psoTrg
->iBitmapFormat
;
189 bltdata
.siSrc
.iFormat
= psoSrc
->iBitmapFormat
;
192 /* Set the source format info */
193 bltdata
.siSrc
.pvScan0
= psoSrc
->pvScan0
;
194 bltdata
.siSrc
.lDelta
= psoSrc
->lDelta
;
195 bltdata
.siSrc
.cjAdvanceY
= bltdata
.dy
* psoSrc
->lDelta
;
196 bltdata
.siSrc
.jBpp
= gajBitsPerFormat
[psoSrc
->iBitmapFormat
];
200 bltdata
.siDst
.iFormat
= psoTrg
->iBitmapFormat
;
203 /* Set the destination format info */
204 bltdata
.siDst
.pvScan0
= psoTrg
->pvScan0
;
205 bltdata
.siDst
.lDelta
= psoTrg
->lDelta
;
206 bltdata
.siDst
.cjAdvanceY
= bltdata
.dy
* psoTrg
->lDelta
;
207 bltdata
.siDst
.jBpp
= gajBitsPerFormat
[psoTrg
->iBitmapFormat
];
209 /* Check if the ROP uses a pattern / brush */
210 if (ROP4_USES_PATTERN(rop4
))
212 /* Must have a brush */
213 ASSERT(pbo
); // FIXME: test this!
215 /* Copy the solid color */
216 bltdata
.ulSolidColor
= pbo
->iSolidColor
;
218 /* Check if this is a pattern brush */
219 if (pbo
->iSolidColor
== 0xFFFFFFFF)
221 /* Get the realized pattern bitmap */
222 psoPattern
= BRUSHOBJ_psoPattern(pbo
);
229 /* Set the pattern format info */
230 bltdata
.siPat
.iFormat
= psoPattern
->iBitmapFormat
;
231 bltdata
.siPat
.pvScan0
= psoPattern
->pvScan0
;
232 bltdata
.siPat
.lDelta
= psoPattern
->lDelta
;
233 bltdata
.siPat
.cjAdvanceY
= bltdata
.dy
* psoPattern
->lDelta
;
234 bltdata
.siPat
.jBpp
= gajBitsPerFormat
[psoPattern
->iBitmapFormat
];
236 bltdata
.ulPatWidth
= psoPattern
->sizlBitmap
.cx
;
237 bltdata
.ulPatHeight
= psoPattern
->sizlBitmap
.cy
;
239 psizlPat
= &psoPattern
->sizlBitmap
;
253 /* Check if the ROP uses a mask */
254 if (ROP4_USES_MASK(rop4
))
256 /* Must have a mask surface and point */
262 /* Set the mask format info */
263 bltdata
.siMsk
.iFormat
= psoMask
->iBitmapFormat
;
264 bltdata
.siMsk
.pvScan0
= psoMask
->pvScan0
;
265 bltdata
.siMsk
.lDelta
= psoMask
->lDelta
;
266 bltdata
.siMsk
.cjAdvanceY
= bltdata
.dy
* psoMask
->lDelta
;
267 bltdata
.siMsk
.jBpp
= 1;
269 /* Calculate the masking function index */
270 iFunctionIndex
= ROP4_USES_PATTERN(rop4
) ? 1 : 0;
271 iFunctionIndex
|= ROP4_USES_SOURCE(rop4
) ? 2 : 0;
272 iFunctionIndex
|= ROP4_USES_DEST(rop4
) ? 4 : 0;
274 /* Get the masking function */
275 pfnBitBlt
= gapfnMaskFunction
[iFunctionIndex
];
279 /* Get the function index from the foreground ROP index*/
280 iFunctionIndex
= gajIndexPerRop
[ROP4_FGND(rop4
)];
282 /* Get the dib function */
283 pfnBitBlt
= gapfnDibFunction
[iFunctionIndex
];
286 /* If no clip object is given, use trivial one */
287 if (!pco
) pco
= (CLIPOBJ
*)&gxcoTrivial
;
289 /* Check if we need to enumerate rects */
290 if (pco
->iDComplexity
== DC_COMPLEX
)
292 /* Start the enumeration of the clip object */
293 CLIPOBJ_cEnumStart(pco
, FALSE
, CT_RECTANGLES
, iDirection
, 0);
294 bEnumMore
= CLIPOBJ_bEnum(pco
, sizeof(rcenum
), (ULONG
*)&rcenum
);
296 else if (pco
->iDComplexity
== DC_RECT
)
298 /* Use the clip bounds */
299 rcenum
.arcl
[0] = pco
->rclBounds
;
305 /* Use the target rect */
306 rcenum
.arcl
[0] = rcTrg
;
311 /* Enter enumeration loop */
314 /* Loop all rectangles we got */
315 for (i
= 0; i
< rcenum
.c
; i
++)
317 /* Intersect this rect with the target rect */
318 if (!RECTL_bIntersectRect(&rcenum
.arcl
[i
], &rcenum
.arcl
[i
], &rcTrg
))
320 /* This rect is outside the bounds, continue */
324 /* Calculate coordinates and pointers */
325 CalculateCoordinates(&bltdata
,
333 /* Call the dib function */
337 /* Bail out, when there's nothing more to do */
338 if(!bEnumMore
) break;
340 /* Enumerate more rectangles */
341 bEnumMore
= CLIPOBJ_bEnum(pco
, sizeof(rcenum
), (ULONG
*)&rcenum
);
351 _Out_ PPOINTL pptOffset
,
352 _Out_ PSIZEL psizTrg
,
353 _In_ PPOINTL pptlSrc
,
356 LONG x
, y
, cxMax
, cyMax
;
358 x
= pptlSrc
->x
+ pptOffset
->x
;
359 if (x
< 0) pptOffset
->x
-= x
, x
= 0;
361 cxMax
= psizSrc
->cx
- x
;
362 if (psizTrg
->cx
> cxMax
) psizTrg
->cx
= cxMax
;
364 y
= pptlSrc
->y
+ pptOffset
->y
;
365 if (y
< 0) pptOffset
->y
-= y
, y
= 0;
367 cyMax
= psizSrc
->cy
- y
;
368 if (psizTrg
->cy
> cyMax
) psizTrg
->cy
= cyMax
;
374 _Inout_ SURFOBJ
*psoTrg
,
375 _In_opt_ SURFOBJ
*psoSrc
,
376 _In_opt_ SURFOBJ
*psoMask
,
377 _In_opt_ CLIPOBJ
*pco
,
378 _In_opt_ XLATEOBJ
*pxlo
,
380 _When_(psoSrc
, _In_
) POINTL
*pptlSrc
,
381 _When_(psoMask
, _In_
) POINTL
*pptlMask
,
382 _In_opt_ BRUSHOBJ
*pbo
,
383 _When_(pbo
, _In_
) POINTL
*pptlBrush
,
388 POINTL ptOffset
, ptSrc
, ptMask
, ptBrush
;
390 PFN_DrvBitBlt pfnBitBlt
;
395 ASSERT(IS_VALID_ROP4(rop4
));
397 ASSERT(psoTrg
->iBitmapFormat
>= BMF_1BPP
);
398 ASSERT(psoTrg
->iBitmapFormat
<= BMF_32BPP
);
401 /* Clip the target rect to the extents of the target surface */
402 rcClipped
.left
= max(prclTrg
->left
, 0);
403 rcClipped
.top
= max(prclTrg
->top
, 0);
404 rcClipped
.right
= min(prclTrg
->right
, psoTrg
->sizlBitmap
.cx
);
405 rcClipped
.bottom
= min(prclTrg
->bottom
, psoTrg
->sizlBitmap
.cy
);
407 /* If no clip object is given, use trivial one */
408 if (!pco
) pco
= (CLIPOBJ
*)&gxcoTrivial
;
410 /* Check if there is something to clip */
411 if (pco
->iDComplexity
!= DC_TRIVIAL
)
413 /* Clip the target rect to the bounds of the clipping region */
414 if (!RECTL_bIntersectRect(&rcClipped
, &rcClipped
, &pco
->rclBounds
))
421 /* Don't pass a clip object with a single rectangle */
422 if (pco
->iDComplexity
== DC_RECT
) pco
= (CLIPOBJ
*)&gxcoTrivial
;
424 /* Calculate initial offset and size */
425 ptOffset
.x
= rcClipped
.left
- prclTrg
->left
;
426 ptOffset
.y
= rcClipped
.top
- prclTrg
->top
;
427 sizTrg
.cx
= rcClipped
.right
- rcClipped
.left
;
428 sizTrg
.cy
= rcClipped
.bottom
- rcClipped
.top
;
430 /* Check if the ROP uses a source */
431 if (ROP4_USES_SOURCE(rop4
))
433 /* Must have a source surface and point */
437 /* Get the source point */
440 /* Clip against the extents of the source surface */
441 AdjustOffsetAndSize(&ptOffset
, &sizTrg
, &ptSrc
, &psoSrc
->sizlBitmap
);
450 /* Check if the ROP uses a mask */
451 if (ROP4_USES_MASK(rop4
))
453 /* Must have a mask surface and point */
457 /* Get the mask point */
460 /* Clip against the extents of the mask surface */
461 AdjustOffsetAndSize(&ptOffset
, &sizTrg
, &ptMask
, &psoMask
->sizlBitmap
);
470 /* Check if all has been clipped away */
471 if ((sizTrg
.cx
<= 0) || (sizTrg
.cy
<= 0))
474 /* Adjust the points */
475 ptSrc
.x
+= ptOffset
.x
;
476 ptSrc
.y
+= ptOffset
.y
;
477 ptMask
.x
+= ptOffset
.x
;
478 ptMask
.y
+= ptOffset
.y
;
480 /* Check if we have a brush origin */
483 /* calculate the new brush origin */
484 ptBrush
.x
= pptlBrush
->x
+ ptOffset
.x
;
485 ptBrush
.y
= pptlBrush
->y
+ ptOffset
.y
;
488 /* Recalculate the target rect */
489 rcClipped
.left
= prclTrg
->left
+ ptOffset
.x
;
490 rcClipped
.top
= prclTrg
->top
+ ptOffset
.y
;
491 rcClipped
.right
= rcClipped
.left
+ sizTrg
.cx
;
492 rcClipped
.bottom
= rcClipped
.top
+ sizTrg
.cy
;
494 /* Is the target surface device managed? */
495 if (SURFOBJ_flags(psoTrg
) & HOOK_BITBLT
)
497 /* Is the source a different device managed surface? */
498 if (psoSrc
&& (psoSrc
->hdev
!= psoTrg
->hdev
) &&
499 (SURFOBJ_flags(psoSrc
) & HOOK_BITBLT
))
501 ERR("Need to copy to standard bitmap format!\n");
505 pfnBitBlt
= GDIDEVFUNCS(psoTrg
).BitBlt
;
507 /* Otherwise is the source surface device managed? */
508 else if (psoSrc
&& (SURFOBJ_flags(psoSrc
) & HOOK_BITBLT
))
510 pfnBitBlt
= GDIDEVFUNCS(psoSrc
).BitBlt
;
514 pfnBitBlt
= EngBitBlt
;
517 bResult
= pfnBitBlt(psoTrg
,
523 psoSrc
? &ptSrc
: NULL
,
524 psoMask
? &ptMask
: NULL
,
526 pptlBrush
? &ptBrush
: NULL
,
529 // FIXME: cleanup temp surface!
537 IN SURFOBJ
*psoTrgUMPD
,
538 IN SURFOBJ
*psoSrcUMPD
,
539 IN SURFOBJ
*psoMaskUMPD
,
541 IN XLATEOBJ
*pxloUMPD
,
545 IN BRUSHOBJ
*pboUMPD
,
546 IN POINTL
*pptlBrush
,
550 POINTL ptlSrc
, ptlMask
, ptlBrush
;
551 HSURF hsurfTrg
, hsurfSrc
= NULL
, hsurfMask
= NULL
;
552 HANDLE hBrushObj
; // HUMPDOBJ
553 SURFOBJ
*psoTrg
, *psoSrc
, *psoMask
;
561 ProbeForRead(prclTrg
, sizeof(RECTL
), 1);
564 ProbeForRead(psoTrgUMPD
, sizeof(SURFOBJ
), 1);
565 hsurfTrg
= psoTrgUMPD
->hsurf
;
567 if (ROP4_USES_SOURCE(rop4
))
569 ProbeForRead(pptlSrc
, sizeof(POINTL
), 1);
572 ProbeForRead(psoSrcUMPD
, sizeof(SURFOBJ
), 1);
573 hsurfSrc
= psoSrcUMPD
->hsurf
;
576 if (ROP4_USES_MASK(rop4
))
578 ProbeForRead(pptlMask
, sizeof(POINTL
), 1);
581 ProbeForRead(psoMaskUMPD
, sizeof(SURFOBJ
), 1);
582 hsurfMask
= psoMaskUMPD
->hsurf
;
585 if (ROP4_USES_PATTERN(rop4
))
587 ProbeForRead(pptlBrush
, sizeof(POINTL
), 1);
588 ptlBrush
= *pptlBrush
;
590 ProbeForRead(psoSrcUMPD
, sizeof(SURFOBJ
), 1);
591 hBrushObj
= pboUMPD
->pvRbrush
; // FIXME
594 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
596 _SEH2_YIELD(return FALSE
);
600 // FIXME: these need to be converted/locked!
608 bResult
= EngBitBlt(psoTrg
,
614 pptlSrc
? &ptlSrc
: NULL
,
615 pptlMask
? &ptlMask
: NULL
,
617 pptlBrush
? &ptlBrush
: NULL
,
633 PFN_DrvCopyBits pfnCopyBits
;
635 /* Is the target surface device managed? */
636 if (SURFOBJ_flags(psoTrg
) & HOOK_COPYBITS
)
638 pfnCopyBits
= GDIDEVFUNCS(psoTrg
).CopyBits
;
640 if (SURFOBJ_flags(psoSrc
) & HOOK_COPYBITS
)
642 pfnCopyBits
= GDIDEVFUNCS(psoSrc
).CopyBits
;
646 /* Use SRCCOPY for 2 bitmaps */
647 return EngBitBlt(psoTrg
,
660 /* Forward to the driver */
661 return pfnCopyBits(psoTrg
, psoSrc
, pco
, pxlo
, prclTrg
, pptlSrc
);
674 return EngCopyBits(psoTrg
, psoSrc
, pco
, pxlo
, prclTrg
, pptlSrc
);