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.

390 lines
14 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: drawstream.c *
  3. * *
  4. * Client side draw stream support. Handles metafiling if primary *
  5. * is a metafile. *
  6. * *
  7. * Created: 03-Mar-2001 *
  8. * Author: Barton House [bhouse] *
  9. * *
  10. * Copyright (c) 1991-2001 Microsoft Corporation *
  11. \**************************************************************************/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. /******************************Public*Routine******************************\
  15. * GdiDrawStream
  16. *
  17. *
  18. * Arguments:
  19. *
  20. *
  21. *
  22. * Return Value:
  23. *
  24. *
  25. *
  26. * History:
  27. *
  28. * 3/21/2001 Barton House
  29. *
  30. \**************************************************************************/
  31. BOOL
  32. GdiDrawStream(
  33. HDC hdcDst,
  34. ULONG cjIn,
  35. VOID *pvIn)
  36. {
  37. BOOL bRet = FALSE;
  38. PDC_ATTR pdca;
  39. FIXUP_HANDLE(hdcDst);
  40. if (IS_ALTDC_TYPE(hdcDst))
  41. {
  42. HBITMAP hbmSource = NULL;
  43. HRGN hrgnSaved = NULL;
  44. HBITMAP hbmScratch = NULL;
  45. HDC hdcScratch = NULL;
  46. int iDstClip = -1;
  47. ULONG * pul = (ULONG *) pvIn;
  48. if(cjIn < sizeof(ULONG))
  49. return FALSE;
  50. if(*pul++ != 'DrwS')
  51. return FALSE;
  52. cjIn -= sizeof(ULONG);
  53. while(cjIn >= sizeof(ULONG))
  54. {
  55. ULONG command = *pul;
  56. ULONG commandSize;
  57. RECTL rclDstClip;
  58. switch(command)
  59. {
  60. case DS_SETTARGETID: // set target
  61. {
  62. DS_SETTARGET * cmd = (DS_SETTARGET *) pul;
  63. commandSize = sizeof(*cmd);
  64. if(cjIn < commandSize)
  65. goto altExit;
  66. if((HDC) ULongToHandle(cmd->hdc) != hdcDst)
  67. {
  68. // NOTE: This restriction is only in place for the
  69. // initial implementation of GdiDrawStream.
  70. WARNING("GdiDrawStream: target must match primary target");
  71. goto altExit;
  72. }
  73. rclDstClip = cmd->rclDstClip;
  74. if(hrgnSaved == NULL)
  75. {
  76. int iRet;
  77. hrgnSaved = CreateRectRgn(0,0,0,0);
  78. if(hrgnSaved == NULL)
  79. {
  80. WARNING("GdiDrawStream: unable to create saved region");
  81. goto altExit;
  82. }
  83. iDstClip = GetClipRgn(hdcDst, hrgnSaved);
  84. if(iDstClip == -1)
  85. {
  86. WARNING("GdiDrawStream: failed to get DC application clip");
  87. goto altExit;
  88. }
  89. }
  90. else
  91. {
  92. // need to restore target clip
  93. if(iDstClip)
  94. {
  95. SelectClipRgn(hdcDst, hrgnSaved);
  96. }
  97. else
  98. {
  99. SelectClipRgn(hdcDst, NULL);
  100. }
  101. }
  102. IntersectClipRect(hdcDst, rclDstClip.left, rclDstClip.top, rclDstClip.right, rclDstClip.bottom);
  103. }
  104. break;
  105. case DS_SETSOURCEID: // set source
  106. {
  107. DS_SETSOURCE * cmd = (DS_SETSOURCE *) pul;
  108. commandSize = sizeof(*cmd);
  109. if(cjIn < commandSize)
  110. goto altExit;
  111. hbmSource = (HBITMAP) ULongToHandle(cmd->hbm);
  112. }
  113. break;
  114. case DS_NINEGRIDID:
  115. {
  116. DS_NINEGRID * cmd = (DS_NINEGRID *) pul;
  117. LONG lSrcWidth = cmd->rclSrc.right - cmd->rclSrc.left;
  118. LONG lSrcHeight = cmd->rclSrc.bottom - cmd->rclSrc.top;
  119. LONG lDstWidth = cmd->rclDst.right - cmd->rclDst.left;
  120. LONG lDstHeight = cmd->rclDst.bottom - cmd->rclDst.top;
  121. BOOL bRenderRet;
  122. RECTL rclDst = cmd->rclDst;
  123. struct {
  124. BITMAPINFOHEADER bmih;
  125. ULONG masks[3];
  126. } bmi;
  127. struct {
  128. DS_HEADER hdr;
  129. DS_SETTARGET setTarget;
  130. DS_SETSOURCE setSource;
  131. DS_NINEGRID ng;
  132. } scratchStream;
  133. RECTL rclScratch;
  134. commandSize = sizeof(DS_NINEGRID);
  135. // validate nine grid
  136. #define DSDNG_MASK 0x007F // move to wingdip.h
  137. if(cmd->ngi.flFlags & ~DSDNG_MASK)
  138. {
  139. WARNING("GreDrawStream: unrecognized nine grid flags set\n");
  140. goto altExit;
  141. }
  142. if(lSrcWidth < 0 || lSrcHeight < 0)
  143. {
  144. WARNING("GreDrawStream: nine grid rclSrc is not well ordered\n");
  145. goto altExit;
  146. }
  147. if(cmd->ngi.flFlags & DSDNG_TRUESIZE)
  148. {
  149. if(lDstWidth > lSrcWidth)
  150. {
  151. lDstWidth = lSrcWidth;
  152. rclDst.right = rclDst.left + lDstWidth;
  153. }
  154. if(lDstHeight > lSrcHeight)
  155. {
  156. lDstHeight = lSrcHeight;
  157. rclDst.bottom = rclDst.top + lDstHeight;
  158. }
  159. }
  160. else
  161. {
  162. // NOTE: we have to check individual first then sum due to possible
  163. // numerical overflows that could occur in the sum that might
  164. // not be detected otherwise.
  165. if(cmd->ngi.ulLeftWidth < 0 ||
  166. cmd->ngi.ulRightWidth < 0 ||
  167. cmd->ngi.ulTopHeight < 0 ||
  168. cmd->ngi.ulBottomHeight < 0 ||
  169. cmd->ngi.ulLeftWidth > lSrcWidth ||
  170. cmd->ngi.ulRightWidth > lSrcWidth ||
  171. cmd->ngi.ulTopHeight > lSrcHeight ||
  172. cmd->ngi.ulBottomHeight > lSrcHeight ||
  173. cmd->ngi.ulLeftWidth + cmd->ngi.ulRightWidth > lSrcWidth ||
  174. cmd->ngi.ulTopHeight + cmd->ngi.ulBottomHeight > lSrcHeight)
  175. {
  176. WARNING("GreDrawStream: nine grid width is greater then rclSrc width or negative\n");
  177. goto altExit;
  178. }
  179. }
  180. if((cmd->ngi.flFlags & (DSDNG_TRANSPARENT | DSDNG_PERPIXELALPHA)) == (DSDNG_TRANSPARENT | DSDNG_PERPIXELALPHA))
  181. {
  182. WARNING("GreDrawStream: nine grid attempt to set both transparency and per pixel alpha\n");
  183. goto altExit;
  184. }
  185. // create temporary to render nine grid into
  186. bmi.bmih.biSize = sizeof(bmi.bmih);
  187. bmi.bmih.biWidth = lDstWidth;
  188. bmi.bmih.biHeight = lDstHeight;
  189. bmi.bmih.biPlanes = 1;
  190. bmi.bmih.biBitCount = 32;
  191. bmi.bmih.biCompression = BI_BITFIELDS;
  192. bmi.bmih.biSizeImage = 0;
  193. bmi.bmih.biXPelsPerMeter = 0;
  194. bmi.bmih.biYPelsPerMeter = 0;
  195. bmi.bmih.biClrUsed = 3;
  196. bmi.bmih.biClrImportant = 0;
  197. bmi.masks[0] = 0xff0000; // red
  198. bmi.masks[1] = 0x00ff00; // green
  199. bmi.masks[2] = 0x0000ff; // blue
  200. if(hbmScratch != NULL)
  201. DeleteObject(hbmScratch);
  202. hbmScratch = CreateDIBitmap(hdcDst, &bmi.bmih, CBM_CREATEDIB , NULL, (BITMAPINFO*)&bmi.bmih, DIB_RGB_COLORS);
  203. if(hbmScratch == NULL)
  204. {
  205. WARNING("GdiDrawStream: unable to create temporary\n");
  206. goto altExit;
  207. }
  208. if(hdcScratch == NULL)
  209. {
  210. hdcScratch = CreateCompatibleDC(hdcDst);
  211. if(hdcScratch == NULL)
  212. {
  213. WARNING("GdiDrawStream: unable to create temporary dc\n");
  214. goto altExit;
  215. }
  216. }
  217. SelectObject(hdcScratch, hbmScratch);
  218. rclScratch.left = 0;
  219. rclScratch.top = 0;
  220. rclScratch.right = lDstWidth;
  221. rclScratch.bottom = lDstHeight;
  222. scratchStream.hdr.magic = DS_MAGIC;
  223. scratchStream.setTarget.ulCmdID = DS_SETTARGETID;
  224. scratchStream.setTarget.hdc = HandleToULong(hdcScratch);
  225. scratchStream.setTarget.rclDstClip = rclScratch;
  226. scratchStream.setSource.ulCmdID = DS_SETSOURCEID;
  227. scratchStream.setSource.hbm = HandleToULong(hbmSource);
  228. scratchStream.ng.ulCmdID = DS_NINEGRIDID;
  229. scratchStream.ng.rclDst = rclScratch;
  230. scratchStream.ng.rclSrc = cmd->rclSrc;
  231. scratchStream.ng.ngi = cmd->ngi;
  232. scratchStream.ng.ngi.flFlags &= ~(DSDNG_TRANSPARENT | DSDNG_PERPIXELALPHA);
  233. NtGdiDrawStream(hdcScratch, sizeof(scratchStream), &scratchStream);
  234. if(cmd->ngi.flFlags & DSDNG_TRANSPARENT)
  235. {
  236. bRenderRet = GdiTransparentBlt(hdcDst,
  237. rclDst.left,
  238. rclDst.top,
  239. lDstWidth,
  240. lDstHeight,
  241. hdcScratch,
  242. 0,
  243. 0,
  244. lDstWidth,
  245. lDstHeight,
  246. cmd->ngi.crTransparent);
  247. }
  248. else if(cmd->ngi.flFlags & DSDNG_PERPIXELALPHA)
  249. {
  250. // alpha blend
  251. BLENDFUNCTION bfx;
  252. bfx.AlphaFormat = AC_SRC_ALPHA;
  253. bfx.BlendFlags = 0;
  254. bfx.BlendOp = AC_SRC_OVER;
  255. bfx.SourceConstantAlpha = 255;
  256. bRenderRet = GdiAlphaBlend(hdcDst,
  257. rclDst.left,
  258. rclDst.top,
  259. lDstWidth,
  260. lDstHeight,
  261. hdcScratch,
  262. 0,
  263. 0,
  264. lDstWidth,
  265. lDstHeight,
  266. bfx);
  267. }
  268. else
  269. {
  270. // bitblt
  271. bRenderRet = BitBlt(hdcDst,
  272. rclDst.left,
  273. rclDst.top,
  274. lDstWidth,
  275. lDstHeight,
  276. hdcScratch,
  277. 0,
  278. 0,
  279. SRCCOPY);
  280. }
  281. if(!bRenderRet)
  282. {
  283. WARNING("GdiDrawStream: failed to render temporary to destination");
  284. goto altExit;
  285. }
  286. }
  287. break;
  288. default:
  289. WARNING("GdiDrawStream: unrecognized command");
  290. goto altExit;
  291. }
  292. pul += commandSize / sizeof(ULONG);
  293. cjIn -= commandSize;
  294. }
  295. bRet = TRUE;
  296. altExit:
  297. if(iDstClip == 1)
  298. {
  299. SelectClipRgn(hdcDst, hrgnSaved);
  300. }
  301. else if(iDstClip == 0)
  302. {
  303. SelectClipRgn(hdcDst, NULL);
  304. }
  305. if(hbmScratch != NULL)
  306. DeleteObject(hbmScratch);
  307. if(hdcScratch != NULL)
  308. DeleteDC(hdcScratch);
  309. if(hrgnSaved != NULL)
  310. DeleteObject(hrgnSaved);
  311. return bRet;
  312. }
  313. RESETUSERPOLLCOUNT();
  314. bRet = NtGdiDrawStream(
  315. hdcDst,
  316. cjIn,
  317. pvIn);
  318. return(bRet);
  319. }