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.

787 lines
19 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1999 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * PathIterator.cpp
  8. *
  9. * Abstract:
  10. *
  11. * Implementation of the DpPathTypeIterator and DpPathIterator classes
  12. *
  13. * Revision History:
  14. *
  15. * 11/13/1999 ikkof
  16. * Created it.
  17. *
  18. \**************************************************************************/
  19. #include "precomp.hpp"
  20. VOID
  21. DpPathTypeIterator::SetTypes(const BYTE* types, INT count)
  22. {
  23. if(types && count > 0)
  24. {
  25. Types = types;
  26. Count = count;
  27. // Set Valid flag to TRUE so that CheckValid()
  28. // can call NextSubpath() and NextPathType().
  29. SetValid(TRUE);
  30. SetValid(CheckValid());
  31. }
  32. else
  33. Initialize();
  34. }
  35. // !!! bhouse CheckValid should not be required
  36. //
  37. // When we create an iterator, we should be able to provide
  38. // data that is consistent and that does not need to be
  39. // checked.
  40. // Also, CheckValid actually has side effects like determining
  41. // whether the path has beziers and calculating sub-path count.
  42. // These should be provided at iterator creation time or taken
  43. // out of the source path for which the iterator is created.
  44. // The reasoning is that this data should persist beyond the
  45. // lifespan of the iterator so that we do not have to keep
  46. // re-calculating information that can be calculated once and
  47. // stored with the path.
  48. BOOL
  49. DpPathTypeIterator::CheckValid()
  50. {
  51. if(Count < 0)
  52. return FALSE;
  53. else if(Count == 0) // Allow an empty path.
  54. return TRUE;
  55. else
  56. {
  57. // If Count > 0 and Types = NULL, the path is not valid.
  58. if(Types == NULL)
  59. return FALSE;
  60. }
  61. INT startIndex, endIndex;
  62. BOOL isClosed;
  63. BOOL isValid = TRUE;
  64. Rewind();
  65. INT subpathCount = 0;
  66. HasBezier = FALSE;
  67. ExtendedPath = FALSE;
  68. while(
  69. NextSubpath(&startIndex, &endIndex, &isClosed)
  70. && isValid
  71. )
  72. {
  73. INT typeStartIndex, typeEndIndex;
  74. BYTE pathType = PathPointTypeStart;
  75. if(endIndex == startIndex && Count > 1)
  76. {
  77. // This is a case when the next subpath has only one point.
  78. isValid = FALSE;
  79. }
  80. while(
  81. NextPathType(&pathType, &typeStartIndex, &typeEndIndex)
  82. && isValid
  83. )
  84. {
  85. INT count = typeEndIndex - typeStartIndex + 1;
  86. INT order = (INT) pathType;
  87. switch(pathType)
  88. {
  89. case PathPointTypeStart:
  90. // This happens when there is only one point
  91. // in a path.
  92. if(count == 1)
  93. isValid;
  94. else
  95. {
  96. ASSERT(("Invalid path type."));
  97. isValid = FALSE;
  98. }
  99. break;
  100. // The number of the Bezier points must be in the form of
  101. // n*order + 1.
  102. case PathPointTypeBezier3:
  103. if(count % order != 1)
  104. isValid = FALSE;
  105. if(!HasBezier)
  106. HasBezier = TRUE;
  107. if(order != 3 && !ExtendedPath)
  108. ExtendedPath = TRUE;
  109. break;
  110. case PathPointTypeLine:
  111. break;
  112. default:
  113. // Undefined path type.
  114. WARNING(("Undefined path type."));
  115. isValid = FALSE;
  116. break;
  117. }
  118. }
  119. subpathCount++;
  120. }
  121. Rewind();
  122. SubpathCount = subpathCount;
  123. return isValid;
  124. }
  125. /**************************************************************************\
  126. *
  127. * Function Description:
  128. *
  129. * Returns the index range of the next subpah.
  130. *
  131. * Arguments:
  132. *
  133. * [OUT] startIndex - the starting index of the next subpath.
  134. * [OUT] endIndex - the ending index of the next subpath.
  135. * [OUT] isClosed - TRUE is the next subpath is closed.
  136. *
  137. * Return Value:
  138. *
  139. * Retuns the sumber of points in the next subpath.
  140. * Returns 0 if there is no more subpath.
  141. *
  142. * History:
  143. *
  144. * 11/01/1999 ikkof
  145. * Created it.
  146. *
  147. \**************************************************************************/
  148. INT
  149. DpPathTypeIterator::NextSubpath(
  150. INT* startIndex,
  151. INT* endIndex,
  152. BOOL *isClosed
  153. )
  154. {
  155. if(!IsValid() || Count == 0)
  156. return 0;
  157. INT count = Count;
  158. if(SubpathEndIndex >= count - 1)
  159. return 0;
  160. INT i;
  161. // Set the starting index of the current subpath.
  162. if(SubpathEndIndex <= 0)
  163. {
  164. SubpathStartIndex = 0;
  165. i = 1;
  166. }
  167. else
  168. {
  169. SubpathStartIndex = SubpathEndIndex + 1;
  170. SubpathEndIndex = SubpathStartIndex;
  171. i = SubpathStartIndex + 1;
  172. }
  173. BOOL hasData = FALSE;
  174. INT segmentCount = 0;
  175. const BYTE* types = Types + i;
  176. while(i < count)
  177. {
  178. // Do the move segments.
  179. segmentCount = 0;
  180. while(i < count && (*types & PathPointTypePathTypeMask) == PathPointTypeStart)
  181. {
  182. segmentCount++;
  183. if(hasData)
  184. {
  185. break;
  186. }
  187. else
  188. {
  189. // Skip the consequtive move segments in the beginning of a subpath.
  190. SubpathStartIndex = i;
  191. SubpathEndIndex = SubpathStartIndex;
  192. i++;
  193. types++;
  194. }
  195. }
  196. if(segmentCount > 0 && hasData)
  197. {
  198. SubpathEndIndex = i - 1;
  199. break;
  200. }
  201. // Do the non-move segments.
  202. segmentCount = 0;
  203. while(i < count && (*types & PathPointTypePathTypeMask) != PathPointTypeStart)
  204. {
  205. i++;
  206. types++;
  207. segmentCount++;
  208. }
  209. if(segmentCount > 0)
  210. {
  211. hasData = TRUE;
  212. }
  213. }
  214. *startIndex = SubpathStartIndex;
  215. if(i >= count)
  216. SubpathEndIndex = count - 1; // The last subpath.
  217. *endIndex = SubpathEndIndex;
  218. segmentCount = SubpathEndIndex - SubpathStartIndex + 1;
  219. if(segmentCount > 1)
  220. {
  221. // If there is the close flag this subpath is closed.
  222. if((Types[SubpathEndIndex] & PathPointTypeCloseSubpath))
  223. {
  224. *isClosed = TRUE;
  225. }
  226. else
  227. *isClosed = FALSE;
  228. }
  229. else
  230. *isClosed = FALSE;
  231. // Set the start and end index of type to be the starting index of
  232. // the current subpath. NextPathType() will start from the
  233. // beginning of the current subpath.
  234. TypeStartIndex = SubpathStartIndex;
  235. TypeEndIndex = -1; // Indicate that this is the first type
  236. // in the current subpath.
  237. // Set the current index to the start index of the subpath.
  238. Index = SubpathStartIndex;
  239. return segmentCount;
  240. }
  241. /**************************************************************************\
  242. *
  243. * Function Description:
  244. *
  245. * Returns the path type, and the index range of the next segment.
  246. * This must be used after NextSubpath() is called. This returns only
  247. * the next segment within the current subpath.
  248. *
  249. * Arguments:
  250. *
  251. * [OUT] pathType - the type of the next segment ignoring the closed
  252. * and other flags.
  253. * [OUT] startIndex - the starting index of the next subpath.
  254. * [OUT] endIndex - the ending index of the next subpath.
  255. *
  256. * Return Value:
  257. *
  258. * Retuns the sumber of points in the next segment.
  259. * Returns 0 if there is no more segment in the current subpath.
  260. *
  261. * History:
  262. *
  263. * 11/01/1999 ikkof
  264. * Created it.
  265. *
  266. \**************************************************************************/
  267. INT
  268. DpPathTypeIterator::NextPathType(
  269. BYTE* pathType,
  270. INT* startIndex,
  271. INT* endIndex
  272. )
  273. {
  274. if(!IsValid() || Count == 0)
  275. return 0;
  276. if(TypeEndIndex >= SubpathEndIndex)
  277. return 0; // There is no more segment in the current subpath.
  278. INT count = SubpathEndIndex + 1; // Limit for the ending index.
  279. if(TypeEndIndex <= 0)
  280. TypeEndIndex = SubpathStartIndex; // This is the first type.
  281. TypeStartIndex = TypeEndIndex;
  282. INT i = TypeStartIndex;
  283. INT segmentCount = 0;
  284. i++; // Go to the next point.
  285. const BYTE* types = Types + i;
  286. while(i < count)
  287. {
  288. // Do the move segments.
  289. segmentCount = 0;
  290. while(i < count && (*types & PathPointTypePathTypeMask) == PathPointTypeStart)
  291. {
  292. // Move the start and end index.
  293. TypeStartIndex = i;
  294. TypeEndIndex = TypeStartIndex;
  295. i++;
  296. types++;
  297. segmentCount++;
  298. }
  299. // Do the non-move segments.
  300. segmentCount = 0;
  301. BYTE nextType = *types & PathPointTypePathTypeMask;
  302. while(i < count && (*types & PathPointTypePathTypeMask) == nextType)
  303. {
  304. i++;
  305. types++;
  306. segmentCount++;
  307. }
  308. if(segmentCount > 0)
  309. {
  310. TypeEndIndex = TypeStartIndex + segmentCount;
  311. *pathType = nextType;
  312. break;
  313. }
  314. }
  315. *startIndex = TypeStartIndex;
  316. *endIndex = TypeEndIndex;
  317. segmentCount = TypeEndIndex - TypeStartIndex + 1;
  318. return segmentCount;
  319. }
  320. /**************************************************************************\
  321. *
  322. * Function Description:
  323. *
  324. * Returns the index range of the next subpah.
  325. *
  326. * Arguments:
  327. *
  328. * [OUT] startIndex - the starting index of the next subpath.
  329. * [OUT] endIndex - the ending index of the next subpath.
  330. * [OUT] isClosed - TRUE is the next subpath is closed.
  331. *
  332. * Return Value:
  333. *
  334. * Retuns the sumber of points in the next subpath.
  335. * Returns 0 if there is no more subpath.
  336. *
  337. * History:
  338. *
  339. * 11/01/1999 ikkof
  340. * Created it.
  341. *
  342. \**************************************************************************/
  343. INT
  344. DpPathTypeIterator::NextMarker(
  345. INT* startIndex,
  346. INT* endIndex
  347. )
  348. {
  349. if(!IsValid() || Count == 0)
  350. return 0;
  351. INT count = Count;
  352. if(MarkerEndIndex >= count - 1)
  353. return 0;
  354. INT i;
  355. // Set the starting index of the current subpath.
  356. if(MarkerEndIndex <= 0)
  357. {
  358. MarkerStartIndex = 0;
  359. i = 1;
  360. }
  361. else
  362. {
  363. MarkerStartIndex = MarkerEndIndex + 1;
  364. MarkerEndIndex = MarkerStartIndex;
  365. i = MarkerStartIndex + 1;
  366. }
  367. const BYTE* types = Types + i;
  368. BOOL hasData = FALSE;
  369. while(i < count && (*types & PathPointTypePathMarker) == 0)
  370. {
  371. i++;
  372. types++;
  373. }
  374. if(i < count)
  375. MarkerEndIndex = i;
  376. else
  377. MarkerEndIndex = count - 1;
  378. *startIndex = MarkerStartIndex;
  379. *endIndex = MarkerEndIndex;
  380. INT segmentCount = MarkerEndIndex - MarkerStartIndex + 1;
  381. // Set the start and end index of type to be the starting index of
  382. // the current marker. NextSubpath() and NextPathType() will
  383. // start from the beginning of the current current marked path.
  384. SubpathStartIndex = SubpathEndIndex = MarkerStartIndex;
  385. TypeStartIndex = TypeEndIndex = MarkerStartIndex;
  386. // Set the current index to the start index of the subpath.
  387. Index = MarkerStartIndex;
  388. return segmentCount;
  389. }
  390. /**************************************************************************\
  391. *
  392. * Function Description:
  393. *
  394. * Returns TRUE if the control type in the given index is in dash mode.
  395. * Otherwise this returns FALSE. If the given index is outside of
  396. * the range this returns FALSE. A user must know the range of the
  397. * index beforehand to find the correct information.
  398. *
  399. \**************************************************************************/
  400. BOOL DpPathTypeIterator::IsDashMode(INT index)
  401. {
  402. if(!IsValid() || Count == 0 || index < 0 || index >= Count)
  403. return FALSE;
  404. return (Types[index] & PathPointTypeDashMode);
  405. }
  406. DpPathIterator::DpPathIterator(
  407. const DpPath* path
  408. )
  409. {
  410. Initialize();
  411. if(path)
  412. {
  413. const BYTE* types = path->GetPathTypes();
  414. const GpPointF* points = path->GetPathPoints();
  415. INT count = path->GetPointCount();
  416. SetData(points, types, count);
  417. }
  418. }
  419. VOID
  420. DpPathIterator::SetData(
  421. const GpPointF* points,
  422. const BYTE* types,
  423. INT count
  424. )
  425. {
  426. if(points && types && count > 0)
  427. {
  428. Points = points;
  429. Types = types;
  430. Count = count;
  431. // Set Valid flag to TRUE so that CheckValid()
  432. // can call NextSubpath() and NextPathType().
  433. SetValid(TRUE);
  434. SetValid(CheckValid());
  435. }
  436. else
  437. Initialize();
  438. }
  439. VOID
  440. DpPathIterator::SetData(
  441. const DpPath* path
  442. )
  443. {
  444. if(path)
  445. {
  446. const BYTE* types = path->GetPathTypes();
  447. const GpPointF* points = path->GetPathPoints();
  448. INT count = path->GetPointCount();
  449. SetData(points, types, count);
  450. }
  451. else
  452. Initialize();
  453. }
  454. INT
  455. DpPathIterator::NextSubpath(
  456. INT* startIndex,
  457. INT* endIndex,
  458. BOOL *isClosed
  459. )
  460. {
  461. if(!IsValid() || Count == 0)
  462. {
  463. return 0;
  464. }
  465. BOOL closed = TRUE;
  466. INT start = 0, end = 0;
  467. INT count = DpPathTypeIterator::NextSubpath(&start, &end, &closed);
  468. *startIndex = start;
  469. *endIndex = end;
  470. *isClosed = closed;
  471. return count;
  472. }
  473. INT
  474. DpPathIterator::NextSubpath(
  475. DpPath* path,
  476. BOOL *isClosed
  477. )
  478. {
  479. if(!IsValid() || Count == 0 || !path)
  480. {
  481. return 0;
  482. }
  483. BOOL closed = TRUE;
  484. INT start = 0, end = 0;
  485. INT count = DpPathTypeIterator::NextSubpath(&start, &end, &closed);
  486. GpPathData pathData;
  487. pathData.Count = count;
  488. pathData.Points = (GpPointF*) &Points[start];
  489. pathData.Types = (BYTE*) &Types[start];
  490. path->SetPathData(&pathData);
  491. *isClosed = closed;
  492. return count;
  493. }
  494. INT
  495. DpPathIterator::NextMarker(
  496. INT* startIndex,
  497. INT* endIndex
  498. )
  499. {
  500. if(!IsValid() || Count == 0)
  501. return 0;
  502. INT count = DpPathTypeIterator::NextMarker(startIndex, endIndex);
  503. return count;
  504. }
  505. INT
  506. DpPathIterator::NextMarker(
  507. DpPath* path
  508. )
  509. {
  510. if(!IsValid() || Count == 0 || !path)
  511. return 0;
  512. BOOL closed;
  513. INT start = 0, end = 0;
  514. INT count = DpPathTypeIterator::NextMarker(&start, &end);
  515. GpPathData pathData;
  516. pathData.Count = count;
  517. pathData.Points = (GpPointF*) &Points[start];
  518. pathData.Types = (BYTE*) &Types[start];
  519. path->SetPathData(&pathData);
  520. return count;
  521. }
  522. /**************************************************************************\
  523. *
  524. * Function Description:
  525. *
  526. * This retrieves the next points and types up to the number count.
  527. * This does not copy the unnecessary (consequetive) move points.
  528. * This fills up the data until the count number is reached. This fills
  529. * data beyond the current subpath.
  530. *
  531. * Arguments:
  532. *
  533. * [OUT] points - point array to copy the retrieved point data.
  534. * [OUT] types - type array to copy the retrieved type data.
  535. * [IN] count - the number of points to be copied (request).
  536. *
  537. * Retrun Value:
  538. * Returns the total number of the retrieved points.
  539. *
  540. \**************************************************************************/
  541. INT
  542. DpPathIterator::Enumerate(
  543. GpPointF* points,
  544. BYTE* types,
  545. INT count
  546. )
  547. {
  548. if(!IsValid() || Count == 0)
  549. return 0;
  550. INT totalNumber = 0;
  551. INT number = EnumerateWithinSubpath(points, types, count);
  552. while(number > 0)
  553. {
  554. totalNumber += number;
  555. count -= number;
  556. if(count > 0)
  557. {
  558. points += number;
  559. types += number;
  560. number = EnumerateWithinSubpath(points, types, count);
  561. }
  562. else
  563. number = 0;
  564. }
  565. return totalNumber;
  566. }
  567. /**************************************************************************\
  568. *
  569. * Function Description:
  570. *
  571. * This retrieves the next points and types up to the number count.
  572. * This does not copy the unnecessary (consequetive) move points.
  573. * This fills up the data until the count number is reached or the
  574. * end of the current subopath is reached.
  575. *
  576. * Arguments:
  577. *
  578. * [OUT] points - point array to copy the retrieved point data.
  579. * [OUT] types - type array to copy the retrieved type data.
  580. * [IN] count - the number of points to be copied (request).
  581. *
  582. * Retrun Value:
  583. * Returns the total number of the retrieved points.
  584. *
  585. \**************************************************************************/
  586. INT
  587. DpPathIterator::EnumerateWithinSubpath(
  588. GpPointF* points,
  589. BYTE* types,
  590. INT count
  591. )
  592. {
  593. if(!IsValid() || Count == 0 || count <= 0 || !points || !types)
  594. return 0;
  595. INT startIndex, endIndex;
  596. BOOL isClosed;
  597. INT segmentCount;
  598. if(Index == 0)
  599. segmentCount = NextSubpath(&startIndex, &endIndex, &isClosed);
  600. if(Index > SubpathEndIndex)
  601. segmentCount = NextSubpath(&startIndex, &endIndex, &isClosed);
  602. else
  603. segmentCount = SubpathEndIndex - SubpathStartIndex + 1;
  604. if(segmentCount == 0)
  605. return 0; // No more segment.
  606. count = min(count, SubpathEndIndex - Index + 1);
  607. if(count > 0)
  608. {
  609. GpMemcpy(points, Points + Index, count*sizeof(GpPointF));
  610. GpMemcpy(types, Types + Index, count);
  611. Index += count;
  612. }
  613. return count;
  614. }
  615. /**************************************************************************\
  616. *
  617. * Function Description:
  618. *
  619. * This copies the data stored in Points and Types arrays
  620. * in the index range between startIndex and endIndex.
  621. * This may copy unnecessary (consequetive) move points.
  622. * startIndex and endIndex must be within the index range of
  623. * the original data. Otherwise, this does not copy the data
  624. * and returns 0.
  625. *
  626. * Arguments:
  627. *
  628. * [OUT] points - point array to copy the retrieved point data.
  629. * [OUT] types - type array to copy the retrieved type data.
  630. * [IN] startIndex - start index of the origianl data
  631. * [IN] endIndex - end index of the origianl data.
  632. *
  633. * Retrun Value:
  634. * Returns the total number of the copied points.
  635. *
  636. \**************************************************************************/
  637. INT
  638. DpPathIterator::CopyData(
  639. GpPointF* points,
  640. BYTE* types,
  641. INT startIndex,
  642. INT endIndex
  643. )
  644. {
  645. if(!IsValid() || Count == 0 || startIndex < 0 || endIndex >= Count
  646. || startIndex > endIndex || !points || !types)
  647. return 0;
  648. INT count = endIndex - startIndex + 1;
  649. ASSERT(count > 0);
  650. GpMemcpy(points, Points + startIndex, count*sizeof(GpPointF));
  651. GpMemcpy(types, Types + startIndex, count);
  652. Index += count;
  653. return count;
  654. }