- merge r47350, slightly modified to get it the yarotows way

svn path=/branches/reactos-yarotows/; revision=47366
This commit is contained in:
Jérôme Gardou 2010-05-26 22:29:45 +00:00
parent a37321ad04
commit 5ba3469f7b
3 changed files with 107 additions and 144 deletions

View file

@ -122,10 +122,15 @@ IntGdiPolyPolygon(DC *dc,
PULONG PolyCounts, PULONG PolyCounts,
int Count); int Count);
BOOL FASTCALL IntGdiGradientFill(DC *dc, BOOL
NTAPI
GreGradientFill(
HDC hdc,
PTRIVERTEX pVertex, PTRIVERTEX pVertex,
ULONG uVertex, ULONG nVertex,
PVOID pMesh, ULONG uMesh, ULONG ulMode); PVOID pMesh,
ULONG nMesh,
ULONG ulMode);
/* DC functions */ /* DC functions */

View file

@ -1782,7 +1782,6 @@ BOOL UserDrawCaption(
static GRADIENT_RECT gcap = {0, 1}; static GRADIENT_RECT gcap = {0, 1};
TRIVERTEX vert[2]; TRIVERTEX vert[2];
COLORREF Colors[2]; COLORREF Colors[2];
PDC pMemDc;
if (Wnd != NULL) if (Wnd != NULL)
{ {
@ -1835,21 +1834,12 @@ BOOL UserDrawCaption(
vert[1].Blue = (WORD)(Colors[1]>>8) & 0xFF00; vert[1].Blue = (WORD)(Colors[1]>>8) & 0xFF00;
vert[1].Alpha = 0; vert[1].Alpha = 0;
pMemDc = DC_LockDc(hMemDc); if(!GreGradientFill(hMemDc, vert, 2, &gcap,
if(!pMemDc)
{
DPRINT1("%s: Can't lock dc!\n", __FUNCTION__);
goto cleanup;
}
/* There is no need to call DC_vPrepareDCsForBlit for memory DC */
if(!IntGdiGradientFill(pMemDc, vert, 2, &gcap,
1, GRADIENT_FILL_RECT_H)) 1, GRADIENT_FILL_RECT_H))
{ {
DPRINT1("%s: IntGdiGradientFill() failed!\n", __FUNCTION__); DPRINT1("%s: IntGdiGradientFill() failed!\n", __FUNCTION__);
} }
DC_UnlockDc(pMemDc);
} //if(uFlags & DC_GRADIENT) } //if(uFlags & DC_GRADIENT)
} }

View file

@ -856,39 +856,34 @@ NtGdiRoundRect(
return ret; return ret;
} }
BOOL FASTCALL BOOL
IntGdiGradientFill( NTAPI
DC *dc, GreGradientFill(
HDC hdc,
PTRIVERTEX pVertex, PTRIVERTEX pVertex,
ULONG uVertex, ULONG nVertex,
PVOID pMesh, PVOID pMesh,
ULONG uMesh, ULONG nMesh,
ULONG ulMode) ULONG ulMode)
{ {
PDC pdc;
SURFACE *psurf; SURFACE *psurf;
PPALETTE PalDestGDI;
EXLATEOBJ exlo; EXLATEOBJ exlo;
RECTL Extent; RECTL rclExtent;
POINTL DitherOrg; POINTL ptlDitherOrg;
ULONG i; ULONG i;
BOOL Ret; BOOL bRet;
ASSERT(dc);
ASSERT(pVertex);
ASSERT(uVertex);
ASSERT(pMesh);
ASSERT(uMesh);
/* check parameters */ /* check parameters */
if (ulMode & GRADIENT_FILL_TRIANGLE) if (ulMode & GRADIENT_FILL_TRIANGLE)
{ {
PGRADIENT_TRIANGLE tr = (PGRADIENT_TRIANGLE)pMesh; PGRADIENT_TRIANGLE pTriangle = (PGRADIENT_TRIANGLE)pMesh;
for (i = 0; i < uMesh; i++, tr++) for (i = 0; i < nMesh; i++, pTriangle++)
{ {
if (tr->Vertex1 >= uVertex || if (pTriangle->Vertex1 >= nVertex ||
tr->Vertex2 >= uVertex || pTriangle->Vertex2 >= nVertex ||
tr->Vertex3 >= uVertex) pTriangle->Vertex3 >= nVertex)
{ {
SetLastWin32Error(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE; return FALSE;
@ -897,10 +892,10 @@ IntGdiGradientFill(
} }
else else
{ {
PGRADIENT_RECT rc = (PGRADIENT_RECT)pMesh; PGRADIENT_RECT pRect = (PGRADIENT_RECT)pMesh;
for (i = 0; i < uMesh; i++, rc++) for (i = 0; i < nMesh; i++, pRect++)
{ {
if (rc->UpperLeft >= uVertex || rc->LowerRight >= uVertex) if (pRect->UpperLeft >= nVertex || pRect->LowerRight >= nVertex)
{ {
SetLastWin32Error(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE; return FALSE;
@ -908,61 +903,74 @@ IntGdiGradientFill(
} }
} }
/* Lock the output DC */
pdc = DC_LockDc(hdc);
if(!pdc)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
if(pdc->dctype == DC_TYPE_INFO)
{
DC_UnlockDc(pdc);
/* Yes, Windows really returns TRUE in this case */
return TRUE;
}
psurf = pdc->dclevel.pSurface;
if(!psurf)
{
/* Memory DC with no surface selected */
DC_UnlockDc(pdc);
return TRUE; //CHECKME
}
/* calculate extent */ /* calculate extent */
Extent.left = Extent.right = pVertex->x; rclExtent.left = rclExtent.right = pVertex->x;
Extent.top = Extent.bottom = pVertex->y; rclExtent.top = rclExtent.bottom = pVertex->y;
for (i = 0; i < uVertex; i++) for (i = 0; i < nVertex; i++)
{ {
Extent.left = min(Extent.left, (pVertex + i)->x); rclExtent.left = min(rclExtent.left, (pVertex + i)->x);
Extent.right = max(Extent.right, (pVertex + i)->x); rclExtent.right = max(rclExtent.right, (pVertex + i)->x);
Extent.top = min(Extent.top, (pVertex + i)->y); rclExtent.top = min(rclExtent.top, (pVertex + i)->y);
Extent.bottom = max(Extent.bottom, (pVertex + i)->y); rclExtent.bottom = max(rclExtent.bottom, (pVertex + i)->y);
} }
IntLPtoDP(dc, (LPPOINT)&Extent, 2); IntLPtoDP(pdc, (LPPOINT)&rclExtent, 2);
Extent.left += dc->ptlDCOrig.x; rclExtent.left += pdc->ptlDCOrig.x;
Extent.right += dc->ptlDCOrig.x; rclExtent.right += pdc->ptlDCOrig.x;
Extent.top += dc->ptlDCOrig.y; rclExtent.top += pdc->ptlDCOrig.y;
Extent.bottom += dc->ptlDCOrig.y; rclExtent.bottom += pdc->ptlDCOrig.y;
DitherOrg.x = DitherOrg.y = 0; ptlDitherOrg.x = ptlDitherOrg.y = 0;
IntLPtoDP(dc, (LPPOINT)&DitherOrg, 1); IntLPtoDP(pdc, (LPPOINT)&ptlDitherOrg, 1);
DitherOrg.x += dc->ptlDCOrig.x; ptlDitherOrg.x += pdc->ptlDCOrig.x;
DitherOrg.y += dc->ptlDCOrig.y; ptlDitherOrg.y += pdc->ptlDCOrig.y;
psurf = dc->dclevel.pSurface; EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0, 0);
/* FIXME - psurf can be NULL!!! Don't assert but handle this case gracefully! */
ASSERT(psurf);
if (psurf->ppal) ASSERT(pdc->rosdc.CombinedClip);
{
PalDestGDI = psurf->ppal;
GDIOBJ_IncrementShareCount(&PalDestGDI->BaseObject);
}
else
// Destination palette obtained from the hDC
PalDestGDI = PALETTE_ShareLockPalette(dc->ppdev->devinfo.hpalDefault);
EXLATEOBJ_vInitialize(&exlo, &gpalRGB, PalDestGDI, 0, 0, 0); DC_vPrepareDCsForBlit(pdc, rclExtent, NULL, rclExtent);
Ret = IntEngGradientFill(&psurf->SurfObj, bRet = IntEngGradientFill(&psurf->SurfObj,
dc->rosdc.CombinedClip, pdc->rosdc.CombinedClip,
&exlo.xlo, &exlo.xlo,
pVertex, pVertex,
uVertex, nVertex,
pMesh, pMesh,
uMesh, nMesh,
&Extent, &rclExtent,
&DitherOrg, &ptlDitherOrg,
ulMode); ulMode);
EXLATEOBJ_vCleanup(&exlo); EXLATEOBJ_vCleanup(&exlo);
DC_vFinishBlit(pdc, NULL);
DC_UnlockDc(pdc);
if (PalDestGDI) return bRet;
PALETTE_ShareUnlockPalette(PalDestGDI);
return Ret;
} }
BOOL BOOL
@ -970,33 +978,19 @@ APIENTRY
NtGdiGradientFill( NtGdiGradientFill(
HDC hdc, HDC hdc,
PTRIVERTEX pVertex, PTRIVERTEX pVertex,
ULONG uVertex, ULONG nVertex,
PVOID pMesh, PVOID pMesh,
ULONG uMesh, ULONG nMesh,
ULONG ulMode) ULONG ulMode)
{ {
DC *dc; BOOL bRet;
BOOL Ret;
PTRIVERTEX SafeVertex; PTRIVERTEX SafeVertex;
PVOID SafeMesh; PVOID SafeMesh;
ULONG SizeMesh; ULONG cbVertex, cbMesh;
NTSTATUS Status = STATUS_SUCCESS;
dc = DC_LockDc(hdc); /* Validate parameters */
if (!dc) if (!pVertex || !nVertex || !pMesh || !nMesh)
{ {
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
if (dc->dctype == DC_TYPE_INFO)
{
DC_UnlockDc(dc);
/* Yes, Windows really returns TRUE in this case */
return TRUE;
}
if (!pVertex || !uVertex || !pMesh || !uMesh)
{
DC_UnlockDc(dc);
SetLastWin32Error(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE; return FALSE;
} }
@ -1005,81 +999,55 @@ NtGdiGradientFill(
{ {
case GRADIENT_FILL_RECT_H: case GRADIENT_FILL_RECT_H:
case GRADIENT_FILL_RECT_V: case GRADIENT_FILL_RECT_V:
SizeMesh = uMesh * sizeof(GRADIENT_RECT); cbMesh = nMesh * sizeof(GRADIENT_RECT);
break; break;
case GRADIENT_FILL_TRIANGLE: case GRADIENT_FILL_TRIANGLE:
SizeMesh = uMesh * sizeof(TRIVERTEX); cbMesh = nMesh * sizeof(GRADIENT_TRIANGLE);
break; break;
default: default:
DC_UnlockDc(dc);
SetLastWin32Error(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE; return FALSE;
} }
_SEH2_TRY cbVertex = nVertex * sizeof(TRIVERTEX) ;
if(cbVertex + cbMesh <= cbVertex)
{ {
ProbeForRead(pVertex, /* Overflow */
uVertex * sizeof(TRIVERTEX), return FALSE ;
1);
ProbeForRead(pMesh,
SizeMesh,
1);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
if (!NT_SUCCESS(Status))
{
DC_UnlockDc(dc);
SetLastWin32Error(Status);
return FALSE;
} }
if (!(SafeVertex = ExAllocatePoolWithTag(PagedPool, (uVertex * sizeof(TRIVERTEX)) + SizeMesh, TAG_SHAPE))) /* Allocate a kernel mode buffer */
SafeVertex = ExAllocatePoolWithTag(PagedPool, cbVertex + cbMesh, TAG_SHAPE);
if(!SafeVertex)
{ {
DC_UnlockDc(dc);
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return FALSE; return FALSE;
} }
SafeMesh = (PTRIVERTEX)(SafeVertex + uVertex); SafeMesh = (PVOID)((ULONG_PTR)SafeVertex + cbVertex);
/* Copy the parameters to kernel mode */
_SEH2_TRY _SEH2_TRY
{ {
/* pointers were already probed! */ ProbeForRead(pVertex, cbVertex, 1);
RtlCopyMemory(SafeVertex, ProbeForRead(pMesh, cbMesh, 1);
pVertex, RtlCopyMemory(SafeVertex, pVertex, cbVertex);
uVertex * sizeof(TRIVERTEX)); RtlCopyMemory(SafeMesh, pMesh, cbMesh);
RtlCopyMemory(SafeMesh,
pMesh,
SizeMesh);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
Status = _SEH2_GetExceptionCode(); ExFreePoolWithTag(SafeVertex, TAG_SHAPE);
SetLastNtError(_SEH2_GetExceptionCode());
_SEH2_YIELD(return FALSE;)
} }
_SEH2_END; _SEH2_END;
if (!NT_SUCCESS(Status)) /* Call the internal function */
{ bRet = GreGradientFill(hdc, SafeVertex, nVertex, SafeMesh, nMesh, ulMode);
DC_UnlockDc(dc);
ExFreePoolWithTag(SafeVertex, TAG_SHAPE);
SetLastNtError(Status);
return FALSE;
}
DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds, /* Cleanup and return result */
NULL, dc->rosdc.CombinedClip->rclBounds); ExFreePoolWithTag(SafeVertex, TAG_SHAPE);
return bRet;
Ret = IntGdiGradientFill(dc, SafeVertex, uVertex, SafeMesh, uMesh, ulMode);
DC_vFinishBlit(dc, NULL) ;
DC_UnlockDc(dc);
ExFreePool(SafeVertex);
return Ret;
} }
BOOL APIENTRY BOOL APIENTRY