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.

5849 lines
171 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1998 Microsoft Corporation
  4. *
  5. * Abstract:
  6. *
  7. * Implementation of GpBrush class
  8. *
  9. * Revision History:
  10. *
  11. * 12/09/1998 davidx
  12. * Flesh out brush interfaces.
  13. *
  14. * 12/08/1998 andrewgo
  15. * Initial placeholders.
  16. *
  17. \**************************************************************************/
  18. #include "precomp.hpp"
  19. // For GetData and SetData methods
  20. #define GDIP_BRUSHFLAGS_PATH 0x00000001
  21. #define GDIP_BRUSHFLAGS_TRANSFORM 0x00000002
  22. #define GDIP_BRUSHFLAGS_PRESETCOLORS 0x00000004
  23. #define GDIP_BRUSHFLAGS_BLENDFACTORS 0x00000008
  24. #define GDIP_BRUSHFLAGS_BLENDFACTORSH GDIP_BRUSHFLAGS_BLENDFACTORS
  25. #define GDIP_BRUSHFLAGS_BLENDFACTORSV 0x00000010
  26. #define GDIP_BRUSHFLAGS_BLENDFACTORS0 GDIP_BRUSHFLAGS_BLENDFACTORSH
  27. #define GDIP_BRUSHFLAGS_BLENDFACTORS1 GDIP_BRUSHFLAGS_BLENDFACTORSV
  28. #define GDIP_BRUSHFLAGS_BLENDFACTORS2 0x00000020
  29. #define GDIP_BRUSHFLAGS_FOCUSSCALES 0x00000040
  30. #define GDIP_BRUSHFLAGS_ISGAMMACORRECTED 0x00000080
  31. // Defined in path.cpp
  32. extern BOOL
  33. IsRectanglePoints(
  34. const GpPointF* points,
  35. INT count,
  36. const GpMatrix * matrix,
  37. GpRectF * transformedBounds
  38. );
  39. GpStatus
  40. GpElementaryBrush::MultiplyTransform(const GpMatrix& matrix,
  41. GpMatrixOrder order)
  42. {
  43. GpStatus status = Ok;
  44. if (matrix.IsInvertible())
  45. {
  46. if (order == MatrixOrderPrepend)
  47. {
  48. DeviceBrush.Xform.Prepend(matrix);
  49. }
  50. else
  51. {
  52. DeviceBrush.Xform.Append(matrix);
  53. }
  54. UpdateUid();
  55. }
  56. else
  57. status = InvalidParameter;
  58. return status;
  59. }
  60. /**************************************************************************\
  61. *
  62. * Function Description:
  63. *
  64. * Calculate the brush transform from a starting point and two directions.
  65. *
  66. * Arguments:
  67. *
  68. * [OUT] m - matrix coefficients
  69. * [OUT] width - width (the length of dP1)
  70. * [OUT] height - height (the length of dP2)
  71. * [IN] p0 - the starting point of the brush.
  72. * [IN] dP1 - the vector to represent the transformed x-direction.
  73. * [IN] dP2 - the vector to represent the transformed y-direction.
  74. *
  75. * Return Vaule:
  76. *
  77. * TRUE if the transform matrix is non-degenerate.
  78. * Otherwise returns FALSE.
  79. *
  80. * History:
  81. *
  82. * 06/03/1999 ikkof
  83. * Created it.
  84. *
  85. \**************************************************************************/
  86. BOOL getLineGradientTransform(
  87. REAL* m,
  88. REAL* width,
  89. REAL* height,
  90. const GpPointF& p0,
  91. const GpPointF& dP1,
  92. const GpPointF& dP2
  93. )
  94. {
  95. // Make sure the flat API has correctly set the FPU.
  96. FPUStateSaver::AssertMode();
  97. REAL l1 = dP1.X*dP1.X + dP1.Y*dP1.Y;
  98. REAL l2 = dP2.X*dP2.X + dP2.Y*dP2.Y;
  99. REAL test = dP1.X*dP2.Y - dP1.Y*dP2.X;
  100. if(l1 == 0 || l2 == 0 || test == 0)
  101. return FALSE;
  102. l1 = REALSQRT(l1);
  103. l2 = REALSQRT(l2);
  104. m[0] = TOREAL(dP1.X/l1); // M11
  105. m[1] = TOREAL(dP1.Y/l1); // M12
  106. m[2] = TOREAL(dP2.X/l2); // M21
  107. m[3] = TOREAL(dP2.Y/l2); // M22
  108. m[4] = TOREAL(p0.X - p0.X*m[0] - p0.Y*m[2]); // Dx
  109. m[5] = TOREAL(p0.Y - p0.X*m[1] - p0.Y*m[3]); // Dy
  110. *width = l1;
  111. *height = l2;
  112. return TRUE;
  113. }
  114. static GpStatus
  115. LinearGradientRectFromPoints(
  116. const GpPointF& point1,
  117. const GpPointF& point2,
  118. GpRectF & rect
  119. )
  120. {
  121. // If the API specifies two coincident points, we
  122. // can't get information for the gradient, so we
  123. // fail the construction here.
  124. if( IsClosePointF(point1, point2) )
  125. {
  126. return InvalidParameter;
  127. }
  128. // Compute the bounding rectangle of the two input points.
  129. rect.X = min(point1.X, point2.X);
  130. rect.Y = min(point1.Y, point2.Y);
  131. rect.Width = REALABS(point1.X-point2.X);
  132. rect.Height = REALABS(point1.Y-point2.Y);
  133. // eliminate degenerate rectangles when the two
  134. // input points form a horizontal or vertical line.
  135. // This is a very odd way of coercing a 1d linear gradient
  136. // into a rect gradient and avoiding later matrix computation error
  137. // when we try get an affine warp between this rectangle and a
  138. // reference rectangle.
  139. if( IsCloseReal(point1.X, point2.X) )
  140. {
  141. rect.X -= rect.Height/2;
  142. rect.Width = rect.Height;
  143. }
  144. if( IsCloseReal(point1.Y, point2.Y) )
  145. {
  146. rect.Y -= rect.Width/2;
  147. rect.Height = rect.Width;
  148. }
  149. return Ok;
  150. }
  151. static GpStatus
  152. CalcLinearGradientXform(
  153. REAL angle,
  154. BOOL isAngleScalable,
  155. const GpRectF& rect,
  156. GpMatrix& xform
  157. )
  158. {
  159. GpPointF p0, dP1, dP2;
  160. angle = GpModF(angle, 360);
  161. INT zone;
  162. REALD deltaTheta;
  163. const REALD degreeToRadian = 3.1415926535897932/180;
  164. if(angle < 90)
  165. {
  166. zone = 0;
  167. deltaTheta = angle;
  168. }
  169. else if(angle < 180)
  170. {
  171. zone = 1;
  172. deltaTheta = 180 - angle;
  173. }
  174. else if(angle < 270)
  175. {
  176. zone = 2;
  177. deltaTheta = angle - 180;
  178. }
  179. else
  180. {
  181. zone = 3;
  182. deltaTheta = 360 - angle;
  183. }
  184. REALD s, c;
  185. deltaTheta *= degreeToRadian;
  186. s = sin(deltaTheta);
  187. c = cos(deltaTheta);
  188. // d0 is the distance between p0 and the starting corner of the
  189. // original rectangle.
  190. // d1 and d2 is the length of dP1 and dP2, respectively.
  191. REALD top, left, w, h, d0, d1, d2;
  192. REALD x0, y0; // Starting corner of the original rectangle.
  193. GpPointD norm; // Direction of dP1.
  194. // Direction of dP2 = (-norm.Y, norm.X) which is 90 degree rotation
  195. // of dP1.
  196. if(!isAngleScalable)
  197. {
  198. left = rect.X;
  199. top = rect.Y;
  200. w = rect.Width;
  201. h = rect.Height;
  202. }
  203. else
  204. {
  205. // Scale to (0, 0, 1, 1) rectangle.
  206. top = 0.0;
  207. left = 0.0;
  208. w = 1.0;
  209. h = 1.0;
  210. }
  211. switch(zone)
  212. {
  213. case 0:
  214. d0 = w*s;
  215. norm.X = c;
  216. norm.Y = s;
  217. x0 = left;
  218. y0 = top;
  219. break;
  220. case 1:
  221. d0 = h*c;
  222. norm.X = - c;
  223. norm.Y = s;
  224. x0 = left + w;
  225. y0 = top;
  226. break;
  227. case 2:
  228. d0 = w*s;
  229. norm.X = - c;
  230. norm.Y = - s;
  231. x0 = left + w;
  232. y0 = top + h;
  233. break;
  234. case 3:
  235. d0 = h*c;
  236. norm.X = c;
  237. norm.Y = - s;
  238. x0 = left;
  239. y0 = top + h;
  240. break;
  241. }
  242. d2 = w*s + h*c;
  243. d1 = w*c + h*s;
  244. p0.X = TOREAL(x0 + d0*norm.Y);
  245. p0.Y = TOREAL(y0 - d0*norm.X);
  246. dP1.X = TOREAL(d1*norm.X);
  247. dP1.Y = TOREAL(d1*norm.Y);
  248. dP2.X = TOREAL(- d2*norm.Y);
  249. dP2.Y = TOREAL(d2*norm.X);
  250. if(isAngleScalable)
  251. {
  252. // Scale back.
  253. p0.X = rect.Width*p0.X + rect.X;
  254. p0.Y = rect.Height*p0.Y + rect.Y;
  255. dP1.X *= rect.Width;
  256. dP1.Y *= rect.Height;
  257. dP2.X *= rect.Width;
  258. dP2.Y *= rect.Height;
  259. }
  260. // Set up the transform.
  261. GpPointF points[3];
  262. points[0] = p0;
  263. points[1].X = p0.X + dP1.X;
  264. points[1].Y = p0.Y + dP1.Y;
  265. points[2].X = p0.X + dP2.X;
  266. points[2].Y = p0.Y + dP2.Y;
  267. GpStatus status;
  268. if(xform.InferAffineMatrix(&points[0], rect) == Ok)
  269. {
  270. return Ok;
  271. }
  272. return InvalidParameter;
  273. }
  274. GpStatus
  275. GpLineGradient::ChangeLinePoints(
  276. const GpPointF& point1,
  277. const GpPointF& point2,
  278. BOOL isAngleScalable
  279. )
  280. {
  281. GpStatus status;
  282. GpRectF rect;
  283. if ((status = LinearGradientRectFromPoints(point1, point2, rect)) != Ok)
  284. {
  285. return status;
  286. }
  287. REAL angle = GetAngleFromPoints(point1, point2);
  288. GpMatrix xform;
  289. if ((status = CalcLinearGradientXform(angle, isAngleScalable, rect, xform)) == Ok)
  290. {
  291. DeviceBrush.Xform = xform;
  292. DeviceBrush.Rect = rect;
  293. DeviceBrush.IsAngleScalable = isAngleScalable;
  294. DeviceBrush.Points[0] = point1;
  295. DeviceBrush.Points[1] = point2;
  296. return Ok;
  297. }
  298. return status;
  299. }
  300. GpLineGradient::GpLineGradient(
  301. const GpPointF& point1,
  302. const GpPointF& point2,
  303. const GpColor& color1,
  304. const GpColor& color2,
  305. GpWrapMode wrapMode
  306. )
  307. {
  308. // Make sure the flat API has correctly set the FPU.
  309. FPUStateSaver::AssertMode();
  310. REAL angle;
  311. GpRectF rect;
  312. if (LinearGradientRectFromPoints(point1, point2, rect) != Ok)
  313. {
  314. SetValid(FALSE);
  315. return;
  316. }
  317. // Compute the angle of the line formed by point1 and point2.
  318. // Note atan2 is only undefined if dP.Y == 0.0 and dP.X == 0.0
  319. // and then it returns 0 radians. We take care of that case separately
  320. // (above).
  321. // Also, atan2 correctly computes the quadrant from the two input points.
  322. GpPointF dP = point2 - point1;
  323. double rad = atan2((double)(dP.Y), (double)(dP.X));
  324. SetLineGradient(
  325. point1,
  326. point2,
  327. rect,
  328. color1,
  329. color2,
  330. // why aren't we working in radians???
  331. (REAL)(rad*180.0/3.1415926535897932),
  332. FALSE,
  333. wrapMode
  334. );
  335. }
  336. /**************************************************************************\
  337. *
  338. * Function Description:
  339. *
  340. * Creates a LineGradient which is defined by the rectangle.
  341. *
  342. * Arguments:
  343. *
  344. * [IN] rect - the rectangle to define this gradient.
  345. * [IN] color1 - the color of the start point.
  346. * [IN] color2 - the color of the end point.
  347. * [IN] mode - the line gradient mode
  348. * [IN] wrapMode - the wrap mode of this brush.
  349. *
  350. * The start and end points of this gradient is defined as follows
  351. * according to the line gradient mode:
  352. *
  353. * mode start point end point
  354. * -------------------------------------------------------------
  355. * LineGradientHorizontal top-left top-right
  356. * LineGradientVertical top-right bottom-right
  357. * LineGradientForwardDiagonal top-left bottom-right
  358. * LineGradientBackwardDiagonal bottom-left top-right
  359. *
  360. *
  361. * History:
  362. *
  363. * 06/03/1999 ikkof
  364. * Created it.
  365. *
  366. \**************************************************************************/
  367. GpLineGradient::GpLineGradient(
  368. const GpRectF& rect,
  369. const GpColor& color1,
  370. const GpColor& color2,
  371. LinearGradientMode mode,
  372. GpWrapMode wrapMode
  373. )
  374. {
  375. // Make sure the flat API has correctly set the FPU.
  376. FPUStateSaver::AssertMode();
  377. BOOL isAngleScalable = TRUE;
  378. REAL angle = 0;
  379. GpPointF point1;
  380. GpPointF point2;
  381. switch(mode)
  382. {
  383. case LinearGradientModeHorizontal:
  384. angle = 0;
  385. point1.X = rect.X;
  386. point1.Y = (rect.Y + rect.GetBottom()) / 2.0f;
  387. point2.X = rect.GetRight();
  388. point2.Y = point1.Y;
  389. break;
  390. case LinearGradientModeVertical:
  391. angle = 90;
  392. point1.X = (rect.X + rect.GetRight()) / 2.0f;
  393. point1.Y = rect.Y;
  394. point2.X = point1.X;
  395. point2.Y = rect.GetBottom();
  396. break;
  397. case LinearGradientModeForwardDiagonal:
  398. angle = 45;
  399. point1.X = rect.X;
  400. point1.Y = rect.Y;
  401. point2.X = rect.GetRight();
  402. point2.Y = rect.GetBottom();
  403. break;
  404. case LinearGradientModeBackwardDiagonal:
  405. angle = 135;
  406. point1.X = rect.GetRight();
  407. point1.Y = rect.Y;
  408. point2.X = rect.X;
  409. point2.Y = rect.GetBottom();
  410. break;
  411. default:
  412. // No such a case.
  413. ASSERT(0);
  414. SetValid(FALSE);
  415. return;
  416. }
  417. SetLineGradient(
  418. point1,
  419. point2,
  420. rect,
  421. color1,
  422. color2,
  423. angle,
  424. isAngleScalable,
  425. wrapMode);
  426. }
  427. /**************************************************************************\
  428. *
  429. * Function Description:
  430. *
  431. * Creates a LineGradient which is defined by the rectangle.
  432. *
  433. * Arguments:
  434. *
  435. * [IN] rect - the rectangle to define this gradient.
  436. * [IN] color1 - the color of the start point.
  437. * [IN] color2 - the color of the end point.
  438. * [IN] angle - the angle of the gradient
  439. * [IN] isAngleScalable - TRUE if 45 degree is corner to corner.
  440. * The default value is FALSE.
  441. * [IN] wrapMode - the wrap mode of this brush.
  442. *
  443. *
  444. *
  445. * History:
  446. *
  447. * 10/06/1999 ikkof
  448. * Created it.
  449. *
  450. \**************************************************************************/
  451. GpLineGradient::GpLineGradient(
  452. const GpRectF& rect,
  453. const GpColor& color1,
  454. const GpColor& color2,
  455. REAL angle,
  456. BOOL isAngleScalable,
  457. GpWrapMode wrapMode
  458. )
  459. {
  460. // Make sure the flat API has correctly set the FPU.
  461. FPUStateSaver::AssertMode();
  462. GpPointF point1;
  463. GpPointF point2;
  464. // Not an Office scenario, but need to fix at some point
  465. // so we can print to PCL better.
  466. point1.X = point1.Y = point2.X = point2.Y = 0;
  467. SetLineGradient(
  468. point1,
  469. point2,
  470. rect,
  471. color1,
  472. color2,
  473. angle,
  474. isAngleScalable,
  475. wrapMode);
  476. }
  477. GpStatus
  478. GpLineGradient::SetLineGradient(
  479. const GpPointF& point1,
  480. const GpPointF& point2,
  481. const GpRectF& rect,
  482. const GpColor& color1,
  483. const GpColor& color2,
  484. REAL angle,
  485. BOOL isAngleScalable,
  486. GpWrapMode wrapMode
  487. )
  488. {
  489. // Make sure the flat API has correctly set the FPU.
  490. FPUStateSaver::AssertMode();
  491. DeviceBrush.Wrap = wrapMode;
  492. DeviceBrush.Colors[0] = color1;
  493. DeviceBrush.Colors[1] = color2;
  494. DeviceBrush.Colors[2] = color1;
  495. DeviceBrush.Colors[3] = color2;
  496. DeviceBrush.BlendCounts[0] = DeviceBrush.BlendCounts[1] = 1;
  497. DeviceBrush.BlendFactors[0] = DeviceBrush.BlendFactors[1] = NULL;
  498. DeviceBrush.Falloffs[0] = DeviceBrush.Falloffs[1] = 1;
  499. GpStatus status;
  500. if (CalcLinearGradientXform(angle, isAngleScalable, rect, DeviceBrush.Xform) == Ok)
  501. {
  502. SetValid(TRUE);
  503. DeviceBrush.Rect = rect;
  504. DeviceBrush.IsAngleScalable = isAngleScalable;
  505. DeviceBrush.Points[0] = point1;
  506. DeviceBrush.Points[1] = point2;
  507. status = Ok;
  508. }
  509. else
  510. {
  511. SetValid(FALSE);
  512. GpMemset(&DeviceBrush.Rect, 0, sizeof(DeviceBrush.Rect));
  513. GpMemset(DeviceBrush.Points, 0, sizeof(DeviceBrush.Points[0]) * 2);
  514. DeviceBrush.IsAngleScalable = FALSE;
  515. status = InvalidParameter;
  516. }
  517. return status;
  518. }
  519. GpStatus
  520. GpLineGradient::SetLinePoints(
  521. const GpPointF& point1,
  522. const GpPointF& point2
  523. )
  524. {
  525. // Make sure the flat API has correctly set the FPU.
  526. FPUStateSaver::AssertMode();
  527. GpPointF p0, dP1, dP2;
  528. p0 = point1;
  529. dP1.X = point2.X - point1.X;
  530. dP1.Y = point2.Y - point1.Y;
  531. dP2.X = - dP1.Y;
  532. dP2.Y = dP1.X;
  533. REAL m[6];
  534. REAL width, height;
  535. if(getLineGradientTransform(&m[0], &width, &height, p0, dP1, dP2))
  536. {
  537. SetValid(TRUE);
  538. DeviceBrush.Rect.X = p0.X;
  539. DeviceBrush.Rect.Y = p0.Y;
  540. DeviceBrush.Rect.Width = width;
  541. DeviceBrush.Rect.Height = height;
  542. }
  543. else
  544. {
  545. // Don't change the current state.
  546. return GenericError;
  547. }
  548. DeviceBrush.Xform.SetMatrix(m);
  549. UpdateUid();
  550. return Ok;
  551. }
  552. GpStatus
  553. GpLineGradient::GetLinePoints(GpPointF* points)
  554. {
  555. // Make sure the flat API has correctly set the FPU.
  556. FPUStateSaver::AssertMode();
  557. ASSERT(points);
  558. points[0].X = DeviceBrush.Rect.X;
  559. points[0].Y = DeviceBrush.Rect.Y;
  560. points[1].X = DeviceBrush.Rect.X + DeviceBrush.Rect.Width;
  561. points[1].Y = DeviceBrush.Rect.Y + DeviceBrush.Rect.Height;
  562. DeviceBrush.Xform.Transform(points, 2);
  563. return Ok;
  564. }
  565. INT
  566. GpLineGradient::GetPresetBlendCount()
  567. {
  568. if(DeviceBrush.UsesPresetColors)
  569. return DeviceBrush.BlendCounts[0];
  570. else
  571. return 0;
  572. }
  573. /*
  574. ** This returns the premultiplied colors
  575. */
  576. GpStatus
  577. GpLineGradient::GetPresetBlend(
  578. GpColor* blendColors,
  579. REAL* blendPositions,
  580. INT count)
  581. {
  582. // Make sure the flat API has correctly set the FPU.
  583. FPUStateSaver::AssertMode();
  584. if(!blendColors || !blendPositions || count <= 1)
  585. return InvalidParameter;
  586. if(DeviceBrush.UsesPresetColors &&
  587. DeviceBrush.PresetColors &&
  588. DeviceBrush.BlendPositions[0])
  589. {
  590. for(INT i = 0; i < count; i++)
  591. {
  592. blendColors[i].SetColor(DeviceBrush.PresetColors[i]);
  593. }
  594. GpMemcpy(blendPositions,
  595. DeviceBrush.BlendPositions[0],
  596. count*sizeof(REAL));
  597. return Ok;
  598. }
  599. else
  600. return GenericError;
  601. }
  602. GpStatus
  603. GpLineGradient::SetPresetBlend(
  604. const GpColor* blendColors,
  605. const REAL* blendPositions,
  606. INT count)
  607. {
  608. // Make sure the flat API has correctly set the FPU.
  609. FPUStateSaver::AssertMode();
  610. if(!blendColors || !blendPositions || count <= 1)
  611. return InvalidParameter;
  612. ARGB* newColors = (ARGB*) GpRealloc(DeviceBrush.PresetColors,
  613. count*sizeof(ARGB));
  614. if (newColors != NULL)
  615. {
  616. DeviceBrush.PresetColors = newColors;
  617. }
  618. else
  619. {
  620. return OutOfMemory;
  621. }
  622. REAL* newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[0],
  623. count*sizeof(REAL));
  624. if (newPositions != NULL)
  625. {
  626. DeviceBrush.BlendPositions[0] = newPositions;
  627. }
  628. else
  629. {
  630. return OutOfMemory;
  631. }
  632. GpFree(DeviceBrush.BlendFactors[0]);
  633. // DeviceBrush.BlendFactors[1] is always NULL for LineGradient.
  634. DeviceBrush.BlendFactors[0] = NULL;
  635. DeviceBrush.UsesPresetColors = TRUE;
  636. for(INT i = 0; i < count; i++)
  637. {
  638. newColors[i] = blendColors[i].GetValue();
  639. }
  640. GpMemcpy(newPositions, blendPositions, count*sizeof(REAL));
  641. DeviceBrush.BlendCounts[0] = count;
  642. UpdateUid();
  643. return Ok;
  644. }
  645. /**************************************************************************\
  646. *
  647. * Function Description:
  648. *
  649. * Blend any transparent colors in this brush with white. Note that
  650. * colors are premultiplied, since they will become fully opaque.
  651. *
  652. * Arguments:
  653. *
  654. * Return Value:
  655. *
  656. * GpStatus - Ok or failure status
  657. *
  658. \**************************************************************************/
  659. GpStatus GpLineGradient::BlendWithWhite()
  660. {
  661. if (DeviceBrush.UsesPresetColors)
  662. {
  663. GpColor color;
  664. for (INT i=0; i<DeviceBrush.BlendCounts[0]; i++)
  665. {
  666. color.SetValue(GpColor::ConvertToPremultiplied(DeviceBrush.PresetColors[i]));
  667. color.BlendOpaqueWithWhite();
  668. DeviceBrush.PresetColors[i] = color.GetValue();
  669. }
  670. return Ok;
  671. }
  672. else
  673. {
  674. return GpRectGradient::BlendWithWhite();
  675. }
  676. }
  677. BOOL
  678. GpPathGradient::IsRectangle() const
  679. {
  680. BOOL result = FALSE;
  681. if (DeviceBrush.PointsPtr != NULL)
  682. result = IsRectanglePoints(DeviceBrush.PointsPtr, DeviceBrush.Count, NULL, NULL);
  683. else
  684. {
  685. GpPath* path = static_cast<GpPath*> (DeviceBrush.Path);
  686. if(path)
  687. result = path->IsRectangle(NULL);
  688. }
  689. return result;
  690. }
  691. INT
  692. GpPathGradient::GetPresetBlendCount() const
  693. {
  694. if(DeviceBrush.UsesPresetColors)
  695. return DeviceBrush.BlendCounts[0];
  696. else
  697. return 0;
  698. }
  699. /*
  700. ** This returns the premultiplied colors
  701. */
  702. GpStatus
  703. GpPathGradient::GetPresetBlend(
  704. GpColor* blendColors,
  705. REAL* blendPositions,
  706. INT count) const
  707. {
  708. if(!blendColors || !blendPositions || count <= 1)
  709. return InvalidParameter;
  710. if(DeviceBrush.UsesPresetColors && DeviceBrush.PresetColors && DeviceBrush.BlendPositions[0])
  711. {
  712. // Users will obtain the preset colors as radial blend colors.
  713. // 0 position means the center location and 1 position means the
  714. // the outer edge. In order to convert those colors and position arrays
  715. // from the weight factor arrays in PathGradient,
  716. // we must invert the order of the returned arrays.
  717. for(INT i = 0; i < count; i++)
  718. {
  719. blendColors[count - 1 -i].SetColor(DeviceBrush.PresetColors[i]);
  720. blendPositions[count - 1 -i] = TOREAL(1.0 - DeviceBrush.BlendPositions[0][i]);
  721. }
  722. return Ok;
  723. }
  724. else
  725. return GenericError;
  726. }
  727. GpStatus
  728. GpPathGradient::SetPresetBlend(
  729. const GpColor* blendColors,
  730. const REAL* blendPositions,
  731. INT count)
  732. {
  733. if(!blendColors || !blendPositions || count <= 1)
  734. return InvalidParameter;
  735. ARGB* newColors = (ARGB*) GpRealloc(DeviceBrush.PresetColors, count*sizeof(ARGB));
  736. if (newColors != NULL)
  737. {
  738. DeviceBrush.PresetColors = newColors;
  739. }
  740. else
  741. {
  742. return OutOfMemory;
  743. }
  744. REAL* newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[0], count*sizeof(REAL));
  745. if (newPositions != NULL)
  746. {
  747. DeviceBrush.BlendPositions[0] = newPositions;
  748. }
  749. else
  750. {
  751. return OutOfMemory;
  752. }
  753. GpFree(DeviceBrush.BlendFactors[0]);
  754. DeviceBrush.BlendFactors[0] = NULL;
  755. DeviceBrush.UsesPresetColors = TRUE;
  756. // Users will supply the preset colors as radial blend colors.
  757. // 0 position means the center location and 1 position means the
  758. // the outer edge. In order to convert those colors and position arrays
  759. // to the weight factor arrays in PathGradient,
  760. // we must invert the order of the given arrays.
  761. for(INT i = 0; i < count; i++)
  762. {
  763. // PresetColors are stored non-premultiplied.
  764. newColors[count - 1 - i] = blendColors[i].GetValue();
  765. newPositions[count - 1 - i] = TOREAL(1.0 - blendPositions[i]);
  766. }
  767. DeviceBrush.BlendCounts[0] = count;
  768. UpdateUid();
  769. return Ok;
  770. }
  771. //==================================================================
  772. // Copy constructors
  773. //==================================================================
  774. GpElementaryBrush::GpElementaryBrush(const GpElementaryBrush *brush)
  775. {
  776. if(brush && brush->IsValid())
  777. {
  778. // !!! [asecchia] we should really be asking the DeviceBrush to
  779. // copy it's members instead of duplicating the code all over
  780. // the place. Current code is error prone - each subclass is has to
  781. // know all about how to copy and what has or hasn't been updated on
  782. // the chain down to it's ancestor.
  783. DeviceBrush.Xform = brush->DeviceBrush.Xform;
  784. DeviceBrush.Wrap = brush->DeviceBrush.Wrap;
  785. DeviceBrush.IsGammaCorrected = brush->DeviceBrush.IsGammaCorrected;
  786. SetValid(brush->IsValid());
  787. }
  788. else
  789. SetValid(FALSE);
  790. }
  791. GpTexture::GpTexture(
  792. const GpTexture *brush
  793. ) : GpElementaryBrush(brush)
  794. {
  795. if(brush && brush->IsValid())
  796. {
  797. const DpBrush* devBrush = &(brush->DeviceBrush);
  798. InitializeBrush(brush->Image, devBrush->Wrap, NULL);
  799. SetTransform(devBrush->Xform);
  800. }
  801. else
  802. SetValid(FALSE);
  803. }
  804. GpRectGradient::GpRectGradient(
  805. const GpRectGradient *brush
  806. ) : GpGradientBrush(brush)
  807. {
  808. if(brush && brush->IsValid())
  809. {
  810. const DpBrush* devBrush = &(brush->DeviceBrush);
  811. InitializeBrush(
  812. devBrush->Rect,
  813. &(devBrush->Colors[0]),
  814. devBrush->Wrap
  815. );
  816. SetTransform(devBrush->Xform);
  817. SetHorizontalBlend(
  818. devBrush->BlendFactors[0],
  819. devBrush->BlendPositions[0],
  820. devBrush->BlendCounts[0]
  821. );
  822. SetVerticalBlend(
  823. devBrush->BlendFactors[1],
  824. devBrush->BlendPositions[1],
  825. devBrush->BlendCounts[1]
  826. );
  827. }
  828. else
  829. SetValid(FALSE);
  830. }
  831. GpLineGradient::GpLineGradient(
  832. const GpLineGradient *brush
  833. ) : GpRectGradient(brush)
  834. {
  835. if(brush && brush->IsValid())
  836. {
  837. // Copy the preset colors.
  838. // !!! [asecchia] why isn't this handled in a uniform way?
  839. const DpBrush* devBrush = &(brush->DeviceBrush);
  840. DeviceBrush.Points[0] = devBrush->Points[0];
  841. DeviceBrush.Points[1] = devBrush->Points[1];
  842. DeviceBrush.IsAngleScalable = devBrush->IsAngleScalable;
  843. if(devBrush->UsesPresetColors)
  844. {
  845. SetPresetBlend(
  846. (GpColor*)(devBrush->PresetColors),
  847. (REAL*)(devBrush->BlendPositions[0]),
  848. devBrush->BlendCounts[0]
  849. );
  850. }
  851. }
  852. }
  853. GpPathGradient::GpPathGradient(
  854. const GpPathGradient *brush
  855. ) : GpGradientBrush(brush)
  856. {
  857. if(brush && brush->IsValid())
  858. {
  859. const DpBrush* devBrush = &(brush->DeviceBrush);
  860. // If a path exists for the brush, use that for initialization.
  861. // Otherwise, use the points collection.
  862. if (devBrush->Path != NULL)
  863. {
  864. DefaultBrush();
  865. DeviceBrush.Wrap = devBrush->Wrap;
  866. DeviceBrush.Path = devBrush->Path->ClonePath();
  867. PrepareBrush();
  868. }
  869. else
  870. {
  871. InitializeBrush(devBrush->PointsPtr,
  872. devBrush->Count,
  873. devBrush->Wrap);
  874. }
  875. if(IsValid())
  876. {
  877. SetTransform(devBrush->Xform);
  878. SetCenterPoint(devBrush->Points[0]);
  879. SetCenterColor(devBrush->Colors[0]);
  880. SetSurroundColors(devBrush->ColorsPtr);
  881. DeviceBrush.Falloffs[0] = devBrush->Falloffs[0];
  882. DeviceBrush.FocusScaleX = devBrush->FocusScaleX;
  883. DeviceBrush.FocusScaleY = devBrush->FocusScaleY;
  884. DeviceBrush.UsesPresetColors = devBrush->UsesPresetColors;
  885. INT blendCount = devBrush->BlendCounts[0];
  886. DeviceBrush.BlendCounts[0] = blendCount;
  887. // If we're cloning a brush with preset colors, copy preset colors
  888. // and blend positions. Otherwise, copy the blend factors and
  889. // blend positions.
  890. if (devBrush->UsesPresetColors)
  891. {
  892. ARGB* newColors = (ARGB*) GpRealloc(DeviceBrush.PresetColors, blendCount*sizeof(ARGB));
  893. if (newColors != NULL)
  894. {
  895. DeviceBrush.PresetColors = newColors;
  896. REAL* newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[0], blendCount*sizeof(REAL));
  897. if (newPositions != NULL)
  898. {
  899. DeviceBrush.BlendPositions[0] = newPositions;
  900. GpFree(DeviceBrush.BlendFactors[0]);
  901. DeviceBrush.BlendFactors[0] = NULL;
  902. memcpy(DeviceBrush.PresetColors,
  903. devBrush->PresetColors,
  904. blendCount*sizeof(ARGB));
  905. memcpy(DeviceBrush.BlendPositions[0],
  906. devBrush->BlendPositions[0],
  907. blendCount*sizeof(REAL));
  908. }
  909. else
  910. {
  911. SetValid(FALSE);
  912. }
  913. }
  914. else
  915. {
  916. SetValid(FALSE);
  917. }
  918. }
  919. else if (devBrush->BlendFactors[0] && devBrush->BlendPositions[0])
  920. {
  921. REAL* newFactors = (REAL*) GpRealloc(DeviceBrush.BlendFactors[0], blendCount*sizeof(REAL));
  922. if (newFactors != NULL)
  923. {
  924. DeviceBrush.BlendFactors[0] = newFactors;
  925. REAL* newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[0], blendCount*sizeof(REAL));
  926. if (newPositions != NULL)
  927. {
  928. DeviceBrush.BlendPositions[0] = newPositions;
  929. memcpy(DeviceBrush.BlendFactors[0],
  930. devBrush->BlendFactors[0],
  931. blendCount*sizeof(REAL));
  932. memcpy(DeviceBrush.BlendPositions[0],
  933. devBrush->BlendPositions[0],
  934. blendCount*sizeof(REAL));
  935. }
  936. else
  937. {
  938. SetValid(FALSE);
  939. }
  940. }
  941. else
  942. {
  943. SetValid(FALSE);
  944. }
  945. }
  946. }
  947. }
  948. else
  949. SetValid(FALSE);
  950. }
  951. GpHatch::GpHatch(const GpHatch* brush)
  952. {
  953. if(brush && brush->IsValid())
  954. {
  955. const DpBrush* devBrush = &(brush->DeviceBrush);
  956. InitializeBrush(devBrush->Style,
  957. devBrush->Colors[0],
  958. devBrush->Colors[1]);
  959. }
  960. else
  961. SetValid(FALSE);
  962. }
  963. /**************************************************************************\
  964. *
  965. * Function Description:
  966. *
  967. * Getting horizontal falloff / blend-factors for
  968. * a rectangular gradient brush object
  969. *
  970. * Arguments:
  971. *
  972. * [OUT] blendFactors - Buffer for returning the horizontal
  973. * falloff or blend-factors.
  974. * count - Size of the buffer (in number of REAL elements)
  975. *
  976. * Return Value:
  977. *
  978. * Status code
  979. *
  980. \**************************************************************************/
  981. GpStatus
  982. GpRectGradient::GetHorizontalBlend(
  983. REAL* blendFactors,
  984. REAL* blendPositions,
  985. INT count
  986. )
  987. {
  988. if(!blendFactors || !blendPositions || count < 1)
  989. return InvalidParameter;
  990. // Check if the input buffer is big enough
  991. if (count < DeviceBrush.BlendCounts[0])
  992. return InsufficientBuffer;
  993. if (DeviceBrush.BlendCounts[0] == 1)
  994. {
  995. // Return falloff parameter
  996. blendFactors[0] = DeviceBrush.Falloffs[0];
  997. }
  998. else
  999. {
  1000. // Return blend factors
  1001. GpMemcpy(
  1002. blendFactors,
  1003. DeviceBrush.BlendFactors[0],
  1004. DeviceBrush.BlendCounts[0]*sizeof(REAL)
  1005. );
  1006. GpMemcpy(
  1007. blendPositions,
  1008. DeviceBrush.BlendPositions[0],
  1009. DeviceBrush.BlendCounts[0]*sizeof(REAL)
  1010. );
  1011. }
  1012. return Ok;
  1013. }
  1014. /**************************************************************************\
  1015. *
  1016. * Function Description:
  1017. *
  1018. * Setting horizontal falloff / blend-factors for
  1019. * a rectangular gradient brush object
  1020. *
  1021. * Arguments:
  1022. *
  1023. * [IN] blendFactors - Specify the new blend factors
  1024. * count - Number of elements in the blend factor array
  1025. *
  1026. * Return Value:
  1027. *
  1028. * Status code
  1029. *
  1030. \**************************************************************************/
  1031. GpStatus
  1032. GpRectGradient::SetHorizontalBlend(
  1033. const REAL* blendFactors,
  1034. const REAL* blendPositions,
  1035. INT count
  1036. )
  1037. {
  1038. if(!blendFactors || !blendPositions || count < 1)
  1039. return InvalidParameter;
  1040. if (count == 1)
  1041. {
  1042. // Setting falloff parameter
  1043. GpFree(DeviceBrush.BlendFactors[0]);
  1044. DeviceBrush.BlendFactors[0] = NULL;
  1045. GpFree(DeviceBrush.BlendPositions[0]);
  1046. DeviceBrush.BlendPositions[0] = NULL;
  1047. if (blendFactors == NULL)
  1048. DeviceBrush.Falloffs[0] = 1;
  1049. else
  1050. DeviceBrush.Falloffs[0] = blendFactors[0];
  1051. DeviceBrush.BlendCounts[0] = 1;
  1052. }
  1053. else
  1054. {
  1055. ASSERT(blendFactors != NULL && blendPositions != NULL);
  1056. // blend positions must start at 0.0 and end at 1.0
  1057. if (REALABS(blendPositions[0]) > REAL_EPSILON ||
  1058. REALABS(1.0f - blendPositions[count-1]) > REAL_EPSILON)
  1059. {
  1060. return InvalidParameter;
  1061. }
  1062. // Setting blend factors
  1063. REAL* newFactors;
  1064. REAL* newPositions;
  1065. newFactors = (REAL*) GpRealloc(DeviceBrush.BlendFactors[0], count*sizeof(REAL));
  1066. if (newFactors != NULL)
  1067. {
  1068. DeviceBrush.BlendFactors[0] = newFactors;
  1069. }
  1070. else
  1071. {
  1072. return OutOfMemory;
  1073. }
  1074. newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[0], count*sizeof(REAL));
  1075. if (newPositions != NULL)
  1076. {
  1077. DeviceBrush.BlendPositions[0] = newPositions;
  1078. }
  1079. else
  1080. {
  1081. return OutOfMemory;
  1082. }
  1083. if (newFactors == NULL || newPositions == NULL)
  1084. return OutOfMemory;
  1085. GpMemcpy(newFactors, blendFactors, count*sizeof(REAL));
  1086. GpMemcpy(newPositions, blendPositions, count*sizeof(REAL));
  1087. DeviceBrush.BlendCounts[0] = count;
  1088. }
  1089. DeviceBrush.UsesPresetColors = FALSE;
  1090. GpFree(DeviceBrush.PresetColors);
  1091. DeviceBrush.PresetColors = NULL;
  1092. UpdateUid();
  1093. return Ok;
  1094. }
  1095. /**************************************************************************\
  1096. *
  1097. * Function Description:
  1098. *
  1099. * Getting vertical falloff / blend-factors for
  1100. * a rectangular gradient brush object
  1101. *
  1102. * Arguments:
  1103. *
  1104. * [OUT] blendFactors - Buffer for returning the vertical
  1105. * falloff or blend-factors.
  1106. * count - Size of the buffer (in number of REAL elements)
  1107. *
  1108. * Return Value:
  1109. *
  1110. * Status code
  1111. *
  1112. \**************************************************************************/
  1113. GpStatus
  1114. GpRectGradient::GetVerticalBlend(
  1115. REAL* blendFactors,
  1116. REAL* blendPositions,
  1117. INT count
  1118. )
  1119. {
  1120. if(!blendFactors || !blendPositions || count < 1)
  1121. return InvalidParameter;
  1122. // Check if the input buffer is big enough
  1123. if (count < DeviceBrush.BlendCounts[1])
  1124. return InsufficientBuffer;
  1125. if (DeviceBrush.BlendCounts[1] == 1)
  1126. {
  1127. // Return falloff parameter
  1128. blendFactors[0] = DeviceBrush.Falloffs[1];
  1129. }
  1130. else
  1131. {
  1132. // Return blend factors
  1133. GpMemcpy(
  1134. blendFactors,
  1135. DeviceBrush.BlendFactors[1],
  1136. DeviceBrush.BlendCounts[1]*sizeof(REAL));
  1137. GpMemcpy(
  1138. blendPositions,
  1139. DeviceBrush.BlendPositions[1],
  1140. DeviceBrush.BlendCounts[1]*sizeof(REAL));
  1141. }
  1142. return Ok;
  1143. }
  1144. /**************************************************************************\
  1145. *
  1146. * Function Description:
  1147. *
  1148. * Setting vertical falloff / blend-factors for
  1149. * a rectangular gradient brush object
  1150. *
  1151. * Arguments:
  1152. *
  1153. * [IN] blendFactors - Specify the new blend factors
  1154. * count - Number of elements in the blend factor array
  1155. *
  1156. * Return Value:
  1157. *
  1158. * Status code
  1159. *
  1160. \**************************************************************************/
  1161. GpStatus
  1162. GpRectGradient::SetVerticalBlend(
  1163. const REAL* blendFactors,
  1164. const REAL* blendPositions,
  1165. INT count
  1166. )
  1167. {
  1168. if(!blendFactors || !blendPositions || count < 1)
  1169. return InvalidParameter;
  1170. if (count == 1)
  1171. {
  1172. // Setting falloff parameter
  1173. GpFree(DeviceBrush.BlendFactors[1]);
  1174. DeviceBrush.BlendFactors[1] = NULL;
  1175. GpFree(DeviceBrush.BlendPositions[1]);
  1176. DeviceBrush.BlendPositions[1] = NULL;
  1177. if (blendFactors == NULL)
  1178. DeviceBrush.Falloffs[1] = 1;
  1179. else
  1180. DeviceBrush.Falloffs[1] = blendFactors[0];
  1181. DeviceBrush.BlendCounts[1] = 1;
  1182. }
  1183. else
  1184. {
  1185. ASSERT(blendFactors != NULL && blendPositions != NULL);
  1186. // Setting blend factors
  1187. REAL* newFactors;
  1188. REAL* newPositions;
  1189. newFactors = (REAL*) GpRealloc(DeviceBrush.BlendFactors[1], count*sizeof(REAL));
  1190. if (newFactors != NULL)
  1191. {
  1192. DeviceBrush.BlendFactors[1] = newFactors;
  1193. }
  1194. else
  1195. {
  1196. return OutOfMemory;
  1197. }
  1198. newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[1], count*sizeof(REAL));
  1199. if (newPositions != NULL)
  1200. {
  1201. DeviceBrush.BlendPositions[1] = newPositions;
  1202. }
  1203. else
  1204. {
  1205. return OutOfMemory;
  1206. }
  1207. GpMemcpy(newFactors, blendFactors, count*sizeof(REAL));
  1208. GpMemcpy(newPositions, blendPositions, count*sizeof(REAL));
  1209. DeviceBrush.BlendCounts[1] = count;
  1210. }
  1211. DeviceBrush.UsesPresetColors = FALSE;
  1212. GpFree(DeviceBrush.PresetColors);
  1213. DeviceBrush.PresetColors = NULL;
  1214. UpdateUid();
  1215. return Ok;
  1216. }
  1217. /**************************************************************************\
  1218. *
  1219. * Function Description:
  1220. *
  1221. * Blend any transparent colors in this brush with white. Note that colors
  1222. * are converted to premultiplied first, since they will become fully opaque.
  1223. *
  1224. * Arguments:
  1225. *
  1226. * Return Value:
  1227. *
  1228. * GpStatus - Ok or failure status
  1229. *
  1230. \**************************************************************************/
  1231. GpStatus GpRectGradient::BlendWithWhite()
  1232. {
  1233. GpColor color;
  1234. for (INT i=0; i<4; i++)
  1235. {
  1236. color.SetValue(DeviceBrush.Colors[i].GetPremultipliedValue());
  1237. color.BlendOpaqueWithWhite();
  1238. DeviceBrush.Colors[i] = color.GetValue();
  1239. }
  1240. return Ok;
  1241. }
  1242. //--------------------------------------------------------------------------
  1243. // Path Gradient
  1244. //--------------------------------------------------------------------------
  1245. VOID
  1246. GpPathGradient::PrepareBrush()
  1247. {
  1248. GpPath* path = static_cast<GpPath*> (DeviceBrush.Path);
  1249. if (path)
  1250. {
  1251. DeviceBrush.Count = path->Points.GetCount();
  1252. GpPointF* points = path->Points.GetDataBuffer();
  1253. if(!DeviceBrush.ColorsPtr)
  1254. {
  1255. DeviceBrush.ColorsPtr = (GpColor*)GpMalloc(DeviceBrush.Count*sizeof(GpColor));
  1256. if (DeviceBrush.ColorsPtr != NULL)
  1257. GpMemset(&DeviceBrush.ColorsPtr[0], 255, DeviceBrush.Count*sizeof(GpColor));
  1258. }
  1259. REAL xmin, xmax, ymin, ymax, x0, y0;
  1260. x0 = xmin = xmax = points[0].X;
  1261. y0 = ymin = ymax = points[0].Y;
  1262. for(INT i = 1; i < DeviceBrush.Count; i++)
  1263. {
  1264. x0 += points[i].X;
  1265. y0 += points[i].Y;
  1266. xmin = min(xmin, points[i].X);
  1267. xmax = max(xmax, points[i].X);
  1268. ymin = min(ymin, points[i].Y);
  1269. ymax = max(ymax, points[i].Y);
  1270. }
  1271. DeviceBrush.Rect.X = xmin;
  1272. DeviceBrush.Rect.Width = xmax - xmin;
  1273. DeviceBrush.Rect.Y = ymin;
  1274. DeviceBrush.Rect.Height = ymax - ymin;
  1275. if(!WrapModeIsValid(DeviceBrush.Wrap) || DeviceBrush.Rect.Width <= 0 || DeviceBrush.Rect.Height <= 0)
  1276. return;
  1277. DeviceBrush.Points[0].X = x0/DeviceBrush.Count;
  1278. DeviceBrush.Points[0].Y = y0/DeviceBrush.Count;
  1279. SetValid(TRUE);
  1280. }
  1281. }
  1282. GpStatus
  1283. GpPathGradient::Flatten(GpMatrix* matrix) const
  1284. {
  1285. GpPath* path = static_cast<GpPath*> (DeviceBrush.Path);
  1286. if(!path)
  1287. return Ok;
  1288. if(path->HasCurve())
  1289. {
  1290. INT origCount = DeviceBrush.Count;
  1291. GpStatus status = path->Flatten(
  1292. const_cast<DynByteArray*>(&FlattenTypes),
  1293. const_cast<DynPointFArray*> (&FlattenPoints),
  1294. matrix);
  1295. if(status == Ok)
  1296. {
  1297. DeviceBrush.Count = FlattenPoints.GetCount();
  1298. DeviceBrush.PointsPtr = FlattenPoints.GetDataBuffer();
  1299. if ((DeviceBrush.Count > origCount) &&
  1300. (DeviceBrush.ColorsPtr != NULL))
  1301. {
  1302. // The colors array is no longer the proper size. Adjust the
  1303. // size and copy up the last color. It is the apps responsibility
  1304. // to estimate and specify the correct number of flattened points.
  1305. const_cast<GpColor*>(DeviceBrush.ColorsPtr) = (GpColor*) GpRealloc((VOID*)DeviceBrush.ColorsPtr,
  1306. sizeof(GpColor)*DeviceBrush.Count);
  1307. if (DeviceBrush.ColorsPtr != NULL)
  1308. {
  1309. GpColor copyColor = (origCount > 1) ?
  1310. DeviceBrush.ColorsPtr[origCount-1] :
  1311. GpColor(0xFFFFFFFF);
  1312. for (INT i=origCount; i<DeviceBrush.Count; i++)
  1313. {
  1314. DeviceBrush.ColorsPtr[i] = copyColor;
  1315. }
  1316. }
  1317. else
  1318. {
  1319. return OutOfMemory;
  1320. }
  1321. }
  1322. }
  1323. }
  1324. else
  1325. {
  1326. DeviceBrush.Count = path->GetPointCount();
  1327. DeviceBrush.PointsPtr = const_cast<GpPointF*> (path->GetPathPoints());
  1328. }
  1329. return Ok;
  1330. }
  1331. GpStatus
  1332. GpPathGradient::GetBlend(
  1333. REAL* blendFactors,
  1334. REAL* blendPositions,
  1335. INT count
  1336. ) const
  1337. {
  1338. if(!blendFactors || !blendPositions || count < 1)
  1339. return InvalidParameter;
  1340. // Check if the input buffer is big enough
  1341. if (count < DeviceBrush.BlendCounts[0])
  1342. return InsufficientBuffer;
  1343. if (DeviceBrush.BlendCounts[0] == 1)
  1344. {
  1345. // Return falloff parameter
  1346. blendFactors[0] = DeviceBrush.Falloffs[0];
  1347. }
  1348. else
  1349. {
  1350. // Return blend factors
  1351. // Users want to obtain the blend factor as radial blend factors.
  1352. // 0 blend factor means 100 % center color and 0 position means
  1353. // the center location. In order to return those factor and
  1354. // position arrays, we must invert the weight and position factor
  1355. // arrays stored in this PathGradient class.
  1356. for(INT i = 0; i < DeviceBrush.BlendCounts[0]; i++)
  1357. {
  1358. blendFactors[DeviceBrush.BlendCounts[0] - 1 - i] = TOREAL(1.0 - DeviceBrush.BlendFactors[0][i]);
  1359. blendPositions[DeviceBrush.BlendCounts[0] - 1 - i] = TOREAL(1.0 - DeviceBrush.BlendPositions[0][i]);
  1360. }
  1361. }
  1362. return Ok;
  1363. }
  1364. GpStatus
  1365. GpPathGradient::SetBlend(
  1366. const REAL* blendFactors,
  1367. const REAL* blendPositions,
  1368. INT count
  1369. )
  1370. {
  1371. if(!blendFactors || !blendPositions || count < 1)
  1372. return InvalidParameter;
  1373. if (count == 1)
  1374. {
  1375. // Setting falloff parameter
  1376. GpFree(DeviceBrush.BlendFactors[0]);
  1377. DeviceBrush.BlendFactors[0] = NULL;
  1378. GpFree(DeviceBrush.BlendPositions[0]);
  1379. DeviceBrush.BlendPositions[0] = NULL;
  1380. if (blendFactors == NULL)
  1381. DeviceBrush.Falloffs[0] = 1;
  1382. else
  1383. DeviceBrush.Falloffs[0] = blendFactors[0];
  1384. DeviceBrush.BlendCounts[0] = 1;
  1385. }
  1386. else
  1387. {
  1388. // blend positions must start at 0.0 and end at 1.0
  1389. if (REALABS(blendPositions[0]) > REAL_EPSILON ||
  1390. REALABS(1.0f - blendPositions[count-1]) > REAL_EPSILON)
  1391. {
  1392. return InvalidParameter;
  1393. }
  1394. // Setting blend factors
  1395. REAL* newFactors;
  1396. REAL* newPositions;
  1397. newFactors = (REAL*) GpRealloc(DeviceBrush.BlendFactors[0], count*sizeof(REAL));
  1398. if (newFactors != NULL)
  1399. {
  1400. DeviceBrush.BlendFactors[0] = newFactors;
  1401. }
  1402. else
  1403. {
  1404. return OutOfMemory;
  1405. }
  1406. newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[0], count*sizeof(REAL));
  1407. if (newPositions != NULL)
  1408. {
  1409. DeviceBrush.BlendPositions[0] = newPositions;
  1410. }
  1411. else
  1412. {
  1413. return OutOfMemory;
  1414. }
  1415. // Users will supply the blend factor as radial blend factors.
  1416. // 0 blend factor means 100 % center color and 0 position means
  1417. // the center location. In order to convert those factor and position arrays
  1418. // to the weight and position factor arrays in PathGradient,
  1419. // we must invert the given arrays.
  1420. for(INT i = 0; i < count; i++)
  1421. {
  1422. newFactors[count - 1 - i] = TOREAL(1.0 - blendFactors[i]);
  1423. newPositions[count - 1 - i] = TOREAL(1.0 - blendPositions[i]);
  1424. }
  1425. DeviceBrush.BlendCounts[0] = count;
  1426. }
  1427. DeviceBrush.UsesPresetColors = FALSE;
  1428. GpFree(DeviceBrush.PresetColors);
  1429. DeviceBrush.PresetColors = NULL;
  1430. UpdateUid();
  1431. return Ok;
  1432. }
  1433. GpStatus
  1434. GpGradientBrush::GetSigmaBlendArray(
  1435. REAL focus,
  1436. REAL scale,
  1437. INT* count,
  1438. REAL* blendFactors,
  1439. REAL* blendPositions)
  1440. {
  1441. // Make sure the FPU is set correctly.
  1442. FPUStateSaver::AssertMode();
  1443. if(!blendFactors || !blendPositions || !count)
  1444. return InvalidParameter;
  1445. // This gives 1/4 of the Sigma array.
  1446. static REAL factors[] =
  1447. {
  1448. 0, 59, 120, 182, 247, 314, 383, 454,
  1449. 527, 602, 680, 759, 841, 926, 1013, 1102,
  1450. 1194, 1288, 1385, 1485, 1587, 1692, 1800, 1911,
  1451. 2024, 2141, 2260, 2383, 2508, 2637, 2769, 2904,
  1452. 3042, 3183, 3328, 3477, 3628, 3783, 3942, 4104,
  1453. 4270, 4439, 4612, 4789, 4969, 5153, 5341, 5533,
  1454. 5728, 5928, 6131, 6338, 6549, 6764, 6983, 7206,
  1455. 7434, 7665, 7900, 8139, 8382, 8630, 8881, 9136,
  1456. 9396, 9660, 9927, 10199, 10475, 10755, 11039, 11327,
  1457. 11619, 11916, 12216, 12520, 12828, 13140, 13456, 13776,
  1458. 14099, 14427, 14758, 15093, 15431, 15774, 16119, 16469,
  1459. 16822, 17178, 17538, 17901, 18267, 18637, 19009, 19385,
  1460. 19764, 20146, 20530, 20918, 21308, 21701, 22096, 22494,
  1461. 22894, 23297, 23702, 24109, 24518, 24929, 25342, 25756,
  1462. 26173, 26591, 27010, 27431, 27853, 28276, 28701, 29126,
  1463. 29552, 29979, 30407, 30836, 31264, 31694, 32123, 32553
  1464. };
  1465. if(focus < 0 || focus > 1 || scale < 0 || scale > 1)
  1466. return InvalidParameter;
  1467. if(blendFactors && blendPositions)
  1468. {
  1469. INT i, n;
  1470. scale /= 65536;
  1471. REAL one = 65536;
  1472. if(focus > 0 && focus < 1)
  1473. {
  1474. for(i = 0; i < 128; i++)
  1475. {
  1476. blendFactors[i] = factors[i];
  1477. blendPositions[i] = focus*i/255;
  1478. }
  1479. for(i = 128; i < 256; i++)
  1480. {
  1481. blendFactors[i] = one - factors[255 - i];
  1482. blendPositions[i] = focus*i/255;
  1483. }
  1484. // skip i = 256 since this gives the same data.
  1485. for(i = 257; i < 384; i++)
  1486. {
  1487. blendFactors[i - 1] = one - factors[i - 256];
  1488. blendPositions[i - 1] = TOREAL(focus + (1.0 - focus)*(i - 256)/255);
  1489. }
  1490. for(i = 384; i < 512; i++)
  1491. {
  1492. blendFactors[i - 1] = factors[511 - i];
  1493. blendPositions[i - 1] = TOREAL(focus + (1.0 - focus)*(i - 256)/255);
  1494. }
  1495. // Set n to 511 because we skipped index 256 above to avoid
  1496. // the duplicate 1 entry in the ramp from 0 to 1 to 0.
  1497. n = 511;
  1498. }
  1499. else if(focus == 1)
  1500. {
  1501. for(i = 0; i < 128; i++)
  1502. {
  1503. blendFactors[i] = factors[i];
  1504. blendPositions[i] = TOREAL(i)/255;
  1505. }
  1506. for(i = 128; i < 256; i++)
  1507. {
  1508. blendFactors[i] = one - factors[255 - i];
  1509. blendPositions[i] = TOREAL(i)/255;
  1510. }
  1511. n = 256;
  1512. }
  1513. else // focus == 0
  1514. {
  1515. for(i = 256; i < 384; i++)
  1516. {
  1517. blendFactors[i - 256] = one - factors[i - 256];
  1518. blendPositions[i - 256] = TOREAL(i - 256)/255;
  1519. }
  1520. for(i = 384; i < 512; i++)
  1521. {
  1522. blendFactors[i - 256] = factors[511 - i];
  1523. blendPositions[i - 256] = TOREAL(i - 256)/255;
  1524. }
  1525. n = 256;
  1526. }
  1527. for(i = 0; i < n; i++)
  1528. blendFactors[i] *= scale;
  1529. *count = n;
  1530. return Ok;
  1531. }
  1532. else
  1533. return InvalidParameter;
  1534. }
  1535. GpStatus
  1536. GpGradientBrush::GetLinearBlendArray(
  1537. REAL focus,
  1538. REAL scale,
  1539. INT* count,
  1540. REAL* blendFactors,
  1541. REAL* blendPositions)
  1542. {
  1543. if(!blendFactors || !blendPositions || !count)
  1544. return InvalidParameter;
  1545. if(focus < 0 || focus > 1 || scale < 0 || scale > 1)
  1546. return InvalidParameter;
  1547. if(blendFactors && blendPositions)
  1548. {
  1549. if(focus > 0 && focus < 1)
  1550. {
  1551. blendFactors[0] = 0.0f;
  1552. blendFactors[1] = scale;
  1553. blendFactors[2] = 0.0f;
  1554. blendPositions[0] = 0.0f;
  1555. blendPositions[1] = focus;
  1556. blendPositions[2] = 1.0f;
  1557. *count = 3;
  1558. }
  1559. else if(focus == 1)
  1560. {
  1561. blendFactors[0] = 0.0f;
  1562. blendFactors[1] = scale;
  1563. blendPositions[0] = 0.0f;
  1564. blendPositions[1] = 1.0f;
  1565. *count = 2;
  1566. }
  1567. else // focus == 0
  1568. {
  1569. blendFactors[0] = scale;
  1570. blendFactors[1] = 0.0f;
  1571. blendPositions[0] = 0.0f;
  1572. blendPositions[1] = 1.0f;
  1573. *count = 2;
  1574. }
  1575. return Ok;
  1576. }
  1577. else
  1578. return InvalidParameter;
  1579. }
  1580. GpStatus
  1581. GpGradientBrush::SetSigmaBlend(
  1582. REAL focus,
  1583. REAL scale)
  1584. {
  1585. REAL* blendFactors = (REAL*) GpMalloc(512*sizeof(REAL));
  1586. REAL* blendPositions = (REAL*) GpMalloc(512*sizeof(REAL));
  1587. INT count;
  1588. GpStatus status;
  1589. if(blendFactors && blendPositions)
  1590. {
  1591. status = GetSigmaBlendArray(focus, scale,
  1592. &count, blendFactors, blendPositions);
  1593. if(status == Ok)
  1594. status = SetBlend(&blendFactors[0], &blendPositions[0], count);
  1595. }
  1596. else
  1597. status = OutOfMemory;
  1598. GpFree(blendFactors);
  1599. GpFree(blendPositions);
  1600. return status;
  1601. }
  1602. GpStatus
  1603. GpGradientBrush::SetLinearBlend(
  1604. REAL focus,
  1605. REAL scale)
  1606. {
  1607. REAL blendFactors[3];
  1608. REAL blendPositions[3];
  1609. INT count;
  1610. GpStatus status = GetLinearBlendArray(focus, scale,
  1611. &count, &blendFactors[0], &blendPositions[0]);
  1612. if(status != Ok)
  1613. return status;
  1614. return SetBlend(&blendFactors[0], &blendPositions[0], count);
  1615. }
  1616. //--------------------------------------------------------------------------
  1617. // Hatch Brush
  1618. //--------------------------------------------------------------------------
  1619. const BYTE GdipHatchPatterns8bpp[HatchStyleTotal][64] = {
  1620. { // HatchStyleHorizontal, 0
  1621. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1622. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1623. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1624. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1625. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1626. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1627. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1628. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1629. },
  1630. { // HatchStyleVertical, 1
  1631. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1632. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1633. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1634. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1635. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1636. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1637. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1638. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1639. },
  1640. { // HatchStyleForwardDiagonal, 2
  1641. 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
  1642. 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
  1643. 0x00, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
  1644. 0x00, 0x00, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00,
  1645. 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x00, 0x00,
  1646. 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x00,
  1647. 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80,
  1648. 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
  1649. },
  1650. { // HatchStyleBackwardDiagonal, 3
  1651. 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
  1652. 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80,
  1653. 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x00,
  1654. 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x00, 0x00,
  1655. 0x00, 0x00, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00,
  1656. 0x00, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
  1657. 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
  1658. 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
  1659. },
  1660. { // HatchStyleCross, 4
  1661. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1662. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1663. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1664. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1665. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1666. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1667. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1668. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1669. },
  1670. { // HatchStyleDiagonalCross 5
  1671. 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
  1672. 0x80, 0xff, 0x80, 0x00, 0x00, 0x80, 0xff, 0x80,
  1673. 0x00, 0x80, 0xff, 0x80, 0x80, 0xff, 0x80, 0x00,
  1674. 0x00, 0x00, 0x80, 0xff, 0xff, 0x80, 0x00, 0x00,
  1675. 0x00, 0x00, 0x80, 0xff, 0xff, 0x80, 0x00, 0x00,
  1676. 0x00, 0x80, 0xff, 0x80, 0x80, 0xff, 0x80, 0x00,
  1677. 0x80, 0xff, 0x80, 0x00, 0x00, 0x80, 0xff, 0x80,
  1678. 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
  1679. },
  1680. { // HatchStyle05Percent, 6
  1681. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1682. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1683. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1684. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1685. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1686. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1687. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1688. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1689. },
  1690. { // HatchStyle10Percent, 7
  1691. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1692. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1693. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1694. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1695. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1696. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1697. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1698. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1699. },
  1700. { // HatchStyle20Percent, 8
  1701. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1702. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1703. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
  1704. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1705. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1706. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1707. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
  1708. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1709. },
  1710. { // HatchStyle25Percent, 9
  1711. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1712. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
  1713. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1714. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
  1715. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1716. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
  1717. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1718. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
  1719. },
  1720. { // HatchStyle30Percent, 10
  1721. 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
  1722. 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  1723. 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
  1724. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
  1725. 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
  1726. 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  1727. 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
  1728. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
  1729. },
  1730. { // HatchStyle40Percent, 11
  1731. 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
  1732. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1733. 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
  1734. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
  1735. 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
  1736. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1737. 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
  1738. 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1739. },
  1740. { // HatchStyle50Percent, 12
  1741. 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
  1742. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1743. 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
  1744. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1745. 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
  1746. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1747. 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
  1748. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1749. },
  1750. { // HatchStyle60Percent, 13
  1751. 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
  1752. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1753. 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff,
  1754. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1755. 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
  1756. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1757. 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff,
  1758. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1759. },
  1760. { // HatchStyle70Percent, 14
  1761. 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff,
  1762. 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
  1763. 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff,
  1764. 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
  1765. 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff,
  1766. 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
  1767. 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff,
  1768. 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
  1769. },
  1770. { // HatchStyle75Percent, 15
  1771. 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff,
  1772. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1773. 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
  1774. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1775. 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff,
  1776. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1777. 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
  1778. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1779. },
  1780. { // HatchStyle80Percent, 16
  1781. 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff,
  1782. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1783. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
  1784. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1785. 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff,
  1786. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1787. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
  1788. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1789. },
  1790. { // HatchStyle90Percent, 17
  1791. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1792. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1793. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1794. 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff,
  1795. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1796. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1797. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1798. 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1799. },
  1800. { // HatchStyleLightDownwardDiagonal, 18
  1801. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1802. 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  1803. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
  1804. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
  1805. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1806. 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  1807. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
  1808. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
  1809. },
  1810. { // HatchStyleLightUpwardDiagonal, 19
  1811. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
  1812. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
  1813. 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  1814. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1815. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
  1816. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
  1817. 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  1818. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1819. },
  1820. { // HatchStyleDarkDownwardDiagonal, 20
  1821. 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  1822. 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
  1823. 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
  1824. 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
  1825. 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  1826. 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
  1827. 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
  1828. 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
  1829. },
  1830. { // HatchStyleDarkUpwardDiagonal, 21
  1831. 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
  1832. 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
  1833. 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  1834. 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
  1835. 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
  1836. 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
  1837. 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  1838. 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
  1839. },
  1840. { // HatchStyleWideDownwardDiagonal, 22
  1841. 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  1842. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
  1843. 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  1844. 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  1845. 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
  1846. 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00,
  1847. 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
  1848. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
  1849. },
  1850. { // HatchStyleWideUpwardDiagonal, 23
  1851. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
  1852. 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
  1853. 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00,
  1854. 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
  1855. 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  1856. 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  1857. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
  1858. 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  1859. },
  1860. { // HatchStyleLightVertical, 24
  1861. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1862. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1863. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1864. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1865. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1866. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1867. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1868. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1869. },
  1870. { // HatchStyleLightHorizontal, 25
  1871. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1872. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1873. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1874. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1875. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1876. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1877. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1878. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1879. },
  1880. { // HatchStyleNarrowVertical, 26
  1881. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1882. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1883. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1884. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1885. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1886. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1887. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1888. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1889. },
  1890. { // HatchStyleNarrowHorizontal, 27
  1891. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1892. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1893. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1894. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1895. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1896. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1897. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1898. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1899. },
  1900. { // HatchStyleDarkVertical, 28
  1901. 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  1902. 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  1903. 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  1904. 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  1905. 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  1906. 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  1907. 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  1908. 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  1909. },
  1910. { // HatchStyleDarkHorizontal, 29
  1911. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1912. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1913. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1914. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1915. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1916. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1917. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1918. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1919. },
  1920. { // HatchStyleDashedDownwardDiagonal, 30
  1921. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1922. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1923. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1924. 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  1925. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
  1926. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
  1927. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1928. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1929. },
  1930. { // HatchStyleDashedUpwardDiagonal, 31
  1931. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1932. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1933. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
  1934. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
  1935. 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  1936. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1937. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1938. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1939. },
  1940. { // HatchStyleDashedHorizontal, 32
  1941. 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  1942. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1943. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1944. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1945. 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  1946. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1947. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1948. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1949. },
  1950. { // HatchStyleDashedVertical, 33
  1951. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1952. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1953. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1954. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1955. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1956. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1957. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1958. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1959. },
  1960. { // HatchStyleSmallConfetti, 34
  1961. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1962. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  1963. 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1964. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  1965. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
  1966. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  1967. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
  1968. 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  1969. },
  1970. { // HatchStyleLargeConfetti, 35
  1971. 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff,
  1972. 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  1973. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
  1974. 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff,
  1975. 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
  1976. 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1977. 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  1978. 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff,
  1979. },
  1980. { // HatchStyleZigZag, 36
  1981. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  1982. 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  1983. 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
  1984. 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
  1985. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  1986. 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  1987. 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
  1988. 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
  1989. },
  1990. { // HatchStyleWave, 37
  1991. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1992. 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
  1993. 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff,
  1994. 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1995. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1996. 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
  1997. 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff,
  1998. 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1999. },
  2000. { // HatchStyleDiagonalBrick, 38
  2001. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  2002. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  2003. 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  2004. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  2005. 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
  2006. 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
  2007. 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  2008. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  2009. },
  2010. { // HatchStyleHorizontalBrick, 39
  2011. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  2012. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2013. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2014. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2015. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  2016. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  2017. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  2018. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  2019. },
  2020. { // HatchStyleWeave, 40
  2021. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  2022. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
  2023. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
  2024. 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
  2025. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  2026. 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
  2027. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
  2028. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
  2029. },
  2030. { // HatchStylePlaid, 41
  2031. 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
  2032. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  2033. 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
  2034. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  2035. 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  2036. 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  2037. 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  2038. 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  2039. },
  2040. { // HatchStyleDivot, 42
  2041. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2042. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
  2043. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  2044. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
  2045. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2046. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2047. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  2048. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2049. },
  2050. { // HatchStyleDottedGrid, 43
  2051. 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
  2052. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2053. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2054. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2055. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2056. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2057. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2058. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2059. },
  2060. { // HatchStyleDottedDiamond, 44
  2061. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2062. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2063. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
  2064. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2065. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  2066. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2067. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
  2068. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2069. },
  2070. { // HatchStyleShingle, 45
  2071. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
  2072. 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  2073. 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  2074. 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  2075. 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  2076. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  2077. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  2078. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  2079. },
  2080. { // HatchStyleTrellis, 46
  2081. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  2082. 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
  2083. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  2084. 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
  2085. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  2086. 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
  2087. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  2088. 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
  2089. },
  2090. { // HatchStyleSphere, 47
  2091. 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff,
  2092. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  2093. 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  2094. 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  2095. 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff,
  2096. 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
  2097. 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  2098. 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  2099. },
  2100. { // HatchStyleSmallGrid, 48
  2101. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  2102. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  2103. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  2104. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  2105. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  2106. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  2107. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  2108. 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
  2109. },
  2110. { // HatchStyleSmallCheckerBoard, 49
  2111. 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
  2112. 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
  2113. 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
  2114. 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
  2115. 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
  2116. 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
  2117. 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
  2118. 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
  2119. },
  2120. { // HatchStyleLargeCheckerBoard, 50
  2121. 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  2122. 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  2123. 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  2124. 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  2125. 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  2126. 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  2127. 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  2128. 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  2129. },
  2130. { // HatchStyleOutlinedDiamond, 51
  2131. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  2132. 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  2133. 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
  2134. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
  2135. 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
  2136. 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  2137. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  2138. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  2139. },
  2140. { // HatchStyleSolidDiamond, 52
  2141. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
  2142. 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  2143. 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
  2144. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
  2145. 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
  2146. 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  2147. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
  2148. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2149. },
  2150. };
  2151. VOID
  2152. GpHatch::InitializeData()
  2153. {
  2154. if ((DeviceBrush.Style >= HatchStyleMin) &&
  2155. (DeviceBrush.Style <= HatchStyleMax))
  2156. {
  2157. GpMemcpy(DeviceBrush.Data, GdipHatchPatterns8bpp[DeviceBrush.Style], 64);
  2158. }
  2159. else
  2160. {
  2161. WARNING1("Bad Hatch Style Value");
  2162. GpMemset(DeviceBrush.Data, 0x00, 64); // make it transparent
  2163. }
  2164. }
  2165. /***************************************************************************\
  2166. *
  2167. * Equivalence comparsion functions
  2168. *
  2169. \***************************************************************************/
  2170. /**************************************************************************\
  2171. *
  2172. * Function Description:
  2173. *
  2174. * Answer TRUE if brush and the receiver are equivalent (i.e. - they will
  2175. * render indentically)
  2176. *
  2177. * Arguments:
  2178. *
  2179. * [IN] brush - GpBrush, or subclass, to compare this against.
  2180. *
  2181. * Return Value:
  2182. *
  2183. * TRUE if equivalent
  2184. *
  2185. * Created - 5/28/99 peterost
  2186. *
  2187. \**************************************************************************/
  2188. BOOL
  2189. GpHatch::IsEqual(const GpBrush * brush) const
  2190. {
  2191. if(!brush)
  2192. return FALSE;
  2193. if (brush == this)
  2194. return TRUE;
  2195. if (GpBrush::IsEqual(brush))
  2196. {
  2197. const GpHatch * hbrush = static_cast<const GpHatch *>(brush);
  2198. return hbrush->DeviceBrush.Style == DeviceBrush.Style &&
  2199. hbrush->DeviceBrush.Colors[0].IsEqual(DeviceBrush.Colors[0]) &&
  2200. hbrush->DeviceBrush.Colors[1].IsEqual(DeviceBrush.Colors[1]);
  2201. }
  2202. else
  2203. {
  2204. return FALSE;
  2205. }
  2206. }
  2207. /**************************************************************************\
  2208. *
  2209. * Function Description:
  2210. *
  2211. * Answer TRUE if brush and the receiver are equivalent (i.e. - they will
  2212. * render indentically). RectGradient brushes require all four colors and
  2213. * blend factors to be equal.
  2214. *
  2215. * Arguments:
  2216. *
  2217. * [IN] brush - GpBrush, or subclass, to compare this against.
  2218. *
  2219. * Return Value:
  2220. *
  2221. * TRUE if equivalent
  2222. *
  2223. * Created - 5/28/99 peterost
  2224. *
  2225. \**************************************************************************/
  2226. BOOL
  2227. GpRectGradient::IsEqual(const GpBrush * brush) const
  2228. {
  2229. if(!brush)
  2230. return FALSE;
  2231. if (brush == this)
  2232. return TRUE;
  2233. if (GpGradientBrush::IsEqual(brush))
  2234. {
  2235. const GpRectGradient * rbrush = static_cast<const GpRectGradient *>(brush);
  2236. if (rbrush->DeviceBrush.UsesPresetColors == DeviceBrush.UsesPresetColors &&
  2237. rbrush->DeviceBrush.BlendCounts[0] == DeviceBrush.BlendCounts[0] &&
  2238. rbrush->DeviceBrush.BlendCounts[1] == DeviceBrush.BlendCounts[1])
  2239. {
  2240. INT i;
  2241. if (DeviceBrush.UsesPresetColors)
  2242. {
  2243. // For preset colors, only the horizontal blend variables are used.
  2244. for (INT i=0; i<DeviceBrush.BlendCounts[0]; i++)
  2245. {
  2246. if (rbrush->DeviceBrush.PresetColors[i] != DeviceBrush.PresetColors[i] ||
  2247. rbrush->DeviceBrush.BlendPositions[0][i] != DeviceBrush.BlendPositions[0][i])
  2248. return FALSE;
  2249. }
  2250. }
  2251. else
  2252. {
  2253. for (i=0; i<4; i++)
  2254. {
  2255. if (!rbrush->DeviceBrush.Colors[i].IsEqual(DeviceBrush.Colors[i]))
  2256. return FALSE;
  2257. }
  2258. if (DeviceBrush.BlendCounts[0] > 1)
  2259. {
  2260. for (i=0; i<DeviceBrush.BlendCounts[0]; i++)
  2261. {
  2262. if (rbrush->DeviceBrush.BlendFactors[0][i] != DeviceBrush.BlendFactors[0][i] ||
  2263. rbrush->DeviceBrush.BlendPositions[0][i] != DeviceBrush.BlendPositions[0][i])
  2264. return FALSE;
  2265. }
  2266. }
  2267. else if (rbrush->DeviceBrush.Falloffs[0] != DeviceBrush.Falloffs[0])
  2268. {
  2269. return FALSE;
  2270. }
  2271. if (DeviceBrush.BlendCounts[1] > 1)
  2272. {
  2273. for (i=0; i<DeviceBrush.BlendCounts[1]; i++)
  2274. {
  2275. if (rbrush->DeviceBrush.BlendFactors[1][i] != DeviceBrush.BlendFactors[1][i] ||
  2276. rbrush->DeviceBrush.BlendPositions[1][i] != DeviceBrush.BlendPositions[1][i])
  2277. return FALSE;
  2278. }
  2279. }
  2280. else if (rbrush->DeviceBrush.Falloffs[1] != DeviceBrush.Falloffs[1])
  2281. {
  2282. return FALSE;
  2283. }
  2284. }
  2285. return TRUE;
  2286. }
  2287. else
  2288. {
  2289. return FALSE;
  2290. }
  2291. }
  2292. else
  2293. {
  2294. return FALSE;
  2295. }
  2296. }
  2297. /**************************************************************************\
  2298. *
  2299. * Function Description:
  2300. *
  2301. * Answer TRUE if brush and the receiver are equivalent (i.e. - they will
  2302. * render indentically).
  2303. *
  2304. * Arguments:
  2305. *
  2306. * [IN] brush - GpBrush, or subclass, to compare this against.
  2307. *
  2308. * Return Value:
  2309. *
  2310. * TRUE if equivalent
  2311. *
  2312. * Created - 6/2/99 peterost
  2313. *
  2314. \**************************************************************************/
  2315. #if 0
  2316. BOOL
  2317. GpRadialGradient::IsEqual(const GpBrush * brush) const
  2318. {
  2319. if(!brush)
  2320. return FALSE;
  2321. if (brush == this)
  2322. return TRUE;
  2323. if (GpGradientBrush::IsEqual(brush))
  2324. {
  2325. const GpRadialGradient * rbrush = static_cast<const GpRadialGradient *>(brush);
  2326. if (rbrush->DeviceBrush.UsesPresetColors == DeviceBrush.UsesPresetColors &&
  2327. rbrush->DeviceBrush.BlendCounts[0] == DeviceBrush.BlendCounts[0])
  2328. {
  2329. if (DeviceBrush.UsesPresetColors)
  2330. {
  2331. for (INT i=0; i<DeviceBrush.BlendCounts[0]; i++)
  2332. {
  2333. if (rbrush->DeviceBrush.PresetColors[i] != DeviceBrush.PresetColors[i] ||
  2334. rbrush->DeviceBrush.BlendPositions[0][i] != DeviceBrush.BlendPositions[0][i])
  2335. return FALSE;
  2336. }
  2337. }
  2338. else
  2339. {
  2340. if (rbrush->DeviceBrush.Colors[0].IsEqual(DeviceBrush.Colors[0]) &&
  2341. rbrush->DeviceBrush.Colors[1].IsEqual(DeviceBrush.Colors[1]))
  2342. {
  2343. if (DeviceBrush.BlendCounts[0] > 1)
  2344. {
  2345. for (INT i=0; i<DeviceBrush.BlendCounts[0]; i++)
  2346. {
  2347. if (rbrush->DeviceBrush.BlendFactors[0][i] != DeviceBrush.BlendFactors[0][i] ||
  2348. rbrush->DeviceBrush.BlendPositions[0][i] != DeviceBrush.BlendPositions[0][i])
  2349. return FALSE;
  2350. }
  2351. }
  2352. else if (rbrush->DeviceBrush.Falloffs[0] != DeviceBrush.Falloffs[0])
  2353. {
  2354. return FALSE;
  2355. }
  2356. }
  2357. else
  2358. {
  2359. return FALSE;
  2360. }
  2361. }
  2362. return TRUE;
  2363. }
  2364. else
  2365. {
  2366. return FALSE;
  2367. }
  2368. }
  2369. else
  2370. {
  2371. return FALSE;
  2372. }
  2373. }
  2374. /**************************************************************************\
  2375. *
  2376. * Function Description:
  2377. *
  2378. * Answer TRUE if brush and the receiver are equivalent (i.e. - they will
  2379. * render indentically).
  2380. *
  2381. * Arguments:
  2382. *
  2383. * [IN] brush - GpBrush, or subclass, to compare this against.
  2384. *
  2385. * Return Value:
  2386. *
  2387. * TRUE if equivalent
  2388. *
  2389. * Created - 6/7/99 peterost
  2390. *
  2391. \**************************************************************************/
  2392. BOOL
  2393. GpTriangleGradient::IsEqual(const GpBrush * brush) const
  2394. {
  2395. if(!brush)
  2396. return FALSE;
  2397. if (brush == this)
  2398. return TRUE;
  2399. if (GpGradientBrush::IsEqual(brush))
  2400. {
  2401. const GpTriangleGradient * tbrush = static_cast<const GpTriangleGradient *>(brush);
  2402. if (tbrush->DeviceBrush.BlendCounts[0] == DeviceBrush.BlendCounts[0] &&
  2403. tbrush->DeviceBrush.BlendCounts[1] == DeviceBrush.BlendCounts[1] &&
  2404. tbrush->DeviceBrush.BlendCounts[2] == DeviceBrush.BlendCounts[2] &&
  2405. tbrush->DeviceBrush.Rect.Equals(DeviceBrush.Rect))
  2406. {
  2407. INT i;
  2408. for (i=0; i<3; i++)
  2409. {
  2410. if (tbrush->DeviceBrush.Points[i].X != DeviceBrush.Points[i].X ||
  2411. tbrush->DeviceBrush.Points[i].Y != DeviceBrush.Points[i].Y ||
  2412. !(tbrush->DeviceBrush.Colors[i].IsEqual(DeviceBrush.Colors[i])))
  2413. return FALSE;
  2414. }
  2415. if (DeviceBrush.BlendCounts[0] > 1)
  2416. {
  2417. for (i=0; i<DeviceBrush.BlendCounts[0]; i++)
  2418. {
  2419. if (tbrush->DeviceBrush.BlendFactors[0][i] != DeviceBrush.BlendFactors[0][i] ||
  2420. tbrush->DeviceBrush.BlendPositions[0][i] != DeviceBrush.BlendPositions[0][i])
  2421. return FALSE;
  2422. }
  2423. }
  2424. else if (tbrush->DeviceBrush.Falloffs[0] != DeviceBrush.Falloffs[0])
  2425. {
  2426. return FALSE;
  2427. }
  2428. if (DeviceBrush.BlendCounts[1] > 1)
  2429. {
  2430. for (i=0; i<DeviceBrush.BlendCounts[1]; i++)
  2431. {
  2432. if (tbrush->DeviceBrush.BlendFactors[1][i] != DeviceBrush.BlendFactors[1][i] ||
  2433. tbrush->DeviceBrush.BlendPositions[1][i] != DeviceBrush.BlendPositions[1][i])
  2434. return FALSE;
  2435. }
  2436. }
  2437. else if (tbrush->DeviceBrush.Falloffs[1] != DeviceBrush.Falloffs[1])
  2438. {
  2439. return FALSE;
  2440. }
  2441. if (DeviceBrush.BlendCounts[2] > 1)
  2442. {
  2443. for (i=0; i<DeviceBrush.BlendCounts[2]; i++)
  2444. {
  2445. if (tbrush->DeviceBrush.BlendFactors[2][i] != DeviceBrush.BlendFactors[2][i] ||
  2446. tbrush->DeviceBrush.BlendPositions[2][i] != DeviceBrush.BlendPositions[2][i])
  2447. return FALSE;
  2448. }
  2449. }
  2450. else if (tbrush->DeviceBrush.Falloffs[2] != DeviceBrush.Falloffs[2])
  2451. {
  2452. return FALSE;
  2453. }
  2454. return TRUE;
  2455. }
  2456. else
  2457. {
  2458. return FALSE;
  2459. }
  2460. }
  2461. else
  2462. {
  2463. return FALSE;
  2464. }
  2465. }
  2466. #endif
  2467. /**************************************************************************\
  2468. *
  2469. * Function Description:
  2470. *
  2471. * Answer TRUE if brush and the receiver are equivalent (i.e. - they will
  2472. * render indentically).
  2473. *
  2474. * Arguments:
  2475. *
  2476. * [IN] brush - GpBrush, or subclass, to compare this against.
  2477. *
  2478. * Return Value:
  2479. *
  2480. * TRUE if equivalent
  2481. *
  2482. * Created - 6/7/99 peterost
  2483. *
  2484. \**************************************************************************/
  2485. BOOL
  2486. GpPathGradient::IsEqual(const GpBrush * brush) const
  2487. {
  2488. if(!brush)
  2489. return FALSE;
  2490. if (brush == this)
  2491. return TRUE;
  2492. if (GpGradientBrush::IsEqual(brush))
  2493. {
  2494. const GpPathGradient * pbrush = static_cast<const GpPathGradient *>(brush);
  2495. if (pbrush->DeviceBrush.BlendCounts[0] == DeviceBrush.BlendCounts[0] &&
  2496. pbrush->DeviceBrush.Count == DeviceBrush.Count &&
  2497. pbrush->DeviceBrush.OneSurroundColor == DeviceBrush.OneSurroundColor &&
  2498. pbrush->DeviceBrush.UsesPresetColors == DeviceBrush.UsesPresetColors &&
  2499. pbrush->DeviceBrush.Points[0].X == DeviceBrush.Points[0].X &&
  2500. pbrush->DeviceBrush.Points[0].Y == DeviceBrush.Points[0].Y &&
  2501. pbrush->DeviceBrush.Rect.Equals(DeviceBrush.Rect) &&
  2502. pbrush->DeviceBrush.Colors[0].IsEqual(DeviceBrush.Colors[0])
  2503. )
  2504. {
  2505. INT i;
  2506. for (i=0; i<DeviceBrush.Count; i++)
  2507. {
  2508. if (pbrush->DeviceBrush.PointsPtr[i].X != DeviceBrush.PointsPtr[i].X ||
  2509. pbrush->DeviceBrush.PointsPtr[i].Y != DeviceBrush.PointsPtr[i].Y ||
  2510. !(pbrush->DeviceBrush.ColorsPtr[i].IsEqual(DeviceBrush.ColorsPtr[i])))
  2511. return FALSE;
  2512. }
  2513. if (DeviceBrush.UsesPresetColors)
  2514. {
  2515. for (i=0; i<DeviceBrush.BlendCounts[0]; i++)
  2516. {
  2517. if (pbrush->DeviceBrush.PresetColors[i] != DeviceBrush.PresetColors[i] ||
  2518. pbrush->DeviceBrush.BlendPositions[0][i] != DeviceBrush.BlendPositions[0][i])
  2519. return FALSE;
  2520. }
  2521. }
  2522. else
  2523. {
  2524. if (DeviceBrush.BlendCounts[0] > 1)
  2525. {
  2526. for (i=0; i<DeviceBrush.BlendCounts[0]; i++)
  2527. {
  2528. if (pbrush->DeviceBrush.BlendFactors[0][i] != DeviceBrush.BlendFactors[0][i] ||
  2529. pbrush->DeviceBrush.BlendPositions[0][i] != DeviceBrush.BlendPositions[0][i])
  2530. return FALSE;
  2531. }
  2532. }
  2533. else if (pbrush->DeviceBrush.Falloffs[0] != DeviceBrush.Falloffs[0])
  2534. {
  2535. return FALSE;
  2536. }
  2537. }
  2538. }
  2539. return TRUE;
  2540. }
  2541. else
  2542. {
  2543. return FALSE;
  2544. }
  2545. }
  2546. DpOutputSpan*
  2547. GpSolidFill::CreateOutputSpan(
  2548. DpScanBuffer * scan,
  2549. DpContext *context,
  2550. const GpRect *drawBounds)
  2551. {
  2552. return new DpOutputSolidColorSpan(
  2553. DeviceBrush.SolidColor.GetPremultipliedValue(),
  2554. scan
  2555. );
  2556. }
  2557. DpOutputSpan*
  2558. GpRectGradient::CreateOutputSpan(
  2559. DpScanBuffer * scan,
  2560. DpContext *context,
  2561. const GpRect *drawBounds)
  2562. {
  2563. DpOutputSpan* span = NULL;
  2564. ARGB argb[4];
  2565. for(INT i = 0; i < 4; i++)
  2566. {
  2567. argb[i] = DeviceBrush.Colors[i].GetValue();
  2568. }
  2569. BOOL isHorizontal = FALSE;
  2570. BOOL isVertical = FALSE;
  2571. if(HasPresetColors() && DeviceBrush.BlendCounts[0] > 1)
  2572. isHorizontal = TRUE;
  2573. if(!isHorizontal && argb[0] == argb[2] && argb[1] == argb[3])
  2574. isHorizontal = TRUE;
  2575. if(!isHorizontal && argb[0] == argb[1] && argb[2] == argb[3])
  2576. isVertical = TRUE;
  2577. if(!isHorizontal && !isVertical)
  2578. {
  2579. span = new DpOutputGradientSpan(this, scan, context);
  2580. }
  2581. else
  2582. {
  2583. // !!![andrewgo] Not sure why a LinearGradient is coming down to us
  2584. // as BrushRectGrad - if it comes down as a BrushTypeLinearGradient
  2585. // (as it should) then we don't have to do any of the
  2586. // above 'isHorizontal', 'isVertical' stuff
  2587. FPUStateSaver fpuState; // Set the rounding mode.
  2588. if ((GetBrushType() == BrushTypeLinearGradient) /*|| (GetBrushType() == BrushRectGrad)*/)
  2589. {
  2590. if (OSInfo::HasMMX)
  2591. {
  2592. span = new DpOutputLinearGradientSpan_MMX(this, scan, context);
  2593. }
  2594. else
  2595. {
  2596. span = new DpOutputLinearGradientSpan(this, scan, context);
  2597. }
  2598. }
  2599. else
  2600. {
  2601. span = new DpOutputOneDGradientSpan(this, scan, context,
  2602. isHorizontal, isVertical);
  2603. }
  2604. }
  2605. if (span && !span->IsValid())
  2606. {
  2607. delete span;
  2608. span = NULL;
  2609. }
  2610. return span;
  2611. }
  2612. #if 0
  2613. DpOutputSpan*
  2614. GpRadialGradient::CreateOutputSpan(
  2615. DpScanBuffer * scan,
  2616. DpContext *context,
  2617. const GpRect *drawBounds)
  2618. {
  2619. return new DpOutputOneDGradientSpan(
  2620. this,
  2621. scan,
  2622. context
  2623. );
  2624. }
  2625. DpOutputSpan*
  2626. GpTriangleGradient::CreateOutputSpan(
  2627. DpScanBuffer * scan,
  2628. DpContext *context,
  2629. const GpRect *drawBounds)
  2630. {
  2631. return new DpOutputTriangleGradientSpan(
  2632. this,
  2633. scan,
  2634. context
  2635. );
  2636. }
  2637. #endif
  2638. DpOutputSpan*
  2639. GpPathGradient::CreateOutputSpan(
  2640. DpScanBuffer * scan,
  2641. DpContext *context,
  2642. const GpRect *drawBounds)
  2643. {
  2644. FPUStateSaver::AssertMode();
  2645. DpOutputSpan* span = NULL;
  2646. WrapMode wrap = DeviceBrush.Wrap;
  2647. // Check to see if a tiled gradient is really needed. It
  2648. // is not necessary if the transformed drawbounds fit
  2649. // entirely within the bounds of the brush rectangle.
  2650. if (drawBounds && wrap != WrapModeClamp)
  2651. {
  2652. GpMatrix inverseXForm = context->WorldToDevice;
  2653. if (Ok == inverseXForm.Invert())
  2654. {
  2655. GpRectF brushRect = DeviceBrush.Rect;
  2656. GpRectF transformRect;
  2657. TransformBounds(
  2658. &inverseXForm,
  2659. (REAL)drawBounds->GetLeft(),
  2660. (REAL)drawBounds->GetTop(),
  2661. (REAL)drawBounds->GetRight(),
  2662. (REAL)drawBounds->GetBottom(),
  2663. &transformRect
  2664. );
  2665. if (brushRect.Contains(transformRect))
  2666. {
  2667. wrap = WrapModeClamp;
  2668. }
  2669. }
  2670. }
  2671. if(wrap == WrapModeClamp)
  2672. {
  2673. if(!DeviceBrush.OneSurroundColor)
  2674. {
  2675. span = new DpOutputPathGradientSpan(
  2676. this,
  2677. scan,
  2678. context
  2679. );
  2680. }
  2681. else
  2682. {
  2683. span = new DpOutputOneDPathGradientSpan(
  2684. this,
  2685. scan,
  2686. context
  2687. );
  2688. }
  2689. }
  2690. else
  2691. {
  2692. INT width, height, ix, iy;
  2693. GpRectF brushRect = DeviceBrush.Rect;
  2694. // Create a texture brush to represent this path gradient brush.
  2695. // We do this by creating a texture as close to device resolution
  2696. // as we can and computing the transform (brush to world) for the
  2697. // texture brush decomposed into two transforms that take the
  2698. // brush via device space. The texture brush transform
  2699. // usually works out to be the inverse of the world to device, so
  2700. // the final texture brush draws with a resultant identity transform
  2701. // regardless of the world to device matrix. (exception when there is
  2702. // a rotation in the w2d).
  2703. GpPointF worldDestPoints[3];
  2704. worldDestPoints[0].X = brushRect.X ;
  2705. worldDestPoints[0].Y = brushRect.Y;
  2706. worldDestPoints[1].X = worldDestPoints[0].X + brushRect.Width;
  2707. worldDestPoints[1].Y = worldDestPoints[0].Y;
  2708. worldDestPoints[2].X = worldDestPoints[0].X;
  2709. worldDestPoints[2].Y = worldDestPoints[0].Y + brushRect.Height;
  2710. // Take into account transformation by both the brush xform and
  2711. // the world to device. This will handle transforms such as
  2712. // UnitInch and w2d scales.
  2713. // First get the destination points in world space by applying the
  2714. // brush transform.
  2715. DeviceBrush.Xform.Transform(worldDestPoints, 3);
  2716. GpPointF deviceDestPoints[3];
  2717. GpMemcpy(deviceDestPoints, worldDestPoints, sizeof(worldDestPoints));
  2718. // Now get the device space destination points by applying the
  2719. // world to device transform.
  2720. context->WorldToDevice.Transform(deviceDestPoints, 3);
  2721. // Compute the bounds in device space.
  2722. REAL xmin, xmax, ymin, ymax, nextX, nextY;
  2723. xmin = xmax = deviceDestPoints[1].X +
  2724. deviceDestPoints[2].X - deviceDestPoints[0].X;
  2725. ymin = ymax = deviceDestPoints[1].Y +
  2726. deviceDestPoints[2].Y - deviceDestPoints[0].Y;
  2727. for(INT i = 0; i < 3; i++)
  2728. {
  2729. nextX = deviceDestPoints[i].X;
  2730. nextY = deviceDestPoints[i].Y;
  2731. if(nextX < xmin)
  2732. xmin = nextX;
  2733. else if(nextX > xmax)
  2734. xmax = nextX;
  2735. if(nextY < ymin)
  2736. ymin = nextY;
  2737. else if(nextY > ymax)
  2738. ymax = nextY;
  2739. }
  2740. // Set the optimal bitmap bounds.
  2741. ix = GpRound(xmin);
  2742. iy = GpRound(ymin);
  2743. width = GpRound(xmax) - ix;
  2744. height = GpRound(ymax) - iy;
  2745. GpRectF bitmapBounds(0, 0, TOREAL(width), TOREAL(height));
  2746. // Decompose brushRect --> worldDestPoints transform into two matrix.
  2747. // mat1: brushRect --> bitmapBounds (device space)
  2748. // mat2: bitmapBounds --> worldDestPoints
  2749. GpMatrix mat1, mat2;
  2750. mat1.InferAffineMatrix(bitmapBounds, brushRect);
  2751. mat2.InferAffineMatrix(worldDestPoints, bitmapBounds);
  2752. if(width <= 0 || height <= 0)
  2753. return NULL;
  2754. // Create a bitmap which the gradient will be drawn onto.
  2755. // Make it the full width and height of the gradient, even
  2756. // though only a small portion may be used to simplify
  2757. // handling by downstream functions.
  2758. GpBitmap* bitmap = new GpBitmap(width, height, PixelFormat32bppARGB);
  2759. if(bitmap)
  2760. {
  2761. GpGraphics* g = bitmap->GetGraphicsContext();
  2762. if(g)
  2763. {
  2764. GpLock lock(g->GetObjectLock());
  2765. // Set the transform to brushRect --> bitmapBounds.
  2766. g->MultiplyWorldTransform(mat1);
  2767. WrapMode savedWrapMode = DeviceBrush.Wrap;
  2768. DeviceBrush.Wrap = WrapModeClamp;
  2769. GpMatrix savedMat = DeviceBrush.Xform;
  2770. DeviceBrush.Xform.Reset();
  2771. g->FillRect(this, brushRect.X, brushRect.Y,
  2772. brushRect.Width, brushRect.Height);
  2773. DeviceBrush.Wrap = savedWrapMode;
  2774. DeviceBrush.Xform = savedMat;
  2775. if(MorphedBrush)
  2776. delete MorphedBrush;
  2777. // Create a texuture with a unit tile and set the
  2778. // brush transform to bitmapBounds --> worldDestPoints.
  2779. GpTexture* texture = new GpTexture(bitmap, savedWrapMode);
  2780. // span must be NULL at this point. If it's not, we're going
  2781. // to leak memory when we create it below, or in the case of
  2782. // an error out, we may end up with uninitialized memory
  2783. // being returned to the caller.
  2784. ASSERT(span == NULL);
  2785. if(texture)
  2786. {
  2787. texture->MultiplyTransform(mat2);
  2788. span = texture->CreateOutputSpan(scan, context, drawBounds);
  2789. }
  2790. // Even if we failed to create the texture, we still want to
  2791. // set a reasonable (NULL) value for MorphedBrush so that we
  2792. // don't have a dangling pointer.
  2793. MorphedBrush = texture;
  2794. }
  2795. // We're done with this graphics.
  2796. // NOTE: this is explicitly done outside of the scope of the
  2797. // GpLock object, so that the GpLock (which modifies the graphics
  2798. // in its destructor) doesn't touch freed memory.
  2799. delete g;
  2800. bitmap->Dispose();
  2801. }
  2802. }
  2803. return span;
  2804. }
  2805. DpOutputSpan*
  2806. GpTexture::CreateOutputSpan(
  2807. DpScanBuffer *scan,
  2808. DpContext *context,
  2809. const GpRect *drawBounds)
  2810. {
  2811. DpOutputBilinearSpan *textureSpan = NULL;
  2812. GpMatrix brushTransform;
  2813. GpMatrix worldToDevice;
  2814. // Figure out the world-to-device transform:
  2815. worldToDevice = context->WorldToDevice;
  2816. this->GetTransform(&brushTransform);
  2817. worldToDevice.Prepend(brushTransform);
  2818. // Go through our heirarchy of scan drawers:
  2819. if (worldToDevice.IsIntegerTranslate() &&
  2820. ((this->GetWrapMode() == WrapModeTile) ||
  2821. (this->GetWrapMode() == WrapModeClamp)))
  2822. {
  2823. textureSpan = new DpOutputBilinearSpan_Identity(this,
  2824. scan,
  2825. &worldToDevice,
  2826. context);
  2827. }
  2828. else if (OSInfo::HasMMX &&
  2829. GpValidFixed16(DeviceBrush.Rect.Width) &&
  2830. GpValidFixed16(DeviceBrush.Rect.Height))
  2831. {
  2832. textureSpan = new DpOutputBilinearSpan_MMX(this,
  2833. scan,
  2834. &worldToDevice,
  2835. context);
  2836. }
  2837. // Scan drawer creation may fail, so clean up and try one last time
  2838. if ((textureSpan) && !textureSpan->IsValid())
  2839. {
  2840. delete textureSpan;
  2841. textureSpan = NULL;
  2842. }
  2843. if (!textureSpan)
  2844. {
  2845. textureSpan = new DpOutputBilinearSpan(this,
  2846. scan,
  2847. &worldToDevice,
  2848. context);
  2849. }
  2850. if ((textureSpan) && !textureSpan->IsValid())
  2851. {
  2852. delete textureSpan;
  2853. textureSpan = NULL;
  2854. }
  2855. return textureSpan;
  2856. }
  2857. DpOutputSpan*
  2858. GpHatch::CreateOutputSpan(
  2859. DpScanBuffer * scan,
  2860. DpContext *context,
  2861. const GpRect *drawBounds)
  2862. {
  2863. if (StretchFactor == 1)
  2864. {
  2865. return new DpOutputHatchSpan(
  2866. this,
  2867. scan,
  2868. context
  2869. );
  2870. }
  2871. else
  2872. {
  2873. return new DpOutputStretchedHatchSpan(
  2874. this,
  2875. scan,
  2876. context,
  2877. StretchFactor
  2878. );
  2879. }
  2880. }
  2881. class SolidBrushData : public ObjectTypeData
  2882. {
  2883. public:
  2884. ARGB SolidColor;
  2885. };
  2886. /**************************************************************************\
  2887. *
  2888. * Function Description:
  2889. *
  2890. * Get the brush data.
  2891. *
  2892. * Arguments:
  2893. *
  2894. * [IN] dataBuffer - fill this buffer with the data
  2895. * [IN/OUT] size - IN - size of buffer; OUT - number bytes written
  2896. *
  2897. * Return Value:
  2898. *
  2899. * GpStatus - Ok or error code
  2900. *
  2901. * Created:
  2902. *
  2903. * 9/13/1999 DCurtis
  2904. *
  2905. \**************************************************************************/
  2906. GpStatus
  2907. GpSolidFill::GetData(
  2908. IStream * stream
  2909. ) const
  2910. {
  2911. ASSERT (stream != NULL);
  2912. SolidBrushData brushData;
  2913. brushData.Type = DeviceBrush.Type;
  2914. brushData.SolidColor = DeviceBrush.SolidColor.GetValue();
  2915. stream->Write(&brushData, sizeof(brushData), NULL);
  2916. return Ok;
  2917. }
  2918. UINT
  2919. GpSolidFill::GetDataSize() const
  2920. {
  2921. return sizeof(SolidBrushData);
  2922. }
  2923. /**************************************************************************\
  2924. *
  2925. * Function Description:
  2926. *
  2927. * Read the brush object from memory.
  2928. *
  2929. * Arguments:
  2930. *
  2931. * [IN] dataBuffer - the data that was read from the stream
  2932. * [IN] size - the size of the data
  2933. *
  2934. * Return Value:
  2935. *
  2936. * GpStatus - Ok or failure status
  2937. *
  2938. * Created:
  2939. *
  2940. * 4/26/1999 DCurtis
  2941. *
  2942. \**************************************************************************/
  2943. GpStatus
  2944. GpSolidFill::SetData(
  2945. const BYTE * dataBuffer,
  2946. UINT size
  2947. )
  2948. {
  2949. ASSERT ((GpBrushType)(((SolidBrushData *)dataBuffer)->Type) == BrushTypeSolidColor);
  2950. if (dataBuffer == NULL)
  2951. {
  2952. WARNING(("dataBuffer is NULL"));
  2953. return InvalidParameter;
  2954. }
  2955. if (size < sizeof(SolidBrushData))
  2956. {
  2957. WARNING(("size too small"));
  2958. return InvalidParameter;
  2959. }
  2960. if (!((SolidBrushData *)dataBuffer)->MajorVersionMatches())
  2961. {
  2962. WARNING(("Version number mismatch"));
  2963. return InvalidParameter;
  2964. }
  2965. SetColor(GpColor(((SolidBrushData *)dataBuffer)->SolidColor));
  2966. return Ok;
  2967. }
  2968. GpStatus
  2969. GpSolidFill::ColorAdjust(
  2970. GpRecolor * recolor,
  2971. ColorAdjustType type
  2972. )
  2973. {
  2974. if(!recolor)
  2975. return InvalidParameter;
  2976. if (type == ColorAdjustTypeDefault)
  2977. {
  2978. type = ColorAdjustTypeBrush;
  2979. }
  2980. ARGB solidColor32 = Color.GetValue();
  2981. recolor->ColorAdjust(&solidColor32, 1, type);
  2982. this->SetColor(GpColor(solidColor32));
  2983. return Ok;
  2984. }
  2985. class TextureBrushData : public ObjectTypeData
  2986. {
  2987. public:
  2988. INT32 Flags;
  2989. INT32 Wrap;
  2990. };
  2991. /**************************************************************************\
  2992. *
  2993. * Function Description:
  2994. *
  2995. * Get the brush data.
  2996. *
  2997. * Arguments:
  2998. *
  2999. * [IN] dataBuffer - fill this buffer with the data
  3000. * [IN/OUT] size - IN - size of buffer; OUT - number bytes written
  3001. *
  3002. * Return Value:
  3003. *
  3004. * GpStatus - Ok or error code
  3005. *
  3006. * Created:
  3007. *
  3008. * 9/13/1999 DCurtis
  3009. *
  3010. \**************************************************************************/
  3011. GpStatus
  3012. GpTexture::GetData(
  3013. IStream * stream
  3014. ) const
  3015. {
  3016. ASSERT (stream != NULL);
  3017. if (Image == NULL)
  3018. {
  3019. WARNING(("Image is NULL"));
  3020. return Ok;
  3021. }
  3022. INT flags = 0;
  3023. if (DeviceBrush.IsGammaCorrected)
  3024. {
  3025. flags |= GDIP_BRUSHFLAGS_ISGAMMACORRECTED;
  3026. }
  3027. if (!DeviceBrush.Xform.IsIdentity())
  3028. {
  3029. flags |= GDIP_BRUSHFLAGS_TRANSFORM;
  3030. }
  3031. TextureBrushData brushData;
  3032. brushData.Type = DeviceBrush.Type;
  3033. brushData.Flags = flags;
  3034. brushData.Wrap = DeviceBrush.Wrap;
  3035. stream->Write(&brushData, sizeof(brushData), NULL);
  3036. if (flags & GDIP_BRUSHFLAGS_TRANSFORM)
  3037. {
  3038. DeviceBrush.Xform.WriteMatrix(stream);
  3039. }
  3040. return Image->GetData(stream);
  3041. }
  3042. UINT
  3043. GpTexture::GetDataSize() const
  3044. {
  3045. if (Image == NULL)
  3046. {
  3047. WARNING(("Image is NULL"));
  3048. return 0;
  3049. }
  3050. UINT size = sizeof(TextureBrushData);
  3051. if (!DeviceBrush.Xform.IsIdentity())
  3052. {
  3053. size += GDIP_MATRIX_SIZE;
  3054. }
  3055. size += Image->GetDataSize();
  3056. return size;
  3057. }
  3058. /**************************************************************************\
  3059. *
  3060. * Function Description:
  3061. *
  3062. * Read the brush object from memory.
  3063. *
  3064. * Arguments:
  3065. *
  3066. * [IN] dataBuffer - the data that was read from the stream
  3067. * [IN] size - the size of the data
  3068. *
  3069. * Return Value:
  3070. *
  3071. * GpStatus - Ok or failure status
  3072. *
  3073. * Created:
  3074. *
  3075. * 4/26/1999 DCurtis
  3076. *
  3077. \**************************************************************************/
  3078. GpStatus
  3079. GpTexture::SetData(
  3080. const BYTE * dataBuffer,
  3081. UINT size
  3082. )
  3083. {
  3084. ASSERT ((GpBrushType)(((TextureBrushData *)dataBuffer)->Type) == BrushTypeTextureFill);
  3085. if (dataBuffer == NULL)
  3086. {
  3087. WARNING(("dataBuffer is NULL"));
  3088. return InvalidParameter;
  3089. }
  3090. if (size < sizeof(TextureBrushData))
  3091. {
  3092. WARNING(("size too small"));
  3093. return InvalidParameter;
  3094. }
  3095. const TextureBrushData * brushData;
  3096. brushData = reinterpret_cast<const TextureBrushData *>(dataBuffer);
  3097. if (!brushData->MajorVersionMatches())
  3098. {
  3099. WARNING(("Version number mismatch"));
  3100. return InvalidParameter;
  3101. }
  3102. DeviceBrush.Type = BrushTypeTextureFill;
  3103. DeviceBrush.Wrap = (GpWrapMode) brushData->Wrap;
  3104. DeviceBrush.IsGammaCorrected = ((brushData->Flags & GDIP_BRUSHFLAGS_ISGAMMACORRECTED) != 0);
  3105. dataBuffer += sizeof(TextureBrushData);
  3106. size -= sizeof(TextureBrushData);
  3107. if (brushData->Flags & GDIP_BRUSHFLAGS_TRANSFORM)
  3108. {
  3109. if (size < GDIP_MATRIX_SIZE)
  3110. {
  3111. WARNING(("size too small"));
  3112. return InvalidParameter;
  3113. }
  3114. DeviceBrush.Xform.SetMatrix((REAL *)dataBuffer);
  3115. dataBuffer += GDIP_MATRIX_SIZE;
  3116. size -= GDIP_MATRIX_SIZE;
  3117. }
  3118. if (Image != NULL)
  3119. {
  3120. Image->Dispose();
  3121. Image = NULL;
  3122. }
  3123. if (size >= sizeof(ObjectTypeData))
  3124. {
  3125. Image = (GpImage *)GpObject::Factory(ObjectTypeImage, (const ObjectData *)dataBuffer, size);
  3126. if (Image != NULL)
  3127. {
  3128. if ((Image->SetData(dataBuffer, size) == Ok) && Image->IsValid() &&
  3129. ((ImageType = Image->GetImageType()) == ImageTypeBitmap))
  3130. {
  3131. GpPageUnit unit;
  3132. Image->GetBounds(&DeviceBrush.Rect, &unit);
  3133. SetValid(TRUE);
  3134. UpdateUid();
  3135. return Ok;
  3136. }
  3137. Image->Dispose();
  3138. Image = NULL;
  3139. }
  3140. }
  3141. WARNING(("Failure getting image"));
  3142. GpMemset(&DeviceBrush.Rect, 0, sizeof(DeviceBrush.Rect));
  3143. SetValid(FALSE);
  3144. return GenericError;
  3145. }
  3146. GpStatus
  3147. GpTexture::ColorAdjust(
  3148. GpRecolor * recolor,
  3149. ColorAdjustType type
  3150. )
  3151. {
  3152. if (type == ColorAdjustTypeDefault)
  3153. {
  3154. type = ColorAdjustTypeBrush;
  3155. }
  3156. if (Image != NULL)
  3157. {
  3158. Image->ColorAdjust(recolor, type);
  3159. UpdateUid();
  3160. }
  3161. return Ok;
  3162. }
  3163. VOID GpTexture::InitializeBrush(
  3164. GpImage* image,
  3165. GpWrapMode wrapMode,
  3166. const GpRectF* rect,
  3167. const GpImageAttributes *imageAttributes)
  3168. {
  3169. ASSERT(image && image->IsValid());
  3170. if (!WrapModeIsValid(wrapMode))
  3171. {
  3172. WARNING(("bad wrap mode"));
  3173. goto Failure;
  3174. }
  3175. GpImageType imageType;
  3176. imageType = image->GetImageType();
  3177. if (imageType == ImageTypeBitmap)
  3178. {
  3179. InitializeBrushBitmap(
  3180. static_cast<GpBitmap*>(image),
  3181. wrapMode, rect, imageAttributes
  3182. );
  3183. }
  3184. else if (imageType == ImageTypeMetafile)
  3185. {
  3186. // For now, convert the metafile into a bitmap image and use that to
  3187. // create the brush.
  3188. GpBitmap * bitmapImage;
  3189. if (rect != NULL)
  3190. {
  3191. // !!! we don't handle this case yet
  3192. if ((rect->X != 0) || (rect->Y != 0))
  3193. {
  3194. WARNING(("No handling for non-zero start in metafiles"));
  3195. }
  3196. // Don't apply the imageAttributes now, because WMF/EMF rendering
  3197. // doesn't support alpha. So wait until it's been converted to
  3198. // a bitmap to apply the imageAttributes.
  3199. bitmapImage = ((GpMetafile *)image)->GetBitmap(
  3200. GpRound(rect->Width),
  3201. GpRound(rect->Height), NULL);
  3202. }
  3203. else
  3204. {
  3205. // Let the metafile decide how big the bitmap should be
  3206. // Don't apply the imageAttributes now, because WMF/EMF rendering
  3207. // doesn't support alpha. So wait until it's been converted to
  3208. // a bitmap to apply the imageAttributes.
  3209. bitmapImage = ((GpMetafile *)image)->GetBitmap(0, 0, NULL);
  3210. }
  3211. if (bitmapImage != NULL)
  3212. {
  3213. ASSERT (bitmapImage->IsValid());
  3214. InitializeBrushBitmap(bitmapImage, wrapMode, NULL, imageAttributes, TRUE);
  3215. return;
  3216. }
  3217. goto Failure;
  3218. }
  3219. else // unknown image type
  3220. {
  3221. WARNING(("unknown image type"));
  3222. Failure:
  3223. Image = NULL;
  3224. SetValid(FALSE);
  3225. }
  3226. }
  3227. VOID GpTexture::InitializeBrushBitmap(
  3228. GpBitmap* bitmap,
  3229. GpWrapMode wrapMode,
  3230. const GpRectF* rect,
  3231. const GpImageAttributes *imageAttributes,
  3232. BOOL useBitmap)
  3233. {
  3234. DeviceBrush.Type = BrushTypeTextureFill;
  3235. DeviceBrush.Wrap = wrapMode;
  3236. ImageType = ImageTypeBitmap;
  3237. Image = NULL;
  3238. FPUStateSaver fpState; // Setup the fpu state.
  3239. if (bitmap && bitmap->IsValid())
  3240. {
  3241. GpRect *pRectI = NULL;
  3242. GpRect recti;
  3243. if(rect)
  3244. {
  3245. recti.X = GpRound(rect->X);
  3246. recti.Y = GpRound(rect->Y);
  3247. recti.Width = GpRound(rect->Width);
  3248. recti.Height = GpRound(rect->Height);
  3249. pRectI = &recti;
  3250. }
  3251. if(imageAttributes)
  3252. {
  3253. GpBitmap *dst = NULL;
  3254. if (bitmap->Recolor(
  3255. imageAttributes->recolor, &dst,
  3256. NULL, NULL, pRectI
  3257. ) == Ok)
  3258. {
  3259. Image = dst;
  3260. // If useBitmap is TRUE that means the caller has transferred
  3261. // ownership of bitmap to us. In this case, Recolor makes
  3262. // a clone of the bitmap that we're going to use, so we have
  3263. // to free the bitmap passed in and use the clone instead,
  3264. // otherwise we leak.
  3265. if(useBitmap)
  3266. {
  3267. bitmap->Dispose();
  3268. }
  3269. }
  3270. }
  3271. // !!! note that this should be non-premultiplied ARGB.
  3272. // we'll fix this when we drop premultiplied data [asecchia]
  3273. // also note that the output of RecolorImage is 32BPP_ARGB
  3274. // if it's not NULL it's because the RecolorImage code cloned it already
  3275. if (Image == NULL)
  3276. {
  3277. if (useBitmap)
  3278. {
  3279. // This is for the case where we constructed a bitmap
  3280. // from a metafile image.
  3281. Image = bitmap;
  3282. }
  3283. else
  3284. {
  3285. #ifdef NO_PREMULTIPLIED_ALPHA
  3286. Image = bitmap->Clone(pRectI, PIXFMT_32BPP_ARGB);
  3287. #else
  3288. Image = bitmap->Clone(pRectI, PIXFMT_32BPP_PARGB);
  3289. #endif
  3290. }
  3291. }
  3292. }
  3293. if (Image && Image->IsValid())
  3294. {
  3295. SetValid(TRUE);
  3296. // Rect is given as a pixel unit in bitmap.
  3297. GpPageUnit unit;
  3298. Image->GetBounds(&DeviceBrush.Rect, &unit);
  3299. }
  3300. else
  3301. {
  3302. SetValid(FALSE);
  3303. GpMemset(&DeviceBrush.Rect,
  3304. 0,
  3305. sizeof(DeviceBrush.Rect));
  3306. }
  3307. }
  3308. // See if this texture fill is really a picture fill (with a bitmap,
  3309. // not a metafile).
  3310. BOOL
  3311. GpTexture::IsPictureFill(
  3312. const GpMatrix * worldToDevice,
  3313. const GpRect * drawBounds
  3314. ) const
  3315. {
  3316. ASSERT ((drawBounds->Width > 0) && (drawBounds->Height > 0));
  3317. BOOL isPictureFill = FALSE;
  3318. GpMatrix newBrushMatrix;
  3319. this->GetTransform(&newBrushMatrix);
  3320. if (worldToDevice != NULL)
  3321. {
  3322. newBrushMatrix.Append(*worldToDevice);
  3323. }
  3324. newBrushMatrix.Translate(
  3325. (REAL)-(drawBounds->X),
  3326. (REAL)-(drawBounds->Y),
  3327. MatrixOrderAppend
  3328. );
  3329. // See if the texture is supposed to fill the drawBounds.
  3330. // If so, this is a picture fill.
  3331. if (newBrushMatrix.IsTranslateScale())
  3332. {
  3333. Size size;
  3334. // If the texture is not a bitmap, this returns InvalidParameter.
  3335. if (this->GetBitmapSize(&size) == Ok)
  3336. {
  3337. GpRectF transformedRect(0.0f, 0.0f, (REAL)size.Width, (REAL)size.Height);
  3338. newBrushMatrix.TransformRect(transformedRect);
  3339. // get the transformed width
  3340. INT deltaValue = abs(GpRound(transformedRect.Width) - drawBounds->Width);
  3341. // We might be off a little because of the pixel offset mode
  3342. // or a matrix that isn't quite right for whatever reason.
  3343. if (deltaValue <= 2)
  3344. {
  3345. // get the transformed height
  3346. deltaValue = abs(GpRound(transformedRect.Height) - drawBounds->Height);
  3347. if (deltaValue <= 2)
  3348. {
  3349. if ((abs(GpRound(transformedRect.X)) <= 2) &&
  3350. (abs(GpRound(transformedRect.Y)) <= 2))
  3351. {
  3352. isPictureFill = TRUE;
  3353. }
  3354. }
  3355. }
  3356. }
  3357. }
  3358. return isPictureFill;
  3359. }
  3360. class RectGradientBrushData : public ObjectTypeData
  3361. {
  3362. public:
  3363. INT32 Flags;
  3364. INT32 Wrap;
  3365. GpRectF Rect;
  3366. UINT32 Color0;
  3367. UINT32 Color1;
  3368. UINT32 Color2;
  3369. UINT32 Color3;
  3370. };
  3371. /**************************************************************************\
  3372. *
  3373. * Function Description:
  3374. *
  3375. * Get the brush data.
  3376. *
  3377. * Arguments:
  3378. *
  3379. * [IN] dataBuffer - fill this buffer with the data
  3380. * [IN/OUT] size - IN - size of buffer; OUT - number bytes written
  3381. *
  3382. * Return Value:
  3383. *
  3384. * GpStatus - Ok or error code
  3385. *
  3386. * Created:
  3387. *
  3388. * 9/13/1999 DCurtis
  3389. *
  3390. \**************************************************************************/
  3391. GpStatus
  3392. GpRectGradient::GetData(
  3393. IStream * stream
  3394. ) const
  3395. {
  3396. ASSERT (stream != NULL);
  3397. INT flags = 0;
  3398. if (DeviceBrush.IsGammaCorrected)
  3399. {
  3400. flags |= GDIP_BRUSHFLAGS_ISGAMMACORRECTED;
  3401. }
  3402. if (!DeviceBrush.Xform.IsIdentity())
  3403. {
  3404. flags |= GDIP_BRUSHFLAGS_TRANSFORM;
  3405. }
  3406. // Note: can't have both blendFactors and presetColors at the same time
  3407. // PresetColors used for GpLineGradient, but not for GpRectGradient.
  3408. if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL) &&
  3409. (DeviceBrush.BlendPositions[0] != NULL) && (DeviceBrush.BlendFactors[0] == NULL))
  3410. {
  3411. flags |= GDIP_BRUSHFLAGS_PRESETCOLORS;
  3412. }
  3413. if ((DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.BlendFactors[0] != NULL) && (DeviceBrush.BlendPositions[0] != NULL))
  3414. {
  3415. flags |= GDIP_BRUSHFLAGS_BLENDFACTORSH;
  3416. }
  3417. if ((DeviceBrush.BlendCounts[1] > 1) && (DeviceBrush.BlendFactors[1] != NULL) && (DeviceBrush.BlendPositions[1] != NULL))
  3418. {
  3419. flags |= GDIP_BRUSHFLAGS_BLENDFACTORSV;
  3420. }
  3421. RectGradientBrushData brushData;
  3422. brushData.Type = DeviceBrush.Type;
  3423. brushData.Flags = flags;
  3424. brushData.Wrap = DeviceBrush.Wrap;
  3425. brushData.Rect = DeviceBrush.Rect;
  3426. brushData.Color0 = DeviceBrush.Colors[0].GetValue();
  3427. brushData.Color1 = DeviceBrush.Colors[1].GetValue();
  3428. brushData.Color2 = DeviceBrush.Colors[2].GetValue();
  3429. brushData.Color3 = DeviceBrush.Colors[3].GetValue();
  3430. stream->Write(&brushData, sizeof(brushData), NULL);
  3431. if (flags & GDIP_BRUSHFLAGS_TRANSFORM)
  3432. {
  3433. DeviceBrush.Xform.WriteMatrix(stream);
  3434. }
  3435. if (flags & GDIP_BRUSHFLAGS_PRESETCOLORS)
  3436. {
  3437. INT realSize = DeviceBrush.BlendCounts[0] * sizeof(REAL);
  3438. INT argbSize = DeviceBrush.BlendCounts[0] * sizeof(ARGB);
  3439. stream->Write(&DeviceBrush.BlendCounts[0], sizeof(INT32), NULL);
  3440. stream->Write(DeviceBrush.BlendPositions[0], realSize, NULL);
  3441. stream->Write(DeviceBrush.PresetColors, argbSize, NULL);
  3442. }
  3443. if (flags & GDIP_BRUSHFLAGS_BLENDFACTORSH)
  3444. {
  3445. INT realSize = DeviceBrush.BlendCounts[0] * sizeof(REAL);
  3446. stream->Write(&DeviceBrush.BlendCounts[0], sizeof(INT32), NULL);
  3447. stream->Write(DeviceBrush.BlendPositions[0], realSize, NULL);
  3448. stream->Write(DeviceBrush.BlendFactors[0], realSize, NULL);
  3449. }
  3450. if (flags & GDIP_BRUSHFLAGS_BLENDFACTORSV)
  3451. {
  3452. INT realSize = DeviceBrush.BlendCounts[1] * sizeof(REAL);
  3453. stream->Write(&DeviceBrush.BlendCounts[1], sizeof(INT32), NULL);
  3454. stream->Write(DeviceBrush.BlendPositions[1], realSize, NULL);
  3455. stream->Write(DeviceBrush.BlendFactors[1], realSize, NULL);
  3456. }
  3457. return Ok;
  3458. }
  3459. UINT
  3460. GpRectGradient::GetDataSize() const
  3461. {
  3462. UINT size = sizeof(RectGradientBrushData);
  3463. if (!DeviceBrush.Xform.IsIdentity())
  3464. {
  3465. size += GDIP_MATRIX_SIZE;
  3466. }
  3467. // Note: can't have both blendFactors and presetColors at the same time
  3468. // PresetColors used for GpLineGradient, but not for GpRectGradient.
  3469. if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL) &&
  3470. (DeviceBrush.BlendPositions[0] != NULL) && (DeviceBrush.BlendFactors[0] == NULL))
  3471. {
  3472. size += sizeof(INT32) + ((sizeof(ARGB) + sizeof(REAL)) * DeviceBrush.BlendCounts[0]);
  3473. }
  3474. if ((DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.BlendFactors[0] != NULL) && (DeviceBrush.BlendPositions[0] != NULL))
  3475. {
  3476. size += sizeof(INT32) + ((sizeof(REAL) + sizeof(REAL)) * DeviceBrush.BlendCounts[0]);
  3477. }
  3478. if ((DeviceBrush.BlendCounts[1] > 1) && (DeviceBrush.BlendFactors[1] != NULL) && (DeviceBrush.BlendPositions[1] != NULL))
  3479. {
  3480. size += sizeof(INT32) + ((sizeof(REAL) + sizeof(REAL)) * DeviceBrush.BlendCounts[1]);
  3481. }
  3482. return size;
  3483. }
  3484. /**************************************************************************\
  3485. *
  3486. * Function Description:
  3487. *
  3488. * Read the brush object from memory.
  3489. *
  3490. * Arguments:
  3491. *
  3492. * [IN] dataBuffer - the data that was read from the stream
  3493. * [IN] size - the size of the data
  3494. *
  3495. * Return Value:
  3496. *
  3497. * GpStatus - Ok or failure status
  3498. *
  3499. * Created:
  3500. *
  3501. * 4/26/1999 DCurtis
  3502. *
  3503. \**************************************************************************/
  3504. GpStatus
  3505. GpRectGradient::SetData(
  3506. const BYTE * dataBuffer,
  3507. UINT size
  3508. )
  3509. {
  3510. ASSERT ((GpBrushType)(((RectGradientBrushData *)dataBuffer)->Type) == BrushTypeLinearGradient);
  3511. if (dataBuffer == NULL)
  3512. {
  3513. WARNING(("dataBuffer is NULL"));
  3514. return InvalidParameter;
  3515. }
  3516. if (size < sizeof(RectGradientBrushData))
  3517. {
  3518. WARNING(("size too small"));
  3519. return InvalidParameter;
  3520. }
  3521. const RectGradientBrushData * brushData;
  3522. GpColor colors[4];
  3523. brushData = reinterpret_cast<const RectGradientBrushData *>(dataBuffer);
  3524. if (!brushData->MajorVersionMatches())
  3525. {
  3526. WARNING(("Version number mismatch"));
  3527. return InvalidParameter;
  3528. }
  3529. colors[0].SetValue(brushData->Color0);
  3530. colors[1].SetValue(brushData->Color1);
  3531. colors[2].SetValue(brushData->Color2);
  3532. colors[3].SetValue(brushData->Color3);
  3533. InitializeBrush(brushData->Rect, colors, (GpWrapMode) brushData->Wrap);
  3534. DeviceBrush.IsGammaCorrected = ((brushData->Flags & GDIP_BRUSHFLAGS_ISGAMMACORRECTED) != 0);
  3535. dataBuffer += sizeof(RectGradientBrushData);
  3536. size -= sizeof(RectGradientBrushData);
  3537. if (brushData->Flags & GDIP_BRUSHFLAGS_TRANSFORM)
  3538. {
  3539. if (size < GDIP_MATRIX_SIZE)
  3540. {
  3541. WARNING(("size too small"));
  3542. return InvalidParameter;
  3543. }
  3544. DeviceBrush.Xform.SetMatrix((REAL *)dataBuffer);
  3545. dataBuffer += GDIP_MATRIX_SIZE;
  3546. size -= GDIP_MATRIX_SIZE;
  3547. }
  3548. if (brushData->Flags & GDIP_BRUSHFLAGS_PRESETCOLORS)
  3549. {
  3550. if (size < sizeof(INT32))
  3551. {
  3552. WARNING(("size too small"));
  3553. return InvalidParameter;
  3554. }
  3555. UINT count = ((INT32 *)dataBuffer)[0];
  3556. dataBuffer += sizeof(INT32);
  3557. size -= sizeof(INT32);
  3558. UINT realSize = count * sizeof(REAL);
  3559. UINT argbSize = count * sizeof(ARGB);
  3560. if (size < (realSize + argbSize))
  3561. {
  3562. WARNING(("size too small"));
  3563. return InvalidParameter;
  3564. }
  3565. ARGB* newColors = (ARGB*) GpRealloc(DeviceBrush.PresetColors, argbSize);
  3566. if (newColors != NULL)
  3567. {
  3568. // We have to just copy in the ARGB values, because they've already
  3569. // been premultiplied.
  3570. // Actually PresetColors is NON-premultiplied, but this code should
  3571. // still be right because we write them out non-premultiplied too.
  3572. GpMemcpy(newColors, dataBuffer + realSize, argbSize);
  3573. DeviceBrush.PresetColors = newColors;
  3574. REAL* newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[0], realSize);
  3575. if (newPositions != NULL)
  3576. {
  3577. GpMemcpy(newPositions, dataBuffer, realSize);
  3578. DeviceBrush.BlendPositions[0] = newPositions;
  3579. GpFree(DeviceBrush.BlendFactors[0]);
  3580. DeviceBrush.BlendFactors[0] = NULL;
  3581. DeviceBrush.UsesPresetColors = TRUE;
  3582. DeviceBrush.BlendCounts[0] = count;
  3583. }
  3584. }
  3585. dataBuffer += (realSize + argbSize);
  3586. size -= (realSize + argbSize);
  3587. }
  3588. if (brushData->Flags & GDIP_BRUSHFLAGS_BLENDFACTORSH)
  3589. {
  3590. if (size < sizeof(INT32))
  3591. {
  3592. WARNING(("size too small"));
  3593. return InvalidParameter;
  3594. }
  3595. UINT count = ((INT32 *)dataBuffer)[0];
  3596. dataBuffer += sizeof(INT32);
  3597. size -= sizeof(INT32);
  3598. UINT realSize = count * sizeof(REAL);
  3599. if (size < (2 * realSize))
  3600. {
  3601. WARNING(("size too small"));
  3602. return InvalidParameter;
  3603. }
  3604. this->SetHorizontalBlend((REAL *)(dataBuffer + realSize),(REAL *)dataBuffer, count);
  3605. dataBuffer += (2 * realSize);
  3606. size -= (2 * realSize);
  3607. }
  3608. if (brushData->Flags & GDIP_BRUSHFLAGS_BLENDFACTORSV)
  3609. {
  3610. if (size < sizeof(INT32))
  3611. {
  3612. WARNING(("size too small"));
  3613. return InvalidParameter;
  3614. }
  3615. UINT count = ((INT32 *)dataBuffer)[0];
  3616. dataBuffer += sizeof(INT32);
  3617. size -= sizeof(INT32);
  3618. UINT realSize = count * sizeof(REAL);
  3619. if (size < (2 * realSize))
  3620. {
  3621. WARNING(("size too small"));
  3622. return InvalidParameter;
  3623. }
  3624. this->SetVerticalBlend((REAL *)(dataBuffer + realSize), (REAL *)dataBuffer, count);
  3625. dataBuffer += (2 * realSize);
  3626. size -= (2 * realSize);
  3627. }
  3628. UpdateUid();
  3629. return Ok;
  3630. }
  3631. GpStatus
  3632. GpRectGradient::ColorAdjust(
  3633. GpRecolor * recolor,
  3634. ColorAdjustType type
  3635. )
  3636. {
  3637. if(!recolor)
  3638. return InvalidParameter;
  3639. if (type == ColorAdjustTypeDefault)
  3640. {
  3641. type = ColorAdjustTypeBrush;
  3642. }
  3643. ARGB solidColor32[4];
  3644. solidColor32[0] = DeviceBrush.Colors[0].GetValue();
  3645. solidColor32[1] = DeviceBrush.Colors[1].GetValue();
  3646. solidColor32[2] = DeviceBrush.Colors[2].GetValue();
  3647. solidColor32[3] = DeviceBrush.Colors[3].GetValue();
  3648. recolor->ColorAdjust(solidColor32, 4, type);
  3649. DeviceBrush.Colors[0].SetValue(solidColor32[0]);
  3650. DeviceBrush.Colors[1].SetValue(solidColor32[1]);
  3651. DeviceBrush.Colors[2].SetValue(solidColor32[2]);
  3652. DeviceBrush.Colors[3].SetValue(solidColor32[3]);
  3653. if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL))
  3654. {
  3655. recolor->ColorAdjust(DeviceBrush.PresetColors, DeviceBrush.BlendCounts[0], type);
  3656. }
  3657. UpdateUid();
  3658. return Ok;
  3659. }
  3660. #if 0
  3661. class RadialGradientBrushData : public ObjectTypeData
  3662. {
  3663. public:
  3664. INT32 Flags;
  3665. INT32 Wrap;
  3666. GpRectF Rect;
  3667. UINT32 CenterColor;
  3668. UINT32 BoundaryColor;
  3669. };
  3670. /**************************************************************************\
  3671. *
  3672. * Function Description:
  3673. *
  3674. * Get the brush data.
  3675. *
  3676. * Arguments:
  3677. *
  3678. * [IN] dataBuffer - fill this buffer with the data
  3679. * [IN/OUT] size - IN - size of buffer; OUT - number bytes written
  3680. *
  3681. * Return Value:
  3682. *
  3683. * GpStatus - Ok or error code
  3684. *
  3685. * Created:
  3686. *
  3687. * 9/13/1999 DCurtis
  3688. *
  3689. \**************************************************************************/
  3690. GpStatus
  3691. GpRadialGradient::GetData(
  3692. IStream * stream
  3693. ) const
  3694. {
  3695. ASSERT (stream != NULL);
  3696. INT flags = 0;
  3697. if (DeviceBrush.IsGammaCorrected)
  3698. {
  3699. flags |= GDIP_BRUSHFLAGS_ISGAMMACORRECTED;
  3700. }
  3701. if (!DeviceBrush.Xform.IsIdentity())
  3702. {
  3703. flags |= GDIP_BRUSHFLAGS_TRANSFORM;
  3704. }
  3705. // Note: can't have both blendFactors and presetColors at the same time
  3706. if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL) &&
  3707. (DeviceBrush.BlendPositions[0] != NULL) && (DeviceBrush.BlendFactors[0] == NULL))
  3708. {
  3709. flags |= GDIP_BRUSHFLAGS_PRESETCOLORS;
  3710. }
  3711. if ((DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.BlendFactors[0] != NULL) && (DeviceBrush.BlendPositions[0] != NULL))
  3712. {
  3713. flags |= GDIP_BRUSHFLAGS_BLENDFACTORS;
  3714. }
  3715. RadialGradientBrushData brushData;
  3716. brushData.Type = DeviceBrush.Type;
  3717. brushData.Flags = flags;
  3718. brushData.Wrap = DeviceBrush.Wrap;
  3719. brushData.Rect = DeviceBrush.Rect;
  3720. brushData.CenterColor = DeviceBrush.Colors[0].GetValue();
  3721. brushData.BoundaryColor = DeviceBrush.Colors[1].GetValue();
  3722. stream->Write(&brushData, sizeof(brushData), NULL);
  3723. if (flags & GDIP_BRUSHFLAGS_TRANSFORM)
  3724. {
  3725. DeviceBrush.Xform.WriteMatrix(stream);
  3726. }
  3727. if (flags & GDIP_BRUSHFLAGS_PRESETCOLORS)
  3728. {
  3729. INT realSize = DeviceBrush.BlendCounts[0] * sizeof(REAL);
  3730. INT argbSize = DeviceBrush.BlendCounts[0] * sizeof(ARGB);
  3731. stream->Write(&DeviceBrush.BlendCounts[0], sizeof(INT32), NULL);
  3732. stream->Write(DeviceBrush.BlendPositions[0], realSize, NULL);
  3733. stream->Write(DeviceBrush.PresetColors, argbSize, NULL);
  3734. }
  3735. if (flags & GDIP_BRUSHFLAGS_BLENDFACTORS)
  3736. {
  3737. INT realSize = DeviceBrush.BlendCounts[0] * sizeof(REAL);
  3738. stream->Write(&DeviceBrush.BlendCounts[0], sizeof(INT32), NULL);
  3739. stream->Write(DeviceBrush.BlendPositions[0], realSize, NULL);
  3740. stream->Write(DeviceBrush.BlendFactors[0], realSize, NULL);
  3741. }
  3742. return Ok;
  3743. }
  3744. UINT
  3745. GpRadialGradient::GetDataSize() const
  3746. {
  3747. UINT size = sizeof(RadialGradientBrushData);
  3748. if (!DeviceBrush.Xform.IsIdentity())
  3749. {
  3750. size += GDIP_MATRIX_SIZE;
  3751. }
  3752. // Note: can't have both blendFactors and presetColors at the same time
  3753. if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL) &&
  3754. (DeviceBrush.BlendPositions[0] != NULL) && (DeviceBrush.BlendFactors[0] == NULL))
  3755. {
  3756. size += sizeof(INT32) + ((sizeof(ARGB) + sizeof(REAL)) * DeviceBrush.BlendCounts[0]);
  3757. }
  3758. if ((DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.BlendFactors[0] != NULL) && (DeviceBrush.BlendPositions[0] != NULL))
  3759. {
  3760. size += sizeof(INT32) + ((sizeof(REAL) + sizeof(REAL)) * DeviceBrush.BlendCounts[0]);
  3761. }
  3762. return size;
  3763. }
  3764. /**************************************************************************\
  3765. *
  3766. * Function Description:
  3767. *
  3768. * Read the brush object from memory.
  3769. *
  3770. * Arguments:
  3771. *
  3772. * [IN] dataBuffer - the data that was read from the stream
  3773. * [IN] size - the size of the data
  3774. *
  3775. * Return Value:
  3776. *
  3777. * GpStatus - Ok or failure status
  3778. *
  3779. * Created:
  3780. *
  3781. * 4/26/1999 DCurtis
  3782. *
  3783. \**************************************************************************/
  3784. GpStatus
  3785. GpRadialGradient::SetData(
  3786. const BYTE * dataBuffer,
  3787. UINT size
  3788. )
  3789. {
  3790. // ASSERT ((GpBrushType)(((RadialGradientBrushData *)dataBuffer)->Type) == BrushTypeRadialGradient);
  3791. if (dataBuffer == NULL)
  3792. {
  3793. WARNING(("dataBuffer is NULL"));
  3794. return InvalidParameter;
  3795. }
  3796. if (size < sizeof(RadialGradientBrushData))
  3797. {
  3798. WARNING(("size too small"));
  3799. return InvalidParameter;
  3800. }
  3801. const RadialGradientBrushData * brushData;
  3802. GpColor centerColor;
  3803. GpColor boundaryColor;
  3804. brushData = reinterpret_cast<const RadialGradientBrushData *>(dataBuffer);
  3805. if (!brushData->MajorVersionMatches())
  3806. {
  3807. WARNING(("Version number mismatch"));
  3808. return InvalidParameter;
  3809. }
  3810. centerColor.SetValue(brushData->CenterColor);
  3811. boundaryColor.SetValue(brushData->BoundaryColor);
  3812. InitializeBrush(
  3813. brushData->Rect,
  3814. centerColor,
  3815. boundaryColor,
  3816. (GpWrapMode) brushData->Wrap
  3817. );
  3818. DeviceBrush.IsGammaCorrected = ((brushData->Flags & GDIP_BRUSHFLAGS_ISGAMMACORRECTED) != 0);
  3819. dataBuffer += sizeof(RadialGradientBrushData);
  3820. size -= sizeof(RadialGradientBrushData);
  3821. if (brushData->Flags & GDIP_BRUSHFLAGS_TRANSFORM)
  3822. {
  3823. if (size < GDIP_MATRIX_SIZE)
  3824. {
  3825. WARNING(("size too small"));
  3826. return InvalidParameter;
  3827. }
  3828. DeviceBrush.Xform.SetMatrix((REAL *)dataBuffer);
  3829. dataBuffer += GDIP_MATRIX_SIZE;
  3830. size -= GDIP_MATRIX_SIZE;
  3831. }
  3832. if (brushData->Flags & GDIP_BRUSHFLAGS_PRESETCOLORS)
  3833. {
  3834. if (size < sizeof(INT32))
  3835. {
  3836. WARNING(("size too small"));
  3837. return InvalidParameter;
  3838. }
  3839. UINT count = ((INT32 *)dataBuffer)[0];
  3840. dataBuffer += sizeof(INT32);
  3841. size -= sizeof(INT32);
  3842. UINT realSize = count * sizeof(REAL);
  3843. UINT argbSize = count * sizeof(ARGB);
  3844. if (size < (realSize + argbSize))
  3845. {
  3846. WARNING(("size too small"));
  3847. return InvalidParameter;
  3848. }
  3849. ARGB* newColors = (ARGB*) GpRealloc(DeviceBrush.PresetColors, argbSize);
  3850. if (newColors != NULL)
  3851. {
  3852. // We have to just copy in the ARGB values, because they've already
  3853. // been premultiplied.
  3854. GpMemcpy(newColors, dataBuffer + realSize, argbSize);
  3855. DeviceBrush.PresetColors = newColors;
  3856. REAL* newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[0], realSize);
  3857. if (newPositions != NULL)
  3858. {
  3859. GpMemcpy(newPositions, dataBuffer, realSize);
  3860. DeviceBrush.BlendPositions[0] = newPositions;
  3861. GpFree(DeviceBrush.BlendFactors[0]);
  3862. DeviceBrush.BlendFactors[0] = NULL;
  3863. DeviceBrush.UsesPresetColors = TRUE;
  3864. DeviceBrush.BlendCounts[0] = count;
  3865. }
  3866. }
  3867. dataBuffer += (realSize + argbSize);
  3868. size -= (realSize + argbSize);
  3869. }
  3870. if (brushData->Flags & GDIP_BRUSHFLAGS_BLENDFACTORS)
  3871. {
  3872. if (size < sizeof(INT32))
  3873. {
  3874. WARNING(("size too small"));
  3875. return InvalidParameter;
  3876. }
  3877. UINT count = ((INT32 *)dataBuffer)[0];
  3878. dataBuffer += sizeof(INT32);
  3879. size -= sizeof(INT32);
  3880. UINT realSize = count * sizeof(REAL);
  3881. if (size < (2 * realSize))
  3882. {
  3883. WARNING(("size too small"));
  3884. return InvalidParameter;
  3885. }
  3886. this->SetBlend((REAL *)(dataBuffer + realSize), (REAL *)dataBuffer, count);
  3887. dataBuffer += (2 * realSize);
  3888. size -= (2 * realSize);
  3889. }
  3890. UpdateUid();
  3891. return Ok;
  3892. }
  3893. GpStatus
  3894. GpRadialGradient::ColorAdjust(
  3895. GpRecolor * recolor,
  3896. ColorAdjustType type
  3897. )
  3898. {
  3899. if(!recolor)
  3900. return InvalidParameter;
  3901. if (type == ColorAdjustTypeDefault)
  3902. {
  3903. type = ColorAdjustTypeBrush;
  3904. }
  3905. ARGB solidColor32[2];
  3906. solidColor32[0] = DeviceBrush.Colors[0].GetValue();
  3907. solidColor32[1] = DeviceBrush.Colors[1].GetValue();
  3908. recolor->ColorAdjust(solidColor32, 2, type);
  3909. DeviceBrush.Colors[0].SetValue(solidColor32[0]);
  3910. DeviceBrush.Colors[1].SetValue(solidColor32[1]);
  3911. if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL))
  3912. {
  3913. recolor->ColorAdjust(DeviceBrush.PresetColors, DeviceBrush.BlendCounts[0], type);
  3914. }
  3915. UpdateUid();
  3916. return Ok;
  3917. }
  3918. class TriangleGradientBrushData : public ObjectTypeData
  3919. {
  3920. public:
  3921. INT32 Flags;
  3922. INT32 Wrap;
  3923. GpPointF Points[3];
  3924. UINT32 Color0;
  3925. UINT32 Color1;
  3926. UINT32 Color2;
  3927. };
  3928. /**************************************************************************\
  3929. *
  3930. * Function Description:
  3931. *
  3932. * Get the brush data.
  3933. *
  3934. * Arguments:
  3935. *
  3936. * [IN] dataBuffer - fill this buffer with the data
  3937. * [IN/OUT] size - IN - size of buffer; OUT - number bytes written
  3938. *
  3939. * Return Value:
  3940. *
  3941. * GpStatus - Ok or error code
  3942. *
  3943. * Created:
  3944. *
  3945. * 9/13/1999 DCurtis
  3946. *
  3947. \**************************************************************************/
  3948. GpStatus
  3949. GpTriangleGradient::GetData(
  3950. IStream * stream
  3951. ) const
  3952. {
  3953. ASSERT (stream != NULL);
  3954. INT flags = 0;
  3955. if (DeviceBrush.IsGammaCorrected)
  3956. {
  3957. flags |= GDIP_BRUSHFLAGS_ISGAMMACORRECTED;
  3958. }
  3959. if (!DeviceBrush.Xform.IsIdentity())
  3960. {
  3961. flags |= GDIP_BRUSHFLAGS_TRANSFORM;
  3962. }
  3963. if ((DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.BlendFactors[0] != NULL) && (DeviceBrush.BlendPositions[0] != NULL))
  3964. {
  3965. flags |= GDIP_BRUSHFLAGS_BLENDFACTORS0;
  3966. }
  3967. if ((DeviceBrush.BlendCounts[1] > 1) && (DeviceBrush.BlendFactors[1] != NULL) && (DeviceBrush.BlendPositions[1] != NULL))
  3968. {
  3969. flags |= GDIP_BRUSHFLAGS_BLENDFACTORS1;
  3970. }
  3971. if ((DeviceBrush.BlendCounts[2] > 1) && (DeviceBrush.BlendFactors[2] != NULL) && (DeviceBrush.BlendPositions[2] != NULL))
  3972. {
  3973. flags |= GDIP_BRUSHFLAGS_BLENDFACTORS2;
  3974. }
  3975. TriangleGradientBrushData brushData;
  3976. brushData.Type = DeviceBrush.Type;
  3977. brushData.Flags = flags;
  3978. brushData.Wrap = DeviceBrush.Wrap;
  3979. brushData.Points[0] = DeviceBrush.Points[0];
  3980. brushData.Points[1] = DeviceBrush.Points[1];
  3981. brushData.Points[2] = DeviceBrush.Points[2];
  3982. brushData.Color0 = DeviceBrush.Colors[0].GetValue();
  3983. brushData.Color1 = DeviceBrush.Colors[1].GetValue();
  3984. brushData.Color2 = DeviceBrush.Colors[2].GetValue();
  3985. stream->Write(&brushData, sizeof(brushData), NULL);
  3986. if (flags & GDIP_BRUSHFLAGS_TRANSFORM)
  3987. {
  3988. DeviceBrush.Xform.WriteMatrix(stream);
  3989. }
  3990. if (flags & GDIP_BRUSHFLAGS_BLENDFACTORS0)
  3991. {
  3992. INT realSize = DeviceBrush.BlendCounts[0] * sizeof(REAL);
  3993. stream->Write(&DeviceBrush.BlendCounts[0], sizeof(INT32), NULL);
  3994. stream->Write(DeviceBrush.BlendPositions[0], realSize, NULL);
  3995. stream->Write(DeviceBrush.BlendFactors[0], realSize, NULL);
  3996. }
  3997. if (flags & GDIP_BRUSHFLAGS_BLENDFACTORS1)
  3998. {
  3999. INT realSize = DeviceBrush.BlendCounts[1] * sizeof(REAL);
  4000. stream->Write(&DeviceBrush.BlendCounts[1], sizeof(INT32), NULL);
  4001. stream->Write(DeviceBrush.BlendPositions[1], realSize, NULL);
  4002. stream->Write(DeviceBrush.BlendFactors[1], realSize, NULL);
  4003. }
  4004. if (flags & GDIP_BRUSHFLAGS_BLENDFACTORS2)
  4005. {
  4006. INT realSize = DeviceBrush.BlendCounts[2] * sizeof(REAL);
  4007. stream->Write(&DeviceBrush.BlendCounts[2], sizeof(INT32), NULL);
  4008. stream->Write(DeviceBrush.BlendPositions[2], realSize, NULL);
  4009. stream->Write(DeviceBrush.BlendFactors[2], realSize, NULL);
  4010. }
  4011. return Ok;
  4012. }
  4013. UINT
  4014. GpTriangleGradient::GetDataSize() const
  4015. {
  4016. UINT size = sizeof(RectGradientBrushData);
  4017. if (!DeviceBrush.Xform.IsIdentity())
  4018. {
  4019. size += GDIP_MATRIX_SIZE;
  4020. }
  4021. if ((DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.BlendFactors[0] != NULL) && (DeviceBrush.BlendPositions[0] != NULL))
  4022. {
  4023. size += sizeof(INT32) + ((sizeof(REAL) + sizeof(REAL)) * DeviceBrush.BlendCounts[0]);
  4024. }
  4025. if ((DeviceBrush.BlendCounts[1] > 1) && (DeviceBrush.BlendFactors[1] != NULL) && (DeviceBrush.BlendPositions[1] != NULL))
  4026. {
  4027. size += sizeof(INT32) + ((sizeof(REAL) + sizeof(REAL)) * DeviceBrush.BlendCounts[1]);
  4028. }
  4029. if ((DeviceBrush.BlendCounts[2] > 1) && (DeviceBrush.BlendFactors[2] != NULL) && (DeviceBrush.BlendPositions[2] != NULL))
  4030. {
  4031. size += sizeof(INT32) + ((sizeof(REAL) + sizeof(REAL)) * DeviceBrush.BlendCounts[2]);
  4032. }
  4033. return size;
  4034. }
  4035. /**************************************************************************\
  4036. *
  4037. * Function Description:
  4038. *
  4039. * Read the brush object from memory.
  4040. *
  4041. * Arguments:
  4042. *
  4043. * [IN] dataBuffer - the data that was read from the stream
  4044. * [IN] size - the size of the data
  4045. *
  4046. * Return Value:
  4047. *
  4048. * GpStatus - Ok or failure status
  4049. *
  4050. * Created:
  4051. *
  4052. * 4/26/1999 DCurtis
  4053. *
  4054. \**************************************************************************/
  4055. GpStatus
  4056. GpTriangleGradient::SetData(
  4057. const BYTE * dataBuffer,
  4058. UINT size
  4059. )
  4060. {
  4061. // ASSERT ((GpBrushType)(((TriangleGradientBrushData *)dataBuffer)->Type) == BrushTypeTriangleGradient);
  4062. if (dataBuffer == NULL)
  4063. {
  4064. WARNING(("dataBuffer is NULL"));
  4065. return InvalidParameter;
  4066. }
  4067. if (size < sizeof(TriangleGradientBrushData))
  4068. {
  4069. WARNING(("size too small"));
  4070. return InvalidParameter;
  4071. }
  4072. const TriangleGradientBrushData * brushData;
  4073. GpColor colors[3];
  4074. brushData = reinterpret_cast<const TriangleGradientBrushData *>(dataBuffer);
  4075. if (!brushData->MajorVersionMatches())
  4076. {
  4077. WARNING(("Version number mismatch"));
  4078. return InvalidParameter;
  4079. }
  4080. colors[0].SetValue(brushData->Color0);
  4081. colors[1].SetValue(brushData->Color1);
  4082. colors[2].SetValue(brushData->Color2);
  4083. InitializeBrush(brushData->Points, colors, (GpWrapMode) brushData->Wrap);
  4084. DeviceBrush.IsGammaCorrected = ((brushData->Flags & GDIP_BRUSHFLAGS_ISGAMMACORRECTED) != 0);
  4085. dataBuffer += sizeof(TriangleGradientBrushData);
  4086. size -= sizeof(TriangleGradientBrushData);
  4087. if (brushData->Flags & GDIP_BRUSHFLAGS_TRANSFORM)
  4088. {
  4089. if (size < GDIP_MATRIX_SIZE)
  4090. {
  4091. WARNING(("size too small"));
  4092. return InvalidParameter;
  4093. }
  4094. DeviceBrush.Xform.SetMatrix((REAL *)dataBuffer);
  4095. dataBuffer += GDIP_MATRIX_SIZE;
  4096. size -= GDIP_MATRIX_SIZE;
  4097. }
  4098. if (brushData->Flags & GDIP_BRUSHFLAGS_BLENDFACTORS0)
  4099. {
  4100. if (size < sizeof(INT32))
  4101. {
  4102. WARNING(("size too small"));
  4103. return InvalidParameter;
  4104. }
  4105. UINT count = ((INT32 *)dataBuffer)[0];
  4106. dataBuffer += sizeof(INT32);
  4107. size -= sizeof(INT32);
  4108. UINT realSize = count * sizeof(REAL);
  4109. if (size < (2 * realSize))
  4110. {
  4111. WARNING(("size too small"));
  4112. return InvalidParameter;
  4113. }
  4114. this->SetBlend0((REAL *)(dataBuffer + realSize), (REAL *)dataBuffer, count);
  4115. dataBuffer += (2 * realSize);
  4116. size -= (2 * realSize);
  4117. }
  4118. if (brushData->Flags & GDIP_BRUSHFLAGS_BLENDFACTORS1)
  4119. {
  4120. if (size < sizeof(INT32))
  4121. {
  4122. WARNING(("size too small"));
  4123. return InvalidParameter;
  4124. }
  4125. UINT count = ((INT32 *)dataBuffer)[0];
  4126. dataBuffer += sizeof(INT32);
  4127. size -= sizeof(INT32);
  4128. UINT realSize = count * sizeof(REAL);
  4129. if (size < (2 * realSize))
  4130. {
  4131. WARNING(("size too small"));
  4132. return InvalidParameter;
  4133. }
  4134. this->SetBlend1((REAL *)(dataBuffer + realSize), (REAL *)dataBuffer, count);
  4135. dataBuffer += (2 * realSize);
  4136. size -= (2 * realSize);
  4137. }
  4138. if (brushData->Flags & GDIP_BRUSHFLAGS_BLENDFACTORS2)
  4139. {
  4140. if (size < sizeof(INT32))
  4141. {
  4142. WARNING(("size too small"));
  4143. return InvalidParameter;
  4144. }
  4145. UINT count = ((INT32 *)dataBuffer)[0];
  4146. dataBuffer += sizeof(INT32);
  4147. size -= sizeof(INT32);
  4148. UINT realSize = count * sizeof(REAL);
  4149. if (size < (2 * realSize))
  4150. {
  4151. WARNING(("size too small"));
  4152. return InvalidParameter;
  4153. }
  4154. this->SetBlend2((REAL *)(dataBuffer + realSize), (REAL *)dataBuffer, count);
  4155. dataBuffer += (2 * realSize);
  4156. size -= (2 * realSize);
  4157. }
  4158. UpdateUid();
  4159. return Ok;
  4160. }
  4161. GpStatus
  4162. GpTriangleGradient::ColorAdjust(
  4163. GpRecolor * recolor,
  4164. ColorAdjustType type
  4165. )
  4166. {
  4167. if(!recolor)
  4168. return InvalidParameter;
  4169. if (type == ColorAdjustTypeDefault)
  4170. {
  4171. type = ColorAdjustTypeBrush;
  4172. }
  4173. ARGB solidColor32[3];
  4174. solidColor32[0] = DeviceBrush.Colors[0].GetValue();
  4175. solidColor32[1] = DeviceBrush.Colors[1].GetValue();
  4176. solidColor32[2] = DeviceBrush.Colors[2].GetValue();
  4177. recolor->ColorAdjust(solidColor32, 3, type);
  4178. DeviceBrush.Colors[0].SetValue(solidColor32[0]);
  4179. DeviceBrush.Colors[1].SetValue(solidColor32[1]);
  4180. DeviceBrush.Colors[2].SetValue(solidColor32[2]);
  4181. UpdateUid();
  4182. return Ok;
  4183. }
  4184. #endif
  4185. class PathGradientBrushData : public ObjectTypeData
  4186. {
  4187. public:
  4188. INT32 Flags;
  4189. INT32 Wrap;
  4190. UINT32 CenterColor;
  4191. GpPointF CenterPoint;
  4192. UINT32 SurroundingColorCount;
  4193. };
  4194. /**************************************************************************\
  4195. *
  4196. * Function Description:
  4197. *
  4198. * Get the brush data.
  4199. *
  4200. * Arguments:
  4201. *
  4202. * [IN] dataBuffer - fill this buffer with the data
  4203. * [IN/OUT] size - IN - size of buffer; OUT - number bytes written
  4204. *
  4205. * Return Value:
  4206. *
  4207. * GpStatus - Ok or error code
  4208. *
  4209. * Created:
  4210. *
  4211. * 9/13/1999 DCurtis
  4212. *
  4213. \**************************************************************************/
  4214. GpStatus
  4215. GpPathGradient::GetData(
  4216. IStream * stream
  4217. ) const
  4218. {
  4219. ASSERT (stream != NULL);
  4220. UINT pathSize = 0;
  4221. UINT surroundingColorCount = DeviceBrush.OneSurroundColor ? 1 : DeviceBrush.Count;
  4222. INT flags = 0;
  4223. GpPath * path = GpPath::GetPath(DeviceBrush.Path);
  4224. if (DeviceBrush.IsGammaCorrected)
  4225. {
  4226. flags |= GDIP_BRUSHFLAGS_ISGAMMACORRECTED;
  4227. }
  4228. if ((DeviceBrush.PointsPtr == NULL) && (path != NULL))
  4229. {
  4230. flags |= GDIP_BRUSHFLAGS_PATH;
  4231. pathSize = path->GetDataSize();
  4232. ASSERT((pathSize & 0x03) == 0);
  4233. }
  4234. if (!DeviceBrush.Xform.IsIdentity())
  4235. {
  4236. flags |= GDIP_BRUSHFLAGS_TRANSFORM;
  4237. }
  4238. // Note: can't have both blendFactors and presetColors at the same time
  4239. if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL) &&
  4240. (DeviceBrush.BlendPositions[0] != NULL) && (DeviceBrush.BlendFactors[0] == NULL))
  4241. {
  4242. flags |= GDIP_BRUSHFLAGS_PRESETCOLORS;
  4243. }
  4244. if ((DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.BlendFactors[0] != NULL) && (DeviceBrush.BlendPositions[0] != NULL))
  4245. {
  4246. flags |= GDIP_BRUSHFLAGS_BLENDFACTORS;
  4247. }
  4248. if((DeviceBrush.FocusScaleX != 0) || (DeviceBrush.FocusScaleY != 0))
  4249. {
  4250. flags |= GDIP_BRUSHFLAGS_FOCUSSCALES;
  4251. }
  4252. PathGradientBrushData brushData;
  4253. brushData.Type = DeviceBrush.Type;
  4254. brushData.Flags = flags;
  4255. brushData.Wrap = DeviceBrush.Wrap;
  4256. brushData.CenterColor = DeviceBrush.Colors[0].GetValue();
  4257. brushData.CenterPoint = DeviceBrush.Points[0];
  4258. brushData.SurroundingColorCount = surroundingColorCount;
  4259. stream->Write(&brushData, sizeof(brushData), NULL);
  4260. ARGB argb;
  4261. for (UINT i = 0; i < surroundingColorCount; i++)
  4262. {
  4263. argb = DeviceBrush.ColorsPtr[i].GetValue();
  4264. stream->Write(&argb, sizeof(argb), NULL);
  4265. }
  4266. if (flags & GDIP_BRUSHFLAGS_PATH)
  4267. {
  4268. stream->Write(&pathSize, sizeof(INT32), NULL);
  4269. path->GetData(stream);
  4270. }
  4271. else
  4272. {
  4273. INT count = DeviceBrush.Count;
  4274. if (DeviceBrush.PointsPtr == NULL)
  4275. {
  4276. count = 0;
  4277. }
  4278. stream->Write(&count, sizeof(INT32), NULL);
  4279. if (count > 0)
  4280. {
  4281. INT pointsSize = count * sizeof(DeviceBrush.PointsPtr[0]);
  4282. stream->Write(DeviceBrush.PointsPtr, pointsSize, NULL);
  4283. }
  4284. }
  4285. if (flags & GDIP_BRUSHFLAGS_TRANSFORM)
  4286. {
  4287. DeviceBrush.Xform.WriteMatrix(stream);
  4288. }
  4289. if (flags & GDIP_BRUSHFLAGS_PRESETCOLORS)
  4290. {
  4291. INT count = DeviceBrush.BlendCounts[0];
  4292. INT realSize = count * sizeof(REAL);
  4293. INT argbSize = count * sizeof(ARGB);
  4294. REAL *newPositions = (REAL*) GpMalloc(realSize);
  4295. if (newPositions == NULL )
  4296. {
  4297. return OutOfMemory;
  4298. }
  4299. ARGB *newARGB = (ARGB*) GpMalloc(argbSize);
  4300. if (newARGB == NULL )
  4301. {
  4302. GpFree(newPositions);
  4303. return OutOfMemory;
  4304. }
  4305. GpColor *newPresetColors = new GpColor[count];
  4306. if (newPresetColors == NULL)
  4307. {
  4308. GpFree(newPositions);
  4309. GpFree (newARGB);
  4310. return OutOfMemory;
  4311. }
  4312. // Users will supply the preset colors as radial blend colors.
  4313. // 0 position means the center location and 1 position means the
  4314. // the outer edge. These are stored inverted internally, so to get back
  4315. // to the original user values, invert again.
  4316. GetPresetBlend(newPresetColors, newPositions, count);
  4317. for (INT i = 0; i < count; i++)
  4318. {
  4319. newARGB[i] = newPresetColors[i].GetValue();
  4320. }
  4321. stream->Write(&count, sizeof(INT32), NULL);
  4322. stream->Write(newPositions, realSize, NULL);
  4323. stream->Write(newARGB, argbSize, NULL);
  4324. GpFree(newPositions);
  4325. GpFree(newARGB);
  4326. delete newPresetColors;
  4327. }
  4328. if (flags & GDIP_BRUSHFLAGS_BLENDFACTORS)
  4329. {
  4330. INT count = DeviceBrush.BlendCounts[0];
  4331. INT realSize = count * sizeof(REAL);
  4332. // Users will supply the blend factor as radial blend factors, and these are stored
  4333. // with inverted values. To get back the original user specified blend factors to
  4334. // store, they must be inverted again.
  4335. REAL *newFactors = (REAL*) GpMalloc(realSize);
  4336. if (newFactors == NULL )
  4337. {
  4338. return OutOfMemory;
  4339. }
  4340. REAL *newPositions = (REAL*) GpMalloc(realSize);
  4341. if (newPositions == NULL )
  4342. {
  4343. GpFree(newFactors);
  4344. return OutOfMemory;
  4345. }
  4346. GetBlend(newFactors, newPositions, count);
  4347. stream->Write(&count, sizeof(INT32), NULL);
  4348. stream->Write(newPositions, realSize, NULL);
  4349. stream->Write(newFactors, realSize, NULL);
  4350. GpFree(newPositions);
  4351. GpFree(newFactors);
  4352. }
  4353. if (flags & GDIP_BRUSHFLAGS_FOCUSSCALES)
  4354. {
  4355. INT count = 2;
  4356. REAL focusScale[2];
  4357. focusScale[0] = DeviceBrush.FocusScaleX;
  4358. focusScale[1] = DeviceBrush.FocusScaleY;
  4359. stream->Write(&count, sizeof(INT32), NULL);
  4360. stream->Write(focusScale, 2 * sizeof(REAL), NULL);
  4361. }
  4362. return Ok;
  4363. }
  4364. UINT
  4365. GpPathGradient::GetDataSize() const
  4366. {
  4367. UINT pathSize;
  4368. UINT surroundingColorCount = DeviceBrush.OneSurroundColor ? 1 : DeviceBrush.Count;
  4369. UINT size = sizeof(PathGradientBrushData) +
  4370. (surroundingColorCount * sizeof(ARGB));
  4371. GpPath* path = static_cast<GpPath*> (DeviceBrush.Path);
  4372. if (DeviceBrush.PointsPtr != NULL)
  4373. {
  4374. size += sizeof(INT32) + (DeviceBrush.Count * sizeof(DeviceBrush.PointsPtr[0]));
  4375. }
  4376. else if (path != NULL)
  4377. {
  4378. pathSize = path->GetDataSize();
  4379. ASSERT((pathSize & 0x03) == 0);
  4380. size += sizeof(INT32) + pathSize;
  4381. }
  4382. if (!DeviceBrush.Xform.IsIdentity())
  4383. {
  4384. size += GDIP_MATRIX_SIZE;
  4385. }
  4386. // Note: can't have both blendFactors and presetColors at the same time
  4387. if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL) &&
  4388. (DeviceBrush.BlendPositions[0] != NULL) && (DeviceBrush.BlendFactors[0] == NULL))
  4389. {
  4390. size += sizeof(INT32) + ((sizeof(ARGB) + sizeof(REAL)) * DeviceBrush.BlendCounts[0]);
  4391. }
  4392. if ((DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.BlendFactors[0] != NULL) && (DeviceBrush.BlendPositions[0] != NULL))
  4393. {
  4394. size += sizeof(INT32) + ((sizeof(REAL) + sizeof(REAL)) * DeviceBrush.BlendCounts[0]);
  4395. }
  4396. if((DeviceBrush.FocusScaleX != 0) || (DeviceBrush.FocusScaleY != 0))
  4397. {
  4398. size += sizeof(INT32) + 2*sizeof(REAL);
  4399. }
  4400. return size;
  4401. }
  4402. /**************************************************************************\
  4403. *
  4404. * Function Description:
  4405. *
  4406. * Read the brush object from memory.
  4407. *
  4408. * Arguments:
  4409. *
  4410. * [IN] dataBuffer - the data that was read from the stream
  4411. * [IN] size - the size of the data
  4412. *
  4413. * Return Value:
  4414. *
  4415. * GpStatus - Ok or failure status
  4416. *
  4417. * Created:
  4418. *
  4419. * 4/26/1999 DCurtis
  4420. *
  4421. \**************************************************************************/
  4422. GpStatus
  4423. GpPathGradient::SetData(
  4424. const BYTE * dataBuffer,
  4425. UINT size
  4426. )
  4427. {
  4428. ASSERT ((GpBrushType)(((PathGradientBrushData *)dataBuffer)->Type) == BrushTypePathGradient);
  4429. if (dataBuffer == NULL)
  4430. {
  4431. WARNING(("dataBuffer is NULL"));
  4432. return InvalidParameter;
  4433. }
  4434. if (size < sizeof(PathGradientBrushData))
  4435. {
  4436. WARNING(("size too small"));
  4437. return InvalidParameter;
  4438. }
  4439. if (DeviceBrush.PointsPtr != NULL)
  4440. {
  4441. GpFree(DeviceBrush.PointsPtr);
  4442. DeviceBrush.PointsPtr = NULL;
  4443. }
  4444. GpPath* path = static_cast<GpPath*> (DeviceBrush.Path);
  4445. if (path != NULL)
  4446. {
  4447. delete path;
  4448. path = NULL;
  4449. }
  4450. const PathGradientBrushData * brushData;
  4451. ARGB * surroundingColors;
  4452. brushData = reinterpret_cast<const PathGradientBrushData *>(dataBuffer);
  4453. if (!brushData->MajorVersionMatches())
  4454. {
  4455. WARNING(("Version number mismatch"));
  4456. return InvalidParameter;
  4457. }
  4458. dataBuffer += sizeof(PathGradientBrushData);
  4459. size -= sizeof(PathGradientBrushData);
  4460. if (size < (brushData->SurroundingColorCount * sizeof(ARGB)))
  4461. {
  4462. WARNING(("size too small"));
  4463. return InvalidParameter;
  4464. }
  4465. surroundingColors = (ARGB *)dataBuffer;
  4466. dataBuffer += (brushData->SurroundingColorCount * sizeof(ARGB));
  4467. size -= (brushData->SurroundingColorCount * sizeof(ARGB));
  4468. if (brushData->Flags & GDIP_BRUSHFLAGS_PATH)
  4469. {
  4470. if (size < sizeof(INT32))
  4471. {
  4472. WARNING(("size too small"));
  4473. return InvalidParameter;
  4474. }
  4475. UINT pathSize = ((INT32 *)dataBuffer)[0];
  4476. dataBuffer += sizeof(INT32);
  4477. size -= sizeof(INT32);
  4478. DefaultBrush();
  4479. DeviceBrush.Wrap = (GpWrapMode) brushData->Wrap;
  4480. if (size < pathSize)
  4481. {
  4482. WARNING(("size too small"));
  4483. return InvalidParameter;
  4484. }
  4485. path = new GpPath();
  4486. if (path)
  4487. {
  4488. path->SetData(dataBuffer, pathSize);
  4489. }
  4490. DeviceBrush.Path = path;
  4491. PrepareBrush();
  4492. dataBuffer += pathSize;
  4493. size -= pathSize;
  4494. }
  4495. else
  4496. {
  4497. if (size < sizeof(INT32))
  4498. {
  4499. WARNING(("size too small"));
  4500. return InvalidParameter;
  4501. }
  4502. INT count = ((INT32 *)dataBuffer)[0];
  4503. dataBuffer += sizeof(INT32);
  4504. size -= sizeof(INT32);
  4505. if (size < (count * sizeof(GpPointF)))
  4506. {
  4507. WARNING(("size too small"));
  4508. return InvalidParameter;
  4509. }
  4510. InitializeBrush((GpPointF *)dataBuffer, count, (GpWrapMode) brushData->Wrap);
  4511. dataBuffer += (count * sizeof(GpPointF));
  4512. size -= (count * sizeof(GpPointF));
  4513. }
  4514. DeviceBrush.IsGammaCorrected = ((brushData->Flags & GDIP_BRUSHFLAGS_ISGAMMACORRECTED) != 0);
  4515. SetCenterPoint(brushData->CenterPoint);
  4516. SetCenterColor(GpColor(brushData->CenterColor));
  4517. DeviceBrush.OneSurroundColor = (brushData->SurroundingColorCount == 1);
  4518. if (DeviceBrush.ColorsPtr != NULL)
  4519. {
  4520. for (UINT32 i = 0; i < brushData->SurroundingColorCount; i++)
  4521. {
  4522. SetSurroundColor(GpColor(surroundingColors[i]), i);
  4523. }
  4524. // OneSurroundColor requires n colors and they are all set to the
  4525. // same value. This is a very weird requirement, but that's the way
  4526. // it was written. One color simply isn't enough.
  4527. if (i == 1)
  4528. {
  4529. for (i = 1; (INT)i < DeviceBrush.Count; i++)
  4530. {
  4531. DeviceBrush.ColorsPtr[i] = GpColor(surroundingColors[0]);
  4532. }
  4533. }
  4534. }
  4535. if (brushData->Flags & GDIP_BRUSHFLAGS_TRANSFORM)
  4536. {
  4537. if (size < GDIP_MATRIX_SIZE)
  4538. {
  4539. WARNING(("size too small"));
  4540. return InvalidParameter;
  4541. }
  4542. DeviceBrush.Xform.SetMatrix((REAL *)dataBuffer);
  4543. dataBuffer += GDIP_MATRIX_SIZE;
  4544. size -= GDIP_MATRIX_SIZE;
  4545. }
  4546. if (brushData->Flags & GDIP_BRUSHFLAGS_PRESETCOLORS)
  4547. {
  4548. if (size < sizeof(INT32))
  4549. {
  4550. WARNING(("size too small"));
  4551. return InvalidParameter;
  4552. }
  4553. UINT count = ((INT32 *)dataBuffer)[0];
  4554. dataBuffer += sizeof(INT32);
  4555. size -= sizeof(INT32);
  4556. UINT realSize = count * sizeof(REAL);
  4557. UINT argbSize = count * sizeof(ARGB);
  4558. if (size < (realSize + argbSize))
  4559. {
  4560. WARNING(("size too small"));
  4561. return InvalidParameter;
  4562. }
  4563. ARGB *argbBuffer = (ARGB*)(dataBuffer + realSize);
  4564. GpColor *colors = new GpColor[count];
  4565. if (colors == NULL)
  4566. {
  4567. return OutOfMemory;
  4568. }
  4569. for (UINT i = 0; i < count; i++)
  4570. {
  4571. colors[i].SetValue(argbBuffer[i]);
  4572. }
  4573. this->SetPresetBlend(colors, (REAL *)dataBuffer, count);
  4574. dataBuffer += (realSize + argbSize);
  4575. size -= (realSize + argbSize);
  4576. delete colors;
  4577. }
  4578. if (brushData->Flags & GDIP_BRUSHFLAGS_BLENDFACTORS)
  4579. {
  4580. if (size < sizeof(INT32))
  4581. {
  4582. WARNING(("size too small"));
  4583. return InvalidParameter;
  4584. }
  4585. UINT count = ((INT32 *)dataBuffer)[0];
  4586. dataBuffer += sizeof(INT32);
  4587. size -= sizeof(INT32);
  4588. UINT realSize = count * sizeof(REAL);
  4589. if (size < (2 * realSize))
  4590. {
  4591. WARNING(("size too small"));
  4592. return InvalidParameter;
  4593. }
  4594. this->SetBlend((REAL *)(dataBuffer + realSize), (REAL *)dataBuffer, count);
  4595. dataBuffer += (2 * realSize);
  4596. size -= (2 * realSize);
  4597. }
  4598. if (brushData->Flags & GDIP_BRUSHFLAGS_FOCUSSCALES)
  4599. {
  4600. if (size < sizeof(INT32))
  4601. {
  4602. WARNING(("size too small"));
  4603. return InvalidParameter;
  4604. }
  4605. INT count = ((INT32 *)dataBuffer)[0];
  4606. dataBuffer += sizeof(INT32);
  4607. size -= sizeof(INT32);
  4608. if (size < (2 * sizeof(REAL)))
  4609. {
  4610. WARNING(("size too small"));
  4611. return InvalidParameter;
  4612. }
  4613. DeviceBrush.FocusScaleX = ((REAL *) dataBuffer)[0];
  4614. DeviceBrush.FocusScaleY = ((REAL *) dataBuffer)[1];
  4615. dataBuffer += (2 * sizeof(REAL));
  4616. size -= (2 * sizeof(REAL));
  4617. }
  4618. UpdateUid();
  4619. return Ok;
  4620. }
  4621. /**************************************************************************\
  4622. *
  4623. * Function Description:
  4624. *
  4625. * Blend any transparent colors in this brush with white. Note that
  4626. * colors are premultiplied, since they will become fully opaque.
  4627. *
  4628. * Arguments:
  4629. *
  4630. * Return Value:
  4631. *
  4632. * GpStatus - Ok or failure status
  4633. *
  4634. \**************************************************************************/
  4635. GpStatus GpPathGradient::BlendWithWhite()
  4636. {
  4637. DeviceBrush.Colors[0].SetValue(
  4638. GpColor::ConvertToPremultiplied(DeviceBrush.Colors[0].GetValue()));
  4639. DeviceBrush.Colors[0].BlendOpaqueWithWhite();
  4640. if (DeviceBrush.UsesPresetColors)
  4641. {
  4642. GpColor color;
  4643. for (INT i=0; i<DeviceBrush.BlendCounts[0]; i++)
  4644. {
  4645. color.SetValue(GpColor::ConvertToPremultiplied(DeviceBrush.PresetColors[i]));
  4646. color.BlendOpaqueWithWhite();
  4647. DeviceBrush.PresetColors[i] = color.GetValue();
  4648. }
  4649. }
  4650. else
  4651. {
  4652. for (INT i=0; i<DeviceBrush.Count; i++)
  4653. {
  4654. DeviceBrush.ColorsPtr[i].SetValue(
  4655. GpColor::ConvertToPremultiplied(DeviceBrush.ColorsPtr[i].GetValue()));
  4656. DeviceBrush.ColorsPtr[i].BlendOpaqueWithWhite();
  4657. }
  4658. }
  4659. return Ok;
  4660. }
  4661. /**************************************************************************\
  4662. *
  4663. * Function Description:
  4664. *
  4665. * Set the surround color.
  4666. *
  4667. * Arguments:
  4668. *
  4669. * [IN] color - the color to set.
  4670. * [IN] index - which color to set.
  4671. *
  4672. * Return Value:
  4673. *
  4674. * GpStatus - Ok or failure status
  4675. *
  4676. \**************************************************************************/
  4677. GpStatus GpPathGradient::SetSurroundColor(GpColor& color, INT index)
  4678. {
  4679. if(index >= 0 && index < DeviceBrush.Count)
  4680. {
  4681. if(DeviceBrush.OneSurroundColor)
  4682. {
  4683. if(index == 0)
  4684. {
  4685. DeviceBrush.ColorsPtr[0] = color;
  4686. // OneSurroundColor requires n colors and they are all set to the
  4687. // same value. This is a very weird requirement, but that's the way
  4688. // it was written. One color simply isn't enough.
  4689. for (INT i = 1; i < DeviceBrush.Count; i++)
  4690. {
  4691. DeviceBrush.ColorsPtr[i] = GpColor(DeviceBrush.ColorsPtr[0]);
  4692. }
  4693. UpdateUid();
  4694. }
  4695. else
  4696. {
  4697. if(DeviceBrush.ColorsPtr[0].GetValue() !=
  4698. color.GetValue())
  4699. {
  4700. DeviceBrush.OneSurroundColor = FALSE;
  4701. DeviceBrush.ColorsPtr[index] = color;
  4702. UpdateUid();
  4703. }
  4704. }
  4705. }
  4706. else
  4707. {
  4708. DeviceBrush.ColorsPtr[index] = color;
  4709. UpdateUid();
  4710. }
  4711. return Ok;
  4712. }
  4713. else
  4714. return InvalidParameter;
  4715. }
  4716. /**************************************************************************\
  4717. *
  4718. * Function Description:
  4719. *
  4720. * Set the surround colors.
  4721. *
  4722. * Arguments:
  4723. *
  4724. * [IN] color - the color to set.
  4725. *
  4726. * Return Value:
  4727. *
  4728. * GpStatus - Ok or failure status
  4729. *
  4730. \**************************************************************************/
  4731. GpStatus GpPathGradient::SetSurroundColors(const GpColor* colors)
  4732. {
  4733. GpStatus status = InvalidParameter;
  4734. ASSERT(DeviceBrush.Count > 0);
  4735. if(IsValid() && colors && DeviceBrush.Count > 0)
  4736. {
  4737. GpMemcpy(
  4738. DeviceBrush.ColorsPtr,
  4739. colors,
  4740. DeviceBrush.Count*sizeof(GpColor)
  4741. );
  4742. DeviceBrush.OneSurroundColor = TRUE;
  4743. INT i = 1;
  4744. ARGB value = colors[0].GetValue();
  4745. while((i < DeviceBrush.Count) && (DeviceBrush.OneSurroundColor))
  4746. {
  4747. if(colors[i].GetValue() != value)
  4748. {
  4749. DeviceBrush.OneSurroundColor = FALSE;
  4750. }
  4751. i++;
  4752. }
  4753. UpdateUid();
  4754. status = Ok;
  4755. }
  4756. return status;
  4757. }
  4758. GpStatus
  4759. GpPathGradient::ColorAdjust(
  4760. GpRecolor * recolor,
  4761. ColorAdjustType type
  4762. )
  4763. {
  4764. if(!recolor)
  4765. return InvalidParameter;
  4766. if (type == ColorAdjustTypeDefault)
  4767. {
  4768. type = ColorAdjustTypeBrush;
  4769. }
  4770. INT surroundingColorCount = DeviceBrush.OneSurroundColor ? 1 : DeviceBrush.Count;
  4771. if ((surroundingColorCount > 0) && (DeviceBrush.ColorsPtr != NULL))
  4772. {
  4773. ARGB solidColor32[32];
  4774. ARGB * color32 = solidColor32;
  4775. if (surroundingColorCount > 32)
  4776. {
  4777. color32 = new ARGB[surroundingColorCount];
  4778. if (color32 == NULL)
  4779. {
  4780. return OutOfMemory;
  4781. }
  4782. }
  4783. INT i;
  4784. for (i = 0; i < surroundingColorCount; i++)
  4785. {
  4786. color32[i] = DeviceBrush.ColorsPtr[i].GetValue();
  4787. }
  4788. recolor->ColorAdjust(color32, surroundingColorCount, type);
  4789. for (i = 0; i < surroundingColorCount; i++)
  4790. {
  4791. DeviceBrush.ColorsPtr[i].SetValue(color32[i]);
  4792. }
  4793. if (color32 != solidColor32)
  4794. {
  4795. delete[] color32;
  4796. }
  4797. }
  4798. if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL))
  4799. {
  4800. recolor->ColorAdjust(DeviceBrush.PresetColors, DeviceBrush.BlendCounts[0], type);
  4801. }
  4802. UpdateUid();
  4803. return Ok;
  4804. }
  4805. class HatchBrushData : public ObjectTypeData
  4806. {
  4807. public:
  4808. INT32 Style;
  4809. UINT32 ForeColor;
  4810. UINT32 BackColor;
  4811. };
  4812. /**************************************************************************\
  4813. *
  4814. * Function Description:
  4815. *
  4816. * Get the brush data.
  4817. *
  4818. * Arguments:
  4819. *
  4820. * [IN] dataBuffer - fill this buffer with the data
  4821. * [IN/OUT] size - IN - size of buffer; OUT - number bytes written
  4822. *
  4823. * Return Value:
  4824. *
  4825. * GpStatus - Ok or error code
  4826. *
  4827. * Created:
  4828. *
  4829. * 9/13/1999 DCurtis
  4830. *
  4831. \**************************************************************************/
  4832. GpStatus
  4833. GpHatch::GetData(
  4834. IStream * stream
  4835. ) const
  4836. {
  4837. ASSERT (stream != NULL);
  4838. HatchBrushData brushData;
  4839. brushData.Type = DeviceBrush.Type;
  4840. brushData.Style = DeviceBrush.Style;
  4841. brushData.ForeColor = DeviceBrush.Colors[0].GetValue();
  4842. brushData.BackColor = DeviceBrush.Colors[1].GetValue();
  4843. stream->Write(&brushData, sizeof(brushData), NULL);
  4844. return Ok;
  4845. }
  4846. UINT
  4847. GpHatch::GetDataSize() const
  4848. {
  4849. return sizeof(HatchBrushData);
  4850. }
  4851. /**************************************************************************\
  4852. *
  4853. * Function Description:
  4854. *
  4855. * Read the brush object from memory.
  4856. *
  4857. * Arguments:
  4858. *
  4859. * [IN] dataBuffer - the data that was read from the stream
  4860. * [IN] size - the size of the data
  4861. *
  4862. * Return Value:
  4863. *
  4864. * GpStatus - Ok or failure status
  4865. *
  4866. * Created:
  4867. *
  4868. * 4/26/1999 DCurtis
  4869. *
  4870. \**************************************************************************/
  4871. GpStatus
  4872. GpHatch::SetData(
  4873. const BYTE * dataBuffer,
  4874. UINT size
  4875. )
  4876. {
  4877. ASSERT ((GpBrushType)(((HatchBrushData *)dataBuffer)->Type) == BrushTypeHatchFill);
  4878. if (dataBuffer == NULL)
  4879. {
  4880. WARNING(("dataBuffer is NULL"));
  4881. return InvalidParameter;
  4882. }
  4883. if (size < sizeof(HatchBrushData))
  4884. {
  4885. WARNING(("size too small"));
  4886. return InvalidParameter;
  4887. }
  4888. const HatchBrushData * brushData;
  4889. brushData = reinterpret_cast<const HatchBrushData *>(dataBuffer);
  4890. if (!brushData->MajorVersionMatches())
  4891. {
  4892. WARNING(("Version number mismatch"));
  4893. return InvalidParameter;
  4894. }
  4895. InitializeBrush(static_cast<GpHatchStyle>(brushData->Style),
  4896. GpColor(brushData->ForeColor),
  4897. GpColor(brushData->BackColor));
  4898. UpdateUid();
  4899. return Ok;
  4900. }
  4901. GpStatus
  4902. GpHatch::ColorAdjust(
  4903. GpRecolor * recolor,
  4904. ColorAdjustType type
  4905. )
  4906. {
  4907. ASSERT(recolor != NULL);
  4908. if (type == ColorAdjustTypeDefault)
  4909. {
  4910. type = ColorAdjustTypeBrush;
  4911. }
  4912. ARGB solidColor32[2];
  4913. solidColor32[0] = DeviceBrush.Colors[0].GetValue();
  4914. //!!! bhouse: bug?
  4915. // seems that this should be BackColor ... I'm making the
  4916. // change!
  4917. // solidColor32[1] = ForeColor.GetValue();
  4918. solidColor32[1] = DeviceBrush.Colors[1].GetValue();
  4919. recolor->ColorAdjust(solidColor32, 2, type);
  4920. DeviceBrush.Colors[0].SetValue(solidColor32[0]);
  4921. DeviceBrush.Colors[1].SetValue(solidColor32[1]);
  4922. UpdateUid();
  4923. return Ok;
  4924. }
  4925. static COLORREF
  4926. AverageColors(
  4927. const GpColor * colors,
  4928. INT count
  4929. )
  4930. {
  4931. REAL r = 0;
  4932. REAL g = 0;
  4933. REAL b = 0;
  4934. if (count > 0)
  4935. {
  4936. for (INT i = 0; i < count; i++)
  4937. {
  4938. r += colors->GetRed();
  4939. g += colors->GetGreen();
  4940. b += colors->GetBlue();
  4941. }
  4942. r /= count;
  4943. g /= count;
  4944. b /= count;
  4945. }
  4946. INT red = GpRound(r);
  4947. INT green = GpRound(g);
  4948. INT blue = GpRound(b);
  4949. return RGB(red, green, blue);
  4950. }
  4951. static COLORREF
  4952. AverageColors(
  4953. const GpColor & color1,
  4954. const GpColor & color2
  4955. )
  4956. {
  4957. REAL r = ((REAL)((INT)color1.GetRed() + (INT)color2.GetRed())) / 2.0f;
  4958. REAL g = ((REAL)((INT)color1.GetGreen()+ (INT)color2.GetGreen())) / 2.0f;
  4959. REAL b = ((REAL)((INT)color1.GetBlue() + (INT)color2.GetBlue())) / 2.0f;
  4960. INT red = GpRound(r);
  4961. INT green = GpRound(g);
  4962. INT blue = GpRound(b);
  4963. return RGB(red, green, blue);
  4964. }
  4965. COLORREF
  4966. ToCOLORREF(
  4967. const DpBrush * deviceBrush
  4968. )
  4969. {
  4970. switch (deviceBrush->Type)
  4971. {
  4972. default:
  4973. ASSERT(0);
  4974. // FALLTHRU
  4975. case BrushTypeSolidColor:
  4976. return deviceBrush->SolidColor.ToCOLORREF();
  4977. case BrushTypeHatchFill:
  4978. return AverageColors(deviceBrush->Colors[0],
  4979. deviceBrush->Colors[1]);
  4980. case BrushTypeTextureFill:
  4981. return RGB(0x80, 0x80, 0x80);
  4982. // case BrushRectGrad:
  4983. case BrushTypeLinearGradient:
  4984. return AverageColors(deviceBrush->Colors, 4);
  4985. #if 0
  4986. case BrushRadialGrad:
  4987. return AverageColors(deviceBrush->Colors[0],
  4988. deviceBrush->Colors[1]);
  4989. case BrushTriangleGrad:
  4990. return AverageColors(deviceBrush->Colors, 3);
  4991. #endif
  4992. case BrushTypePathGradient:
  4993. return AverageColors(deviceBrush->Colors[0],
  4994. deviceBrush->ColorsPtr[0]);
  4995. }
  4996. }