{} procedure CalcRect(var src,dst:TRECT;mode:dword); var dh, dw:integer; begin if (Mode and frbkStretch)=frbkStretch then begin if (Mode and frbkProportional)<>0 then begin if (dst.right*src.bottom)>(src.right*dst.bottom) then begin dh:=dst.bottom; dw:=dh*src.right div src.bottom end else begin dw:=dst.right; dh:=dw*src.bottom div src.right; end; end else begin dw:=dst.right; dh:=dst.bottom; end; end else if (Mode and frbkStretchX)<>0 then begin dw:=dst.right; if (Mode and frbkProportional)<>0 then dh:=dw*src.bottom div src.right else dh:=src.bottom; end else if (Mode and frbkStretchY)<>0 then begin dh:=dst.bottom; if (Mode and frbkProportional)<>0 then dw:=dh*src.right div src.bottom else dw:=src.right; end else begin dw:=src.right; dh:=src.bottom; end; if (Mode and frbkBottom)<>0 then begin if dh<=dst.bottom then begin dst.top:=(dst.bottom-dh); end else begin src.top:=(dh-dst.bottom); dh:=dst.bottom; src.bottom:=src.top+dh; end; end; if (Mode and frbkRight)<>0 then begin if dw<=dst.right then begin dst.left:=(dst.right-dw); end else begin src.left:=(dw-dst.right); dw:=dst.right; src.right:=src.left+dw; end; end; if (Mode and frbkCenterX)<>0 then begin if dw<=dst.right then begin dst.left:=(dst.right-dw) div 2; end else begin src.left:=(dw-dst.right) div 2; dw:=dst.right; src.right:=src.left+dw; end; end; if (Mode and frbkCenterY)<>0 then begin if dh<=dst.bottom then begin dst.top:=(dst.bottom-dh) div 2; end else begin src.top:=(dh-dst.bottom) div 2; dh:=dst.bottom; src.bottom:=src.top+dh; end; end; dst.right:=dst.left+dw; dst.bottom:=dst.top+dh; end; function CreateDIB32(dc:HDC;w,h:integer):HBITMAP; var pt:pointer; bi:TBITMAPINFO; begin FillChar(bi,SizeOf(TBITMAPINFO),0); bi.bmiHeader.biSize :=SizeOf(TBITMAPINFOHEADER); bi.bmiHeader.biWidth :=w; bi.bmiHeader.biHeight :=h; bi.bmiHeader.biPlanes :=1; bi.bmiHeader.biBitCount:=32; result:=CreateDIBSection(dc,bi,DIB_RGB_COLORS,pt,0,0); end; procedure PreMultiplyChanells(hbmp:HBITMAP); type tPixel=array [0..3] of Byte; var bmp:windows.TBITMAP; flag:bool; pBitmapBits:PByte; Len:dword; bh,bw,y,x,z:integer; pPixel:^tPixel; alpha:dword; //f:THANDLE; begin GetObject(hbmp,SizeOf(bmp),@bmp); bh:=bmp.bmHeight; bw:=bmp.bmWidth; z:=bw*4; Len:=bh*z; mGetMem(pBitmapBits,Len); GetBitmapBits(hbmp,Len,pBitmapBits); flag:=true; for y:=0 to bh-1 do begin pointer(pPixel):=PAnsiChar(pBitmapBits)+z*y; for x:=0 to bw-1 do begin if pPixel^[3]<>0 then flag:=false else pPixel^[3]:=255; inc(pByte(pPixel),4); end end; if not flag then begin GetBitmapBits(hbmp,Len,pBitmapBits); // alpha not changed for y:=0 to bh-1 do begin pointer(pPixel):=PAnsiChar(pBitmapBits)+z*y; for x:=0 to bw-1 do begin alpha:=pPixel^[3]; if alpha<255 then begin pPixel^[0]:=dword(pPixel^[0])*alpha div 255; pPixel^[1]:=dword(pPixel^[1])*alpha div 255; pPixel^[2]:=dword(pPixel^[2])*alpha div 255; end; inc(pByte(pPixel),4); end end; end; SetBitmapBits(hbmp,Len,pBitmapBits); mFreeMem(pBitmapBits); end; function FixBitmap(dc:HDC;var hBmp:HBITMAP):HBITMAP; var dc24,dc32:HDC; hBitmap32,obmp24,obmp32:HBITMAP; bmpInfo:windows.TBITMAP; begin GetObject(hBmp,SizeOf(bmpInfo),@bmpInfo); if bmpInfo.bmBitsPixel<>32 then begin dc32:=CreateCompatibleDC(dc); dc24:=CreateCompatibleDC(dc); hBitmap32:=CreateDIB32(dc,bmpInfo.bmWidth,bmpInfo.bmHeight); obmp24:=SelectObject(dc24,hBmp); obmp32:=SelectObject(dc32,hBitmap32); BitBlt(dc32,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,dc24,0,0,SRCCOPY); DeleteObject(SelectObject(dc24,obmp24)); SelectObject(dc32,obmp32); DeleteDC(dc24); DeleteDC(dc32); hBmp:=hBitmap32; end; PreMultiplyChanells(hBmp); result:=hBmp; end; procedure TWATFrame.PreparePicture(dc:HDC;rc:TRECT); var bmpinfo:windows.TBITMAP; src,dst:TRECT; x,y,w,h,dh:integer; br:HBRUSH; hdcbmp:HDC; bf:BLENDFUNCTION; hOld:THANDLE; D:PWATFrameData; begin D:=CustomData; D.BkDC:=CreateCompatibleDC(dc); FixBitmap(dc,D.BkBitmap); DeleteObject(SelectObject(D.BkDC,CreateDIB32(dc,rc.right-rc.left,rc.bottom-rc.top))); //fill empty space by BK color br:=CreateSolidBrush(D.BkColor); FillRect(D.BkDC,rc,br); DeleteObject(br); CopyRect(dst,rc); hdcbmp:=CreateCompatibleDC(D.BkDC); GetObject(D.BkBitmap,SizeOf(bmpinfo),@bmpinfo); hOld:=SelectObject(hdcbmp,D.BkBitmap); SetRect(src,0,0,bmpinfo.bmWidth,bmpinfo.bmHeight); if (D.padding.top+D.padding.bottom)<(dst.bottom-dst.top) then dec(dst.bottom,D.padding.top+D.padding.bottom); if (D.padding.left+D.padding.right)<(dst.right-dst.left) then dec(dst.right,D.padding.left+D.padding.right); CalcRect(src,dst,D.BkMode); // calculate final picture rect w:=1; if (D.BkMode and frbkTileX)<>0 then begin x:=dst.right; while x0 then begin y:=dst.bottom; while y0 do begin dh:=h; y:=dst.top+D.padding.top; if y0 do begin Windows.AlphaBlend(D.BkDC,x,y,dst.right-dst.left,dst.bottom-dst.top, hdcbmp,src.left,src.top,src.right-src.left,src.bottom-src.top,bf); inc(y,dst.bottom); dec(dh); end; inc(x,dst.right); dec(w); end; SelectObject(hdcbmp,hOld); DeleteDC(hdcbmp); end;