reactos/win32ss/gdi/ntgdi/dcutil.c
David Quintana 34a27346de Sync with trunk r63786.
svn path=/branches/shell-experiments/; revision=63788
2014-07-31 00:57:14 +00:00

778 lines
17 KiB
C

#include <win32k.h>
#define NDEBUG
#include <debug.h>
BOOL FASTCALL
GreDPtoLP(HDC hdc, LPPOINT lpPoints, INT nCount)
{
PDC dc;
if (!(dc = DC_LockDc(hdc)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
IntDPtoLP(dc, lpPoints, nCount);
DC_UnlockDc(dc);
return TRUE;
}
BOOL FASTCALL
GreLPtoDP(HDC hdc, LPPOINT lpPoints, INT nCount)
{
PDC dc;
if (!(dc = DC_LockDc(hdc)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
IntLPtoDP(dc, lpPoints, nCount);
DC_UnlockDc(dc);
return TRUE;
}
int FASTCALL
GreGetBkMode(HDC hdc)
{
PDC dc;
LONG lBkMode;
if (!(dc = DC_LockDc(hdc)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return CLR_INVALID;
}
lBkMode = dc->pdcattr->lBkMode;
DC_UnlockDc(dc);
return lBkMode;
}
int FASTCALL
GreGetMapMode(HDC hdc)
{
PDC dc;
INT iMapMode;
if (!(dc = DC_LockDc(hdc)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return CLR_INVALID;
}
iMapMode = dc->pdcattr->iMapMode;
DC_UnlockDc(dc);
return iMapMode;
}
COLORREF FASTCALL
GreGetTextColor(HDC hdc)
{
PDC dc;
ULONG ulForegroundClr;
if (!(dc = DC_LockDc(hdc)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return CLR_INVALID;
}
ulForegroundClr = dc->pdcattr->ulForegroundClr;
DC_UnlockDc(dc);
return ulForegroundClr;
}
COLORREF FASTCALL
IntGdiSetBkColor(HDC hDC, COLORREF color)
{
COLORREF oldColor;
PDC dc;
PDC_ATTR pdcattr;
HBRUSH hBrush;
if (!(dc = DC_LockDc(hDC)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return CLR_INVALID;
}
pdcattr = dc->pdcattr;
oldColor = pdcattr->crBackgroundClr;
pdcattr->crBackgroundClr = color;
pdcattr->ulBackgroundClr = (ULONG)color;
pdcattr->ulDirty_ |= DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_FILL; // Clear Flag if set.
hBrush = pdcattr->hbrush;
DC_UnlockDc(dc);
NtGdiSelectBrush(hDC, hBrush);
return oldColor;
}
INT FASTCALL
IntGdiSetBkMode(HDC hDC, INT Mode)
{
COLORREF oldMode;
PDC dc;
PDC_ATTR pdcattr;
if (!(dc = DC_LockDc(hDC)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return CLR_INVALID;
}
pdcattr = dc->pdcattr;
oldMode = pdcattr->lBkMode;
pdcattr->jBkMode = Mode;
pdcattr->lBkMode = Mode;
DC_UnlockDc(dc);
return oldMode;
}
UINT
FASTCALL
IntGdiSetTextAlign(HDC hDC,
UINT Mode)
{
UINT prevAlign;
DC *dc;
PDC_ATTR pdcattr;
dc = DC_LockDc(hDC);
if (!dc)
{
EngSetLastError(ERROR_INVALID_HANDLE);
return GDI_ERROR;
}
pdcattr = dc->pdcattr;
prevAlign = pdcattr->lTextAlign;
pdcattr->lTextAlign = Mode;
DC_UnlockDc(dc);
return prevAlign;
}
COLORREF
FASTCALL
IntGdiSetTextColor(HDC hDC,
COLORREF color)
{
COLORREF crOldColor;
PDC pdc;
PDC_ATTR pdcattr;
pdc = DC_LockDc(hDC);
if (!pdc)
{
EngSetLastError(ERROR_INVALID_HANDLE);
return CLR_INVALID;
}
pdcattr = pdc->pdcattr;
// What about ulForegroundClr, like in gdi32?
crOldColor = pdcattr->crForegroundClr;
pdcattr->crForegroundClr = color;
DC_vUpdateTextBrush(pdc);
DC_UnlockDc(pdc);
return crOldColor;
}
COLORREF FASTCALL
IntSetDCBrushColor(HDC hdc, COLORREF crColor)
{
COLORREF OldColor = CLR_INVALID;
PDC dc;
if (!(dc = DC_LockDc(hdc)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return CLR_INVALID;
}
else
{
OldColor = (COLORREF) dc->pdcattr->ulBrushClr;
dc->pdcattr->ulBrushClr = (ULONG) crColor;
if ( dc->pdcattr->crBrushClr != crColor )
{
dc->pdcattr->ulDirty_ |= DIRTY_FILL;
dc->pdcattr->crBrushClr = crColor;
}
}
DC_UnlockDc(dc);
return OldColor;
}
COLORREF FASTCALL
IntSetDCPenColor(HDC hdc, COLORREF crColor)
{
COLORREF OldColor;
PDC dc;
if (!(dc = DC_LockDc(hdc)))
{
EngSetLastError(ERROR_INVALID_PARAMETER);
return CLR_INVALID;
}
OldColor = (COLORREF)dc->pdcattr->ulPenClr;
dc->pdcattr->ulPenClr = (ULONG)crColor;
if (dc->pdcattr->crPenClr != crColor)
{
dc->pdcattr->ulDirty_ |= DIRTY_LINE;
dc->pdcattr->crPenClr = crColor;
}
DC_UnlockDc(dc);
return OldColor;
}
int
FASTCALL
GreSetStretchBltMode(HDC hDC, int iStretchMode)
{
PDC pdc;
PDC_ATTR pdcattr;
INT oSMode = 0;
pdc = DC_LockDc(hDC);
if (pdc)
{
pdcattr = pdc->pdcattr;
oSMode = pdcattr->lStretchBltMode;
pdcattr->lStretchBltMode = iStretchMode;
// Wine returns an error here. We set the default.
if ((iStretchMode <= 0) || (iStretchMode > MAXSTRETCHBLTMODE)) iStretchMode = WHITEONBLACK;
pdcattr->jStretchBltMode = iStretchMode;
DC_UnlockDc(pdc);
}
return oSMode;
}
VOID
FASTCALL
DCU_SetDcUndeletable(HDC hDC)
{
PDC dc = DC_LockDc(hDC);
if (!dc)
{
EngSetLastError(ERROR_INVALID_HANDLE);
return;
}
dc->fs |= DC_FLAG_PERMANENT;
DC_UnlockDc(dc);
return;
}
#if 0
BOOL FASTCALL
IntIsPrimarySurface(SURFOBJ *SurfObj)
{
if (PrimarySurface.pSurface == NULL)
{
return FALSE;
}
return SurfObj->hsurf == PrimarySurface.pSurface; // <- FIXME: WTF?
}
#endif
BOOL
FASTCALL
IntSetDefaultRegion(PDC pdc)
{
PSURFACE pSurface;
PROSRGNDATA prgn;
RECTL rclWnd, rclClip;
IntGdiReleaseRaoRgn(pdc);
rclWnd.left = 0;
rclWnd.top = 0;
rclWnd.right = pdc->dclevel.sizl.cx;
rclWnd.bottom = pdc->dclevel.sizl.cy;
rclClip = rclWnd;
//EngAcquireSemaphoreShared(pdc->ppdev->hsemDevLock);
if (pdc->ppdev->flFlags & PDEV_META_DEVICE)
{
pSurface = pdc->dclevel.pSurface;
if (pSurface && pSurface->flags & PDEV_SURFACE)
{
rclClip.left += pdc->ppdev->ptlOrigion.x;
rclClip.top += pdc->ppdev->ptlOrigion.y;
rclClip.right += pdc->ppdev->ptlOrigion.x;
rclClip.bottom += pdc->ppdev->ptlOrigion.y;
}
}
//EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
prgn = pdc->prgnVis;
if (prgn && prgn != prgnDefault)
{
REGION_SetRectRgn( prgn,
rclClip.left,
rclClip.top,
rclClip.right ,
rclClip.bottom );
}
else
{
prgn = IntSysCreateRectpRgn( rclClip.left,
rclClip.top,
rclClip.right ,
rclClip.bottom );
pdc->prgnVis = prgn;
}
if (prgn)
{
pdc->ptlDCOrig.x = 0;
pdc->ptlDCOrig.y = 0;
pdc->erclWindow = rclWnd;
pdc->erclClip = rclClip;
/* Might be an InitDC or DCE... */
pdc->ptlFillOrigin.x = pdc->dcattr.VisRectRegion.Rect.right;
pdc->ptlFillOrigin.y = pdc->dcattr.VisRectRegion.Rect.bottom;
return TRUE;
}
pdc->prgnVis = prgnDefault;
return FALSE;
}
BOOL APIENTRY
NtGdiCancelDC(HDC hDC)
{
UNIMPLEMENTED;
return FALSE;
}
WORD APIENTRY
IntGdiSetHookFlags(HDC hDC, WORD Flags)
{
WORD wRet;
DC *dc = DC_LockDc(hDC);
if (NULL == dc)
{
EngSetLastError(ERROR_INVALID_HANDLE);
return 0;
}
wRet = dc->fs & DC_FLAG_DIRTY_RAO; // FIXME: Wrong flag!
/* Info in "Undocumented Windows" is slightly confusing. */
DPRINT("DC %p, Flags %04x\n", hDC, Flags);
if (Flags & DCHF_INVALIDATEVISRGN)
{
/* hVisRgn has to be updated */
dc->fs |= DC_FLAG_DIRTY_RAO;
}
else if (Flags & DCHF_VALIDATEVISRGN || 0 == Flags)
{
//dc->fs &= ~DC_FLAG_DIRTY_RAO;
}
DC_UnlockDc(dc);
return wRet;
}
BOOL
APIENTRY
NtGdiGetDCDword(
HDC hDC,
UINT u,
DWORD *Result)
{
BOOL Ret = TRUE;
PDC pdc;
PDC_ATTR pdcattr;
DWORD SafeResult = 0;
NTSTATUS Status = STATUS_SUCCESS;
if (!Result)
{
EngSetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
pdc = DC_LockDc(hDC);
if (!pdc)
{
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
pdcattr = pdc->pdcattr;
switch (u)
{
case GdiGetJournal:
break;
case GdiGetRelAbs:
SafeResult = pdcattr->lRelAbs;
break;
case GdiGetBreakExtra:
SafeResult = pdcattr->lBreakExtra;
break;
case GdiGerCharBreak:
SafeResult = pdcattr->cBreak;
break;
case GdiGetArcDirection:
if (pdcattr->dwLayout & LAYOUT_RTL)
SafeResult = AD_CLOCKWISE - ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
else
SafeResult = ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) + AD_COUNTERCLOCKWISE;
break;
case GdiGetEMFRestorDc:
break;
case GdiGetFontLanguageInfo:
SafeResult = IntGetFontLanguageInfo(pdc);
break;
case GdiGetIsMemDc:
SafeResult = pdc->dctype;
break;
case GdiGetMapMode:
SafeResult = pdcattr->iMapMode;
break;
case GdiGetTextCharExtra:
SafeResult = pdcattr->lTextExtra;
break;
default:
EngSetLastError(ERROR_INVALID_PARAMETER);
Ret = FALSE;
break;
}
if (Ret)
{
_SEH2_TRY
{
ProbeForWrite(Result, sizeof(DWORD), 1);
*Result = SafeResult;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
Ret = FALSE;
}
}
DC_UnlockDc(pdc);
return Ret;
}
_Success_(return != FALSE)
BOOL
APIENTRY
NtGdiGetAndSetDCDword(
_In_ HDC hdc,
_In_ UINT u,
_In_ DWORD dwIn,
_Out_ DWORD *pdwResult)
{
BOOL Ret = TRUE;
PDC pdc;
PDC_ATTR pdcattr;
DWORD SafeResult = 0;
NTSTATUS Status = STATUS_SUCCESS;
if (!pdwResult)
{
EngSetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
pdc = DC_LockDc(hdc);
if (!pdc)
{
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
pdcattr = pdc->pdcattr;
switch (u)
{
case GdiGetSetCopyCount:
SafeResult = pdc->ulCopyCount;
pdc->ulCopyCount = dwIn;
break;
case GdiGetSetTextAlign:
SafeResult = pdcattr->lTextAlign;
pdcattr->lTextAlign = dwIn;
// pdcattr->flTextAlign = dwIn; // Flags!
break;
case GdiGetSetRelAbs:
SafeResult = pdcattr->lRelAbs;
pdcattr->lRelAbs = dwIn;
break;
case GdiGetSetTextCharExtra:
SafeResult = pdcattr->lTextExtra;
pdcattr->lTextExtra = dwIn;
break;
case GdiGetSetSelectFont:
break;
case GdiGetSetMapperFlagsInternal:
if (dwIn & ~1)
{
EngSetLastError(ERROR_INVALID_PARAMETER);
Ret = FALSE;
break;
}
SafeResult = pdcattr->flFontMapper;
pdcattr->flFontMapper = dwIn;
break;
case GdiGetSetMapMode:
SafeResult = IntGdiSetMapMode(pdc, dwIn);
break;
case GdiGetSetArcDirection:
if (dwIn != AD_COUNTERCLOCKWISE && dwIn != AD_CLOCKWISE)
{
EngSetLastError(ERROR_INVALID_PARAMETER);
Ret = FALSE;
break;
}
if (pdcattr->dwLayout & LAYOUT_RTL) // Right to Left
{
SafeResult = AD_CLOCKWISE - ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
if (dwIn == AD_CLOCKWISE)
{
pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
break;
}
pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
}
else // Left to Right
{
SafeResult = ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) +
AD_COUNTERCLOCKWISE;
if (dwIn == AD_COUNTERCLOCKWISE)
{
pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
break;
}
pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
}
break;
default:
EngSetLastError(ERROR_INVALID_PARAMETER);
Ret = FALSE;
break;
}
if (Ret)
{
_SEH2_TRY
{
ProbeForWrite(pdwResult, sizeof(DWORD), 1);
*pdwResult = SafeResult;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
Ret = FALSE;
}
}
DC_UnlockDc(pdc);
return Ret;
}
DWORD
APIENTRY
NtGdiGetBoundsRect(
IN HDC hdc,
OUT LPRECT prc,
IN DWORD flags)
{
DWORD ret;
PDC pdc;
/* Lock the DC */
if (!(pdc = DC_LockDc(hdc))) return 0;
/* Get the return value */
ret = pdc->fs & DC_ACCUM_APP ? DCB_ENABLE : DCB_DISABLE;
ret |= RECTL_bIsEmptyRect(&pdc->erclBoundsApp) ? DCB_RESET : DCB_SET;
/* Copy the rect to the caller */
_SEH2_TRY
{
ProbeForWrite(prc, sizeof(RECT), 1);
*prc = pdc->erclBoundsApp;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ret = 0;
}
_SEH2_END;
if (flags & DCB_RESET)
{
RECTL_vSetEmptyRect(&pdc->erclBoundsApp);
}
DC_UnlockDc(pdc);
return ret;
}
DWORD
APIENTRY
NtGdiSetBoundsRect(
IN HDC hdc,
IN LPRECT prc,
IN DWORD flags)
{
DWORD ret;
PDC pdc;
RECTL rcl;
/* Verify arguments */
if ((flags & DCB_ENABLE) && (flags & DCB_DISABLE)) return 0;
/* Lock the DC */
if (!(pdc = DC_LockDc(hdc))) return 0;
/* Get the return value */
ret = pdc->fs & DC_ACCUM_APP ? DCB_ENABLE : DCB_DISABLE;
ret |= RECTL_bIsEmptyRect(&pdc->erclBoundsApp) ? DCB_RESET : DCB_SET;
if (flags & DCB_RESET)
{
RECTL_vSetEmptyRect(&pdc->erclBoundsApp);
}
if (flags & DCB_ACCUMULATE)
{
/* Capture the rect */
_SEH2_TRY
{
ProbeForRead(prc, sizeof(RECT), 1);
rcl = *prc;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
DC_UnlockDc(pdc);
_SEH2_YIELD(return 0;)
}
_SEH2_END;
RECTL_vMakeWellOrdered(&rcl);
RECTL_bUnionRect(&pdc->erclBoundsApp, &pdc->erclBoundsApp, &rcl);
}
if (flags & DCB_ENABLE) pdc->fs |= DC_ACCUM_APP;
if (flags & DCB_DISABLE) pdc->fs &= ~DC_ACCUM_APP;
DC_UnlockDc(pdc);
return ret;
}
/* Translates a COLORREF to the right color in the specified DC color space */
ULONG
TranslateCOLORREF(PDC pdc, COLORREF crColor)
{
PSURFACE psurfDC;
PPALETTE ppalDC;
ULONG index, ulColor, iBitmapFormat;
EXLATEOBJ exlo;
/* Get the DC surface */
psurfDC = pdc->dclevel.pSurface;
/* If no surface is selected, use the default bitmap */
if (!psurfDC)
psurfDC = psurfDefaultBitmap;
/* Check what color type this is */
switch (crColor >> 24)
{
case 0x00: /* RGB color */
break;
case 0x01: /* PALETTEINDEX */
index = crColor & 0xFFFFFF;
ppalDC = pdc->dclevel.ppal;
if (index >= ppalDC->NumColors) index = 0;
/* Get the RGB value */
crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index);
break;
case 0x02: /* PALETTERGB */
if (pdc->dclevel.hpal != StockObjects[DEFAULT_PALETTE])
{
/* First find the nearest index in the dc palette */
ppalDC = pdc->dclevel.ppal;
index = PALETTE_ulGetNearestIndex(ppalDC, crColor & 0xFFFFFF);
/* Get the RGB value */
crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index);
}
else
{
/* Use the pure color */
crColor = crColor & 0x00FFFFFF;
}
break;
case 0x10: /* DIBINDEX */
/* Mask the value to match the target bpp */
iBitmapFormat = psurfDC->SurfObj.iBitmapFormat;
if (iBitmapFormat == BMF_1BPP) index = crColor & 0x1;
else if (iBitmapFormat == BMF_4BPP) index = crColor & 0xf;
else if (iBitmapFormat == BMF_8BPP) index = crColor & 0xFF;
else if (iBitmapFormat == BMF_16BPP) index = crColor & 0xFFFF;
else index = crColor & 0xFFFFFF;
return index;
default:
DPRINT("Unsupported color type %u passed\n", crColor >> 24);
crColor &= 0xFFFFFF;
}
/* Initialize an XLATEOBJ from RGB to the target surface */
EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurfDC->ppal, 0xFFFFFF, 0, 0);
/* Translate the color to the target format */
ulColor = XLATEOBJ_iXlate(&exlo.xlo, crColor);
/* Cleanup the XLATEOBJ */
EXLATEOBJ_vCleanup(&exlo);
return ulColor;
}