BOOL FASTCALL IntEngGradientFillRect( IN SURFOBJ *psoDest, IN CLIPOBJ *pco, IN XLATEOBJ *pxlo, IN TRIVERTEX *pVertex, IN ULONG nVertex, IN PGRADIENT_RECT gRect, IN RECTL *prclExtents, IN POINTL *pptlDitherOrg, IN BOOL Horizontal) { SURFOBJ *psoOutput; TRIVERTEX *v1, *v2; RECTL rcGradient, rcSG; RECT_ENUM RectEnum; BOOL EnumMore; ULONG i; POINTL Translate; INTENG_ENTER_LEAVE EnterLeave; LONG y, dy, c[3], dc[3], ec[3], ic[3]; v1 = (pVertex + gRect->UpperLeft); v2 = (pVertex + gRect->LowerRight); rcGradient.left = min(v1->x, v2->x); rcGradient.right = max(v1->x, v2->x); rcGradient.top = min(v1->y, v2->y); rcGradient.bottom = max(v1->y, v2->y); rcSG = rcGradient; RECTL_vOffsetRect(&rcSG, pptlDitherOrg->x, pptlDitherOrg->y); if(Horizontal) { dy = abs(rcGradient.right - rcGradient.left); } else { dy = abs(rcGradient.bottom - rcGradient.top); } if(!IntEngEnter(&EnterLeave, psoDest, &rcSG, FALSE, &Translate, &psoOutput)) { return FALSE; } if((v1->Red != v2->Red || v1->Green != v2->Green || v1->Blue != v2->Blue) && dy > 1) { CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); do { RECTL FillRect; ULONG Color; if (Horizontal) { EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= rcSG.bottom; i++) { if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], &rcSG)) { HVINITCOL(Red, 0); HVINITCOL(Green, 1); HVINITCOL(Blue, 2); for (y = rcSG.left; y < FillRect.right; y++) { if (y >= FillRect.left) { Color = XLATEOBJ_iXlate(pxlo, RGB(c[0], c[1], c[2])); DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_VLine( psoOutput, y + Translate.x, FillRect.top + Translate.y, FillRect.bottom + Translate.y, Color); } HVSTEPCOL(0); HVSTEPCOL(1); HVSTEPCOL(2); } } } continue; } /* vertical */ EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= rcSG.bottom; i++) { if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], &rcSG)) { HVINITCOL(Red, 0); HVINITCOL(Green, 1); HVINITCOL(Blue, 2); for (y = rcSG.top; y < FillRect.bottom; y++) { if (y >= FillRect.top) { Color = XLATEOBJ_iXlate(pxlo, RGB(c[0], c[1], c[2])); DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_HLine(psoOutput, FillRect.left + Translate.x, FillRect.right + Translate.x, y + Translate.y, Color); } HVSTEPCOL(0); HVSTEPCOL(1); HVSTEPCOL(2); } } } } while (EnumMore); return IntEngLeave(&EnterLeave); } /* rectangle has only one color, no calculation required */ CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); do { RECTL FillRect; ULONG Color = XLATEOBJ_iXlate(pxlo, RGB(v1->Red, v1->Green, v1->Blue)); EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= rcSG.bottom; i++) { if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], &rcSG)) { for (; FillRect.top < FillRect.bottom; FillRect.top++) { DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_HLine(psoOutput, FillRect.left + Translate.x, FillRect.right + Translate.x, FillRect.top + Translate.y, Color); } } } } while (EnumMore); return IntEngLeave(&EnterLeave); }
BOOL FASTCALL UITOOLS95_DrawFrameScroll(HDC dc, LPRECT r, UINT uFlags) { LOGFONTW lf; HFONT hFont, hOldFont; COLORREF clrsave; RECT myr; INT bkmode; WCHAR Symbol; switch(uFlags & 0xff) { case DFCS_SCROLLCOMBOBOX: case DFCS_SCROLLDOWN: Symbol = '6'; break; case DFCS_SCROLLUP: Symbol = '5'; break; case DFCS_SCROLLLEFT: Symbol = '3'; break; case DFCS_SCROLLRIGHT: Symbol = '4'; break; case DFCS_SCROLLSIZEGRIP: case DFCS_SCROLLSIZEGRIPRIGHT: RtlZeroMemory(&lf, sizeof(LOGFONTW)); UITOOLS_MakeSquareRect(r, &myr); lf.lfHeight = myr.bottom - myr.top; lf.lfWidth = 0; lf.lfWeight = FW_NORMAL; lf.lfCharSet = DEFAULT_CHARSET; RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett")); hFont = GreCreateFontIndirectW(&lf); /* save font and text color */ hOldFont = NtGdiSelectFont(dc, hFont); clrsave = GreGetTextColor(dc); bkmode = GreGetBkMode(dc); /* set color and drawing mode */ IntGdiSetBkMode(dc, TRANSPARENT); if (!(uFlags & (DFCS_MONO | DFCS_FLAT))) { IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT)); /* draw selected symbol */ Symbol = ((uFlags & 0xff) == DFCS_SCROLLSIZEGRIP) ? 'o' : 'x'; GreTextOutW(dc, myr.left, myr.top, &Symbol, 1); IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNSHADOW)); } else IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME)); /* draw selected symbol */ Symbol = ((uFlags & 0xff) == DFCS_SCROLLSIZEGRIP) ? 'p' : 'y'; GreTextOutW(dc, myr.left, myr.top, &Symbol, 1); /* restore previous settings */ IntGdiSetTextColor(dc, clrsave); NtGdiSelectFont(dc, hOldFont); IntGdiSetBkMode(dc, bkmode); GreDeleteObject(hFont); return TRUE; default: return FALSE; } IntDrawRectEdge(dc, r, (uFlags & DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, (uFlags&DFCS_FLAT) | BF_MIDDLE | BF_RECT); RtlZeroMemory(&lf, sizeof(LOGFONTW)); UITOOLS_MakeSquareRect(r, &myr); myr.left += 1; myr.top += 1; myr.right -= 1; myr.bottom -= 1; if(uFlags & DFCS_PUSHED) RECTL_vOffsetRect(&myr,1,1); lf.lfHeight = myr.bottom - myr.top; lf.lfWidth = 0; lf.lfWeight = FW_NORMAL; lf.lfCharSet = DEFAULT_CHARSET; RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett")); hFont = GreCreateFontIndirectW(&lf); /* save font and text color */ hOldFont = NtGdiSelectFont(dc, hFont); clrsave = GreGetTextColor(dc); bkmode = GreGetBkMode(dc); /* set color and drawing mode */ IntGdiSetBkMode(dc, TRANSPARENT); if(uFlags & DFCS_INACTIVE) { /* draw shadow */ IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT)); GreTextOutW(dc, myr.left + 1, myr.top + 1, &Symbol, 1); } IntGdiSetTextColor(dc, IntGetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT)); /* draw selected symbol */ GreTextOutW(dc, myr.left, myr.top, &Symbol, 1); /* restore previous settings */ IntGdiSetTextColor(dc, clrsave); NtGdiSelectFont(dc, hOldFont); IntGdiSetBkMode(dc, bkmode); GreDeleteObject(hFont); return TRUE; }
/* Mostly inspired from wine code. * We use low level functions because: * - at this point, the icon bitmap could have a different bit depth than the DC, * making it thus impossible to use NtCreateCompatibleDC and selecting the bitmap. * This happens after a mode setting change. * - it avoids massive GDI objects locking when only the destination surface needs it. * - It makes (small) performance gains. */ BOOL UserDrawIconEx( HDC hDc, INT xLeft, INT yTop, PCURICON_OBJECT pIcon, INT cxWidth, INT cyHeight, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags) { PSURFACE psurfDest, psurfMask, psurfColor; //, psurfOffScreen = NULL; PDC pdc = NULL; BOOL Ret = FALSE; HBITMAP hbmMask, hbmColor, hbmAlpha; BOOL bOffScreen; RECTL rcDest, rcSrc; CLIPOBJ* pdcClipObj = NULL; EXLATEOBJ exlo; /* Stupid case */ if((diFlags & DI_NORMAL) == 0) { ERR("DrawIconEx called without mask or color bitmap to draw.\n"); return FALSE; } if (pIcon->CURSORF_flags & CURSORF_ACON) { ACON* pAcon = (ACON*)pIcon; if(istepIfAniCur >= pAcon->cicur) { ERR("NtUserDrawIconEx: istepIfAniCur too big!\n"); return FALSE; } pIcon = pAcon->aspcur[pAcon->aicur[istepIfAniCur]]; } hbmMask = pIcon->hbmMask; hbmColor = pIcon->hbmColor; hbmAlpha = pIcon->hbmAlpha; /* * Get our objects. * Shared locks are enough, we are only reading those bitmaps */ psurfMask = SURFACE_ShareLockSurface(hbmMask); if(psurfMask == NULL) { ERR("Unable to lock the mask surface.\n"); return FALSE; } /* Color bitmap is not mandatory */ if(hbmColor == NULL) { /* But then the mask bitmap must have the information in it's bottom half */ ASSERT(psurfMask->SurfObj.sizlBitmap.cy == 2*pIcon->cy); psurfColor = NULL; } else if ((psurfColor = SURFACE_ShareLockSurface(hbmColor)) == NULL) { ERR("Unable to lock the color bitmap.\n"); SURFACE_ShareUnlockSurface(psurfMask); return FALSE; } pdc = DC_LockDc(hDc); if(!pdc) { ERR("Could not lock the destination DC.\n"); SURFACE_ShareUnlockSurface(psurfMask); if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); return FALSE; } /* Calculate destination rectangle */ RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight); IntLPtoDP(pdc, (LPPOINT)&rcDest, 2); RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y); /* Prepare the underlying surface */ DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest); /* We now have our destination surface and rectangle */ psurfDest = pdc->dclevel.pSurface; if(psurfDest == NULL) { /* Empty DC */ DC_vFinishBlit(pdc, NULL); DC_UnlockDc(pdc); SURFACE_ShareUnlockSurface(psurfMask); if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); return FALSE; } /* Set source rect */ RECTL_vSetRect(&rcSrc, 0, 0, pIcon->cx, pIcon->cy); /* Fix width parameter, if needed */ if (!cxWidth) { if(diFlags & DI_DEFAULTSIZE) cxWidth = is_icon(pIcon) ? UserGetSystemMetrics(SM_CXICON) : UserGetSystemMetrics(SM_CXCURSOR); else cxWidth = pIcon->cx; } /* Fix height parameter, if needed */ if (!cyHeight) { if(diFlags & DI_DEFAULTSIZE) cyHeight = is_icon(pIcon) ? UserGetSystemMetrics(SM_CYICON) : UserGetSystemMetrics(SM_CYCURSOR); else cyHeight = pIcon->cy; } /* Should we render off-screen? */ bOffScreen = hbrFlickerFreeDraw && (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH); if (bOffScreen) { /* Yes: Allocate and paint the offscreen surface */ EBRUSHOBJ eboFill; PBRUSH pbrush = BRUSH_ShareLockBrush(hbrFlickerFreeDraw); TRACE("Performing off-screen rendering.\n"); if(!pbrush) { ERR("Failed to get brush object.\n"); goto Cleanup; } #if 0 //We lock the hdc surface during the whole function it makes no sense to use an offscreen surface for "flicker free" drawing psurfOffScreen = SURFACE_AllocSurface(STYPE_BITMAP, cxWidth, cyHeight, psurfDest->SurfObj.iBitmapFormat, 0, 0, NULL); if(!psurfOffScreen) { ERR("Failed to allocate the off-screen surface.\n"); BRUSH_ShareUnlockBrush(pbrush); goto Cleanup; } /* Paint the brush */ EBRUSHOBJ_vInit(&eboFill, pbrush, psurfOffScreen, 0x00FFFFFF, 0, NULL); RECTL_vSetRect(&rcDest, 0, 0, cxWidth, cyHeight); Ret = IntEngBitBlt(&psurfOffScreen->SurfObj, NULL, NULL, NULL, NULL, &rcDest, NULL, NULL, &eboFill.BrushObject, &pbrush->ptOrigin, ROP4_PATCOPY); /* Clean up everything */ EBRUSHOBJ_vCleanup(&eboFill); BRUSH_ShareUnlockBrush(pbrush); if(!Ret) { ERR("Failed to paint the off-screen surface.\n"); goto Cleanup; } /* We now have our destination surface */ psurfDest = psurfOffScreen; #else pdcClipObj = pdc->rosdc.CombinedClip; /* Paint the brush */ EBRUSHOBJ_vInit(&eboFill, pbrush, psurfDest, 0x00FFFFFF, 0, NULL); Ret = IntEngBitBlt(&psurfDest->SurfObj, NULL, NULL, pdcClipObj, NULL, &rcDest, NULL, NULL, &eboFill.BrushObject, &pbrush->ptOrigin, ROP4_PATCOPY); /* Clean up everything */ EBRUSHOBJ_vCleanup(&eboFill); BRUSH_ShareUnlockBrush(pbrush); if(!Ret) { ERR("Failed to paint the off-screen surface.\n"); goto Cleanup; } #endif } else { /* We directly draw to the DC */ TRACE("Performing on screen rendering.\n"); pdcClipObj = pdc->rosdc.CombinedClip; // psurfOffScreen = NULL; } /* Now do the rendering */ if(hbmAlpha && ((diFlags & DI_NORMAL) == DI_NORMAL)) { BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } }; PSURFACE psurf = NULL; psurf = SURFACE_ShareLockSurface(hbmAlpha); if(!psurf) { ERR("SURFACE_LockSurface failed!\n"); goto NoAlpha; } /* Initialize color translation object */ EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xFFFFFFFF, 0xFFFFFFFF, 0); /* Now do it */ Ret = IntEngAlphaBlend(&psurfDest->SurfObj, &psurf->SurfObj, pdcClipObj, &exlo.xlo, &rcDest, &rcSrc, &blendobj); EXLATEOBJ_vCleanup(&exlo); SURFACE_ShareUnlockSurface(psurf); if(Ret) goto done; ERR("NtGdiAlphaBlend failed!\n"); } NoAlpha: if (diFlags & DI_MASK) { DWORD rop4 = (diFlags & DI_IMAGE) ? ROP4_SRCAND : ROP4_SRCCOPY; EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0); Ret = IntEngStretchBlt(&psurfDest->SurfObj, &psurfMask->SurfObj, NULL, pdcClipObj, &exlo.xlo, NULL, &rcDest, &rcSrc, NULL, NULL, NULL, rop4); EXLATEOBJ_vCleanup(&exlo); if(!Ret) { ERR("Failed to mask the bitmap data.\n"); goto Cleanup; } } if(diFlags & DI_IMAGE) { if (psurfColor) { DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY ; EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0); Ret = IntEngStretchBlt(&psurfDest->SurfObj, &psurfColor->SurfObj, NULL, pdcClipObj, &exlo.xlo, NULL, &rcDest, &rcSrc, NULL, NULL, NULL, rop4); EXLATEOBJ_vCleanup(&exlo); if(!Ret) { ERR("Failed to render the icon bitmap.\n"); goto Cleanup; } } else { /* Mask bitmap holds the information in its bottom half */ DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY; RECTL_vOffsetRect(&rcSrc, 0, pIcon->cy); EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0); Ret = IntEngStretchBlt(&psurfDest->SurfObj, &psurfMask->SurfObj, NULL, pdcClipObj, &exlo.xlo, NULL, &rcDest, &rcSrc, NULL, NULL, NULL, rop4); EXLATEOBJ_vCleanup(&exlo); if(!Ret) { ERR("Failed to render the icon bitmap.\n"); goto Cleanup; } } } done: #if 0 /* We're done. Was it a double buffered draw ? */ if(bOffScreen) { /* Yes. Draw it back to our DC */ POINTL ptSrc = {0, 0}; /* Calculate destination rectangle */ RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight); IntLPtoDP(pdc, (LPPOINT)&rcDest, 2); RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y); /* Get the clip object */ pdcClipObj = pdc->rosdc.CombinedClip; /* We now have our destination surface and rectangle */ psurfDest = pdc->dclevel.pSurface; /* Color translation */ EXLATEOBJ_vInitialize(&exlo, psurfOffScreen->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0); /* Blt it! */ Ret = IntEngBitBlt(&psurfDest->SurfObj, &psurfOffScreen->SurfObj, NULL, pdcClipObj, &exlo.xlo, &rcDest, &ptSrc, NULL, NULL, NULL, ROP4_SRCCOPY); EXLATEOBJ_vCleanup(&exlo); } #endif Cleanup: if(pdc) { DC_vFinishBlit(pdc, NULL); DC_UnlockDc(pdc); } #if 0 /* Delete off screen rendering surface */ if(psurfOffScreen) GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject); #endif /* Unlock other surfaces */ SURFACE_ShareUnlockSurface(psurfMask); if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); return Ret; }
BOOL FASTCALL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags) { LOGFONTW lf; HFONT hFont, hOldFont; COLORREF clrsave; RECT myr; INT bkmode; WCHAR Symbol; switch(uFlags & 0xff) { case DFCS_CAPTIONCLOSE: Symbol = 'r'; break; case DFCS_CAPTIONHELP: Symbol = 's'; break; case DFCS_CAPTIONMIN: Symbol = '0'; break; case DFCS_CAPTIONMAX: Symbol = '1'; break; case DFCS_CAPTIONRESTORE: Symbol = '2'; break; default: return FALSE; } IntDrawRectEdge(dc,r,(uFlags&DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT | BF_MIDDLE | BF_SOFT); RtlZeroMemory(&lf, sizeof(LOGFONTW)); UITOOLS_MakeSquareRect(r, &myr); myr.left += 1; myr.top += 1; myr.right -= 1; myr.bottom -= 1; if(uFlags & DFCS_PUSHED) RECTL_vOffsetRect(&myr,1,1); lf.lfHeight = myr.bottom - myr.top; lf.lfWidth = 0; lf.lfWeight = FW_NORMAL; lf.lfCharSet = DEFAULT_CHARSET; lf.lfQuality = NONANTIALIASED_QUALITY; RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett")); hFont = GreCreateFontIndirectW(&lf); /* save font and text color */ hOldFont = NtGdiSelectFont(dc, hFont); clrsave = GreGetTextColor(dc); bkmode = GreGetBkMode(dc); /* set color and drawing mode */ IntGdiSetBkMode(dc, TRANSPARENT); if(uFlags & DFCS_INACTIVE) { /* draw shadow */ IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT)); GreTextOutW(dc, myr.left + 1, myr.top + 1, &Symbol, 1); } IntGdiSetTextColor(dc, IntGetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT)); /* draw selected symbol */ GreTextOutW(dc, myr.left, myr.top, &Symbol, 1); /* restore previous settings */ IntGdiSetTextColor(dc, clrsave); NtGdiSelectFont(dc, hOldFont); IntGdiSetBkMode(dc, bkmode); GreDeleteObject(hFont); return TRUE; }
BOOL FASTCALL IntGetScrollBarRect (PWND Wnd, INT nBar, RECTL *lprect) { BOOL vertical; *lprect = Wnd->rcClient; RECTL_vOffsetRect( lprect, -Wnd->rcWindow.left, -Wnd->rcWindow.top ); if (Wnd->ExStyle & WS_EX_LAYOUTRTL) mirror_rect( &Wnd->rcWindow, lprect ); switch (nBar) { case SB_HORZ: lprect->top = lprect->bottom; lprect->bottom += UserGetSystemMetrics (SM_CYHSCROLL); if (Wnd->style & WS_BORDER) { lprect->left--; lprect->right++; } else if (Wnd->style & WS_VSCROLL) { lprect->right++; } vertical = FALSE; break; case SB_VERT: if(Wnd->ExStyle & WS_EX_LEFTSCROLLBAR) { lprect->right = lprect->left; lprect->left -= UserGetSystemMetrics(SM_CXVSCROLL); } else { lprect->left = lprect->right; lprect->right += UserGetSystemMetrics(SM_CXVSCROLL); } if (Wnd->style & WS_BORDER) { lprect->top--; lprect->bottom++; } else if (Wnd->style & WS_HSCROLL) { lprect->bottom++; } vertical = TRUE; break; case SB_CTL: IntGetClientRect (Wnd, lprect); vertical = !!(Wnd->style & SBS_VERT); break; default: return FALSE; } return vertical; }