static void test_memory_dc_clipping(void) { HDC hdc; HRGN hrgn, hrgn_empty; HBITMAP hbmp; RECT rc; int ret; hdc = CreateCompatibleDC(0); hrgn_empty = CreateRectRgn(0, 0, 0, 0); hrgn = CreateRectRgn(0, 0, 0, 0); hbmp = CreateCompatibleBitmap(hdc, 100, 100); ret = GetClipRgn(hdc, hrgn); ok(ret == 0, "expected 0, got %d\n", ret); ret = ExtSelectClipRgn(hdc, hrgn_empty, RGN_DIFF); ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret); ret = GetClipRgn(hdc, hrgn); ok(ret == 1, "expected 1, got %d\n", ret); ret = GetRgnBox(hrgn, &rc); ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret); ok(rc.left == 0 && rc.top == 0 && rc.right == 1 && rc.bottom == 1, "expected 0,0-1,1, got %d,%d-%d,%d\n", rc.left, rc.top, rc.right, rc.bottom); ret = ExtSelectClipRgn(hdc, 0, RGN_COPY); ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret); ret = GetClipRgn(hdc, hrgn); ok(ret == 0, "expected 0, got %d\n", ret); SelectObject(hdc, hbmp); ret = ExtSelectClipRgn(hdc, hrgn_empty, RGN_DIFF); ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret); ret = GetClipRgn(hdc, hrgn); ok(ret == 1, "expected 1, got %d\n", ret); ret = GetRgnBox(hrgn, &rc); ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret); ok(rc.left == 0 && rc.top == 0 && rc.right == 100 && rc.bottom == 100, "expected 0,0-100,100, got %d,%d-%d,%d\n", rc.left, rc.top, rc.right, rc.bottom); DeleteDC(hdc); DeleteObject(hrgn); DeleteObject(hrgn_empty); DeleteObject(hbmp); }
static void test_window_dc_clipping(void) { HDC hdc; HRGN hrgn, hrgn_empty; HWND hwnd; RECT rc; int ret, screen_width, screen_height; /* Windows versions earlier than Win2k do not support the virtual screen metrics, * so we fall back to the primary screen metrics. */ screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN); if(!screen_width) screen_width = GetSystemMetrics(SM_CXSCREEN); screen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN); if(!screen_height) screen_height = GetSystemMetrics(SM_CYSCREEN); trace("screen resolution %d x %d\n", screen_width, screen_height); hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, -100, -100, screen_width * 2, screen_height * 2, 0, 0, 0, NULL); hdc = GetWindowDC(0); hrgn_empty = CreateRectRgn(0, 0, 0, 0); hrgn = CreateRectRgn(0, 0, 0, 0); ret = GetClipRgn(hdc, hrgn); ok(ret == 0, "expected 0, got %d\n", ret); ret = ExtSelectClipRgn(hdc, hrgn_empty, RGN_DIFF); ok(ret == SIMPLEREGION || (ret == COMPLEXREGION && GetSystemMetrics(SM_CMONITORS) > 1), "expected SIMPLEREGION, got %d\n", ret); ret = GetClipRgn(hdc, hrgn); ok(ret == 1, "expected 1, got %d\n", ret); ret = GetRgnBox(hrgn, &rc); ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret); ok(rc.left == 0 && rc.top == 0 && rc.right == screen_width && rc.bottom == screen_height, "expected 0,0-%d,%d, got %d,%d-%d,%d\n", screen_width, screen_height, rc.left, rc.top, rc.right, rc.bottom); ret = ExtSelectClipRgn(hdc, 0, RGN_COPY); ok(ret == SIMPLEREGION || (ret == COMPLEXREGION && GetSystemMetrics(SM_CMONITORS) > 1), "expected SIMPLEREGION, got %d\n", ret); ret = GetClipRgn(hdc, hrgn); ok(ret == 0, "expected 0, got %d\n", ret); DeleteDC(hdc); DeleteObject(hrgn); DeleteObject(hrgn_empty); DestroyWindow(hwnd); }
/* * @implemented */ int WINAPI SelectClipRgn( _In_ HDC hdc, _In_ HRGN hrgn) { return ExtSelectClipRgn(hdc, hrgn, RGN_COPY); }
ClipRect(HDC m_hDC, RECT& newClipRect) : m_old(m_hDC) { RECT rcClip = newClipRect; ::LPtoDP(m_hDC, (LPPOINT)&rcClip, 2); m_hNewRegionClip = CreateRectRgnIndirect(&rcClip); ///SelectClipRgn(m_hDC, m_hNewRegionClip); ExtSelectClipRgn(m_hDC, m_hNewRegionClip, RGN_AND); }
/* PA: Set and get the clipping region of a picture: WinClipRgnPicture takes the intersection of the argument clipRgn with the current clipping region. WinSetClipRgnPicture sets the argument clipRgn as the new clipping region. WinGetClipRgnPicture gets the current clipping region. */ void WinClipRgnPicture (HRGN cliprgn, OSPictContext context) { int error; error = ExtSelectClipRgn (context->hDC, cliprgn, RGN_AND); if (error==ERROR) ErrorExit ("Fatal error in WinClipRgnPicture: ExtSelectClipRgn returned ERROR."); } /* WinClipRgnPicture */
BOOL IntersectClipRect(HDC hdc, int x, int y, int right, int bottom) { /* TODO */ HRGN rgn = CreateRectRgn(x, y, right, bottom); BOOL ret = (ExtSelectClipRgn(hdc, rgn, RGN_AND) != ERROR); DeleteObject(rgn); return ret; }
// // UspAttrTextOut // // Display a line of text previously analyzed with UspAnalyze. The stored // ATTR[] visual-attribute list is used to stylize the text as it is drawn. // // Coloured text-display using Uniscribe is very complicated. // Three passes are required if high-quality text output is the goal. // // Returns: adjusted x-coordinate // int WINAPI UspTextOut ( USPDATA * uspData, HDC hdc, int xpos, int ypos, int lineHeight, int lineAdjustY, RECT * bounds ) { HRGN hrgn, hrgnClip; if(uspData->stringLen == 0 || uspData->glyphCount == 0) return xpos; hrgnClip = CreateRectRgn(0,0,1,1); GetClipRgn(hdc, hrgnClip); // // 1. draw all background colours, including selection-highlights; // selected areas are added to the HDC clipping region which prevents // step#2 (below) from drawing over them // SetBkMode(hdc, OPAQUE); PaintBackground(uspData, hdc, xpos, ypos, lineHeight, bounds); // // 2. draw the text normally. Selected areas are left untouched // because of the clipping-region created in step#1 // SetBkMode(hdc, TRANSPARENT); PaintForeground(uspData, hdc, xpos, ypos + lineAdjustY, bounds, FALSE); // // 3. redraw the text using a single text-selection-colour (i.e. white) // in the same position, directly over the top of the text drawn in step#2 // // Before we do this, the HDC clipping-region is inverted, // so only selection areas are modified this time // hrgn = CreateRectRgnIndirect(bounds); ExtSelectClipRgn(hdc, hrgn, RGN_XOR); SetBkMode(hdc, TRANSPARENT); xpos = PaintForeground(uspData, hdc, xpos, ypos + lineAdjustY, bounds, TRUE); // remove clipping regions SelectClipRgn(hdc, hrgnClip); DeleteObject(hrgn); DeleteObject(hrgnClip); return xpos; }
/* * @implemented * */ HGDIOBJ WINAPI SelectObject( _In_ HDC hdc, _In_ HGDIOBJ hobj) { /* Fix up 16 bit handles */ hobj = GdiFixUpHandle(hobj); if (!GdiIsHandleValid(hobj)) { return NULL; } /* Call the appropriate select function */ switch (GDI_HANDLE_GET_TYPE(hobj)) { case GDILoObjType_LO_REGION_TYPE: return (HGDIOBJ)ExtSelectClipRgn(hdc, hobj, RGN_COPY); case GDILoObjType_LO_BITMAP_TYPE: case GDILoObjType_LO_DIBSECTION_TYPE: return GdiSelectBitmap(hdc, hobj); case GDILoObjType_LO_BRUSH_TYPE: return GdiSelectBrush(hdc, hobj); case GDILoObjType_LO_PEN_TYPE: case GDILoObjType_LO_EXTPEN_TYPE: return GdiSelectPen(hdc, hobj); case GDILoObjType_LO_FONT_TYPE: return GdiSelectFont(hdc, hobj); case GDILoObjType_LO_ICMLCS_TYPE: return SetColorSpace(hdc, hobj); case GDILoObjType_LO_PALETTE_TYPE: SetLastError(ERROR_INVALID_FUNCTION); default: return NULL; } return NULL; }
void VDVideoWindow::NCPaint(HRGN hrgn) { HDC hdc; // MSDN docs are in error -- if you do not include 0x10000, GetDCEx() will // return NULL but still won't set an error flag. Feng Yuan's Windows // Graphics book calls this the "undocumented flag that makes GetDCEx() // succeed" flag. ^^; // // WINE's source code documents it as DCX_USESTYLE, which makes more sense, // and that is the way WINE's DefWindowProc() handles WM_NCPAINT. This is // a cleaner solution than using DCX_CACHE, which also works but overrides // CS_OWNDC and CS_PARENTDC. I'm not going to argue with years of reverse // engineering. // // NOTE: Using DCX_INTERSECTRGN as recommended by MSDN causes Windows 98 // GDI to intermittently crash! hdc = GetDCEx(mhwnd, NULL, DCX_WINDOW|0x10000); if (hdc) { RECT rc; GetWindowRect(mhwnd, &rc); if ((WPARAM)hrgn > 1) { OffsetClipRgn(hdc, rc.left, rc.top); ExtSelectClipRgn(hdc, hrgn, RGN_AND); OffsetClipRgn(hdc, -rc.left, -rc.top); } OffsetRect(&rc, -rc.left, -rc.top); DrawEdge(hdc, &rc, BDR_RAISEDOUTER|BDR_RAISEDINNER, BF_RECT); rc.left += 2; rc.right -= 2; rc.top += 2; rc.bottom -= 2; DrawEdge(hdc, &rc, BDR_SUNKENOUTER|BDR_SUNKENINNER, BF_RECT); ReleaseDC(mhwnd, hdc); } }
//////////////////////////////////////////////////////////////////////////////// // Draws (stretch) the image with transparency & alpha support // > hdc: destination device context // > x,y: (optional) offset // > cx,cy: (optional) size. long CxImage::Draw(HDC hdc, long x, long y, long cx, long cy, RECT* pClipRect) { if((pDib==0)||(hdc==0)||(cx==0)||(cy==0)||(!info.bEnabled)) return 0; if (cx < 0) cx = head.biWidth; if (cy < 0) cy = head.biHeight; bool bTransparent = info.nBkgndIndex != -1; bool bAlpha = pAlpha != 0; RECT mainbox; // (experimental) if (pClipRect){ GetClipBox(hdc,&mainbox); HRGN rgn = CreateRectRgnIndirect(pClipRect); ExtSelectClipRgn(hdc,rgn,RGN_AND); DeleteObject(rgn); } if (!(bTransparent || bAlpha || info.bAlphaPaletteEnabled)){ if (cx==head.biWidth && cy==head.biHeight){ //NORMAL SetStretchBltMode(hdc,COLORONCOLOR); SetDIBitsToDevice(hdc, x, y, cx, cy, 0, 0, 0, cy, info.pImage,(BITMAPINFO*)pDib,DIB_RGB_COLORS); } else { //STRETCH RECT clipbox,paintbox; GetClipBox(hdc,&clipbox); paintbox.left = min(clipbox.right,max(clipbox.left,x)); paintbox.right = max(clipbox.left,min(clipbox.right,x+cx)); paintbox.top = min(clipbox.bottom,max(clipbox.top,y)); paintbox.bottom = max(clipbox.top,min(clipbox.bottom,y+cy)); long destw = paintbox.right - paintbox.left; long desth = paintbox.bottom - paintbox.top; //pixel informations RGBQUAD c={0,0,0,0}; //Preparing Bitmap Info BITMAPINFO bmInfo; memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER)); bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); bmInfo.bmiHeader.biWidth=destw; bmInfo.bmiHeader.biHeight=desth; bmInfo.bmiHeader.biPlanes=1; bmInfo.bmiHeader.biBitCount=24; BYTE *pbase; //points to the final dib BYTE *pdst; //current pixel from pbase BYTE *ppix; //current pixel from image //get the background HDC TmpDC=CreateCompatibleDC(hdc); HBITMAP TmpBmp=CreateDIBSection(hdc,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0); HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp); if (pbase){ long xx,yy,yoffset; long ew = ((((24 * destw) + 31) / 32) * 4); long ymax = paintbox.bottom; long xmin = paintbox.left; float fx=(float)head.biWidth/(float)cx; float fy=(float)head.biHeight/(float)cy; long sx,sy; for(yy=0;yy<desth;yy++){ sy=max(0L,head.biHeight-(long)ceil(((ymax-yy-y)*fy))); yoffset=sy*head.biWidth; pdst=pbase+yy*ew; for(xx=0;xx<destw;xx++){ sx=(long)floor(((xx+xmin-x)*fx)); if (head.biClrUsed){ c=GetPaletteColor(GetPixelIndex(sx,sy)); } else { ppix=info.pImage+sy*info.dwEffWidth+sx*3; c.rgbBlue = *ppix++; c.rgbGreen= *ppix++; c.rgbRed = *ppix; } *pdst++=c.rgbBlue; *pdst++=c.rgbGreen; *pdst++=c.rgbRed; } } } //paint the image & cleanup SetDIBitsToDevice(hdc,paintbox.left,paintbox.top,destw,desth,0,0,0,desth,pbase,&bmInfo,0); DeleteObject(SelectObject(TmpDC,TmpObj)); DeleteDC(TmpDC); } } else { // draw image with transparent/alpha blending ////////////////////////////////////////////////////////////////// //Alpha blend - Thanks to Florian Egel //find the smallest area to paint RECT clipbox,paintbox; GetClipBox(hdc,&clipbox); paintbox.left = min(clipbox.right,max(clipbox.left,x)); paintbox.right = max(clipbox.left,min(clipbox.right,x+cx)); paintbox.top = min(clipbox.bottom,max(clipbox.top,y)); paintbox.bottom = max(clipbox.top,min(clipbox.bottom,y+cy)); long destw = paintbox.right - paintbox.left; long desth = paintbox.bottom - paintbox.top; //pixel informations RGBQUAD c={0,0,0,0}; RGBQUAD ct = GetTransColor(); long* pc = (long*)&c; long* pct= (long*)&ct; //Preparing Bitmap Info BITMAPINFO bmInfo; memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER)); bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); bmInfo.bmiHeader.biWidth=destw; bmInfo.bmiHeader.biHeight=desth; bmInfo.bmiHeader.biPlanes=1; bmInfo.bmiHeader.biBitCount=24; BYTE *pbase; //points to the final dib BYTE *pdst; //current pixel from pbase BYTE *ppix; //current pixel from image //get the background HDC TmpDC=CreateCompatibleDC(hdc); HBITMAP TmpBmp=CreateDIBSection(hdc,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0); HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp); BitBlt(TmpDC,0,0,destw,desth,hdc,paintbox.left,paintbox.top,SRCCOPY); if (pbase){ long xx,yy,yoffset,ix,iy; BYTE a,a1; long ew = ((((24 * destw) + 31) / 32) * 4); long ymax = paintbox.bottom; long xmin = paintbox.left; if (cx!=head.biWidth || cy!=head.biHeight){ //STRETCH float fx=(float)head.biWidth/(float)cx; float fy=(float)head.biHeight/(float)cy; long sx,sy; for(yy=0;yy<desth;yy++){ sy=max(0L,head.biHeight-(long)ceil(((ymax-yy-y)*fy))); yoffset=sy*head.biWidth; pdst=pbase+yy*ew; for(xx=0;xx<destw;xx++){ sx=(long)floor(((xx+xmin-x)*fx)); if (bAlpha) a=pAlpha[yoffset+sx]; else a=255; a =(BYTE)((a*(1+info.nAlphaMax))>>8); if (head.biClrUsed){ c=GetPaletteColor(GetPixelIndex(sx,sy)); if (info.bAlphaPaletteEnabled){ a= (BYTE)((a*(1+c.rgbReserved))>>8); } } else { ppix=info.pImage+sy*info.dwEffWidth+sx*3; c.rgbBlue = *ppix++; c.rgbGreen= *ppix++; c.rgbRed = *ppix; } if (*pc!=*pct || !bTransparent){ // DJT, assume many pixels are fully transparent or opaque and thus avoid multiplication if (a == 0) { // Transparent, retain dest pdst+=3; } else if (a == 255) { // opaque, ignore dest *pdst++= c.rgbBlue; *pdst++= c.rgbGreen; *pdst++= c.rgbRed; } else { // semi transparent a1=(BYTE)~a; *pdst++=(BYTE)((*pdst * a1 + a * c.rgbBlue)>>8); *pdst++=(BYTE)((*pdst * a1 + a * c.rgbGreen)>>8); *pdst++=(BYTE)((*pdst * a1 + a * c.rgbRed)>>8); } } else { pdst+=3; } }
static void test_dc_layout(void) { INT ret, size_cx, size_cy, res_x, res_y, dpi_x, dpi_y; SIZE size; POINT pt; HBITMAP bitmap; RECT rc, ret_rc; HDC hdc; HRGN hrgn; if (!pGetLayout || !pSetLayout) { win_skip( "Don't have SetLayout\n" ); return; } hdc = CreateCompatibleDC(0); bitmap = CreateCompatibleBitmap( hdc, 100, 100 ); SelectObject( hdc, bitmap ); size_cx = GetDeviceCaps(hdc, HORZSIZE); size_cy = GetDeviceCaps(hdc, VERTSIZE); res_x = GetDeviceCaps(hdc, HORZRES); res_y = GetDeviceCaps(hdc, VERTRES); dpi_x = GetDeviceCaps(hdc, LOGPIXELSX); dpi_y = GetDeviceCaps(hdc, LOGPIXELSY); ret = GetMapMode( hdc ); ok(ret == MM_TEXT, "expected MM_TEXT, got %d\n", ret); expect_viewport_ext(hdc, 1, 1); expect_window_ext(hdc, 1, 1); expect_world_transform(hdc, 1.0, 1.0); expect_LPtoDP(hdc, 1000, 1000); pSetLayout( hdc, LAYOUT_RTL ); if (!pGetLayout( hdc )) { win_skip( "SetLayout not supported\n" ); DeleteDC(hdc); return; } ret = GetMapMode( hdc ); ok(ret == MM_ANISOTROPIC, "expected MM_ANISOTROPIC, got %d\n", ret); expect_viewport_ext(hdc, 1, 1); expect_window_ext(hdc, 1, 1); expect_world_transform(hdc, 1.0, 1.0); expect_LPtoDP(hdc, -1000 + 99, 1000); GetViewportOrgEx( hdc, &pt ); ok( pt.x == 0 && pt.y == 0, "wrong origin %d,%d\n", pt.x, pt.y ); GetWindowOrgEx( hdc, &pt ); ok( pt.x == 0 && pt.y == 0, "wrong origin %d,%d\n", pt.x, pt.y ); GetDCOrgEx( hdc, &pt ); ok( pt.x == 0 && pt.y == 0, "wrong origin %d,%d\n", pt.x, pt.y ); if (pGetTransform) { XFORM xform; BOOL ret = pGetTransform( hdc, 0x204, &xform ); /* World -> Device */ ok( ret, "got %d\n", ret ); ok( xform.eM11 == -1.0, "got %f\n", xform.eM11 ); ok( xform.eM12 == 0.0, "got %f\n", xform.eM12 ); ok( xform.eM21 == 0.0, "got %f\n", xform.eM21 ); ok( xform.eM22 == 1.0, "got %f\n", xform.eM22 ); ok( xform.eDx == 99.0, "got %f\n", xform.eDx ); ok( xform.eDy == 0.0, "got %f\n", xform.eDy ); } SetRect( &rc, 10, 10, 20, 20 ); IntersectClipRect( hdc, 10, 10, 20, 20 ); hrgn = CreateRectRgn( 0, 0, 0, 0 ); GetClipRgn( hdc, hrgn ); GetRgnBox( hrgn, &ret_rc ); ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n", ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom ); pSetLayout( hdc, LAYOUT_LTR ); SetRect( &rc, 80, 10, 90, 20 ); GetClipRgn( hdc, hrgn ); GetRgnBox( hrgn, &ret_rc ); ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n", ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom ); GetClipBox( hdc, &ret_rc ); ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n", ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom ); IntersectClipRect( hdc, 80, 10, 85, 20 ); pSetLayout( hdc, LAYOUT_RTL ); SetRect( &rc, 15, 10, 20, 20 ); GetClipRgn( hdc, hrgn ); GetRgnBox( hrgn, &ret_rc ); ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n", ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom ); GetClipBox( hdc, &ret_rc ); ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n", ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom ); SetRectRgn( hrgn, 60, 10, 80, 20 ); pSetLayout( hdc, LAYOUT_LTR ); ExtSelectClipRgn( hdc, hrgn, RGN_OR ); pSetLayout( hdc, LAYOUT_RTL ); SetRect( &rc, 15, 10, 40, 20 ); GetClipRgn( hdc, hrgn ); GetRgnBox( hrgn, &ret_rc ); ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n", ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom ); GetClipBox( hdc, &ret_rc ); ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n", ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom ); /* OffsetClipRgn mirrors too */ OffsetClipRgn( hdc, 5, 5 ); OffsetRect( &rc, 5, 5 ); GetClipRgn( hdc, hrgn ); GetRgnBox( hrgn, &ret_rc ); ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n", ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom ); /* GetRandomRgn returns the raw region */ if (pGetRandomRgn) { SetRect( &rc, 55, 15, 80, 25 ); pGetRandomRgn( hdc, hrgn, 1 ); GetRgnBox( hrgn, &ret_rc ); ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n", ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom ); } SetMapMode(hdc, MM_LOMETRIC); ret = GetMapMode( hdc ); ok(ret == MM_ANISOTROPIC, "expected MM_ANISOTROPIC, got %d\n", ret); expect_viewport_ext(hdc, res_x, -res_y); ok( GetWindowExtEx( hdc, &size ), "GetWindowExtEx failed\n" ); ok( rough_match( size.cx, size_cx * 10 ) || rough_match( size.cx, MulDiv( res_x, 254, dpi_x )), /* Vista uses a more precise method */ "expected cx %d or %d, got %d\n", size_cx * 10, MulDiv( res_x, 254, dpi_x ), size.cx ); ok( rough_match( size.cy, size_cy * 10 ) || rough_match( size.cy, MulDiv( res_y, 254, dpi_y )), /* Vista uses a more precise method */ "expected cy %d or %d, got %d\n", size_cy * 10, MulDiv( res_y, 254, dpi_y ), size.cy ); expect_world_transform(hdc, 1.0, 1.0); expect_LPtoDP(hdc, -MulDiv(1000 / 10, res_x, size_cx) + 99, -MulDiv(1000 / 10, res_y, size_cy)); SetMapMode(hdc, MM_TEXT); ret = GetMapMode( hdc ); ok(ret == MM_ANISOTROPIC, "expected MM_ANISOTROPIC, got %d\n", ret); pSetLayout( hdc, LAYOUT_LTR ); ret = GetMapMode( hdc ); ok(ret == MM_ANISOTROPIC, "expected MM_ANISOTROPIC, got %d\n", ret); SetMapMode(hdc, MM_TEXT); ret = GetMapMode( hdc ); ok(ret == MM_TEXT, "expected MM_TEXT, got %d\n", ret); DeleteDC(hdc); DeleteObject( bitmap ); }
static void draw_graphics(HDC hdc, BITMAPINFO *bmi, BYTE *bits, const char ***sha1) { DWORD dib_size = get_dib_size(bmi); HPEN solid_pen, dashed_pen, orig_pen; HBRUSH solid_brush, dib_brush, hatch_brush, orig_brush; INT i, y, hatch_style; HRGN hrgn, hrgn2; BYTE dib_brush_buf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD) + 16 * 16 * sizeof(DWORD)]; /* Enough for 16 x 16 at 32 bpp */ BITMAPINFO *brush_bi = (BITMAPINFO*)dib_brush_buf; BYTE *brush_bits; BOOL dib_is_1bpp = (bmi->bmiHeader.biBitCount == 1); memset(bits, 0xcc, dib_size); compare_hash(bmi, bits, sha1, "empty"); solid_pen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0xff)); orig_pen = SelectObject(hdc, solid_pen); SetBrushOrgEx(hdc, 0, 0, NULL); /* horizontal and vertical lines */ for(i = 1; i <= 16; i++) { SetROP2(hdc, i); MoveToEx(hdc, 10, i * 3, NULL); LineTo(hdc, 100, i * 3); /* l -> r */ MoveToEx(hdc, 100, 50 + i * 3, NULL); LineTo(hdc, 10, 50 + i * 3); /* r -> l */ MoveToEx(hdc, 120 + i * 3, 10, NULL); LineTo(hdc, 120 + i * 3, 100); /* t -> b */ MoveToEx(hdc, 170 + i * 3, 100, NULL); LineTo(hdc, 170 + i * 3, 10); /* b -> t */ } compare_hash(bmi, bits, sha1, "h and v solid lines"); memset(bits, 0xcc, dib_size); /* diagonal lines */ SetROP2(hdc, R2_COPYPEN); for(i = 0; i < 16; i++) { double s = sin(M_PI * i / 8.0); double c = cos(M_PI * i / 8.0); MoveToEx(hdc, 200.5 + 10 * c, 200.5 + 10 * s, NULL); LineTo(hdc, 200.5 + 100 * c, 200.5 + 100 * s); } compare_hash(bmi, bits, sha1, "diagonal solid lines"); memset(bits, 0xcc, dib_size); for(i = 0; i < sizeof(bias_check) / sizeof(bias_check[0]); i++) { MoveToEx(hdc, bias_check[i].left, bias_check[i].top, NULL); LineTo(hdc, bias_check[i].right, bias_check[i].bottom); } compare_hash(bmi, bits, sha1, "more diagonal solid lines"); memset(bits, 0xcc, dib_size); /* solid brush PatBlt */ solid_brush = CreateSolidBrush(RGB(0x33, 0xaa, 0xff)); orig_brush = SelectObject(hdc, solid_brush); for(i = 0, y = 10; i < 256; i++) { BOOL ret; ret = PatBlt(hdc, 10, y, 100, 10, rop3[i]); if(rop_uses_src(rop3[i])) ok(ret == FALSE, "got TRUE for %x\n", rop3[i]); else { ok(ret, "got FALSE for %x\n", rop3[i]); y += 20; } } compare_hash(bmi, bits, sha1, "solid patblt"); memset(bits, 0xcc, dib_size); /* clipped lines */ hrgn = CreateRectRgn(10, 10, 200, 20); hrgn2 = CreateRectRgn(100, 100, 200, 200); CombineRgn(hrgn, hrgn, hrgn2, RGN_OR); SetRectRgn(hrgn2, 290, 100, 300, 200); CombineRgn(hrgn, hrgn, hrgn2, RGN_OR); ExtSelectClipRgn(hdc, hrgn, RGN_COPY); DeleteObject(hrgn2); for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++) { MoveToEx(hdc, hline_clips[i].left, hline_clips[i].top, NULL); LineTo(hdc, hline_clips[i].right, hline_clips[i].bottom); } compare_hash(bmi, bits, sha1, "clipped solid hlines"); memset(bits, 0xcc, dib_size); for(i = 0; i < sizeof(vline_clips)/sizeof(vline_clips[0]); i++) { MoveToEx(hdc, vline_clips[i].left, vline_clips[i].top, NULL); LineTo(hdc, vline_clips[i].right, vline_clips[i].bottom); } compare_hash(bmi, bits, sha1, "clipped solid vlines"); memset(bits, 0xcc, dib_size); for(i = 0; i < sizeof(line_clips)/sizeof(line_clips[0]); i++) { MoveToEx(hdc, line_clips[i].left, line_clips[i].top, NULL); LineTo(hdc, line_clips[i].right, line_clips[i].bottom); } compare_hash(bmi, bits, sha1, "clipped solid diagonal lines"); memset(bits, 0xcc, dib_size); /* clipped PatBlt */ for(i = 0; i < sizeof(patblt_clips) / sizeof(patblt_clips[0]); i++) { PatBlt(hdc, patblt_clips[i].left, patblt_clips[i].top, patblt_clips[i].right - patblt_clips[i].left, patblt_clips[i].bottom - patblt_clips[i].top, PATCOPY); } compare_hash(bmi, bits, sha1, "clipped patblt"); memset(bits, 0xcc, dib_size); /* clipped dashed lines */ dashed_pen = CreatePen(PS_DASH, 1, RGB(0xff, 0, 0)); SelectObject(hdc, dashed_pen); SetBkMode(hdc, TRANSPARENT); SetBkColor(hdc, RGB(0, 0xff, 0)); for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++) { MoveToEx(hdc, hline_clips[i].left, hline_clips[i].top, NULL); LineTo(hdc, hline_clips[i].right, hline_clips[i].bottom); } compare_hash(bmi, bits, sha1, "clipped dashed hlines"); memset(bits, 0xcc, dib_size); for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++) { MoveToEx(hdc, hline_clips[i].right - 1, hline_clips[i].bottom, NULL); LineTo(hdc, hline_clips[i].left - 1, hline_clips[i].top); } compare_hash(bmi, bits, sha1, "clipped dashed hlines r -> l"); memset(bits, 0xcc, dib_size); for(i = 0; i < sizeof(vline_clips)/sizeof(vline_clips[0]); i++) { MoveToEx(hdc, vline_clips[i].left, vline_clips[i].top, NULL); LineTo(hdc, vline_clips[i].right, vline_clips[i].bottom); } compare_hash(bmi, bits, sha1, "clipped dashed vlines"); memset(bits, 0xcc, dib_size); for(i = 0; i < sizeof(vline_clips)/sizeof(vline_clips[0]); i++) { MoveToEx(hdc, vline_clips[i].right, vline_clips[i].bottom - 1, NULL); LineTo(hdc, vline_clips[i].left, vline_clips[i].top - 1); } compare_hash(bmi, bits, sha1, "clipped dashed vlines b -> t"); memset(bits, 0xcc, dib_size); for(i = 0; i < sizeof(line_clips)/sizeof(line_clips[0]); i++) { MoveToEx(hdc, line_clips[i].left, line_clips[i].top, NULL); LineTo(hdc, line_clips[i].right, line_clips[i].bottom); } compare_hash(bmi, bits, sha1, "clipped dashed diagonal lines"); memset(bits, 0xcc, dib_size); SetBkMode(hdc, OPAQUE); for(i = 0; i < sizeof(line_clips)/sizeof(line_clips[0]); i++) { MoveToEx(hdc, line_clips[i].left, line_clips[i].top, NULL); LineTo(hdc, line_clips[i].right, line_clips[i].bottom); } compare_hash(bmi, bits, sha1, "clipped opaque dashed diagonal lines"); memset(bits, 0xcc, dib_size); ExtSelectClipRgn(hdc, NULL, RGN_COPY); /* 8888 DIB pattern brush */ brush_bi->bmiHeader = dib_brush_header_8888; brush_bits = (BYTE*)brush_bi + sizeof(BITMAPINFOHEADER); memset(brush_bits, 0, 16 * 16 * sizeof(DWORD)); brush_bits[2] = 0xff; brush_bits[6] = 0xff; brush_bits[14] = 0xff; brush_bits[65] = 0xff; brush_bits[69] = 0xff; brush_bits[72] = 0xff; dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS); SelectObject(hdc, dib_brush); SetBrushOrgEx(hdc, 1, 1, NULL); for(i = 0, y = 10; i < 256; i++) { BOOL ret; if(!rop_uses_src(rop3[i])) { ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]); ok(ret, "got FALSE for %x\n", rop3[i]); y += 25; } } compare_hash_broken_todo(bmi, bits, sha1, "top-down 8888 dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); memset(bits, 0xcc, dib_size); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); /* 8888 bottom-up DIB pattern brush */ brush_bi->bmiHeader.biHeight = -brush_bi->bmiHeader.biHeight; dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS); SelectObject(hdc, dib_brush); /* This used to set the x origin to 100 as well, but there's a Windows bug for 24 bpp where the brush's x offset is incorrectly calculated for rops that involve both D and P */ SetBrushOrgEx(hdc, 4, 100, NULL); for(i = 0, y = 10; i < 256; i++) { BOOL ret; if(!rop_uses_src(rop3[i])) { ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]); ok(ret, "got FALSE for %x\n", rop3[i]); y += 25; } } compare_hash_broken_todo(bmi, bits, sha1, "bottom-up 8888 dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); memset(bits, 0xcc, dib_size); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); /* 24 bpp dib pattern brush */ brush_bi->bmiHeader = dib_brush_header_24; brush_bits = (BYTE*)brush_bi + sizeof(BITMAPINFOHEADER); memset(brush_bits, 0, 16 * 16 * 3); brush_bits[0] = brush_bits[3] = brush_bits[6] = brush_bits[8] = 0xff; brush_bits[49] = brush_bits[52] = 0xff; dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS); SelectObject(hdc, dib_brush); SetBrushOrgEx(hdc, 1, 1, NULL); for(i = 0, y = 10; i < 256; i++) { BOOL ret; if(!rop_uses_src(rop3[i])) { ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]); ok(ret, "got FALSE for %x\n", rop3[i]); y += 25; } } compare_hash_broken_todo(bmi, bits, sha1, "top-down 24 bpp brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); memset(bits, 0xcc, dib_size); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); /* 555 dib pattern brush */ brush_bi->bmiHeader = dib_brush_header_555; brush_bits = (BYTE*)brush_bi + sizeof(BITMAPINFOHEADER); memset(brush_bits, 0, 16 * 16 * sizeof(WORD)); brush_bits[0] = brush_bits[1] = 0xff; brush_bits[32] = brush_bits[34] = 0x7c; dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS); SelectObject(hdc, dib_brush); SetBrushOrgEx(hdc, 1, 1, NULL); for(i = 0, y = 10; i < 256; i++) { BOOL ret; if(!rop_uses_src(rop3[i])) { ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]); ok(ret, "got FALSE for %x\n", rop3[i]); y += 25; } } compare_hash_broken_todo(bmi, bits, sha1, "top-down 555 dib brush patblt", dib_is_1bpp ? 1 : 0, dib_is_1bpp); memset(bits, 0xcc, dib_size); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); SetBrushOrgEx(hdc, 0, 0, NULL); /* 8 bpp dib pattern brush */ brush_bi->bmiHeader = dib_brush_header_8; brush_bi->bmiHeader.biClrUsed = 3; memset(brush_bi->bmiColors, 0, brush_bi->bmiHeader.biClrUsed * sizeof(RGBQUAD)); brush_bi->bmiColors[0].rgbRed = 0xff; brush_bi->bmiColors[1].rgbRed = 0xff; brush_bi->bmiColors[1].rgbGreen = 0xff; brush_bi->bmiColors[1].rgbBlue = 0xff; brush_bits = (BYTE*)brush_bi + sizeof(BITMAPINFOHEADER) + brush_bi->bmiHeader.biClrUsed * sizeof(RGBQUAD); memset(brush_bits, 0, 16 * 16 * sizeof(BYTE)); brush_bits[0] = brush_bits[1] = 1; brush_bits[16] = brush_bits[17] = 2; brush_bits[32] = brush_bits[33] = 6; dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS); SelectObject(hdc, dib_brush); SetBrushOrgEx(hdc, 1, 1, NULL); for(i = 0, y = 10; i < 256; i++) { BOOL ret; if(!rop_uses_src(rop3[i])) { ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]); ok(ret, "got FALSE for %x\n", rop3[i]); y += 25; } } compare_hash_broken_todo(bmi, bits, sha1, "top-down 8 bpp dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); memset(bits, 0xcc, dib_size); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); /* 4 bpp dib pattern brush */ brush_bi->bmiHeader = dib_brush_header_4; dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS); SelectObject(hdc, dib_brush); SetBrushOrgEx(hdc, 1, 1, NULL); for(i = 0, y = 10; i < 256; i++) { BOOL ret; if(!rop_uses_src(rop3[i])) { ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]); ok(ret, "got FALSE for %x\n", rop3[i]); y += 25; } } compare_hash_broken_todo(bmi, bits, sha1, "top-down 4 bpp dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); memset(bits, 0xcc, dib_size); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); /* 1 bpp dib pattern brush */ brush_bi->bmiHeader = dib_brush_header_1; brush_bi->bmiHeader.biClrUsed = 2; memset(brush_bits, 0, 16 * 4); brush_bits[0] = 0xf0; brush_bits[4] = 0xf0; brush_bits[8] = 0xf0; dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS); SelectObject(hdc, dib_brush); for(i = 0, y = 10; i < 256; i++) { BOOL ret; if(!rop_uses_src(rop3[i])) { ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]); ok(ret, "got FALSE for %x\n", rop3[i]); y += 25; } } compare_hash_broken_todo(bmi, bits, sha1, "top-down 1 bpp dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); memset(bits, 0xcc, dib_size); SelectObject(hdc, orig_brush); SetBrushOrgEx(hdc, 0, 0, NULL); /* Rectangle */ SelectObject(hdc, solid_pen); SelectObject(hdc, solid_brush); for(i = 0; i < sizeof(rectangles)/sizeof(rectangles[0]); i++) { Rectangle(hdc, rectangles[i].left, rectangles[i].top, rectangles[i].right, rectangles[i].bottom); } SelectObject(hdc, dashed_pen); for(i = 0; i < sizeof(rectangles)/sizeof(rectangles[0]); i++) { Rectangle(hdc, rectangles[i].left, rectangles[i].top + 150, rectangles[i].right, rectangles[i].bottom + 150); } compare_hash(bmi, bits, sha1, "rectangles"); memset(bits, 0xcc, dib_size); SelectObject(hdc, solid_pen); /* PaintRgn */ PaintRgn(hdc, hrgn); compare_hash(bmi, bits, sha1, "PaintRgn"); memset(bits, 0xcc, dib_size); /* RTL rectangles */ if( !pSetLayout ) { win_skip("Don't have SetLayout\n"); (*sha1)++; } else { pSetLayout(hdc, LAYOUT_RTL); PaintRgn(hdc, hrgn); PatBlt(hdc, 10, 250, 10, 10, PATCOPY); Rectangle(hdc, 100, 250, 110, 260); compare_hash(bmi, bits, sha1, "rtl"); memset(bits, 0xcc, dib_size); pSetLayout(hdc, LAYOUT_LTR); } for(i = 0, y = 10; i < 256; i++) { BOOL ret; if(!rop_uses_src(rop3[i])) { for(hatch_style = HS_HORIZONTAL; hatch_style <= HS_DIAGCROSS; hatch_style++) { hatch_brush = CreateHatchBrush(hatch_style, RGB(0xff, 0, 0)); SelectObject(hdc, hatch_brush); ret = PatBlt(hdc, 10 + i + 30 * hatch_style, y, 20, 20, rop3[i]); ok(ret, "got FALSE for %x\n", rop3[i]); SelectObject(hdc, orig_brush); DeleteObject(hatch_brush); } y += 25; } } compare_hash_broken_todo(bmi, bits, sha1, "hatch brushes", 1, FALSE); /* nt4 is different */ memset(bits, 0xcc, dib_size); SelectObject(hdc, orig_brush); SelectObject(hdc, orig_pen); DeleteObject(hrgn); DeleteObject(dib_brush); DeleteObject(dashed_pen); DeleteObject(solid_brush); DeleteObject(solid_pen); }
void clipper_t::merge(int x, int y, int w, int h) { temp_object_t reg(CreateRectRgn(x, y, x+w, y+h)); ExtSelectClipRgn(hdc, (HRGN)reg.handle, RGN_OR); }
/************************************************************************* * ScrollDC (X11DRV.@) */ BOOL X11DRV_ScrollDC( HDC hdc, INT dx, INT dy, const RECT *lprcScroll, const RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate ) { RECT rcSrc, rcClip, offset; INT dxdev, dydev, res; HRGN DstRgn, clipRgn, visrgn; INT code = X11DRV_START_EXPOSURES; TRACE("dx,dy %d,%d rcScroll %s rcClip %s hrgnUpdate %p lprcUpdate %p\n", dx, dy, wine_dbgstr_rect(lprcScroll), wine_dbgstr_rect(lprcClip), hrgnUpdate, lprcUpdate); /* enable X-exposure events */ if (hrgnUpdate || lprcUpdate) ExtEscape( hdc, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code, 0, NULL ); /* get the visible region */ visrgn=CreateRectRgn( 0, 0, 0, 0); GetRandomRgn( hdc, visrgn, SYSRGN); if( !(GetVersion() & 0x80000000)) { /* Window NT/2k/XP */ POINT org; GetDCOrgEx(hdc, &org); OffsetRgn( visrgn, -org.x, -org.y); } /* intersect with the clipping Region if the DC has one */ clipRgn = CreateRectRgn( 0, 0, 0, 0); if (GetClipRgn( hdc, clipRgn) != 1) { DeleteObject(clipRgn); clipRgn=NULL; } else CombineRgn( visrgn, visrgn, clipRgn, RGN_AND); /* only those pixels in the scroll rectangle that remain in the clipping * rect are scrolled. */ if( lprcClip) rcClip = *lprcClip; else GetClipBox( hdc, &rcClip); rcSrc = rcClip; OffsetRect( &rcClip, -dx, -dy); IntersectRect( &rcSrc, &rcSrc, &rcClip); /* if an scroll rectangle is specified, only the pixels within that * rectangle are scrolled */ if( lprcScroll) IntersectRect( &rcSrc, &rcSrc, lprcScroll); /* now convert to device coordinates */ LPtoDP(hdc, (LPPOINT)&rcSrc, 2); TRACE("source rect: %s\n", wine_dbgstr_rect(&rcSrc)); /* also dx and dy */ SetRect(&offset, 0, 0, dx, dy); LPtoDP(hdc, (LPPOINT)&offset, 2); dxdev = offset.right - offset.left; dydev = offset.bottom - offset.top; /* now intersect with the visible region to get the pixels that will * actually scroll */ DstRgn = CreateRectRgnIndirect( &rcSrc); res = CombineRgn( DstRgn, DstRgn, visrgn, RGN_AND); /* and translate, giving the destination region */ OffsetRgn( DstRgn, dxdev, dydev); if( TRACE_ON( scroll)) dump_region( "Destination scroll region: ", DstRgn); /* if there are any, do it */ if( res > NULLREGION) { RECT rect ; /* clip to the destination region, so we can BitBlt with a simple * bounding rectangle */ if( clipRgn) ExtSelectClipRgn( hdc, DstRgn, RGN_AND); else SelectClipRgn( hdc, DstRgn); GetRgnBox( DstRgn, &rect); DPtoLP(hdc, (LPPOINT)&rect, 2); TRACE("destination rect: %s\n", wine_dbgstr_rect(&rect)); BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, hdc, rect.left - dx, rect.top - dy, SRCCOPY); } /* compute the update areas. This is the combined clip rectangle * minus the scrolled region, and intersected with the visible * region. */ if (hrgnUpdate || lprcUpdate) { HRGN hrgn = hrgnUpdate; HRGN ExpRgn = 0; /* collect all the exposures */ code = X11DRV_END_EXPOSURES; ExtEscape( hdc, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code, sizeof(ExpRgn), (LPSTR)&ExpRgn ); /* Intersect clip and scroll rectangles, allowing NULL values */ if( lprcScroll) if( lprcClip) IntersectRect( &rcClip, lprcClip, lprcScroll); else rcClip = *lprcScroll; else if( lprcClip) rcClip = *lprcClip; else GetClipBox( hdc, &rcClip); /* Convert the combined clip rectangle to device coordinates */ LPtoDP(hdc, (LPPOINT)&rcClip, 2); if( hrgn ) SetRectRgn( hrgn, rcClip.left, rcClip.top, rcClip.right, rcClip.bottom); else hrgn = CreateRectRgnIndirect( &rcClip); CombineRgn( hrgn, hrgn, visrgn, RGN_AND); CombineRgn( hrgn, hrgn, DstRgn, RGN_DIFF); /* add the exposures to this */ if( ExpRgn) { if( TRACE_ON( scroll)) dump_region( "Expose region: ", ExpRgn); CombineRgn( hrgn, hrgn, ExpRgn, RGN_OR); DeleteObject( ExpRgn); } if( TRACE_ON( scroll)) dump_region( "Update region: ", hrgn); if( lprcUpdate) { GetRgnBox( hrgn, lprcUpdate ); /* Put the lprcUpdate in logical coordinates */ DPtoLP( hdc, (LPPOINT)lprcUpdate, 2 ); TRACE("returning lprcUpdate %s\n", wine_dbgstr_rect(lprcUpdate)); } if( !hrgnUpdate) DeleteObject( hrgn); } /* restore original clipping region */ SelectClipRgn( hdc, clipRgn); DeleteObject( visrgn); DeleteObject( DstRgn); if( clipRgn) DeleteObject( clipRgn); return TRUE; }
void CPlayerSeekBar::OnPaint() { CPaintDC dc(this); COLORREF dark = GetSysColor(COLOR_GRAYTEXT), white = GetSysColor(COLOR_WINDOW), shadow = GetSysColor(COLOR_3DSHADOW), light = GetSysColor(COLOR_3DHILIGHT), bkg = GetSysColor(COLOR_BTNFACE); // Thumb { auto& pThumb = m_bEnabled ? m_pEnabledThumb : m_pDisabledThumb; if (!pThumb) { CreateThumb(m_bEnabled, dc); ASSERT(pThumb); } CRect r(GetThumbRect()); CRect ri(GetInnerThumbRect(m_bEnabled, r)); CRgn rg, rgi; VERIFY(rg.CreateRectRgnIndirect(&r)); VERIFY(rgi.CreateRectRgnIndirect(&ri)); ExtSelectClipRgn(dc, rgi, RGN_DIFF); VERIFY(dc.BitBlt(r.TopLeft().x, r.TopLeft().y, r.Width(), r.Height(), pThumb.get(), 0, 0, SRCCOPY)); ExtSelectClipRgn(dc, rg, RGN_XOR); m_lastThumbRect = r; } const CRect channelRect(GetChannelRect()); // Chapters if (m_bHasDuration) { CAutoLock lock(&m_csChapterBag); if (m_pChapterBag) { for (DWORD i = 0; i < m_pChapterBag->ChapGetCount(); i++) { REFERENCE_TIME rtChap; if (SUCCEEDED(m_pChapterBag->ChapGet(i, &rtChap, nullptr))) { long chanPos = channelRect.left + ChannelPointFromPosition(rtChap); CRect r(chanPos, channelRect.top, chanPos + 1, channelRect.bottom); if (r.right < channelRect.right) { r.right++; } ASSERT(r.right <= channelRect.right); dc.FillSolidRect(&r, dark); dc.ExcludeClipRect(&r); } else { ASSERT(FALSE); } } } } // Channel { dc.FillSolidRect(&channelRect, m_bEnabled ? white : bkg); CRect r(channelRect); r.InflateRect(1, 1); dc.Draw3dRect(&r, shadow, light); dc.ExcludeClipRect(&r); } // Background { CRect r; GetClientRect(&r); dc.FillSolidRect(&r, bkg); } }
/*********************************************************************** * SelectClipRgn (GDI32.@) */ INT WINAPI SelectClipRgn( HDC hdc, HRGN hrgn ) { return ExtSelectClipRgn( hdc, hrgn, RGN_COPY ); }
static void test_window_dc_clipping(void) { HDC hdc; HRGN hrgn, hrgn_empty; HWND hwnd; RECT rc, virtual_rect; int ret, screen_width, screen_height; /* Windows versions earlier than Win2k do not support the virtual screen metrics, * so we fall back to the primary screen metrics. */ screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN); if(!screen_width) screen_width = GetSystemMetrics(SM_CXSCREEN); screen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN); if(!screen_height) screen_height = GetSystemMetrics(SM_CYSCREEN); SetRect(&virtual_rect, GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN), GetSystemMetrics(SM_XVIRTUALSCREEN) + screen_width, GetSystemMetrics(SM_YVIRTUALSCREEN) + screen_height); trace("screen resolution %d x %d\n", screen_width, screen_height); hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, -100, -100, screen_width * 2, screen_height * 2, 0, 0, 0, NULL); hdc = GetWindowDC(0); hrgn_empty = CreateRectRgn(0, 0, 0, 0); hrgn = CreateRectRgn(0, 0, 0, 0); ret = GetClipRgn(hdc, hrgn); ok(ret == 0, "expected 0, got %d\n", ret); ret = ExtSelectClipRgn(hdc, 0, RGN_DIFF); ok(ret == 0, "expected 0, got %d\n", ret); ret = GetClipRgn(hdc, hrgn); ok(ret == 0, "expected 0, got %d\n", ret); ret = ExtSelectClipRgn(hdc, hrgn_empty, RGN_DIFF); ok(ret == SIMPLEREGION || (ret == COMPLEXREGION && GetSystemMetrics(SM_CMONITORS) > 1), "expected SIMPLEREGION, got %d\n", ret); ret = GetClipRgn(hdc, hrgn); ok(ret == 1, "expected 1, got %d\n", ret); ret = GetRgnBox(hrgn, &rc); ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret); ok(EqualRect(&rc, &virtual_rect), "expected %s, got %s\n", wine_dbgstr_rect(&virtual_rect), wine_dbgstr_rect(&rc)); SetRect( &rc, 10, 10, 20, 20 ); ret = RectVisible( hdc, &rc ); ok( ret, "RectVisible failed for %s\n", wine_dbgstr_rect(&rc)); SetRect( &rc, 20, 20, 10, 10 ); ret = RectVisible( hdc, &rc ); ok( ret, "RectVisible failed for %s\n", wine_dbgstr_rect(&rc)); ret = ExtSelectClipRgn(hdc, 0, RGN_DIFF); ok(ret == 0, "expected 0, got %d\n", ret); ret = GetClipRgn(hdc, hrgn); ok(ret == 1, "expected 1, got %d\n", ret); ret = GetRgnBox(hrgn, &rc); ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret); ok(EqualRect(&rc, &virtual_rect), "expected %s, got %s\n", wine_dbgstr_rect(&virtual_rect), wine_dbgstr_rect(&rc)); ret = ExtSelectClipRgn(hdc, 0, RGN_COPY); ok(ret == SIMPLEREGION || (ret == COMPLEXREGION && GetSystemMetrics(SM_CMONITORS) > 1), "expected SIMPLEREGION, got %d\n", ret); ret = GetClipRgn(hdc, hrgn); ok(ret == 0, "expected 0, got %d\n", ret); DeleteDC(hdc); DeleteObject(hrgn); DeleteObject(hrgn_empty); DestroyWindow(hwnd); }
void CPlayerSeekBar::OnPaint() { CPaintDC dc(this); // device context for painting bool fEnabled = m_fEnabled && m_start < m_stop; COLORREF white = GetSysColor(COLOR_WINDOW), shadow = GetSysColor(COLOR_3DSHADOW), light = GetSysColor(COLOR_3DHILIGHT), bkg = GetSysColor(COLOR_BTNFACE); // thumb { CRect r = GetThumbRect(), r2 = GetInnerThumbRect(); CRect rt = r, rit = r2; dc.Draw3dRect(&r, light, 0); r.DeflateRect(0, 0, 1, 1); dc.Draw3dRect(&r, light, shadow); r.DeflateRect(1, 1, 1, 1); CBrush b(bkg); dc.FrameRect(&r, &b); r.DeflateRect(0, 1, 0, 1); dc.FrameRect(&r, &b); r.DeflateRect(1, 1, 0, 0); dc.Draw3dRect(&r, shadow, bkg); if(fEnabled) { r.DeflateRect(1, 1, 1, 2); CPen white(PS_INSIDEFRAME, 1, white); CPen* old = dc.SelectObject(&white); dc.MoveTo(r.left, r.top); dc.LineTo(r.right, r.top); dc.MoveTo(r.left, r.bottom); dc.LineTo(r.right, r.bottom); dc.SelectObject(old); dc.SetPixel(r.CenterPoint().x, r.top, 0); dc.SetPixel(r.CenterPoint().x, r.bottom, 0); } dc.SetPixel(r.CenterPoint().x+5, r.top-4, bkg); { CRgn rgn1, rgn2; rgn1.CreateRectRgnIndirect(&rt); rgn2.CreateRectRgnIndirect(&rit); ExtSelectClipRgn(dc, rgn1, RGN_DIFF); ExtSelectClipRgn(dc, rgn2, RGN_OR); } } // channel { CRect r = GetChannelRect(); dc.FillSolidRect(&r, fEnabled ? white : bkg); r.InflateRect(1, 1); dc.Draw3dRect(&r, shadow, light); dc.ExcludeClipRect(&r); } // background { CRect r; GetClientRect(&r); CBrush b(bkg); dc.FillRect(&r, &b); } // Do not call CDialogBar::OnPaint() for painting messages }
/*********************************************************************** * Draw a card. Unlike cdtDrawCard, this version allows you to stretch * card bitmaps to the size you specify (dx, dy). See cdtDraw for info * on card, mode and color parameters. */ BOOL WINAPI cdtDrawExt(HDC hdc, int x, int y, int dx, int dy, int card, int mode, DWORD color) { HDC hMemoryDC; HBITMAP hCardBitmap; HGDIOBJ result; DWORD rasterOp = SRCCOPY; BOOL roundCornersFlag; BOOL eraseFlag = FALSE; BOOL drawFlag = TRUE; TRACE("(%p, %d, %d, %d, %d, %d, %d, %d)\n", hdc, x, y, dx, dy, card, mode, color); roundCornersFlag = !(mode & MODEFLAG_DONT_ROUND_CORNERS) && (dx == cardWidth) && (dy == cardHeight); mode &= ~MODEFLAG_DONT_ROUND_CORNERS; if((card < 0) || (card > CARD_MAX)) { FIXME("Unexpected card: %d\n", card); return FALSE; } if((mode < MODE_FACEUP) || (mode > MODE_DECKO)) { FIXME("Unexpected mode: %d\n", mode); return FALSE; } switch(mode) { case MODE_FACEUP: break; case MODE_FACEDOWN: break; case MODE_HILITE: rasterOp = NOTSRCCOPY; break; case MODE_GHOST: card = CARD_FREE_MASK; eraseFlag = TRUE; rasterOp = SRCAND; break; case MODE_REMOVE: eraseFlag = TRUE; drawFlag = FALSE; break; case MODE_INVISIBLEGHOST: card = CARD_FREE_MASK; rasterOp = SRCAND; break; case MODE_DECKX: card = CARD_BACK_THE_X; break; case MODE_DECKO: card = CARD_BACK_THE_O; break; } hMemoryDC = CreateCompatibleDC(hdc); if(hMemoryDC == 0) return FALSE; if(eraseFlag) { HBRUSH hBrush; RECT rect; hBrush = CreateSolidBrush(color); rect.left = x; rect.top = y; rect.right = x + cardWidth - 1; rect.bottom = y + cardHeight - 1; FillRect(hdc, &rect, hBrush); } if(drawFlag) { hCardBitmap = cardBitmaps[card]; if(hCardBitmap == 0) return FALSE; result = SelectObject(hMemoryDC, hCardBitmap); if((result == 0) || (result == HGDI_ERROR)) { DeleteDC(hMemoryDC); return FALSE; } SetBkColor(hdc, color); if(roundCornersFlag) { /* NOTE: native uses Get/SetPixel for corners, but that really * hurts on X11 since it needs a server round-trip for each pixel. * So we use a clip region instead. */ HRGN saved = CreateRectRgn( 0, 0, 0, 0 ); HRGN line = CreateRectRgn( x + 2, y, x + dx - 2, y + 1 ); HRGN clip = CreateRectRgn( x, y + 2, x + dx, y + dy - 2 ); CombineRgn( clip, clip, line, RGN_OR ); SetRectRgn( line, x + 1, y + 1, x + dx - 1, y + 2 ); CombineRgn( clip, clip, line, RGN_OR ); SetRectRgn( line, x + 1, y + dy - 2, x + dx - 1, y + dy - 1 ); CombineRgn( clip, clip, line, RGN_OR ); SetRectRgn( line, x + 2, y + dy - 1, x + dx - 2, y + dy ); CombineRgn( clip, clip, line, RGN_OR ); DeleteObject( line ); if (!GetClipRgn( hdc, saved )) { DeleteObject( saved ); saved = 0; } ExtSelectClipRgn( hdc, clip, RGN_AND ); DeleteObject( clip ); do_blt(hdc, x, y, dx, dy, hMemoryDC, rasterOp); SelectClipRgn( hdc, saved ); if (saved) DeleteObject( saved ); } else do_blt(hdc, x, y, dx, dy, hMemoryDC, rasterOp); } DeleteDC(hMemoryDC); return TRUE; }
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { PAINTSTRUCT ps; HDC hdc; #if CLIENT3D | IMAGE | GRAPH3D RECT rc; #endif #if GRAPH3D static int countup = 1; int id; static vec1 gx, gy; #endif #if TIMERDEMO static POINT mousept; #endif #if ARCDEMO static int startdegrees = 0; static int enddegrees = 30; #endif switch( msg) { #if TIMERDEMO case WM_CREATE: SetTimer(hwnd, 1, 100, NULL); mousept.x = 60; mousept.y = 20; break; case WM_TIMER: #if GRAPH3D GetClientRect(hwnd, &rc); if(countup) { mousept.y += 20; if(mousept.y >= rc.bottom) { mousept.y -= 20; countup = 0; } } else { mousept.y -= 20; if(mousept.y < 20) { mousept.y += 20; countup = 1; } } SendMessage(hwnd, WM_MOUSEMOVE, 0, MAKELONG(mousept.x, mousept.y)); #endif #if ARCDEMO startdegrees += 10; if(startdegrees >= 360) startdegrees = 0; enddegrees += 15; if(enddegrees >= 360) enddegrees = 0; InvalidateRect(hwnd, NULL, TRUE); #endif break; case WM_DESTROY: KillTimer(hwnd, 1); break; #endif /* TIMERDEMO*/ case WM_SIZE: break; case WM_MOVE: break; #if CLIENT3D case WM_SETFOCUS: PostMessage((HWND)wp, WM_PAINT, 0, 0L); break; case WM_KILLFOCUS: PostMessage((HWND)wp, WM_PAINT, 0, 0L); break; case WM_ERASEBKGND: if(GetFocus() != hwnd) return DefWindowProc(hwnd, msg, wp, lp); return 1; #endif #if GRAPH3D case WM_ERASEBKGND: if((GetWindowLong(hwnd, GWL_ID) & 03) == 1) return 1; return DefWindowProc(hwnd, msg, wp, lp); #endif case WM_PAINT: hdc = BeginPaint(hwnd, &ps); #if CLIENT3D if(GetFocus() == hwnd) { GetClientRect(hwnd, &rc); Draw3dShadow(hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, GetSysColor(COLOR_3DDKSHADOW), GetSysColor(COLOR_3DLIGHT)); InflateRect(&rc, -1, -1); FillRect(hdc, &rc, GetStockObject(GRAY_BRUSH)); } #endif #if IMAGE GetClientRect(hwnd, &rc); DrawDIB(hdc, rc.left+2, rc.top+2, image2); #endif #if ARCDEMO { int x, y, w, h; RECT rc; if(hdc != NULL) { GetWindowRect(hwnd, &rc); rc.top += 13; InflateRect(&rc, -3, -3); /*Ellipse(hdc, 0, 0, rc.right-rc.left, rc.bottom-rc.top);*/ /*Arc(hdc, 0, 0, rc.right-rc.left, rc.bottom-rc.top, 0,0, 0,0);*/ /*Pie(hdc, 0, 0, rc.right-rc.left, rc.bottom-rc.top, 0,0, 0,0);*/ x = rc.left; y = rc.top; w = rc.right - rc.left; h = rc.bottom - rc.top; w += 10; GdSetForeground(GdFindColor(RGB(0,255,0))); GdArcAngle(hdc->psd, x+w/2, y+h/2, w/2, h/2, startdegrees*64, enddegrees*64, MWPIE); GdSetForeground(GdFindColor(RGB(0,0,0))); GdArcAngle(hdc->psd, x+w/2, y+h/2, w/2, h/2, startdegrees*64, enddegrees*64, MWARCOUTLINE); /*GdSetForeground(GdFindColor(RGB(255,255,255)));*/ /*GdPoint(hdc->psd, x+w/2, y+h/2);*/ } EndPaint(hwnd, &ps); break; } #endif /* ARCDEMO*/ #if GRAPH3D id = (int)GetWindowLong(hwnd, GWL_ID) & 03; init3(hdc, id == 1? hwnd: NULL); switch(id) { case 0: rose(1.0, 7, 13); break; case 1: /*look3(0.5, 0.7, 1.5);*/ /*look3(0.2, -2 * gy, 1.0+gx);*/ look3(-2 * gx, -2 * gy, 1.2); drawgrid(-8.0, 8.0, 10, -8.0, 8.0, 10); break; case 2: setcolor3(BLACK); circle3(1.0); break; case 3: setcolor3(BLUE); daisy(1.0, 20); break; } #if CLIPDEMO if(id == 1) { HRGN hrgn, hrgn2; /* create circular clip region for effect*/ GetClientRect(hwnd, &rc); InflateRect(&rc, -80, -80); switch((int)GetWindowLong(hwnd, GWL_ID)) { default: hrgn = CreateEllipticRgnIndirect(&rc); break; case 5: hrgn = CreateRoundRectRgn(rc.left, rc.top, rc.right, rc.bottom, 100, 100); break; case 1: hrgn = CreateRectRgnIndirect(&rc); break; } /* erase background, clip out blit area*/ GetClientRect(hwnd, &rc); hrgn2 = CreateRectRgnIndirect(&rc); SelectClipRgn(hdc, hrgn2); ExtSelectClipRgn(hdc, hrgn, RGN_XOR); DeleteObject(hrgn2); GetClientRect(hwnd, &rc); FillRect(hdc, &rc, GetStockObject(BLACK_BRUSH)); /* clip in only blit area*/ SelectClipRgn(hdc, hrgn); DeleteObject(hrgn); } #endif /* CLIPDEMO*/ paint3(hdc); #endif /* GRAPH3D*/ EndPaint(hwnd, &ps); break; case WM_LBUTTONDOWN: break; case WM_MOUSEMOVE: #if GRAPH3D if((GetWindowLong(hwnd, GWL_ID) & 03) == 1) { POINT pt; POINTSTOPOINT(pt, lp); GetClientRect(hwnd, &rc); gx = (vec1)pt.x / rc.right; gy = (vec1)pt.y / rc.bottom; InvalidateRect(hwnd, NULL, FALSE); mousept.x = pt.x; mousept.y = pt.y; } #endif break; case WM_LBUTTONUP: break; case WM_RBUTTONDOWN: break; default: return DefWindowProc( hwnd, msg, wp, lp); } return( 0); }
void BitBltMergeLayers(HDC hdcDest, int nWidth, int nHeight, HDC hdcSrc, HWND hWnd) { if (hdcSrc && hdcDest) { if (hWnd->exstyle & WS_EX_LAYERED) { DWORD alphaValue; POINT ptDelta = {0,0}; ptDelta.x = hWnd->winrect.left - hdcDest->pt.x; ptDelta.y = hWnd->winrect.top - hdcDest->pt.y; /*transparency enabled using color key crKey*/ if (hWnd->dwFlags & LWA_COLORKEY) { /* mask the color key's most significant byte to 0*/ COLORREF ColorKey = hWnd->crKey & ~MWROP_EXTENSION; if (hWnd->dwFlags & LWA_ALPHA) { SetAlphaValue(hWnd->bAlpha); BitBlt(hdcDest, ptDelta.x, ptDelta.y, nWidth, nHeight, hdcSrc, 0, 0, MWROP_BLENDTRANS | ColorKey); } else { BitBlt(hdcDest, ptDelta.x, ptDelta.y, nWidth, nHeight, hdcSrc, 0, 0, MWROP_SRCTRANSCOPY | ColorKey); } } else { alphaValue = (hWnd->dwFlags & LWA_ALPHA) ? (MWROP_BLENDCONSTANT | hWnd->bAlpha) : SRCCOPY; if (isLayeredParentWindow(hWnd)) { HRGN hrgn, tempHrgn; RECT clientRect, tempRect; POINT clientOrigin; HWND wp = NULL; GetClientRect(currentTargetHWnd, &clientRect); hrgn = CreateRectRgnIndirect(&clientRect); /*store screen coordinates of client window for offset*/ clientOrigin.x = currentTargetHWnd->winrect.left; clientOrigin.y = currentTargetHWnd->winrect.top; /* start with entire client area for clip region, * we then cut out regions occupied by child windows*/ SelectClipRgn(hdcDest, hrgn); /* traverse immediate children to build clip rectangles. * First we call show immediate children to enable * clipping on children for one hide level, check the * clipping to add subtract from clientrect, then disable * back clipping before returning to recursive call */ ShowImmediateChildWindows(hWnd); for (wp = hWnd->children; wp; wp=wp->siblings) { if (wp->unmapcount == 0) { tempRect.left = wp->winrect.left - clientOrigin.x; tempRect.right = wp->winrect.right - clientOrigin.x; tempRect.top = wp->winrect.top - clientOrigin.y; tempRect.bottom = wp->winrect.bottom - clientOrigin.y; tempHrgn = CreateRectRgnIndirect(&tempRect); ExtSelectClipRgn(hdcDest, tempHrgn, RGN_DIFF); DeleteObject(tempHrgn); } } HideImmediateChildWindows(hWnd); BitBlt(hdcDest, ptDelta.x, ptDelta.y, nWidth, nHeight, hdcSrc, 0, 0, alphaValue); SelectClipRgn(hdcDest, NULL); DeleteObject(hrgn); } else { BitBlt(hdcDest, ptDelta.x, ptDelta.y, nWidth, nHeight, hdcSrc, 0, 0, alphaValue); } } } else { BitBlt(hdcDest, 0, 0, nWidth, nHeight, hdcSrc, 0, 0, SRCCOPY); } } }
cairo_status_t _cairo_win32_display_surface_set_clip (cairo_win32_display_surface_t *surface, cairo_clip_t *clip) { char stack[512]; cairo_rectangle_int_t extents; int num_rects; RGNDATA *data; size_t data_size; RECT *rects; int i; HRGN gdi_region; cairo_status_t status; cairo_region_t *region; /* The semantics we want is that any clip set by cairo combines * is intersected with the clip on device context that the * surface was created for. To implement this, we need to * save the original clip when first setting a clip on surface. */ assert (_cairo_clip_is_region (clip)); region = _cairo_clip_get_region (clip); if (region == NULL) return CAIRO_STATUS_SUCCESS; cairo_region_get_extents (region, &extents); num_rects = cairo_region_num_rectangles (region); /* XXX see notes in _cairo_win32_save_initial_clip -- * this code will interact badly with a HDC which had an initial * world transform -- we should probably manually transform the * region rects, because SelectClipRgn takes device units, not * logical units (unlike IntersectClipRect). */ data_size = sizeof (RGNDATAHEADER) + num_rects * sizeof (RECT); if (data_size > sizeof (stack)) { data = malloc (data_size); if (!data) return _cairo_error(CAIRO_STATUS_NO_MEMORY); } else data = (RGNDATA *)stack; data->rdh.dwSize = sizeof (RGNDATAHEADER); data->rdh.iType = RDH_RECTANGLES; data->rdh.nCount = num_rects; data->rdh.nRgnSize = num_rects * sizeof (RECT); data->rdh.rcBound.left = extents.x; data->rdh.rcBound.top = extents.y; data->rdh.rcBound.right = extents.x + extents.width; data->rdh.rcBound.bottom = extents.y + extents.height; rects = (RECT *)data->Buffer; for (i = 0; i < num_rects; i++) { cairo_rectangle_int_t rect; cairo_region_get_rectangle (region, i, &rect); rects[i].left = rect.x; rects[i].top = rect.y; rects[i].right = rect.x + rect.width; rects[i].bottom = rect.y + rect.height; } gdi_region = ExtCreateRegion (NULL, data_size, data); if ((char *)data != stack) free (data); if (!gdi_region) return _cairo_error (CAIRO_STATUS_NO_MEMORY); /* AND the new region into our DC */ status = CAIRO_STATUS_SUCCESS; if (ExtSelectClipRgn (surface->win32.dc, gdi_region, RGN_AND) == ERROR) status = _cairo_win32_print_gdi_error (__FUNCTION__); DeleteObject (gdi_region); return status; }
static void _AniAva_RenderAvatar(ANIAVA_WINDOWINFO * dat, HDC hdcParent /* = NULL*/, RECT * rcInParent /* = NULL */ ) { if (dat->bPaused>0) { dat->bPended=TRUE; return; } else dat->bPended=FALSE; if ( IMMEDIATE_DRAW && hdcParent == NULL ) return; GdiFlush(); #ifdef _DEBUG __AniAva_DebugRenderStrip(); #endif if (dat->bPlaying && IsWindowVisible(dat->hWindow)) { POINT ptWnd={0}; SIZE szWnd={dat->rcPos.right-dat->rcPos.left,dat->rcPos.bottom-dat->rcPos.top}; BLENDFUNCTION bf={AC_SRC_OVER, 0,g_CluiData.bCurrentAlpha*dat->bAlpha/256, AC_SRC_ALPHA }; POINT pt_from={0,0}; HDC hDC_animation=GetDC(NULL); HDC copyFromDC; RECT clistRect; HDC tempDC=NULL; HBITMAP hBmp; HBITMAP hOldBmp; /* int x=bf.SourceConstantAlpha; x=(49152/(383-x))-129; x=min(x,255); x=max(x,0); bf.SourceConstantAlpha=x; */ if ( AniAva.bFlags == 0 ) //simple and fastest method - no borders, round corners and etc. just copy { pt_from.x=dat->ptFromPoint.x+dat->currentFrame*dat->sizeAvatar.cx; pt_from.y=dat->ptFromPoint.y; copyFromDC=AniAva.hAniAvaDC; } else { // ... need to create additional hDC_animation HRGN hRgn=NULL; int cornerRadius= AniAva.cornerRadius; tempDC = CreateCompatibleDC( NULL ); hBmp = ske_CreateDIB32( szWnd.cx, szWnd.cy ); hOldBmp = (HBITMAP)SelectObject(tempDC,hBmp); if ( AniAva.bFlags & AAO_ROUND_CORNERS ) { if (!cornerRadius) //auto radius cornerRadius = min(szWnd.cx, szWnd.cy )/5; } if ( AniAva.bFlags & AAO_HAS_BORDER ) { // if has borders - create region (round corners) and fill it, remember internal as clipping HBRUSH hBrush = CreateSolidBrush( AniAva.borderColor ); HBRUSH hOldBrush = (HBRUSH)SelectObject( tempDC, hBrush ); HRGN rgnOutside = CreateRoundRectRgn( 0, 0, szWnd.cx+1, szWnd.cy+1, cornerRadius<<1, cornerRadius<<1); hRgn=CreateRoundRectRgn( 1, 1, szWnd.cx, szWnd.cy, cornerRadius<<1, cornerRadius<<1); CombineRgn( rgnOutside,rgnOutside,hRgn,RGN_DIFF); FillRgn( tempDC, rgnOutside, hBrush); ske_SetRgnOpaque( tempDC, rgnOutside, TRUE); SelectObject(tempDC, hOldBrush); DeleteObject(hBrush); DeleteObject(rgnOutside); } else if ( cornerRadius > 0 ) { // else create clipping area (round corners) hRgn=CreateRoundRectRgn(0, 0, szWnd.cx+1, szWnd.cy+1, cornerRadius<<1, cornerRadius<<1); } else { hRgn=CreateRectRgn(0, 0, szWnd.cx+1, szWnd.cy+1); } // select clip area if ( hRgn ) ExtSelectClipRgn(tempDC, hRgn, RGN_AND); if ( AniAva.bFlags & AAO_OPAQUE) { // if back color - fill clipping area HBRUSH hBrush = CreateSolidBrush( AniAva.bkgColor ); HBRUSH hOldBrush = (HBRUSH)SelectObject( tempDC, hBrush ); FillRgn( tempDC, hRgn, hBrush ); ske_SetRgnOpaque( tempDC, hRgn, TRUE ); } // draw avatar if ( !(AniAva.bFlags & AAO_OPAQUE) ) BitBlt(tempDC,0, 0, szWnd.cx, szWnd.cy , AniAva.hAniAvaDC , dat->ptFromPoint.x+dat->sizeAvatar.cx*dat->currentFrame, dat->ptFromPoint.y, SRCCOPY); else { BLENDFUNCTION abf={AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; ske_AlphaBlend(tempDC,0, 0, szWnd.cx, szWnd.cy , AniAva.hAniAvaDC, dat->ptFromPoint.x+dat->sizeAvatar.cx*dat->currentFrame, dat->ptFromPoint.y, szWnd.cx, szWnd.cy, abf); } // reset clip area if ( hRgn ) { DeleteObject(hRgn); hRgn = CreateRectRgn(0, 0, szWnd.cx, szWnd.cy); SelectClipRgn(tempDC, hRgn); DeleteObject(hRgn); } if ( ( AniAva.bFlags & AAO_HAS_OVERLAY ) && ( dat->overlayIconIdx != -1 ) && ( AniAva.overlayIconImageList ) ) { // if overlay - draw overlay icon // position - on avatar int x=szWnd.cx-ICON_WIDTH; int y=szWnd.cy-ICON_HEIGHT; ske_ImageList_DrawEx(AniAva.overlayIconImageList, dat->overlayIconIdx&0xFFFF, tempDC, x, y, ICON_WIDTH, ICON_HEIGHT, CLR_NONE, CLR_NONE, ILD_NORMAL); } copyFromDC=tempDC; } // intersect visible area // update layered window GetWindowRect(pcli->hwndContactTree, &clistRect); if (dat->rcPos.top<0) { pt_from.y+=-dat->rcPos.top; szWnd.cy+=dat->rcPos.top; } if (dat->rcPos.bottom>clistRect.bottom-clistRect.top) { szWnd.cy-=(dat->rcPos.bottom-(clistRect.bottom-clistRect.top)); } ptWnd.x=dat->rcPos.left+clistRect.left; ptWnd.y=(dat->rcPos.top>0 ? dat->rcPos.top :0)+clistRect.top; if (szWnd.cy>0) { if ( hdcParent && rcInParent && IMMEDIATE_DRAW ) { if ( AniAva.bFlags & AAO_OPAQUE ) BitBlt( hdcParent, rcInParent->left, rcInParent->top, szWnd.cx, szWnd.cy, copyFromDC, pt_from.x, pt_from.y, SRCCOPY); else { BLENDFUNCTION abf={AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; ske_AlphaBlend( hdcParent, rcInParent->left, rcInParent->top, szWnd.cx, szWnd.cy, copyFromDC, pt_from.x, pt_from.y, szWnd.cx, szWnd.cy, abf); } } else if (!g_proc_UpdateLayeredWindow(dat->hWindow, hDC_animation, &ptWnd, &szWnd, copyFromDC, &pt_from, RGB(0,0,0), &bf, ULW_ALPHA )) { LONG exStyle; exStyle=GetWindowLong(dat->hWindow,GWL_EXSTYLE); exStyle|=WS_EX_LAYERED; SetWindowLong(dat->hWindow,GWL_EXSTYLE,exStyle); if ( !IMMEDIATE_DRAW ) SetWindowPos( pcli->hwndContactTree, dat->hWindow, 0, 0, 0, 0, SWP_ASYNCWINDOWPOS | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSENDCHANGING ); g_proc_UpdateLayeredWindow(dat->hWindow, hDC_animation, &ptWnd, &szWnd, copyFromDC, &pt_from, RGB(0,0,0), &bf, ULW_ALPHA ); } g_CluiData.fAeroGlass = false; CLUI_UpdateAeroGlass(); } else { dat->bPlaying=FALSE; } ReleaseDC(NULL,hDC_animation); if (tempDC) { SelectObject(tempDC, hOldBmp); DeleteObject(hBmp); DeleteDC(tempDC); } } if (!dat->bPlaying) { ShowWindow(dat->hWindow, SW_HIDE); KillTimer(dat->hWindow,2); //stop animation till set pos will be called } GdiFlush(); }
BOOL TooltipOnNotify(LRESULT *plRes, LPARAM lParam) { if (!hwndTooltip || hwndTooltip != ((LPNMHDR)lParam)->hwndFrom) return FALSE; switch (((LPNMHDR)lParam)->code) { case NM_CUSTOMDRAW: if (bTooltipCustomDrawDisable) break; if (((LPNMCUSTOMDRAW)lParam)->dwDrawStage == CDDS_PREPAINT) { if (((LPNMCUSTOMDRAW)lParam)->rc.top) { RECT rc; TooltipUpdate(((LPNMCUSTOMDRAW)lParam)->hdc, &((LPNMCUSTOMDRAW)lParam)->rc, &rc, ((LPNMTTCUSTOMDRAW)lParam)->uDrawFlags); ExcludeClipRect(((LPNMCUSTOMDRAW)lParam)->hdc, rc.left, rc.top, rc.right, rc.bottom); } else { ExcludeClipRect(((LPNMCUSTOMDRAW)lParam)->hdc, ((LPNMCUSTOMDRAW)lParam)->rc.left, ((LPNMCUSTOMDRAW)lParam)->rc.top, ((LPNMCUSTOMDRAW)lParam)->rc.right, ((LPNMCUSTOMDRAW)lParam)->rc.bottom); } *plRes = CDRF_NOTIFYPOSTPAINT; return TRUE; } if (((LPNMCUSTOMDRAW)lParam)->dwDrawStage == CDDS_POSTPAINT) { HRGN hrgn = CreateRectRgn(((LPNMCUSTOMDRAW)lParam)->rc.left, ((LPNMCUSTOMDRAW)lParam)->rc.top, ((LPNMCUSTOMDRAW)lParam)->rc.right, ((LPNMCUSTOMDRAW)lParam)->rc.bottom); if (hrgn) { ExtSelectClipRgn(((LPNMCUSTOMDRAW)lParam)->hdc, hrgn, RGN_OR); DeleteObject(hrgn); } *plRes = 0; return TRUE; } break; case TTN_NEEDTEXTW: if (!bTooltipShow || !bTooltipUpdated) { TooltipUpdateText(); TooltipUpdateTitle(); } MultiByteToWideChar(CP_ACP, 0, formatTooltip, -1, formatTooltipW, sizeof(formatTooltipW)/sizeof(WCHAR)); ((LPTOOLTIPTEXTW)lParam)->lpszText = formatTooltipW; *plRes = 0; //if (!formatTooltipW[0] && bVista) // PostMessage(hwndClock, CLOCKM_VISTATOOLTIP, 1, 0); return TRUE; case TTN_NEEDTEXT: if (!bTooltipShow || !bTooltipUpdated) { TooltipUpdateText(); TooltipUpdateTitle(); } ((LPTOOLTIPTEXT)lParam)->lpszText = formatTooltip; *plRes = 0; //if (!formatTooltip[0] && bVista) // PostMessage(hwndClock, CLOCKM_VISTATOOLTIP, 1, 0); return TRUE; case TTN_SHOW: if (!bTooltipShow) { TooltipUpdateText(); TooltipUpdateTitle(); SetWindowPos(hwndTooltip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE); bTooltipShow = TRUE; } break; case TTN_POP: bTooltipShow = FALSE; bTooltipUpdated = FALSE; break; } return FALSE; }
// Similar to DrawText win32 api function // Pass uFormat | DT_CALCRECT to calc rectangle to be returned by lpRect // parseInfo is optional (pass NULL and it will be calculated and deleted inside function int Smileys_DrawText(HDC hDC, LPCTSTR lpString, int nCount, LPRECT lpRect, UINT uFormat, const char *protocol, SmileysParseInfo parseInfo) { SmileysParseInfo info; int ret; if (nCount < 0) nCount = (int)mir_tstrlen(lpString); // Get parse info if (parseInfo == NULL) info = Smileys_PreParse(lpString, nCount, protocol); else info = parseInfo; if (uFormat & DT_CALCRECT) { SIZE text_size = GetTextSize(hDC, lpString, info->pieces, uFormat, info->max_height); lpRect->bottom = min(lpRect->bottom, lpRect->top + text_size.cy); if (text_size.cx < lpRect->right - lpRect->left) { if (uFormat & DT_RIGHT) lpRect->left = lpRect->right - text_size.cx; else lpRect->right = lpRect->left + text_size.cx; } ret = text_size.cy; } else { // Clipping rgn HRGN oldRgn = CreateRectRgn(0, 0, 1, 1); if (GetClipRgn(hDC, oldRgn) != 1) { DeleteObject(oldRgn); oldRgn = NULL; } HRGN rgn = CreateRectRgnIndirect(lpRect); ExtSelectClipRgn(hDC, rgn, RGN_AND); // Draw if (info->pieces == NULL) { ret = skin_DrawText(hDC, lpString, nCount, lpRect, uFormat); } else { RECT rc = *lpRect; SIZE text_size = GetTextSize(hDC, lpString, info->pieces, uFormat, info->max_height); if (text_size.cx < rc.right - rc.left) { if (uFormat & DT_RIGHT) rc.left = rc.right - text_size.cx; else rc.right = rc.left + text_size.cx; } ret = text_size.cy; DrawTextSmiley(hDC, rc, lpString, nCount, info->pieces, uFormat, info->max_height); } // Clipping rgn SelectClipRgn(hDC, oldRgn); DeleteObject(rgn); if (oldRgn) DeleteObject(oldRgn); } // Free parse info if (parseInfo == NULL) Smileys_FreeParse(info); return ret; }