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.

578 lines
18 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: engbrush.cxx
  3. *
  4. * Brush realization for the engine.
  5. *
  6. * Created: 13-May-1991 23:25:49
  7. * Author: Patrick Haluptzok patrickh
  8. *
  9. * Copyright (c) 1990-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. #if DBG
  13. ULONG engbrushalloc = 0, engbrushcachecheck = 0;
  14. ULONG engbrushcachegrabbed = 0, engbrushcachehit = 0;
  15. #endif
  16. /******************************Public*Routine******************************\
  17. * EngRealizeBrush
  18. *
  19. * Realizes a brush for the engine simulations.
  20. *
  21. * We realize a brush by converting psoPattern to have the same bpp and color
  22. * format as the destination surface. We copy the monochrome mask unmodified.
  23. *
  24. * psoPattern is assumed never to be NULL.
  25. *
  26. * Returns: TRUE for success, FALSE for failure.
  27. *
  28. * History:
  29. * 21-Nov-1993 -by- Michael Abrash [mikeab]
  30. * Removed impossible case of psoPattern == NULL, cleaned up.
  31. *
  32. * 20-Jan-1992 -by- Donald Sidoroff [donalds]
  33. * Tiled pattern and mask to DWORD boundaries
  34. *
  35. * 25-Apr-1991 -by- Patrick Haluptzok patrickh
  36. * Wrote it.
  37. \**************************************************************************/
  38. BOOL EngRealizeBrush(
  39. BRUSHOBJ *pbo,
  40. SURFOBJ *psoTarget,
  41. SURFOBJ *psoPattern,
  42. SURFOBJ *psoMask,
  43. XLATEOBJ *pxlo,
  44. ULONG iHatch)
  45. {
  46. PSURFACE pSurfTarg = SURFOBJ_TO_SURFACE(psoTarget);
  47. PSURFACE pSurfPat = SURFOBJ_TO_SURFACE(psoPattern);
  48. PSURFACE pSurfMsk = SURFOBJ_TO_SURFACE(psoMask);
  49. ULONG ulSizeTotal;
  50. ULONG ulSizePat;
  51. ULONG cjScanPat, cjScanMsk;
  52. SIZEL sizlPat;
  53. SIZEL sizlMsk;
  54. LONG cxPatRealized;
  55. LONG cxMskRealized;
  56. ULONG iFormat;
  57. POINTL ptlSrc;
  58. RECTL rclDst;
  59. DEVBITMAPINFO dbmi;
  60. BOOL bHalftoneTile = FALSE;
  61. ASSERTGDI(pbo->iSolidColor == 0xFFFFFFFF, "ERROR GDI iSolidColor");
  62. ASSERTGDI(pSurfTarg != NULL, "ERROR GDI EngRealizeBrush NULL psoTarg");
  63. ASSERTGDI(pSurfPat != NULL, "ERROR GDI EngRealizeBrush NULL psoPattern");
  64. ASSERTGDI(!(iHatch & RB_DITHERCOLOR),
  65. "ERROR GDI EngRealizeBrush RB_DITHERCOLOR set");
  66. //
  67. // Calculate the space needed for the pattern.
  68. //
  69. iFormat = pSurfTarg->iFormat();
  70. //
  71. // Check if they are having the engine simulate to a bitmap compatible
  72. // with their surface. The brushobj has the device's surfobj in it
  73. // but we assume if they got here it's because they created a bitmap
  74. // compatible with thier format and
  75. // are drawing on it. Maybe we should have the pvGetEngBrush pass
  76. // the pSurfTarg along so we know what it is here, because from
  77. // here we haven't got access to the real surfobj being painted on.
  78. //
  79. ASSERTGDI(pSurfPat->iType() == STYPE_BITMAP, "ERROR GDI EngRealizeBrush2");
  80. sizlPat = pSurfPat->sizl();
  81. PDEVICEHALFTONEINFO pDevHTInfo = NULL;
  82. PDEVOBJ po(pSurfTarg->hdev());
  83. // The following list shows the halftone dithering cell size mapped to
  84. // cxPattern x cyPattern in pDevHTInfo
  85. //
  86. // This is done only for 1bpp in the following code
  87. //
  88. // dither cell chosen at UI --> what we got from pDevHTInfo
  89. //
  90. // 2x2 --> 8x4
  91. // 4x4 --> 8x4
  92. // 6x6 --> 12x6
  93. // 8x8 --> 8x8
  94. // 10x10 --> 10x10
  95. // 12x12 --> 12x12
  96. // 14x14 --> 14x14
  97. // 16x16 --> 16x16
  98. // 91x91 --> 91x91
  99. //
  100. if ((po.pDevHTInfo() != NULL) || po.bEnableHalftone(NULL))
  101. {
  102. pDevHTInfo = (DEVICEHALFTONEINFO *)po.pDevHTInfo();
  103. }
  104. switch(iFormat)
  105. {
  106. case BMF_1BPP:
  107. ulSizePat = 1;
  108. if ((sizlPat.cx == 32) ||
  109. (sizlPat.cx == 16) ||
  110. (sizlPat.cx == 8))
  111. {
  112. cxPatRealized = 32;
  113. //
  114. // take the least common multiple
  115. // of 32(dword aligned) and pDevHTInfocxPattern
  116. //
  117. if (pDevHTInfo)
  118. {
  119. switch (pDevHTInfo->cxPattern)
  120. {
  121. case 12:
  122. cxPatRealized = 96;
  123. bHalftoneTile = TRUE;
  124. break;
  125. case 10:
  126. cxPatRealized = 160;
  127. bHalftoneTile = TRUE;
  128. break;
  129. case 14:
  130. cxPatRealized = 224;
  131. bHalftoneTile = TRUE;
  132. break;
  133. case 91:
  134. break;
  135. default:
  136. break;
  137. }
  138. }
  139. }
  140. else
  141. {
  142. cxPatRealized = (sizlPat.cx + 63) & ~31;
  143. }
  144. break;
  145. case BMF_4BPP:
  146. ulSizePat = 4;
  147. if (sizlPat.cx == 8)
  148. {
  149. cxPatRealized = 8;
  150. }
  151. else
  152. {
  153. cxPatRealized = (sizlPat.cx + 15) & ~7;
  154. }
  155. break;
  156. case BMF_8BPP:
  157. ulSizePat = 8;
  158. cxPatRealized = (sizlPat.cx + 7) & ~3;
  159. break;
  160. case BMF_16BPP:
  161. ulSizePat = 16;
  162. cxPatRealized = (sizlPat.cx + 7) & ~3;
  163. break;
  164. case BMF_24BPP:
  165. ulSizePat = 24;
  166. cxPatRealized = (sizlPat.cx + 7) & ~3;
  167. break;
  168. case BMF_32BPP:
  169. ulSizePat = 32;
  170. cxPatRealized = sizlPat.cx;
  171. break;
  172. default:
  173. RIP("ERROR GDI EngRealizeBrush3");
  174. }
  175. //
  176. // Calculate the size to hold the pattern in the Target's format.
  177. //
  178. cjScanPat = (ulSizePat * cxPatRealized) >> 3;
  179. ulSizeTotal = sizeof(ENGBRUSH) + (ulSizePat = sizlPat.cy * cjScanPat);
  180. //
  181. // Calculate the additional space needed if we have a mask passed down.
  182. //
  183. if (pSurfMsk != NULL)
  184. {
  185. ASSERTGDI(pSurfMsk->iFormat() == BMF_1BPP, "ERROR GDI EngRealizeBrush4");
  186. ASSERTGDI(pSurfMsk->iType() == STYPE_BITMAP, "ERROR GDI EngRealizeBrush5");
  187. sizlMsk = pSurfMsk->sizl();
  188. if ((sizlMsk.cx == 32) ||
  189. (sizlMsk.cx == 16) ||
  190. (sizlMsk.cx == 8))
  191. {
  192. cxMskRealized = 32;
  193. }
  194. else
  195. {
  196. cxMskRealized = (sizlMsk.cx + 63) & ~31;
  197. }
  198. cjScanMsk = cxMskRealized >> 3;
  199. ulSizeTotal += sizlMsk.cy * cjScanMsk;
  200. }
  201. //
  202. // Allocate memory for the realization.
  203. //
  204. PENGBRUSH pengbrush;
  205. #if DBG
  206. engbrushalloc++;
  207. #endif
  208. //
  209. // If there's a cached ENGBRUSH, try to use it instead of allocating
  210. //
  211. if (gpCachedEngbrush != NULL)
  212. {
  213. #if DBG
  214. engbrushcachecheck++;
  215. #endif
  216. //
  217. // Try to grab the cached ENGBRUSH
  218. //
  219. if ((pengbrush =
  220. (PENGBRUSH) InterlockedExchangePointer((PVOID *)&gpCachedEngbrush,
  221. NULL))
  222. != NULL)
  223. {
  224. #if DBG
  225. engbrushcachegrabbed++;
  226. #endif
  227. //
  228. // Got the cached ENGBRUSH; see if it's big enough
  229. //
  230. // Note: -4 because we define the realization buffer start as aj[0]
  231. if (pengbrush->ulSizeGet() >= (sizeof(ENGBRUSH) - 4 + ulSizeTotal))
  232. {
  233. #if DBG
  234. engbrushcachehit++;
  235. #endif
  236. //
  237. // It's big enough, so we'll use it and we're done
  238. //
  239. goto BrushAllocated;
  240. }
  241. else
  242. {
  243. //
  244. // Not big enough; free it and do a normal allocation
  245. //
  246. VFREEMEM(pengbrush);
  247. }
  248. }
  249. }
  250. // Note: -4 because we define the realization buffer start as aj[0]
  251. if ((pengbrush = (PENGBRUSH)
  252. PALLOCMEM(ULONG(sizeof(ENGBRUSH) - 4 + ulSizeTotal),'rbeG'))
  253. == NULL)
  254. {
  255. WARNING("GDI EngRealizeBrush Couldn't allocate for engine realization");
  256. return(FALSE);
  257. }
  258. BrushAllocated:
  259. EBRUSHOBJ *pebo = (EBRUSHOBJ *) pbo;
  260. //
  261. // Store the pointer to the realization in the brush.
  262. //
  263. pebo->pengbrush(pengbrush);
  264. //
  265. // Remember the size of the allocation, for caching.
  266. //
  267. pengbrush->ulSizeSet(sizeof(ENGBRUSH) - 4 + ulSizeTotal);
  268. //
  269. // Set up the Pat part. The pattern can never be NULL.
  270. //
  271. pengbrush->lDeltaPat = cjScanPat;
  272. pengbrush->cxPatR = cxPatRealized;
  273. pengbrush->cxPat = bHalftoneTile ? cxPatRealized : sizlPat.cx;
  274. pengbrush->cyPat = sizlPat.cy;
  275. pengbrush->pjPat = pengbrush->aj;
  276. pengbrush->iDitherFormat = iFormat;
  277. dbmi.iFormat = iFormat;
  278. dbmi.cxBitmap = cxPatRealized;
  279. dbmi.cyBitmap = sizlPat.cy;
  280. dbmi.hpal = 0;
  281. dbmi.fl = BMF_TOPDOWN;
  282. SURFMEM SurfDimo;
  283. SurfDimo.bCreateDIB(&dbmi, pengbrush->pjPat);
  284. if (!SurfDimo.bValid())
  285. {
  286. // hmgr logs out of memory error
  287. return(FALSE);
  288. }
  289. ptlSrc.x = 0;
  290. ptlSrc.y = 0;
  291. rclDst.left = 0;
  292. rclDst.top = 0;
  293. rclDst.right = sizlPat.cx;
  294. rclDst.bottom = sizlPat.cy;
  295. // Below cases, we need halftoning for this brush.
  296. //
  297. // 1) Target surface is 1bpp, and this is pattern/bitmap brush, and the foreground
  298. // and background are differrent
  299. // 2) Target surface is 4bpp, and ICM is enabled in system or apps, and this is NOT
  300. // monochrone brush with same fore and background color.
  301. BOOL bSameColor = (((EBRUSHOBJ *)pbo)->crCurrentText() == ((EBRUSHOBJ *)pbo)->crCurrentBack());
  302. if (((iFormat == BMF_1BPP) && (iHatch >= HS_NULL) && !bSameColor) // 1
  303. ||
  304. ((iFormat == BMF_4BPP) && (pebo->bIsAppsICM() || pebo->bIsHostICM()) // 2
  305. && !(bSameColor && (pebo->bIsMonochrome())))
  306. )
  307. {
  308. PALMEMOBJ palHatch;
  309. EXLATEOBJ exloHatch;
  310. PALETTE *ppalOrg = NULL;
  311. // Special case to go thru halftone code
  312. POINTL ptl;
  313. ptl.x = 0; ptl.y = 0;
  314. RECTL rclSrc;
  315. rclSrc = rclDst;
  316. SurfDimo.ps->hdev(pSurfTarg->hdev());
  317. BOOL bHatch = (iHatch < HS_DDI_MAX);
  318. // If this is Hatch or monochrome brush, and ICM is enabled, ...
  319. if ((bHatch || pebo->bIsMonochrome()) &&
  320. (pebo->bIsAppsICM() || pebo->bIsHostICM()))
  321. {
  322. // Create temporary palette for hatch/mono brush from back/foregournd color
  323. // This is nessesary to let halftone bitblt work correctly.
  324. COLORREF aPalHatch[2];
  325. // If this is hatch brush, get foreground color from crRealized.
  326. // For monochrome brush, get from current text color.
  327. if (bHatch)
  328. {
  329. ICMMSG(("EngRealizeBrush called with hatch brush\n"));
  330. ICMMSG(("Forground color = %x\n", pebo->crRealized()));
  331. ICMMSG(("Background color = %x\n", pebo->crCurrentBack()));
  332. // crCurrentBack goes to index 0
  333. // crRealized goes to index 1
  334. //
  335. // See brushddi.cxx : bGetRealizedBrush() for hatch brush case.
  336. aPalHatch[0] = pebo->crCurrentBack();
  337. aPalHatch[1] = pebo->crRealized();
  338. }
  339. else // if (pebo->bIsMonochorme())
  340. {
  341. ICMMSG(("EngRealizeBrush called with monochrome brush\n"));
  342. ICMMSG(("Forground color = %x\n", pebo->crCurrentText()));
  343. ICMMSG(("Background color = %x\n", pebo->crCurrentBack()));
  344. // Text color goes to index 0.
  345. // Background color goes to index 1.
  346. //
  347. // See ylateobj.cxx : CreateXlateObject() when source is monochrome case.
  348. aPalHatch[0] = pebo->crCurrentText();
  349. aPalHatch[1] = pebo->crCurrentBack();
  350. }
  351. if (palHatch.bCreatePalette(PAL_INDEXED, 2, (PULONG) aPalHatch,
  352. 0, 0, 0, PAL_FREE))
  353. {
  354. if (exloHatch.bInitXlateObj(
  355. pebo->hcmXform(),
  356. pebo->lIcmMode(),
  357. palHatch.ppalGet(),
  358. pebo->psoTarg()->ppal(),
  359. pebo->palDC(),
  360. pebo->palDC(),
  361. pebo->crCurrentText(),
  362. pebo->crCurrentBack(),
  363. 0x00FFFFFF))
  364. {
  365. pxlo = exloHatch.pxlo();
  366. //
  367. // Halftone code always pick up palette from surface, if it exist,
  368. // and the palette in monochrome bitmap is black/white, but here,
  369. // text/background color must be used, so disable surface palette
  370. // here by put null, so that halftone code will pick up right palette
  371. // from XLATEOBJ.
  372. //
  373. ppalOrg = pSurfPat->ppal();
  374. pSurfPat->ppal(NULL);
  375. }
  376. else
  377. {
  378. WARNING1("EngRealizeBrush: failed to create xlate for ICM\n");
  379. }
  380. }
  381. else
  382. {
  383. WARNING1("EngRealizeBrush: failed to create palette for ICM\n");
  384. }
  385. }
  386. if ((iFormat == BMF_1BPP) && bHalftoneTile)
  387. {
  388. rclDst.right = cxPatRealized;
  389. EngHTBlt(
  390. SurfDimo.pSurfobj(), // Target surface
  391. pSurfPat->pSurfobj(), // Source surface
  392. NULL, // mask surface
  393. (CLIPOBJ *) NULL, // Clip through this
  394. pxlo, // Color translation
  395. NULL, // pca
  396. &ptl, // pptlBrushOrg
  397. &rclDst,
  398. &rclSrc,
  399. NULL,
  400. BBPF_TILE_SRC,
  401. NULL);
  402. }
  403. else
  404. {
  405. while (rclDst.left != cxPatRealized)
  406. {
  407. EngStretchBlt(
  408. SurfDimo.pSurfobj(), // Target surface
  409. pSurfPat->pSurfobj(), // Source surface
  410. NULL, // mask surface
  411. (CLIPOBJ *) NULL, // Clip through this
  412. pxlo, // Color translation
  413. NULL, // pca
  414. &ptl, // pptlBrushOrg
  415. &rclDst,
  416. &rclSrc,
  417. NULL,
  418. HALFTONE);
  419. rclDst.left = rclDst.right;
  420. rclDst.right += sizlPat.cx;
  421. if (rclDst.right > cxPatRealized)
  422. rclDst.right = cxPatRealized;
  423. }
  424. }
  425. if (ppalOrg)
  426. {
  427. pSurfPat->ppal(ppalOrg);
  428. }
  429. }
  430. else // normal cases
  431. {
  432. while (rclDst.left != cxPatRealized)
  433. {
  434. EngCopyBits(
  435. SurfDimo.pSurfobj(), // Target surface
  436. pSurfPat->pSurfobj(), // Source surface
  437. (CLIPOBJ *) NULL, // Clip through this
  438. pxlo, // Color translation
  439. &rclDst, // Target offset and extent
  440. &ptlSrc);
  441. rclDst.left = rclDst.right;
  442. rclDst.right += sizlPat.cx;
  443. if (rclDst.right > cxPatRealized)
  444. rclDst.right = cxPatRealized;
  445. }
  446. }
  447. //
  448. // Set up the Msk part.
  449. //
  450. if (pSurfMsk == (PSURFACE) NULL)
  451. {
  452. //
  453. // Flag that there's no mask.
  454. //
  455. pengbrush->pjMsk = (PBYTE) NULL;
  456. }
  457. else
  458. {
  459. pengbrush->lDeltaMsk = cjScanMsk;
  460. pengbrush->cxMskR = cxMskRealized;
  461. pengbrush->cxMsk = sizlMsk.cx;
  462. pengbrush->cyMsk = sizlMsk.cy;
  463. pengbrush->pjMsk = pengbrush->aj + ulSizePat;
  464. dbmi.iFormat = BMF_1BPP;
  465. dbmi.cxBitmap = cxMskRealized;
  466. dbmi.cyBitmap = sizlMsk.cy;
  467. dbmi.hpal = (HPALETTE)0;
  468. dbmi.fl = BMF_TOPDOWN;
  469. SURFMEM SurfDimo;
  470. SurfDimo.bCreateDIB(&dbmi, pengbrush->pjMsk);
  471. if (!SurfDimo.bValid())
  472. {
  473. // hmgr logs out of memory error
  474. return(FALSE);
  475. }
  476. ptlSrc.x = 0;
  477. ptlSrc.y = 0;
  478. rclDst.left = 0;
  479. rclDst.top = 0;
  480. rclDst.right = sizlMsk.cx;
  481. rclDst.bottom = sizlMsk.cy;
  482. while (rclDst.left != cxMskRealized)
  483. {
  484. EngCopyBits(
  485. SurfDimo.pSurfobj(), // target surface
  486. pSurfMsk->pSurfobj(), // source surface
  487. (CLIPOBJ *) NULL, // no clipping
  488. NULL, // no color translation
  489. &rclDst, // target offset and extent
  490. &ptlSrc // source start point
  491. );
  492. rclDst.left = rclDst.right;
  493. rclDst.right += sizlMsk.cx;
  494. if (rclDst.right > cxMskRealized)
  495. {
  496. rclDst.right = cxMskRealized;
  497. }
  498. }
  499. }
  500. return(TRUE);
  501. }