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.

580 lines
14 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1998-1999 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * path.hpp
  8. *
  9. * Abstract:
  10. *
  11. * Path related declarations
  12. *
  13. * Revision History:
  14. *
  15. * 12/06/1998 davidx
  16. * Created it.
  17. *
  18. * 06/16/1999 t-wehunt
  19. * Added RemoveSelfIntersections().
  20. *
  21. \**************************************************************************/
  22. #ifndef _PATH_HPP
  23. #define _PATH_HPP
  24. // This is used by the widener as an internal flag and as a deletion mask for
  25. // the endcap placement code. These two usages do not overlap.
  26. const INT PathPointTypeInternalUse = 0x40;
  27. /*
  28. // PathPointType is defined in GdiplusEnums.h.
  29. // Internally, we can use 0x40 for the internal use.
  30. //--------------------------------------------------------------------------
  31. // Path point types (only the lowest 8 bits are used.)
  32. // The lowest 3 bits are interpreted as point type
  33. // The higher 5 bits are reserved for flags.
  34. //--------------------------------------------------------------------------
  35. enum PathPointType
  36. {
  37. PathPointTypeStart = 0, // move
  38. PathPointTypeLine = 1, // line
  39. PathPointTypeBezier = 3, // default Beizer (= cubic Bezier)
  40. PathPointTypePathTypeMask = 0x07, // type mask (lowest 3 bits).
  41. PathPointTypeDashMode = 0x10, // currently in dash mode.
  42. PathPointTypePathMarker = 0x20, // a marker for the path.
  43. PathPointTypeCloseSubpath = 0x80, // closed flag
  44. // Path types used for advanced path.
  45. PathPointTypeBezier2 = 2, // quadratic Beizer
  46. PathPointTypeBezier3 = 3, // cubic Bezier
  47. PathPointTypeBezier4 = 4, // quartic (4th order) Beizer
  48. PathPointTypeBezier5 = 5, // quintic (5th order) Bezier
  49. PathPointTypeBezier6 = 6 // hexaic (6th order) Bezier
  50. };
  51. */
  52. class GpGlyphPath;
  53. inline BOOL IsStartType(BYTE type)
  54. {
  55. return ((type & PathPointTypePathTypeMask) ==
  56. PathPointTypeStart);
  57. }
  58. inline BOOL IsClosedType(BYTE type)
  59. {
  60. return ((type & PathPointTypeCloseSubpath) ==
  61. PathPointTypeCloseSubpath);
  62. }
  63. inline BOOL IsDashType(BYTE type)
  64. {
  65. return ((type & PathPointTypeDashMode) ==
  66. PathPointTypeDashMode);
  67. }
  68. class GpPath : public DpPath
  69. {
  70. friend class GpGraphics;
  71. friend class GpPathGradient;
  72. public:
  73. // Path constructors
  74. GpPath(GpFillMode fillMode = FillModeAlternate)
  75. {
  76. InitDefaultState(fillMode);
  77. SetValid(TRUE);
  78. }
  79. GpPath(const GpPointF* points,
  80. const BYTE* types,
  81. INT count,
  82. GpFillMode fillMode = FillModeAlternate);
  83. GpPath(
  84. const GpPointF *points,
  85. INT count,
  86. GpPointF *stackPoints,
  87. BYTE *stackTypes,
  88. INT stackCount,
  89. GpFillMode fillMode = FillModeAlternate,
  90. DpPathFlags flags = PossiblyNonConvex
  91. );
  92. GpPath(HRGN hRgn); // create a path from a GDI region handle
  93. GpPath(const DpRegion* region); // create a path from a GDI+ region
  94. // Get the lock object
  95. GpLockable *GetObjectLock()
  96. {
  97. return &Lockable;
  98. }
  99. GpPath* Clone() const
  100. {
  101. ASSERT(IsValid())
  102. GpPath* path = new GpPath(this);
  103. CheckValid(path);
  104. return path;
  105. }
  106. GpStatus Reset(GpFillMode fillMode = FillModeAlternate)
  107. {
  108. // !!! bhouse We should allow reseting invalid paths
  109. ASSERT(IsValid());
  110. InitDefaultState(fillMode);
  111. return Ok;
  112. }
  113. virtual GpStatus
  114. GetBounds(
  115. GpRect *bounds,
  116. const GpMatrix *matrix = NULL,
  117. const DpPen* pen = NULL,
  118. REAL dpiX = 0,
  119. REAL dpiY = 0
  120. ) const;
  121. virtual GpStatus
  122. GetBounds(
  123. GpRectF *bounds,
  124. const GpMatrix *matrix = NULL,
  125. const DpPen* pen = NULL,
  126. REAL dpiX = 0,
  127. REAL dpiY = 0
  128. ) const;
  129. REAL GetSharpestAngle() const
  130. {
  131. if(!(CacheFlags & kSharpestAngleValid))
  132. CalcSharpestAngle();
  133. return SharpestAngle;
  134. }
  135. // Set a marker at the current location.
  136. GpStatus SetMarker();
  137. // Clear all markers.
  138. GpStatus ClearMarkers();
  139. // Add lines to the path object
  140. GpStatus AddLine(const GpPointF& pt1, const GpPointF& pt2)
  141. {
  142. GpPointF points[2];
  143. points[0] = pt1;
  144. points[1] = pt2;
  145. return AddLines(points, 2);
  146. }
  147. GpStatus AddLine(REAL x1, REAL y1, REAL x2, REAL y2)
  148. {
  149. GpPointF points[2];
  150. points[0].X = x1;
  151. points[0].Y = y1;
  152. points[1].X = x2;
  153. points[1].Y = y2;
  154. return AddLines(points, 2);
  155. }
  156. GpStatus AddLines(const GpPointF* points, INT count);
  157. // Add an arc to the path object
  158. GpStatus AddArc(const GpRectF& rect, REAL startAngle, REAL sweepAngle);
  159. GpStatus AddArc(REAL x, REAL y, REAL width, REAL height,
  160. REAL startAngle, REAL sweepAngle)
  161. {
  162. GpRectF rect(x, y, width, height);
  163. return AddArc(rect, startAngle, sweepAngle);
  164. }
  165. // Add Bezier curves to the path object
  166. GpStatus AddBezier(const GpPointF& pt1, const GpPointF& pt2,
  167. const GpPointF& pt3, const GpPointF& pt4);
  168. GpStatus AddBezier(REAL x1, REAL y1, REAL x2, REAL y2,
  169. REAL x3, REAL y3, REAL x4, REAL y4);
  170. GpStatus AddBeziers(const GpPointF* points, INT count);
  171. // Add cardinal splines to the path object
  172. GpStatus AddCurve(const GpPointF* points, INT count);
  173. GpStatus AddCurve(const GpPointF* points, INT count, REAL tension,
  174. INT offset, INT numberOfSegments);
  175. GpStatus AddClosedCurve(const GpPointF* points, INT count);
  176. GpStatus AddClosedCurve(const GpPointF* points, INT count, REAL tension);
  177. // Add closed shapes to the path object
  178. GpStatus AddRects(const GpRectF* rects, INT count);
  179. GpStatus AddRects(const RECT* rects, INT count);
  180. GpStatus AddPolygon(const GpPointF* points, INT count);
  181. GpStatus AddEllipse(const GpRectF& rect);
  182. GpStatus AddPie(const GpRectF& rect, REAL startAngle, REAL sweepAngle);
  183. GpStatus AddRect(const GpRectF& rect)
  184. {
  185. return AddRects(&rect, 1);
  186. }
  187. GpStatus AddEllipse(REAL x, REAL y, REAL width, REAL height)
  188. {
  189. GpRectF rect(x, y, width, height);
  190. return AddEllipse(rect);
  191. }
  192. GpStatus AddPie(REAL x, REAL y, REAL width, REAL height,
  193. REAL startAngle, REAL sweepAngle)
  194. {
  195. GpRectF rect(x, y, width, height);
  196. return AddPie(rect, startAngle, sweepAngle);
  197. }
  198. // Add a path to the path object
  199. GpStatus AddPath(const GpPointF* points, const BYTE* types, INT count,
  200. BOOL connect);
  201. GpStatus AddPath(const GpPath* path, BOOL connect);
  202. // Reverse the direction of a path.
  203. GpStatus Reverse();
  204. GpStatus GetLastPoint(GpPointF* point);
  205. // used by font
  206. GpStatus MoveTo(const GpPointF point);
  207. GpStatus AddPoints(const GpPointF* points, ULONG count, PathPointType type);
  208. GpStatus AddGlyphPath(GpGlyphPath *glyphPath, REAL x, REAL y, const GpMatrix * matrix = 0);
  209. GpStatus AddString(
  210. const WCHAR *string,
  211. INT length,
  212. const GpFontFamily *family,
  213. INT style,
  214. REAL emSize,
  215. const RectF *layoutRect,
  216. const GpStringFormat *format
  217. );
  218. // Get the flatten data.
  219. virtual GpStatus Flatten(
  220. DynByteArray *flattenTypes,
  221. DynPointFArray *flattenPoints,
  222. const GpMatrix *matrix = NULL,
  223. const REAL flatness = FlatnessDefault
  224. ) const;
  225. // Flatten this path.
  226. GpStatus Flatten(
  227. const GpMatrix *matrix = NULL,
  228. const REAL flatness = FlatnessDefault
  229. );
  230. // Get the morph and flatten data.
  231. GpStatus WarpAndFlatten(
  232. DynByteArray* flattenTypes,
  233. DynPointFArray* flattenPoints,
  234. const GpMatrix* matrix,
  235. const GpPointF* destPoint,
  236. INT count,
  237. const GpRectF& srcRect,
  238. WarpMode warpMode = WarpModePerspective
  239. );
  240. // Morph and flatten itself.
  241. GpStatus WarpAndFlattenSelf(
  242. GpMatrix* matrix,
  243. const GpPointF* destPoint,
  244. INT count,
  245. const GpRectF& srcRect,
  246. WarpMode warpMode = WarpModePerspective
  247. ); // Morph to the flatten points.
  248. // Widen the path object
  249. GpPath*
  250. GetWidenedPath(
  251. const GpPen* pen,
  252. const GpMatrix* matrix = NULL,
  253. REAL flatness = FlatnessDefault
  254. ) const;
  255. GpStatus
  256. Widen(
  257. GpPen* pen,
  258. GpMatrix* matrix = NULL,
  259. REAL flatness = FlatnessDefault
  260. );
  261. // Get the flattened path.
  262. virtual const DpPath *
  263. GetFlattenedPath(
  264. const GpMatrix* matrix,
  265. DpEnumerationType type,
  266. const DpPen* pen = NULL
  267. ) const;
  268. // Dreate a dashed path. (override)
  269. GpPath*
  270. CreateDashedPath(
  271. const GpPen* pen,
  272. const GpMatrix* matrix,
  273. REAL dpiX,
  274. REAL dpiY,
  275. REAL dashScale = 1.0f,
  276. BOOL needDashCaps = TRUE
  277. ) const;
  278. GpPath*
  279. CreateDashedPath(
  280. const DpPen* pen,
  281. const GpMatrix* matrix,
  282. REAL dpiX,
  283. REAL dpiY,
  284. REAL dashScale = 1.0f,
  285. BOOL needDashCaps = TRUE
  286. ) const;
  287. // Get the open and closed portion of the current path.
  288. GpPath* GetOpenPath();
  289. GpPath* GetClosedPath();
  290. // Determine if the path is empty, i.e. with no points
  291. BOOL IsEmpty() const
  292. {
  293. return GetPointCount() == 0;
  294. }
  295. BOOL IsRectangle(
  296. const GpMatrix * matrix,
  297. GpRectF * transformedBounds = NULL
  298. ) const;
  299. // Determine if path consists of a single polygon/polyline.
  300. BOOL IsPolygon() const
  301. {
  302. return (SubpathCount == 1) && !HasBezier;
  303. }
  304. // Return true if the two objects represent identical paths
  305. BOOL IsEqual(const GpPath* path) const;
  306. // Transform the path by the specified matrix
  307. VOID Transform(const GpMatrix * matrix);
  308. VOID SetHasBezier(BOOL _hasBezier) { HasBezier = _hasBezier; }
  309. // Hit testing
  310. GpStatus IsVisible(
  311. GpPointF* point,
  312. BOOL* isVisible,
  313. GpMatrix* matrix = NULL);
  314. GpStatus IsOutlineVisible(GpPointF* point, BOOL* isVisible, GpPen* pen,
  315. GpMatrix* matrix = NULL, REAL dpiX = 0, REAL dpiY = 0);
  316. // DDI entry point handlers for DpPath
  317. static GpPath* GetPath(const DpPath* path)
  318. {
  319. return (GpPath*)(path);
  320. }
  321. static DpPath* DriverCreateWidenedPath(
  322. const DpPath* path,
  323. const DpPen* pen,
  324. DpContext* context,
  325. BOOL outline
  326. );
  327. static VOID DriverDeletePath(DpPath* path);
  328. static DpPath* DriverClonePath(DpPath* path);
  329. static VOID DriverTransformPath(DpPath* path, GpMatrix* matrix);
  330. // Compute the winding mode outline.
  331. GpStatus ComputeWindingModeOutline(
  332. const GpMatrix *matrix,
  333. REAL flatness,
  334. BOOL *wereIntersectsRemoved = NULL
  335. );
  336. // Used for a mark-sweep point deletion algorithm in the path.
  337. VOID EraseMarkedSegments();
  338. virtual DynArray<SubpathInfo> *GetSubpathInformation() const;
  339. protected:
  340. VOID ComputeSubpathInformationCache() const;
  341. GpPath(const GpPath* path);
  342. GpPath *GetWidenedPathInternal(
  343. const DpPen *pen,
  344. const GpMatrix *matrix,
  345. REAL flatness = FlatnessDefault,
  346. BOOL insetPen = FALSE
  347. ) const;
  348. protected:
  349. BYTE*
  350. AddPointHelper(
  351. const GpPointF* points,
  352. INT count,
  353. BOOL addClosedFigure
  354. );
  355. GpPath*
  356. GetOpenOrClosedPath(BOOL openPath);
  357. static GpPointF*
  358. ConvertSplineToBezierPoints(
  359. const GpPointF* points,
  360. INT count,
  361. INT offset,
  362. INT numberOfSegments,
  363. REAL tension,
  364. INT* bezierCount
  365. );
  366. static INT
  367. GetArcPoints(
  368. GpPointF* points,
  369. const GpRectF& rect,
  370. REAL startAngle,
  371. REAL sweepAngle
  372. );
  373. VOID InitDefaultState(GpFillMode fillMode);
  374. VOID ResetCacheBounds() const
  375. {
  376. CacheFlags = (kCacheBoundsValid | kSharpestAngleValid);
  377. SharpestAngle = 2;
  378. CacheBounds.X = 0;
  379. CacheBounds.Y = 0;
  380. CacheBounds.Width = 0;
  381. CacheBounds.Height = 0;
  382. }
  383. VOID InvalidateCache() const
  384. {
  385. CacheFlags = 0;
  386. }
  387. VOID UpdateCacheBounds() const
  388. {
  389. if(!(CacheFlags & kCacheBoundsValid))
  390. CalcCacheBounds();
  391. }
  392. VOID CalcCacheBounds() const;
  393. VOID CalcSharpestAngle() const;
  394. // Data Members:
  395. protected:
  396. GpLockable Lockable; // object lock
  397. enum {
  398. kCacheBoundsValid = 1,
  399. kSharpestAngleValid = 2,
  400. kSubpathInfoValid = 4
  401. };
  402. mutable ULONG CacheFlags;
  403. mutable GpRectF CacheBounds;
  404. mutable REAL SharpestAngle;
  405. // Some small number of subpaths for our initial allocation should suffice
  406. // for most usage scenarios.
  407. mutable DynArrayIA<SubpathInfo, 3> SubpathInfoCache;
  408. };
  409. class GpPathIterator : public DpPathIterator
  410. {
  411. public:
  412. GpPathIterator(GpPath* path) : DpPathIterator(path)
  413. {
  414. }
  415. virtual INT GetCount()
  416. {
  417. if(IsValid())
  418. return Count;
  419. else
  420. return 0;
  421. }
  422. virtual INT GetSubpathCount()
  423. {
  424. if(IsValid())
  425. return SubpathCount;
  426. else
  427. return 0;
  428. }
  429. // This iterator is not used for the extended path.
  430. virtual BOOL IsValid() {return (DpPathIterator::IsValid() && !ExtendedPath);}
  431. // Get the lock object
  432. GpLockable *GetObjectLock()
  433. {
  434. return &Lockable;
  435. }
  436. protected:
  437. GpLockable Lockable;
  438. };
  439. #endif // !_PATH_HPP