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.

1130 lines
29 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: brushapi.cxx *
  3. * *
  4. * Contains all the various GDI versions of Brush creation. *
  5. * *
  6. * Created: 06-Nov-1990 14:46:03 *
  7. * Author: Walt Moore [waltm] *
  8. * *
  9. * Copyright (c) 1990-1999 Microsoft Corporation *
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. #include "engline.hxx"
  13. // Default wide-line style arrays:
  14. ULONG gaulGeometricDot[] = { 1, 1 };
  15. ULONG gaulGeometricDash[] = { 3, 1 };
  16. ULONG gaulGeometricDashDot[] = { 3, 1, 1, 1 };
  17. ULONG gaulGeometricDashDotDot[] = { 3, 1, 1, 1, 1, 1 };
  18. // Default cosmetic style arrays (must all sum to 8):
  19. LONG_FLOAT galeCosmeticDot[] = { {1}, {1}, {1}, {1},
  20. {1}, {1}, {1}, {1} };
  21. LONG_FLOAT galeCosmeticDash[] = { {6}, {2} };
  22. LONG_FLOAT galeCosmeticDashDot[] = { {3}, {2}, {1}, {2} };
  23. LONG_FLOAT galeCosmeticDashDotDot[] = { {3}, {1}, {1}, {1}, {1}, {1} };
  24. /**************************************************************************\
  25. * hCreateSolidBrushInternal(clrr, bPen)
  26. *
  27. * Creates a solid brush. Whether or not the brush is solid or dithered
  28. * will depend on what mode the DC is in at realization time.
  29. *
  30. \**************************************************************************/
  31. HBRUSH
  32. hCreateSolidBrushInternal(
  33. COLORREF clrr,
  34. BOOL bPen,
  35. HBRUSH hbr,
  36. BOOL bSharedMem)
  37. {
  38. HBRUSH hbrReturn = NULL;
  39. if (hbr)
  40. {
  41. //
  42. // If an already created brush is passed, just try to set it.
  43. //
  44. if (GreSetSolidBrushInternal(hbr,clrr,bPen,FALSE))
  45. {
  46. hbrReturn = hbr;
  47. }
  48. }
  49. else
  50. {
  51. BRUSHMEMOBJ brmo(clrr, HS_DITHEREDCLR, bPen, bSharedMem);
  52. if (brmo.bValid())
  53. {
  54. brmo.vKeepIt();
  55. brmo.vEnableDither();
  56. hbrReturn = brmo.hbrush();
  57. }
  58. }
  59. return hbrReturn;
  60. }
  61. /**************************************************************************\
  62. * GreCreateSolidBrush()
  63. *
  64. \**************************************************************************/
  65. HBRUSH
  66. GreCreateSolidBrush(
  67. COLORREF clrr)
  68. {
  69. return(hCreateSolidBrushInternal(clrr,FALSE,NULL,FALSE));
  70. }
  71. /**************************************************************************\
  72. * NtGdiCreateSolidBrush()
  73. *
  74. \**************************************************************************/
  75. HBRUSH
  76. APIENTRY
  77. NtGdiCreateSolidBrush(
  78. COLORREF cr,
  79. HBRUSH hbr
  80. )
  81. {
  82. HBRUSH hbrush;
  83. hbrush = hCreateSolidBrushInternal(cr, FALSE, hbr, TRUE);
  84. return (hbrush);
  85. }
  86. /**************************************************************************\
  87. * hCreateHatchBrushInternal(ulStyle, clrr, bPen)
  88. *
  89. * Creates a hatch brush.
  90. *
  91. * History:
  92. * 07-Jun-1995 -by- Andre Vachon [andreva]
  93. * Wrote it.
  94. \**************************************************************************/
  95. HBRUSH
  96. hCreateHatchBrushInternal(
  97. ULONG ulStyle,
  98. COLORREF clrr,
  99. BOOL bPen)
  100. {
  101. HBRUSH hbr = NULL;
  102. if (ulStyle <= HS_API_MAX-1)
  103. {
  104. BRUSHMEMOBJ brmo(clrr, ulStyle, bPen, FALSE);
  105. if (brmo.bValid())
  106. {
  107. brmo.vKeepIt();
  108. hbr = brmo.hbrush();
  109. }
  110. }
  111. return hbr;
  112. }
  113. /**************************************************************************\
  114. * NtGdiCreateHatchBrushInternal(ulStyle, clrr, bPen)
  115. *
  116. \**************************************************************************/
  117. HBRUSH
  118. APIENTRY
  119. NtGdiCreateHatchBrushInternal(
  120. ULONG ulStyle,
  121. COLORREF cr,
  122. BOOL bPen
  123. )
  124. {
  125. HBRUSH hbrush;
  126. hbrush = hCreateHatchBrushInternal (ulStyle, cr, bPen);
  127. return (hbrush);
  128. }
  129. /******************************Public*Routine******************************\
  130. * NtGdiCreatePatternBrushInternal()
  131. *
  132. * History:
  133. * 01-Nov-1994 -by- Eric Kutter [erick]
  134. * Wrote it.
  135. \**************************************************************************/
  136. HBRUSH
  137. APIENTRY
  138. NtGdiCreatePatternBrushInternal(
  139. HBITMAP hbm,
  140. BOOL bPen,
  141. BOOL b8X8
  142. )
  143. {
  144. HBRUSH hbrush;
  145. hbrush = GreCreatePatternBrushInternal(hbm,bPen,b8X8);
  146. return (hbrush);
  147. }
  148. /******************************Public*Routine******************************\
  149. * NtGdiCreateDIBBrush()
  150. *
  151. * History:
  152. * 01-Nov-1994 -by- Eric Kutter [erick]
  153. * Wrote it.
  154. \**************************************************************************/
  155. HBRUSH
  156. APIENTRY
  157. NtGdiCreateDIBBrush(
  158. PVOID pv,
  159. FLONG fl,
  160. UINT cj,
  161. BOOL b8X8,
  162. BOOL bPen,
  163. PVOID pClient
  164. )
  165. {
  166. HBRUSH hbrRet;
  167. PVOID pvTmp;
  168. pvTmp = AllocFreeTmpBuffer(cj);
  169. if (pvTmp)
  170. {
  171. hbrRet = (HBRUSH)1;
  172. __try
  173. {
  174. ProbeForRead(pv,cj, sizeof(BYTE));
  175. RtlCopyMemory(pvTmp,pv,cj);
  176. }
  177. __except(EXCEPTION_EXECUTE_HANDLER)
  178. {
  179. // SetLastError(GetExceptionCode());
  180. hbrRet = (HBRUSH)0;
  181. }
  182. if (hbrRet)
  183. {
  184. hbrRet = GreCreateDIBBrush(pvTmp,fl,cj,b8X8,bPen,pClient);
  185. }
  186. FreeTmpBuffer(pvTmp);
  187. }
  188. else
  189. {
  190. // SetLastError();
  191. hbrRet = (HBRUSH)0;
  192. }
  193. return(hbrRet);
  194. }
  195. /**************************************************************************\
  196. * GreCreatePatternBrushInternal(hbm, bPen)
  197. *
  198. * Creates a pattern brush from the bitmap passed in.
  199. *
  200. * History:
  201. * Mon 24-Jun-1991 -by- Patrick Haluptzok [patrickh]
  202. * Wrote it.
  203. \**************************************************************************/
  204. HBRUSH GreCreatePatternBrushInternal(
  205. HBITMAP hbm,
  206. BOOL bPen,
  207. BOOL b8X8)
  208. {
  209. HBRUSH hbrReturn = (HBRUSH) 0;
  210. SURFREF SurfBmo((HSURF)hbm);
  211. if (SurfBmo.bValid())
  212. {
  213. if (SurfBmo.ps->bApiBitmap())
  214. {
  215. HBITMAP hbmClone;
  216. if (b8X8)
  217. hbmClone = hbmCreateClone(SurfBmo.ps,8,8);
  218. else
  219. hbmClone = hbmCreateClone(SurfBmo.ps,0,0);
  220. if (hbmClone != (HBITMAP) 0)
  221. {
  222. XEPALOBJ pal(SurfBmo.ps->ppal());
  223. BRUSHMEMOBJ brmo(hbmClone, hbm, pal.bIsMonochrome(), DIB_RGB_COLORS,
  224. BR_IS_BITMAP, bPen);
  225. if (brmo.bValid())
  226. {
  227. hbrReturn = brmo.hbrush();
  228. brmo.vKeepIt();
  229. } // hmgr logs error code
  230. } // hmgr logs error code
  231. }
  232. else
  233. {
  234. WARNING("GreCreatePatternBrushInternal: Invalid surface");
  235. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  236. }
  237. }
  238. else
  239. {
  240. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  241. }
  242. return(hbrReturn);
  243. }
  244. HBRUSH GreCreatePatternBrush(HBITMAP hbm)
  245. {
  246. return(GreCreatePatternBrushInternal(hbm,FALSE,FALSE));
  247. }
  248. /******************************Public*Routine******************************\
  249. * GreCreateDIBBrush
  250. *
  251. * Creates a DIB pattern brush.
  252. *
  253. * History:
  254. * 02-Jun-1991 -by- Patrick Haluptzok patrickh
  255. * Wrote it.
  256. \**************************************************************************/
  257. HBRUSH
  258. GreCreateDIBBrush(PVOID pv, FLONG fl, UINT cjMax, BOOL b8X8, BOOL bPen, PVOID pClient)
  259. {
  260. // Validate your parameters.
  261. if ((pv == (PVOID) 0) ||
  262. (cjMax < sizeof(BITMAPINFOHEADER)) ||
  263. (((BITMAPINFOHEADER *) pv)->biSize > cjMax) ||
  264. ((fl != DIB_PAL_INDICES) &&
  265. (fl != DIB_PAL_COLORS) &&
  266. (fl != DIB_RGB_COLORS)))
  267. {
  268. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  269. return((HBRUSH) 0);
  270. }
  271. // Compute offset to the bits
  272. UINT cjHeader = ((BITMAPINFOHEADER *) pv)->biSize;
  273. PBYTE pjBits = ((PBYTE) pv) + cjHeader;
  274. PUSHORT pusIndices;
  275. UINT uiBits,cSize,uiCompression;
  276. UINT cPalEntriesTotal;
  277. LPBITMAPINFO pbmiTmp = NULL;
  278. UINT cPalEntryMax;
  279. uiBits = ((BITMAPINFOHEADER *) pv)->biBitCount;
  280. pusIndices = (PUSHORT) pjBits;
  281. cSize = sizeof(RGBQUAD);
  282. cPalEntriesTotal = (UINT) ((BITMAPINFOHEADER *) pv)->biClrUsed;
  283. uiCompression = ((BITMAPINFOHEADER *) pv)->biCompression;
  284. // Check proper settings for compression.
  285. if (uiCompression == BI_BITFIELDS)
  286. {
  287. cPalEntriesTotal = 3;
  288. if (fl == DIB_PAL_COLORS)
  289. fl = DIB_RGB_COLORS;
  290. if ((uiBits != 16) && (uiBits != 32))
  291. {
  292. WARNING("CreateDIBPatternBrush given invalid data for BI_BITFIELDS\n");
  293. return((HBRUSH) 0);
  294. }
  295. }
  296. else if (uiCompression == BI_RGB)
  297. {
  298. switch(uiBits)
  299. {
  300. case 1:
  301. cPalEntryMax = 2;
  302. break;
  303. case 4:
  304. cPalEntryMax = 16;
  305. break;
  306. case 8:
  307. cPalEntryMax = 256;
  308. break;
  309. case 16:
  310. case 24:
  311. case 32:
  312. cPalEntryMax =
  313. cPalEntriesTotal = 0;
  314. // Win3.1 ignores the DIB_PAL_COLORS flag when non-indexed passed in.
  315. if (fl == DIB_PAL_COLORS)
  316. fl = DIB_RGB_COLORS;
  317. break;
  318. default:
  319. WARNING("GreCreateDIBPatternBrushPt failed because of invalid bit count BI_RGB");
  320. return((HBRUSH) 0);
  321. }
  322. if (cPalEntriesTotal == 0)
  323. {
  324. cPalEntriesTotal = cPalEntryMax;
  325. }
  326. else
  327. cPalEntriesTotal = MIN(cPalEntryMax, cPalEntriesTotal);
  328. }
  329. else if (uiCompression == BI_RLE4)
  330. {
  331. if (uiBits != 4)
  332. {
  333. WARNING("CreateDIBrush RLE4 invalid bpp\n");
  334. return((HBRUSH) 0);
  335. }
  336. if (cPalEntriesTotal == 0)
  337. {
  338. cPalEntriesTotal = 16;
  339. }
  340. }
  341. else if (uiCompression == BI_RLE8)
  342. {
  343. if (uiBits != 8)
  344. {
  345. WARNING("CreateDIBrush RLE8 invalid bpp\n");
  346. return((HBRUSH) 0);
  347. }
  348. if (cPalEntriesTotal == 0)
  349. {
  350. cPalEntriesTotal = 256;
  351. }
  352. }
  353. else
  354. {
  355. // We don't support any other compressions for creating a brush on NT.
  356. WARNING("Unknown Compression passed in - failed CreateDIBPatternBrush\n");
  357. return((HBRUSH) 0);
  358. }
  359. // Check for the DIB_PAL_COLORS case.
  360. if (fl == DIB_PAL_COLORS)
  361. cSize = sizeof(USHORT);
  362. else if (fl == DIB_PAL_INDICES)
  363. cSize = 0;
  364. // Validate that buffer is large enough to include color table. Guarantees
  365. // that pjBits is within the bounds of the pv buffer passed in.
  366. UINT cjColorTable = (((cSize * cPalEntriesTotal) + 3) & ~3);
  367. if (cjColorTable > (cjMax - cjHeader))
  368. {
  369. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  370. return(0);
  371. }
  372. pjBits += cjColorTable; // now, pjBits = pv + cjHeader + cjColorTable
  373. //
  374. // Sundown: safe to truncate to INT since pjBits - pv will not exceed 4GB
  375. // (validation above ensures that difference is <= cjMax)
  376. //
  377. INT cjBits = cjMax - (INT)(pjBits - (PBYTE)pv);
  378. // Store the handle to bitmap just like a pattern brush, only mark
  379. // it as a DIB.
  380. HBITMAP hbmDIB;
  381. FLONG flCreate = DIB_RGB_COLORS;
  382. if (fl != DIB_RGB_COLORS)
  383. {
  384. flCreate = DIB_PAL_NONE;
  385. }
  386. hbmDIB = GreCreateDIBitmapReal(
  387. (HDC) 0,
  388. CBM_INIT | CBM_CREATEDIB,
  389. pjBits,
  390. (BITMAPINFO *)pv,
  391. flCreate,
  392. cjMax,
  393. cjBits,
  394. NULL,
  395. 0,
  396. NULL,
  397. CDBI_INTERNAL,
  398. 0,
  399. NULL);
  400. if (hbmDIB == (HBITMAP) 0)
  401. {
  402. WARNING("GreCreateDIBPatternBrush failed because GreCreateDIBitmap failed");
  403. return((HBRUSH) 0);
  404. }
  405. if (b8X8)
  406. {
  407. SURFREF so((HSURF)hbmDIB);
  408. ASSERTGDI(so.bValid(), "ERROR just created and already dead");
  409. SIZEL sizlNew = so.ps->sizl();
  410. if (so.ps->sizl().cx > 8)
  411. {
  412. sizlNew.cx = 8;
  413. }
  414. if (so.ps->sizl().cy > 8)
  415. {
  416. sizlNew.cy = 8;
  417. }
  418. so.ps->sizl(sizlNew);
  419. }
  420. // Now if we are creating a DIB_PAL_COLORS DIB brush we need to save the
  421. // indices in the palette, so at runtime we can do the right thing.
  422. if (fl == DIB_PAL_COLORS)
  423. {
  424. SURFREF so((HSURF)hbmDIB);
  425. ASSERTGDI(so.bValid(), "ERROR GreCreateDIBBrush surface\n");
  426. XEPALOBJ pal(so.ps->ppal());
  427. pal.flPal(PAL_BRUSHHACK);
  428. ASSERTGDI(pal.bValid(), "ERROR GreCreateDIBBrush pal.bValid\n");
  429. ASSERTGDI(!pal.bIsPalDefault(), "ERROR GreCreateDIBBrush pal.bIsPal\n");
  430. RtlCopyMemory((PUSHORT) pal.apalColorGet(), pusIndices,
  431. cPalEntriesTotal << 1);
  432. // Remember how big the color table is
  433. pal.cColorTableLength(cPalEntriesTotal);
  434. }
  435. BRUSHMEMOBJ brmo(hbmDIB, (HBITMAP)pClient, FALSE, fl, BR_IS_DIB, bPen);
  436. HBRUSH hbrRet;
  437. if (brmo.bValid())
  438. {
  439. brmo.vKeepIt();
  440. brmo.iUsage(fl);
  441. hbrRet = brmo.hbrush();
  442. }
  443. else
  444. {
  445. bDeleteSurface((HSURF)hbmDIB);
  446. hbrRet = (HBRUSH) 0;
  447. }
  448. return(hbrRet);
  449. }
  450. /******************************Public*Routine******************************\
  451. * GreMarkUndeletableBrush
  452. *
  453. * Private API for USER.
  454. *
  455. * Mark a Brush as undeletable. This must be called before the Brush is ever
  456. * passed out to an application.
  457. *
  458. * History:
  459. * 13-Sep-1991 -by- Patrick Haluptzok patrickh
  460. * Wrote it.
  461. \**************************************************************************/
  462. VOID GreMarkUndeletableBrush(HBRUSH hbr)
  463. {
  464. if(hbr == NULL)
  465. {
  466. WARNING("GreMarkUndeletableBrush called with NULL handle");
  467. }
  468. else if(!HmgMarkUndeletable((HOBJ)hbr, BRUSH_TYPE))
  469. {
  470. RIP("GreMarkUndeletableBrush failed to mark handle undeletable");
  471. }
  472. }
  473. /******************************Public*Routine******************************\
  474. * GreMarkDeletableBrush
  475. *
  476. * Private API for USER.
  477. *
  478. * This can be called anytime by USER to make the Brush deletable. We need
  479. * to check they don't do this on our global objects.
  480. *
  481. * History:
  482. * 13-Sep-1991 -by- Patrick Haluptzok patrickh
  483. * Wrote it.
  484. \**************************************************************************/
  485. VOID GreMarkDeletableBrush(HBRUSH hbr)
  486. {
  487. BRUSHSELOBJ bro(hbr);
  488. if (bro.bValid())
  489. {
  490. if(!bro.bIsGlobal())
  491. {
  492. if (hbr == NULL)
  493. {
  494. WARNING("GreMarkDeletableBrush called with NULL handle");
  495. }
  496. else if (!HmgMarkDeletable((HOBJ)hbr,BRUSH_TYPE))
  497. {
  498. RIP("GreMarkDeletableBrush failed to mark handle deletable");
  499. }
  500. }
  501. }
  502. else
  503. {
  504. WARNING("ERROR User gives Gdi invalid Brush");
  505. }
  506. }
  507. /******************************Public*Routine******************************\
  508. * GreCreatePen
  509. *
  510. * API creates a logical pen.
  511. *
  512. * History:
  513. * 08-May-1991 -by- Patrick Haluptzok patrickh
  514. * Wrote it.
  515. \**************************************************************************/
  516. HPEN GreCreatePen(int iPenStyle, int ulWidth, COLORREF clrr, HBRUSH hbr)
  517. {
  518. HPEN hRet = 0;
  519. PW32THREAD pthread = W32GetCurrentThread();
  520. ASSERTGDI(!hbr,"GreCreatePen - hbr\n");
  521. switch(iPenStyle)
  522. {
  523. case PS_NULL:
  524. case PS_SOLID:
  525. case PS_DASH:
  526. case PS_DOT:
  527. case PS_DASHDOT:
  528. case PS_DASHDOTDOT:
  529. case PS_INSIDEFRAME:
  530. break;
  531. default:
  532. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  533. return((HPEN) 0);
  534. }
  535. hRet = GreExtCreatePen(iPenStyle,
  536. ulWidth,
  537. BS_SOLID,
  538. clrr,
  539. 0,
  540. 0,
  541. 0,
  542. (PULONG) NULL,
  543. 0,
  544. TRUE,
  545. hbr);
  546. return (hRet);
  547. }
  548. /******************************Public*Routine******************************\
  549. * GreExtCreatePen
  550. *
  551. * API creates an old-style or extended logical pen.
  552. *
  553. * History:
  554. * 23-Jan-1992 -by- J. Andrew Goossen [andrewgo]
  555. * Wrote it.
  556. \**************************************************************************/
  557. HPEN GreExtCreatePen(
  558. ULONG flPenStyle,
  559. ULONG ulWidth,
  560. ULONG iBrushStyle,
  561. ULONG ulColor,
  562. ULONG_PTR lClientHatch,
  563. ULONG_PTR lHatch,
  564. ULONG cstyle,
  565. PULONG pulStyle,
  566. ULONG cjDIB,
  567. BOOL bOldStylePen,
  568. HBRUSH hbrush)
  569. {
  570. BOOL bInvalidParm = FALSE;
  571. BOOL bDefaultStyle = FALSE;
  572. PFLOAT_LONG pstyle = (PFLOAT_LONG) NULL;
  573. ULONG iType = flPenStyle & PS_TYPE_MASK;
  574. ULONG ulStyle = flPenStyle & PS_STYLE_MASK;
  575. ULONG iJoin;
  576. ULONG iEndCap;
  577. // We take the absoluate value of the integer width, like Win3 does:
  578. LONG lWidthPen = ABS((LONG) ulWidth);
  579. // Make sure no weird bits are set where none of our fields are:
  580. if ((flPenStyle &
  581. ~(PS_TYPE_MASK | PS_STYLE_MASK | PS_ENDCAP_MASK | PS_JOIN_MASK)) != 0)
  582. {
  583. bInvalidParm = TRUE;
  584. }
  585. // Don't do any more parameter checking for NULL pens:
  586. if (ulStyle == PS_NULL)
  587. return(STOCKOBJ_NULLPEN);
  588. // Do some more parameter checking.
  589. switch(iType)
  590. {
  591. case PS_GEOMETRIC:
  592. break;
  593. case PS_COSMETIC:
  594. if ((iBrushStyle == BS_SOLID) ||
  595. ((iBrushStyle == BS_HATCHED) &&
  596. ((lHatch == HS_SOLIDTEXTCLR) || (lHatch == HS_SOLIDBKCLR))))
  597. {
  598. break;
  599. }
  600. default:
  601. bInvalidParm = TRUE;
  602. }
  603. if (lWidthPen != 1 && iType == PS_COSMETIC && !bOldStylePen)
  604. {
  605. bInvalidParm = TRUE;
  606. }
  607. switch(flPenStyle & PS_JOIN_MASK)
  608. {
  609. case PS_JOIN_ROUND: iJoin = JOIN_ROUND; break;
  610. case PS_JOIN_BEVEL: iJoin = JOIN_BEVEL; break;
  611. case PS_JOIN_MITER: iJoin = JOIN_MITER; break;
  612. default:
  613. bInvalidParm = TRUE;
  614. }
  615. switch(flPenStyle & PS_ENDCAP_MASK)
  616. {
  617. case PS_ENDCAP_ROUND: iEndCap = ENDCAP_ROUND; break;
  618. case PS_ENDCAP_FLAT: iEndCap = ENDCAP_BUTT; break;
  619. case PS_ENDCAP_SQUARE: iEndCap = ENDCAP_SQUARE; break;
  620. default:
  621. bInvalidParm = TRUE;
  622. }
  623. // Zero length array allowed iff not doing a user-supplied style,
  624. // and aribtrarily limit the style array size:
  625. if ((ulStyle == PS_USERSTYLE && cstyle == 0) ||
  626. (ulStyle != PS_USERSTYLE && cstyle != 0) ||
  627. cstyle > STYLE_MAX_COUNT)
  628. {
  629. bInvalidParm = TRUE;
  630. }
  631. if (iType == PS_GEOMETRIC)
  632. {
  633. switch(ulStyle)
  634. {
  635. case PS_DOT:
  636. cstyle = sizeof(gaulGeometricDot) / sizeof(ULONG);
  637. pulStyle = gaulGeometricDot;
  638. break;
  639. case PS_DASH:
  640. cstyle = sizeof(gaulGeometricDash) / sizeof(ULONG);
  641. pulStyle = gaulGeometricDash;
  642. break;
  643. case PS_DASHDOT:
  644. cstyle = sizeof(gaulGeometricDashDot) / sizeof(ULONG);
  645. pulStyle = gaulGeometricDashDot;
  646. break;
  647. case PS_DASHDOTDOT:
  648. cstyle = sizeof(gaulGeometricDashDotDot) / sizeof(ULONG);
  649. pulStyle = gaulGeometricDashDotDot;
  650. break;
  651. case PS_USERSTYLE:
  652. case PS_SOLID:
  653. break;
  654. case PS_INSIDEFRAME:
  655. break;
  656. case PS_ALTERNATE:
  657. default:
  658. bInvalidParm = TRUE;
  659. }
  660. }
  661. else
  662. {
  663. switch(ulStyle)
  664. {
  665. case PS_DOT:
  666. cstyle = sizeof(galeCosmeticDot) / sizeof(LONG_FLOAT);
  667. pstyle = &galeCosmeticDot[0].el;
  668. bDefaultStyle = TRUE;
  669. break;
  670. case PS_DASH:
  671. cstyle = sizeof(galeCosmeticDash) / sizeof(LONG_FLOAT);
  672. pstyle = &galeCosmeticDash[0].el;
  673. bDefaultStyle = TRUE;
  674. break;
  675. case PS_DASHDOT:
  676. cstyle = sizeof(galeCosmeticDashDot) / sizeof(LONG_FLOAT);
  677. pstyle = &galeCosmeticDashDot[0].el;
  678. bDefaultStyle = TRUE;
  679. break;
  680. case PS_DASHDOTDOT:
  681. cstyle = sizeof(galeCosmeticDashDotDot) / sizeof(LONG_FLOAT);
  682. pstyle = &galeCosmeticDashDotDot[0].el;
  683. bDefaultStyle = TRUE;
  684. break;
  685. case PS_USERSTYLE:
  686. case PS_SOLID:
  687. break;
  688. case PS_ALTERNATE:
  689. break;
  690. case PS_INSIDEFRAME:
  691. // Don't allow PS_INSIDEFRAME with new style cosmetic pens:
  692. if (!bOldStylePen)
  693. bInvalidParm = TRUE;
  694. break;
  695. default:
  696. bInvalidParm = TRUE;
  697. }
  698. }
  699. if (bInvalidParm)
  700. {
  701. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  702. return((HPEN) 0);
  703. }
  704. if (cstyle > 0 && pstyle == (PFLOAT_LONG) NULL)
  705. {
  706. pstyle = (PFLOAT_LONG) PALLOCNOZ(cstyle * sizeof(FLOAT_LONG),'ytsG');
  707. if (pstyle == (PFLOAT_LONG) NULL)
  708. {
  709. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  710. return((HPEN) 0);
  711. }
  712. PFLOAT_LONG ple = pstyle;
  713. PFLOAT_LONG pleEnd = ple + cstyle;
  714. if (iType == PS_COSMETIC || bOldStylePen)
  715. {
  716. // Handle cosmetic styles:
  717. LONG lMin = 1;
  718. LONG lMax = 1;
  719. LONG lSum = 0;
  720. while (ple < pleEnd)
  721. {
  722. ple->l = (LONG) *pulStyle;
  723. lMin = MIN(lMin, ple->l);
  724. lMax = MAX(lMax, ple->l);
  725. lSum += ple->l;
  726. pulStyle++;
  727. ple++;
  728. }
  729. if (lMin <= 0 || lMax > STYLE_MAX_VALUE || lSum > STYLE_MAX_VALUE)
  730. bInvalidParm = TRUE;
  731. }
  732. else
  733. {
  734. // Handle geometric styles:
  735. LONG lSum = 0;
  736. LONG lMin = 0;
  737. while (ple < pleEnd)
  738. {
  739. LONG lLength = (LONG) *pulStyle;
  740. // Default styles are based on multiples of the pen width:
  741. if (ulStyle != PS_USERSTYLE)
  742. {
  743. // For round and square caps, shorten dashes and lengthen
  744. // the gaps:
  745. if (iEndCap != ENDCAP_BUTT)
  746. lLength += ((ple - pstyle) & 1) ? 1 : -1;
  747. // Don't really care about overflow on this multiplication:
  748. lLength *= lWidthPen;
  749. }
  750. lMin = MIN(lMin, lLength);
  751. lSum += lLength;
  752. EFLOATEXT efLength(lLength);
  753. efLength.vEfToF(ple->e);
  754. pulStyle++;
  755. ple++;
  756. }
  757. if (lMin < 0 || lSum <= 0)
  758. bInvalidParm = TRUE;
  759. }
  760. if (bInvalidParm)
  761. {
  762. // At least one entry in the style array has to be non-zero:
  763. VFREEMEM(pstyle);
  764. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  765. return((HPEN) 0);
  766. }
  767. }
  768. HBRUSH hbr = 0;
  769. switch(iBrushStyle)
  770. {
  771. case BS_HOLLOW:
  772. if (pstyle != (PFLOAT_LONG) NULL && !bDefaultStyle)
  773. VFREEMEM(pstyle);
  774. return(STOCKOBJ_NULLPEN);
  775. case BS_SOLID:
  776. hbr = hCreateSolidBrushInternal(ulColor,
  777. TRUE,
  778. hbrush,
  779. (lWidthPen == 0) && (ulStyle == PS_SOLID));
  780. break;
  781. case BS_HATCHED:
  782. hbr = hCreateHatchBrushInternal((ULONG) lHatch, ulColor, TRUE);
  783. break;
  784. case BS_PATTERN:
  785. hbr = GreCreatePatternBrushInternal((HBITMAP) lHatch, TRUE,FALSE);
  786. break;
  787. case BS_DIBPATTERNPT:
  788. hbr = GreCreateDIBBrush((PVOID) lHatch, ulColor,
  789. (UINT) cjDIB, FALSE, TRUE, (PVOID)lClientHatch);
  790. break;
  791. case BS_DIBPATTERN:
  792. RIP("BS_DIBPATTERN not supported in server");
  793. default:
  794. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  795. }
  796. if (hbr == (HBRUSH) 0)
  797. {
  798. if (pstyle != (PFLOAT_LONG) NULL && !bDefaultStyle)
  799. VFREEMEM(pstyle);
  800. return((HPEN) 0);
  801. }
  802. BRUSHSELOBJ bso(hbr);
  803. // we had better validate this since it is just a handle, it could already
  804. // have been deleted.
  805. if (!bso.bValid())
  806. {
  807. WARNING("Created invalid pen\n");
  808. if (pstyle != (PFLOAT_LONG) NULL && !bDefaultStyle)
  809. VFREEMEM(pstyle);
  810. return((HPEN)0);
  811. }
  812. bso.vSetPen();
  813. bso.flStylePen(flPenStyle);
  814. bso.iEndCap(iEndCap);
  815. bso.iJoin(iJoin);
  816. bso.pstyle(pstyle);
  817. bso.cstyle(cstyle);
  818. bso.lWidthPen(lWidthPen);
  819. if (bDefaultStyle)
  820. bso.vSetDefaultStyle();
  821. bso.lBrushStyle (iBrushStyle);
  822. bso.lHatch (lClientHatch);
  823. if (iType == PS_GEOMETRIC || bOldStylePen)
  824. {
  825. // Geometric line widths are FLOATs in the LINEATTRS structure, so
  826. // we have to keep a FLOAT version of its width around too:
  827. EFLOATEXT efWidth(lWidthPen);
  828. FLOATL l_eWidth;
  829. efWidth.vEfToF(l_eWidth);
  830. bso.l_eWidthPen(l_eWidth);
  831. }
  832. // we need to add the pen/extpen bits to handle type for the client
  833. HBRUSH hbrPen = (HBRUSH) MODIFY_HMGR_TYPE(hbr,LO_EXTPEN_TYPE);
  834. if (bOldStylePen)
  835. {
  836. bso.vSetOldStylePen();
  837. bso.vDisableDither();
  838. if (ulStyle == PS_INSIDEFRAME)
  839. {
  840. bso.vEnableDither();
  841. bso.vSetInsideFrame();
  842. }
  843. hbrPen = (HBRUSH) MODIFY_HMGR_TYPE(hbr,LO_PEN_TYPE);
  844. }
  845. else if (iType == PS_COSMETIC)
  846. {
  847. // For now, cosmetic lines must also be solid colored:
  848. bso.vDisableDither();
  849. }
  850. else
  851. {
  852. // We also support inside frame for geometric ExtCreatePen pens:
  853. if (ulStyle == PS_INSIDEFRAME)
  854. {
  855. bso.vSetInsideFrame();
  856. }
  857. }
  858. // we now set the new pen handle type. This must be done while the pen is locked
  859. HmgModifyHandleType((HOBJ)hbrPen);
  860. ASSERTGDI(!bInvalidParm, "Invalid parm?");
  861. return((HPEN) hbrPen);
  862. }
  863. /******************************Public*Routine******************************\
  864. * GreCreatePenIndirect
  865. *
  866. * API creates a logical pen.
  867. *
  868. * History:
  869. * 08-May-1991 -by- Patrick Haluptzok patrickh
  870. * Wrote it.
  871. \**************************************************************************/
  872. HPEN GreCreatePenIndirect(LPLOGPEN lpLogPen)
  873. {
  874. return(GreCreatePen((int)lpLogPen->lopnStyle,
  875. (int)lpLogPen->lopnWidth.x,
  876. lpLogPen->lopnColor,0));
  877. }
  878. /******************************Public*Routine******************************\
  879. * GreMonoBitmap
  880. *
  881. * Is the specified bitmap monochromatic?
  882. *
  883. * History:
  884. * 18-Mar-1992 -by- Donald Sidoroff [donalds]
  885. * Wrote it.
  886. \**************************************************************************/
  887. BOOL NtGdiMonoBitmap(HBITMAP hbm)
  888. {
  889. SURFREF SurfBmo((HSURF)hbm);
  890. if (!SurfBmo.bValid())
  891. return(FALSE);
  892. XEPALOBJ pal(SurfBmo.ps->ppal());
  893. return(pal.bIsMonochrome());
  894. }
  895. /******************************Public*Routine******************************\
  896. * GreGetObjectBitmapHandle
  897. *
  898. * Gets the handle of the bitmap associated with this brush
  899. *
  900. * History:
  901. * 09-Mar-1992 -by- Donald Sidoroff [donalds]
  902. * Wrote it.
  903. \**************************************************************************/
  904. HBITMAP GreGetObjectBitmapHandle(
  905. HBRUSH hbr,
  906. UINT *piUsage)
  907. {
  908. BRUSHSELOBJ ebo(hbr);
  909. if (!ebo.bValid())
  910. {
  911. return((HBITMAP) 0);
  912. }
  913. HBITMAP hbm = ebo.hbmPattern();
  914. if (ebo.bPalColors())
  915. {
  916. *piUsage = DIB_PAL_COLORS;
  917. }
  918. else if (ebo.bPalIndices())
  919. {
  920. *piUsage = DIB_PAL_INDICES;
  921. }
  922. else
  923. {
  924. *piUsage = DIB_RGB_COLORS;
  925. }
  926. return(hbm);
  927. }