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.

413 lines
11 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: pathclip.cxx
  3. *
  4. * This module handles the reading of the path for the line-clipping
  5. * component (which resides mostly in clipline.cxx).
  6. *
  7. * Created: 02-Apr-1991 08:45:30
  8. * Author: Eric Kutter [erick]
  9. *
  10. * Copyright (c) 1991-1999 Microsoft Corporation
  11. \**************************************************************************/
  12. #include "precomp.hxx"
  13. /******************************Public*Routine******************************\
  14. * PATHOBJ_vEnumStartClipLines
  15. *
  16. * Engine helper function.
  17. *
  18. * History:
  19. * 04-Apr-1991 -by- Eric Kutter [erick]
  20. * Wrote it.
  21. \**************************************************************************/
  22. VOID PATHOBJ_vEnumStartClipLines(
  23. PATHOBJ *ppo,
  24. CLIPOBJ *pco,
  25. SURFOBJ *pso,
  26. PLINEATTRS pla)
  27. {
  28. PSURFACE pSurf = SURFOBJ_TO_SURFACE(pso);
  29. ((ECLIPOBJ *)pco)->vEnumPathStart(ppo, pSurf, pla);
  30. }
  31. /******************************Public*Routine******************************\
  32. * PATHOBJ_bEnumClipLines
  33. *
  34. * Engine helper function.
  35. *
  36. * History:
  37. * 04-Apr-1991 -by- Eric Kutter [erick]
  38. * Wrote it.
  39. \**************************************************************************/
  40. BOOL PATHOBJ_bEnumClipLines(
  41. PATHOBJ *ppo,
  42. ULONG cj,
  43. PCLIPLINE pcl)
  44. {
  45. ECLIPOBJ *pco = (ECLIPOBJ *)((EPATHOBJ *)ppo)->pco;
  46. return(pco->bEnumPath(ppo,cj,pcl));
  47. }
  48. /******************************Member*Function*****************************\
  49. * XCLIPOBJ::vEnumPathStart
  50. *
  51. * History:
  52. * 24-Feb-1992 -by- J. Andrew Goossen [andrewgo]
  53. * Added styling support.
  54. *
  55. * 04-Apr-1991 -by- Eric Kutter [erick]
  56. * Wrote it.
  57. \**************************************************************************/
  58. VOID XCLIPOBJ::vEnumPathStart(PATHOBJ *ppo_, SURFACE *pSurf, PLINEATTRS pla)
  59. {
  60. EPATHOBJ *ppo = (EPATHOBJ *)ppo_;
  61. pcle = ppo->pcleGet();
  62. ppo->vEnumStart();
  63. ppo->pco = (CLIPOBJ *)this;
  64. pcle->fl = CLO_LINEDONE; // need a new line segment
  65. pcle->cPoints = 0;
  66. // spTotal2 will be non-zero when we're doing styling:
  67. pcle->spTotal2 = 0;
  68. pcle->plStyleState = &pla->elStyleState.l;
  69. pcle->xStep = 1;
  70. pcle->yStep = 1;
  71. pcle->xyDensity = 1;
  72. if (pla->fl & LA_ALTERNATE)
  73. {
  74. // Alternate style is special and has every second pixel off, so
  75. // we pretend a style unit is a single pixel long, and that we
  76. // have the style array {1}:
  77. pcle->spTotal2 = 2;
  78. pcle->spStyleEnd = HIWORD(pla->elStyleState.l) & 1;
  79. }
  80. else if (pla->pstyle != (PFLOAT_LONG) NULL)
  81. {
  82. if (pSurf->hdev() == 0)
  83. {
  84. WARNING("Driver didn't call EngAssociateSurface before calling\n");
  85. WARNING("EngStrokePath or vEnumPathStart, so styles may be wrong\n");
  86. pcle->xyDensity = 3; // Supply a default
  87. }
  88. else
  89. {
  90. PDEVOBJ po(pSurf->hdev());
  91. pcle->xStep = po.xStyleStep();
  92. pcle->yStep = po.yStyleStep();
  93. pcle->xyDensity = po.denStyleStep();
  94. }
  95. // Get ready for styling:
  96. PFLOAT_LONG pstyle = pla->pstyle + pla->cstyle;
  97. while (pstyle > pla->pstyle)
  98. {
  99. pstyle--;
  100. pcle->spTotal2 += pstyle->l;
  101. }
  102. ASSERTGDI((pcle->spTotal2 & ~0x7fffL) == 0, "Style array too long");
  103. pcle->spTotal2 <<= 1;
  104. pcle->spTotal2 *= pcle->xyDensity;
  105. // Construct our scaled style state, remembering that a driver could
  106. // have left the style state in a funky way:
  107. pcle->spStyleEnd = HIWORD(pla->elStyleState.l) * pcle->xyDensity +
  108. LOWORD(pla->elStyleState.l);
  109. pcle->spStyleEnd %= (ULONG) pcle->spTotal2;
  110. if (pcle->spStyleEnd < 0)
  111. {
  112. WARNING("GDISRV vEnumPathStart: style state < 0\n");
  113. pcle->spStyleEnd = 0;
  114. }
  115. }
  116. // get the first line. We don't care about flOld because we
  117. // don't care about last pel exclusion here.
  118. FLONG flOld;
  119. bGetLine(ppo,&flOld);
  120. }
  121. /******************************Member*Function*****************************\
  122. * BOOL XCLIPOBJ::bEnumPath
  123. *
  124. * bEnumPath fills the pcl data structure with a line and runs that
  125. * specify uncliped parts of the line. If there are too many runs to
  126. * fit in the supplied structure, the next call to this function will
  127. * return the next set of runs.
  128. *
  129. * This routine assumes that the line to be clipped is already set in
  130. * the XCLIPOBJ which initialy is done through vEnumStartPath. After
  131. * that, this routine will always complete with the next line setup.
  132. *
  133. * returns
  134. * TRUE - there are more runs to enumerate
  135. * FALSE - this is the last set of runs in the path
  136. *
  137. * History:
  138. *
  139. * 21-Feb-1992 -by- J. Andrew Goossen [andrewgo]
  140. * Made lines exclusive of ends.
  141. *
  142. * 04-Apr-1991 -by- Eric Kutter [erick]
  143. * Wrote it.
  144. \**************************************************************************/
  145. BOOL XCLIPOBJ::bEnumPath(
  146. PATHOBJ *ppo_,
  147. ULONG cj,
  148. PCLIPLINE pcl)
  149. {
  150. pcl->c = 0;
  151. // See if we're simply done the path:
  152. if (bEnumDone())
  153. return(FALSE);
  154. EPATHOBJ *ppo = (EPATHOBJ *) ppo_;
  155. BOOL bMore;
  156. do
  157. {
  158. // assume next line already setup.
  159. // get the run's for the current line. If we have all the runs, do
  160. // last pel exclusion. If we don't have all of the runs, we know
  161. // there is at least one unclipped pel after the current set of runs.
  162. bMore = bEnumLine(cj,pcl);
  163. if (!bMore)
  164. {
  165. // save information about current line
  166. FLONG flOld = pcle->fl;
  167. ASSERTGDI(pcle->dda.lX1 >= pcle->dda.lX0, "irunOld < 0");
  168. // get the next non-zero length line (bGetLine is FALSE if there aren't
  169. // any more lines in the path):
  170. bGetLine(ppo,&flOld);
  171. }
  172. } while ((pcl->c == 0) && !bEnumDone());
  173. // if we made it to here with no runs, we must be done.
  174. if (bEnumDone() && bStyling())
  175. {
  176. // We're all done, so update style state in LINEATTRS:
  177. *pcle->plStyleState = lGetStyleState(pcle->spStyleEnd);
  178. }
  179. return(!bEnumDone());
  180. }
  181. /******************************Public*Routine******************************\
  182. * XCLIPOBJ::bGetLine
  183. *
  184. * Fill ppo with the next line segment in the path. This may be a closing
  185. * segment of the current sub-path.
  186. *
  187. * It may be necessary to ask the path for more points.
  188. *
  189. * returns
  190. * TRUE - if there were more line segments
  191. * FALSE - if no more line segments.
  192. *
  193. * History:
  194. * 16-Oct-1991 -by- Eric Kutter [erick]
  195. * Wrote it.
  196. \**************************************************************************/
  197. BOOL XCLIPOBJ::bGetLine(EPATHOBJ *ppo, FLONG *pflOld)
  198. {
  199. DONTUSE(pflOld);
  200. FLONG fl;
  201. FLONG flBeginSub = 0;
  202. // This for(;;) is for eating zero-length lines
  203. for (;;)
  204. {
  205. if (bEnumDone())
  206. return(FALSE);
  207. // if we still have more points in the current set
  208. if (pcle->cPoints > 1)
  209. {
  210. pcle->ptfx0 = *pcle->pptfx1;
  211. ++pcle->pptfx1;
  212. --pcle->cPoints;
  213. if (bEnumStartLine((PD_CLOSEFIGURE & pcle->fl) | flBeginSub))
  214. return(TRUE);
  215. }
  216. // otherwise, if we need to close the figure
  217. else if (bCloseFigure())
  218. {
  219. pcle->ptfx0 = *pcle->pptfx1;
  220. pcle->pptfx1 = &pcle->ptfxStartSub;
  221. // bEnumStartLine will turn off PD_CLOSFIGURE and turn on CLO_CLOSING:
  222. if (!bEnumStartLine(CLO_CLOSING) || flBeginSub)
  223. continue;
  224. return(TRUE);
  225. }
  226. // otherwise, lets get some more points
  227. else
  228. {
  229. if (!bGetMorePoints(ppo,&fl))
  230. {
  231. return(FALSE);
  232. }
  233. if (bEnumStartLine(fl | flBeginSub))
  234. return(TRUE);
  235. // Okay, the first line in the subpath was zero-length. So remember
  236. // that we're really still at the start of a subpath, and get the
  237. // next line:
  238. // NOTE: We have to make sure we pass on the RESETSTYLE flag too!
  239. flBeginSub |= (pcle->fl & (PD_BEGINSUBPATH | PD_RESETSTYLE));
  240. }
  241. }
  242. }
  243. /******************************Public*Routine******************************\
  244. * XCLIPOBJ::bGetMorePoints
  245. *
  246. * This routine gets the next set of points from the path object. If this
  247. * routine returns TRUE, it is guranteed that their are at least enough points
  248. * for one more line segment.
  249. *
  250. * returns
  251. * TRUE - If there were more points to get
  252. * FALSE - if no more points
  253. *
  254. * History:
  255. * 15-Oct-1991 -by- Eric Kutter [erick]
  256. * Wrote it.
  257. \**************************************************************************/
  258. BOOL XCLIPOBJ::bGetMorePoints(EPATHOBJ *ppo, FLONG *fl)
  259. {
  260. // if we have already gotten all points, return failure
  261. if (pcle->fl & CLO_PATHDONE)
  262. {
  263. pcle->fl |= CLO_ENUMDONE;
  264. return(FALSE);
  265. }
  266. // if this is a continuation, we need to save the last point
  267. if (pcle->cPoints == 1)
  268. pcle->ptfx0 = *pcle->pptfx1;
  269. // ask the path for some more points
  270. PATHDATA pd;
  271. if (!(ppo->bEnum(&pd)))
  272. {
  273. // this is the last chunk of points
  274. pcle->fl |= CLO_PATHDONE;
  275. // check if we actualy got any. If no, we must be done!
  276. if (pd.count == 0)
  277. {
  278. pcle->fl |= CLO_ENUMDONE;
  279. return(FALSE);
  280. }
  281. }
  282. // do a little debugging
  283. ASSERTGDI(pd.count > 0, "CLIPPATH: Path is Empty\n");
  284. ASSERTGDI(((pcle->cPoints == 0) ? (pd.flags & PD_BEGINSUBPATH) : TRUE),
  285. "XCLIPOBJ::bGetMorePoints - 0 points not at BEGINSUBPATH \n");
  286. // if it is the begining of a sub-path, remember the first point
  287. if (pd.flags & PD_BEGINSUBPATH)
  288. {
  289. pcle->ptfxStartSub = *pd.pptfx;
  290. pcle->ptfx0 = *pd.pptfx;
  291. // if we only got one point, we had better ask for more
  292. if (pd.count == 1)
  293. {
  294. ASSERTGDI(!(pcle->fl & CLO_PATHDONE),"One point in subpath");
  295. if (!ppo->bEnum(&pd))
  296. {
  297. pcle->fl |= CLO_PATHDONE;
  298. // check if we actualy got any. If no, we must be done!
  299. if (pd.count == 0)
  300. {
  301. pcle->fl |= CLO_ENUMDONE;
  302. return(FALSE);
  303. }
  304. }
  305. pcle->pptfx1 = pd.pptfx;
  306. pcle->cPoints = pd.count;
  307. }
  308. else
  309. {
  310. // remember that we took two points out of the current set
  311. pcle->pptfx1 = pd.pptfx + 1;
  312. pcle->cPoints = pd.count - 1;
  313. }
  314. }
  315. else
  316. {
  317. // this is a continuation of the previous set of points
  318. pcle->pptfx1 = pd.pptfx;
  319. pcle->cPoints = pd.count;
  320. }
  321. *fl = pd.flags;
  322. return(TRUE);
  323. }