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.

420 lines
9.9 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1998 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * XBezier.hpp
  8. *
  9. * Abstract:
  10. *
  11. * Interface of GpXBezier and its DDA classes
  12. *
  13. * Revision History:
  14. *
  15. * 11/05/1999 ikkof
  16. * Created it.
  17. *
  18. \**************************************************************************/
  19. #ifndef _XBEZIER_HPP
  20. #define _XBEZIER_HPP
  21. #define FLATNESS_LIMIT 0.25
  22. #define DISTANCE_LIMIT 2.0
  23. #define BZ_BUFF_SIZE 32
  24. class GpXPoints
  25. {
  26. friend class GpXPath;
  27. friend class GpXBezier;
  28. public:
  29. INT Dimension;
  30. INT Count; // Number of Points
  31. REALD* Data;
  32. protected:
  33. BOOL IsDataAllocated;
  34. public:
  35. GpXPoints()
  36. {
  37. Initialize();
  38. }
  39. // When XPoints is created from a given data with copyData = FALSE,
  40. // the caller is responsible for deleting the data after XPoints is no longer
  41. // used.
  42. GpXPoints(REALD* data, INT dimension, INT count, BOOL copyData = TRUE)
  43. {
  44. Initialize();
  45. SetData(data, dimension, count, copyData);
  46. }
  47. GpXPoints(GpPointF* points, INT count)
  48. {
  49. Initialize();
  50. if(points && count > 0)
  51. {
  52. Data = (REALD*) GpMalloc(2*count*sizeof(REALD));
  53. if(Data)
  54. {
  55. INT i = 0, j = 0;
  56. while(j < count)
  57. {
  58. Data[i++] = points[j].X;
  59. Data[i++] = points[j].Y;
  60. j++;
  61. }
  62. Dimension = 2;
  63. Count = count;
  64. IsDataAllocated = TRUE;
  65. }
  66. }
  67. }
  68. GpXPoints(GpPointD* points, INT count)
  69. {
  70. Initialize();
  71. if(points && count > 0)
  72. {
  73. Data = (REALD*) GpMalloc(2*count*sizeof(REALD));
  74. if(Data)
  75. {
  76. INT i = 0, j = 0;
  77. while(j < count)
  78. {
  79. Data[i++] = points[j].X;
  80. Data[i++] = points[j].Y;
  81. j++;
  82. }
  83. Dimension = 2;
  84. Count = count;
  85. IsDataAllocated = TRUE;
  86. }
  87. }
  88. }
  89. REALD* GetData() {return Data;}
  90. // When XPoints is created from a given data with copyData = FALSE,
  91. // the caller is responsible for deleting the data after XPoints is no longer
  92. // used.
  93. GpStatus
  94. SetData(REALD* data, INT dimension, INT count, BOOL copyData = TRUE)
  95. {
  96. GpStatus status = Ok;
  97. if(data && dimension > 0 || count > 0)
  98. {
  99. REALD* newData = NULL;
  100. if(copyData)
  101. {
  102. INT totalSize = dimension*count*sizeof(REALD);
  103. if(IsDataAllocated)
  104. newData = (REALD*) GpRealloc(Data, totalSize);
  105. else
  106. newData = (REALD*) GpMalloc(totalSize);
  107. if(newData)
  108. {
  109. GpMemcpy(newData, data, totalSize);
  110. IsDataAllocated;
  111. }
  112. else
  113. status = OutOfMemory;
  114. }
  115. else
  116. {
  117. if(Data && IsDataAllocated)
  118. GpFree(Data);
  119. newData = data;
  120. IsDataAllocated = FALSE;
  121. }
  122. if(status == Ok)
  123. {
  124. Dimension = dimension;
  125. Count = count;
  126. Data = newData;
  127. }
  128. }
  129. else
  130. status = InvalidParameter;
  131. return status;
  132. }
  133. GpStatus Transform(const GpMatrix* matrix);
  134. BOOL AreEqualPoints(INT index1, INT index2)
  135. {
  136. if(index1 < 0 || index1 >= Count
  137. || index2 < 0 || index2 >= Count || Data == NULL)
  138. return FALSE; // either index is out of the range or no data.
  139. BOOL areEqual = TRUE;
  140. if(index1 != index2)
  141. {
  142. REALD* data1 = Data + index1*Dimension;
  143. REALD* data2 = Data + index2*Dimension;
  144. INT k = 0;
  145. while(k < Dimension && areEqual)
  146. {
  147. if(*data1++ != *data2++)
  148. areEqual = FALSE;
  149. k++;
  150. }
  151. }
  152. return areEqual;
  153. }
  154. static GpStatus
  155. GpXPoints::TransformPoints(
  156. const GpMatrix* matrix,
  157. REALD* data,
  158. INT dimension,
  159. INT count
  160. );
  161. ~GpXPoints()
  162. {
  163. if(Data && IsDataAllocated)
  164. GpFree(Data);
  165. }
  166. protected:
  167. VOID Initialize()
  168. {
  169. Dimension = 0;
  170. Count = 0;
  171. Data = NULL;
  172. IsDataAllocated = FALSE;
  173. }
  174. };
  175. //********************************************************
  176. // GpXBezierDDA class
  177. //********************************************************
  178. class GpXBezierConstants
  179. {
  180. friend class GpXBezierDDA;
  181. private:
  182. REALD H[7][7]; // Half step
  183. REALD D[7][7]; // Double step
  184. REALD S[7][7]; // One step
  185. REALD F[7][7]; // Polynomical transform.
  186. REALD H6[7][7]; // Poly to Bez transform in 6th order.
  187. REALD G6[7][7]; // Bez to Poly transform in 6th order.
  188. public:
  189. GpXBezierConstants();
  190. };
  191. class GpXBezierDDA
  192. {
  193. protected:
  194. GpXBezierConstants C;
  195. protected:
  196. REALD T;
  197. REALD Dt;
  198. REALD Q[16];
  199. REALD P[16];
  200. INT NthOrder;
  201. INT Dimension;
  202. INT NSteps;
  203. REAL FlatnessLimit;
  204. REAL DistanceLimit;
  205. public:
  206. public:
  207. GpXBezierDDA() { Initialize(); }
  208. GpXBezierDDA(
  209. const GpXPoints& xpoints,
  210. REAL flatnessLimit = FLATNESS_LIMIT,
  211. REAL distanceLimit = DISTANCE_LIMIT
  212. )
  213. {
  214. Initialize();
  215. SetBezier(xpoints, flatnessLimit, distanceLimit);
  216. }
  217. VOID
  218. SetBezier(
  219. const GpXPoints& xpoints,
  220. REAL flatnessLimit = FLATNESS_LIMIT,
  221. REAL distanceLimit = DISTANCE_LIMIT
  222. );
  223. INT GetSteps() { return NSteps; }
  224. VOID InitDDA(GpPointF* pt);
  225. VOID HalveStepSize();
  226. VOID DoubleStepSize();
  227. VOID FastShrinkStepSize(INT shift);
  228. VOID TakeStep();
  229. BOOL NeedsSubdivide(REAL itsFlatnessLimit);
  230. BOOL GetNextPoint(GpPointF* pt);
  231. VOID MoveForward();
  232. INT GetControlPoints(GpXPoints* xpoints);
  233. protected:
  234. VOID Initialize();
  235. VOID SetPolynomicalCoefficients();
  236. VOID TakeConvergentStep();
  237. BOOL Get2DDistanceVector(REALD* dx, REALD* dy, INT from, INT to);
  238. };
  239. //************************************
  240. // XBezier class
  241. //************************************
  242. #define NthOrderMax 6
  243. class GpXBezier
  244. {
  245. private:
  246. // We now use an ObjectTag to determine if the object is valid
  247. // instead of using a BOOL. This is much more robust and helps
  248. // with debugging. It also enables us to version our objects
  249. // more easily with a version number in the ObjectTag.
  250. ObjectTag Tag; // Keep this as the 1st value in the object!
  251. protected:
  252. VOID SetValid(BOOL valid)
  253. {
  254. Tag = valid ? ObjectTagGpBezier : ObjectTagInvalid;
  255. }
  256. public:
  257. BOOL IsValid() const
  258. {
  259. ASSERT((Tag == ObjectTagGpBezier) || (Tag == ObjectTagInvalid));
  260. #if DBG
  261. if (Tag == ObjectTagInvalid)
  262. {
  263. WARNING1("Invalid GpBezier");
  264. }
  265. #endif
  266. return (Tag == ObjectTagGpBezier);
  267. }
  268. GpXBezier()
  269. {
  270. Initialize();
  271. }
  272. GpXBezier(INT order, const GpPointF* points, INT count)
  273. {
  274. Initialize();
  275. SetValid(SetBeziers(order, points, count));
  276. }
  277. GpXBezier(INT order, const GpXPoints& xpoints)
  278. {
  279. Initialize();
  280. SetValid(SetBeziers(order, xpoints));
  281. }
  282. ~GpXBezier();
  283. GpStatus SetBeziers(INT order, const GpPointF* points, INT count);
  284. GpStatus SetBeziers(INT order, const GpXPoints& xpoints);
  285. virtual INT GetControlCount() {return Count;}
  286. virtual VOID GetBounds(GpMatrix* matrix, GpRect* bounds);
  287. virtual VOID Transform(GpMatrix* matrix);
  288. virtual GpStatus Flatten(
  289. DynPointFArray* flattenPts,
  290. const GpMatrix* matrix);
  291. protected:
  292. VOID Initialize()
  293. {
  294. NthOrder = 0;
  295. Dimension = 0;
  296. Count = 0;
  297. Data = NULL;
  298. FlatnessLimit = FLATNESS_LIMIT;
  299. DistanceLimit = DISTANCE_LIMIT;
  300. SetValid(TRUE);
  301. }
  302. GpStatus
  303. FlattenEachBezier(
  304. DynPointFArray* flattenPts,
  305. GpXBezierDDA& dda,
  306. BOOL isFirstBezier,
  307. const GpMatrix* matrix,
  308. const REALD* bezierData
  309. );
  310. GpStatus
  311. Get2DPoints(
  312. GpPointF* points,
  313. INT count,
  314. const REALD* dataPoints,
  315. const GpMatrix* matrix = NULL);
  316. GpStatus CheckInputData(const GpPointF* points, INT count)
  317. {
  318. GpStatus status = InvalidParameter;
  319. if(NthOrder > 0)
  320. {
  321. if(count > NthOrder)
  322. {
  323. INT reminder = count % NthOrder;
  324. if(reminder == 1 && points !=NULL)
  325. status = Ok;
  326. }
  327. }
  328. else // NthOrder <= 0
  329. {
  330. if(count > 1 && points != NULL)
  331. {
  332. if(count <= NthOrderMax + 1)
  333. {
  334. NthOrder = count - 1;
  335. status = Ok;
  336. }
  337. }
  338. }
  339. return status;
  340. }
  341. protected: // GDI+ INTERNAL
  342. // Following are the two values to determin the flatness.
  343. REAL FlatnessLimit; // The maximum flateness.
  344. REAL DistanceLimit; // The minimum distance.
  345. private: // GDI+ INTERNAL
  346. INT NthOrder;
  347. INT Dimension;
  348. INT Count;
  349. REALD* Data;
  350. };
  351. #endif