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.

2447 lines
64 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1998 Microsoft Corporation
  4. *
  5. * Abstract:
  6. *
  7. * Brush API related declarations
  8. *
  9. * Revision History:
  10. *
  11. * 12/09/1998 davidx
  12. * Flesh out Brush interfaces.
  13. *
  14. * 12/08/1998 andrewgo
  15. * Created it.
  16. *
  17. \**************************************************************************/
  18. #ifndef _BRUSH_HPP
  19. #define _BRUSH_HPP
  20. #define HatchBrush HatchFillBrush
  21. #include "path.hpp" // GpPathGradient needs GpPath.
  22. #include <stddef.h>
  23. #include "..\..\sdkinc\GdiplusColor.h" // IsOpaque needs AlphaMask.
  24. COLORREF
  25. ToCOLORREF(
  26. const DpBrush * deviceBrush
  27. );
  28. enum GpSpecialGradientType
  29. {
  30. GradientTypeNotSpecial,
  31. GradientTypeHorizontal,
  32. GradientTypeVertical,
  33. GradientTypeDiagonal,
  34. GradientTypePathTwoStep,
  35. GradientTypePathComplex
  36. };
  37. //--------------------------------------------------------------------------
  38. // Abstract base class for various brush types
  39. //--------------------------------------------------------------------------
  40. class GpBrush : public GpObject
  41. {
  42. protected:
  43. VOID SetValid(BOOL valid)
  44. {
  45. GpObject::SetValid(valid ? ObjectTagBrush : ObjectTagInvalid);
  46. }
  47. public:
  48. // Make a copy of the Brush object
  49. virtual GpBrush* Clone() const = 0;
  50. // Virtual destructor
  51. virtual ~GpBrush() {}
  52. // Determine if brushes are equivalent
  53. virtual BOOL IsEqual(const GpBrush * brush) const
  54. {
  55. return DeviceBrush.Type == brush->DeviceBrush.Type;
  56. }
  57. // Get the lock object
  58. GpLockable *GetObjectLock() const
  59. {
  60. return &Lockable;
  61. }
  62. GpBrushType GetBrushType() const
  63. {
  64. return DeviceBrush.Type;
  65. }
  66. const DpBrush * GetDeviceBrush() const
  67. {
  68. return & DeviceBrush;
  69. }
  70. virtual BOOL IsValid() const
  71. {
  72. return GpObject::IsValid(ObjectTagBrush);
  73. }
  74. virtual const DpPath * GetOutlinePath() const
  75. {
  76. return NULL;
  77. }
  78. virtual BOOL IsOpaque(BOOL ColorsOnly = FALSE) const = 0;
  79. //IsSolid currently means that the entire fill has the same ARGB color.
  80. //v2: Think about changing this to mean same RGB color instead.
  81. virtual BOOL IsSolid() const = 0;
  82. virtual BOOL IsNearConstant(BYTE *MinAlpha, BYTE* MaxAlpha) const = 0;
  83. // return Horizontal, Vertical, or (in future path)
  84. virtual GpSpecialGradientType
  85. GetSpecialGradientType(const GpMatrix* matrix) const = 0;
  86. virtual ObjectType GetObjectType() const { return ObjectTypeBrush; }
  87. static GpBrush * GetBrush(const DpBrush * brush)
  88. {
  89. return (GpBrush *) ((BYTE *) brush - offsetof(GpBrush, DeviceBrush));
  90. }
  91. COLORREF ToCOLORREF() const
  92. {
  93. return ::ToCOLORREF(&DeviceBrush);
  94. }
  95. virtual DpOutputSpan* CreateOutputSpan(
  96. DpScanBuffer * scan,
  97. DpContext *context,
  98. const GpRect *drawBounds = NULL) = 0;
  99. void SetGammaCorrection(BOOL useGamma)
  100. {
  101. DeviceBrush.IsGammaCorrected = useGamma;
  102. }
  103. BOOL GetGammaCorrection() const
  104. {
  105. return DeviceBrush.IsGammaCorrected;
  106. }
  107. protected: // GDI+ Internal
  108. DpBrush DeviceBrush;
  109. mutable GpLockable Lockable;
  110. };
  111. //--------------------------------------------------------------------------
  112. // Represent solid fill brush object
  113. //--------------------------------------------------------------------------
  114. class GpSolidFill : public GpBrush
  115. {
  116. public:
  117. GpSolidFill(VOID)
  118. {
  119. DefaultBrush();
  120. }
  121. GpSolidFill(const GpColor& color)
  122. : Color(color)
  123. {
  124. DeviceBrush.Type = BrushTypeSolidColor;
  125. DeviceBrush.SolidColor.SetColor(color.GetValue());
  126. SetValid(TRUE);
  127. }
  128. ~GpSolidFill() {}
  129. virtual UINT GetDataSize() const;
  130. virtual GpStatus GetData(IStream * stream) const;
  131. virtual GpStatus SetData(const BYTE * dataBuffer, UINT size);
  132. virtual GpStatus ColorAdjust(
  133. GpRecolor * recolor,
  134. ColorAdjustType type
  135. );
  136. GpColor GetColor() const
  137. {
  138. return Color;
  139. }
  140. VOID SetColor(const GpColor& color)
  141. {
  142. Color = color;
  143. DeviceBrush.SolidColor.SetColor(color.GetValue());
  144. }
  145. GpBrush* Clone() const
  146. {
  147. return new GpSolidFill(Color);
  148. }
  149. virtual BOOL IsEqual(const GpSolidFill * brush) const
  150. {
  151. return Color.IsEqual(brush->Color);
  152. }
  153. virtual BOOL IsOpaque(BOOL ColorsOnly = FALSE) const
  154. {
  155. return DeviceBrush.SolidColor.IsOpaque();
  156. }
  157. virtual BOOL IsSolid() const
  158. {
  159. //This may have to change if we change the defination of IsSolid.
  160. //See comment at GpBrush::IsSolid() for more info.
  161. return TRUE;
  162. }
  163. virtual BOOL IsNearConstant(BYTE *MinAlpha, BYTE* MaxAlpha) const
  164. {
  165. *MinAlpha = Color.GetAlpha();
  166. *MaxAlpha = *MinAlpha;
  167. return TRUE;
  168. }
  169. virtual GpSpecialGradientType
  170. GetSpecialGradientType(const GpMatrix* matrix) const
  171. {
  172. return GradientTypeNotSpecial;
  173. }
  174. virtual DpOutputSpan* CreateOutputSpan(
  175. DpScanBuffer * scan,
  176. DpContext *context,
  177. const GpRect *drawBounds=NULL);
  178. private:
  179. //bhouse: why do we have store a GpColor here?
  180. GpColor Color;
  181. VOID DefaultBrush()
  182. {
  183. Color.SetValue(Color::Black);
  184. DeviceBrush.Type = BrushTypeSolidColor;
  185. DeviceBrush.SolidColor.SetColor(Color.GetValue());
  186. SetValid(TRUE);
  187. }
  188. };
  189. //--------------------------------------------------------------------------
  190. // Abstract brush which is made of an elementary object.
  191. //--------------------------------------------------------------------------
  192. class GpElementaryBrush : public GpBrush
  193. {
  194. public:
  195. virtual BOOL IsOpaque(BOOL ColorsOnly = FALSE) const = 0;
  196. // Set/get brush transform
  197. GpStatus SetTransform(const GpMatrix& matrix)
  198. {
  199. GpStatus status = Ok;
  200. // Keep the transform invertible
  201. if (matrix.IsInvertible())
  202. {
  203. DeviceBrush.Xform = matrix;
  204. UpdateUid();
  205. }
  206. else
  207. status = InvalidParameter;
  208. return status;
  209. }
  210. GpStatus GetTransform(GpMatrix* matrix) const
  211. {
  212. *matrix = DeviceBrush.Xform;
  213. return Ok;
  214. }
  215. GpStatus ResetTransform()
  216. {
  217. DeviceBrush.Xform.Reset();
  218. UpdateUid();
  219. return Ok;
  220. }
  221. GpStatus MultiplyTransform(const GpMatrix& matrix,
  222. GpMatrixOrder order = MatrixOrderPrepend);
  223. GpStatus TranslateTransform(REAL dx, REAL dy,
  224. GpMatrixOrder order = MatrixOrderPrepend)
  225. {
  226. DeviceBrush.Xform.Translate(dx, dy, order);
  227. UpdateUid();
  228. return Ok;
  229. }
  230. GpStatus ScaleTransform(REAL sx, REAL sy,
  231. GpMatrixOrder order = MatrixOrderPrepend)
  232. {
  233. DeviceBrush.Xform.Scale(sx, sy, order);
  234. UpdateUid();
  235. return Ok;
  236. }
  237. GpStatus ScalePath(REAL sx, REAL sy)
  238. {
  239. DeviceBrush.Rect.X *= sx;
  240. DeviceBrush.Rect.Y *= sy;
  241. DeviceBrush.Rect.Height *= sy;
  242. DeviceBrush.Rect.Width *= sx;
  243. DeviceBrush.Points[0].X = DeviceBrush.Points[0].X * sx;
  244. DeviceBrush.Points[0].Y = DeviceBrush.Points[0].Y * sy;
  245. if (DeviceBrush.Path != NULL)
  246. {
  247. GpMatrix matrix(sx, 0.0f, 0.0f, sy, 0.0f, 0.0f);
  248. DeviceBrush.Path->Transform(&matrix);
  249. }
  250. else if (DeviceBrush.PointsPtr && DeviceBrush.Count > 0)
  251. {
  252. for (INT i = 0; i < DeviceBrush.Count; i++)
  253. {
  254. DeviceBrush.PointsPtr[i].X *= sx;
  255. DeviceBrush.PointsPtr[i].Y *= sy;
  256. }
  257. }
  258. UpdateUid();
  259. return Ok;
  260. }
  261. GpStatus RotateTransform(REAL angle,
  262. GpMatrixOrder order = MatrixOrderPrepend)
  263. {
  264. DeviceBrush.Xform.Rotate(angle, order);
  265. UpdateUid();
  266. return Ok;
  267. }
  268. // Set/get brush wrapping mode
  269. VOID SetWrapMode(GpWrapMode wrapMode)
  270. {
  271. if (!WrapModeIsValid(wrapMode))
  272. return;
  273. DeviceBrush.Wrap = wrapMode;
  274. UpdateUid();
  275. }
  276. GpWrapMode GetWrapMode() const
  277. {
  278. return DeviceBrush.Wrap;
  279. }
  280. // Get source rectangle
  281. VOID GetRect(GpRectF& rect) const
  282. {
  283. rect = DeviceBrush.Rect;
  284. }
  285. // Determine if the brushes are equivalent. Only compare for equivalence
  286. // if both brushes are valid.
  287. virtual BOOL isEqual(const GpBrush * brush) const
  288. {
  289. if (GpBrush::IsEqual(brush))
  290. {
  291. const GpElementaryBrush * ebrush;
  292. ebrush = static_cast<const GpElementaryBrush *>(brush);
  293. return IsValid() &&
  294. ebrush->IsValid() &&
  295. ebrush->DeviceBrush.Wrap == DeviceBrush.Wrap &&
  296. ebrush->DeviceBrush.Xform.IsEqual(&DeviceBrush.Xform);
  297. }
  298. else
  299. {
  300. return FALSE;
  301. }
  302. }
  303. virtual GpSpecialGradientType
  304. GetSpecialGradientType(const GpMatrix* matrix) const
  305. {
  306. return GradientTypeNotSpecial;
  307. }
  308. protected: // GDI+ Internal
  309. GpElementaryBrush()
  310. {
  311. SetValid(FALSE);
  312. DeviceBrush.Wrap = WrapModeTile;
  313. DeviceBrush.IsGammaCorrected = FALSE;
  314. }
  315. GpElementaryBrush(const GpElementaryBrush* brush);
  316. };
  317. //--------------------------------------------------------------------------
  318. // Represent texture brush object
  319. //
  320. // A rectangel returned by GetRect() is given by the pixel unit in case of
  321. // GpBitmap and by the inch unit in case of GpMetafile.
  322. //--------------------------------------------------------------------------
  323. class GpTexture : public GpElementaryBrush
  324. {
  325. public:
  326. // Constructors
  327. GpTexture() {
  328. DefaultBrush();
  329. }
  330. GpTexture(GpImage* image, GpWrapMode wrapMode = WrapModeTile)
  331. {
  332. InitializeBrush(image, wrapMode, NULL);
  333. }
  334. GpTexture(GpImage* image, GpWrapMode wrapMode, const GpRectF& rect)
  335. {
  336. InitializeBrush(image, wrapMode, &rect);
  337. }
  338. GpTexture(GpImage *image, const GpRectF& rect, const GpImageAttributes *imageAttributes)
  339. {
  340. GpWrapMode wrapMode = WrapModeTile;
  341. if (imageAttributes)
  342. {
  343. wrapMode = imageAttributes->DeviceImageAttributes.wrapMode;
  344. if (!imageAttributes->HasRecoloring())
  345. {
  346. imageAttributes = NULL;
  347. }
  348. }
  349. InitializeBrush(image, wrapMode, &rect, imageAttributes);
  350. }
  351. GpBrush* Clone() const
  352. {
  353. return new GpTexture(this);
  354. }
  355. ~GpTexture() {
  356. if(Image)
  357. Image->Dispose();
  358. }
  359. virtual UINT GetDataSize() const;
  360. virtual GpStatus GetData(IStream * stream) const;
  361. virtual GpStatus SetData(const BYTE * dataBuffer, UINT size);
  362. virtual GpStatus ColorAdjust(
  363. GpRecolor * recolor,
  364. ColorAdjustType type
  365. );
  366. // Get texture brush attributes
  367. GpImage* GetImage()
  368. {
  369. // !!!
  370. // Notice that we're returning a pointer
  371. // to our internal bitmap object here.
  372. return Image;
  373. }
  374. GpImageType GetImageType() const
  375. {
  376. return ImageType;
  377. }
  378. GpBitmap* GetBitmap() const
  379. {
  380. // !!!
  381. // Notice that we're returning a pointer
  382. // to our internal bitmap object here.
  383. if(ImageType == ImageTypeBitmap)
  384. return static_cast<GpBitmap*>(Image);
  385. else
  386. return NULL;
  387. }
  388. GpStatus GetBitmapSize(Size * size) const
  389. {
  390. GpBitmap * brushBitmap = this->GetBitmap();
  391. if (brushBitmap != NULL)
  392. {
  393. brushBitmap->GetSize(size);
  394. return Ok;
  395. }
  396. size->Width = size->Height = 0;
  397. return InvalidParameter;
  398. }
  399. // Check the opacity of bitmap.
  400. BOOL IsOpaque(BOOL ColorsOnly = FALSE) const
  401. {
  402. DpTransparency transparency;
  403. GpBitmap *bitmap = GetBitmap();
  404. if (bitmap == NULL)
  405. {
  406. return FALSE;
  407. }
  408. ASSERT(bitmap->IsValid());
  409. if (ColorsOnly) // get real transparency, not cached
  410. {
  411. if (bitmap->GetTransparencyFlags(&transparency,
  412. PixelFormat32bppPARGB) != Ok)
  413. {
  414. transparency = TransparencyUnknown;
  415. }
  416. }
  417. else
  418. {
  419. if (bitmap->GetTransparencyHint(&transparency) != Ok)
  420. {
  421. transparency = TransparencyUnknown;
  422. }
  423. }
  424. switch (transparency)
  425. {
  426. case TransparencyUnknown:
  427. case TransparencySimple:
  428. case TransparencyComplex:
  429. case TransparencyNearConstant:
  430. return FALSE;
  431. case TransparencyOpaque:
  432. case TransparencyNoAlpha:
  433. return TRUE;
  434. }
  435. ASSERT(FALSE);
  436. return FALSE;
  437. }
  438. BOOL Is01Bitmap() const
  439. {
  440. DpTransparency transparency;
  441. GpBitmap *bitmap = GetBitmap();
  442. if (bitmap == NULL)
  443. {
  444. return FALSE;
  445. }
  446. ASSERT(bitmap->IsValid());
  447. if (bitmap->GetTransparencyHint(&transparency) != Ok)
  448. return FALSE;
  449. switch (transparency)
  450. {
  451. case TransparencyUnknown:
  452. case TransparencyOpaque:
  453. case TransparencyNoAlpha:
  454. case TransparencyComplex:
  455. case TransparencyNearConstant:
  456. return FALSE;
  457. case TransparencySimple:
  458. return TRUE;
  459. }
  460. ASSERT(FALSE);
  461. return FALSE;
  462. }
  463. virtual BOOL IsSolid() const
  464. {
  465. //This may have to change if we change the defination of IsSolid.
  466. //See comment at GpBrush::IsSolid() for more info.
  467. return FALSE;
  468. }
  469. virtual BOOL IsNearConstant(BYTE *MinAlpha, BYTE* MaxAlpha) const
  470. {
  471. DpTransparency transparency;
  472. GpBitmap *bitmap = GetBitmap();
  473. if (bitmap == NULL)
  474. {
  475. return FALSE;
  476. }
  477. ASSERT(bitmap->IsValid());
  478. return (bitmap->GetTransparencyFlags(&transparency,
  479. PixelFormat32bppPARGB,
  480. MinAlpha,
  481. MaxAlpha) == Ok) &&
  482. transparency == TransparencyNearConstant;
  483. }
  484. // See if this texture fill is really a picture fill
  485. BOOL IsPictureFill(
  486. const GpMatrix * worldToDevice,
  487. const GpRect * drawBounds
  488. ) const;
  489. // Determine if the brushes are equivalent
  490. virtual BOOL isEqual(const GpBrush * brush) const
  491. {
  492. // HACKHACK - To avoid a potentially large bitmap comparison,
  493. // treat all texture brushes as different...
  494. return FALSE;
  495. }
  496. virtual DpOutputSpan* CreateOutputSpan(
  497. DpScanBuffer * scan,
  498. DpContext *context,
  499. const GpRect *drawBounds=NULL);
  500. private:
  501. GpTexture(const GpTexture *brush);
  502. VOID InitializeBrush(
  503. GpImage* image,
  504. GpWrapMode wrapMode,
  505. const GpRectF* rect,
  506. const GpImageAttributes *imageAttributes=NULL);
  507. VOID InitializeBrushBitmap(
  508. GpBitmap* bitmap,
  509. GpWrapMode wrapMode,
  510. const GpRectF* rect,
  511. const GpImageAttributes *imageAttributes,
  512. BOOL useBitmap = FALSE // use the bitmap instead of cloning it?
  513. );
  514. VOID DefaultBrush()
  515. {
  516. InitializeBrushBitmap(NULL, WrapModeTile, NULL, NULL);
  517. }
  518. private:
  519. GpImageType ImageType;
  520. GpImage * Image; // brush image
  521. };
  522. class GpGradientBrush : public GpElementaryBrush
  523. {
  524. public:
  525. virtual VOID GetColors(GpColor* colors) const = 0;
  526. virtual INT GetNumberOfColors() const = 0;
  527. virtual BOOL UsesDefaultColorArray() const = 0;
  528. virtual BOOL IsOpaque(BOOL ColorsOnly = FALSE) const = 0;
  529. virtual GpStatus SetBlend(
  530. const REAL* blendFactors,
  531. const REAL* blendPositions,
  532. INT count)
  533. {
  534. return NotImplemented;
  535. }
  536. // Determine if the brushes are equivalent
  537. virtual BOOL isEqual(const GpBrush * brush) const
  538. {
  539. if (GpElementaryBrush::IsEqual(brush))
  540. {
  541. const DpBrush * deviceBrush = brush->GetDeviceBrush();
  542. return deviceBrush->Rect.Equals(DeviceBrush.Rect);
  543. }
  544. else
  545. {
  546. return FALSE;
  547. }
  548. }
  549. virtual GpStatus BlendWithWhite()
  550. {
  551. return NotImplemented;
  552. }
  553. GpStatus SetSigmaBlend(REAL focus, REAL scale = 1.0f);
  554. GpStatus SetLinearBlend(REAL focus, REAL scale = 1.0f);
  555. protected:
  556. GpGradientBrush()
  557. {
  558. GpMemset(&DeviceBrush.Rect, 0, sizeof(DeviceBrush.Rect));
  559. }
  560. GpGradientBrush(
  561. const GpGradientBrush* brush
  562. ) : GpElementaryBrush(brush)
  563. {
  564. GpMemset(&DeviceBrush.Rect, 0, sizeof(DeviceBrush.Rect));
  565. }
  566. GpStatus GetSigmaBlendArray(
  567. REAL focus,
  568. REAL scale,
  569. INT* count,
  570. REAL* blendFactors,
  571. REAL* blendPositions);
  572. GpStatus GetLinearBlendArray(
  573. REAL focus,
  574. REAL scale,
  575. INT* count,
  576. REAL* blendFactors,
  577. REAL* blendPositions);
  578. };
  579. //--------------------------------------------------------------------------
  580. // Represent rectangular gradient brush object
  581. //--------------------------------------------------------------------------
  582. class GpRectGradient : public GpGradientBrush
  583. {
  584. friend class DpOutputGradientSpan;
  585. friend class DpOutputOneDGradientSpan;
  586. friend class DpOutputLinearGradientSpan;
  587. public:
  588. // Constructors
  589. GpRectGradient(VOID)
  590. {
  591. DefaultBrush();
  592. }
  593. GpRectGradient(
  594. const GpRectF& rect,
  595. const GpColor* colors,
  596. GpWrapMode wrapMode = WrapModeTile)
  597. {
  598. InitializeBrush(rect, colors, wrapMode);
  599. }
  600. virtual GpBrush* Clone() const
  601. {
  602. return new GpRectGradient(this);
  603. }
  604. ~GpRectGradient()
  605. {
  606. GpFree(DeviceBrush.BlendFactors[0]);
  607. GpFree(DeviceBrush.BlendFactors[1]);
  608. GpFree(DeviceBrush.BlendPositions[0]);
  609. GpFree(DeviceBrush.BlendPositions[1]);
  610. GpFree(DeviceBrush.PresetColors);
  611. }
  612. virtual UINT GetDataSize() const;
  613. virtual GpStatus GetData(IStream * stream) const;
  614. virtual GpStatus SetData(const BYTE * dataBuffer, UINT size);
  615. virtual GpStatus ColorAdjust(
  616. GpRecolor * recolor,
  617. ColorAdjustType type
  618. );
  619. virtual GpStatus BlendWithWhite();
  620. // Get/set colors
  621. VOID GetColors(GpColor* colors) const
  622. {
  623. ASSERT(colors);
  624. colors[0] = DeviceBrush.Colors[0];
  625. colors[1] = DeviceBrush.Colors[1];
  626. colors[2] = DeviceBrush.Colors[2];
  627. colors[3] = DeviceBrush.Colors[3];
  628. }
  629. VOID SetColors(const GpColor* colors)
  630. {
  631. ASSERT(colors);
  632. DeviceBrush.Colors[0] = colors[0];
  633. DeviceBrush.Colors[1] = colors[1];
  634. DeviceBrush.Colors[2] = colors[2];
  635. DeviceBrush.Colors[3] = colors[3];
  636. UpdateUid();
  637. }
  638. INT GetNumberOfColors() const {return 4;}
  639. BOOL UsesDefaultColorArray() const {return TRUE;}
  640. // Get/set blend factors
  641. //
  642. // If the blendFactors.length = 1, then it's treated
  643. // as the falloff parameter. Otherwise, it's the array
  644. // of blend factors.
  645. INT GetHorizontalBlendCount()
  646. {
  647. return DeviceBrush.BlendCounts[0];
  648. }
  649. GpStatus GetHorizontalBlend(
  650. REAL* blendFactors,
  651. REAL* blendPositions,
  652. INT count
  653. );
  654. GpStatus SetHorizontalBlend(
  655. const REAL* blendFactors,
  656. const REAL* blendPositions,
  657. INT count
  658. );
  659. INT GetVerticalBlendCount()
  660. {
  661. return DeviceBrush.BlendCounts[1];
  662. }
  663. GpStatus GetVerticalBlend(
  664. REAL* blendFactors,
  665. REAL* blendPositions,
  666. INT count
  667. );
  668. virtual GpStatus SetVerticalBlend(
  669. const REAL* blendFactors,
  670. const REAL* blendPositions,
  671. INT count
  672. );
  673. BOOL HasPresetColors() const
  674. {
  675. return DeviceBrush.UsesPresetColors;
  676. }
  677. // Check the opacity of this brush element. It is opaque only if
  678. // ALL of the colors are opaque.
  679. BOOL IsOpaque(BOOL ColorsOnly = FALSE) const
  680. {
  681. BOOL opaque = ColorsOnly || DeviceBrush.Wrap != WrapModeClamp;
  682. if (HasPresetColors())
  683. {
  684. INT i=0;
  685. while (opaque && (i < DeviceBrush.BlendCounts[0]))
  686. {
  687. opaque = opaque && GpColor(DeviceBrush.PresetColors[i]).IsOpaque();
  688. i++;
  689. }
  690. }
  691. else
  692. {
  693. opaque = opaque &&
  694. DeviceBrush.Colors[0].IsOpaque() &&
  695. DeviceBrush.Colors[1].IsOpaque() &&
  696. DeviceBrush.Colors[2].IsOpaque() &&
  697. DeviceBrush.Colors[3].IsOpaque();
  698. }
  699. return opaque;
  700. }
  701. virtual BOOL IsSolid() const
  702. {
  703. //This may have to change if we change the defination of IsSolid.
  704. //See comment at GpBrush::IsSolid() for more info.
  705. return FALSE;
  706. }
  707. virtual BOOL IsNearConstant(BYTE* MinAlpha, BYTE* MaxAlpha) const
  708. {
  709. if (HasPresetColors())
  710. {
  711. *MaxAlpha = GpColor(DeviceBrush.PresetColors[0]).GetAlpha();
  712. *MinAlpha = *MaxAlpha;
  713. for (INT i=1; i<DeviceBrush.BlendCounts[0]; i++)
  714. {
  715. *MaxAlpha = max(*MaxAlpha, GpColor(DeviceBrush.PresetColors[i]).GetAlpha());
  716. *MinAlpha = min(*MinAlpha, GpColor(DeviceBrush.PresetColors[i]).GetAlpha());
  717. }
  718. }
  719. else
  720. {
  721. *MinAlpha = min(min(DeviceBrush.Colors[0].GetAlpha(),
  722. DeviceBrush.Colors[1].GetAlpha()),
  723. min(DeviceBrush.Colors[2].GetAlpha(),
  724. DeviceBrush.Colors[3].GetAlpha()));
  725. *MaxAlpha = max(max(DeviceBrush.Colors[0].GetAlpha(),
  726. DeviceBrush.Colors[1].GetAlpha()),
  727. max(DeviceBrush.Colors[2].GetAlpha(),
  728. DeviceBrush.Colors[3].GetAlpha()));
  729. }
  730. return (*MaxAlpha - *MinAlpha < NEARCONSTANTALPHA);
  731. }
  732. virtual BOOL IsEqual(const GpBrush * brush) const;
  733. virtual DpOutputSpan* CreateOutputSpan(
  734. DpScanBuffer * scan,
  735. DpContext *context,
  736. const GpRect *drawBounds=NULL);
  737. protected:
  738. GpRectGradient(const GpRectGradient* brush);
  739. VOID InitializeBrush(
  740. const GpRectF& rect,
  741. const GpColor* colors,
  742. GpWrapMode wrapMode
  743. )
  744. {
  745. DeviceBrush.Type = (BrushType) BrushTypeLinearGradient; // BrushRectGrad;
  746. DeviceBrush.Wrap = wrapMode;
  747. DeviceBrush.Rect = rect;
  748. DeviceBrush.UsesPresetColors = FALSE;
  749. DeviceBrush.BlendCounts[0] = 1;
  750. DeviceBrush.BlendCounts[1] = 1;
  751. DeviceBrush.BlendFactors[0] = NULL;
  752. DeviceBrush.BlendFactors[1] = NULL;
  753. DeviceBrush.BlendPositions[0] = NULL;
  754. DeviceBrush.BlendPositions[1] = NULL;
  755. DeviceBrush.Falloffs[0] = 1;
  756. DeviceBrush.Falloffs[1] = 1;
  757. DeviceBrush.PresetColors = NULL;
  758. if(!WrapModeIsValid(wrapMode) || rect.Width <= 0 || rect.Height <= 0)
  759. {
  760. SetValid(FALSE);
  761. return;
  762. }
  763. SetValid(TRUE);
  764. SetColors(colors);
  765. }
  766. VOID DefaultBrush(VOID)
  767. {
  768. DeviceBrush.Type = (BrushType) BrushTypeLinearGradient; //BrushRectGrad;
  769. DeviceBrush.Wrap = WrapModeTile;
  770. DeviceBrush.UsesPresetColors = FALSE;
  771. GpMemset(&DeviceBrush.Rect, 0, sizeof(Rect));
  772. GpColor color; // NULL brush
  773. DeviceBrush.Colors[0] = color;
  774. DeviceBrush.Colors[1] = color;
  775. DeviceBrush.Colors[2] = color;
  776. DeviceBrush.Colors[3] = color;
  777. DeviceBrush.BlendCounts[0] = 1;
  778. DeviceBrush.BlendCounts[1] = 1;
  779. DeviceBrush.BlendFactors[0] = NULL;
  780. DeviceBrush.BlendFactors[1] = NULL;
  781. DeviceBrush.BlendPositions[0] = NULL;
  782. DeviceBrush.BlendPositions[1] = NULL;
  783. DeviceBrush.Falloffs[0] = 1;
  784. DeviceBrush.Falloffs[1] = 1;
  785. DeviceBrush.PresetColors = NULL;
  786. // Defaults used for GpLineGradient
  787. DeviceBrush.IsAngleScalable = FALSE;
  788. DeviceBrush.Points[0].X = DeviceBrush.Points[0].Y = 0;
  789. DeviceBrush.Points[1].X = DeviceBrush.Points[1].Y = 0;
  790. SetValid(FALSE);
  791. }
  792. protected:
  793. };
  794. class GpLineGradient : public GpRectGradient
  795. {
  796. friend class DpOutputGradientSpan;
  797. friend class DpOutputOneDGradientSpan;
  798. public:
  799. // Constructors
  800. GpLineGradient(VOID)
  801. {
  802. DefaultBrush();
  803. }
  804. GpLineGradient(
  805. const GpPointF& point1,
  806. const GpPointF& point2,
  807. const GpColor& color1,
  808. const GpColor& color2,
  809. GpWrapMode wrapMode = WrapModeTile
  810. );
  811. GpLineGradient(
  812. const GpRectF& rect,
  813. const GpColor& color1,
  814. const GpColor& color2,
  815. LinearGradientMode mode,
  816. GpWrapMode wrapMode = WrapModeTile
  817. );
  818. GpLineGradient(
  819. const GpRectF& rect,
  820. const GpColor& color1,
  821. const GpColor& color2,
  822. REAL angle,
  823. BOOL isAngleScalable = FALSE,
  824. GpWrapMode wrapMode = WrapModeTile
  825. );
  826. GpLineGradient(
  827. const GpRectF& rect,
  828. const GpColor* colors,
  829. GpWrapMode wrapMode = WrapModeTile)
  830. :GpRectGradient(rect, colors, wrapMode)
  831. {
  832. }
  833. GpBrush* Clone() const
  834. {
  835. return new GpLineGradient(this);
  836. }
  837. virtual GpStatus BlendWithWhite();
  838. // Note: ChangeLinePoints works dramatically differently than SetLinePoints.
  839. // ChangeLinePoints is more like the constructor that takes points.
  840. GpStatus
  841. GpLineGradient::ChangeLinePoints(
  842. const GpPointF& point1,
  843. const GpPointF& point2,
  844. BOOL isAngleScalable
  845. );
  846. GpStatus SetLinePoints(const GpPointF& point1, const GpPointF& point2);
  847. GpStatus GetLinePoints(GpPointF* points);
  848. VOID SetLineColors(const GpColor& color1, const GpColor& color2)
  849. {
  850. DeviceBrush.Colors[0] = color1;
  851. DeviceBrush.Colors[1] = color2;
  852. DeviceBrush.Colors[2] = color1;
  853. DeviceBrush.Colors[3] = color2;
  854. UpdateUid();
  855. }
  856. VOID GetLineColors(GpColor* colors)
  857. {
  858. colors[0] = DeviceBrush.Colors[0];
  859. colors[1] = DeviceBrush.Colors[1];
  860. }
  861. // Get/set blend factors
  862. //
  863. // If the blendFactors.length = 1, then it's treated
  864. // as the falloff parameter. Otherwise, it's the array
  865. // of blend factors.
  866. INT GetBlendCount()
  867. {
  868. return GetHorizontalBlendCount();
  869. }
  870. GpStatus GetBlend(REAL* blendFactors, REAL* blendPositions, INT count)
  871. {
  872. return GetHorizontalBlend(blendFactors, blendPositions, count);
  873. }
  874. GpStatus SetBlend(
  875. const REAL* blendFactors,
  876. const REAL* blendPositions,
  877. INT count
  878. )
  879. {
  880. return SetHorizontalBlend(blendFactors, blendPositions, count);
  881. }
  882. // Setting Vertical Blend factor is not allowed.
  883. GpStatus SetVerticalBlend(
  884. const REAL* blendFactors,
  885. const REAL* blendPositions,
  886. INT count
  887. )
  888. {
  889. ASSERT(0);
  890. return GenericError;
  891. }
  892. // Get/set preset blend-factors
  893. INT GetPresetBlendCount();
  894. GpStatus GetPresetBlend(
  895. GpColor* blendColors,
  896. REAL* blendPositions,
  897. INT count);
  898. GpStatus SetPresetBlend(
  899. const GpColor* blendColors,
  900. const REAL* blendPositions,
  901. INT count);
  902. virtual GpSpecialGradientType
  903. GetSpecialGradientType(const GpMatrix* matrix) const
  904. {
  905. GpMatrix m;
  906. GpMatrix::MultiplyMatrix(m, DeviceBrush.Xform, *matrix);
  907. if (m.IsTranslateScale())
  908. {
  909. return GradientTypeVertical;
  910. }
  911. else if (REALABS(m.GetM11()) < CPLX_EPSILON &&
  912. REALABS(m.GetM12()) >= CPLX_EPSILON &&
  913. REALABS(m.GetM21()) >= CPLX_EPSILON &&
  914. REALABS(m.GetM22()) < CPLX_EPSILON)
  915. {
  916. return GradientTypeHorizontal;
  917. }
  918. else
  919. {
  920. return GradientTypeDiagonal;
  921. }
  922. }
  923. protected:
  924. GpLineGradient(const GpLineGradient* brush);
  925. GpStatus SetLineGradient(
  926. const GpPointF& point1,
  927. const GpPointF& point2,
  928. const GpRectF& rect,
  929. const GpColor& color1,
  930. const GpColor& color2,
  931. REAL angle,
  932. BOOL isAngleScalable = FALSE,
  933. GpWrapMode wrapMode = WrapModeTile
  934. );
  935. };
  936. //--------------------------------------------------------------------------
  937. // Represent radial gradient brush object
  938. //--------------------------------------------------------------------------
  939. #if 0
  940. class GpRadialGradient : public GpGradientBrush
  941. {
  942. friend class DpOutputGradientSpan;
  943. friend class DpOutputOneDGradientSpan;
  944. public:
  945. // Constructors
  946. GpRadialGradient(VOID)
  947. {
  948. DefaultBrush();
  949. }
  950. GpRadialGradient(
  951. const GpRectF& rect,
  952. const GpColor& centerColor,
  953. const GpColor& boundaryColor,
  954. GpWrapMode wrapMode = WrapModeClamp
  955. )
  956. {
  957. InitializeBrush(rect, centerColor, boundaryColor, wrapMode);
  958. }
  959. GpBrush* Clone() const
  960. {
  961. return new GpRadialGradient(this);
  962. }
  963. ~GpRadialGradient()
  964. {
  965. GpFree(DeviceBrush.BlendFactors[0]);
  966. GpFree(DeviceBrush.BlendPositions[0]);
  967. GpFree(DeviceBrush.PresetColors);
  968. }
  969. virtual UINT GetDataSize() const;
  970. virtual GpStatus GetData(IStream * stream) const;
  971. virtual GpStatus SetData(const BYTE * dataBuffer, UINT size);
  972. virtual GpStatus ColorAdjust(
  973. GpRecolor * recolor,
  974. ColorAdjustType type
  975. );
  976. // Get/set color attributes
  977. VOID SetCenterColor(const GpColor& color)
  978. {
  979. DeviceBrush.Colors[0] = color;
  980. UpdateUid();
  981. }
  982. VOID SetBoundaryColor(const GpColor& color)
  983. {
  984. DeviceBrush.Colors[1] = color;
  985. UpdateUid();
  986. }
  987. GpColor GetCenterColor() const
  988. {
  989. return DeviceBrush.Colors[0];
  990. }
  991. GpColor GetBoundaryColor() const
  992. {
  993. return DeviceBrush.Colors[1];
  994. }
  995. VOID GetColors(GpColor* colors) const
  996. {
  997. colors[0] = DeviceBrush.Colors[0];
  998. colors[1] = DeviceBrush.Colors[1];
  999. }
  1000. INT GetNumberOfColors() const {return 2;}
  1001. BOOL UsesDefaultColorArray() const {return TRUE;}
  1002. // Get/set falloff / blend-factors
  1003. INT GetBlendCount()
  1004. {
  1005. return DeviceBrush.BlendCounts[0];
  1006. }
  1007. GpStatus GetBlend(
  1008. REAL* blendFactors,
  1009. REAL* blendPositions,
  1010. INT count) const;
  1011. GpStatus SetBlend(
  1012. const REAL* blendFactors,
  1013. const REAL* blendPosition,
  1014. INT count
  1015. );
  1016. // Get/set preset blend-factors
  1017. BOOL HasPresetColors() const
  1018. {
  1019. return DeviceBrush.UsesPresetColors;
  1020. }
  1021. INT GetPresetBlendCount() const;
  1022. GpStatus GetPresetBlend(
  1023. GpColor* blendColors,
  1024. REAL* blendPositions,
  1025. INT count) const;
  1026. GpStatus SetPresetBlend(
  1027. const GpColor* blendColors,
  1028. const REAL* blendPositions,
  1029. INT count);
  1030. // Check the opacity of this brush element.
  1031. virtual BOOL IsOpaque(BOOL ColorsOnly = FALSE) const
  1032. {
  1033. // This gradient brush is opaque only if
  1034. // all the colors are opaque and wrap mode is not WrapModeClamp.
  1035. // In case of WrapModeClamp mode, we need alpha channel to do
  1036. // clipping outside of the oval.
  1037. return (DeviceBrush.Colors[0].IsOpaque() &&
  1038. DeviceBrush.Colors[1].IsOpaque() &&
  1039. (ColorsOnly || DeviceBrush.Wrap != WrapModeClamp));
  1040. }
  1041. virtual BOOL IsSolid() const
  1042. {
  1043. //This may have to change if we change the defination of IsSolid.
  1044. //See comment at GpBrush::IsSolid() for more info.
  1045. return FALSE;
  1046. }
  1047. virtual BOOL IsNearConstant(BYTE* MinAlpha, BYTE* MaxAlpha) const
  1048. {
  1049. *MinAlpha = min(DeviceBrush.Colors[0].GetAlpha(),
  1050. DeviceBrush.Colors[1].GetAlpha());
  1051. *MaxAlpha = max(DeviceBrush.Colors[0].GetAlpha(),
  1052. DeviceBrush.Colors[1].GetAlpha());
  1053. return (*MaxAlpha - *MinAlpha < NEARCONSTANTALPHA);
  1054. }
  1055. virtual BOOL IsEqual(const GpBrush * brush) const;
  1056. virtual DpOutputSpan* CreateOutputSpan(
  1057. DpScanBuffer * scan,
  1058. DpContext *context,
  1059. const GpRect *drawBounds=NULL);
  1060. private:
  1061. GpRadialGradient(const GpRadialGradient *brush);
  1062. VOID
  1063. InitializeBrush(
  1064. const GpRectF& rect,
  1065. const GpColor& centerColor,
  1066. const GpColor& boundaryColor,
  1067. GpWrapMode wrapMode
  1068. )
  1069. {
  1070. DeviceBrush.Type = (BrushType)-1; //BrushRadialGrad;
  1071. DeviceBrush.Wrap = wrapMode;
  1072. DeviceBrush.Rect = rect;
  1073. DeviceBrush.UsesPresetColors = FALSE;
  1074. DeviceBrush.Colors[0] = centerColor;
  1075. DeviceBrush.Colors[1] = boundaryColor;
  1076. DeviceBrush.BlendFactors[0] = NULL;
  1077. DeviceBrush.BlendPositions[0] = NULL;
  1078. DeviceBrush.BlendCounts[0] = 1;
  1079. DeviceBrush.Falloffs[0] = 1;
  1080. DeviceBrush.PresetColors = NULL;
  1081. SetValid(WrapModeIsValid(wrapMode) && rect.Width > 0 && rect.Height > 0);
  1082. }
  1083. VOID DefaultBrush(VOID)
  1084. {
  1085. DeviceBrush.Type = (BrushType)-1; //BrushRadialGrad;
  1086. GpMemset(&DeviceBrush.Rect, 0, sizeof(DeviceBrush.Rect));
  1087. DeviceBrush.Wrap = WrapModeTile;
  1088. DeviceBrush.UsesPresetColors = FALSE;
  1089. GpColor color(255, 255, 255); // Opaque white
  1090. DeviceBrush.Colors[0] = color;
  1091. DeviceBrush.Colors[1] = color;
  1092. DeviceBrush.BlendFactors[0] = NULL;
  1093. DeviceBrush.BlendPositions[0] = NULL;
  1094. DeviceBrush.BlendCounts[0] = 1;
  1095. DeviceBrush.Falloffs[0] = 1;
  1096. DeviceBrush.PresetColors = NULL;
  1097. SetValid(FALSE);
  1098. }
  1099. };
  1100. #endif
  1101. //--------------------------------------------------------------------------
  1102. // Represent triangle gradient brush object
  1103. //--------------------------------------------------------------------------
  1104. #if 0
  1105. class GpTriangleGradient : public GpGradientBrush
  1106. {
  1107. friend class DpOutputTriangleGradientSpan;
  1108. public:
  1109. // Constructors
  1110. GpTriangleGradient(VOID)
  1111. {
  1112. DefaultBrush();
  1113. }
  1114. GpTriangleGradient(
  1115. const GpPointF* points,
  1116. const GpColor* colors,
  1117. GpWrapMode wrapMode = WrapModeClamp
  1118. )
  1119. {
  1120. InitializeBrush(
  1121. points,
  1122. colors,
  1123. wrapMode);
  1124. }
  1125. GpBrush* Clone() const
  1126. {
  1127. return new GpTriangleGradient(this);
  1128. }
  1129. ~GpTriangleGradient()
  1130. {
  1131. GpFree(DeviceBrush.BlendFactors[0]);
  1132. GpFree(DeviceBrush.BlendFactors[1]);
  1133. GpFree(DeviceBrush.BlendFactors[2]);
  1134. GpFree(DeviceBrush.BlendPositions[0]);
  1135. GpFree(DeviceBrush.BlendPositions[1]);
  1136. GpFree(DeviceBrush.BlendPositions[2]);
  1137. }
  1138. virtual UINT GetDataSize() const;
  1139. virtual GpStatus GetData(IStream * stream) const;
  1140. virtual GpStatus SetData(const BYTE * dataBuffer, UINT size);
  1141. virtual GpStatus ColorAdjust(
  1142. GpRecolor * recolor,
  1143. ColorAdjustType type
  1144. );
  1145. // Get/set colors
  1146. VOID GetColors(GpColor* colors) const
  1147. {
  1148. colors[0] = DeviceBrush.Colors[0];
  1149. colors[1] = DeviceBrush.Colors[1];
  1150. colors[2] = DeviceBrush.Colors[2];
  1151. }
  1152. VOID SetColors(const GpColor* colors)
  1153. {
  1154. DeviceBrush.Colors[0] = colors[0];
  1155. DeviceBrush.Colors[1] = colors[1];
  1156. DeviceBrush.Colors[2] = colors[2];
  1157. UpdateUid();
  1158. }
  1159. // Get/set triangle
  1160. VOID GetTriangle(GpPointF* points) const
  1161. {
  1162. points[0] = DeviceBrush.Points[0];
  1163. points[1] = DeviceBrush.Points[1];
  1164. points[2] = DeviceBrush.Points[2];
  1165. }
  1166. VOID SetTriangle(const GpPointF* points)
  1167. {
  1168. DeviceBrush.Points[0] = points[0];
  1169. DeviceBrush.Points[1] = points[1];
  1170. DeviceBrush.Points[2] = points[2];
  1171. UpdateUid();
  1172. }
  1173. INT GetNumberOfColors() const {return 3;}
  1174. BOOL UsesDefaultColorArray() const {return TRUE;}
  1175. // Get/set falloff / blend-factors
  1176. INT GetBlendCount0() const
  1177. {
  1178. return DeviceBrush.BlendCounts[0];
  1179. }
  1180. INT GetBlendCount1() const
  1181. {
  1182. return DeviceBrush.BlendCounts[1];
  1183. }
  1184. INT GetBlendCount2() const
  1185. {
  1186. return DeviceBrush.BlendCounts[2];
  1187. }
  1188. //!!! bhouse We really don't need all of these GetBlendX methods. We
  1189. // should just implement a single GetBlend() which takes an index.
  1190. // With the change to the data layout, the argument for this method
  1191. // is stronger. This should remove a bunch of redundant code.
  1192. GpStatus GetBlend0(
  1193. REAL* blendFactors,
  1194. REAL* blendPositions,
  1195. INT count) const;
  1196. GpStatus SetBlend0(
  1197. const REAL* blendFactors,
  1198. const REAL* blendPositions,
  1199. INT count);
  1200. GpStatus GetBlend1(
  1201. REAL* blendFactors,
  1202. REAL* blendPositions,
  1203. INT count) const;
  1204. GpStatus SetBlend1(
  1205. const REAL* blendFactors,
  1206. const REAL* blendPositions,
  1207. INT count);
  1208. GpStatus GetBlend2(
  1209. REAL* blendFactors,
  1210. REAL* blendPositions,
  1211. INT count) const;
  1212. GpStatus SetBlend2(
  1213. const REAL* blendFactors,
  1214. const REAL* blendPositions,
  1215. INT count);
  1216. // Check the opacity of this brush element.
  1217. virtual BOOL IsOpaque(BOOL ColorsOnly = FALSE) const
  1218. {
  1219. // This gradient brush is opaque only if
  1220. // all the colors are opaque.
  1221. // In case of WrapModeClamp mode, we need alpha channel to do
  1222. // clipping outside of the triangle.
  1223. return (DeviceBrush.Colors[0].IsOpaque() &&
  1224. DeviceBrush.Colors[1].IsOpaque() &&
  1225. DeviceBrush.Colors[2].IsOpaque() &&
  1226. (ColorsOnly || DeviceBrush.Wrap != WrapModeClamp));
  1227. }
  1228. virtual BOOL IsSolid() const
  1229. {
  1230. //This may have to change if we change the defination of IsSolid.
  1231. //See comment at GpBrush::IsSolid() for more info.
  1232. return FALSE;
  1233. }
  1234. virtual BOOL IsNearConstant(BYTE* MinAlpha, BYTE* MaxAlpha) const
  1235. {
  1236. *MinAlpha = min(DeviceBrush.Colors[0].GetAlpha(),
  1237. DeviceBrush.Colors[1].GetAlpha());
  1238. *MinAlpha = min(*MinAlpha,
  1239. DeviceBrush.Colors[2].GetAlpha());
  1240. *MaxAlpha = max(DeviceBrush.Colors[0].GetAlpha(),
  1241. DeviceBrush.Colors[1].GetAlpha());
  1242. *MaxAlpha = min(*MaxAlpha,
  1243. DeviceBrush.Colors[2].GetAlpha());
  1244. return (*MaxAlpha - *MinAlpha < NEARCONSTANTALPHA);
  1245. }
  1246. virtual BOOL IsEqual(const GpBrush * brush) const;
  1247. virtual DpOutputSpan* CreateOutputSpan(
  1248. DpScanBuffer * scan,
  1249. DpContext *context,
  1250. const pRect *drawBounds=NULL);
  1251. protected: // GDI+ Internal
  1252. GpTriangleGradient(const GpTriangleGradient* brush);
  1253. VOID
  1254. InitializeBrush(
  1255. const GpPointF* points,
  1256. const GpColor* colors,
  1257. GpWrapMode wrapMode
  1258. )
  1259. {
  1260. DeviceBrush.Type = (BrushType)-1; //BrushTriangleGrad;
  1261. DeviceBrush.Wrap = wrapMode;
  1262. // Set the blending and fall off factors.
  1263. DeviceBrush.Falloffs[0] = 1;
  1264. DeviceBrush.Falloffs[1] = 1;
  1265. DeviceBrush.Falloffs[2] = 1;
  1266. DeviceBrush.BlendCounts[0] = 1;
  1267. DeviceBrush.BlendCounts[1] = 1;
  1268. DeviceBrush.BlendCounts[2] = 1;
  1269. DeviceBrush.BlendFactors[0] = NULL;
  1270. DeviceBrush.BlendFactors[1] = NULL;
  1271. DeviceBrush.BlendFactors[2] = NULL;
  1272. DeviceBrush.BlendPositions[0] = NULL;
  1273. DeviceBrush.BlendPositions[1] = NULL;
  1274. DeviceBrush.BlendPositions[2] = NULL;
  1275. GpMemcpy(&DeviceBrush.Points[0],
  1276. points,
  1277. 3*sizeof(GpPointF));
  1278. GpMemcpy(&DeviceBrush.Colors[0],
  1279. colors,
  1280. 3*sizeof(GpColor));
  1281. // Get the boundary rectangle.
  1282. REAL xmin, xmax, ymin, ymax;
  1283. xmin = min(DeviceBrush.Points[0].X,
  1284. DeviceBrush.Points[1].X);
  1285. xmax = max(DeviceBrush.Points[0].X,
  1286. DeviceBrush.Points[1].X);
  1287. ymin = min(DeviceBrush.Points[0].Y,
  1288. DeviceBrush.Points[1].Y);
  1289. ymax = max(DeviceBrush.Points[0].Y,
  1290. DeviceBrush.Points[1].Y);
  1291. xmin = min(xmin, DeviceBrush.Points[2].X);
  1292. xmax = max(xmax, DeviceBrush.Points[2].X);
  1293. ymin = min(ymin, DeviceBrush.Points[2].Y);
  1294. ymax = max(ymax, DeviceBrush.Points[2].Y);
  1295. DeviceBrush.Rect.X = xmin;
  1296. DeviceBrush.Rect.Width = xmax - xmin;
  1297. DeviceBrush.Rect.Y = ymin;
  1298. DeviceBrush.Rect.Height = ymax - ymin;
  1299. if(!WrapModeIsValid(wrapMode) ||
  1300. DeviceBrush.Rect.Width <= 0 ||
  1301. DeviceBrush.Rect.Height <= 0)
  1302. {
  1303. SetValid(FALSE);
  1304. return;
  1305. }
  1306. SetValid(TRUE);
  1307. }
  1308. VOID DefaultBrush()
  1309. {
  1310. DeviceBrush.Type = (BrushType)-1; //BrushTriangleGrad;
  1311. GpMemset(&DeviceBrush.Points, 0, 3*sizeof(GpPointF));
  1312. DeviceBrush.Wrap = WrapModeClamp;
  1313. GpColor color(255, 255, 255); // Opaque white
  1314. DeviceBrush.Colors[0] = color;
  1315. DeviceBrush.Colors[1] = color;
  1316. DeviceBrush.Colors[2] = color;
  1317. GpMemset(&DeviceBrush.Rect, 0, sizeof(DeviceBrush.Rect));
  1318. DeviceBrush.Falloffs[0] = 1;
  1319. DeviceBrush.Falloffs[1] = 1;
  1320. DeviceBrush.Falloffs[2] = 1;
  1321. DeviceBrush.BlendCounts[0] = 1;
  1322. DeviceBrush.BlendCounts[1] = 1;
  1323. DeviceBrush.BlendCounts[2] = 1;
  1324. DeviceBrush.BlendFactors[0] = NULL;
  1325. DeviceBrush.BlendFactors[1] = NULL;
  1326. DeviceBrush.BlendFactors[2] = NULL;
  1327. DeviceBrush.BlendPositions[0] = NULL;
  1328. DeviceBrush.BlendPositions[1] = NULL;
  1329. DeviceBrush.BlendPositions[2] = NULL;
  1330. SetValid(FALSE);
  1331. }
  1332. };
  1333. #endif
  1334. //--------------------------------------------------------------------------
  1335. // Represent polygon gradient brush object
  1336. //--------------------------------------------------------------------------
  1337. class GpPathGradient : public GpGradientBrush
  1338. {
  1339. friend class DpOutputPathGradientSpan;
  1340. friend class DpOutputOneDPathGradientSpan;
  1341. public:
  1342. // Constructors
  1343. GpPathGradient()
  1344. {
  1345. DefaultBrush();
  1346. }
  1347. GpPathGradient(
  1348. const GpPointF* points,
  1349. INT count,
  1350. GpWrapMode wrapMode = WrapModeClamp
  1351. )
  1352. {
  1353. InitializeBrush(
  1354. points,
  1355. count,
  1356. wrapMode);
  1357. }
  1358. GpPathGradient(
  1359. const GpPath* path,
  1360. GpWrapMode wrapMode = WrapModeClamp
  1361. )
  1362. {
  1363. DefaultBrush();
  1364. DeviceBrush.Wrap = wrapMode;
  1365. if(path)
  1366. {
  1367. DeviceBrush.Path = new GpPath((GpPath*) path);
  1368. PrepareBrush();
  1369. }
  1370. else
  1371. DeviceBrush.Path = NULL;
  1372. }
  1373. BOOL IsRectangle() const;
  1374. GpBrush* Clone() const
  1375. {
  1376. return new GpPathGradient(this);
  1377. }
  1378. ~GpPathGradient()
  1379. {
  1380. if(DeviceBrush.Path)
  1381. delete DeviceBrush.Path;
  1382. else
  1383. GpFree(DeviceBrush.PointsPtr);
  1384. GpFree(DeviceBrush.ColorsPtr);
  1385. GpFree(DeviceBrush.BlendFactors[0]);
  1386. GpFree(DeviceBrush.BlendPositions[0]);
  1387. GpFree(DeviceBrush.PresetColors);
  1388. if(MorphedBrush)
  1389. delete MorphedBrush;
  1390. }
  1391. virtual UINT GetDataSize() const;
  1392. virtual GpStatus GetData(IStream * stream) const;
  1393. virtual GpStatus SetData(const BYTE * dataBuffer, UINT size);
  1394. virtual GpStatus ColorAdjust(
  1395. GpRecolor * recolor,
  1396. ColorAdjustType type
  1397. );
  1398. virtual GpStatus BlendWithWhite();
  1399. // Get/set colors
  1400. VOID GetCenterColor(GpColor* color) const
  1401. {
  1402. if(color)
  1403. *color = DeviceBrush.Colors[0];
  1404. }
  1405. VOID SetCenterColor(const GpColor& color)
  1406. {
  1407. DeviceBrush.Colors[0] = color;
  1408. UpdateUid();
  1409. }
  1410. GpStatus GetSurroundColor(GpColor* color, INT index) const
  1411. {
  1412. if(color && index >= 0 && index < DeviceBrush.Count)
  1413. {
  1414. if(DeviceBrush.OneSurroundColor)
  1415. *color = DeviceBrush.ColorsPtr[0];
  1416. else
  1417. *color = DeviceBrush.ColorsPtr[index];
  1418. return Ok;
  1419. }
  1420. else
  1421. return InvalidParameter;
  1422. }
  1423. GpStatus SetSurroundColor(GpColor& color, INT index);
  1424. GpStatus SetSurroundColors(const GpColor* colors);
  1425. GpStatus GetSurroundColors(GpColor* colors) const
  1426. {
  1427. GpStatus status = InvalidParameter;
  1428. if(IsValid() && colors) {
  1429. GpMemcpy(colors,
  1430. DeviceBrush.ColorsPtr,
  1431. DeviceBrush.Count*sizeof(GpColor));
  1432. status = Ok;
  1433. }
  1434. return status;
  1435. }
  1436. // Get/set polygon
  1437. GpStatus GetPolygon(GpPointF* points)
  1438. {
  1439. GpStatus status = InvalidParameter;
  1440. ASSERT(DeviceBrush.Count > 0);
  1441. if(IsValid() && points && DeviceBrush.Count > 0)
  1442. {
  1443. GpMemcpy(points,
  1444. DeviceBrush.PointsPtr,
  1445. DeviceBrush.Count*sizeof(GpPointF));
  1446. status = Ok;
  1447. }
  1448. return status;
  1449. }
  1450. GpStatus SetPolygon(const GpPointF* points)
  1451. {
  1452. GpStatus status = InvalidParameter;
  1453. ASSERT(DeviceBrush.Count > 0);
  1454. if(IsValid() && points && DeviceBrush.Count > 0)
  1455. {
  1456. GpMemcpy(DeviceBrush.PointsPtr,
  1457. points,
  1458. DeviceBrush.Count*sizeof(GpPointF));
  1459. UpdateUid();
  1460. status = Ok;
  1461. }
  1462. return status;
  1463. }
  1464. GpStatus GetPoint(GpPointF* point, INT index) const
  1465. {
  1466. if(point && index >= 0 && index < DeviceBrush.Count)
  1467. {
  1468. *point = DeviceBrush.PointsPtr[index];
  1469. return Ok;
  1470. }
  1471. else
  1472. return GenericError;
  1473. }
  1474. GpStatus SetPoint(GpPointF& point, INT index)
  1475. {
  1476. if(index >= 0 && index < DeviceBrush.Count)
  1477. {
  1478. DeviceBrush.PointsPtr[index] = point;
  1479. UpdateUid();
  1480. return Ok;
  1481. }
  1482. else
  1483. return InvalidParameter;
  1484. }
  1485. GpStatus GetCenterPoint(GpPointF* point) const
  1486. {
  1487. if(point)
  1488. {
  1489. *point = DeviceBrush.Points[0];
  1490. return Ok;
  1491. }
  1492. else
  1493. return InvalidParameter;
  1494. }
  1495. GpStatus SetCenterPoint(const GpPointF& point)
  1496. {
  1497. DeviceBrush.Points[0] = point;
  1498. UpdateUid();
  1499. return Ok;
  1500. }
  1501. GpStatus GetInflationFactor(REAL* inflation) const
  1502. {
  1503. if (inflation)
  1504. {
  1505. *inflation = InflationFactor;
  1506. return Ok;
  1507. }
  1508. else
  1509. {
  1510. return InvalidParameter;
  1511. }
  1512. }
  1513. GpStatus SetInflationFactor(REAL inflation)
  1514. {
  1515. InflationFactor = inflation;
  1516. UpdateUid();
  1517. return Ok;
  1518. }
  1519. GpStatus GetFocusScales(REAL* xScale, REAL* yScale)
  1520. {
  1521. if(xScale && yScale)
  1522. {
  1523. *xScale = DeviceBrush.FocusScaleX;
  1524. *yScale = DeviceBrush.FocusScaleY;
  1525. return Ok;
  1526. }
  1527. else
  1528. return InvalidParameter;
  1529. }
  1530. GpStatus SetFocusScales(REAL xScale, REAL yScale)
  1531. {
  1532. DeviceBrush.FocusScaleX = xScale;
  1533. DeviceBrush.FocusScaleY = yScale;
  1534. UpdateUid();
  1535. return Ok;
  1536. }
  1537. // Number of Surround Points and Colors.
  1538. INT GetNumberOfPoints() const {return DeviceBrush.Count;}
  1539. INT GetNumberOfColors() const {return DeviceBrush.Count;}
  1540. BOOL UsesDefaultColorArray() const {return FALSE;} // Don't use
  1541. // the default array.
  1542. VOID GetColors(GpColor* colors) const // Implement a vurtual function.
  1543. {
  1544. GetSurroundColors(colors);
  1545. }
  1546. // Get/set falloff / blend-factors
  1547. BOOL HasPresetColors() const
  1548. {
  1549. return DeviceBrush.UsesPresetColors;
  1550. }
  1551. INT GetBlendCount() const
  1552. {
  1553. return DeviceBrush.BlendCounts[0];
  1554. }
  1555. GpStatus GetBlend(REAL* blendFactors, REAL* blendPositions, INT count) const;
  1556. GpStatus SetBlend(const REAL* blendFactors,
  1557. const REAL* blendPositions, INT count);
  1558. // Get/set preset blend-factors
  1559. INT GetPresetBlendCount() const;
  1560. GpStatus GetPresetBlend(
  1561. GpColor* blendColors,
  1562. REAL* blendPositions,
  1563. INT count) const;
  1564. GpStatus SetPresetBlend(
  1565. const GpColor* blendColors,
  1566. const REAL* blendPositions,
  1567. INT count);
  1568. // Check if the Path Gradient is rectangular.
  1569. BOOL IsRectangular() const
  1570. {
  1571. const GpPointF *points;
  1572. INT count;
  1573. if (DeviceBrush.Path != NULL)
  1574. {
  1575. return DeviceBrush.Path->IsRectangular();
  1576. }
  1577. else
  1578. {
  1579. count = DeviceBrush.Count;
  1580. points = DeviceBrush.PointsPtr;
  1581. }
  1582. if (count > 0 && points != NULL)
  1583. {
  1584. for (INT i=0; i<count; i++)
  1585. {
  1586. INT j = (i+1) % count;
  1587. if (REALABS(points[i].X-points[j].X) > REAL_EPSILON &&
  1588. REALABS(points[i].Y-points[j].Y) > REAL_EPSILON)
  1589. {
  1590. // Points are not at 90 degree angles, not rectangular.
  1591. return FALSE;
  1592. }
  1593. }
  1594. return TRUE;
  1595. }
  1596. return FALSE;
  1597. }
  1598. // Check the opacity of this brush element.
  1599. virtual BOOL IsOpaque(BOOL ColorsOnly = FALSE) const
  1600. {
  1601. // This gradient brush is opaque only if
  1602. // all the colors are opaque (including the center color
  1603. // which is DeviceBrush.Colors[0]).
  1604. // In case of WrapModeClamp mode, we need alpha channel to do
  1605. // clipping outside of the polygon.
  1606. BOOL test;
  1607. if(ColorsOnly || DeviceBrush.Wrap != WrapModeClamp)
  1608. {
  1609. test = (ColorsOnly || IsRectangle()) &&
  1610. DeviceBrush.Colors[0].IsOpaque();
  1611. INT i = 0;
  1612. INT count = DeviceBrush.UsesPresetColors ? DeviceBrush.BlendCounts[0] : DeviceBrush.Count;
  1613. while(i < count && test)
  1614. {
  1615. if (DeviceBrush.UsesPresetColors)
  1616. {
  1617. test = (DeviceBrush.PresetColors[i] & Color::AlphaMask) ==
  1618. Color::AlphaMask;
  1619. }
  1620. else
  1621. {
  1622. test = DeviceBrush.ColorsPtr[i].IsOpaque();
  1623. }
  1624. i++;
  1625. }
  1626. }
  1627. else
  1628. test = FALSE;
  1629. return test;
  1630. }
  1631. virtual GpSpecialGradientType
  1632. GetSpecialGradientType(const GpMatrix* matrix) const
  1633. {
  1634. if (DeviceBrush.UsesPresetColors)
  1635. {
  1636. ARGB color1 = DeviceBrush.Colors[0].GetValue(); // Center color
  1637. ARGB color2 = DeviceBrush.PresetColors[0]; // 1st Preset Color
  1638. for (INT i=1; i<DeviceBrush.BlendCounts[0]; i++)
  1639. {
  1640. ARGB color = DeviceBrush.PresetColors[i];
  1641. if ((color1 != color) && (color2 != color))
  1642. {
  1643. if (color1 == color2)
  1644. {
  1645. color2 = color;
  1646. }
  1647. else
  1648. {
  1649. return GradientTypePathComplex;
  1650. }
  1651. }
  1652. }
  1653. }
  1654. else
  1655. {
  1656. if (DeviceBrush.OneSurroundColor || DeviceBrush.Count <= 2)
  1657. {
  1658. return GradientTypePathTwoStep;
  1659. }
  1660. GpColor *color1 = &(DeviceBrush.ColorsPtr[0]);
  1661. GpColor *color2 = &(DeviceBrush.ColorsPtr[1]);
  1662. for (INT i=2; i<DeviceBrush.Count; i++)
  1663. {
  1664. GpColor *color = &(DeviceBrush.ColorsPtr[i]);
  1665. if (!color1->IsEqual(*color) && !color2->IsEqual(*color))
  1666. {
  1667. if (color1->IsEqual(*color2))
  1668. {
  1669. color2 = color;
  1670. }
  1671. else
  1672. {
  1673. return GradientTypePathComplex;
  1674. }
  1675. }
  1676. }
  1677. }
  1678. return GradientTypePathTwoStep;
  1679. }
  1680. virtual BOOL IsSolid() const
  1681. {
  1682. //This is not optimal but is such a rare case that it probably
  1683. //shouldn't be fixed as long as we keep the defination of IsSolid
  1684. //that we are currently using. See comment at GpBrush::IsSolid for
  1685. //definition.
  1686. return FALSE;
  1687. }
  1688. virtual BOOL IsNearConstant(BYTE* MinAlpha, BYTE* MaxAlpha) const
  1689. {
  1690. if (HasPresetColors())
  1691. {
  1692. *MaxAlpha = DeviceBrush.Colors[0].GetAlpha();
  1693. *MinAlpha = *MaxAlpha;
  1694. for (INT i=0; i<DeviceBrush.BlendCounts[0]; i++)
  1695. {
  1696. *MaxAlpha = max(*MaxAlpha, GpColor(DeviceBrush.PresetColors[i]).GetAlpha());
  1697. *MinAlpha = min(*MinAlpha, GpColor(DeviceBrush.PresetColors[i]).GetAlpha());
  1698. }
  1699. }
  1700. else
  1701. {
  1702. if (DeviceBrush.OneSurroundColor)
  1703. {
  1704. *MaxAlpha = max((DeviceBrush.ColorsPtr[0]).GetAlpha(), // surround
  1705. (DeviceBrush.Colors[0]).GetAlpha()); // center
  1706. *MinAlpha = min((DeviceBrush.ColorsPtr[0]).GetAlpha(), // surround
  1707. (DeviceBrush.Colors[0]).GetAlpha()); // center }
  1708. }
  1709. else
  1710. {
  1711. *MaxAlpha = DeviceBrush.Colors[0].GetAlpha();
  1712. *MinAlpha = *MaxAlpha;
  1713. for (INT i=0; i<DeviceBrush.Count; i++)
  1714. {
  1715. *MaxAlpha = max(*MaxAlpha, DeviceBrush.ColorsPtr[i].GetAlpha());
  1716. *MinAlpha = min(*MinAlpha, DeviceBrush.ColorsPtr[i].GetAlpha());
  1717. }
  1718. }
  1719. }
  1720. return (*MaxAlpha - *MinAlpha < NEARCONSTANTALPHA);
  1721. }
  1722. virtual BOOL IsEqual(const GpBrush * brush) const;
  1723. virtual DpOutputSpan* CreateOutputSpan(
  1724. DpScanBuffer * scan,
  1725. DpContext *context,
  1726. const GpRect *drawBounds=NULL);
  1727. protected: // GDI+ Internal
  1728. GpPathGradient(const GpPathGradient* brush);
  1729. VOID
  1730. PrepareBrush();
  1731. VOID
  1732. InitializeBrush(
  1733. const GpPointF* points,
  1734. INT count,
  1735. GpWrapMode wrapMode = WrapModeClamp
  1736. )
  1737. {
  1738. DeviceBrush.Type = BrushTypePathGradient;
  1739. DeviceBrush.Wrap = wrapMode;
  1740. SetValid(FALSE);
  1741. DeviceBrush.OneSurroundColor = TRUE;
  1742. DeviceBrush.UsesPresetColors = FALSE;
  1743. MorphedBrush = NULL;
  1744. DeviceBrush.Path = NULL;
  1745. DeviceBrush.PointsPtr = NULL;
  1746. DeviceBrush.ColorsPtr = NULL;
  1747. // Set the blending and fall off factors.
  1748. DeviceBrush.Falloffs[0] = 1;
  1749. DeviceBrush.BlendCounts[0] = 1;
  1750. DeviceBrush.BlendFactors[0] = NULL;
  1751. DeviceBrush.BlendPositions[0] = NULL;
  1752. DeviceBrush.PresetColors = NULL;
  1753. if(!WrapModeIsValid(wrapMode) || count <= 0 || points == NULL)
  1754. {
  1755. DeviceBrush.Count = 0;
  1756. return;
  1757. }
  1758. DeviceBrush.Count = count;
  1759. // Get the boundary rectangle.
  1760. REAL xmin, xmax, ymin, ymax, x0, y0;
  1761. x0 = xmin = xmax = points[0].X;
  1762. y0 = ymin = ymax = points[0].Y;
  1763. for(INT i = 1; i < DeviceBrush.Count; i++)
  1764. {
  1765. x0 += points[i].X;
  1766. y0 += points[i].Y;
  1767. xmin = min(xmin, points[i].X);
  1768. xmax = max(xmax, points[i].X);
  1769. ymin = min(ymin, points[i].Y);
  1770. ymax = max(ymax, points[i].Y);
  1771. }
  1772. DeviceBrush.Rect.X = xmin;
  1773. DeviceBrush.Rect.Width = xmax - xmin;
  1774. DeviceBrush.Rect.Y = ymin;
  1775. DeviceBrush.Rect.Height = ymax - ymin;
  1776. if(DeviceBrush.Rect.Width <= 0 ||
  1777. DeviceBrush.Rect.Height <= 0)
  1778. return;
  1779. // The default center point is the center of gravity.
  1780. DeviceBrush.Points[0].X = x0 / DeviceBrush.Count;
  1781. DeviceBrush.Points[0].Y = y0 / DeviceBrush.Count;
  1782. DeviceBrush.PointsPtr =
  1783. (GpPointF*) GpMalloc(DeviceBrush.Count *
  1784. sizeof(GpPointF));
  1785. if(!DeviceBrush.PointsPtr)
  1786. {
  1787. DeviceBrush.Count = 0;
  1788. return;
  1789. }
  1790. DeviceBrush.ColorsPtr =
  1791. (GpColor*) GpMalloc(DeviceBrush.Count *
  1792. sizeof(GpColor));
  1793. if(!DeviceBrush.ColorsPtr)
  1794. {
  1795. GpFree(DeviceBrush.PointsPtr);
  1796. DeviceBrush.PointsPtr = NULL;
  1797. DeviceBrush.Count = 0;
  1798. return;
  1799. }
  1800. // If this comes so far, both Points and Colors are valid.
  1801. GpMemcpy(&DeviceBrush.PointsPtr[0],
  1802. points,
  1803. DeviceBrush.Count*sizeof(GpPointF));
  1804. GpMemset(&DeviceBrush.ColorsPtr[0],
  1805. 255,
  1806. DeviceBrush.Count*sizeof(GpColor));
  1807. DeviceBrush.FocusScaleX = 0;
  1808. DeviceBrush.FocusScaleY = 0;
  1809. InflationFactor = 0.0f;
  1810. SetValid(TRUE);
  1811. }
  1812. VOID DefaultBrush(VOID)
  1813. {
  1814. DeviceBrush.Type = BrushTypePathGradient;
  1815. SetValid(FALSE);
  1816. DeviceBrush.OneSurroundColor = TRUE;
  1817. DeviceBrush.Wrap = WrapModeClamp;
  1818. DeviceBrush.UsesPresetColors = FALSE;
  1819. DeviceBrush.Path = NULL;
  1820. DeviceBrush.PointsPtr = NULL;
  1821. DeviceBrush.ColorsPtr = 0;
  1822. DeviceBrush.Count = 0;
  1823. // The default center point is the center of gravity.
  1824. GpMemset(&DeviceBrush.Rect, 0, sizeof(GpRectF));
  1825. GpMemset(&DeviceBrush.Points, 0, sizeof(GpPointF));
  1826. GpMemset(&DeviceBrush.Colors, 255, sizeof(GpColor));
  1827. DeviceBrush.FocusScaleX = 0;
  1828. DeviceBrush.FocusScaleY = 0;
  1829. // Set the blending and fall off factors.
  1830. DeviceBrush.Falloffs[0] = 1;
  1831. DeviceBrush.BlendCounts[0] = 1;
  1832. DeviceBrush.BlendFactors[0] = NULL;
  1833. DeviceBrush.BlendPositions[0] = NULL;
  1834. DeviceBrush.PresetColors = NULL;
  1835. MorphedBrush = NULL;
  1836. InflationFactor = 0.0f;
  1837. }
  1838. // This does not update the Uid of the object because it's defined as const
  1839. // But the object doesn't really change anyway
  1840. GpStatus Flatten(GpMatrix* matrix) const;
  1841. virtual
  1842. const DpPath *
  1843. GetOutlinePath(
  1844. VOID
  1845. ) const
  1846. {
  1847. return DeviceBrush.Path;
  1848. }
  1849. protected:
  1850. GpBrush* MorphedBrush;
  1851. DynByteArray FlattenTypes;
  1852. DynPointFArray FlattenPoints;
  1853. REAL InflationFactor;
  1854. };
  1855. //--------------------------------------------------------------------------
  1856. // Represent hatch brush object
  1857. //--------------------------------------------------------------------------
  1858. class GpHatch : public GpBrush
  1859. {
  1860. friend class DpOutputHatchSpan;
  1861. public:
  1862. // Constructors
  1863. GpHatch(VOID)
  1864. {
  1865. DefaultBrush();
  1866. }
  1867. GpHatch(GpHatchStyle hatchStyle, const GpColor& foreColor)
  1868. {
  1869. InitializeBrush(hatchStyle, foreColor, 0);
  1870. }
  1871. GpHatch(
  1872. GpHatchStyle hatchStyle,
  1873. const GpColor& foreColor,
  1874. const GpColor& backColor)
  1875. {
  1876. InitializeBrush(hatchStyle, foreColor, backColor);
  1877. }
  1878. GpBrush* Clone() const
  1879. {
  1880. return new GpHatch(this);
  1881. }
  1882. ~GpHatch() {}
  1883. virtual UINT GetDataSize() const;
  1884. virtual GpStatus GetData(IStream * stream) const;
  1885. virtual GpStatus SetData(const BYTE * dataBuffer, UINT size);
  1886. virtual GpStatus ColorAdjust(
  1887. GpRecolor * recolor,
  1888. ColorAdjustType type
  1889. );
  1890. virtual BOOL IsOpaque(BOOL ColorsOnly = FALSE) const
  1891. {
  1892. // This brush is opaque only if
  1893. // all the colors are opaque.
  1894. return (DeviceBrush.Colors[0].IsOpaque() &&
  1895. DeviceBrush.Colors[1].IsOpaque());
  1896. }
  1897. virtual BOOL IsSolid() const
  1898. {
  1899. //This may have to change if we change the defination of IsSolid.
  1900. //See comment at GpBrush::IsSolid() for more info.
  1901. return FALSE;
  1902. }
  1903. virtual BOOL IsNearConstant(BYTE* MinAlpha, BYTE* MaxAlpha) const
  1904. {
  1905. *MinAlpha = min(DeviceBrush.Colors[0].GetAlpha(),
  1906. DeviceBrush.Colors[1].GetAlpha());
  1907. *MaxAlpha = max(DeviceBrush.Colors[0].GetAlpha(),
  1908. DeviceBrush.Colors[1].GetAlpha());
  1909. return (*MaxAlpha - *MinAlpha < NEARCONSTANTALPHA);
  1910. }
  1911. virtual BOOL IsEqual(const GpBrush * brush) const;
  1912. virtual DpOutputSpan* CreateOutputSpan(
  1913. DpScanBuffer * scan,
  1914. DpContext *context,
  1915. const GpRect *drawBounds=NULL);
  1916. virtual GpSpecialGradientType
  1917. GetSpecialGradientType(const GpMatrix* matrix) const
  1918. {
  1919. return GradientTypeNotSpecial;
  1920. }
  1921. GpHatchStyle GetHatchStyle()
  1922. {
  1923. return DeviceBrush.Style;
  1924. }
  1925. GpStatus GetForegroundColor(GpColor* color)
  1926. {
  1927. ASSERT(color != NULL);
  1928. *color = DeviceBrush.Colors[0];
  1929. return Ok;
  1930. }
  1931. GpStatus GetBackgroundColor(GpColor* color)
  1932. {
  1933. ASSERT(color != NULL);
  1934. *color = DeviceBrush.Colors[1];
  1935. return Ok;
  1936. }
  1937. VOID SetStretchFactor(INT stretch)
  1938. {
  1939. StretchFactor = stretch;
  1940. }
  1941. private:
  1942. GpHatch(const GpHatch* brush);
  1943. VOID
  1944. InitializeBrush(
  1945. GpHatchStyle hatchStyle,
  1946. const GpColor& foreColor,
  1947. const GpColor& backColor
  1948. )
  1949. {
  1950. DeviceBrush.Type = BrushTypeHatchFill;
  1951. DeviceBrush.Style = hatchStyle;
  1952. DeviceBrush.Colors[0] = foreColor;
  1953. DeviceBrush.Colors[1] = backColor;
  1954. StretchFactor = 1;
  1955. InitializeData();
  1956. SetValid(TRUE);
  1957. }
  1958. VOID DefaultBrush()
  1959. {
  1960. InitializeBrush(HatchStyle50Percent,
  1961. GpColor(Color::Black),
  1962. GpColor(Color::White));
  1963. }
  1964. VOID
  1965. InitializeData();
  1966. INT StretchFactor;
  1967. };
  1968. #endif _BRUSH_HPP