PPALETTE NTAPI PALETTE_AllocPalette2(ULONG Mode, ULONG NumColors, ULONG *Colors, ULONG Red, ULONG Green, ULONG Blue) { PPALETTE PalGDI; PalGDI = (PPALETTE)GDIOBJ_AllocateObject(GDIObjType_PAL_TYPE, sizeof(PALETTE), BASEFLAG_LOOKASIDE); if (!PalGDI) { DPRINT1("Could not allocate a palette.\n"); return NULL; } PalGDI->Self = PalGDI->BaseObject.hHmgr; PalGDI->flFlags = Mode; if (NULL != Colors) { PalGDI->IndexedColors = ExAllocatePoolWithTag(PagedPool, sizeof(PALETTEENTRY) * NumColors, TAG_PALETTE); if (NULL == PalGDI->IndexedColors) { GDIOBJ_vDeleteObject(&PalGDI->BaseObject); return NULL; } RtlCopyMemory(PalGDI->IndexedColors, Colors, sizeof(PALETTEENTRY) * NumColors); } if (Mode & PAL_INDEXED) { PalGDI->NumColors = NumColors; } else if (Mode & PAL_BITFIELDS) { PalGDI->RedMask = Red; PalGDI->GreenMask = Green; PalGDI->BlueMask = Blue; if (Red == 0x7c00 && Green == 0x3E0 && Blue == 0x1F) PalGDI->flFlags |= PAL_RGB16_555; else if (Red == 0xF800 && Green == 0x7E0 && Blue == 0x1F) PalGDI->flFlags |= PAL_RGB16_565; else if (Red == 0xFF0000 && Green == 0xFF00 && Blue == 0xFF) PalGDI->flFlags |= PAL_BGR; else if (Red == 0xFF && Green == 0xFF00 && Blue == 0xFF0000) PalGDI->flFlags |= PAL_RGB; } return PalGDI; }
HPALETTE FASTCALL PALETTE_AllocPaletteIndexedRGB(ULONG NumColors, CONST RGBQUAD *Colors) { HPALETTE NewPalette; PPALETTE PalGDI; UINT i; PalGDI = (PPALETTE)GDIOBJ_AllocateObject(GDIObjType_PAL_TYPE, sizeof(PALETTE), BASEFLAG_LOOKASIDE); if (!PalGDI) { DPRINT1("Could not allocate a palette.\n"); return NULL; } if (!GDIOBJ_hInsertObject(&PalGDI->BaseObject, GDI_OBJ_HMGR_POWNED)) { DPRINT1("Could not insert palette into handle table.\n"); GDIOBJ_vFreeObject(&PalGDI->BaseObject); return NULL; } NewPalette = PalGDI->BaseObject.hHmgr; PalGDI->Self = NewPalette; PalGDI->flFlags = PAL_INDEXED; PalGDI->IndexedColors = ExAllocatePoolWithTag(PagedPool, sizeof(PALETTEENTRY) * NumColors, TAG_PALETTE); if (NULL == PalGDI->IndexedColors) { GDIOBJ_vDeleteObject(&PalGDI->BaseObject); return NULL; } for (i = 0; i < NumColors; i++) { PalGDI->IndexedColors[i].peRed = Colors[i].rgbRed; PalGDI->IndexedColors[i].peGreen = Colors[i].rgbGreen; PalGDI->IndexedColors[i].peBlue = Colors[i].rgbBlue; PalGDI->IndexedColors[i].peFlags = 0; } PalGDI->NumColors = NumColors; PALETTE_UnlockPalette(PalGDI); return NewPalette; }
/* * @implemented */ BOOL APIENTRY EngDeletePalette(IN HPALETTE hpal) { PPALETTE ppal; ppal = PALETTE_ShareLockPalette(hpal); if (!ppal) return FALSE; GDIOBJ_vDeleteObject(&ppal->BaseObject); return TRUE; }
BOOL APIENTRY EngDeleteSurface( _In_ _Post_ptr_invalid_ HSURF hsurf) { PSURFACE psurf; psurf = SURFACE_ShareLockSurface(hsurf); if (!psurf) { DPRINT1("Could not reference surface %p to delete\n", hsurf); return FALSE; } GDIOBJ_vDeleteObject(&psurf->BaseObject); return TRUE; }
/* * @implemented */ HPALETTE APIENTRY NtGdiCreatePaletteInternal( IN LPLOGPALETTE plogpalUser, IN UINT cEntries) { HPALETTE hpal = NULL; PPALETTE ppal; ULONG i, cjSize; ppal = PALETTE_AllocPalWithHandle(PAL_INDEXED, cEntries, NULL, 0, 0, 0); if (ppal == NULL) { return NULL; } cjSize = FIELD_OFFSET(LOGPALETTE, palPalEntry[cEntries]); _SEH2_TRY { ProbeForRead(plogpalUser, cjSize, 1); for (i = 0; i < cEntries; i++) { ppal->IndexedColors[i] = plogpalUser->palPalEntry[i]; } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { GDIOBJ_vDeleteObject(&ppal->BaseObject); _SEH2_YIELD(return NULL); } _SEH2_END; PALETTE_ValidateFlags(ppal->IndexedColors, cEntries); hpal = ppal->BaseObject.hHmgr; PALETTE_UnlockPalette(ppal); return hpal; }
HBITMAP APIENTRY NtGdiCreateBitmap( IN INT nWidth, IN INT nHeight, IN UINT cPlanes, IN UINT cBitsPixel, IN OPTIONAL LPBYTE pUnsafeBits) { HBITMAP hbmp; ULONG cRealBpp, cjWidthBytes, iFormat; ULONGLONG cjSize; PSURFACE psurf; /* Calculate bitmap format and real bits per pixel. */ iFormat = BitmapFormat(cBitsPixel * cPlanes, BI_RGB); cRealBpp = gajBitsPerFormat[iFormat]; /* Calculate width and image size in bytes */ cjWidthBytes = WIDTH_BYTES_ALIGN16(nWidth, cRealBpp); cjSize = (ULONGLONG)cjWidthBytes * nHeight; /* Check parameters (possible overflow of cjSize!) */ if ((iFormat == 0) || (nWidth <= 0) || (nWidth >= 0x8000000) || (nHeight <= 0) || (cBitsPixel > 32) || (cPlanes > 32) || (cjSize >= 0x100000000ULL)) { DPRINT1("Invalid bitmap format! Width=%d, Height=%d, Bpp=%u, Planes=%u\n", nWidth, nHeight, cBitsPixel, cPlanes); EngSetLastError(ERROR_INVALID_PARAMETER); return NULL; } /* Allocate the surface (but don't set the bits) */ psurf = SURFACE_AllocSurface(STYPE_BITMAP, nWidth, nHeight, iFormat, 0, 0, NULL); if (!psurf) { DPRINT1("SURFACE_AllocSurface failed.\n"); return NULL; } /* Mark as API and DDB bitmap */ psurf->flags |= (API_BITMAP | DDB_SURFACE); /* Check if we have bits to set */ if (pUnsafeBits) { /* Protect with SEH and copy the bits */ _SEH2_TRY { ProbeForRead(pUnsafeBits, (SIZE_T)cjSize, 1); UnsafeSetBitmapBits(psurf, 0, pUnsafeBits); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { GDIOBJ_vDeleteObject(&psurf->BaseObject); _SEH2_YIELD(return NULL;) } _SEH2_END } else {
HPEN APIENTRY IntGdiExtCreatePen( DWORD dwPenStyle, DWORD dwWidth, IN ULONG ulBrushStyle, IN ULONG ulColor, IN ULONG_PTR ulClientHatch, IN ULONG_PTR ulHatch, DWORD dwStyleCount, PULONG pStyle, IN ULONG cjDIB, IN BOOL bOldStylePen, IN OPTIONAL HBRUSH hbrush) { HPEN hPen; PBRUSH pbrushPen; static const BYTE PatternAlternate[] = {0x55, 0x55, 0x55, 0}; static const BYTE PatternDash[] = {0xFF, 0xFF, 0xC0, 0}; static const BYTE PatternDot[] = {0xE3, 0x8E, 0x38, 0}; static const BYTE PatternDashDot[] = {0xFF, 0x81, 0xC0, 0}; static const BYTE PatternDashDotDot[] = {0xFF, 0x8E, 0x38, 0}; dwWidth = abs(dwWidth); if ( (dwPenStyle & PS_STYLE_MASK) == PS_NULL) { return StockObjects[NULL_PEN]; } if (bOldStylePen) { pbrushPen = PEN_AllocPenWithHandle(); } else { pbrushPen = PEN_AllocExtPenWithHandle(); } if (!pbrushPen) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); DPRINT("Can't allocate pen\n"); return 0; } hPen = pbrushPen->BaseObject.hHmgr; // If nWidth is zero, the pen is a single pixel wide, regardless of the current transformation. if ((bOldStylePen) && (!dwWidth) && ((dwPenStyle & PS_STYLE_MASK) != PS_SOLID)) dwWidth = 1; pbrushPen->lWidth = dwWidth; pbrushPen->eWidth = (FLOAT)pbrushPen->lWidth; pbrushPen->ulPenStyle = dwPenStyle; pbrushPen->BrushAttr.lbColor = ulColor; pbrushPen->iBrushStyle = ulBrushStyle; // FIXME: Copy the bitmap first ? pbrushPen->hbmClient = (HANDLE)ulClientHatch; pbrushPen->dwStyleCount = dwStyleCount; pbrushPen->pStyle = pStyle; pbrushPen->flAttrs = bOldStylePen ? BR_IS_OLDSTYLEPEN : BR_IS_PEN; // If dwPenStyle is PS_COSMETIC, the width must be set to 1. if ( !(bOldStylePen) && ((dwPenStyle & PS_TYPE_MASK) == PS_COSMETIC) && ( dwWidth != 1) ) goto ExitCleanup; switch (dwPenStyle & PS_STYLE_MASK) { case PS_NULL: pbrushPen->flAttrs |= BR_IS_NULL; break; case PS_SOLID: pbrushPen->flAttrs |= BR_IS_SOLID; break; case PS_ALTERNATE: pbrushPen->flAttrs |= BR_IS_BITMAP; pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternAlternate); break; case PS_DOT: pbrushPen->flAttrs |= BR_IS_BITMAP; pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDot); break; case PS_DASH: pbrushPen->flAttrs |= BR_IS_BITMAP; pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDash); break; case PS_DASHDOT: pbrushPen->flAttrs |= BR_IS_BITMAP; pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDot); break; case PS_DASHDOTDOT: pbrushPen->flAttrs |= BR_IS_BITMAP; pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDotDot); break; case PS_INSIDEFRAME: pbrushPen->flAttrs |= (BR_IS_SOLID | BR_IS_INSIDEFRAME); break; case PS_USERSTYLE: if ((dwPenStyle & PS_TYPE_MASK) == PS_COSMETIC) { /* FIXME: PS_USERSTYLE workaround */ DPRINT1("PS_COSMETIC | PS_USERSTYLE not handled\n"); pbrushPen->flAttrs |= BR_IS_SOLID; break; } else { UINT i; BOOL has_neg = FALSE, all_zero = TRUE; for(i = 0; (i < dwStyleCount) && !has_neg; i++) { has_neg = has_neg || (((INT)(pStyle[i])) < 0); all_zero = all_zero && (pStyle[i] == 0); } if(all_zero || has_neg) { goto ExitCleanup; } } /* FIXME: What style here? */ pbrushPen->flAttrs |= 0; break; default: DPRINT1("IntGdiExtCreatePen unknown penstyle %x\n", dwPenStyle); } PEN_UnlockPen(pbrushPen); return hPen; ExitCleanup: EngSetLastError(ERROR_INVALID_PARAMETER); pbrushPen->pStyle = NULL; GDIOBJ_vDeleteObject(&pbrushPen->BaseObject); return NULL; }
PSURFACE NTAPI SURFACE_AllocSurface( _In_ USHORT iType, _In_ ULONG cx, _In_ ULONG cy, _In_ ULONG iFormat, _In_ ULONG fjBitmap, _In_opt_ ULONG cjWidth, _In_opt_ ULONG cjBufSize, _In_opt_ PVOID pvBits) { ULONG cBitsPixel, cjBits, cjObject; PSURFACE psurf; SURFOBJ *pso; PVOID pvSection; NT_ASSERT(!pvBits || (iType == STYPE_BITMAP)); NT_ASSERT((iFormat <= BMF_32BPP) || (cjBufSize != 0)); NT_ASSERT((LONG)cy > 0); /* Verify format */ if ((iFormat < BMF_1BPP) || (iFormat > BMF_PNG)) { DPRINT1("Invalid bitmap format: %lu\n", iFormat); return NULL; } /* Get bits per pixel from the format */ cBitsPixel = gajBitsPerFormat[iFormat]; /* Are bits and a width in bytes given? */ if (pvBits && cjWidth) { /* Align the width (Windows compatibility, drivers expect that) */ cjWidth = WIDTH_BYTES_ALIGN32((cjWidth << 3) / cBitsPixel, cBitsPixel); } else { /* Calculate width from the bitmap width in pixels */ cjWidth = WIDTH_BYTES_ALIGN32(cx, cBitsPixel); } /* Is this an uncompressed format? */ if (iFormat <= BMF_32BPP) { /* Calculate the correct bitmap size in bytes */ if (!NT_SUCCESS(RtlULongMult(cjWidth, cy, &cjBits))) { DPRINT1("Overflow calculating size: cjWidth %lu, cy %lu\n", cjWidth, cy); return NULL; } /* Did we get a buffer and size? */ if ((pvBits != NULL) && (cjBufSize != 0)) { /* Make sure the buffer is large enough */ if (cjBufSize < cjBits) { DPRINT1("Buffer is too small, required: %lu, got %lu\n", cjBits, cjBufSize); return NULL; } } } else { /* Compressed format, use the provided size */ NT_ASSERT(cjBufSize != 0); cjBits = cjBufSize; } /* Check if we need an extra large object */ if ((iType == STYPE_BITMAP) && (pvBits == NULL) && !(fjBitmap & BMF_USERMEM) && !(fjBitmap & BMF_KMSECTION)) { /* Allocate an object large enough to hold the bits */ cjObject = sizeof(SURFACE) + cjBits; } else { /* Otherwise just allocate the SURFACE structure */ cjObject = sizeof(SURFACE); } /* Check for arithmetic overflow */ if (cjObject < sizeof(SURFACE)) { /* Fail! */ DPRINT1("Overflow calculating cjObject: cjBits %lu\n", cjBits); return NULL; } /* Allocate a SURFACE object */ psurf = (PSURFACE)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP, cjObject); if (!psurf) { return NULL; } /* Initialize the basic fields */ pso = &psurf->SurfObj; pso->hsurf = psurf->BaseObject.hHmgr; pso->sizlBitmap.cx = cx; pso->sizlBitmap.cy = cy; pso->iBitmapFormat = iFormat; pso->iType = iType; pso->fjBitmap = (USHORT)fjBitmap; pso->iUniq = InterlockedIncrement(&giUniqueSurface); pso->cjBits = cjBits; /* Check if we need a bitmap buffer */ if (iType == STYPE_BITMAP) { /* Check if we got one or if we need to allocate one */ if (pvBits != NULL) { /* Use the caller provided buffer */ pso->pvBits = pvBits; } else if (fjBitmap & BMF_USERMEM) { /* User mode memory was requested */ pso->pvBits = EngAllocUserMem(cjBits, 0); /* Check for failure */ if (!pso->pvBits) { GDIOBJ_vDeleteObject(&psurf->BaseObject); return NULL; } } else if (fjBitmap & BMF_KMSECTION) { /* Use a kernel mode section */ pso->pvBits = EngAllocSectionMem(&pvSection, (fjBitmap & BMF_NOZEROINIT) ? 0 : FL_ZERO_MEMORY, cjBits, TAG_DIB); /* Check for failure */ if (!pso->pvBits) { GDIOBJ_vDeleteObject(&psurf->BaseObject); return NULL; } /* Free the section already, but keep the mapping */ EngFreeSectionMem(pvSection, NULL); } else { /* Buffer is after the object */ pso->pvBits = psurf + 1; /* Zero the buffer, except requested otherwise */ if (!(fjBitmap & BMF_NOZEROINIT)) { RtlZeroMemory(pso->pvBits, cjBits); } } /* Set pvScan0 and lDelta */ if (fjBitmap & BMF_TOPDOWN) { /* Topdown is the normal way */ pso->pvScan0 = pso->pvBits; pso->lDelta = cjWidth; } else { /* Inversed bitmap (bottom up) */ pso->pvScan0 = ((PCHAR)pso->pvBits + pso->cjBits - cjWidth); pso->lDelta = -(LONG)cjWidth; } } else { /* There are no bitmap bits */ pso->pvScan0 = pso->pvBits = NULL; pso->lDelta = 0; } /* Assign a default palette and increment its reference count */ SURFACE_vSetPalette(psurf, appalSurfaceDefault[iFormat]); return psurf; }
/* 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; }