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.

515 lines
16 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: pixelapi.cxx
  3. *
  4. * This contains the functions that get/set individual pixels.
  5. *
  6. * Created: 25-Apr-1991 11:32:15
  7. * Author: Patrick Haluptzok patrickh
  8. *
  9. * Copyright (c) 1990-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. /******************************Public*Routine******************************\
  13. * GreSetPixel
  14. *
  15. * API entry point for putting a single pixel on the screen.
  16. *
  17. * Returns: -1 if point not in clip rgn or for blt failure,
  18. * or the color put on the device surface for success.
  19. *
  20. * History:
  21. * Tue 17-May-1994 -by- Patrick Haluptzok [patrickh]
  22. * update for size/perf and bug fix.
  23. *
  24. * Thu 4-Mar-1992 -by- Kent Diamond [kentd]
  25. * Pass in Attribute cache.
  26. *
  27. * Thu 27-Feb-1992 -by- Patrick Haluptzok [patrickh]
  28. * Fix RGB return.
  29. *
  30. * Thu 05-Dec-1991 -by- Patrick Haluptzok [patrickh]
  31. * bug fix, optimize for size, add error code logging.
  32. *
  33. * Fri 16-Aug-1991 -by- Patrick Haluptzok [patrickh]
  34. * Bug fix, make it return -1 for blt failure, cleanup
  35. *
  36. * 20-Apr-1991 -by- Patrick Haluptzok patrickh
  37. * Wrote it.
  38. \**************************************************************************/
  39. DWORD APIENTRY NtGdiSetPixel(HDC hdcDst, int x, int y, COLORREF crColor)
  40. {
  41. PAL_ULONG palul;
  42. palul.ul = 0xFFFFFFFF;
  43. XDCOBJ dcoDst(hdcDst);
  44. if (dcoDst.bValid())
  45. {
  46. //
  47. // Transform the coordinates to device space.
  48. //
  49. EPOINTL eptlDst(x,y);
  50. EXFORMOBJ xoDst(dcoDst, WORLD_TO_DEVICE);
  51. xoDst.bXform(eptlDst);
  52. ERECTL erclDst(eptlDst.x,eptlDst.y,eptlDst.x+1,eptlDst.y+1);
  53. //
  54. // Accumulate bounds. We can do this before knowing if the operation is
  55. // successful because bounds can be loose.
  56. //
  57. if (dcoDst.fjAccum())
  58. dcoDst.vAccumulate(erclDst);
  59. //
  60. // Check surface is included in DC.
  61. //
  62. if (dcoDst.bHasSurface())
  63. {
  64. //
  65. // Lock the device.
  66. //
  67. DEVLOCKOBJ dloTrg;
  68. if (dloTrg.bLock(dcoDst))
  69. {
  70. SURFACE *pSurfDst = dcoDst.pSurface();
  71. //
  72. // With a fixed DC origin we can change the destination to SCREEN coordinates.
  73. //
  74. erclDst += dcoDst.eptlOrigin();
  75. //
  76. // Parameter validation to avoid sticky overflow errors.
  77. // Note the validation is performed after the transform.
  78. // Any point that starts out in the invalid FIX zone may
  79. // potentially be transformed into the valid range and
  80. // therefore should be plotted.
  81. // Any point that's had it's bottom right wrap will be also invalidated
  82. // by this check.
  83. // Use of BLTOFXOK is probably an overkill, but lower level code
  84. // could potentially do a FIX conversion.
  85. //
  86. if (!BLTOFXOK(erclDst.left) ||
  87. !BLTOFXOK(erclDst.right) ||
  88. !BLTOFXOK(erclDst.top) ||
  89. !BLTOFXOK(erclDst.bottom))
  90. {
  91. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  92. //
  93. // XDCOBJ does not automagically clean up it's locks in
  94. // its destructor so we have do it explicitly here.
  95. //
  96. dcoDst.vUnlockFast();
  97. return (DWORD)(GDI_ERROR); //fail
  98. }
  99. ECLIPOBJ *pco = NULL;
  100. //
  101. // This is a pretty knarly expression to save a return in here.
  102. // Basically pco can be NULL if the rect is completely in the
  103. // cached rect in the DC or if we set up a clip object that isn't empty.
  104. //
  105. if (((erclDst.left >= dcoDst.prclClip()->left) &&
  106. (erclDst.right <= dcoDst.prclClip()->right) &&
  107. (erclDst.top >= dcoDst.prclClip()->top) &&
  108. (erclDst.bottom <= dcoDst.prclClip()->bottom)) ||
  109. (pco = dcoDst.pco(),
  110. pco->vSetup(dcoDst.prgnEffRao(), erclDst,CLIP_NOFORCETRIV),
  111. !pco->erclExclude().bEmpty()))
  112. {
  113. //
  114. // Make a fake solid color brush for this guy.
  115. //
  116. XEPALOBJ palDst(pSurfDst->ppal());
  117. XEPALOBJ palDstDC(dcoDst.ppal());
  118. BBRUSHOBJ bo;
  119. BOOL bCMYKColor = dcoDst.pdc->bIsCMYKColor();
  120. //
  121. // Initialize BRUSHOBJ on stack.
  122. //
  123. bo.pvRbrush = (PVOID) NULL;
  124. bo.flColorType = 0;
  125. //
  126. // if the in CMYK color mode, iSolidColor is CMYK color.
  127. //
  128. if (bCMYKColor)
  129. {
  130. bo.iSolidColor = crColor;
  131. bo.flColorType = (BR_CMYKCOLOR | BR_HOST_ICM);
  132. if (gbMultiMonMismatchColor)
  133. {
  134. bo.crRealized(crColor);
  135. bo.crDCPalColor(crColor);
  136. }
  137. }
  138. else
  139. {
  140. bo.iSolidColor = ulGetNearestIndexFromColorref(palDst, palDstDC, crColor);
  141. if (dcoDst.pdc->bIsSoftwareICM())
  142. {
  143. bo.flColorType = BR_HOST_ICM;
  144. }
  145. else if (dcoDst.pdc->bIsDeviceICM())
  146. {
  147. bo.flColorType = BR_DEVICE_ICM;
  148. }
  149. if (gbMultiMonMismatchColor)
  150. {
  151. bo.crRealized(crColor);
  152. bo.crDCPalColor(rgbFromColorref(palDst, palDstDC, crColor));
  153. }
  154. }
  155. //
  156. // Set up the correct return value.
  157. //
  158. DEVEXCLUDEOBJ dxo(dcoDst,&erclDst,pco);
  159. INC_SURF_UNIQ(pSurfDst);
  160. ULONG rop4 = gaMix[dcoDst.pdc->jROP2() & 0x0F];
  161. rop4 |= (rop4 << 8);
  162. if ((*(pSurfDst->pfnBitBlt()))
  163. (
  164. pSurfDst->pSurfobj(),
  165. (SURFOBJ *) NULL,
  166. (SURFOBJ *) NULL,
  167. NULL,
  168. NULL,
  169. &erclDst,
  170. (POINTL *) NULL,
  171. (POINTL *) NULL,
  172. &bo,
  173. &dcoDst.pdc->ptlFillOrigin(),
  174. rop4
  175. ))
  176. {
  177. if (bCMYKColor)
  178. {
  179. palul.ul = bo.iSolidColor;
  180. }
  181. else
  182. {
  183. palul.ul = ulIndexToRGB(palDst, palDstDC, bo.iSolidColor);
  184. }
  185. }
  186. }
  187. }
  188. }
  189. dcoDst.vUnlockFast();
  190. }
  191. else
  192. {
  193. WARNING1("ERROR GreSetPixel called on invalid DC\n");
  194. }
  195. return(palul.ul);
  196. }
  197. #if 0
  198. /******************************Public*Routine******************************\
  199. * EngGetPixel
  200. *
  201. * This facilitates GetPixel on DIBs.
  202. *
  203. * History:
  204. * 27-Apr-1991 -by- Patrick Haluptzok patrickh
  205. * Wrote it.
  206. \**************************************************************************/
  207. ULONG EngGetPixel(
  208. SURFACE *pSurfSrc,
  209. PPOINTL pptlSrc)
  210. {
  211. ULONG ulReturn;
  212. PBYTE pjBits;
  213. LONG lDelta;
  214. ASSERTGDI(pSurfSrc != (PDIBOBJ) NULL, "ERROR GDI EngCopyBits");
  215. ASSERTGDI(pptlSrc != (PPOINTL) NULL, "ERROR GDI EngCopyBits");
  216. ASSERTGDI(pSurfSrc->iType() == STYPE_BITMAP, "ERROR GDI EngCopyBits");
  217. ASSERTGDI(pptlSrc->x < pSurfSrc->sizl().cx, "ERROR GDI EngCopyBits");
  218. ASSERTGDI(pptlSrc->y < pSurfSrc->sizl().cy, "ERROR GDI EngCopyBits");
  219. lDelta = pSurfSrc->lDelta();
  220. pjBits = (PBYTE) pSurfSrc->pvScan0();
  221. pjBits = pjBits + (lDelta * pptlSrc->y);
  222. // Synchronize with the device driver before touching the device surface.
  223. {
  224. PDEVOBJ po(pSurfSrc->hdev());
  225. po.vSync(pSurfSrc,NULL,0);
  226. }
  227. switch(pSurfSrc->iFormat())
  228. {
  229. case BMF_1BPP:
  230. // Get the correct byte.
  231. ulReturn = (ULONG) *(pjBits + (pptlSrc->x >> 3));
  232. // Get the correct bit in the lowest bit.
  233. ulReturn = ulReturn >> (7 - (pptlSrc->x & 7));
  234. // Mask off the top bits.
  235. ulReturn = ulReturn & 1;
  236. break;
  237. case BMF_4BPP:
  238. // Get the correct byte.
  239. ulReturn = (ULONG) *(pjBits + (pptlSrc->x >> 1));
  240. if (pptlSrc->x & 1)
  241. ulReturn = ulReturn & 15;
  242. else
  243. ulReturn = ulReturn >> 4;
  244. ASSERTGDI(ulReturn < 16, "ERROR GDI EngCopyBits");
  245. break;
  246. case BMF_8BPP:
  247. ulReturn = (ULONG) *(pjBits + pptlSrc->x);
  248. break;
  249. case BMF_16BPP:
  250. ulReturn = (ULONG) *((PUSHORT) (pjBits + (pptlSrc->x << 1)));
  251. break;
  252. case BMF_24BPP:
  253. pjBits += (pptlSrc->x * 3);
  254. ulReturn = (ULONG) *(pjBits + 2);
  255. ulReturn <<= 8;
  256. ulReturn |= ((ULONG) *(pjBits + 1));
  257. ulReturn <<= 8;
  258. ulReturn |= ((ULONG) *pjBits);
  259. break;
  260. case BMF_32BPP:
  261. ulReturn = *((PULONG) (pjBits + (pptlSrc->x << 2)));
  262. break;
  263. default:
  264. RIP("ERROR GDI EngCopyBits1");
  265. }
  266. return(ulReturn);
  267. }
  268. #endif
  269. /******************************Public*Routine******************************\
  270. * GreGetPixel
  271. *
  272. * API entry point for getting a single pixel on the screen.
  273. *
  274. * Returns: -1 if point not in clip rgn or for blt failure,
  275. * the RGB color put on the device surface for success.
  276. *
  277. * History:
  278. * Tue 17-May-1994 -by- Patrick Haluptzok [patrickh]
  279. * update for size/perf and bug fix.
  280. *
  281. * Thu 27-Feb-1992 -by- Patrick Haluptzok [patrickh]
  282. * Fix RGB return, remove unnecesary work.
  283. *
  284. * 22-Apr-1991 -by- Patrick Haluptzok patrickh
  285. * Wrote it.
  286. \**************************************************************************/
  287. DWORD NtGdiGetPixel(HDC hdc, int x, int y)
  288. {
  289. //
  290. // Lock the destination and its transform.
  291. //
  292. DWORD iSolidColor = 0xFFFFFFFF;
  293. XDCOBJ dcoSrc(hdc);
  294. if (dcoSrc.bValid())
  295. {
  296. //
  297. // Lock the Rao region if we are drawing on a display surface. The Rao
  298. // region might otherwise change asynchronously. The DEVLOCKOBJ also makes
  299. // sure that the VisRgn is up to date, calling the window manager if
  300. // necessary to recompute it. It also protects us from pSurfSrc
  301. // being changed asynchronously by a dynamic mode change.
  302. //
  303. DEVLOCKOBJ dlo;
  304. if (dlo.bLock(dcoSrc))
  305. {
  306. //
  307. // Check we can really do a GetPixel on this device.
  308. //
  309. SURFACE *pSurfSrc = dcoSrc.pSurface();
  310. if ((pSurfSrc != NULL) &&
  311. (pSurfSrc->bReadable() || UserScreenAccessCheck()))
  312. {
  313. EXFORMOBJ xoSrc(dcoSrc, WORLD_TO_DEVICE);
  314. //
  315. // Transform the coordinates to device space.
  316. //
  317. EPOINTL eptlSrc(x,y);
  318. xoSrc.bXform(eptlSrc);
  319. ERECTL erclSrc(eptlSrc.x,eptlSrc.y,eptlSrc.x+1,eptlSrc.y+1);
  320. //
  321. // Shift to Sreen Coordinates
  322. //
  323. erclSrc += dcoSrc.eptlOrigin();
  324. //
  325. // Parameter validation not necessary here. It seems
  326. // that if the +1 above wraps, the initialization of the
  327. // clip obj will catch it in this case.
  328. //
  329. //
  330. // Compute the clipping complexity and maybe reduce the exclusion rectangle.
  331. //
  332. ECLIPOBJ co(dcoSrc.prgnEffRao(), erclSrc);
  333. //
  334. // Check the destination which is reduced by clipping.
  335. //
  336. if (!co.erclExclude().bEmpty())
  337. {
  338. //
  339. // Exclude the pointer.
  340. //
  341. DEVEXCLUDEOBJ dxo(dcoSrc,&erclSrc);
  342. //
  343. // Check target device color.
  344. //
  345. BOOL bCMYKColor = dcoSrc.pdc->bIsCMYKColor();
  346. #if 0
  347. if (pSurfSrc->iType() == STYPE_BITMAP)
  348. {
  349. // We have a special function to quick get it.
  350. iSolidColor = EngGetPixel(
  351. pSurfSrc, // Source surface.
  352. (POINTL *) &erclSrc // Source origin.
  353. );
  354. if (!bCMYKColor)
  355. {
  356. iSolidColor = ulIndexToRGB(palSurf, palDC, iSolidColor);
  357. }
  358. }
  359. else
  360. #endif
  361. {
  362. iSolidColor = 0;
  363. //
  364. // Allocate up a temporary DIB.
  365. //
  366. DEVBITMAPINFO dbmi;
  367. dbmi.cxBitmap = 1;
  368. dbmi.cyBitmap = 1;
  369. dbmi.hpal = (HPALETTE) 0;
  370. dbmi.fl = BMF_TOPDOWN;
  371. RECTL rclDst;
  372. //
  373. // To make sure the color falls into the lower
  374. // bit/nibble/word, the destination rect is adjusted.
  375. //
  376. dbmi.iFormat = pSurfSrc->iFormat();
  377. switch (dbmi.iFormat)
  378. {
  379. case BMF_1BPP:
  380. rclDst.left = 7;
  381. rclDst.right = 8;
  382. break;
  383. case BMF_4BPP:
  384. rclDst.left = 1;
  385. rclDst.right = 2;
  386. break;
  387. default:
  388. rclDst.left = 0;
  389. rclDst.right = 1;
  390. }
  391. SURFMEM SurfTempDIB;
  392. if (SurfTempDIB.bCreateDIB(&dbmi, &iSolidColor))
  393. {
  394. rclDst.top = 0;
  395. rclDst.bottom = 1;
  396. PDEVOBJ pdo(pSurfSrc->hdev());
  397. if ((*PPFNGET(pdo, CopyBits, pSurfSrc->flags()))
  398. (SurfTempDIB.pSurfobj(),
  399. pSurfSrc->pSurfobj(),
  400. (CLIPOBJ *) NULL,
  401. &xloIdent,
  402. &rclDst,
  403. (POINTL *) &erclSrc))
  404. {
  405. if (!bCMYKColor)
  406. {
  407. XEPALOBJ palDC(dcoSrc.ppal());
  408. XEPALOBJ palSurf(pSurfSrc->ppal());
  409. iSolidColor = ulIndexToRGB(palSurf, palDC, iSolidColor);
  410. }
  411. }
  412. }
  413. }
  414. }
  415. }
  416. }
  417. dcoSrc.vUnlockFast();
  418. }
  419. return(iSolidColor);
  420. }