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 NT_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
))
258 /* Check if we don't have a mask surface */
261 /* Must have a brush */
262 NT_ASSERT(pbo
); // FIXME: test this!
264 /* Check if the BRUSHOBJ can provide the mask */
265 psoMask
= BRUSHOBJ_psoMask(pbo
);
268 /* We have no mask, assume the mask is all foreground */
269 rop4
= (rop4
& 0xFF) || ((rop4
& 0xFF) << 8);
273 /* Set the mask format info */
274 bltdata
.siMsk
.iFormat
= psoMask
->iBitmapFormat
;
275 bltdata
.siMsk
.pvScan0
= psoMask
->pvScan0
;
276 bltdata
.siMsk
.lDelta
= psoMask
->lDelta
;
277 bltdata
.siMsk
.cjAdvanceY
= bltdata
.dy
* psoMask
->lDelta
;
278 bltdata
.siMsk
.jBpp
= 1;
280 /* Calculate the masking function index */
281 iFunctionIndex
= ROP4_USES_PATTERN(rop4
) ? 1 : 0;
282 iFunctionIndex
|= ROP4_USES_SOURCE(rop4
) ? 2 : 0;
283 iFunctionIndex
|= ROP4_USES_DEST(rop4
) ? 4 : 0;
285 /* Get the masking function */
286 pfnBitBlt
= gapfnMaskFunction
[iFunctionIndex
];
290 /* Get the function index from the foreground ROP index*/
291 iFunctionIndex
= gajIndexPerRop
[ROP4_FGND(rop4
)];
293 /* Get the dib function */
294 pfnBitBlt
= gapfnDibFunction
[iFunctionIndex
];
297 /* If no clip object is given, use trivial one */
298 if (!pco
) pco
= (CLIPOBJ
*)&gxcoTrivial
;
300 /* Check if we need to enumerate rects */
301 if (pco
->iDComplexity
== DC_COMPLEX
)
303 /* Start the enumeration of the clip object */
304 CLIPOBJ_cEnumStart(pco
, FALSE
, CT_RECTANGLES
, iDirection
, 0);
305 bEnumMore
= CLIPOBJ_bEnum(pco
, sizeof(rcenum
), (ULONG
*)&rcenum
);
307 else if (pco
->iDComplexity
== DC_RECT
)
309 /* Use the clip bounds */
310 rcenum
.arcl
[0] = pco
->rclBounds
;
316 /* Use the target rect */
317 rcenum
.arcl
[0] = rcTrg
;
322 /* Enter enumeration loop */
325 /* Loop all rectangles we got */
326 for (i
= 0; i
< rcenum
.c
; i
++)
328 /* Intersect this rect with the target rect */
329 if (!RECTL_bIntersectRect(&rcenum
.arcl
[i
], &rcenum
.arcl
[i
], &rcTrg
))
331 /* This rect is outside the bounds, continue */
335 /* Calculate coordinates and pointers */
336 CalculateCoordinates(&bltdata
,
344 /* Call the dib function */
348 /* Bail out, when there's nothing more to do */
349 if(!bEnumMore
) break;
351 /* Enumerate more rectangles */
352 bEnumMore
= CLIPOBJ_bEnum(pco
, sizeof(rcenum
), (ULONG
*)&rcenum
);
362 _Out_ PPOINTL pptOffset
,
363 _Out_ PSIZEL psizTrg
,
364 _In_ PPOINTL pptlSrc
,
367 LONG x
, y
, cxMax
, cyMax
;
369 x
= pptlSrc
->x
+ pptOffset
->x
;
370 if (x
< 0) pptOffset
->x
-= x
, x
= 0;
372 cxMax
= psizSrc
->cx
- x
;
373 if (psizTrg
->cx
> cxMax
) psizTrg
->cx
= cxMax
;
375 y
= pptlSrc
->y
+ pptOffset
->y
;
376 if (y
< 0) pptOffset
->y
-= y
, y
= 0;
378 cyMax
= psizSrc
->cy
- y
;
379 if (psizTrg
->cy
> cyMax
) psizTrg
->cy
= cyMax
;
385 _Inout_ SURFOBJ
*psoTrg
,
386 _In_opt_ SURFOBJ
*psoSrc
,
387 _In_opt_ SURFOBJ
*psoMask
,
388 _In_opt_ CLIPOBJ
*pco
,
389 _In_opt_ XLATEOBJ
*pxlo
,
391 _When_(psoSrc
, _In_
) POINTL
*pptlSrc
,
392 _When_(psoMask
, _In_
) POINTL
*pptlMask
,
393 _In_opt_ BRUSHOBJ
*pbo
,
394 _When_(pbo
, _In_
) POINTL
*pptlBrush
,
399 POINTL ptOffset
, ptSrc
, ptMask
, ptBrush
;
401 PFN_DrvBitBlt pfnBitBlt
;
406 ASSERT(IS_VALID_ROP4(rop4
));
408 ASSERT(psoTrg
->iBitmapFormat
>= BMF_1BPP
);
409 ASSERT(psoTrg
->iBitmapFormat
<= BMF_32BPP
);
412 /* Clip the target rect to the extents of the target surface */
413 if (!RECTL_bClipRectBySize(&rcClipped
, prclTrg
, &psoTrg
->sizlBitmap
))
419 /* If no clip object is given, use trivial one */
420 if (!pco
) pco
= (CLIPOBJ
*)&gxcoTrivial
;
422 /* Check if there is something to clip */
423 if (pco
->iDComplexity
!= DC_TRIVIAL
)
425 /* Clip the target rect to the bounds of the clipping region */
426 if (!RECTL_bIntersectRect(&rcClipped
, &rcClipped
, &pco
->rclBounds
))
433 /* Don't pass a clip object with a single rectangle */
434 if (pco
->iDComplexity
== DC_RECT
) pco
= (CLIPOBJ
*)&gxcoTrivial
;
436 /* Calculate initial offset and size */
437 ptOffset
.x
= rcClipped
.left
- prclTrg
->left
;
438 ptOffset
.y
= rcClipped
.top
- prclTrg
->top
;
439 sizTrg
.cx
= rcClipped
.right
- rcClipped
.left
;
440 sizTrg
.cy
= rcClipped
.bottom
- rcClipped
.top
;
442 /* Check if the ROP uses a source */
443 if (ROP4_USES_SOURCE(rop4
))
445 /* Must have a source surface and point */
449 /* Get the source point */
452 /* Clip against the extents of the source surface */
453 AdjustOffsetAndSize(&ptOffset
, &sizTrg
, &ptSrc
, &psoSrc
->sizlBitmap
);
462 /* Check if the ROP uses a mask */
463 if (ROP4_USES_MASK(rop4
))
465 /* Must have a mask surface and point */
469 /* Get the mask point */
472 /* Clip against the extents of the mask surface */
473 AdjustOffsetAndSize(&ptOffset
, &sizTrg
, &ptMask
, &psoMask
->sizlBitmap
);
482 /* Check if all has been clipped away */
483 if ((sizTrg
.cx
<= 0) || (sizTrg
.cy
<= 0))
486 /* Adjust the points */
487 ptSrc
.x
+= ptOffset
.x
;
488 ptSrc
.y
+= ptOffset
.y
;
489 ptMask
.x
+= ptOffset
.x
;
490 ptMask
.y
+= ptOffset
.y
;
492 /* Check if we have a brush origin */
495 /* calculate the new brush origin */
496 ptBrush
.x
= pptlBrush
->x
+ ptOffset
.x
;
497 ptBrush
.y
= pptlBrush
->y
+ ptOffset
.y
;
500 /* Recalculate the target rect */
501 rcClipped
.left
= prclTrg
->left
+ ptOffset
.x
;
502 rcClipped
.top
= prclTrg
->top
+ ptOffset
.y
;
503 rcClipped
.right
= rcClipped
.left
+ sizTrg
.cx
;
504 rcClipped
.bottom
= rcClipped
.top
+ sizTrg
.cy
;
506 /* Is the target surface device managed? */
507 if (SURFOBJ_flags(psoTrg
) & HOOK_BITBLT
)
509 /* Is the source a different device managed surface? */
510 if (psoSrc
&& (psoSrc
->hdev
!= psoTrg
->hdev
) &&
511 (SURFOBJ_flags(psoSrc
) & HOOK_BITBLT
))
513 ERR("Need to copy to standard bitmap format!\n");
517 pfnBitBlt
= GDIDEVFUNCS(psoTrg
).BitBlt
;
519 /* Otherwise is the source surface device managed? */
520 else if (psoSrc
&& (SURFOBJ_flags(psoSrc
) & HOOK_BITBLT
))
522 pfnBitBlt
= GDIDEVFUNCS(psoSrc
).BitBlt
;
526 pfnBitBlt
= EngBitBlt
;
529 bResult
= pfnBitBlt(psoTrg
,
535 psoSrc
? &ptSrc
: NULL
,
536 psoMask
? &ptMask
: NULL
,
538 pptlBrush
? &ptBrush
: NULL
,
541 // FIXME: cleanup temp surface!
549 IN SURFOBJ
*psoTrgUMPD
,
550 IN SURFOBJ
*psoSrcUMPD
,
551 IN SURFOBJ
*psoMaskUMPD
,
553 IN XLATEOBJ
*pxloUMPD
,
557 IN BRUSHOBJ
*pboUMPD
,
558 IN POINTL
*pptlBrush
,
562 POINTL ptlSrc
, ptlMask
, ptlBrush
;
563 HSURF hsurfTrg
, hsurfSrc
= NULL
, hsurfMask
= NULL
;
564 HANDLE hBrushObj
; // HUMPDOBJ
565 SURFOBJ
*psoTrg
, *psoSrc
, *psoMask
;
573 ProbeForRead(prclTrg
, sizeof(RECTL
), 1);
576 ProbeForRead(psoTrgUMPD
, sizeof(SURFOBJ
), 1);
577 hsurfTrg
= psoTrgUMPD
->hsurf
;
579 if (ROP4_USES_SOURCE(rop4
))
581 ProbeForRead(pptlSrc
, sizeof(POINTL
), 1);
584 ProbeForRead(psoSrcUMPD
, sizeof(SURFOBJ
), 1);
585 hsurfSrc
= psoSrcUMPD
->hsurf
;
588 if (ROP4_USES_MASK(rop4
))
590 ProbeForRead(pptlMask
, sizeof(POINTL
), 1);
593 ProbeForRead(psoMaskUMPD
, sizeof(SURFOBJ
), 1);
594 hsurfMask
= psoMaskUMPD
->hsurf
;
597 if (ROP4_USES_PATTERN(rop4
))
599 ProbeForRead(pptlBrush
, sizeof(POINTL
), 1);
600 ptlBrush
= *pptlBrush
;
602 ProbeForRead(psoSrcUMPD
, sizeof(SURFOBJ
), 1);
603 hBrushObj
= pboUMPD
->pvRbrush
; // FIXME
606 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
608 _SEH2_YIELD(return FALSE
);
612 // FIXME: these need to be converted/locked!
620 bResult
= EngBitBlt(psoTrg
,
626 pptlSrc
? &ptlSrc
: NULL
,
627 pptlMask
? &ptlMask
: NULL
,
629 pptlBrush
? &ptlBrush
: NULL
,
645 PFN_DrvCopyBits pfnCopyBits
;
647 /* Is the target surface device managed? */
648 if (SURFOBJ_flags(psoTrg
) & HOOK_COPYBITS
)
650 pfnCopyBits
= GDIDEVFUNCS(psoTrg
).CopyBits
;
652 if (SURFOBJ_flags(psoSrc
) & HOOK_COPYBITS
)
654 pfnCopyBits
= GDIDEVFUNCS(psoSrc
).CopyBits
;
658 /* Use SRCCOPY for 2 bitmaps */
659 return EngBitBlt(psoTrg
,
672 /* Forward to the driver */
673 return pfnCopyBits(psoTrg
, psoSrc
, pco
, pxlo
, prclTrg
, pptlSrc
);
686 return EngCopyBits(psoTrg
, psoSrc
, pco
, pxlo
, prclTrg
, pptlSrc
);