2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 /* $Id: bitmaps.c 28300 2007-08-12 15:20:09Z tkreuzer $ */
26 #define ROP_USES_SOURCE(Rop) (((((Rop) & 0xCC0000) >> 2) != ((Rop) & 0x330000)) || ((((Rop) & 0xCC000000) >> 2) != ((Rop) & 0x33000000)))
27 #define ROP_USES_MASK(Rop) (((Rop) & 0xFF000000) != (((Rop) & 0xff0000) << 8))
29 #define FIXUP_ROP(Rop) if(((Rop) & 0xFF000000) == 0) Rop = MAKEROP4((Rop), (Rop))
30 #define ROP_TO_ROP4(Rop) ((Rop) >> 16)
44 BLENDFUNCTION BlendFunc
,
51 SURFACE
*BitmapDest
, *BitmapSrc
;
52 RECTL DestRect
, SourceRect
;
56 BlendObj
.BlendFunction
= BlendFunc
;
58 if (WidthDest
< 0 || HeightDest
< 0 || WidthSrc
< 0 || HeightSrc
< 0)
60 EngSetLastError(ERROR_INVALID_PARAMETER
);
64 DPRINT("Locking DCs\n");
67 GDIOBJ_LockMultipleObjs(2, ahDC
, apObj
);
71 if ((NULL
== DCDest
) || (NULL
== DCSrc
))
73 DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hDCDest
, hDCSrc
);
74 EngSetLastError(ERROR_INVALID_HANDLE
);
75 if(DCSrc
) GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
76 if(DCDest
) GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
80 if (DCDest
->dctype
== DC_TYPE_INFO
|| DCDest
->dctype
== DCTYPE_INFO
)
82 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
83 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
84 /* Yes, Windows really returns TRUE in this case */
88 DestRect
.left
= XOriginDest
;
89 DestRect
.top
= YOriginDest
;
90 DestRect
.right
= XOriginDest
+ WidthDest
;
91 DestRect
.bottom
= YOriginDest
+ HeightDest
;
92 IntLPtoDP(DCDest
, (LPPOINT
)&DestRect
, 2);
94 DestRect
.left
+= DCDest
->ptlDCOrig
.x
;
95 DestRect
.top
+= DCDest
->ptlDCOrig
.y
;
96 DestRect
.right
+= DCDest
->ptlDCOrig
.x
;
97 DestRect
.bottom
+= DCDest
->ptlDCOrig
.y
;
99 SourceRect
.left
= XOriginSrc
;
100 SourceRect
.top
= YOriginSrc
;
101 SourceRect
.right
= XOriginSrc
+ WidthSrc
;
102 SourceRect
.bottom
= YOriginSrc
+ HeightSrc
;
103 IntLPtoDP(DCSrc
, (LPPOINT
)&SourceRect
, 2);
105 SourceRect
.left
+= DCSrc
->ptlDCOrig
.x
;
106 SourceRect
.top
+= DCSrc
->ptlDCOrig
.y
;
107 SourceRect
.right
+= DCSrc
->ptlDCOrig
.x
;
108 SourceRect
.bottom
+= DCSrc
->ptlDCOrig
.y
;
110 if (!DestRect
.right
||
115 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
116 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
120 /* Prepare DCs for blit */
121 DPRINT("Preparing DCs for blit\n");
122 DC_vPrepareDCsForBlit(DCDest
, DestRect
, DCSrc
, SourceRect
);
124 /* Determine surfaces to be used in the bitblt */
125 BitmapDest
= DCDest
->dclevel
.pSurface
;
132 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
139 /* Create the XLATEOBJ. */
140 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
142 /* Perform the alpha blend operation */
143 DPRINT("Performing the alpha Blend\n");
144 bResult
= IntEngAlphaBlend(&BitmapDest
->SurfObj
,
146 DCDest
->rosdc
.CombinedClip
,
152 EXLATEOBJ_vCleanup(&exlo
);
154 DPRINT("Finishing blit\n");
155 DC_vFinishBlit(DCDest
, DCSrc
);
156 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
157 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
173 IN DWORD crBackColor
,
176 /* Forward to NtGdiMaskBlt */
177 // TODO : what's fl for?
178 return NtGdiMaskBlt(hDCDest
,
211 SURFACE
*BitmapDest
, *BitmapSrc
= NULL
;
212 ULONG TransparentColor
= 0;
216 DPRINT("Locking DCs\n");
219 GDIOBJ_LockMultipleObjs(2, ahDC
, apObj
);
223 if ((NULL
== DCDest
) || (NULL
== DCSrc
))
225 DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hdcDst
, hdcSrc
);
226 EngSetLastError(ERROR_INVALID_HANDLE
);
227 if(DCSrc
) GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
228 if(DCDest
) GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
232 if (DCDest
->dctype
== DC_TYPE_INFO
|| DCDest
->dctype
== DCTYPE_INFO
)
234 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
235 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
236 /* Yes, Windows really returns TRUE in this case */
242 rcDest
.right
= rcDest
.left
+ cxDst
;
243 rcDest
.bottom
= rcDest
.top
+ cyDst
;
244 IntLPtoDP(DCDest
, (LPPOINT
)&rcDest
, 2);
246 rcDest
.left
+= DCDest
->ptlDCOrig
.x
;
247 rcDest
.top
+= DCDest
->ptlDCOrig
.y
;
248 rcDest
.right
+= DCDest
->ptlDCOrig
.x
;
249 rcDest
.bottom
+= DCDest
->ptlDCOrig
.y
;
253 rcSrc
.right
= rcSrc
.left
+ cxSrc
;
254 rcSrc
.bottom
= rcSrc
.top
+ cySrc
;
255 IntLPtoDP(DCSrc
, (LPPOINT
)&rcSrc
, 2);
257 rcSrc
.left
+= DCSrc
->ptlDCOrig
.x
;
258 rcSrc
.top
+= DCSrc
->ptlDCOrig
.y
;
259 rcSrc
.right
+= DCSrc
->ptlDCOrig
.x
;
260 rcSrc
.bottom
+= DCSrc
->ptlDCOrig
.y
;
262 /* Prepare for blit */
263 DC_vPrepareDCsForBlit(DCDest
, rcDest
, DCSrc
, rcSrc
);
265 BitmapDest
= DCDest
->dclevel
.pSurface
;
271 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
277 /* Translate Transparent (RGB) Color to the source palette */
278 EXLATEOBJ_vInitialize(&exlo
, &gpalRGB
, BitmapSrc
->ppal
, 0, 0, 0);
279 TransparentColor
= XLATEOBJ_iXlate(&exlo
.xlo
, (ULONG
)TransColor
);
280 EXLATEOBJ_vCleanup(&exlo
);
282 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
284 Ret
= IntEngTransparentBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
285 DCDest
->rosdc
.CombinedClip
, &exlo
.xlo
, &rcDest
, &rcSrc
,
286 TransparentColor
, 0);
288 EXLATEOBJ_vCleanup(&exlo
);
291 DC_vFinishBlit(DCDest
, DCSrc
);
292 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
293 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
312 IN DWORD crBackColor
)
318 PDC_ATTR pdcattr
= NULL
;
319 SURFACE
*BitmapDest
, *BitmapSrc
= NULL
, *psurfMask
= NULL
;
320 RECTL DestRect
, SourceRect
;
321 POINTL SourcePoint
, MaskPoint
;
324 XLATEOBJ
*XlateObj
= NULL
;
325 BOOL UsesSource
= ROP_USES_SOURCE(dwRop
);
330 UsesMask
= ROP_USES_MASK(dwRop
);
332 //DPRINT1("dwRop : 0x%08x\n", dwRop);
334 /* Take care of mask bitmap */
337 psurfMask
= SURFACE_LockSurface(hbmMask
);
340 EngSetLastError(ERROR_INVALID_HANDLE
);
349 EngSetLastError(ERROR_INVALID_PARAMETER
);
352 if(gajBitsPerFormat
[psurfMask
->SurfObj
.iBitmapFormat
] != 1)
354 EngSetLastError(ERROR_INVALID_PARAMETER
);
355 SURFACE_UnlockSurface(psurfMask
);
361 DPRINT1("Getting Mask bitmap without needing it?\n");
362 SURFACE_UnlockSurface(psurfMask
);
368 /* Take care of source and destination bitmap */
369 DPRINT("Locking DCs\n");
372 GDIOBJ_LockMultipleObjs(2, ahDC
, apObj
);
378 if(DCSrc
) DC_UnlockDc(DCSrc
);
379 DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hdcDest
);
383 if (DCDest
->dctype
== DC_TYPE_INFO
)
385 if(DCSrc
) DC_UnlockDc(DCSrc
);
387 /* Yes, Windows really returns TRUE in this case */
396 DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hdcSrc
);
399 if (DCSrc
->dctype
== DC_TYPE_INFO
)
403 /* Yes, Windows really returns TRUE in this case */
409 DPRINT("Getting a valid Source handle without using source!!!\n");
414 pdcattr
= DCDest
->pdcattr
;
416 DestRect
.left
= nXDest
;
417 DestRect
.top
= nYDest
;
418 DestRect
.right
= nXDest
+ nWidth
;
419 DestRect
.bottom
= nYDest
+ nHeight
;
420 IntLPtoDP(DCDest
, (LPPOINT
)&DestRect
, 2);
422 DestRect
.left
+= DCDest
->ptlDCOrig
.x
;
423 DestRect
.top
+= DCDest
->ptlDCOrig
.y
;
424 DestRect
.right
+= DCDest
->ptlDCOrig
.x
;
425 DestRect
.bottom
+= DCDest
->ptlDCOrig
.y
;
427 SourcePoint
.x
= nXSrc
;
428 SourcePoint
.y
= nYSrc
;
432 IntLPtoDP(DCSrc
, (LPPOINT
)&SourcePoint
, 1);
434 SourcePoint
.x
+= DCSrc
->ptlDCOrig
.x
;
435 SourcePoint
.y
+= DCSrc
->ptlDCOrig
.y
;
436 /* Calculate Source Rect */
437 SourceRect
.left
= SourcePoint
.x
;
438 SourceRect
.top
= SourcePoint
.y
;
439 SourceRect
.right
= SourcePoint
.x
+ DestRect
.right
- DestRect
.left
;
440 SourceRect
.bottom
= SourcePoint
.y
+ DestRect
.bottom
- DestRect
.top
;
444 DC_vPrepareDCsForBlit(DCDest
, DestRect
, DCSrc
, SourceRect
);
446 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
447 DC_vUpdateFillBrush(DCDest
);
449 /* Determine surfaces to be used in the bitblt */
450 BitmapDest
= DCDest
->dclevel
.pSurface
;
457 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
463 /* Create the XLATEOBJ. */
466 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
467 XlateObj
= &exlo
.xlo
;
471 /* Perform the bitblt operation */
472 Status
= IntEngBitBlt(&BitmapDest
->SurfObj
,
473 BitmapSrc
? &BitmapSrc
->SurfObj
: NULL
,
474 psurfMask
? &psurfMask
->SurfObj
: NULL
,
475 DCDest
->rosdc
.CombinedClip
,
480 &DCDest
->eboFill
.BrushObject
,
481 &DCDest
->dclevel
.pbrFill
->ptOrigin
,
485 EXLATEOBJ_vCleanup(&exlo
);
487 DC_vFinishBlit(DCDest
, DCSrc
);
493 if(psurfMask
) SURFACE_UnlockSurface(psurfMask
);
511 IN DWORD crBackColor
)
530 IN DWORD dwBackColor
,
541 SURFACE
*BitmapDest
, *BitmapSrc
= NULL
;
542 SURFACE
*BitmapMask
= NULL
;
548 XLATEOBJ
*XlateObj
= NULL
;
550 BOOL UsesSource
= ROP_USES_SOURCE(ROP
);
554 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
556 EngSetLastError(ERROR_INVALID_PARAMETER
);
560 DPRINT("Locking DCs\n");
564 GDIOBJ_LockMultipleObjs(3, ahDC
, apObj
);
571 if(DCSrc
) GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
572 if(DCMask
) GDIOBJ_UnlockObjByPtr(&DCMask
->BaseObject
);
573 DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest
);
577 if (DCDest
->dctype
== DC_TYPE_INFO
)
579 if(DCSrc
) GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
580 if(DCMask
) GDIOBJ_UnlockObjByPtr(&DCMask
->BaseObject
);
581 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
582 /* Yes, Windows really returns TRUE in this case */
590 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
591 if(DCMask
) GDIOBJ_UnlockObjByPtr(&DCMask
->BaseObject
);
592 DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc
);
595 if (DCSrc
->dctype
== DC_TYPE_INFO
)
597 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
598 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
599 if(DCMask
) GDIOBJ_UnlockObjByPtr(&DCMask
->BaseObject
);
600 /* Yes, Windows really returns TRUE in this case */
606 DPRINT1("Getting a valid Source handle without using source!!!\n");
607 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
611 pdcattr
= DCDest
->pdcattr
;
613 DestRect
.left
= XOriginDest
;
614 DestRect
.top
= YOriginDest
;
615 DestRect
.right
= XOriginDest
+WidthDest
;
616 DestRect
.bottom
= YOriginDest
+HeightDest
;
617 IntLPtoDP(DCDest
, (LPPOINT
)&DestRect
, 2);
619 DestRect
.left
+= DCDest
->ptlDCOrig
.x
;
620 DestRect
.top
+= DCDest
->ptlDCOrig
.y
;
621 DestRect
.right
+= DCDest
->ptlDCOrig
.x
;
622 DestRect
.bottom
+= DCDest
->ptlDCOrig
.y
;
624 SourceRect
.left
= XOriginSrc
;
625 SourceRect
.top
= YOriginSrc
;
626 SourceRect
.right
= XOriginSrc
+WidthSrc
;
627 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
631 IntLPtoDP(DCSrc
, (LPPOINT
)&SourceRect
, 2);
633 SourceRect
.left
+= DCSrc
->ptlDCOrig
.x
;
634 SourceRect
.top
+= DCSrc
->ptlDCOrig
.y
;
635 SourceRect
.right
+= DCSrc
->ptlDCOrig
.x
;
636 SourceRect
.bottom
+= DCSrc
->ptlDCOrig
.y
;
642 /* Only prepare Source and Dest, hdcMask represents a DIB */
643 DC_vPrepareDCsForBlit(DCDest
, DestRect
, DCSrc
, SourceRect
);
645 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
646 DC_vUpdateFillBrush(DCDest
);
648 /* Determine surfaces to be used in the bitblt */
649 BitmapDest
= DCDest
->dclevel
.pSurface
;
650 if (BitmapDest
== NULL
)
654 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
655 if (BitmapSrc
== NULL
)
658 /* Create the XLATEOBJ. */
659 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
660 XlateObj
= &exlo
.xlo
;
663 /* Offset the brush */
664 BrushOrigin
.x
+= DCDest
->ptlDCOrig
.x
;
665 BrushOrigin
.y
+= DCDest
->ptlDCOrig
.y
;
667 /* Make mask surface for source surface */
668 if (BitmapSrc
&& DCMask
)
670 BitmapMask
= DCMask
->dclevel
.pSurface
;
672 (BitmapMask
->SurfObj
.sizlBitmap
.cx
< WidthSrc
||
673 BitmapMask
->SurfObj
.sizlBitmap
.cy
< HeightSrc
))
675 DPRINT1("%dx%d mask is smaller than %dx%d bitmap\n",
676 BitmapMask
->SurfObj
.sizlBitmap
.cx
, BitmapMask
->SurfObj
.sizlBitmap
.cy
,
677 WidthSrc
, HeightSrc
);
678 EXLATEOBJ_vCleanup(&exlo
);
681 /* Create mask offset point */
682 MaskPoint
.x
= XOriginMask
;
683 MaskPoint
.y
= YOriginMask
;
684 IntLPtoDP(DCMask
, &MaskPoint
, 1);
685 MaskPoint
.x
+= DCMask
->ptlDCOrig
.x
;
686 MaskPoint
.y
+= DCMask
->ptlDCOrig
.x
;
689 /* Perform the bitblt operation */
690 Status
= IntEngStretchBlt(&BitmapDest
->SurfObj
,
692 BitmapMask
? &BitmapMask
->SurfObj
: NULL
,
693 DCDest
->rosdc
.CombinedClip
,
697 BitmapMask
? &MaskPoint
: NULL
,
698 &DCDest
->eboFill
.BrushObject
,
703 EXLATEOBJ_vCleanup(&exlo
);
707 DC_vFinishBlit(DCDest
, DCSrc
);
735 IN DWORD dwBackColor
)
737 return GreStretchBltMask(
776 if (pbrush
->flAttrs
& GDIBRUSH_IS_NULL
)
783 DestRect
.left
= XLeft
;
784 DestRect
.right
= XLeft
+ Width
;
788 DestRect
.left
= XLeft
+ Width
+ 1;
789 DestRect
.right
= XLeft
+ 1;
794 DestRect
.top
= YLeft
;
795 DestRect
.bottom
= YLeft
+ Height
;
799 DestRect
.top
= YLeft
+ Height
+ 1;
800 DestRect
.bottom
= YLeft
+ 1;
803 IntLPtoDP(pdc
, (LPPOINT
)&DestRect
, 2);
805 DestRect
.left
+= pdc
->ptlDCOrig
.x
;
806 DestRect
.top
+= pdc
->ptlDCOrig
.y
;
807 DestRect
.right
+= pdc
->ptlDCOrig
.x
;
808 DestRect
.bottom
+= pdc
->ptlDCOrig
.y
;
810 BrushOrigin
.x
= pbrush
->ptOrigin
.x
+ pdc
->ptlDCOrig
.x
;
811 BrushOrigin
.y
= pbrush
->ptOrigin
.y
+ pdc
->ptlDCOrig
.y
;
813 DC_vPrepareDCsForBlit(pdc
, DestRect
, NULL
, DestRect
);
815 psurf
= pdc
->dclevel
.pSurface
;
817 if (pdc
->pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
818 DC_vUpdateFillBrush(pdc
);
820 EBRUSHOBJ_vInit(&eboFill
, pbrush
, pdc
);
826 pdc
->rosdc
.CombinedClip
,
831 &eboFill
.BrushObject
,
835 DC_vFinishBlit(pdc
, NULL
);
837 EBRUSHOBJ_vCleanup(&eboFill
);
854 pdc
= DC_LockDc(hDC
);
857 EngSetLastError(ERROR_INVALID_HANDLE
);
861 if (pdc
->dctype
== DC_TYPE_INFO
)
864 /* Yes, Windows really returns TRUE in this case */
868 for (i
= 0; i
< cRects
; i
++)
870 pbrush
= BRUSH_LockBrush(pRects
->hBrush
);
881 BRUSH_UnlockBrush(pbrush
);
906 BOOL UsesSource
= ROP_USES_SOURCE(ROP
);
909 /* in this case we call on GdiMaskBlt */
910 return NtGdiMaskBlt(hDC
, XLeft
, YLeft
, Width
, Height
, 0,0,0,0,0,0,ROP
,0);
916 EngSetLastError(ERROR_INVALID_HANDLE
);
919 if (dc
->dctype
== DC_TYPE_INFO
)
922 /* Yes, Windows really returns TRUE in this case */
926 pdcattr
= dc
->pdcattr
;
928 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
929 DC_vUpdateFillBrush(dc
);
931 pbrush
= BRUSH_LockBrush(pdcattr
->hbrush
);
934 EngSetLastError(ERROR_INVALID_HANDLE
);
939 ret
= IntPatBlt(dc
, XLeft
, YLeft
, Width
, Height
, ROP
, pbrush
);
941 BRUSH_UnlockBrush(pbrush
);
951 IN PPOLYPATBLT pRects
,
956 NTSTATUS Status
= STATUS_SUCCESS
;
961 rb
= ExAllocatePoolWithTag(PagedPool
, sizeof(PATRECT
) * cRects
, GDITAG_PLGBLT_DATA
);
964 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
970 cRects
* sizeof(PATRECT
),
974 cRects
* sizeof(PATRECT
));
976 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
978 Status
= _SEH2_GetExceptionCode();
982 if (!NT_SUCCESS(Status
))
984 ExFreePoolWithTag(rb
, GDITAG_PLGBLT_DATA
);
985 SetLastNtError(Status
);
990 Ret
= IntGdiPolyPatBlt(hDC
, dwRop
, rb
, cRects
, Mode
);
993 ExFreePoolWithTag(rb
, GDITAG_PLGBLT_DATA
);