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.

616 lines
16 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: mngray.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains the DrawState API
  7. *
  8. * History:
  9. * 01-05-94 FritzS Ported from Chicago
  10. \***************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #define PATOR 0x00FA0089L
  14. #define SRCSTENCIL 0x00B8074AL
  15. #define SRCINVSTENCIL 0x00E20746L
  16. #define BC_INVERT 0x00000001
  17. void BltColor(HDC hdc, HBRUSH hbr, HDC hdcSrce,int xO, int yO,
  18. int cx, int cy, int xO1, int yO1, UINT uBltFlags);
  19. /***************************************************************************\
  20. *
  21. * BitBltSysBmp()
  22. *
  23. * From Chicago -- client *only* for now.
  24. \***************************************************************************/
  25. BOOL FAR BitBltSysBmp(HDC hdc, int x, int y, UINT i)
  26. {
  27. POEMBITMAPINFO pOem = gpsi->oembmi + i;
  28. return(NtUserBitBltSysBmp(hdc, x, y, pOem->cx, pOem->cy, pOem->x, pOem->y, SRCCOPY));
  29. }
  30. /***************************************************************************\
  31. *
  32. * DrawState()
  33. *
  34. * Generic state drawing routine. Does simple drawing into same DC if
  35. * normal state; uses offscreen bitmap otherwise.
  36. *
  37. * We do drawing for these simple types ourselves:
  38. * (1) Text
  39. * lData is string pointer.
  40. * wData is string length
  41. * (2) Icon
  42. * LOWORD(lData) is hIcon
  43. * (3) Bitmap
  44. * LOWORD(lData) is hBitmap
  45. * (4) Glyph (internal)
  46. * LOWORD(lData) is OBI_ value, one of
  47. * OBI_CHECKMARK
  48. * OBI_BULLET
  49. * OBI_MENUARROW
  50. * right now
  51. *
  52. * Other types are required to draw via the callback function, and are
  53. * allowed to stick whatever they want in lData and wData.
  54. *
  55. * We apply the following effects onto the image:
  56. * (1) Normal (nothing)
  57. * (2) Default (drop shadow)
  58. * (3) Union (gray string dither)
  59. * (4) Disabled (embossed)
  60. *
  61. * Note that we do NOT stretch anything. We just clip.
  62. *
  63. *
  64. * FritzS note -- this is client-side *only*. Similar code is in server\mngray.c
  65. *
  66. *
  67. \***************************************************************************/
  68. FUNCLOG10(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, DrawStateW, HDC, hdcDraw, HBRUSH, hbrFore, DRAWSTATEPROC, qfnCallBack, LPARAM, lData, WPARAM, wData, int, x, int, y, int, cx, int, cy, UINT, uFlags)
  69. BOOL DrawStateW(
  70. HDC hdcDraw,
  71. HBRUSH hbrFore,
  72. DRAWSTATEPROC qfnCallBack,
  73. LPARAM lData,
  74. WPARAM wData,
  75. int x,
  76. int y,
  77. int cx,
  78. int cy,
  79. UINT uFlags)
  80. {
  81. HFONT hFont;
  82. HFONT hFontSave = NULL;
  83. HDC hdcT;
  84. HBITMAP hbmpT;
  85. BOOL fResult = FALSE;
  86. DWORD dwPSMFlags;
  87. POINT ptOrg;
  88. int oldAlign;
  89. DWORD dwLayout = GDI_ERROR;
  90. if (ghdcGray == NULL)
  91. return FALSE;
  92. RtlEnterCriticalSection(&gcsHdc);
  93. /*
  94. * These require monochrome conversion
  95. *
  96. * Enforce monochrome: embossed doesn't look great with 2 color displays
  97. */
  98. if ((uFlags & DSS_DISABLED) &&
  99. (gpsi->BitCount == 1 || SYSMET(SLOWMACHINE))) {
  100. uFlags &= ~DSS_DISABLED;
  101. uFlags |= DSS_UNION;
  102. }
  103. if (uFlags & (DSS_DISABLED | DSS_DEFAULT | DSS_UNION))
  104. uFlags |= DSS_MONO;
  105. /*
  106. * Get drawing sizes etc. AND VALIDATE.
  107. */
  108. switch (uFlags & DST_TYPEMASK) {
  109. case DST_GLYPH:
  110. /*
  111. * LOWORD(lData) is OBI_ value.
  112. */
  113. if (LOWORD(lData) >= (WORD)OBI_COUNT) {
  114. goto CDS_Leave;
  115. }
  116. if (!cx) {
  117. cx = gpsi->oembmi[LOWORD(lData)].cx;
  118. }
  119. if (!cy) {
  120. cy = gpsi->oembmi[LOWORD(lData)].cy;
  121. }
  122. break;
  123. case DST_BITMAP:
  124. /*
  125. * LOWORD(lData) is hbmp.
  126. */
  127. if (GetObjectType((HGDIOBJ)lData) != OBJ_BITMAP) {
  128. goto CDS_Leave;
  129. }
  130. if (!cx || !cy) {
  131. BITMAP bmp;
  132. GetObjectW((HGDIOBJ)lData, sizeof(BITMAP), &bmp);
  133. if (!cx)
  134. cx = bmp.bmWidth;
  135. if (!cy)
  136. cy = bmp.bmHeight;
  137. }
  138. break;
  139. case DST_ICON:
  140. /*
  141. * lData is hicon.
  142. */
  143. if (!cx || !cy) {
  144. int cx1 = 0;
  145. int cy1 = 0;
  146. NtUserGetIconSize((HICON)lData, 0, &cx1, &cy1);
  147. if (!cx)
  148. cx = cx1;
  149. if (!cy)
  150. cy = cy1 / 2; // icons are double height in NT
  151. }
  152. break;
  153. case DST_TEXT:
  154. /*
  155. * lData is LPSTR
  156. * NOTE THAT WE DO NOT VALIDATE lData, DUE TO COMPATIBILITY
  157. * WITH GRAYSTRING(). THIS _SHOULD_ FAULT IF YOU PASS IN NULL.
  158. *
  159. * wData is cch.
  160. */
  161. if (!wData)
  162. wData = wcslen((LPWSTR)lData);
  163. if (!cx || !cy) {
  164. SIZE size;
  165. /*
  166. * Make sure we use right dc w/ right font.
  167. */
  168. GetTextExtentPointW(hdcDraw, (LPWSTR)lData, (INT)wData, &size);
  169. if (!cx)
  170. cx = size.cx;
  171. if (!cy)
  172. cy = size.cy;
  173. }
  174. /*
  175. * Now, pretend we're complex if qfnCallBack is supplied AND
  176. * we're supporting GrayString().
  177. */
  178. #if 0 // This will get turned on if/when we change GrayString to tie
  179. // into DrawState.
  180. //
  181. // FritzS
  182. if ((uFlags & DST_GRAYSTRING) && SELECTOROF(qfnCallBack)) {
  183. uFlags &= ~DST_TYPEMASK;
  184. uFlags |= DST_COMPLEX;
  185. }
  186. #endif
  187. break;
  188. case DST_PREFIXTEXT:
  189. if (lData == 0) {
  190. RIPMSG0(RIP_ERROR, "DrawState: NULL DST_PREFIXTEXT string");
  191. goto CDS_Leave;
  192. }
  193. if (!wData)
  194. wData = wcslen((LPWSTR)lData);
  195. if (!cx || !cy) {
  196. SIZE size;
  197. PSMGetTextExtent(hdcDraw, (LPWSTR)lData, (int)wData, &size);
  198. if (!cx)
  199. cx = size.cx;
  200. if (!cy)
  201. cy = size.cy;
  202. }
  203. /*
  204. * Add on height for prefix
  205. */
  206. cy += (2 * SYSMET(CYBORDER));
  207. break;
  208. case DST_COMPLEX:
  209. #if 0
  210. if (!SELECTOROF(qfnCallBack)) {
  211. DebugErr(DBF_ERROR, "DrawState: invalid callback for DST_COMPLEX");
  212. goto CDS_Leave;
  213. }
  214. #endif
  215. break;
  216. default:
  217. RIPMSG0(RIP_ERROR, "DrawState: invalid DST_ type");
  218. goto CDS_Leave;
  219. }
  220. /*
  221. * Optimize: nothing to draw
  222. * Have to call callback if GRAYSTRING for compatibility.
  223. */
  224. if ((!cx || !cy)
  225. // && !(uFlags & DST_GRAYSTRING)
  226. ) {
  227. fResult = TRUE;
  228. goto CDS_Leave;
  229. }
  230. /*
  231. * Setup drawing dc
  232. */
  233. if (uFlags & DSS_MONO) {
  234. hdcT = ghdcGray;
  235. /*
  236. * First turn off mirroring on hdcGray if any.
  237. */
  238. SetLayoutWidth(hdcT, -1, 0);
  239. /*
  240. * Set the ghdcGray layout to be equal to the screen hdcDraw layout.
  241. */
  242. dwLayout = GetLayout(hdcDraw);
  243. if (dwLayout != GDI_ERROR) {
  244. SetLayoutWidth(hdcT, cx, dwLayout);
  245. }
  246. /*
  247. * Is our scratch bitmap big enough? We need potentially
  248. * cx+1 by cy pixels for default etc.
  249. */
  250. if ((gcxGray < cx + 1) || (gcyGray < cy)) {
  251. if (hbmpT = CreateBitmap(max(gcxGray, cx + 1), max(gcyGray, cy), 1, 1, 0L)) {
  252. HBITMAP hbmGray;
  253. hbmGray = SelectObject(ghdcGray, hbmpT);
  254. DeleteObject(hbmGray);
  255. gcxGray = max(gcxGray, cx + 1);
  256. gcyGray = max(gcyGray, cy);
  257. } else {
  258. cx = gcxGray - 1;
  259. cy = gcyGray;
  260. }
  261. }
  262. PatBlt(ghdcGray, 0, 0, gcxGray, gcyGray, WHITENESS);
  263. SetTextCharacterExtra(ghdcGray, GetTextCharacterExtra(hdcDraw));
  264. oldAlign = GetTextAlign(hdcT);
  265. SetTextAlign(hdcT, (oldAlign & ~(TA_RTLREADING |TA_CENTER |TA_RIGHT))
  266. | (GetTextAlign(hdcDraw) & (TA_RTLREADING |TA_CENTER |TA_RIGHT)));
  267. /*
  268. * Setup font
  269. */
  270. if ((uFlags & DST_TYPEMASK) <= DST_TEXTMAX) {
  271. if (GetCurrentObject(hdcDraw, OBJ_FONT) != ghFontSys) {
  272. hFont = SelectObject(hdcDraw, ghFontSys);
  273. SelectObject(hdcDraw, hFont);
  274. hFontSave = SelectObject(ghdcGray, hFont);
  275. }
  276. }
  277. } else {
  278. hdcT = hdcDraw;
  279. /*
  280. * Adjust viewport
  281. */
  282. GetViewportOrgEx(hdcT, &ptOrg);
  283. SetViewportOrgEx(hdcT, ptOrg.x + x, ptOrg.y + y, NULL);
  284. }
  285. /*
  286. * Now, draw original image
  287. */
  288. fResult = TRUE;
  289. switch (uFlags & DST_TYPEMASK) {
  290. case DST_GLYPH:
  291. /*
  292. * Blt w/ current brush in hdcT
  293. */
  294. BitBltSysBmp(hdcT, 0, 0, LOWORD(lData));
  295. break;
  296. case DST_BITMAP:
  297. /*
  298. * Draw the bitmap. If mono, it'll use the colors set up
  299. * in the dc.
  300. */
  301. // RtlEnterCriticalSection(&gcsHdcBits2);
  302. UserAssert(GetBkColor(ghdcBits2) == RGB(255, 255, 255));
  303. UserAssert(GetTextColor(ghdcBits2) == RGB(0, 0, 0));
  304. hbmpT = SelectObject(ghdcBits2, (HBITMAP)lData);
  305. BitBlt(hdcT, 0, 0, cx, cy, ghdcBits2, 0, 0, SRCCOPY);
  306. SelectObject(ghdcBits2, hbmpT);
  307. // RtlLeaveCriticalSection(&gcsHdcBits2);
  308. break;
  309. case DST_ICON:
  310. /*
  311. * Draw the icon.
  312. */
  313. DrawIconEx(hdcT, 0, 0, (HICON)lData, 0, 0, 0, NULL, DI_NORMAL);
  314. break;
  315. case DST_PREFIXTEXT:
  316. if (uFlags & DSS_HIDEPREFIX) {
  317. dwPSMFlags = DT_HIDEPREFIX;
  318. } else if (uFlags & DSS_PREFIXONLY) {
  319. dwPSMFlags = DT_PREFIXONLY;
  320. } else {
  321. dwPSMFlags = 0;
  322. }
  323. PSMTextOut(hdcT, 0, 0, (LPWSTR)lData, (int)wData, dwPSMFlags);
  324. break;
  325. case DST_TEXT:
  326. fResult = TextOutW(hdcT, 0, 0, (LPWSTR)lData, (int)wData);
  327. break;
  328. default:
  329. fResult = (qfnCallBack)(hdcT, lData, wData, cx, cy);
  330. /*
  331. * The callbacks could have altered the attributes of ghdcGray
  332. */
  333. if (hdcT == ghdcGray) {
  334. SetBkColor(ghdcGray, RGB(255, 255, 255));
  335. SetTextColor(ghdcGray, RGB(0, 0, 0));
  336. SelectObject(ghdcGray, GetStockObject(BLACK_BRUSH));
  337. SetBkMode(ghdcGray, OPAQUE);
  338. }
  339. break;
  340. }
  341. /*
  342. * Clean up
  343. */
  344. if (uFlags & DSS_MONO) {
  345. /*
  346. * Reset font
  347. */
  348. if (hFontSave)
  349. SelectObject(hdcT, hFontSave);
  350. SetTextAlign(hdcT, oldAlign);
  351. } else {
  352. /*
  353. * Reset DC.
  354. */
  355. SetViewportOrgEx(hdcT, ptOrg.x, ptOrg.y, NULL);
  356. goto CDS_Leave;
  357. }
  358. /*
  359. * UNION state
  360. * Dither over image
  361. * We want white pixels to stay white, in either dest or pattern.
  362. */
  363. if (uFlags & DSS_UNION) {
  364. POLYPATBLT PolyData;
  365. PolyData.x = 0;
  366. PolyData.y = 0;
  367. PolyData.cx = cx;
  368. PolyData.cy = cy;
  369. PolyData.BrClr.hbr = gpsi->hbrGray;
  370. PolyPatBlt(ghdcGray, PATOR, &PolyData, 1, PPB_BRUSH);
  371. }
  372. /*
  373. * DISABLED state
  374. * Emboss
  375. * Draw over-1/down-1 in hilight color, and in same position in shadow.
  376. *
  377. * DEFAULT state
  378. * Drop shadow
  379. * Draw over-1/down-1 in shadow color, and in same position in foreground
  380. * Draw offset down in shadow color,
  381. */
  382. if (uFlags & DSS_DISABLED) {
  383. BltColor(hdcDraw,
  384. SYSHBR(3DHILIGHT),
  385. ghdcGray,
  386. x + 1,
  387. y + 1,
  388. cx,
  389. cy,
  390. 0,
  391. 0,
  392. BC_INVERT);
  393. BltColor(hdcDraw,
  394. SYSHBR(3DSHADOW),
  395. ghdcGray,
  396. x,
  397. y,
  398. cx,
  399. cy,
  400. 0,
  401. 0,
  402. BC_INVERT);
  403. } else if (uFlags & DSS_DEFAULT) {
  404. BltColor(hdcDraw,
  405. SYSHBR(3DSHADOW),
  406. ghdcGray,
  407. x+1,
  408. y+1,
  409. cx,
  410. cy,
  411. 0,
  412. 0,
  413. BC_INVERT);
  414. goto DrawNormal;
  415. } else {
  416. DrawNormal:
  417. BltColor(hdcDraw, hbrFore, ghdcGray, x, y, cx, cy, 0, 0, BC_INVERT);
  418. }
  419. CDS_Leave:
  420. if (uFlags & DSS_MONO) {
  421. /*
  422. * Set the ghdcGray layout to 0, it is a public DC.
  423. */
  424. if (dwLayout != GDI_ERROR) {
  425. SetLayoutWidth(hdcT, -1, 0);
  426. }
  427. }
  428. RtlLeaveCriticalSection(&gcsHdc);
  429. return fResult;
  430. }
  431. FUNCLOG10(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, DrawStateA, HDC, hDC, HBRUSH, hBrush, DRAWSTATEPROC, func, LPARAM, lParam, WPARAM, wParam, int, x, int, y, int, cx, int, cy, UINT, wFlags)
  432. BOOL DrawStateA(HDC hDC, HBRUSH hBrush, DRAWSTATEPROC func,
  433. LPARAM lParam, WPARAM wParam, int x, int y, int cx, int cy, UINT wFlags)
  434. {
  435. LPARAM lpwstr = lParam;
  436. BOOL bRet;
  437. BOOL bFree;
  438. if (((wFlags & DST_TYPEMASK) == DST_TEXT) ||
  439. ((wFlags & DST_TYPEMASK) == DST_PREFIXTEXT)) {
  440. bFree = TRUE;
  441. if ((wParam = MBToWCS((LPSTR)lParam, wParam ? (int)wParam : USER_AWCONV_COUNTSTRINGSZ, &(LPWSTR)lpwstr, -1, TRUE)) == 0)
  442. return FALSE;
  443. } else {
  444. bFree = FALSE;
  445. }
  446. bRet = DrawStateW(hDC, hBrush, func, lpwstr, wParam, x, y, cx, cy, wFlags);
  447. if (bFree) {
  448. UserLocalFree((HANDLE)lpwstr);
  449. }
  450. return bRet;
  451. }
  452. /***************************************************************************\
  453. * BltColor
  454. *
  455. * History:
  456. \***************************************************************************/
  457. void BltColor(
  458. HDC hdc,
  459. HBRUSH hbr,
  460. HDC hdcSrce,
  461. int xO,
  462. int yO,
  463. int cx,
  464. int cy,
  465. int xO1,
  466. int yO1,
  467. UINT uBltFlags
  468. )
  469. {
  470. HBRUSH hbrSave;
  471. HBRUSH hbrNew = NULL;
  472. DWORD textColorSave;
  473. DWORD bkColorSave;
  474. if (hbr == (HBRUSH)NULL) {
  475. LOGBRUSH lb;
  476. lb.lbStyle = BS_SOLID;
  477. lb.lbColor = GetSysColor(COLOR_WINDOWTEXT);
  478. hbrNew = hbr = CreateBrushIndirect(&lb);
  479. }
  480. /*
  481. * Set the Text and Background colors so that bltColor handles the
  482. * background of buttons (and other bitmaps) properly.
  483. * Save the HDC's old Text and Background colors. This causes problems with
  484. * Omega (and probably other apps) when calling GrayString which uses this
  485. * routine...
  486. */
  487. textColorSave = SetTextColor(hdc, 0x00000000L);
  488. bkColorSave = SetBkColor(hdc, 0x00FFFFFFL);
  489. hbrSave = SelectObject(hdc, hbr);
  490. BitBlt(hdc, xO, yO, cx, cy, hdcSrce,
  491. xO1, yO1, ((uBltFlags & BC_INVERT) ? 0xB8074AL : 0xE20746L));
  492. //xO1, yO1, (fInvert ? 0xB80000 : 0xE20000));
  493. SelectObject(hdc, hbrSave);
  494. /*
  495. * Restore saved colors
  496. */
  497. SetTextColor(hdc, textColorSave);
  498. SetBkColor(hdc, bkColorSave);
  499. if (hbrNew) {
  500. DeleteObject(hbrNew);
  501. }
  502. }