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.

428 lines
13 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1998 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * Rasterizer.hpp
  8. *
  9. * Abstract:
  10. *
  11. * GpRasterizer class definition (and supporting classes)
  12. *
  13. * Created:
  14. *
  15. * 12/15/1998 DCurtis
  16. *
  17. \**************************************************************************/
  18. #ifndef _RASTERIZER_HPP
  19. #define _RASTERIZER_HPP
  20. /////////////////////////////////////////////////////////////////////////
  21. // The x86 C compiler insists on making a divide and modulus operation
  22. // into two DIVs, when it can in fact be done in one. So we use this
  23. // macro.
  24. //
  25. // Note: QUOTIENT_REMAINDER implicitly takes unsigned arguments.
  26. //
  27. // QUOTIENT_REMAINDER_64_32 takes a 64-bit numerator and produces 32-bit
  28. // results.
  29. #if defined(_USE_X86_ASSEMBLY)
  30. #define QUOTIENT_REMAINDER(ulNumerator, ulDenominator, ulQuotient, ulRemainder)\
  31. { \
  32. __asm mov eax, ulNumerator \
  33. __asm sub edx, edx \
  34. __asm div ulDenominator \
  35. __asm mov ulQuotient, eax \
  36. __asm mov ulRemainder, edx \
  37. }
  38. #define QUOTIENT_REMAINDER_64_32(ullNumerator, ulDenominator, ulQuotient, ulRemainder)\
  39. { \
  40. ULONG ulNumeratorLow = *((ULONG*) &ullNumerator); \
  41. ULONG ulNumeratorHigh = *((ULONG*) &ullNumerator + 1); \
  42. __asm mov eax, ulNumeratorLow \
  43. __asm mov edx, ulNumeratorHigh \
  44. __asm div ulDenominator \
  45. __asm mov ulQuotient, eax \
  46. __asm mov ulRemainder, edx \
  47. }
  48. #else
  49. #define QUOTIENT_REMAINDER(ulNumerator, ulDenominator, ulQuotient, ulRemainder)\
  50. { \
  51. ulQuotient = (ULONG) ulNumerator / (ULONG) ulDenominator; \
  52. ulRemainder = (ULONG) ulNumerator % (ULONG) ulDenominator; \
  53. }
  54. #define QUOTIENT_REMAINDER_64_32(ullNumerator, ulDenominator, ulQuotient, ulRemainder)\
  55. { \
  56. ulQuotient = (ULONG) ((ULONGLONG) ullNumerator / (ULONG) ulDenominator); \
  57. ulRemainder = (ULONG) ((ULONGLONG) ullNumerator % (ULONG) ulDenominator);\
  58. }
  59. #endif
  60. enum GpVectorDirection
  61. {
  62. VectorGoingDown = -1,
  63. VectorHorizontal = 0,
  64. VectorGoingUp = 1,
  65. };
  66. // This class does a y (vertical) DDA from (x1,y1) to (x2,y2), where y1 < y2.
  67. // Horizontal lines are not handled.
  68. //
  69. // It is up to the caller to keep track of the current y value. This class
  70. // advances and keeps track of the current x value. The Advance method should
  71. // be called once for each increment of y.
  72. //
  73. // For fill algorithms (such as a winding fill), this class will also keep
  74. // track of the original direction of the vector, if desired.
  75. class GpYDda
  76. {
  77. protected:
  78. INT Error; // DDA cumulative error
  79. INT ErrorUp; // DDA constant 1
  80. INT YDelta; // DDA constant 2
  81. INT YMax; // greatest y value (last scan line)
  82. INT XInc; // DDA X Increment
  83. INT XCur; // current position
  84. GpVectorDirection Direction; // VectorGoingUp or VectorGoingDown
  85. public:
  86. GpYDda() { /* we need a constructor with no params */ }
  87. GpYDda(
  88. FIX4 x1,
  89. FIX4 y1,
  90. FIX4 x2,
  91. FIX4 y2,
  92. GpVectorDirection direction = VectorGoingDown
  93. )
  94. {
  95. Init(x1, y1, x2, y2, direction);
  96. }
  97. virtual ~GpYDda() {}
  98. virtual VOID
  99. Init(
  100. FIX4 x1,
  101. FIX4 y1,
  102. FIX4 x2,
  103. FIX4 y2,
  104. GpVectorDirection direction = VectorGoingDown
  105. );
  106. virtual VOID Advance();
  107. BOOL DoneWithVector (INT y)
  108. {
  109. if (y < this->YMax)
  110. {
  111. Advance();
  112. return FALSE;
  113. }
  114. return TRUE;
  115. }
  116. INT GetX()
  117. {
  118. return this->XCur;
  119. }
  120. GpVectorDirection GetDirection()
  121. {
  122. return Direction;
  123. }
  124. virtual GpYDda * CreateYDda()
  125. {
  126. return new GpYDda();
  127. }
  128. };
  129. // Interface class for outputing a single span of a single raster at a time.
  130. // When all the spans on a raster have been output, the EndRaster method
  131. // is invoked. When all rasterization for all rasters is complete, the
  132. // End method is invoked.
  133. template<class T> class EpScanBufferNative;
  134. #define DpScanBuffer EpScanBufferNative<ARGB>
  135. struct DpBrush;
  136. class DpContext;
  137. // [agodfrey]
  138. // * "Dp" should be "Ep" in this hierarchy.
  139. //
  140. // There are two types of class which use this interface -
  141. // "leaf" classes which actually produce the colors from the brush,
  142. // and "forwarding" ones which modify the input somehow, then forward it
  143. // down to an object of another DpOutputSpan class. The "leaf" ones
  144. // call Scan->NextBuffer, the "forwarding" ones can't. So my suggestion:
  145. //
  146. // * Make just two subclasses of DpOutputSpan, one for each type.
  147. // Derive the rest of them from one of those two, instead of directly
  148. // from DpOutputSpan.
  149. class DpOutputSpan
  150. {
  151. public:
  152. virtual ~DpOutputSpan() {}
  153. virtual GpStatus OutputSpan(
  154. INT y,
  155. INT xMin,
  156. INT xMax
  157. ) = 0;
  158. virtual GpStatus EndRaster() // no more spans on this raster
  159. {
  160. return Ok;
  161. }
  162. virtual GpStatus End() // all done rasterizing everything
  163. {
  164. return Ok;
  165. }
  166. // !!! PERF [agodfrey]: I don't think this needs to be virtual.
  167. // All the implementations seem to return "Scan" - just move the Scan
  168. // pointer into the base class. DpClipRegion can just leave it NULL.
  169. virtual DpScanBuffer* GetScanBuffer()
  170. {
  171. return NULL;
  172. }
  173. virtual BOOL IsValid() const = 0;
  174. static DpOutputSpan * Create(
  175. const DpBrush * brush,
  176. DpScanBuffer * scan,
  177. DpContext * context,
  178. const GpRect * drawBounds=NULL);
  179. };
  180. typedef GpStatus (DpOutputSpan::*DpOutputSpanFunction)(INT, INT&, INT&);
  181. // Interface class for outputing a series of rects within a Y Span.
  182. class GpOutputYSpan
  183. {
  184. public:
  185. virtual ~GpOutputYSpan() {}
  186. virtual GpStatus OutputYSpan(
  187. INT yMin,
  188. INT yMax,
  189. INT * xCoords, // even number of X coordinates
  190. INT numXCoords // must be a multiple of 2
  191. ) = 0;
  192. };
  193. //#define USE_YSPAN_BUILDER
  194. #ifndef USE_YSPAN_BUILDER
  195. // Interface class for outputing a rect at a time. Used by GpRectBuilder class.
  196. class GpOutputRect
  197. {
  198. public:
  199. virtual ~GpOutputRect() {}
  200. virtual GpStatus OutputRect(
  201. INT xMin,
  202. INT yMin,
  203. INT xMax,
  204. INT yMax
  205. ) = 0;
  206. };
  207. // Builds up and outputs Y Span rects from single span inputs
  208. class GpRectBuilder : public DpOutputSpan, // input
  209. public GpOutputYSpan // output
  210. {
  211. private:
  212. // We now use an ObjectTag to determine if the object is valid
  213. // instead of using a BOOL. This is much more robust and helps
  214. // with debugging. It also enables us to version our objects
  215. // more easily with a version number in the ObjectTag.
  216. ObjectTag Tag; // Keep this as the 1st value in the object!
  217. protected:
  218. VOID SetValid(BOOL valid)
  219. {
  220. Tag = valid ? ObjectTagGpRectBuilder : ObjectTagInvalid;
  221. }
  222. protected:
  223. DynIntArray RectXCoords; // currently built rects
  224. DynIntArray RasterXCoords; // x coords of current raster so far
  225. INT RasterY; // y value of current raster
  226. INT RectYMin; // starting y value of current rects
  227. INT RectHeight; // height of current rects
  228. GpOutputYSpan * FlushRects; // Used to output the RectXCoords buffer
  229. GpOutputRect * RenderRect; // Used by FlushRects to ouput each rect
  230. protected:
  231. GpStatus InitArrays();
  232. public:
  233. // You can choose to output a single rect at a time with this constructor,
  234. // or if you use the other constructor it will output an entire Y Span
  235. // at a time.
  236. GpRectBuilder(GpOutputRect * renderRect);
  237. GpRectBuilder(GpOutputYSpan * flushRects);
  238. virtual ~GpRectBuilder()
  239. {
  240. SetValid(FALSE); // so we don't use a deleted object
  241. }
  242. virtual BOOL IsValid() const
  243. {
  244. ASSERT((Tag == ObjectTagGpRectBuilder) || (Tag == ObjectTagInvalid));
  245. #if DBG
  246. if (Tag == ObjectTagInvalid)
  247. {
  248. WARNING1("Invalid GpRectBuilder");
  249. }
  250. #endif
  251. return (Tag == ObjectTagGpRectBuilder);
  252. }
  253. // This method is the input of spans to this class
  254. virtual GpStatus OutputSpan(
  255. INT y,
  256. INT xMin,
  257. INT xMax
  258. );
  259. virtual GpStatus EndRaster();
  260. virtual GpStatus End();
  261. // Default version to output 1 rect at a time
  262. virtual GpStatus OutputYSpan(
  263. INT yMin,
  264. INT yMax,
  265. INT * xCoords, // even number of X coordinates
  266. INT numXCoords // must be a multiple of 2
  267. );
  268. };
  269. #else
  270. // Builds up and outputs Y Span rects from single span inputs
  271. class GpYSpanBuilder : public DpOutputSpan // input
  272. {
  273. private:
  274. // We now use an ObjectTag to determine if the object is valid
  275. // instead of using a BOOL. This is much more robust and helps
  276. // with debugging. It also enables us to version our objects
  277. // more easily with a version number in the ObjectTag.
  278. ObjectTag Tag; // Keep this as the 1st value in the object!
  279. protected:
  280. VOID SetValid(BOOL valid)
  281. {
  282. Tag = valid ? ObjectTagGpYSpanBuilder : ObjectTagInvalid;
  283. }
  284. protected:
  285. DynIntArray XCoords; // x coords of current raster so far
  286. INT Y; // y value of current raster
  287. GpOutputYSpan * Output;
  288. public:
  289. GpYSpanBuilder(GpOutputYSpan * output);
  290. virtual ~GpYSpanBuilder()
  291. {
  292. SetValid(FALSE); // so we don't use a deleted object
  293. }
  294. virtual BOOL IsValid() const
  295. {
  296. ASSERT((Tag == ObjectTagGpYSpanBuilder) || (Tag == ObjectTagInvalid));
  297. #if DBG
  298. if (Tag == ObjectTagInvalid)
  299. {
  300. WARNING1("Invalid GpYSpanBuilder");
  301. }
  302. #endif
  303. return (Tag == ObjectTagGpYSpanBuilder);
  304. }
  305. // This method is the input of spans to this class
  306. virtual GpStatus OutputSpan(
  307. INT y,
  308. INT xMin,
  309. INT xMax
  310. );
  311. virtual GpStatus EndRaster();
  312. };
  313. #endif
  314. class DpPath;
  315. class DpClipRegion;
  316. struct DpPen;
  317. class RasterizeVector;
  318. GpStatus
  319. ConvexRasterizer(
  320. INT yMin, // min y of all vectors
  321. INT yMax, // max y of all vectors
  322. INT numVectors, // num vectors in VectorList
  323. RasterizeVector * vectorList, // list of all vectors of path
  324. INT * sortedVectorIndices, // sorted list of vector indices
  325. GpYDda * dda1,
  326. GpYDda * dda2,
  327. DpOutputSpan * output,
  328. const GpRect * clipBounds
  329. );
  330. GpStatus
  331. NonConvexRasterizer(
  332. INT yMin, // min y of all vectors
  333. INT yMax, // max y of all vectors
  334. INT numVectors, // num vectors in VectorList
  335. RasterizeVector * vectorList, // list of all vectors of path
  336. INT * sortedVectorIndices, // sorted list of vector indices
  337. GpYDda * left,
  338. GpYDda * right,
  339. DpOutputSpan * output,
  340. const GpRect * clipBounds,
  341. BOOL useAlternate
  342. );
  343. GpStatus
  344. Rasterizer(
  345. const DpPath * path,
  346. const GpMatrix * matrix,
  347. GpFillMode fillMode,
  348. DpOutputSpan * output,
  349. REAL dpiX = 0,
  350. REAL dpiY = 0,
  351. const GpRect * clipBounds = NULL,
  352. GpYDda * yDda = NULL,
  353. DpEnumerationType type = Flattened,
  354. const DpPen * pen = NULL
  355. );
  356. GpStatus
  357. Rasterize(
  358. const DpPath * path,
  359. GpMatrix * matrix,
  360. GpFillMode fillMode,
  361. DpOutputSpan * output,
  362. DpClipRegion * clipRegion,
  363. const GpRect * drawBounds,
  364. REAL dpiX,
  365. REAL dpiY,
  366. GpYDda * yDda = NULL,
  367. DpEnumerationType type = Flattened,
  368. const DpPen * pen = NULL
  369. );
  370. #endif // _RASTERIZER_HPP