Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

997 lines
39 KiB

  1. /**MOD+**********************************************************************/
  2. /* Module: opapi.cpp */
  3. /* */
  4. /* Purpose: Output Painter API functions */
  5. /* */
  6. /* Copyright(C) Microsoft Corporation 1997-1999 */
  7. /* */
  8. /****************************************************************************/
  9. #include <adcg.h>
  10. extern "C" {
  11. #define TRC_GROUP TRC_GROUP_CORE
  12. #define TRC_FILE "opapi"
  13. #include <atrcapi.h>
  14. }
  15. #include <math.h>
  16. #include "autil.h"
  17. #include "wui.h"
  18. #include "op.h"
  19. #include "aco.h"
  20. #include "uh.h"
  21. COP::COP(CObjs* objs)
  22. {
  23. _pClientObjects = objs;
  24. _fDimWindow = FALSE;
  25. _iDimWindowStepsLeft = 0;
  26. _nDimWindowTimerID = 0;
  27. //
  28. // Init the OP structure to all zeros
  29. //
  30. DC_MEMSET(&_OP, 0, sizeof(_OP));
  31. }
  32. COP::~COP()
  33. {
  34. }
  35. /**PROC+*********************************************************************/
  36. /* Name: OP_Init */
  37. /* */
  38. /* Purpose: Initialize Output Painter */
  39. /* */
  40. /* Returns: None */
  41. /* */
  42. /* Params: None */
  43. /* */
  44. /**PROC-*********************************************************************/
  45. DCVOID DCAPI COP::OP_Init(DCVOID)
  46. {
  47. #ifndef OS_WINCE
  48. WNDCLASS wndclass;
  49. WNDCLASS tmpWndClass;
  50. #endif
  51. DC_BEGIN_FN("OP_Init");
  52. _pUt = _pClientObjects->_pUtObject;
  53. _pUh = _pClientObjects->_pUHObject;
  54. _pCd = _pClientObjects->_pCdObject;
  55. _pOr = _pClientObjects->_pOrObject;
  56. _pUi = _pClientObjects->_pUiObject;
  57. _pOd = _pClientObjects->_pODObject;
  58. #ifdef OS_WINCE
  59. _pIh = _pClientObjects->_pIhObject;
  60. #endif
  61. #ifndef OS_WINCE
  62. if(!GetClassInfo(_pUi->UI_GetInstanceHandle(), OP_CLASS_NAME, &tmpWndClass))
  63. {
  64. //
  65. // Create Output Painter window
  66. //
  67. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  68. wndclass.lpfnWndProc = OPStaticWndProc;
  69. wndclass.cbClsExtra = 0;
  70. wndclass.cbWndExtra = sizeof(void*);
  71. wndclass.hInstance = _pUi->UI_GetInstanceHandle();
  72. wndclass.hIcon = NULL;
  73. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  74. wndclass.hbrBackground = (HBRUSH)GetStockObject(HOLLOW_BRUSH);
  75. wndclass.lpszMenuName = NULL;
  76. wndclass.lpszClassName = OP_CLASS_NAME;
  77. RegisterClass (&wndclass);
  78. }
  79. _OP.hwndOutputWindow = CreateWindowEx(
  80. #ifndef OS_WINCE
  81. WS_EX_NOPARENTNOTIFY,
  82. #else
  83. 0,
  84. #endif
  85. OP_CLASS_NAME,
  86. _T("Output Painter Window"),
  87. WS_CHILD | WS_CLIPSIBLINGS,
  88. 0,
  89. 0,
  90. 1,
  91. 1,
  92. _pUi->UI_GetUIContainerWindow(),
  93. NULL,
  94. _pUi->UI_GetInstanceHandle(),
  95. this );
  96. if(!_OP.hwndOutputWindow)
  97. {
  98. TRC_ERR((TB,_T("_OP.hwndOutputWindow CreateWindowEx failed: 0x%x\n"),
  99. GetLastError()));
  100. _pUi->UI_FatalError(DC_ERR_WINDOWCREATEFAILED);
  101. return;
  102. }
  103. SetWindowPos( _OP.hwndOutputWindow,
  104. HWND_BOTTOM,
  105. 0, 0, 0, 0,
  106. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE );
  107. #else
  108. _OP.hwndOutputWindow = _pIh->IH_GetInputHandlerWindow();
  109. #endif /* !OS_WINCE */
  110. /************************************************************************/
  111. /* @@JPB: Temporary - should calculate based on bpp. */
  112. /************************************************************************/
  113. _OP.paletteRealizationSupported = TRUE;
  114. DC_END_FN();
  115. return;
  116. } /* OP_Init */
  117. #ifdef SMART_SIZING
  118. /****************************************************************************/
  119. /* Name: OP_AddUpdateRegion */
  120. /* */
  121. /* Purpose: Adds the a given region to the update region. */
  122. /****************************************************************************/
  123. void COP::OP_AddUpdateRegion(DCINT left, DCINT top, DCINT right, DCINT bottom)
  124. {
  125. RECT rect;
  126. float newLeft, newTop, newRight, newBottom;
  127. DCSIZE desktopSize;
  128. DC_BEGIN_FN("OP_AddUpdateRegion");
  129. _pUi->UI_GetDesktopSize(&desktopSize);
  130. //if desktop remains the same size
  131. //we don't need to update this region
  132. if ((_scaleSize.width == desktopSize.width) &&
  133. (_scaleSize.height == desktopSize.height)) {
  134. DC_QUIT;
  135. }
  136. newLeft = (float)left * (float)_scaleSize.width /
  137. (float)desktopSize.width;
  138. newTop = (float)top * (float)_scaleSize.height /
  139. (float)desktopSize.height;
  140. newRight = (float)right * (float)_scaleSize.width /
  141. (float)desktopSize.width;
  142. newBottom = (float)bottom * (float)_scaleSize.height /
  143. (float)desktopSize.height;
  144. //
  145. // Since stretching causes the destination bits to be based not only
  146. // on the direct source bits, but some halftoning of other nearby
  147. // bits, if you are tiling memblt orders and updating the screen,
  148. // you can get some artificats from tiles that reference bits in
  149. // their neighboring tiles that haven't been drawn yet.
  150. //
  151. // When their neighbors are drawn, we'd like to update those first
  152. // tiles so the artifacts will be corrected. To do this we expand
  153. // the size of memblt orders clipping
  154. //
  155. newLeft -= 2;
  156. newTop -= 2;
  157. newRight += 2;
  158. newBottom += 2;
  159. #ifdef USE_GDIPLUS
  160. Gdiplus::RectF rectF(newLeft, newTop, newRight - newLeft, newBottom - newTop);
  161. if (_rgnUpdate.Union(rectF) != Gdiplus::Ok) {
  162. TRC_ERR((TB, _T("Gdiplus::Region.Union() failed")));
  163. }
  164. #else // USE_GDIPLUS
  165. int nnewLeft, nnewTop, nnewRight, nnewBottom;
  166. // Round "outwards"
  167. #ifndef OS_WINCE
  168. nnewLeft = (int)floorf(newLeft);
  169. nnewTop = (int)floorf(newTop);
  170. nnewRight = (int)ceilf(newRight);
  171. nnewBottom = (int)ceilf(newBottom);
  172. #else
  173. nnewLeft = (int)floor(newLeft);
  174. nnewTop = (int)floor(newTop);
  175. nnewRight = (int)ceil(newRight);
  176. nnewBottom = (int)ceil(newBottom);
  177. #endif
  178. // Accommodate regional exclusive cordinates.
  179. // Ok, my thinking says this should be +1, but +2 is what is actually
  180. // required to prevent bad painting.
  181. nnewRight += 1;
  182. nnewBottom += 1;
  183. SetRectRgn(_hrgnUpdateRect, nnewLeft, nnewTop, nnewRight, nnewBottom);
  184. // Combine the rectangle region with the update region.
  185. if (!UnionRgn(_hrgnUpdate, _hrgnUpdate, _hrgnUpdateRect)) {
  186. // The region union failed so we must simplify the region. This
  187. // means that we may paint areas which we have not received an
  188. // updates for - but this is better than not painting areas which
  189. // we have received updates for.
  190. TRC_ALT((TB, _T("UnionRgn failed")));
  191. GetRgnBox(_hrgnUpdate, &rect);
  192. SetRectRgn(_hrgnUpdate, rect.left, rect.top, rect.right + 1,
  193. rect.bottom + 1);
  194. if (!UnionRgn(_hrgnUpdate, _hrgnUpdate, _hrgnUpdateRect))
  195. {
  196. TRC_ERR((TB, _T("UnionRgn failed after simplification")));
  197. }
  198. }
  199. #endif // USE_GDIPLUS
  200. DC_EXIT_POINT:
  201. DC_END_FN();
  202. }
  203. #endif // SMART_SIZING
  204. /**PROC+*********************************************************************/
  205. /* Name: OP_Term */
  206. /* */
  207. /* Purpose: Terminate the Output Painter */
  208. /* */
  209. /* Returns: None */
  210. /* */
  211. /* Params: None */
  212. /* */
  213. /**PROC-*********************************************************************/
  214. DCVOID DCAPI COP::OP_Term(DCVOID)
  215. {
  216. DC_BEGIN_FN("OP_Term");
  217. #ifdef DESTROY_WINDOWS
  218. TRC_NRM((TB, _T("Calling DestroyWindow")));
  219. DestroyWindow(_OP.hwndOutputWindow);
  220. TRC_NRM((TB, _T("Destroyed window")));
  221. if (!UnregisterClass(OP_CLASS_NAME, _pUi->UI_GetInstanceHandle()))
  222. {
  223. //Failure to unregister could happen if another instance is still running
  224. //that's ok...unregistration will happen when the last instance exits.
  225. TRC_ERR((TB, _T("Failed to unregister OP window class")));
  226. }
  227. #endif
  228. //
  229. // Clear window handle
  230. //
  231. _OP.hwndOutputWindow = NULL;
  232. #if defined(SMART_SIZING) && !defined(USE_GDIPLUS)
  233. DeleteRgn(_hrgnUpdate);
  234. DeleteRgn(_hrgnUpdateRect);
  235. #endif
  236. DC_END_FN();
  237. return;
  238. } /* OP_Term */
  239. /**PROC+*********************************************************************/
  240. /* Name: OP_GetOutputWindowHandle */
  241. /* */
  242. /* Purpose: Returns the Output Window handle */
  243. /* */
  244. /* Returns: Output Window handle */
  245. /* */
  246. /* Params: None */
  247. /* */
  248. /**PROC-*********************************************************************/
  249. HWND DCAPI COP::OP_GetOutputWindowHandle(DCVOID)
  250. {
  251. HWND rc;
  252. DC_BEGIN_FN("OP_GetOutputWindowHandle");
  253. if(NULL == _OP.hwndOutputWindow)
  254. {
  255. TRC_ALT((TB,_T("_OP.hwndOutputWindow is NULL")));
  256. }
  257. rc = _OP.hwndOutputWindow;
  258. DC_END_FN();
  259. return(rc);
  260. }
  261. #ifdef OS_WINCE
  262. /**PROC+*********************************************************************/
  263. /* Name: OP_DoPaint */
  264. /* */
  265. /* Purpose: Handle WM_PAINT from IH - Windows CE only. */
  266. /* */
  267. /* Returns: None */
  268. /* */
  269. /* Params: IN hwnd - window handle to paint */
  270. /* */
  271. /* Operation: Required to work around the WS_CLIPSIBLINGS problem */
  272. /* */
  273. /**PROC-*********************************************************************/
  274. DCVOID DCAPI COP::OP_DoPaint(DCUINT hwnd)
  275. {
  276. DC_BEGIN_FN("OP_DoPaint");
  277. OPWndProc((HWND)hwnd, WM_PAINT, 0, 0);
  278. DC_END_FN();
  279. return;
  280. } /* OP_DoPaint */
  281. #endif /* OS_WINCE */
  282. /**PROC+*********************************************************************/
  283. /* Name: OP_PaletteChanged */
  284. /* */
  285. /* Purpose: Handler for WM_PALETTECHANGED messages */
  286. /* */
  287. /* Returns: Nothing */
  288. /* */
  289. /* Params: hwnd - handle of window that received the WM_PALETTECHANGED */
  290. /* message */
  291. /* */
  292. /* hwndTrigger - handle of window that realized the palette */
  293. /* that caused the WM_PALETTECHANGED message to be sent */
  294. /* */
  295. /* Operation: Realizes the current palette in the output window. */
  296. /* */
  297. /* NOTE - This function is called on the UI thread, not the receive thread. */
  298. /* All functions and variables referenced must be thread-safe if */
  299. /* they are also accessed from another thread. */
  300. /* */
  301. /**PROC-*********************************************************************/
  302. DCVOID DCAPI COP::OP_PaletteChanged(HWND hwnd, HWND hwndTrigger)
  303. {
  304. static DCBOOL fRealising = FALSE;
  305. DC_BEGIN_FN("OP_PaletteChanged");
  306. TRC_NRM((TB, _T("WM_PALETTECHANGED hwnd(%p) hwndTrigger(%p)"),
  307. hwnd, hwndTrigger));
  308. /************************************************************************/
  309. /* During termination, may get WM_PALETTECHANGED after the OP window */
  310. /* has been destroyed (in OP_Term). Handle this. */
  311. /************************************************************************/
  312. if (_OP.hwndOutputWindow == NULL)
  313. {
  314. TRC_ALT((TB, _T("No OP window")));
  315. DC_QUIT;
  316. }
  317. /************************************************************************/
  318. /* The system palette has changed. If it wasn't us that did it, then */
  319. /* realize our palette now to set up our new palette mapping. */
  320. /************************************************************************/
  321. if (_OP.palettePDUsBeingProcessed != 0)
  322. {
  323. /********************************************************************/
  324. /* This palette change is the result of a palette PDU, so the */
  325. /* server will be redrawing the screen by itself - we don't need to */
  326. /* trigger a repaint. */
  327. /********************************************************************/
  328. TRC_DBG((TB, _T("Not invalidating client area")));
  329. /********************************************************************/
  330. /* Note the fact that we've now seen the message associated with a */
  331. /* palette PDU. The trace statement is before the decrement so */
  332. /* that the point at which we're most likely to get pre-empted */
  333. /* (TRC_GetBuffer) is before all the variable references. */
  334. /********************************************************************/
  335. TRC_NRM((TB, _T("Palette PDUs now pending processing: %ld"),
  336. _OP.palettePDUsBeingProcessed - 1));
  337. _pUt->UT_InterlockedDecrement(&_OP.palettePDUsBeingProcessed);
  338. }
  339. else if ((hwndTrigger == hwnd) || (hwndTrigger == _OP.hwndOutputWindow))
  340. {
  341. if (fRealising == FALSE)
  342. {
  343. TRC_DBG((TB, _T("Invalidating client area cos we changed palette")));
  344. InvalidateRect(_OP.hwndOutputWindow, NULL, FALSE);
  345. }
  346. else
  347. {
  348. TRC_NRM((TB, _T("Not Invalidating client: still changing palette")));
  349. }
  350. }
  351. else
  352. {
  353. TRC_NRM((TB, _T("Not our window - realize palette in wnd(%p)"), hwnd));
  354. /********************************************************************/
  355. /* if we change the colors at all, we should repaint */
  356. /********************************************************************/
  357. #ifdef OS_WINCE // UpdateColors not supported on WinCE
  358. OPRealizePaletteInWindow(_OP.hwndOutputWindow);
  359. #else
  360. fRealising = TRUE;
  361. if (OPRealizePaletteInWindow(_OP.hwndOutputWindow) != 0)
  362. {
  363. HDC hdcOutputWindow = GetDC(_OP.hwndOutputWindow);
  364. TRC_ASSERT(hdcOutputWindow, (TB, _T("GetDC returned NULL for _OP.hwndOutputWindow")));
  365. if(hdcOutputWindow)
  366. {
  367. TRC_NRM((TB, _T("Updating client area cos palette changed")));
  368. UpdateColors(hdcOutputWindow);
  369. ReleaseDC(_OP.hwndOutputWindow, hdcOutputWindow);
  370. InvalidateRect(_OP.hwndOutputWindow, NULL, FALSE);
  371. }
  372. }
  373. fRealising = FALSE;
  374. #endif /* ifdef OS_WINCE */
  375. }
  376. DC_EXIT_POINT:
  377. DC_END_FN();
  378. return;
  379. }
  380. /**PROC+*********************************************************************/
  381. /* Name: OP_QueryNewPalette */
  382. /* */
  383. /* Purpose: Handler for WM_QUERYNEWPALETTE messages */
  384. /* */
  385. /* Returns: Number of palette entries changed */
  386. /* */
  387. /* Params: hwnd - handle of window that recieved the WM_QUERYNEWPALETTE */
  388. /* message */
  389. /* */
  390. /* Operation: Realizes the current palette in the output window. */
  391. /* */
  392. /* NOTE - This function is called on the UI thread, not the receive thread. */
  393. /* All functions and variables referenced must be thread-safe if */
  394. /* they are also accessed from another thread. */
  395. /* */
  396. /**PROC-*********************************************************************/
  397. DCUINT DCAPI COP::OP_QueryNewPalette(HWND hwnd)
  398. {
  399. DCUINT rc = 0;
  400. DC_BEGIN_FN("OP_QueryNewPalette");
  401. DC_IGNORE_PARAMETER(hwnd);
  402. if (_OP.paletteRealizationSupported)
  403. {
  404. rc = OPRealizePaletteInWindow(_OP.hwndOutputWindow);
  405. TRC_NRM((TB, _T("Palette realized(%u)"), rc));
  406. }
  407. DC_END_FN();
  408. return(rc);
  409. }
  410. /**PROC+*********************************************************************/
  411. /* Name: OP_MaybeForcePaint */
  412. /* */
  413. /* Purpose: Forces the Output Window to be painted if necessary */
  414. /* (if a WM_PAINT has been outstanding for an unreasonable */
  415. /* amount of time). */
  416. /* */
  417. /* Returns: Nothing. */
  418. /* */
  419. /* Params: None. */
  420. /* */
  421. /**PROC-*********************************************************************/
  422. DCVOID DCAPI COP::OP_MaybeForcePaint(DCVOID)
  423. {
  424. DCUINT32 currentTime;
  425. DC_BEGIN_FN("OP_MaybeForcePaint");
  426. currentTime = _pUt->UT_GetCurrentTimeMS();
  427. if ((currentTime - _OP.lastPaintTime) > OP_WORST_CASE_WM_PAINT_PERIOD)
  428. {
  429. /********************************************************************/
  430. /* UpdateWindow synchronously calls the WndProc with a WM_PAINT if */
  431. /* there is a non-NULL update region. */
  432. /********************************************************************/
  433. TRC_DBG((TB, _T("Forced update")));
  434. UpdateWindow(OP_GetOutputWindowHandle());
  435. _OP.lastPaintTime = currentTime;
  436. }
  437. DC_END_FN();
  438. return;
  439. }
  440. //
  441. // OP_DimWindow
  442. // CD call to change the window dim state
  443. //
  444. // Params:
  445. // fDim - BOOL indicating if window should start or stop being dimmed
  446. //
  447. DCVOID DCAPI COP::OP_DimWindow(ULONG_PTR fDim)
  448. {
  449. BOOL fChanged = FALSE;
  450. DC_BEGIN_FN("OP_DimWindow");
  451. fChanged = (_fDimWindow != (BOOL)fDim);
  452. if (fChanged) {
  453. TRC_NRM((TB,_T("Changed window dim state to: %d"), _fDimWindow));
  454. if (fDim) {
  455. OPStartDimmingWindow();
  456. }
  457. else {
  458. OPStopDimmingWindow();
  459. }
  460. InvalidateRect(OP_GetOutputWindowHandle(), NULL, FALSE);
  461. }
  462. DC_END_FN();
  463. }
  464. #ifdef SMART_SIZING
  465. /****************************************************************************/
  466. /* Name: OP_MainWindowSizeChange */
  467. /* */
  468. /* Purpose: Remembers the size of the container for scaling */
  469. /****************************************************************************/
  470. DCVOID DCAPI COP::OP_MainWindowSizeChange(ULONG_PTR msg)
  471. {
  472. DCSIZE desktopSize;
  473. DCUINT width;
  474. DCUINT height;
  475. width = LOWORD(msg);
  476. height = HIWORD(msg);
  477. if (_pUi) {
  478. _pUi->UI_GetDesktopSize(&desktopSize);
  479. if (width <= desktopSize.width) {
  480. _scaleSize.width = width;
  481. } else {
  482. // full screen, or other times the window is bigger than the
  483. // display resolution
  484. _scaleSize.width = desktopSize.width;
  485. }
  486. // Similarly
  487. if (height <= desktopSize.height) {
  488. _scaleSize.height = height;
  489. } else {
  490. _scaleSize.height = desktopSize.height;
  491. }
  492. InvalidateRect(_OP.hwndOutputWindow, NULL, FALSE);
  493. }
  494. }
  495. /**PROC+*********************************************************************/
  496. /* Name: OP_CopyShadowToDC */
  497. /* */
  498. /* Purpose: Copy the contents of the shadow bitmap to the destination, */
  499. /* possibly with stretching */
  500. /* */
  501. /* Returns: None. */
  502. /* */
  503. /* Params: None. */
  504. /* */
  505. /**PROC-*********************************************************************/
  506. BOOL COP::OP_CopyShadowToDC(HDC hdc, LONG srcLeft, LONG srcTop,
  507. LONG srcWidth, LONG srcHeight, BOOL fUseUpdateClipping)
  508. {
  509. BOOL rcBlt, rc;
  510. #ifdef USE_GDIPLUS
  511. Gdiplus::REAL dstLeft, dstTop, dstWidth, dstHeight;
  512. #else // USE_GDIPLUS
  513. FLOAT dstLeft, dstTop, dstWidth, dstHeight;
  514. #endif // USE_GDIPLUS
  515. DCSIZE desktopSize;
  516. #ifdef USE_GDIPLUS
  517. // static Gdiplus::InterpolationMode interpolationMode = Gdiplus::InterpolationModeHighQualityBicubic;
  518. static Gdiplus::InterpolationMode interpolationMode = Gdiplus::InterpolationModeBilinear;
  519. #endif // USE_GDIPLUS
  520. HDC hdcSrcBitmap = !_fDimWindow ? _pUh->UH_GetShadowBitmapDC() :
  521. _pUh->UH_GetDisconnectBitmapDC();
  522. DC_BEGIN_FN("OP_CopyShadowToDC");
  523. _pUi->UI_GetDesktopSize(&desktopSize);
  524. if (!_pUi->UI_GetSmartSizing() ||
  525. ((_scaleSize.width == desktopSize.width) &&
  526. (_scaleSize.height == desktopSize.height))) {
  527. if (fUseUpdateClipping) {
  528. SelectClipRgn(hdc, _pUh->_UH.hrgnUpdate);
  529. }
  530. rcBlt = BitBlt(hdc, srcLeft, srcTop, srcWidth,
  531. srcHeight, hdcSrcBitmap, srcLeft, srcTop,
  532. SRCCOPY);
  533. if (fUseUpdateClipping) {
  534. SelectClipRgn(hdc, NULL);
  535. }
  536. if (rcBlt) {
  537. rc = TRUE;
  538. } else {
  539. /********************************************************/
  540. /* Failed to Blt. */
  541. /********************************************************/
  542. TRC_ERR((TB, _T("BitBlt failed")));
  543. rc = FALSE;
  544. }
  545. } else {
  546. #ifdef USE_GDIPLUS
  547. // Gdiplus version
  548. Gdiplus::Status status;
  549. Gdiplus::Bitmap *source = new Gdiplus::Bitmap(_pUh->_UH.hShadowBitmap, NULL);
  550. if (source && source->GetLastStatus() == Gdiplus::Ok) {
  551. Gdiplus::Graphics *gdst = new Gdiplus::Graphics(hdc);
  552. if (gdst && gdst->GetLastStatus() == Gdiplus::Ok) {
  553. gdst->SetInterpolationMode(interpolationMode);
  554. if (fUseUpdateClipping) {
  555. gdst->SetClip(&_rgnUpdate);
  556. // Adjust the rectangle to be
  557. // no bigger than the bounding box of the clipping
  558. //
  559. // Use the unstretched coordinates for this
  560. RECT rect;
  561. GetRgnBox(_pUh->_UH.hrgnUpdate, &rect);
  562. if (rect.left < srcLeft)
  563. rect.left = srcLeft;
  564. if (rect.top < srcTop)
  565. rect.top = srcTop;
  566. if (rect.right > srcLeft + srcWidth)
  567. rect.right = srcLeft + srcWidth;
  568. if (rect.bottom > srcTop + srcHeight)
  569. rect.bottom = srcTop + srcHeight;
  570. srcLeft = rect.left;
  571. srcWidth = rect.right - rect.left;
  572. srcTop = rect.top;
  573. srcHeight = rect.bottom - rect.top;
  574. }
  575. dstLeft = (float)srcLeft * (float)_scaleSize.width /
  576. (float)desktopSize.width;
  577. dstTop = (float)srcTop * (float)_scaleSize.height /
  578. (float)desktopSize.height;
  579. dstWidth = (float)srcWidth * (float)_scaleSize.width /
  580. (float)desktopSize.width;
  581. dstHeight = (float)srcHeight * (float)_scaleSize.height /
  582. (float)desktopSize.height;
  583. #if 0
  584. Gdiplus::HatchBrush brush(Gdiplus::HatchStyleForwardDiagonal,
  585. Gdiplus::Color(0, 255, 0), Gdiplus::Color(0x00000000));
  586. gdst->FillRectangle(&brush, dstLeft, dstTop, dstLeft + dstWidth,
  587. dstTop + dstHeight);
  588. #endif
  589. Gdiplus::RectF dstrect(dstLeft, dstTop, dstWidth, dstHeight);
  590. status = gdst->DrawImage(source, dstrect, (Gdiplus::REAL)srcLeft,
  591. (Gdiplus::REAL)srcTop, (Gdiplus::REAL)srcWidth,
  592. (Gdiplus::REAL)srcHeight, Gdiplus::UnitPixel);
  593. #if 0
  594. Gdiplus::HatchBrush brush(Gdiplus::HatchStyleForwardDiagonal,
  595. Gdiplus::Color(0, 255, 0), Gdiplus::Color(0x00000000));
  596. gdst->FillRectangle(&brush, dstLeft, dstTop, dstLeft + dstWidth,
  597. dstTop + dstHeight);
  598. #endif
  599. if (fUseUpdateClipping) {
  600. gdst->ResetClip();
  601. }
  602. if (status == Gdiplus::Ok) {
  603. rc = TRUE;
  604. } else {
  605. rc = FALSE;
  606. TRC_ERR((TB, _T("Failed to DrawImage")));
  607. }
  608. delete gdst;
  609. } else {
  610. TRC_ERR((TB, _T("Failed to create Graphics object")));
  611. if (gdst != NULL) {
  612. delete gdst;
  613. }
  614. rc = FALSE;
  615. }
  616. delete source;
  617. } else {
  618. TRC_ERR((TB, _T("Failed to create Bitmap object")));
  619. if (source != NULL) {
  620. delete source;
  621. }
  622. rc = FALSE;
  623. }
  624. #else // USE_GDIPLUS
  625. //
  626. // Non-GDI+ stretching solution, uses StretchBlt with the BltMode set
  627. // to HALFTONE
  628. //
  629. //
  630. // StretchBlt has a bug which will cause incorrect painting for
  631. // top-down, stretched, halftoned blts that use a subrectangle of
  632. // the source.
  633. //
  634. // So instead we'll always use clipping to get a subrectangle
  635. //
  636. if (srcLeft != 0 || srcTop != 0 || (DCUINT)srcWidth != desktopSize.width ||
  637. (DCUINT)srcHeight != desktopSize.height) {
  638. //
  639. // Calculate the destination rectangle
  640. //
  641. dstLeft = (float)srcLeft * (float)_scaleSize.width /
  642. (float)desktopSize.width;
  643. dstTop = (float)srcTop * (float)_scaleSize.height /
  644. (float)desktopSize.height;
  645. dstWidth = (float)srcWidth * (float)_scaleSize.width /
  646. (float)desktopSize.width;
  647. dstHeight = (float)srcHeight * (float)_scaleSize.height /
  648. (float)desktopSize.height;
  649. //
  650. // Make it region
  651. //
  652. int ndstLeft, ndstTop, ndstWidth, ndstHeight;
  653. #ifndef OS_WINCE
  654. ndstLeft = (int)floorf(dstLeft);
  655. ndstTop = (int)floorf(dstTop);
  656. ndstWidth = (int)ceilf(dstWidth);
  657. ndstHeight = (int)ceilf(dstHeight);
  658. #else
  659. ndstLeft = (int)floor(dstLeft);
  660. ndstTop = (int)floor(dstTop);
  661. ndstWidth = (int)ceil(dstWidth);
  662. ndstHeight = (int)ceil(dstHeight);
  663. #endif
  664. SetRectRgn(_hrgnUpdateRect, ndstLeft, ndstTop,
  665. ndstLeft + ndstWidth + 1, ndstTop + ndstHeight + 1);
  666. } else {
  667. dstLeft = 0;
  668. dstTop = 0;
  669. dstWidth = (float)_scaleSize.width;
  670. dstHeight = (float)_scaleSize.height;
  671. SetRectRgn(_hrgnUpdateRect, (int)dstLeft, (int)dstTop,
  672. (int)dstLeft + (int)dstWidth, (int)dstTop + (int)dstHeight);
  673. }
  674. if (fUseUpdateClipping) {
  675. //
  676. // _hrgnUpdate is the actual clipping region, which we don't want
  677. // to disturb. _hrgnUpdateRect is a scratch region we normally
  678. // use to create a rect region in before we update _hrgnUpdate
  679. // This time we do it backwards to preserve _hrgnUpdate but
  680. // since _hrgnUpdateRect is just as scratch anyway, use it and
  681. // don't create an extra region
  682. //
  683. if (!IntersectRgn(_hrgnUpdateRect, _hrgnUpdateRect, _hrgnUpdate)) {
  684. // Combining the regions failed. Consequence? StretchDIBits
  685. // may be slowing because it will copy bits that don't need
  686. // updating. But visually it will still be correct
  687. TRC_ERR((TB, _T("IntersectRgn failed!")));
  688. }
  689. }
  690. SelectClipRgn(hdc, _hrgnUpdateRect);
  691. DIBSECTION ds;
  692. #ifndef OS_WINCE
  693. if (_scaleSize.width >= desktopSize.width &&
  694. _scaleSize.height >= desktopSize.height)
  695. {
  696. //
  697. // PERF: In identity case use COLORONCOLOR
  698. // because HALFTONE is over 10 times slower
  699. //
  700. SetStretchBltMode(hdc, COLORONCOLOR);
  701. }
  702. else
  703. {
  704. //
  705. // HALFTONE looks good but is very slow
  706. //
  707. SetStretchBltMode(hdc, HALFTONE);
  708. }
  709. #endif
  710. SetBrushOrgEx(hdc, 0, 0, NULL);
  711. if (GetObject(_pUh->_UH.hShadowBitmap, sizeof(DIBSECTION), &ds) != 0) {
  712. if (_pUi->UI_GetOsMinorType() == TS_OSMINORTYPE_WINDOWS_NT) {
  713. ds.dsBmih.biHeight *= -1;
  714. }
  715. //
  716. // Update the traditional utility bmih, so we get the right
  717. // colors
  718. //
  719. _pUh->_UH.bitmapInfo.hdr.biHeight = ds.dsBmih.biHeight;
  720. _pUh->_UH.bitmapInfo.hdr.biWidth = ds.dsBmih.biWidth;
  721. _pUh->_UH.bitmapInfo.hdr.biClrImportant = ds.dsBmih.biClrImportant;
  722. _pUh->_UH.bitmapInfo.hdr.biClrUsed = ds.dsBmih.biClrUsed;
  723. #if 0
  724. _pUh->UH_HatchRectDC(hdc, (DCINT)dstLeft, (DCINT)dstTop,
  725. (DCINT)(dstLeft + dstWidth), (DCINT)(dstTop + dstHeight),
  726. UH_RGB_GREEN, UH_BRUSHTYPE_FDIAGONAL);
  727. #endif
  728. if (StretchDIBits(hdc, 0, 0, _scaleSize.width, _scaleSize.height,
  729. 0, 0, desktopSize.width, desktopSize.height,
  730. ds.dsBm.bmBits, (PBITMAPINFO) &(_pUh->_UH.bitmapInfo.hdr),
  731. _pUh->_UH.DIBFormat, SRCCOPY) != GDI_ERROR) {
  732. rc = TRUE;
  733. } else {
  734. TRC_SYSTEM_ERROR("StretchDIBits");
  735. rc = FALSE;
  736. }
  737. } else {
  738. TRC_SYSTEM_ERROR("GetObject");
  739. rc = FALSE;
  740. }
  741. if (fUseUpdateClipping) {
  742. //
  743. // Clear the clipping region
  744. //
  745. SelectClipRgn(hdc, NULL);
  746. }
  747. #endif // USE_GDIPLUS
  748. }
  749. DC_END_FN();
  750. return rc;
  751. }
  752. #endif // SMART_SIZING
  753. /**PROC+*********************************************************************/
  754. /* Name: OP_IncrementPalettePDUCount */
  755. /* */
  756. /* Purpose: Increment the count of palette PDUs being processed. */
  757. /* */
  758. /* Returns: None. */
  759. /* */
  760. /* Params: None. */
  761. /* */
  762. /**PROC-*********************************************************************/
  763. DCVOID DCAPI COP::OP_IncrementPalettePDUCount(DCVOID)
  764. {
  765. DC_BEGIN_FN("OP_IncrementPalettePDUCount");
  766. if (!_pUh->UH_ShadowBitmapIsEnabled())
  767. {
  768. #ifdef DC_DEBUG
  769. /********************************************************************/
  770. /* This tracing is before the interlocked inc so that the point at */
  771. /* which we're most likely to get pre-empted (TRC_GetBuffer) is */
  772. /* before all references to the variable we're interested in. */
  773. /********************************************************************/
  774. if (_OP.palettePDUsBeingProcessed >= 5)
  775. {
  776. TRC_ALT((TB, _T("TOO MANY Palette PDUs now pending processing: %ld"),
  777. _OP.palettePDUsBeingProcessed + 1));
  778. }
  779. else
  780. {
  781. TRC_NRM((TB, _T("Palette PDUs now pending processing: %ld"),
  782. _OP.palettePDUsBeingProcessed + 1));
  783. }
  784. #endif
  785. _pUt->UT_InterlockedIncrement(&_OP.palettePDUsBeingProcessed);
  786. }
  787. DC_END_FN();
  788. return;
  789. } /* OP_IncrementPalettePDUCount */
  790. /**PROC+*********************************************************************/
  791. /* Name: OP_Enable */
  792. /* */
  793. /* Purpose: Prepare OP for a new share. */
  794. /* */
  795. /* Returns: None. */
  796. /* */
  797. /* Params: None. */
  798. /* */
  799. /**PROC-*********************************************************************/
  800. DCVOID DCAPI COP::OP_Enable(DCVOID)
  801. {
  802. DCSIZE desktopSize;
  803. DC_BEGIN_FN("OP_Enable");
  804. /************************************************************************/
  805. /* Reset the count of palette PDUs received so that we correctly handle */
  806. /* abnormal call termination. */
  807. /************************************************************************/
  808. TRC_NRM((TB, _T("Reset pending palette count to zero")));
  809. _OP.palettePDUsBeingProcessed = 0;
  810. /************************************************************************/
  811. /* Show the output window, setting the size to match the new desktop */
  812. /* size */
  813. /************************************************************************/
  814. _pUi->UI_GetDesktopSize(&desktopSize);
  815. TRC_NRM((TB, _T("Show output window size %dx%d"), desktopSize.width,
  816. desktopSize.height));
  817. SetWindowPos( OP_GetOutputWindowHandle(),
  818. NULL,
  819. 0, 0,
  820. desktopSize.width,
  821. desktopSize.height,
  822. SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOMOVE |
  823. SWP_NOACTIVATE | SWP_NOOWNERZORDER );
  824. #if defined(SMART_SIZING) && !defined(USE_GDIPLUS)
  825. _hrgnUpdate = CreateRectRgn(0, 0, 0, 0);
  826. _hrgnUpdateRect = CreateRectRgn(0, 0, 0, 0);
  827. #endif
  828. DC_END_FN();
  829. return;
  830. } /* OP_Enable */
  831. /**PROC+*********************************************************************/
  832. /* Name: OP_Disable */
  833. /* */
  834. /* Purpose: Do OP end-of-share processing */
  835. /* */
  836. /* Returns: None. */
  837. /* */
  838. /* Params: fUseDisabledBitmap - if true display a grayed disable bitmap. */
  839. /* */
  840. /**PROC-*********************************************************************/
  841. DCVOID DCAPI COP::OP_Disable(BOOL fUseDisabledBitmap)
  842. {
  843. DC_BEGIN_FN("OP_Disable");
  844. DC_EXIT_POINT:
  845. DC_END_FN();
  846. return;
  847. } /* OP_Disable */